diff options
author | hut <hut@lavabit.com> | 2011-09-30 04:19:16 +0200 |
---|---|---|
committer | hut <hut@lavabit.com> | 2011-09-30 04:55:07 +0200 |
commit | 41df56beff2785174b4b466c8cc39159a79eaedc (patch) | |
tree | c0fab60a14d969b2a6fc14bfb7668c67f04b2093 | |
parent | b1d25114617f41538f1e9e1740229f5e326c9f88 (diff) | |
download | ranger-41df56beff2785174b4b466c8cc39159a79eaedc.tar.gz |
implemented a new keybinding parser
-rw-r--r-- | ranger/api/commands.py | 6 | ||||
-rw-r--r-- | ranger/container/keybuffer.py | 180 | ||||
-rw-r--r-- | ranger/container/keymap.py | 164 | ||||
-rw-r--r-- | ranger/core/actions.py | 4 | ||||
-rw-r--r-- | ranger/core/environment.py | 12 | ||||
-rw-r--r-- | ranger/core/helper.py | 4 | ||||
-rw-r--r-- | ranger/defaults/commands.py | 32 | ||||
-rw-r--r-- | ranger/defaults/rc.conf | 6 | ||||
-rw-r--r-- | ranger/ext/keybindings.py | 96 | ||||
-rw-r--r-- | ranger/ext/tree.py | 136 | ||||
-rw-r--r-- | ranger/gui/ui.py | 41 | ||||
-rw-r--r-- | ranger/gui/widgets/console.py | 24 | ||||
-rw-r--r-- | ranger/gui/widgets/pager.py | 24 | ||||
-rw-r--r-- | ranger/gui/widgets/taskview.py | 24 |
14 files changed, 161 insertions, 592 deletions
diff --git a/ranger/api/commands.py b/ranger/api/commands.py index 94b7f341..130906b6 100644 --- a/ranger/api/commands.py +++ b/ranger/api/commands.py @@ -39,7 +39,11 @@ class CommandContainer(object): for varname, var in vars(module).items(): try: if issubclass(var, Command) and var != Command: - self.commands[var.name or varname] = var + classdict = var.__mro__[0].__dict__ + if 'name' in classdict and classdict['name']: + self.commands[var.name] = var + else: + self.commands[varname] = var except TypeError: pass for new, old in self.aliases.items(): diff --git a/ranger/container/keybuffer.py b/ranger/container/keybuffer.py deleted file mode 100644 index 23b82a16..00000000 --- a/ranger/container/keybuffer.py +++ /dev/null @@ -1,180 +0,0 @@ -# Copyright (C) 2009, 2010 Roman Zimbelmann <romanz@lavabit.com> -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. - -import curses.ascii -from collections import deque -from string import digits -from ranger.ext.keybinding_parser import parse_keybinding, \ - DIRKEY, ANYKEY, PASSIVE_ACTION -from ranger.container.keymap import Binding, KeyMap # mainly for assertions - -MAX_ALIAS_RECURSION = 20 -digitlist = set(ord(n) for n in digits) - -class KeyBuffer(object): - """The evaluator and storage for pressed keys""" - def __init__(self, keymap, direction_keys): - self.assign(keymap, direction_keys) - - def assign(self, keymap, direction_keys): - """Change the keymap and direction keys of the keybuffer""" - self.keymap = keymap - self.direction_keys = direction_keys - - def add(self, key): - """Add a key and evaluate it""" - assert isinstance(key, int) - assert key >= 0 - self.all_keys.append(key) - self.key_queue.append(key) - while self.key_queue: - key = self.key_queue.popleft() - - # evaluate quantifiers - if self.eval_quantifier and self._do_eval_quantifier(key): - return - - # evaluate the command - if self.eval_command and self._do_eval_command(key): - return - - # evaluate (the first number of) the direction-quantifier - if self.eval_quantifier and self._do_eval_quantifier(key): - return - - # evaluate direction keys {j,k,gg,pagedown,...} - if not self.eval_command: - self._do_eval_direction(key) - - def _do_eval_direction(self, key): - try: - assert isinstance(self.dir_tree_pointer, dict) - self.dir_tree_pointer = self.dir_tree_pointer[key] - except KeyError: - self.failure = True - else: - self._direction_try_to_finish() - - def _direction_try_to_finish(self): - if self.max_alias_recursion <= 0: - self.failure = True - return None - match = self.dir_tree_pointer - assert isinstance(match, (Binding, dict, KeyMap)) - if isinstance(match, KeyMap): - self.dir_tree_pointer = self.dir_tree_pointer._tree - match = self.dir_tree_pointer - if isinstance(self.dir_tree_pointer, Binding): - if match.alias: - self.key_queue.extend(parse_keybinding(match.alias)) - self.dir_tree_pointer = self.direction_keys._tree - self.max_alias_recursion -= 1 - else: - direction = match.actions['dir'].copy() - if self.direction_quant is not None: - direction.multiply(self.direction_quant) - self.directions.append(direction) - self.direction_quant = None - self.eval_command = True - self._try_to_finish() - - def _do_eval_quantifier(self, key): - if self.eval_command: - tree = self.tree_pointer - else: - tree = self.dir_tree_pointer - if key in digitlist and ANYKEY not in tree: - attr = self.eval_command and 'quant' or 'direction_quant' - if getattr(self, attr) is None: - setattr(self, attr, 0) - setattr(self, attr, getattr(self, attr) * 10 + key - 48) - else: - self.eval_quantifier = False - return None - return True - - def _do_eval_command(self, key): - assert isinstance(self.tree_pointer, dict), self.tree_pointer - try: - self.tree_pointer = self.tree_pointer[key] - except TypeError: - self.failure = True - return None - except KeyError: - try: - key in digitlist or self.direction_keys._tree[key] - self.tree_pointer = self.tree_pointer[DIRKEY] - except KeyError: - try: - self.tree_pointer = self.tree_pointer[ANYKEY] - except KeyError: - self.failure = True - return None - else: - self.matches.append(key) - assert isinstance(self.tree_pointer, (Binding, dict)) - self._try_to_finish() - else: - assert isinstance(self.tree_pointer, (Binding, dict)) - self.eval_command = False - self.eval_quantifier = True - self.dir_tree_pointer = self.direction_keys._tree - else: - if isinstance(self.tree_pointer, dict): - try: - self.command = self.tree_pointer[PASSIVE_ACTION] - except (KeyError, TypeError): - self.command = None - self._try_to_finish() - - def _try_to_finish(self): - if self.max_alias_recursion <= 0: - self.failure = True - return None - assert isinstance(self.tree_pointer, (Binding, dict, KeyMap)) - if isinstance(self.tree_pointer, KeyMap): - self.tree_pointer = self.tree_pointer._tree - if isinstance(self.tree_pointer, Binding): - if self.tree_pointer.alias: - keys = parse_keybinding(self.tree_pointer.alias) - self.key_queue.extend(keys) - self.tree_pointer = self.keymap._tree - self.max_alias_recursion -= 1 - else: - self.command = self.tree_pointer - self.done = True - - def clear(self): - """Reset the keybuffer. Do this once before the first usage.""" - self.max_alias_recursion = MAX_ALIAS_RECURSION - self.failure = False - self.done = False - self.quant = None - self.matches = [] - self.command = None - self.direction_quant = None - self.directions = [] - self.all_keys = [] - self.tree_pointer = self.keymap._tree - self.dir_tree_pointer = self.direction_keys._tree - - self.key_queue = deque() - - self.eval_quantifier = True - self.eval_command = True - - def __str__(self): - """returns a concatenation of all characters""" - return "".join("{0:c}".format(c) for c in self.all_keys) diff --git a/ranger/container/keymap.py b/ranger/container/keymap.py deleted file mode 100644 index 8739d22a..00000000 --- a/ranger/container/keymap.py +++ /dev/null @@ -1,164 +0,0 @@ -# Copyright (C) 2009, 2010 Roman Zimbelmann <romanz@lavabit.com> -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. - -from ranger.ext.tree import Tree -from ranger.ext.direction import Direction -from ranger.ext.keybinding_parser import parse_keybinding, DIRKEY, ANYKEY - -FUNC = 'func' -DIRARG = 'dir' -ALIASARG = 'alias' - -class CommandArgs(object): - """ - A CommandArgs object is passed to the keybinding function. - - This object simply aggregates information about the pressed keys - and the current environment. - - Attributes: - fm: the FM instance - wdg: the currently focused widget (or fm, if none is focused) - keybuffer: the keybuffer object - n: the prefixed number, eg 5 in the command "5yy" - directions: a list of directions which are entered for "<dir>" - direction: the first direction object from that list - keys: a string representation of the keybuffer - matches: all keys which are entered for "<any>" - match: the first match - binding: the used Binding object - """ - def __init__(self, fm, widget, keybuf): - self.fm = fm - self.wdg = widget - self.keybuffer = keybuf - self.n = keybuf.quant - self.direction = keybuf.directions and keybuf.directions[0] or None - self.directions = keybuf.directions - self.keys = str(keybuf) - self.matches = keybuf.matches - self.match = keybuf.matches and keybuf.matches[0] or None - self.binding = keybuf.command - - @staticmethod - def from_widget(widget): - return CommandArgs(widget.fm, \ - widget, widget.env.keybuffer) - - -class KeyMap(Tree): - """Contains a tree with all the keybindings""" - def map(self, *args, **keywords): - if keywords: - return self._add_binding(*args, **keywords) - firstarg = args[-1] - if hasattr(firstarg, '__call__'): - keywords[FUNC] = firstarg - return self._add_binding(*args[:-1], **keywords) - def decorator_function(func): - keywords = {FUNC:func} - self.map(*args, **keywords) - return func - return decorator_function - - __call__ = map - - def _add_binding(self, *keys, **actions): - assert keys - bind = Binding(keys, actions) - for key in keys: - self.set(parse_keybinding(key), bind) - - def unmap(self, *keys): - for key in keys: - self.unset(parse_keybinding(key)) - - def __getitem__(self, key): - return self.traverse(parse_keybinding(key)) - - -class KeyMapWithDirections(KeyMap): - def __init__(self, *args, **keywords): - Tree.__init__(self, *args, **keywords) - self.directions = KeyMap() - - def merge(self, other): - Tree.merge(self, other) - if hasattr(other, 'directions'): - Tree.merge(self.directions, other.directions) - - def dir(self, *args, **keywords): - if ALIASARG in keywords: - self.directions.map(*args, **keywords) - else: - self.directions.map(*args, dir=Direction(**keywords)) - - -class KeyManager(object): - def __init__(self, keybuffer, contexts): - self._keybuffer = keybuffer - self._list_of_contexts = contexts - self.clear() - - def clear(self): - self.contexts = dict() - for context in self._list_of_contexts: - self.contexts[context] = KeyMapWithDirections() - - def map(self, context, *args, **keywords): - self.get_context(context).map(*args, **keywords) - - def dir(self, context, *args, **keywords): - self.get_context(context).dir(*args, **keywords) - - def unmap(self, context, *args, **keywords): - self.get_context(context).unmap(*args, **keywords) - - def merge_all(self, keymapwithdirection): - for context, keymap in self.contexts.items(): - keymap.merge(keymapwithdirection) - - def get_context(self, context): - assert isinstance(context, str) - assert context in self.contexts, "no such context: " + context - return self.contexts[context] - - def use_context(self, context): - context = self.get_context(context) - if self._keybuffer.keymap is not context: - self._keybuffer.assign(context, context.directions) - self._keybuffer.clear() - - -class Binding(object): - """The keybinding object""" - def __init__(self, keys, actions): - assert hasattr(keys, '__iter__') - assert isinstance(actions, dict) - self.actions = actions - try: - self.function = self.actions[FUNC] - except KeyError: - self.function = None - try: - self.direction = self.actions[DIRARG] - except KeyError: - self.direction = None - try: - alias = self.actions[ALIASARG] - except KeyError: - self.alias = None - else: - self.alias = tuple(parse_keybinding(alias)) diff --git a/ranger/core/actions.py b/ranger/core/actions.py index 0314888d..3427af7f 100644 --- a/ranger/core/actions.py +++ b/ranger/core/actions.py @@ -98,7 +98,7 @@ class Actions(FileManagerAware, EnvironmentAware, SettingsAware): try: cmd_class = self.commands.get_command(command_name) except: - self.notify("Command not found: `%s'" % command_name) + self.notify("Command not found: `%s'" % command_name, bad=True) else: try: cmd_class(string).execute() @@ -170,6 +170,8 @@ class Actions(FileManagerAware, EnvironmentAware, SettingsAware): def source_cmdlist(self, filename, narg=None): for line in open(filename, 'r'): line = line.rstrip("\r\n") + if line.startswith("#") or not line.strip(): + continue try: self.execute_console(line) except Exception as e: diff --git a/ranger/core/environment.py b/ranger/core/environment.py index cf140410..90f0fefa 100644 --- a/ranger/core/environment.py +++ b/ranger/core/environment.py @@ -20,13 +20,11 @@ import socket from os.path import abspath, normpath, join, expanduser, isdir from ranger.fsobject import Directory -from ranger.container import KeyBuffer, KeyManager, History +from ranger.ext.keybindings import KeyBuffer, KeyMaps +from ranger.container import History from ranger.ext.signals import SignalDispatcher from ranger.core.shared import SettingsAware -ALLOWED_CONTEXTS = ('browser', 'pager', 'embedded_pager', 'taskview', - 'console') - class Environment(SettingsAware, SignalDispatcher): """ A collection of data which is relevant for more than one class. @@ -42,8 +40,6 @@ class Environment(SettingsAware, SignalDispatcher): last_search = None pathway = None path = None - keybuffer = None - keymanager = None def __init__(self, path): SignalDispatcher.__init__(self) @@ -51,8 +47,8 @@ class Environment(SettingsAware, SignalDispatcher): self._cf = None self.pathway = () self.directories = {} - self.keybuffer = KeyBuffer(None, None) - self.keymanager = KeyManager(self.keybuffer, ALLOWED_CONTEXTS) + self.keybuffer = KeyBuffer() + self.keymaps = KeyMaps(self.keybuffer) self.copy = set() self.history = History(self.settings.max_history_size, unique=False) diff --git a/ranger/core/helper.py b/ranger/core/helper.py index 62ab9091..56b8e5ad 100644 --- a/ranger/core/helper.py +++ b/ranger/core/helper.py @@ -112,10 +112,6 @@ def load_settings(fm, clean): from ranger.defaults import apps fm.apps = apps.CustomApplications() - # Setup keymanager - keymanager = ranger.core.shared.EnvironmentAware.env.keymanager - ranger.api.keys.keymanager = keymanager - # Load rc.conf conf = fm.confpath('rc.conf') if os.access(conf, os.R_OK): diff --git a/ranger/defaults/commands.py b/ranger/defaults/commands.py index d2c02865..a40d447d 100644 --- a/ranger/defaults/commands.py +++ b/ranger/defaults/commands.py @@ -778,12 +778,34 @@ class map_(Command): name = 'map' context = 'browser' resolve_macros = False + def execute(self): - command = self.rest(2) - self.fm.env.keymanager.map(self.context, self.arg(1), - func=lambda arg: arg.fm.execute_console(command), -# func=lambda arg: arg.fm.cmd(command, n=arg.n, any=arg.matches), - help=command) + self.fm.env.keymaps.bind(self.context, self.arg(1), self.rest(2)) + + +class cmap(map_): + """:cmap <keysequence> <command> + Maps a command to a keysequence in the "console" context. + + Example: + cmap <ESC> console_close + cmap <C-x> console_type test + """ + context = 'console' + + +class tmap(map_): + """:tmap <keysequence> <command> + Maps a command to a keysequence in the "taskview" context. + """ + context = 'taskview' + + +class pmap(map_): + """:pmap <keysequence> <command> + Maps a command to a keysequence in the "pager" context. + """ + context = 'pager' class filter(Command): diff --git a/ranger/defaults/rc.conf b/ranger/defaults/rc.conf index c462bb65..59401e3b 100644 --- a/ranger/defaults/rc.conf +++ b/ranger/defaults/rc.conf @@ -1,4 +1,8 @@ # VIM +map x break_shit +map gg eval fm.move(to=0) +map G eval fm.move(to=-1) +map : eval fm.open_console() map j eval fm.move(down=1) map k eval fm.move(up=1) map h eval fm.move(left=1) @@ -6,6 +10,8 @@ map l eval fm.move(right=1) map q quit map Q quit +cmap <ESC> quit + map R eval fm.reload_cwd() map <c-r> eval fm.reset() map <c-l> eval fm.redraw_window() diff --git a/ranger/ext/keybindings.py b/ranger/ext/keybindings.py new file mode 100644 index 00000000..36b13ad0 --- /dev/null +++ b/ranger/ext/keybindings.py @@ -0,0 +1,96 @@ +# Copyright (C) 2009, 2010 Roman Zimbelmann <romanz@lavabit.com> +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +from ranger.ext.keybinding_parser import (parse_keybinding, + ANYKEY, PASSIVE_ACTION) + +digits = set(range(ord('0'), ord('9')+1)) + +class KeyMaps(dict): + def __init__(self, keybuffer=None): + dict.__init__(self) + self.keybuffer = keybuffer + self.used_keymap = None + + def bind(self, context, keys, leaf): + try: + pointer = self[context] + except: + self[context] = pointer = dict() + keys = list(parse_keybinding(keys)) + if not keys: + return + last_key = keys[-1] + for key in keys[:-1]: + try: + pointer = pointer[key] + except: + pointer[key] = pointer = dict() + pointer[last_key] = leaf + + def use_keymap(self, keymap_name): + self.keybuffer.keymap = self.get(keymap_name, dict()) + if self.used_keymap != keymap_name: + self.used_keymap = keymap_name + self.keybuffer.clear() + + +class KeyBuffer(object): + any_key = ANYKEY + passive_key = PASSIVE_ACTION + + def __init__(self, keymap=None): + self.keymap = keymap + self.clear() + + def clear(self): + self.keys = [] + self.pointer = self.keymap + self.result = None + self.quantifier = None + self.finished_parsing_quantifier = False + self.finished_parsing = False + self.parse_error = False + + def add(self, key): + self.keys.append(key) + if not self.finished_parsing_quantifier and key in digits: + if self.quantifier is None: + self.quantifier = 0 + self.quantifier = self.quantifier * 10 + key - 48 # (48 = ord(0)) + else: + self.finished_parsing_quantifier = True + + moved = True + if key in self.pointer: + self.pointer = self.pointer[key] + elif self.any_key in self.pointer: + self.pointer = self.pointer[self.any_key] + else: + moved = False + + if moved: + if isinstance(self.pointer, dict): + if self.passive_key in self.pointer: + self.result = self.pointer[self.passive_key] + else: + self.result = self.pointer + self.finished_parsing = True + else: + self.finished_parsing = True + self.parse_error = True + + def __str__(self): + return repr(self.keys) diff --git a/ranger/ext/tree.py b/ranger/ext/tree.py deleted file mode 100644 index a954136b..00000000 --- a/ranger/ext/tree.py +++ /dev/null @@ -1,136 +0,0 @@ -# Copyright (C) 2009, 2010 Roman Zimbelmann <romanz@lavabit.com> -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. - -class Tree(object): - def __init__(self, dictionary=None, parent=None, key=None): - if dictionary is None: - self._tree = dict() - else: - self._tree = dictionary - self.key = key - self.parent = parent - - def copy(self): - """Create a deep copy""" - def deep_copy_dict(dct): - dct = dct.copy() - for key, val in dct.items(): - if isinstance(val, dict): - dct[key] = deep_copy_dict(val) - return dct - newtree = Tree() - if isinstance(self._tree, dict): - newtree._tree = deep_copy_dict(self._tree) - else: - newtree._tree = self._tree - return newtree - - def merge(self, other, copy=False): - """Merge another Tree into a copy of self""" - def deep_merge(branch, otherbranch): - assert isinstance(otherbranch, dict) - if not isinstance(branch, dict): - branch = dict() - elif copy: - branch = branch.copy() - for key, val in otherbranch.items(): - if isinstance(val, dict): - if key not in branch: - branch[key] = None - branch[key] = deep_merge(branch[key], val) - else: - branch[key] = val - return branch - - if isinstance(self._tree, dict) and isinstance(other._tree, dict): - content = deep_merge(self._tree, other._tree) - elif copy and hasattr(other._tree, 'copy'): - content = other._tree.copy() - else: - content = other._tree - return type(self)(content) - - def set(self, keys, value, force=True): - """Sets the element at the end of the path to <value>.""" - if not isinstance(keys, (list, tuple)): - keys = tuple(keys) - if len(keys) == 0: - self.replace(value) - else: - fnc = force and self.plow or self.traverse - subtree = fnc(keys) - subtree.replace(value) - - def unset(self, iterable): - chars = list(iterable) - first = True - - while chars: - if first or isinstance(subtree, Tree) and subtree.empty(): - top = chars.pop() - subtree = self.traverse(chars) - assert top in subtree._tree, "no such key: " + chr(top) - del subtree._tree[top] - else: - break - first = False - - def empty(self): - return len(self._tree) == 0 - - def replace(self, value): - if self.parent: - self.parent[self.key] = value - self._tree = value - - def plow(self, iterable): - """Move along a path, creating nonexistant subtrees""" - tree = self._tree - last_tree = None - char = None - for char in iterable: - try: - newtree = tree[char] - if not isinstance(newtree, dict): - raise KeyError() - except KeyError: - newtree = dict() - tree[char] = newtree - last_tree = tree - tree = newtree - if isinstance(tree, dict): - return type(self)(tree, parent=last_tree, key=char) - else: - return tree - - def traverse(self, iterable): - """Move along a path, raising exceptions when failed""" - tree = self._tree - last_tree = tree - char = None - for char in iterable: - last_tree = tree - try: - tree = tree[char] - except TypeError: - raise KeyError("trying to enter leaf") - except KeyError: - raise KeyError(repr(char) + " not in tree " + str(tree)) - if isinstance(tree, dict): - return type(self)(tree, parent=last_tree, key=char) - else: - return tree - - __getitem__ = traverse diff --git a/ranger/gui/ui.py b/ranger/gui/ui.py index cd11a0d0..a2c5c9a1 100644 --- a/ranger/gui/ui.py +++ b/ranger/gui/ui.py @@ -20,7 +20,6 @@ import _curses from .displayable import DisplayableContainer from ranger.gui.curses_shortcuts import ascii_only -from ranger.container.keymap import CommandArgs from .mouse_event import MouseEvent from ranger.ext.keybinding_parser import ALT_KEY @@ -59,8 +58,7 @@ class UI(DisplayableContainer): self.fm = fm self.win = curses.initscr() - self.env.keymanager.use_context('browser') - self.env.keybuffer.clear() + self.env.keymaps.use_keymap('browser') DisplayableContainer.__init__(self, None) @@ -138,37 +136,26 @@ class UI(DisplayableContainer): if key < 0: self.env.keybuffer.clear() - return - if DisplayableContainer.press(self, key): - return + elif not DisplayableContainer.press(self, key): + self.env.keymaps.use_keymap('browser') + self.press(key) + def press(self, key): + keybuffer = self.env.keybuffer self.status.clear_message() - - self.env.keymanager.use_context('browser') - self.env.key_append(key) - kbuf = self.env.keybuffer - cmd = kbuf.command - self.fm.hide_bookmarks() - if kbuf.failure: - kbuf.clear() - return - elif not cmd: - return + keybuffer.add(key) - self.env.cmd = cmd - - if cmd.function: + if keybuffer.result is not None: try: - cmd.function(CommandArgs.from_widget(self.fm)) - except Exception as error: - self.fm.notify(error) - if kbuf.done: - kbuf.clear() - else: - kbuf.clear() + self.fm.execute_console(keybuffer.result) + finally: + if keybuffer.finished_parsing: + keybuffer.clear() + elif keybuffer.finished_parsing: + keybuffer.clear() def handle_keys(self, *keys): for key in keys: diff --git a/ranger/gui/widgets/console.py b/ranger/gui/widgets/console.py index 00d6828b..f50a5f3c 100644 --- a/ranger/gui/widgets/console.py +++ b/ranger/gui/widgets/console.py @@ -151,28 +151,8 @@ class Console(Widget): self.line = '' def press(self, key): - self.env.keymanager.use_context('console') - self.env.key_append(key) - kbuf = self.env.keybuffer - cmd = kbuf.command - - if kbuf.failure: - kbuf.clear() - return - elif not cmd: - return - - self.env.cmd = cmd - - if cmd.function: - try: - cmd.function(CommandArgs.from_widget(self)) - except Exception as error: - self.fm.notify(error) - if kbuf.done: - kbuf.clear() - else: - kbuf.clear() + self.env.keymaps.use_keymap('console') + self.fm.ui.press(key) def type_key(self, key): self.tab_deque = None diff --git a/ranger/gui/widgets/pager.py b/ranger/gui/widgets/pager.py index cf8f91e4..3c11d38c 100644 --- a/ranger/gui/widgets/pager.py +++ b/ranger/gui/widgets/pager.py @@ -110,28 +110,8 @@ class Pager(Widget): offset=-self.hei + 1) def press(self, key): - self.env.keymanager.use_context(self.embedded and 'embedded_pager' or 'pager') - self.env.key_append(key) - kbuf = self.env.keybuffer - cmd = kbuf.command - - if kbuf.failure: - kbuf.clear() - return - elif not cmd: - return - - self.env.cmd = cmd - - if cmd.function: - try: - cmd.function(CommandArgs.from_widget(self)) - except Exception as error: - self.fm.notify(error) - if kbuf.done: - kbuf.clear() - else: - kbuf.clear() + self.env.keymaps.use_keymap(self.embedded and 'embedded_pager' or 'pager') + self.fm.ui.press(key) def set_source(self, source, strip=False): if self.source and self.source_is_stream: diff --git a/ranger/gui/widgets/taskview.py b/ranger/gui/widgets/taskview.py index e988b08c..2dcace92 100644 --- a/ranger/gui/widgets/taskview.py +++ b/ranger/gui/widgets/taskview.py @@ -96,28 +96,8 @@ class TaskView(Widget, Accumulator): self.fm.loader.move(_from=i, to=to) def press(self, key): - self.env.keymanager.use_context('taskview') - self.env.key_append(key) - kbuf = self.env.keybuffer - cmd = kbuf.command - - if kbuf.failure: - kbuf.clear() - return - elif not cmd: - return - - self.env.cmd = cmd - - if cmd.function: - try: - cmd.function(CommandArgs.from_widget(self)) - except Exception as error: - self.fm.notify(error) - if kbuf.done: - kbuf.clear() - else: - kbuf.clear() + self.env.keymaps.use_keymap('taskview') + self.fm.ui.press(key) def get_list(self): return self.fm.loader.queue |