Merge pull request #806 from vssdeo/805-keyboard-shortcut-support-for-plugins-code-decoupling

805 keyboard shortcut support for plugins code decoupling
This commit is contained in:
Matt Rose 2023-08-25 21:20:05 -04:00 committed by GitHub
commit 9c054ac29e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 177 additions and 2 deletions

View File

@ -720,7 +720,20 @@ class ConfigBase(Borg):
for section_name in ['global_config', 'keybindings']:
dbg('Processing section: %s' % section_name)
section = getattr(self, section_name)
parser[section_name] = dict_diff(DEFAULTS[section_name], section)
if section_name == 'keybindings':
from terminatorlib.plugin import KeyBindUtil
# for plugin KeyBindUtil assist in plugin_util
keybindutil = KeyBindUtil();
keyb_keys = keybindutil.get_all_act_to_keys()
# we only need keys as a reference so to match them
# against new values
keyb_keys = dict.fromkeys(keyb_keys, "")
default_merged_section = {**keyb_keys, **DEFAULTS[section_name]}
merged_section = {**keyb_keys, **section}
parser[section_name] = dict_diff(default_merged_section, merged_section)
else:
parser[section_name] = dict_diff(DEFAULTS[section_name], section)
from .configjson import JSON_PROFILE_NAME, JSON_LAYOUT_NAME

View File

@ -197,3 +197,138 @@ class MenuItem(Plugin):
def callback(self, menuitems, menu, terminal):
"""Callback to transform the enclosed URL"""
raise NotImplementedError
"""
-Basic plugin util for key-press handling, has all mapping to be used
in layout keybindings
Vishweshwar Saran Singh Deo vssdeo@gmail.com
"""
from gi.repository import Gtk, Gdk
from terminatorlib.keybindings import Keybindings, KeymapError
PLUGIN_UTIL_DESC = 0
PLUGIN_UTIL_ACT = 1
PLUGIN_UTIL_KEYS = 2
class KeyBindUtil:
keybindings = Keybindings()
map_key_to_act = {}
map_act_to_keys = {}
map_act_to_desc = {}
def __init__(self, config=None):
self.config = config
#Example
# bind
# first param is desc, second is action str
# self.keyb.bindkey([PluginUrlFindNext , PluginUrlActFindNext, "<Alt>j"])
#
# get action name
# act = self.keyb.keyaction(event)
# if act == "url_find_next":
#check map key_val_mask -> action
def _check_keybind_change(self, key):
act = key[PLUGIN_UTIL_ACT]
for key_val_mask in self.map_key_to_act:
old_act = self.map_key_to_act[key_val_mask]
if act == old_act:
return key_val_mask
return None
#check in config before binding
def bindkey_check_config(self, key):
if not self.config:
raise Warning("bindkey_check_config called without config init")
actstr = key[PLUGIN_UTIL_ACT]
kbsect = self.config.base.get_item('keybindings')
keystr = kbsect[actstr] if actstr in kbsect else ""
dbg("bindkey_check_config:action (%s) key str:(%s)" % (actstr, keystr))
if len(keystr):
key[PLUGIN_UTIL_KEYS] = keystr
dbg("found new Action->KeyVal in config: (%s, %s)"
% (actstr, keystr));
self.bindkey(key)
def bindkey(self, key):
(keyval, mask) = self.keybindings._parsebinding(key[PLUGIN_UTIL_KEYS])
keyval = Gdk.keyval_to_lower(keyval)
mask = Gdk.ModifierType(mask)
ret = (keyval, mask)
dbg("bindkey: (%s) (%s)" % (key[PLUGIN_UTIL_KEYS], str(ret)))
#remove if any old key_val_mask
old_key_val_mask = self._check_keybind_change(key)
if old_key_val_mask:
dbg("found old key binding, removing: (%s)" % str(old_key_val_mask))
del self.map_key_to_act[old_key_val_mask]
#map key-val-mask to action, used to ease key-press management
self.map_key_to_act[ret] = key[PLUGIN_UTIL_ACT]
#map action to key-combo-str, used in preferences->keybinding
self.map_act_to_keys[key[PLUGIN_UTIL_ACT]] = key[PLUGIN_UTIL_KEYS]
#map action to key-combo description, in used preferences->keybinding
self.map_act_to_desc[key[PLUGIN_UTIL_ACT]] = key[PLUGIN_UTIL_DESC]
def unbindkey(self, key):
# Suppose user changed the key-combo and its diff from
# what the plugin had set by default, we need to get
# current key-combo
act = key[PLUGIN_UTIL_ACT]
act_keys = self.map_act_to_keys[act]
(keyval, mask) = self.keybindings._parsebinding(act_keys)
keyval = Gdk.keyval_to_lower(keyval)
mask = Gdk.ModifierType(mask)
ret = (keyval, mask)
dbg("unbindkey: (%s) (%s)" % (key[PLUGIN_UTIL_KEYS], str(ret)))
# FIXME keys should always be there, can also use .pop(key, None)
# lets do it after testing
del self.map_key_to_act[ret]
del self.map_act_to_keys[key[PLUGIN_UTIL_ACT]]
del self.map_act_to_desc[key[PLUGIN_UTIL_ACT]]
def keyaction(self, event):
#FIXME MOD2 mask comes in the event, remove
event.state &= ~Gdk.ModifierType.MOD2_MASK
keyval = Gdk.keyval_to_lower(event.keyval)
ret = (keyval, event.state)
dbg("keyaction: (%s)" % str(ret))
return self.map_key_to_act.get(ret, None)
def get_act_to_keys(self, key):
return self.map_act_to_keys.get(key)
def get_all_act_to_keys(self):
return self.map_act_to_keys
def get_all_act_to_desc(self):
return self.map_act_to_desc
def get_act_to_desc(self, act):
return self.map_act_to_desc.get(act)
#get action to key binding from config
def get_act_to_keys_config(self, act):
if not self.config:
raise Warning("get_keyvalmask_for_act called without config init")
keybindings = self.config["keybindings"]
return keybindings.get(act)

