diff options
-rw-r--r-- | ranger/colorschemes/default.py | 8 | ||||
-rw-r--r-- | ranger/defaults/keys.py | 22 | ||||
-rw-r--r-- | ranger/ext/accumulator.py | 93 | ||||
-rw-r--r-- | ranger/fsobject/fsobject.py | 3 | ||||
-rw-r--r-- | ranger/gui/colorscheme.py | 4 | ||||
-rw-r--r-- | ranger/gui/defaultui.py | 16 | ||||
-rw-r--r-- | ranger/gui/widgets/process_manager.py | 114 |
7 files changed, 258 insertions, 2 deletions
diff --git a/ranger/colorschemes/default.py b/ranger/colorschemes/default.py index e3cdb766..69397800 100644 --- a/ranger/colorschemes/default.py +++ b/ranger/colorschemes/default.py @@ -83,4 +83,12 @@ class Default(ColorScheme): if context.highlight: attr |= reverse + if context.in_pman: + if context.title: + attr |= reverse + fg = cyan + + if context.selected: + attr |= reverse + return fg, bg, attr diff --git a/ranger/defaults/keys.py b/ranger/defaults/keys.py index 5586a4a4..2a775ab9 100644 --- a/ranger/defaults/keys.py +++ b/ranger/defaults/keys.py @@ -137,6 +137,8 @@ def initialize_commands(command_list): bind('h', KEY_LEFT, KEY_BACKSPACE, DEL, lambda fm, n: \ fm.move_left(n or 1)) + bind('P', lambda fm, n: fm.ui.open_pman()) + command_list.rebuild_paths() @@ -182,3 +184,23 @@ def initialize_console_commands(command_list): bind(i, type_key(i)) command_list.rebuild_paths() + +def initialize_process_manager_commands(command_list): + """Initialize the commands for the process manager widget""" + + from ranger.gui.widgets.process_manager import KeyWrapper as wdg + + def bind(*args): + command_list.bind(args[-1], *args[:-1]) + + def do_fm(method, *args, **kw): + return lambda con: getattr(con.fm, method)(*args, **kw) + + bind('j', KEY_DOWN, wdg.move(relative=1)) + bind('k', KEY_UP, wdg.move(relative=-1)) + bind('gg', wdg.move(absolute=0)) + bind('G', wdg.move(absolute=-1)) + + bind('P', ESC, ctrl('d'), lambda wdg, n: wdg.fm.ui.close_pman()) + + command_list.rebuild_paths() diff --git a/ranger/ext/accumulator.py b/ranger/ext/accumulator.py new file mode 100644 index 00000000..7fed72dd --- /dev/null +++ b/ranger/ext/accumulator.py @@ -0,0 +1,93 @@ +class Accumulator(object): + def __init__(self): + self.pointer = 0 + self.pointed_obj = None + + def move(self, relative=0, absolute=None): + i = self.pointer + lst = self.get_list() + length = len(lst) + + if isinstance(absolute, int): + if absolute < 0: # wrap + i = absolute + length + else: + i = absolute + + if isinstance(relative, int): + i += relative + + if i >= length: + i = length - 1 + if i < 0: + i = 0 + + self.pointer = i + self.correct_pointer() + + def move_to_obj(self, arg, attr=None): + if not arg: + return + + lst = self.get_list() + + if not lst: + return + + do_get_attr = isinstance(attr, str) + + good = arg + if do_get_attr: + try: + good = getattr(arg, attr) + except (TypeError, AttributeError): + pass + + for obj, i in zip(lst, range(len(lst))): + if do_get_attr: + try: + test = getattr(obj, attr) + except AttributeError: + continue + else: + test = obj + + if test == good: + self.move(absolute=i) + return True + + return self.move(absolute=self.pointer) + + def correct_pointer(self): + lst = self.get_list() + + if not lst: + self.pointer = 0 + self.pointed_obj = None + + else: + i = self.pointer + + if i is None: + i = 0 + if i >= len(lst): + i = len(lst) - 1 + if i < 0: + i = 0 + + self.pointer = i + self.pointed_obj = lst[i] + + def pointer_is_synced(self): + lst = self.get_list() + try: + return lst[self.pointer] == self.pointed_obj + except (IndexError, KeyError): + return False + + def sync_index(self, **kw): + self.move_to_obj(self.pointed_obj, **kw) + + def get_list(self): + """OVERRIDE THIS""" + return [] diff --git a/ranger/fsobject/fsobject.py b/ranger/fsobject/fsobject.py index 1864a7fc..f7d9772c 100644 --- a/ranger/fsobject/fsobject.py +++ b/ranger/fsobject/fsobject.py @@ -57,6 +57,9 @@ class FileSystemObject(MimeTypeAware, FileManagerAware): self.set_mimetype() self.use() + + def get_description(self): + return "Loading " + str(self) def __str__(self): """returns a string containing the absolute path""" diff --git a/ranger/gui/colorscheme.py b/ranger/gui/colorscheme.py index 4fdcaad2..227051f9 100644 --- a/ranger/gui/colorscheme.py +++ b/ranger/gui/colorscheme.py @@ -1,6 +1,6 @@ CONTEXT_KEYS = [ 'reset', 'error', 'in_display', 'in_statusbar', 'in_titlebar', 'in_console', - 'in_notify', + 'in_notify', 'in_pman', 'directory', 'file', 'hostname', 'executable', 'media', 'link', 'video', 'audio', 'image', 'media', 'document', 'container', @@ -9,7 +9,7 @@ CONTEXT_KEYS = [ 'reset', 'error', 'space', 'permissions', 'owner', 'group', 'mtime', 'nlink', 'scroll', 'all', 'bot', 'top', 'percentage', 'marked', - 'text', 'highlight', + 'title', 'text', 'highlight', 'keybuffer'] # colorscheme specification: diff --git a/ranger/gui/defaultui.py b/ranger/gui/defaultui.py index 2b1fa188..31049178 100644 --- a/ranger/gui/defaultui.py +++ b/ranger/gui/defaultui.py @@ -10,6 +10,7 @@ class DefaultUI(UI): from ranger.gui.widgets.titlebar import TitleBar from ranger.gui.widgets.console import Console from ranger.gui.widgets.statusbar import StatusBar + from ranger.gui.widgets.process_manager import ProcessManager from ranger.gui.widgets.notify import Notify self.titlebar = TitleBar(self.win) self.add_obj(self.titlebar) @@ -24,6 +25,10 @@ class DefaultUI(UI): self.add_obj(self.console) self.console.visible = False + self.pman = ProcessManager(self.win) + self.pman.visible = False + self.add_obj(self.pman) + self.notify = Notify(self.win) self.add_obj(self.notify) @@ -36,6 +41,7 @@ class DefaultUI(UI): # log(notify_hei) self.filelist_container.resize(1, 0, y - 2 - notify_hei, x) + self.pman.resize(1, 0, y - 2 - notify_hei, x) self.notify.resize(y - 1 - notify_hei, 0, notify_hei, x) self.titlebar.resize(0, 0, 1, x) self.status.resize(y - 1, 0, 1, x) @@ -59,6 +65,16 @@ class DefaultUI(UI): self.console.visible = False self.status.visible = True + def open_pman(self): + self.filelist_container.visible = False + self.pman.visible = True + self.pman.focused = True + + def close_pman(self): + self.pman.visible = False + self.filelist_container.visible = True + self.pman.focused = False + def scroll(self, relative): if self.main_filelist: self.main_filelist.scroll(relative) diff --git a/ranger/gui/widgets/process_manager.py b/ranger/gui/widgets/process_manager.py new file mode 100644 index 00000000..ae372112 --- /dev/null +++ b/ranger/gui/widgets/process_manager.py @@ -0,0 +1,114 @@ +""" +The process manager allows you to modify what the loader is doing. +""" + +import curses + +from . import Widget +from ranger.ext.accumulator import Accumulator +from ranger import log +from ranger.container import CommandList +from collections import deque + +class DummyLoadObject(object): + def __init__(self, txt): + self.get_description = lambda: txt + self.load_generator = range(100) + + +class DummyLoader(object): + def __init__(self): + self.queue = deque() + self.queue.append(DummyLoadObject("blub")) + self.queue.append(DummyLoadObject("foo")) + self.queue.append(DummyLoadObject("asfkljflk")) + self.queue.append(DummyLoadObject("g$%GKSERJgsldflj")) + + +class ProcessManager(Widget, Accumulator): + def __init__(self, win): + Widget.__init__(self, win) + Accumulator.__init__(self) + self.scroll_begin = 0 + self.commandlist = CommandList() + self.settings.keys.initialize_process_manager_commands( \ + self.commandlist) + + # ---- dummy loader for testing purposes + self.loader = DummyLoader() + + def draw(self): + base_clr = deque() + base_clr.append('in_pman') + lst = self.get_list() + + if not self.pointer_is_synced(): + self.sync_index() + + self.win.addnstr(self.y, self.x, " Process Manager", self.wid) + self.color_at(self.y, self.x, self.wid, base_clr, 'title') + + if lst: + for i in range(self.hei - 1): + i += self.scroll_begin + try: + obj = lst[i] + except IndexError: + break + y, x = self.y + i + 1, self.x + clr = deque(base_clr) + + if self.pointer == i: + clr.append('selected') + + descr = obj.get_description() + self.win.addnstr(y, x, descr, self.wid) + self.color_at(y, x, self.wid, clr) + + else: + if self.hei > 1: + self.win.addnstr(self.y + 1, self.x,\ + "No processes running", self.wid) + self.color_at(self.y + 1, self.x, self.wid, base_clr, 'error') + + self.color_reset() + + def press(self, key): + try: + tup = self.env.keybuffer.tuple_without_numbers() + if tup: + cmd = self.commandlist[tup] + else: + return + + except KeyError: + self.env.key_clear() + else: + if hasattr(cmd, 'execute'): + cmd.execute(self, self.env.keybuffer.number) + self.env.key_clear() + + def get_list(self): + return self.fm.loader.queue + return self.loader.queue + + +class KeyWrapper(object): + @staticmethod + def move(relative=0, absolute=None): + if absolute is None: + def fnc(wdg, n): + if n is not None: + if relative >= 0: + wdg.move(relative=n) + else: + wdg.move(relative=-n) + else: + wdg.move(relative=relative) + else: + def fnc(wdg, n): + if n is not None: + wdg.move(absolute=n, relative=relative) + else: + wdg.move(absolute=absolute, relative=relative) + return fnc |