# This file is part of ranger, the console file manager. # License: GNU GPL version 3, see the file "AUTHORS" for details. """The BrowserColumn widget displays the contents of a directory or file.""" from __future__ import (absolute_import, division, print_function) import curses import stat from time import time from os.path import splitext try: from bidi.algorithm import get_display # pylint: disable=import-error HAVE_BIDI = True except ImportError: HAVE_BIDI = False from ranger.ext.widestring import WideString from ranger.core import linemode from . import Widget from .pager import Pager def hook_before_drawing(fsobject, color_list): return fsobject, color_list class BrowserColumn(Pager): # pylint: disable=too-many-instance-attributes main_column = False display_infostring = False display_vcsstate = True scroll_begin = 0 target = None last_redraw_time = -1 old_dir = None old_thisfile = None def __init__(self, win, level, tab=None): """Initializes a Browser Column Widget win = the curses window object of the BrowserView level = what to display? level >0 => previews level 0 => current file/directory level <0 => parent directories """ Pager.__init__(self, win) Widget.__init__(self, win) # pylint: disable=non-parent-init-called self.level = level self.tab = tab self.original_level = level self.settings.signal_bind('setopt.display_size_in_main_column', self.request_redraw, weak=True) def request_redraw(self): self.need_redraw = True def click(self, event): # pylint: disable=too-many-branches """Handle a MouseEvent""" direction = event.mouse_wheel_direction() if not (event.pressed(1) or event.pressed(3) or direction): return False if self.target is None: pass elif self.target.is_directory: if self.target.accessible and self.target.content_loaded: index = self.scroll_begin + event.y - self.y if direction: if self.level == -1: self.fm.move_parent(direction) else: return False elif event.pressed(1): if not self.main_column: self.fm.enter_dir(self.target.path) if index < len(self.target): self.fm.move(to=index) elif event.pressed(3): try: clicked_file = self.target.files[index] except IndexError: pass else: if clicked_file.is_directory: self.fm.enter_dir(clicked_file.path, remember=True) elif self.level == 0: self.fm.thisdir.move_to_obj(clicked_file) self.fm.execute_file(clicked_file) elif self.target.is_file: self.scrollbit(direction) else: if self.level > 0 and not direction: self.fm.move(right=0) return True def execute_curses_batch(self, line, commands): """Executes a list of "commands" which can be easily cached. "commands" is a list of lists. Each element contains a text and an attribute. First, the attribute will be set with attrset, then the text is printed. Example: execute_curses_batch(0, [["hello ", 0], ["world", curses.A_BOLD]]) """ try: self.win.move(line, 0) except curses.error: return for entry in commands: text, attr = entry self.addstr(text, attr) def has_preview(self): if self.target is None: return False if self.target.is_file: if not self.target.has_preview(): return False if self.target.is_directory: if self.level > 0 and not self.settings.preview_directories: return False return True def level_shift(self, amount): self.level = self.original_level + amount def level_restore(self): self.level = self.original_level def poke(self): Widget.poke(self) if self.tab is None: tab = self.fm.thistab else: tab = self.tab self.target = tab.at_level(self.level) def draw(self): """Call eit
discard """
  output: '''0 1
1 2
2 3
0 1
1 2
2 3
0 1
1 2
2 3
3 5'''
"""

import macros

macro mymacro(): untyped =
  result = newLit([1, 2, 3])

for a, b in mymacro():
  echo a, " ", b

macro enumerate(x: ForLoopStmt): untyped =
  expectKind x, nnkForStmt
  # we strip off the first for loop variable and use
  # it as an integer counter:
  result = newStmtList()
  result.add newVarStmt(x[0], newLit(0))
  var body = x[^1]
  if body.kind != nnkStmtList:
    body = newTree(nnkStmtList, body)
  body.add newCall(bindSym"inc", x[0])
  var newFor = newTree(nnkForStmt)
  for i in 1..x.len-3:
    newFor.add x[i]
  # transform enumerate(X) to 'X'
  newFor.add x[^2][1]
  newFor.add body
  result.add newFor

for a, b in enumerate(items([1, 2, 3])):
  echo a, " ", b

for a2, b2 in enumerate([1, 2, 3, 5]):
  echo a2, " ", b2
ags and drawn.realpath in self.fm.tags: this_color.append('tagged') if drawn.is_directory: this_color.append('directory') else: this_color.append('file') if drawn.stat: mode = drawn.stat.st_mode if mode & stat.S_IXUSR: this_color.append('executable') if stat.S_ISFIFO(mode): this_color.append('fifo') if stat.S_ISSOCK(mode): this_color.append('socket') if drawn.is_device: this_color.append('device') if drawn.path in copied: this_color.append('cut' if self.fm.do_cut else 'copied') if drawn.is_link: this_color.append('link') this_color.append(drawn.exists and 'good' or 'bad') return this_color def _get_scroll_begin(self): # pylint: disable=too-many-return-statements """Determines scroll_begin (the position of the first displayed file)""" offset = self.settings.scroll_offset dirsize = len(self.target) winsize = self.hei halfwinsize = winsize // 2 index = self._get_index_of_selected_file() or 0 original = self.target.scroll_begin projected = index - original upper_limit = winsize - 1 - offset lower_limit = offset if original < 0: return 0 if dirsize < winsize: return 0 if halfwinsize < offset: return min(dirsize - winsize, max(0, index - halfwinsize)) if original > dirsize - winsize: self.target.scroll_begin = dirsize - winsize return self._get_scroll_begin() if projected < upper_limit and projected > lower_limit: return original if projected > upper_limit: return min(dirsize - winsize, original + (projected - upper_limit)) if projected < upper_limit: return max(0, original - (lower_limit - projected)) return original def _set_scroll_begin(self): """Updates the scroll_begin value""" self.scroll_begin = self._get_scroll_begin() self.target.scroll_begin = self.scroll_begin def scroll(self, n): """scroll down by n lines""" self.need_redraw = True self.target.move(down=n) self.target.scroll_begin += 3 * n def __str__(self): return self.__class__.__name__ + ' at level ' + str(self.level)