View File

@ -18,6 +18,8 @@ from .terminator import Terminator
from .plugin import PluginRegistry
from .version import APP_NAME
from .plugin import KeyBindUtil
def get_color_string(widcol):
return('#%02x%02x%02x' % (widcol.red>>8, widcol.green>>8, widcol.blue>>8))
@ -472,6 +474,15 @@ class PrefsEditor:
liststore = widget.get_model()
liststore.set_sort_column_id(0, Gtk.SortType.ASCENDING)
keybindings = self.config['keybindings']
keybindutil = KeyBindUtil()
plugin_keyb_act = keybindutil.get_all_act_to_keys()
plugin_keyb_desc = keybindutil.get_all_act_to_desc()
#merge give preference to main bindings over plugin
keybindings = {**plugin_keyb_act, **keybindings}
self.keybindingnames = {**plugin_keyb_desc, **self.keybindingnames}
#dbg("appended actions %s names %s" % (keybindings, self.keybindingnames))
for keybinding in keybindings:
keyval = 0
mask = 0
@ -1900,8 +1911,14 @@ class PrefsEditor:
current_binding = liststore.get_value(liststore.get_iter(path), 0)
parsed_accel = Gtk.accelerator_parse(accel)
keybindutil = KeyBindUtil()
keybindings = self.config["keybindings"]
#merge give preference to main bindings over plugin
plugin_keyb_act = keybindutil.get_all_act_to_keys()
keybindings = {**plugin_keyb_act, **keybindings}
duplicate_bindings = []
for conf_binding, conf_accel in self.config["keybindings"].items():
for conf_binding, conf_accel in keybindings.items():
if conf_accel is None:
continue
@ -1944,6 +1961,16 @@ class PrefsEditor:
binding = liststore.get_value(liststore.get_iter(path), 0)
accel = Gtk.accelerator_name(key, mods)
self.config['keybindings'][binding] = accel
plugin_keyb_desc = keybindutil.get_act_to_desc(binding)
if plugin_keyb_desc:
dbg("modifying plugin binding: %s, %s, %s" %
(plugin_keyb_desc, binding, accel))
keybindutil.bindkey([plugin_keyb_desc, binding, accel])
else:
dbg("skipping: %s" % binding)
pass
self.config.save()
def on_cellrenderer_accel_cleared(self, liststore, path):