diff options
-rw-r--r-- | core/keys.lua | 43 | ||||
-rw-r--r-- | modules/textadept/menu.lua | 27 |
2 files changed, 18 insertions, 52 deletions
diff --git a/core/keys.lua b/core/keys.lua index ced1ff80..6187b466 100644 --- a/core/keys.lua +++ b/core/keys.lua @@ -54,13 +54,10 @@ local M = {} -- -- ## Commands -- --- A command bound to a key sequence is either a Lua function or a table --- containing a Lua function with a set of arguments to pass. They are --- functionally equivalent; you can use either. Examples are: +-- A command bound to a key sequence is simply a Lua function. For example: -- -- keys['cn'] = buffer.new -- keys['cz'] = buffer.undo --- keys['a('] = {textadept.editing.enclose, '(', ')'} -- keys['cu'] = function() io.quick_open(_USERHOME) end -- -- Textadept handles [`buffer`]() references properly in static contexts. @@ -98,7 +95,7 @@ local M = {} -- keys['aa'] = { -- a = function1, -- b = function2, --- c = {function3, arg1, arg2} +-- c = {...} -- } -- @field CLEAR (string) -- The key that clears the current key chain. @@ -165,33 +162,14 @@ local function clear_key_sequence() if #keychain == 1 then keychain[1] = nil else keychain = {} end end -local none = {} -local function key_error(e) events.emit(events.ERROR, e) end --- Runs a given command. --- This is also used by *modules/textadept/menu.lua*. --- @param command A function or table as described above. --- @param command_type Equivalent to `type(command)`. --- @return the value the command returns. -M.run_command = function(command, command_type) - local f, args = command_type == 'function' and command or command[1], none - if command_type == 'table' then - args = command - -- If the argument is a view or buffer, use the current one instead. - if type(args[2]) == 'table' then - local mt, buffer, view = getmetatable(args[2]), buffer, view - if mt == getmetatable(buffer) and args[2] ~= ui.command_entry then - args[2] = buffer - elseif mt == getmetatable(view) then - args[2] = view - end - end - end - return select(2, xpcall(f, key_error, table.unpack(args, 2))) -end - -- Return codes for `key_command()`. local INVALID, PROPAGATE, CHAIN, HALT = -1, 0, 1, 2 +-- Error handler for key commands that simply emits the error. This is needed +-- so `key_command()` can return `HALT` instead of never returning due to the +-- error. +local function key_error(e) events.emit(events.ERROR, e) end + -- Runs a key command associated with the current keychain. -- @param prefix Optional prefix name for mode/lexer-specific commands. -- @return `INVALID`, `PROPAGATE`, `CHAIN`, or `HALT`. @@ -201,13 +179,12 @@ local function key_command(prefix) if type(key) ~= 'table' then return INVALID end key = key[keychain[i]] end - local key_type = type(key) - if key_type ~= 'function' and key_type ~= 'table' then return INVALID end - if key_type == 'table' and #key == 0 and next(key) or getmetatable(key) then + if type(key) ~= 'function' and type(key) ~= 'table' then return INVALID end + if type(key) == 'table' then ui.statusbar_text = _L['Keychain:']..' '..table.concat(keychain, ' ') return CHAIN end - return M.run_command(key, key_type) == false and PROPAGATE or HALT + return select(2, xpcall(key, key_error)) == false and PROPAGATE or HALT end -- Handles Textadept keypresses. diff --git a/modules/textadept/menu.lua b/modules/textadept/menu.lua index acbcdd9a..e09c6ca4 100644 --- a/modules/textadept/menu.lua +++ b/modules/textadept/menu.lua @@ -407,19 +407,6 @@ local function get_gdk_key(key_seq) return code, modifiers end --- Get a string uniquely identifying a key binding. --- This is used to match menu items with key bindings to show the key shortcut. --- @param f A value in the `keys` table. -local function get_id(f) - local id = '' - if type(f) == 'function' then - id = tostring(f) - elseif type(f) == 'table' then - for i = 1, #f do id = id..tostring(f[i]) end - end - return id -end - -- Creates a menu suitable for `ui.menu()` from the menu table format. -- Also assigns key commands. -- @param menu The menu to create a GTK+ menu from. @@ -437,7 +424,7 @@ local function read_menu_table(menu, contextmenu) local label, f = menu[i][1], menu[i][2] local menu_id = not contextmenu and #menu_actions + 1 or #contextmenu_actions + 1000 + 1 - local key, mods = get_gdk_key(key_shortcuts[get_id(f)]) + local key, mods = get_gdk_key(key_shortcuts[tostring(f)]) gtkmenu[#gtkmenu + 1] = {label, menu_id, key, mods} if f then local actions = not contextmenu and menu_actions or contextmenu_actions @@ -491,7 +478,7 @@ end local function set_menubar(menubar) if not menubar then ui.menubar = {} return end key_shortcuts, menu_actions = {}, {} -- reset - for key, f in pairs(keys) do key_shortcuts[get_id(f)] = key end + for key, f in pairs(keys) do key_shortcuts[tostring(f)] = key end local _menubar = {} for i = 1, #menubar do _menubar[#_menubar + 1] = ui.menu(read_menu_table(menubar[i])) @@ -532,9 +519,9 @@ events.connect(events.INITIALIZED, set_contextmenus) events.connect(events.MENU_CLICKED, function(menu_id) local actions = menu_id < 1000 and menu_actions or contextmenu_actions local action = actions[menu_id < 1000 and menu_id or menu_id - 1000] - assert(type(action) == 'function' or type(action) == 'table', + assert(type(action) == 'function', _L['Unknown command:']..' '..tostring(action)) - keys.run_command(action, type(action)) + action() end) --- @@ -551,7 +538,7 @@ function M.select_command() elseif menu[i][1] ~= '' then local label = menu.title and menu.title..': '..menu[i][1] or menu[i][1] items[#items + 1] = label:gsub('_([^_])', '%1') - items[#items + 1] = key_shortcuts[get_id(menu[i][2])] or '' + items[#items + 1] = key_shortcuts[tostring(menu[i][2])] or '' commands[#commands + 1] = menu[i][2] end end @@ -562,7 +549,9 @@ function M.select_command() items = items, width = CURSES and ui.size[1] - 2 or nil } if button ~= 1 or not i then return end - keys.run_command(commands[i], type(commands[i])) + assert(type(commands[i]) == 'function', + _L['Unknown command:']..' '..tostring(commands[i])) + commands[i]() end return setmetatable(M, { |