Allow combining multiple independent actions into a single shortcut

Fixes #128
This commit is contained in:
Kovid Goyal 2017-10-20 12:31:36 +05:30
parent e8a1ada5bf
commit efc8b898f8
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
4 changed files with 45 additions and 15 deletions

View File

@ -29,3 +29,5 @@ version 0.4.0 [future]
- The block cursor in now fully opaque but renders the character under it in - The block cursor in now fully opaque but renders the character under it in
the background color, for enhanced visibility. the background color, for enhanced visibility.
- Allow combining multiple independent actions into a single shortcut

View File

@ -168,11 +168,15 @@ class Boss:
def dispatch_special_key(self, key, scancode, action, mods): def dispatch_special_key(self, key, scancode, action, mods):
# Handles shortcuts, return True if the key was consumed # Handles shortcuts, return True if the key was consumed
action = get_shortcut(self.opts.keymap, mods, key, scancode) key_action = get_shortcut(self.opts.keymap, mods, key, scancode)
if action is not None: self.current_key_press_info = key, scancode, action, mods
f = getattr(self, action.func, None) return self.dispatch_action(key_action)
def dispatch_action(self, key_action):
if key_action is not None:
f = getattr(self, key_action.func, None)
if f is not None: if f is not None:
passthrough = f(*action.args) passthrough = f(*key_action.args)
if passthrough is not True: if passthrough is not True:
return True return True
tab = self.active_tab tab = self.active_tab
@ -181,12 +185,13 @@ class Boss:
window = self.active_window window = self.active_window
if window is None: if window is None:
return False return False
if action is not None: if key_action is not None:
f = getattr(tab, action.func, getattr(window, action.func, None)) f = getattr(tab, key_action.func, getattr(window, key_action.func, None))
if f is not None: if f is not None:
passthrough = f(*action.args) passthrough = f(*key_action.args)
if passthrough is not True: if passthrough is not True:
return True return True
key, scancode, action, mods = self.current_key_press_info
data = get_sent_data( data = get_sent_data(
self.opts.send_text_map, key, scancode, mods, window, action self.opts.send_text_map, key, scancode, mods, window, action
) )
@ -195,6 +200,10 @@ class Boss:
return True return True
return False return False
def combine(self, *actions):
for key_action in actions:
self.dispatch_action(key_action)
def on_focus(self, window, focused): def on_focus(self, window, focused):
self.window_is_focused = focused self.window_is_focused = focused
w = self.active_window w = self.active_window

View File

@ -98,12 +98,15 @@ KeyAction = namedtuple('KeyAction', 'func args')
def parse_key_action(action): def parse_key_action(action):
parts = action.split(' ', 1) parts = action.split(' ', 1)
func = parts[0]
if len(parts) == 1: if len(parts) == 1:
return KeyAction(parts[0], ()) return KeyAction(func, ())
safe_print( rest = parts[1]
'Invalid shortcut action: {}. Ignoring.'.format(action), if func == 'combine':
file=sys.stderr sep, rest = rest.split(' ', 1)
) parts = re.split(r'\s*' + re.escape(sep) + r'\s*', rest)
args = tuple(map(parse_key_action, parts))
return KeyAction(func, args)
def parse_key(val, keymap): def parse_key(val, keymap):
@ -118,7 +121,14 @@ def parse_key(val, keymap):
file=sys.stderr file=sys.stderr
) )
return return
try:
paction = parse_key_action(action) paction = parse_key_action(action)
except Exception:
safe_print(
'Invalid shortcut action: {}. Ignoring.'.format(action),
file=sys.stderr
)
else:
if paction is not None: if paction is not None:
keymap[(mods, key)] = paction keymap[(mods, key)] = paction

View File

@ -198,11 +198,20 @@ color14 #14ffff
color7 #dddddd color7 #dddddd
color15 #ffffff color15 #ffffff
# Key mapping # Key mapping
# For a list of key names, see: http://www.glfw.org/docs/latest/group__keys.html # For a list of key names, see: http://www.glfw.org/docs/latest/group__keys.html
# For a list of modifier names, see: http://www.glfw.org/docs/latest/group__mods.html # For a list of modifier names, see: http://www.glfw.org/docs/latest/group__mods.html
#
# You can use the special action no_op to unmap a keyboard shortcut that is # You can use the special action no_op to unmap a keyboard shortcut that is
# assigned in the default configuration. # assigned in the default configuration.
#
# You can combine multiple actions to be triggered by a single shortcut, using the
# syntax below:
# map key combine <separator> action1 <separator> action2 <separator> action3 ...
# For example:
map ctrl+shift+e combine : new_window : next_layout
# this will create a new window and switch to the next available layout
# Clipboard # Clipboard
map ctrl+shift+v paste_from_clipboard map ctrl+shift+v paste_from_clipboard