diff options
-rw-r--r-- | ranger/__main__.py | 1 | ||||
-rw-r--r-- | ranger/container/__init__.py | 2 | ||||
-rw-r--r-- | ranger/container/keymap.py | 33 | ||||
-rw-r--r-- | ranger/core/environment.py | 7 | ||||
-rw-r--r-- | ranger/defaults/keys.py | 557 | ||||
-rw-r--r-- | ranger/defaults/oldkeys.py | 555 | ||||
-rw-r--r-- | ranger/gui/ui.py | 12 | ||||
-rw-r--r-- | ranger/gui/widgets/console.py | 3 | ||||
-rw-r--r-- | ranger/gui/widgets/pager.py | 5 | ||||
-rw-r--r-- | ranger/gui/widgets/taskview.py | 1 | ||||
-rw-r--r-- | ranger/shared/settings.py | 12 | ||||
-rw-r--r-- | test/tc_newkeys.py | 39 | ||||
-rw-r--r-- | test/tc_ui.py | 2 |
13 files changed, 689 insertions, 540 deletions
diff --git a/ranger/__main__.py b/ranger/__main__.py index 674ad8f6..863eadd5 100644 --- a/ranger/__main__.py +++ b/ranger/__main__.py @@ -112,6 +112,7 @@ def main(): path = '.' Environment(path) + SettingsAware._setup_keys() try: my_ui = UI() diff --git a/ranger/container/__init__.py b/ranger/container/__init__.py index 4c8f08ba..c1bb8194 100644 --- a/ranger/container/__init__.py +++ b/ranger/container/__init__.py @@ -17,5 +17,5 @@ used to manage stored data """ from ranger.container.history import History -from .keymap import KeyMap, KeyBuffer +from .keymap import KeyMap, KeyBuffer, KeyManager from .bookmarks import Bookmarks diff --git a/ranger/container/keymap.py b/ranger/container/keymap.py index 1e634f1d..62cf0e7a 100644 --- a/ranger/container/keymap.py +++ b/ranger/container/keymap.py @@ -61,11 +61,11 @@ class KeyMap(Tree): """Contains a tree with all the keybindings""" def map(self, *args, **keywords): if keywords: - return self.add_binding(*args, **keywords) + return self._add_binding(*args, **keywords) firstarg = args[-1] if isfunction(firstarg): keywords[FUNC] = firstarg - return self.add_binding(*args[:-1], **keywords) + return self._add_binding(*args[:-1], **keywords) def decorator_function(func): keywords = {FUNC:func} self.map(*args, **keywords) @@ -74,7 +74,7 @@ class KeyMap(Tree): __call__ = map - def add_binding(self, *keys, **actions): + def _add_binding(self, *keys, **actions): assert keys bind = Binding(keys, actions) for key in keys: @@ -83,6 +83,33 @@ class KeyMap(Tree): def __getitem__(self, key): return self.traverse(translate_keys(key)) + +class KeyManager(object): + def __init__(self, keybuffer, contexts): + self._keybuffer = keybuffer + self._contexts = { + 'any': KeyMap(), + 'directions': KeyMap(), + } + for context in contexts: + self._contexts[context] = KeyMap() + + def map(self, context, *args, **keywords): + self.get_context(context).map(*args, **keywords) + + def get_context(self, context): + assert isinstance(context, str) + assert context in self._contexts, "no such context!" + return self._contexts[context] + __getitem__ = get_context + + def use_context(self, context, directions='directions'): + context = self.get_context(context) + if self._keybuffer.keymap is not context: + directions = self.get_context(directions) + self._keybuffer.assign(context, directions) + self._keybuffer.clear() + class Binding(object): """The keybinding object""" def __init__(self, keys, actions): diff --git a/ranger/core/environment.py b/ranger/core/environment.py index 0b38c475..d83003b1 100644 --- a/ranger/core/environment.py +++ b/ranger/core/environment.py @@ -20,10 +20,13 @@ import socket from os.path import abspath, normpath, join, expanduser, isdir from ranger.fsobject.directory import Directory, NoDirectoryGiven -from ranger.container import KeyBuffer, History +from ranger.container import KeyBuffer, KeyManager, History from ranger.ext.signal_dispatcher import SignalDispatcher from ranger.shared import SettingsAware +ALLOWED_CONTEXTS = ('general', 'pager', 'embedded_pager', 'taskview', + 'console') + class Environment(SettingsAware, SignalDispatcher): """A collection of data which is relevant for more than one class. @@ -40,6 +43,7 @@ class Environment(SettingsAware, SignalDispatcher): pathway = None path = None keybuffer = None + keymanager = None def __init__(self, path): SignalDispatcher.__init__(self) @@ -48,6 +52,7 @@ class Environment(SettingsAware, SignalDispatcher): self.pathway = () self.directories = {} self.keybuffer = KeyBuffer(None, None) + self.keymanager = KeyManager(self.keybuffer, ALLOWED_CONTEXTS) self.copy = set() self.history = History(self.settings.max_history_size) diff --git a/ranger/defaults/keys.py b/ranger/defaults/keys.py index 467d26e6..72558a23 100644 --- a/ranger/defaults/keys.py +++ b/ranger/defaults/keys.py @@ -39,517 +39,48 @@ Check ranger.keyapi for more information from ranger.api.keys import * -def _vimlike_aliases(map): - alias = map.alias - # the key 'k' will always do the same as KEY_UP, etc. - alias(KEY_UP, 'k') - alias(KEY_DOWN, 'j') - alias(KEY_LEFT, 'h') - alias(KEY_RIGHT, 'l') - - alias(KEY_NPAGE, ctrl('f')) - alias(KEY_PPAGE, ctrl('b')) - alias(KEY_HOME, 'gg') - alias(KEY_END, 'G') - - -def _emacs_aliases(map): - alias = map.alias - alias(KEY_LEFT, ctrl('b')) - alias(KEY_RIGHT, ctrl('f')) - alias(KEY_HOME, ctrl('a')) - alias(KEY_END, ctrl('e')) - alias(KEY_DC, ctrl('d')) - alias(DEL, ctrl('h')) - - -def initialize_commands(map): - """Initialize the commands for the main user interface""" - - # -------------------------------------------------------- movement - _vimlike_aliases(map) - _basic_movement(map) - - map.alias(KEY_LEFT, KEY_BACKSPACE, DEL) - map.alias(KEY_RIGHT, KEY_ENTER, ctrl('j')) - - map('%', fm.move(to=50, percentage=True)) - map(KEY_NPAGE, ctrl('f'), fm.move(down=1, pages=True)) - map(KEY_PPAGE, ctrl('b'), fm.move(up=1, pages=True)) - map(ctrl('d'), 'J', fm.move(down=0.5, pages=True)) - map(ctrl('u'), 'K', fm.move(up=0.5, pages=True)) - - map(']', fm.traverse()) - map('[', fm.history_go(-1)) - - # --------------------------------------------------------- history - map('H', fm.history_go(-1)) - map('L', fm.history_go(1)) - - # ----------------------------------------------- tagging / marking - map('t', fm.tag_toggle()) - map('T', fm.tag_remove()) - - map(' ', fm.mark(toggle=True)) - map('v', fm.mark(all=True, toggle=True)) - map('V', fm.mark(all=True, val=False)) - - # ------------------------------------------ file system operations - map('yy', fm.copy()) - map('dd', fm.cut()) - map('pp', fm.paste()) - map('po', fm.paste(overwrite=True)) - map('pl', fm.paste_symlink()) - map('p', hint='press //p// once again to confirm pasting' \ - ', or //l// to create symlinks') - - # ---------------------------------------------------- run programs - map('s', fm.execute_command(os.environ['SHELL'])) - map('E', fm.edit_file()) - map(',term', fm.execute_command('x-terminal-emulator', flags='d')) - map('du', fm.execute_command('du --max-depth=1 -h | less')) - - # -------------------------------------------------- toggle options - map('b', fm.notify('Warning: settings are now changed with z!', bad=True)) - map('z', hint="show_//h//idden //p//review_files //d//irectories_first " \ - "//c//ollapse_preview flush//i//nput ca//s//e_insensitive") - map('zh', fm.toggle_boolean_option('show_hidden')) - map('zp', fm.toggle_boolean_option('preview_files')) - map('zP', fm.toggle_boolean_option('preview_directories')) - map('zi', fm.toggle_boolean_option('flushinput')) - map('zd', fm.toggle_boolean_option('sort_directories_first')) - map('zc', fm.toggle_boolean_option('collapse_preview')) - map('zs', fm.toggle_boolean_option('sort_case_insensitive')) - - # ------------------------------------------------------------ sort - map('o', 'O', hint="//s//ize //b//ase//n//ame //m//time //t//ype //r//everse") - sort_dict = { - 's': 'size', - 'b': 'basename', - 'n': 'basename', - 'm': 'mtime', - 't': 'type', - } - - for key, val in sort_dict.items(): - for key, is_capital in ((key, False), (key.upper(), True)): - # reverse if any of the two letters is capital - map('o' + key, fm.sort(func=val, reverse=is_capital)) - map('O' + key, fm.sort(func=val, reverse=True)) - - map('or', 'Or', 'oR', 'OR', lambda arg: \ - arg.fm.sort(reverse=not arg.fm.settings.sort_reverse)) - - # ----------------------------------------------- console shortcuts - @map("A") - def append_to_filename(arg): - command = 'rename ' + arg.fm.env.cf.basename - arg.fm.open_console(cmode.COMMAND, command) - - map('cw', fm.open_console(cmode.COMMAND, 'rename ')) - map('cd', fm.open_console(cmode.COMMAND, 'cd ')) - map('f', fm.open_console(cmode.COMMAND_QUICK, 'find ')) - map('tf', fm.open_console(cmode.COMMAND, 'filter ')) - map('d', hint='d//u// (disk usage) d//d// (cut)') - map('@', fm.open_console(cmode.OPEN, '@')) - map('#', fm.open_console(cmode.OPEN, 'p!')) - - # --------------------------------------------- jump to directories - map('gh', fm.cd('~')) - map('ge', fm.cd('/etc')) - map('gu', fm.cd('/usr')) - map('gd', fm.cd('/dev')) - map('gl', fm.cd('/lib')) - map('go', fm.cd('/opt')) - map('gv', fm.cd('/var')) - map('gr', 'g/', fm.cd('/')) - map('gm', fm.cd('/media')) - map('gn', fm.cd('/mnt')) - map('gt', fm.cd('/tmp')) - map('gs', fm.cd('/srv')) - map('gR', fm.cd(RANGERDIR)) - - # ------------------------------------------------------------ tabs - map('gc', ctrl('W'), fm.tab_close()) - map('gt', TAB, fm.tab_move(1)) - map('gT', KEY_BTAB, fm.tab_move(-1)) - map('gn', ctrl('N'), fm.tab_new()) - for n in range(10): - map('g' + str(n), fm.tab_open(n)) - - # ------------------------------------------------------- searching - map('/', fm.open_console(cmode.SEARCH)) - - map('n', fm.search()) - map('N', fm.search(forward=False)) - - map('ct', fm.search(order='tag')) - map('cc', fm.search(order='ctime')) - map('cm', fm.search(order='mimetype')) - map('cs', fm.search(order='size')) - map('c', hint='//c//time //m//imetype //s//ize //t//agged') - - # ------------------------------------------------------- bookmarks - for key in ALLOWED_BOOKMARK_KEYS: - map("`" + key, "'" + key, fm.enter_bookmark(key)) - map("m" + key, fm.set_bookmark(key)) - map("um" + key, fm.unset_bookmark(key)) - map("`", "'", "m", "um", draw_bookmarks=True) - - # ---------------------------------------------------- change views - map('i', fm.display_file()) - map(ctrl('p'), fm.display_log()) - map('?', KEY_F1, fm.display_help()) - map('w', lambda arg: arg.fm.ui.open_taskview()) - - # ---------------------------------------------------------- custom - # This is useful to track watched episode of a series. - @bind(']') - def tag_next_and_run(arg): - fm = arg.fm - fm.tag_remove() - fm.tag_remove(movedown=False) - fm.tag_toggle() - fm.move_pointer(relative=-2) - fm.move_right() - fm.move_pointer(relative=1) - - # "enter" = shortcut for "1l" - bind(KEY_ENTER, ctrl('j'), fm.move_right(mode=1)) - - # ------------------------------------------------ system functions - _system_functions(map) - map('ZZ', 'ZQ', fm.exit()) - map(ctrl('R'), fm.reset()) - map('R', fm.reload_cwd()) - @map(ctrl('C')) - def ctrl_c(arg): - try: - item = arg.fm.loader.queue[0] - except: - arg.fm.notify("Type Q or :quit<Enter> to exit Ranger") - else: - arg.fm.notify("Aborting: " + item.get_description()) - arg.fm.loader.remove(index=0) - - map(':', ';', fm.open_console(cmode.COMMAND)) - map('>', fm.open_console(cmode.COMMAND_QUICK)) - map('!', fm.open_console(cmode.OPEN)) - map('r', fm.open_console(cmode.OPEN_QUICK)) - - map.rebuild_paths() - - -def initialize_console_commands(map): - """Initialize the commands for the console widget only""" - - _basic_movement(map) - _emacs_aliases(map) - - # -------------------------------------------------------- movement - map(KEY_UP, wdg.history_move(-1)) - map(KEY_DOWN, wdg.history_move(1)) - map(KEY_HOME, wdg.move(right=0, absolute=True)) - map(KEY_END, wdg.move(right=-1, absolute=True)) - - # ----------------------------------------- deleting / pasting text - map(KEY_DC, wdg.delete(0)) - map(KEY_BACKSPACE, DEL, wdg.delete(-1)) - map(ctrl('w'), wdg.delete_word()) - map(ctrl('k'), wdg.delete_rest(1)) - map(ctrl('u'), wdg.delete_rest(-1)) - map(ctrl('y'), wdg.paste()) - - # ------------------------------------------------ system functions - map(KEY_F1, lambda arg: arg.fm.display_command_help(arg.wdg)) - map(ctrl('c'), ESC, wdg.close()) - map(ctrl('j'), KEY_ENTER, wdg.execute()) - map(TAB, wdg.tab()) - map(KEY_BTAB, wdg.tab(-1)) - - map.rebuild_paths() - - -def initialize_taskview_commands(map): - """Initialize the commands for the TaskView widget""" - _basic_movement(map) - _vimlike_aliases(map) - _system_functions(map) - - # -------------------------------------------------- (re)move tasks - map('K', wdg.task_move(0)) - map('J', wdg.task_move(-1)) - map('dd', wdg.task_remove()) - - # ------------------------------------------------ system functions - map('?', fm.display_help()) - map('w', 'q', ESC, ctrl('d'), ctrl('c'), - lambda arg: arg.fm.ui.close_taskview()) - - map.rebuild_paths() - - -def initialize_pager_commands(map): - _base_pager_commands(map) - map('q', 'i', ESC, KEY_F1, lambda arg: arg.fm.ui.close_pager()) - map.rebuild_paths() - - -def initialize_embedded_pager_commands(map): - _base_pager_commands(map) - map('q', 'i', ESC, lambda arg: arg.fm.ui.close_embedded_pager()) - map.rebuild_paths() - - -def _base_pager_commands(map): - _basic_movement(map) - _vimlike_aliases(map) - _system_functions(map) - - # -------------------------------------------------------- movement - map(KEY_LEFT, wdg.move(left=4)) - map(KEY_RIGHT, wdg.move(right=4)) - map(KEY_NPAGE, ctrl('f'), wdg.move(down=1, pages=True)) - map(KEY_PPAGE, ctrl('b'), wdg.move(up=1, pages=True)) - map(ctrl('d'), wdg.move(down=0.5, pages=True)) - map(ctrl('u'), wdg.move(up=0.5, pages=True)) - map(' ', wdg.move(down=0.8, pages=True)) - - # ---------------------------------------------------------- others - map('E', fm.edit_file()) - map('?', fm.display_help()) - - # --------------------------------------------- less-like shortcuts - map.alias(KEY_NPAGE, 'f') - map.alias(KEY_PPAGE, 'b') - map.alias(ctrl('d'), 'd') - map.alias(ctrl('u'), 'u') - - -def _system_functions(map): - map('Q', fm.exit()) - map(ctrl('L'), fm.redraw_window()) - - -def _basic_movement(map): - map(KEY_DOWN, wdg.move(down=1)) - map(KEY_UP, wdg.move(up=1)) - map(KEY_RIGHT, wdg.move(right=1)) - map(KEY_LEFT, wdg.move(left=1)) - map(KEY_HOME, wdg.move(to=0)) - map(KEY_END, wdg.move(to=-1)) - - - -# ------ newkey: - - -def base_directions(): - # Direction Keys - map = KeyMap() - map('<down>', dir=Direction(down=1)) - map('<up>', dir=Direction(down=-1)) - map('<left>', dir=Direction(right=-1)) - map('<right>', dir=Direction(right=1)) - map('<home>', dir=Direction(down=0, absolute=True)) - map('<end>', dir=Direction(down=-1, absolute=True)) - map('<pagedown>', dir=Direction(down=1, pages=True)) - map('<pageup>', dir=Direction(down=-1, pages=True)) - map('%<any>', dir=Direction(down=1, percentage=True, absolute=True)) - map('<space>', dir=Direction(down=1, pages=True)) - map('<CR>', dir=Direction(down=1)) - - return map - -def vim(): - # Direction Keys - map = KeyMap() - map.merge(base_directions()) - map('j', alias='<down>') - map('k', alias='<up>') - map('h', alias='<left>') - map('l', alias='<right>') - map('gg', alias='<home>') - map('G', alias='<end>') - map('J', dir=Direction(down=20)) - map('K', dir=Direction(down=-20)) - - return map - -def system_keys(): - map = KeyMap() - map('Q', fm.exit()) - map('<mouse>', fm.handle_mouse()) - map('<C-L>', fm.redraw_window()) - map('<resize>', fm.resize()) - - return map - -def browser_keys(): - map = KeyMap() - map.merge(system_keys()) - - @map('<dir>') - def move(arg): - arg.fm.move(narg=arg.n, **arg.direction) - map('gg', fm.move(to=0)) - map(fm.exit(), 'Q') - - map('<cr>', fm.move(dir=Direction(right=1))) - - # --------------------------------------------------------- history - map('H', fm.history_go(-1)) - map('L', fm.history_go(1)) - - # ----------------------------------------------- tagging / marking - map('t', fm.tag_toggle()) - map('T', fm.tag_remove()) - - map(' ', fm.mark(toggle=True)) - map('v', fm.mark(all=True, toggle=True)) - map('V', fm.mark(all=True, val=False)) - - # ------------------------------------------ file system operations - map('yy', fm.copy()) - map('dd', fm.cut()) - map('pp', fm.paste()) - map('po', fm.paste(overwrite=True)) - map('pl', fm.paste_symlink()) - map('p<bg>', fm.hint('press //p// once again to confirm pasting' \ - ', or //l// to create symlinks')) - - # ---------------------------------------------------- run programs - map('s', fm.execute_command(os.environ['SHELL'])) - map('E', fm.edit_file()) - map('.term', fm.execute_command('x-terminal-emulator', flags='d')) - map('du', fm.execute_command('du --max-depth=1 -h | less')) - - # -------------------------------------------------- toggle options - map('b<bg>', fm.hint("bind_//h//idden //p//review_files" \ - "//d//irectories_first //c//ollapse_preview flush//i//nput")) - map('bh', fm.toggle_boolean_option('show_hidden')) - map('bp', fm.toggle_boolean_option('preview_files')) - map('bi', fm.toggle_boolean_option('flushinput')) - map('bd', fm.toggle_boolean_option('directories_first')) - map('bc', fm.toggle_boolean_option('collapse_preview')) - - # ------------------------------------------------------------ sort - map('o<bg>', 'O<bg>', fm.hint("//s//ize //b//ase//n//ame //m//time" \ - " //t//ype //r//everse")) - sort_dict = { - 's': 'size', - 'b': 'basename', - 'n': 'basename', - 'm': 'mtime', - 't': 'type', - } - - for key, val in sort_dict.items(): - for key, is_capital in ((key, False), (key.upper(), True)): - # reverse if any of the two letters is capital - map('o' + key, fm.sort(func=val, reverse=is_capital)) - map('O' + key, fm.sort(func=val, reverse=True)) - - map('or', 'Or', 'oR', 'OR', lambda arg: \ - arg.fm.sort(reverse=not arg.fm.settings.reverse)) - - # ----------------------------------------------- console shortcuts - @map("A") - def append_to_filename(arg): - command = 'rename ' + arg.fm.env.cf.basename - arg.fm.open_console(cmode.COMMAND, command) - - map('cw', fm.open_console(cmode.COMMAND, 'rename ')) - map('cd', fm.open_console(cmode.COMMAND, 'cd ')) - map('f', fm.open_console(cmode.COMMAND_QUICK, 'find ')) - map('bf', fm.open_console(cmode.COMMAND, 'filter ')) - map('d<bg>', fm.hint('d//u// (disk usage) d//d// (cut)')) - - - # --------------------------------------------- jump to directories - map('gh', fm.cd('~')) - map('ge', fm.cd('/etc')) - map('gu', fm.cd('/usr')) - map('gd', fm.cd('/dev')) - map('gl', fm.cd('/lib')) - map('go', fm.cd('/opt')) - map('gv', fm.cd('/var')) - map('gr', 'g/', fm.cd('/')) - map('gm', fm.cd('/media')) - map('gn', fm.cd('/mnt')) - map('gs', fm.cd('/srv')) - map('gR', fm.cd(RANGERDIR)) - - # ------------------------------------------------------------ tabs - map('gc', ctrl('W'), fm.tab_close()) - map('gt', TAB, fm.tab_move(1)) - map('gT', KEY_BTAB, fm.tab_move(-1)) - map('gn', ctrl('N'), fm.tab_new()) - for n in range(10): - map('g' + str(n), fm.tab_open(n)) - map('<A-' + str(n) + '>', fm.tab_open(n)) - - # ------------------------------------------------------- searching - map('/', fm.open_console(cmode.SEARCH)) - - map('n', fm.search()) - map('N', fm.search(forward=False)) - - map('ct', fm.search(order='tag')) - map('cc', fm.search(order='ctime')) - map('cm', fm.search(order='mimetype')) - map('cs', fm.search(order='size')) - map('c<bg>', fm.hint('//c//time //m//imetype //s//ize')) - - # ------------------------------------------------------- bookmarks - for key in ALLOWED_BOOKMARK_KEYS: - map("`" + key, "'" + key, fm.enter_bookmark(key)) - map("m" + key, fm.set_bookmark(key)) - map("um" + key, fm.unset_bookmark(key)) - map("`<bg>", "'<bg>", "m<bg>", fm.draw_bookmarks()) - - - map(':', ';', fm.open_console(cmode.COMMAND)) - - # ---------------------------------------------------- change views - map('i', fm.display_file()) - map(ctrl('p'), fm.display_log()) - map('?', KEY_F1, fm.display_help()) - map('w', lambda arg: arg.fm.ui.open_taskview()) - - # ------------------------------------------------ system functions - map('ZZ', fm.exit()) - map(ctrl('R'), fm.reset()) - map('R', fm.reload_cwd()) - map(ctrl('C'), fm.exit()) - - map(':', ';', fm.open_console(cmode.COMMAND)) - map('>', fm.open_console(cmode.COMMAND_QUICK)) - map('!', fm.open_console(cmode.OPEN)) - map('r', fm.open_console(cmode.OPEN_QUICK)) - - return map - -def console_keys(): - map = KeyMap() - map.merge(system_keys()) - - @map('<any>') - def type_key(arg): - arg.wdg.type_key(arg.match) - - map('<up>', wdg.history_move(-1)) - map('<down>', wdg.history_move(1)) - map('<tab>', wdg.tab()) - -#from pprint import pprint -#pprint(browser_keys()._tree[106].__dict__) -#raise SystemExit() - -ui_keys = browser_keys() -taskview_keys = ui_keys -pager_keys = ui_keys -embedded_pager_keys = ui_keys -console_keys = console_keys() -directions = vim() +# --------------------------------------------------------- +# Define keys for everywhere: +map = keymanager['general'] +@map('<dir>') +def move(arg): + arg.wdg.move(narg=arg.n, **arg.direction) + +map('Q', fm.exit()) +map('<C-L>', fm.redraw_window()) + +# --------------------------------------------------------- +# Define keys in "general" context: +map = keymanager['general'] + + +map('j', fm.move(down=1)) +map('Q', fm.exit()) + +# --------------------------------------------------------- history +map('H', fm.history_go(-1)) +map('L', fm.history_go(1)) + +# ----------------------------------------------- tagging / marking +map('t', fm.tag_toggle()) +map('T', fm.tag_remove()) + +map(' ', fm.mark(toggle=True)) +map('v', fm.mark(all=True, toggle=True)) +map('V', fm.mark(all=True, val=False)) + +# --------------------------------------------------------- +# Define direction keys +map = keymanager.get_context('directions') +map('<down>', dir=Direction(down=1)) +map('<up>', dir=Direction(down=-1)) +map('<left>', dir=Direction(right=-1)) +map('<right>', dir=Direction(right=1)) +map('<home>', dir=Direction(down=0, absolute=True)) +map('<end>', dir=Direction(down=-1, absolute=True)) +map('<pagedown>', dir=Direction(down=1, pages=True)) +map('<pageup>', dir=Direction(down=-1, pages=True)) +map('%<any>', dir=Direction(down=1, percentage=True, absolute=True)) +map('<space>', dir=Direction(down=1, pages=True)) +map('<CR>', dir=Direction(down=1)) diff --git a/ranger/defaults/oldkeys.py b/ranger/defaults/oldkeys.py new file mode 100644 index 00000000..467d26e6 --- /dev/null +++ b/ranger/defaults/oldkeys.py @@ -0,0 +1,555 @@ +# 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/>. + +""" +This is the default key configuration file of ranger. +Syntax for binding keys: map(*keys, fnc) + +keys are one or more key-combinations which are either: +* a string +* an integer which represents an ascii code +* a tuple of integers + +fnc is a function which is called with the CommandArgument object. + +The CommandArgument object has these attributes: +arg.fm: the file manager instance +arg.wdg: the widget or ui instance +arg.n: the number typed before the key combination (if allowed) +arg.keys: the string representation of the used key combination +arg.keybuffer: the keybuffer instance + +Check ranger.keyapi for more information +""" + +# NOTE: The "map" object used below is a callable CommandList +# object and NOT the builtin python map function! + +from ranger.api.keys import * + +def _vimlike_aliases(map): + alias = map.alias + + # the key 'k' will always do the same as KEY_UP, etc. + alias(KEY_UP, 'k') + alias(KEY_DOWN, 'j') + alias(KEY_LEFT, 'h') + alias(KEY_RIGHT, 'l') + + alias(KEY_NPAGE, ctrl('f')) + alias(KEY_PPAGE, ctrl('b')) + alias(KEY_HOME, 'gg') + alias(KEY_END, 'G') + + +def _emacs_aliases(map): + alias = map.alias + alias(KEY_LEFT, ctrl('b')) + alias(KEY_RIGHT, ctrl('f')) + alias(KEY_HOME, ctrl('a')) + alias(KEY_END, ctrl('e')) + alias(KEY_DC, ctrl('d')) + alias(DEL, ctrl('h')) + + +def initialize_commands(map): + """Initialize the commands for the main user interface""" + + # -------------------------------------------------------- movement + _vimlike_aliases(map) + _basic_movement(map) + + map.alias(KEY_LEFT, KEY_BACKSPACE, DEL) + map.alias(KEY_RIGHT, KEY_ENTER, ctrl('j')) + + map('%', fm.move(to=50, percentage=True)) + map(KEY_NPAGE, ctrl('f'), fm.move(down=1, pages=True)) + map(KEY_PPAGE, ctrl('b'), fm.move(up=1, pages=True)) + map(ctrl('d'), 'J', fm.move(down=0.5, pages=True)) + map(ctrl('u'), 'K', fm.move(up=0.5, pages=True)) + + map(']', fm.traverse()) + map('[', fm.history_go(-1)) + + # --------------------------------------------------------- history + map('H', fm.history_go(-1)) + map('L', fm.history_go(1)) + + # ----------------------------------------------- tagging / marking + map('t', fm.tag_toggle()) + map('T', fm.tag_remove()) + + map(' ', fm.mark(toggle=True)) + map('v', fm.mark(all=True, toggle=True)) + map('V', fm.mark(all=True, val=False)) + + # ------------------------------------------ file system operations + map('yy', fm.copy()) + map('dd', fm.cut()) + map('pp', fm.paste()) + map('po', fm.paste(overwrite=True)) + map('pl', fm.paste_symlink()) + map('p', hint='press //p// once again to confirm pasting' \ + ', or //l// to create symlinks') + + # ---------------------------------------------------- run programs + map('s', fm.execute_command(os.environ['SHELL'])) + map('E', fm.edit_file()) + map(',term', fm.execute_command('x-terminal-emulator', flags='d')) + map('du', fm.execute_command('du --max-depth=1 -h | less')) + + # -------------------------------------------------- toggle options + map('b', fm.notify('Warning: settings are now changed with z!', bad=True)) + map('z', hint="show_//h//idden //p//review_files //d//irectories_first " \ + "//c//ollapse_preview flush//i//nput ca//s//e_insensitive") + map('zh', fm.toggle_boolean_option('show_hidden')) + map('zp', fm.toggle_boolean_option('preview_files')) + map('zP', fm.toggle_boolean_option('preview_directories')) + map('zi', fm.toggle_boolean_option('flushinput')) + map('zd', fm.toggle_boolean_option('sort_directories_first')) + map('zc', fm.toggle_boolean_option('collapse_preview')) + map('zs', fm.toggle_boolean_option('sort_case_insensitive')) + + # ------------------------------------------------------------ sort + map('o', 'O', hint="//s//ize //b//ase//n//ame //m//time //t//ype //r//everse") + sort_dict = { + 's': 'size', + 'b': 'basename', + 'n': 'basename', + 'm': 'mtime', + 't': 'type', + } + + for key, val in sort_dict.items(): + for key, is_capital in ((key, False), (key.upper(), True)): + # reverse if any of the two letters is capital + map('o' + key, fm.sort(func=val, reverse=is_capital)) + map('O' + key, fm.sort(func=val, reverse=True)) + + map('or', 'Or', 'oR', 'OR', lambda arg: \ + arg.fm.sort(reverse=not arg.fm.settings.sort_reverse)) + + # ----------------------------------------------- console shortcuts + @map("A") + def append_to_filename(arg): + command = 'rename ' + arg.fm.env.cf.basename + arg.fm.open_console(cmode.COMMAND, command) + + map('cw', fm.open_console(cmode.COMMAND, 'rename ')) + map('cd', fm.open_console(cmode.COMMAND, 'cd ')) + map('f', fm.open_console(cmode.COMMAND_QUICK, 'find ')) + map('tf', fm.open_console(cmode.COMMAND, 'filter ')) + map('d', hint='d//u// (disk usage) d//d// (cut)') + map('@', fm.open_console(cmode.OPEN, '@')) + map('#', fm.open_console(cmode.OPEN, 'p!')) + + # --------------------------------------------- jump to directories + map('gh', fm.cd('~')) + map('ge', fm.cd('/etc')) + map('gu', fm.cd('/usr')) + map('gd', fm.cd('/dev')) + map('gl', fm.cd('/lib')) + map('go', fm.cd('/opt')) + map('gv', fm.cd('/var')) + map('gr', 'g/', fm.cd('/')) + map('gm', fm.cd('/media')) + map('gn', fm.cd('/mnt')) + map('gt', fm.cd('/tmp')) + map('gs', fm.cd('/srv')) + map('gR', fm.cd(RANGERDIR)) + + # ------------------------------------------------------------ tabs + map('gc', ctrl('W'), fm.tab_close()) + map('gt', TAB, fm.tab_move(1)) + map('gT', KEY_BTAB, fm.tab_move(-1)) + map('gn', ctrl('N'), fm.tab_new()) + for n in range(10): + map('g' + str(n), fm.tab_open(n)) + + # ------------------------------------------------------- searching + map('/', fm.open_console(cmode.SEARCH)) + + map('n', fm.search()) + map('N', fm.search(forward=False)) + + map('ct', fm.search(order='tag')) + map('cc', fm.search(order='ctime')) + map('cm', fm.search(order='mimetype')) + map('cs', fm.search(order='size')) + map('c', hint='//c//time //m//imetype //s//ize //t//agged') + + # ------------------------------------------------------- bookmarks + for key in ALLOWED_BOOKMARK_KEYS: + map("`" + key, "'" + key, fm.enter_bookmark(key)) + map("m" + key, fm.set_bookmark(key)) + map("um" + key, fm.unset_bookmark(key)) + map("`", "'", "m", "um", draw_bookmarks=True) + + # ---------------------------------------------------- change views + map('i', fm.display_file()) + map(ctrl('p'), fm.display_log()) + map('?', KEY_F1, fm.display_help()) + map('w', lambda arg: arg.fm.ui.open_taskview()) + + # ---------------------------------------------------------- custom + # This is useful to track watched episode of a series. + @bind(']') + def tag_next_and_run(arg): + fm = arg.fm + fm.tag_remove() + fm.tag_remove(movedown=False) + fm.tag_toggle() + fm.move_pointer(relative=-2) + fm.move_right() + fm.move_pointer(relative=1) + + # "enter" = shortcut for "1l" + bind(KEY_ENTER, ctrl('j'), fm.move_right(mode=1)) + + # ------------------------------------------------ system functions + _system_functions(map) + map('ZZ', 'ZQ', fm.exit()) + map(ctrl('R'), fm.reset()) + map('R', fm.reload_cwd()) + @map(ctrl('C')) + def ctrl_c(arg): + try: + item = arg.fm.loader.queue[0] + except: + arg.fm.notify("Type Q or :quit<Enter> to exit Ranger") + else: + arg.fm.notify("Aborting: " + item.get_description()) + arg.fm.loader.remove(index=0) + + map(':', ';', fm.open_console(cmode.COMMAND)) + map('>', fm.open_console(cmode.COMMAND_QUICK)) + map('!', fm.open_console(cmode.OPEN)) + map('r', fm.open_console(cmode.OPEN_QUICK)) + + map.rebuild_paths() + + +def initialize_console_commands(map): + """Initialize the commands for the console widget only""" + + _basic_movement(map) + _emacs_aliases(map) + + # -------------------------------------------------------- movement + map(KEY_UP, wdg.history_move(-1)) + map(KEY_DOWN, wdg.history_move(1)) + map(KEY_HOME, wdg.move(right=0, absolute=True)) + map(KEY_END, wdg.move(right=-1, absolute=True)) + + # ----------------------------------------- deleting / pasting text + map(KEY_DC, wdg.delete(0)) + map(KEY_BACKSPACE, DEL, wdg.delete(-1)) + map(ctrl('w'), wdg.delete_word()) + map(ctrl('k'), wdg.delete_rest(1)) + map(ctrl('u'), wdg.delete_rest(-1)) + map(ctrl('y'), wdg.paste()) + + # ------------------------------------------------ system functions + map(KEY_F1, lambda arg: arg.fm.display_command_help(arg.wdg)) + map(ctrl('c'), ESC, wdg.close()) + map(ctrl('j'), KEY_ENTER, wdg.execute()) + map(TAB, wdg.tab()) + map(KEY_BTAB, wdg.tab(-1)) + + map.rebuild_paths() + + +def initialize_taskview_commands(map): + """Initialize the commands for the TaskView widget""" + _basic_movement(map) + _vimlike_aliases(map) + _system_functions(map) + + # -------------------------------------------------- (re)move tasks + map('K', wdg.task_move(0)) + map('J', wdg.task_move(-1)) + map('dd', wdg.task_remove()) + + # ------------------------------------------------ system functions + map('?', fm.display_help()) + map('w', 'q', ESC, ctrl('d'), ctrl('c'), + lambda arg: arg.fm.ui.close_taskview()) + + map.rebuild_paths() + + +def initialize_pager_commands(map): + _base_pager_commands(map) + map('q', 'i', ESC, KEY_F1, lambda arg: arg.fm.ui.close_pager()) + map.rebuild_paths() + + +def initialize_embedded_pager_commands(map): + _base_pager_commands(map) + map('q', 'i', ESC, lambda arg: arg.fm.ui.close_embedded_pager()) + map.rebuild_paths() + + +def _base_pager_commands(map): + _basic_movement(map) + _vimlike_aliases(map) + _system_functions(map) + + # -------------------------------------------------------- movement + map(KEY_LEFT, wdg.move(left=4)) + map(KEY_RIGHT, wdg.move(right=4)) + map(KEY_NPAGE, ctrl('f'), wdg.move(down=1, pages=True)) + map(KEY_PPAGE, ctrl('b'), wdg.move(up=1, pages=True)) + map(ctrl('d'), wdg.move(down=0.5, pages=True)) + map(ctrl('u'), wdg.move(up=0.5, pages=True)) + map(' ', wdg.move(down=0.8, pages=True)) + + # ---------------------------------------------------------- others + map('E', fm.edit_file()) + map('?', fm.display_help()) + + # --------------------------------------------- less-like shortcuts + map.alias(KEY_NPAGE, 'f') + map.alias(KEY_PPAGE, 'b') + map.alias(ctrl('d'), 'd') + map.alias(ctrl('u'), 'u') + + +def _system_functions(map): + map('Q', fm.exit()) + map(ctrl('L'), fm.redraw_window()) + + +def _basic_movement(map): + map(KEY_DOWN, wdg.move(down=1)) + map(KEY_UP, wdg.move(up=1)) + map(KEY_RIGHT, wdg.move(right=1)) + map(KEY_LEFT, wdg.move(left=1)) + map(KEY_HOME, wdg.move(to=0)) + map(KEY_END, wdg.move(to=-1)) + + + +# ------ newkey: + + +def base_directions(): + # Direction Keys + map = KeyMap() + map('<down>', dir=Direction(down=1)) + map('<up>', dir=Direction(down=-1)) + map('<left>', dir=Direction(right=-1)) + map('<right>', dir=Direction(right=1)) + map('<home>', dir=Direction(down=0, absolute=True)) + map('<end>', dir=Direction(down=-1, absolute=True)) + map('<pagedown>', dir=Direction(down=1, pages=True)) + map('<pageup>', dir=Direction(down=-1, pages=True)) + map('%<any>', dir=Direction(down=1, percentage=True, absolute=True)) + map('<space>', dir=Direction(down=1, pages=True)) + map('<CR>', dir=Direction(down=1)) + + return map + +def vim(): + # Direction Keys + map = KeyMap() + map.merge(base_directions()) + map('j', alias='<down>') + map('k', alias='<up>') + map('h', alias='<left>') + map('l', alias='<right>') + map('gg', alias='<home>') + map('G', alias='<end>') + map('J', dir=Direction(down=20)) + map('K', dir=Direction(down=-20)) + + return map + +def system_keys(): + map = KeyMap() + map('Q', fm.exit()) + map('<mouse>', fm.handle_mouse()) + map('<C-L>', fm.redraw_window()) + map('<resize>', fm.resize()) + + return map + +def browser_keys(): + map = KeyMap() + map.merge(system_keys()) + + @map('<dir>') + def move(arg): + arg.fm.move(narg=arg.n, **arg.direction) + map('gg', fm.move(to=0)) + map(fm.exit(), 'Q') + + map('<cr>', fm.move(dir=Direction(right=1))) + + # --------------------------------------------------------- history + map('H', fm.history_go(-1)) + map('L', fm.history_go(1)) + + # ----------------------------------------------- tagging / marking + map('t', fm.tag_toggle()) + map('T', fm.tag_remove()) + + map(' ', fm.mark(toggle=True)) + map('v', fm.mark(all=True, toggle=True)) + map('V', fm.mark(all=True, val=False)) + + # ------------------------------------------ file system operations + map('yy', fm.copy()) + map('dd', fm.cut()) + map('pp', fm.paste()) + map('po', fm.paste(overwrite=True)) + map('pl', fm.paste_symlink()) + map('p<bg>', fm.hint('press //p// once again to confirm pasting' \ + ', or //l// to create symlinks')) + + # ---------------------------------------------------- run programs + map('s', fm.execute_command(os.environ['SHELL'])) + map('E', fm.edit_file()) + map('.term', fm.execute_command('x-terminal-emulator', flags='d')) + map('du', fm.execute_command('du --max-depth=1 -h | less')) + + # -------------------------------------------------- toggle options + map('b<bg>', fm.hint("bind_//h//idden //p//review_files" \ + "//d//irectories_first //c//ollapse_preview flush//i//nput")) + map('bh', fm.toggle_boolean_option('show_hidden')) + map('bp', fm.toggle_boolean_option('preview_files')) + map('bi', fm.toggle_boolean_option('flushinput')) + map('bd', fm.toggle_boolean_option('directories_first')) + map('bc', fm.toggle_boolean_option('collapse_preview')) + + # ------------------------------------------------------------ sort + map('o<bg>', 'O<bg>', fm.hint("//s//ize //b//ase//n//ame //m//time" \ + " //t//ype //r//everse")) + sort_dict = { + 's': 'size', + 'b': 'basename', + 'n': 'basename', + 'm': 'mtime', + 't': 'type', + } + + for key, val in sort_dict.items(): + for key, is_capital in ((key, False), (key.upper(), True)): + # reverse if any of the two letters is capital + map('o' + key, fm.sort(func=val, reverse=is_capital)) + map('O' + key, fm.sort(func=val, reverse=True)) + + map('or', 'Or', 'oR', 'OR', lambda arg: \ + arg.fm.sort(reverse=not arg.fm.settings.reverse)) + + # ----------------------------------------------- console shortcuts + @map("A") + def append_to_filename(arg): + command = 'rename ' + arg.fm.env.cf.basename + arg.fm.open_console(cmode.COMMAND, command) + + map('cw', fm.open_console(cmode.COMMAND, 'rename ')) + map('cd', fm.open_console(cmode.COMMAND, 'cd ')) + map('f', fm.open_console(cmode.COMMAND_QUICK, 'find ')) + map('bf', fm.open_console(cmode.COMMAND, 'filter ')) + map('d<bg>', fm.hint('d//u// (disk usage) d//d// (cut)')) + + + # --------------------------------------------- jump to directories + map('gh', fm.cd('~')) + map('ge', fm.cd('/etc')) + map('gu', fm.cd('/usr')) + map('gd', fm.cd('/dev')) + map('gl', fm.cd('/lib')) + map('go', fm.cd('/opt')) + map('gv', fm.cd('/var')) + map('gr', 'g/', fm.cd('/')) + map('gm', fm.cd('/media')) + map('gn', fm.cd('/mnt')) + map('gs', fm.cd('/srv')) + map('gR', fm.cd(RANGERDIR)) + + # ------------------------------------------------------------ tabs + map('gc', ctrl('W'), fm.tab_close()) + map('gt', TAB, fm.tab_move(1)) + map('gT', KEY_BTAB, fm.tab_move(-1)) + map('gn', ctrl('N'), fm.tab_new()) + for n in range(10): + map('g' + str(n), fm.tab_open(n)) + map('<A-' + str(n) + '>', fm.tab_open(n)) + + # ------------------------------------------------------- searching + map('/', fm.open_console(cmode.SEARCH)) + + map('n', fm.search()) + map('N', fm.search(forward=False)) + + map('ct', fm.search(order='tag')) + map('cc', fm.search(order='ctime')) + map('cm', fm.search(order='mimetype')) + map('cs', fm.search(order='size')) + map('c<bg>', fm.hint('//c//time //m//imetype //s//ize')) + + # ------------------------------------------------------- bookmarks + for key in ALLOWED_BOOKMARK_KEYS: + map("`" + key, "'" + key, fm.enter_bookmark(key)) + map("m" + key, fm.set_bookmark(key)) + map("um" + key, fm.unset_bookmark(key)) + map("`<bg>", "'<bg>", "m<bg>", fm.draw_bookmarks()) + + + map(':', ';', fm.open_console(cmode.COMMAND)) + + # ---------------------------------------------------- change views + map('i', fm.display_file()) + map(ctrl('p'), fm.display_log()) + map('?', KEY_F1, fm.display_help()) + map('w', lambda arg: arg.fm.ui.open_taskview()) + + # ------------------------------------------------ system functions + map('ZZ', fm.exit()) + map(ctrl('R'), fm.reset()) + map('R', fm.reload_cwd()) + map(ctrl('C'), fm.exit()) + + map(':', ';', fm.open_console(cmode.COMMAND)) + map('>', fm.open_console(cmode.COMMAND_QUICK)) + map('!', fm.open_console(cmode.OPEN)) + map('r', fm.open_console(cmode.OPEN_QUICK)) + + return map + +def console_keys(): + map = KeyMap() + map.merge(system_keys()) + + @map('<any>') + def type_key(arg): + arg.wdg.type_key(arg.match) + + map('<up>', wdg.history_move(-1)) + map('<down>', wdg.history_move(1)) + map('<tab>', wdg.tab()) + +#from pprint import pprint +#pprint(browser_keys()._tree[106].__dict__) +#raise SystemExit() + +ui_keys = browser_keys() +taskview_keys = ui_keys +pager_keys = ui_keys +embedded_pager_keys = ui_keys +console_keys = console_keys() +directions = vim() diff --git a/ranger/gui/ui.py b/ranger/gui/ui.py index 8d355665..f81f1c5d 100644 --- a/ranger/gui/ui.py +++ b/ranger/gui/ui.py @@ -31,7 +31,7 @@ class UI(DisplayableContainer): is_set_up = False mousemask = curses.ALL_MOUSE_EVENTS | curses.REPORT_MOUSE_POSITION load_mode = False - def __init__(self, keymap=None, env=None, fm=None): + def __init__(self, env=None, fm=None): self._draw_title = os.environ["TERM"] in TERMINALS_WITH_TITLE os.environ['ESCDELAY'] = '25' # don't know a cleaner way @@ -40,12 +40,8 @@ class UI(DisplayableContainer): if fm is not None: self.fm = fm - if keymap is None: - self.keymap = self.settings.keys.browser_keys() - else: - self.keymap = keymap self.win = curses.initscr() - self.env.keybuffer.assign(self.keymap, self.settings.keys.directions) + self.env.keymanager.use_context('general') self.env.keybuffer.clear() DisplayableContainer.__init__(self, None) @@ -131,11 +127,11 @@ class UI(DisplayableContainer): self.env.keybuffer.clear() return - self.env.key_append(key) - if DisplayableContainer.press(self, key): return + self.env.keymanager.use_context('general') + self.env.key_append(key) kbuf = self.env.keybuffer cmd = kbuf.command diff --git a/ranger/gui/widgets/console.py b/ranger/gui/widgets/console.py index aaa85d8e..67bd7893 100644 --- a/ranger/gui/widgets/console.py +++ b/ranger/gui/widgets/console.py @@ -59,7 +59,6 @@ class Console(Widget): def __init__(self, win): from ranger.container import History Widget.__init__(self, win) - self.keymap = self.settings.keys.console_keys self.clear() self.histories = [] # load histories from files @@ -154,8 +153,6 @@ class Console(Widget): self.line = '' def press(self, key): - from curses.ascii import ctrl, ESC - keytuple = self.env.keybuffer.tuple_with_numbers() try: cmd = self.commandlist[keytuple] diff --git a/ranger/gui/widgets/pager.py b/ranger/gui/widgets/pager.py index e915f790..b99bf5db 100644 --- a/ranger/gui/widgets/pager.py +++ b/ranger/gui/widgets/pager.py @@ -40,11 +40,6 @@ class Pager(Widget): self.markup = None self.lines = [] - if embedded: - self.keymap = self.settings.keys.embedded_pager_keys - else: - self.keymap = self.settings.keys.pager_keys - def move_horizontal(self, *a, **k): """For compatibility""" self.fm.notify("Your keys.py is out of date. Can't scroll!", bad=True) diff --git a/ranger/gui/widgets/taskview.py b/ranger/gui/widgets/taskview.py index f7937e11..fe31646d 100644 --- a/ranger/gui/widgets/taskview.py +++ b/ranger/gui/widgets/taskview.py @@ -30,7 +30,6 @@ class TaskView(Widget, Accumulator): Widget.__init__(self, win) Accumulator.__init__(self) self.scroll_begin = 0 - self.keymap = self.settings.keys.taskview_keys def draw(self): base_clr = deque() diff --git a/ranger/shared/settings.py b/ranger/shared/settings.py index a4a58e6e..e4a58f33 100644 --- a/ranger/shared/settings.py +++ b/ranger/shared/settings.py @@ -154,10 +154,16 @@ class SettingsAware(object): except ImportError: from ranger.defaults import apps settings._raw_set('apps', apps) + + SettingsAware.settings = settings + + @staticmethod + def _setup_keys(): # ugly! but works. + import ranger.api.keys + import ranger.shared + env = ranger.shared.EnvironmentAware.env + ranger.api.keys.keymanager = env.keymanager try: import keys except ImportError: from ranger.defaults import keys - settings._raw_set('keys', keys) - - SettingsAware.settings = settings diff --git a/test/tc_newkeys.py b/test/tc_newkeys.py index c953e88b..b1cb42fb 100644 --- a/test/tc_newkeys.py +++ b/test/tc_newkeys.py @@ -24,7 +24,7 @@ import sys class PressTestCase(TestCase): """Some useful methods for the actual test""" - def _mkpress(self, keybuffer, keymap): + def _mkpress(self, keybuffer, _=0): def press(keys): keybuffer.clear() match = keybuffer.simulate_press(keys) @@ -492,5 +492,42 @@ class Test(PressTestCase): s.replace('Y') self.assertNotEqual(t._tree, u._tree) + def test_keymap_with_context(self): + def func(arg): + return 5 + def getdown(arg): + return arg.direction.down() + + buffer = KeyBuffer(None, None) + press = self._mkpress(buffer) + kmc = KeyManager(buffer, ['foo', 'bar']) + + map = kmc.get_context('foo') + map('a', func) + map('b', func) + map = kmc.get_context('bar') + map('c', func) + map('<dir>', getdown) + + kmc.map('directions', 'j', dir=Direction(down=1)) + + kmc.use_context('foo') + self.assertEqual(5, press('a')) + self.assertEqual(5, press('b')) + self.assertPressFails(buffer, 'c') + + kmc.use_context('bar') + self.assertPressFails(buffer, 'a') + self.assertPressFails(buffer, 'b') + self.assertEqual(5, press('c')) + self.assertEqual(1, press('j')) + kmc.use_context('foo') + kmc.use_context('foo') + kmc.use_context('foo') + kmc.use_context('bar') + kmc.use_context('foo') + kmc.use_context('bar') + kmc.use_context('bar') + self.assertEqual(1, press('j')) if __name__ == '__main__': main() diff --git a/test/tc_ui.py b/test/tc_ui.py index 98ddff93..3c659459 100644 --- a/test/tc_ui.py +++ b/test/tc_ui.py @@ -28,7 +28,7 @@ class Test(unittest.TestCase): def setUp(self): self.fm = Fake() - self.ui = ui.UI(env=Fake(), fm=self.fm, keymap=Fake()) + self.ui = ui.UI(env=Fake(), fm=self.fm) def fakesetup(): self.ui.widget = Fake() |