aboutsummaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
authormitchell <70453897+667e-11@users.noreply.github.com>2010-12-26 19:43:49 -0500
committermitchell <70453897+667e-11@users.noreply.github.com>2010-12-26 19:43:49 -0500
commit034d3e7335cb8991333fe9a2edb99509689ebcfa (patch)
tree1bfddee1ce87622cd1af2c5e52d03a4b1d236650 /modules
parenteaf639a59643ee3e84a573c2c3d95c78326fd41c (diff)
downloadtextadept-034d3e7335cb8991333fe9a2edb99509689ebcfa.tar.gz
textadept-034d3e7335cb8991333fe9a2edb99509689ebcfa.zip
Separated key command manager from key command definitions.
Diffstat (limited to 'modules')
-rw-r--r--modules/textadept/editing.lua5
-rw-r--r--modules/textadept/find.lua7
-rw-r--r--modules/textadept/keys.lua285
3 files changed, 9 insertions, 288 deletions
diff --git a/modules/textadept/editing.lua b/modules/textadept/editing.lua
index fd618c9f..6a0f7cca 100644
--- a/modules/textadept/editing.lua
+++ b/modules/textadept/editing.lua
@@ -2,6 +2,7 @@
local L = _G.locale.localize
local events = _G.events
+local K = keys.KEYSYMS
---
-- Editing commands for the textadept module.
@@ -85,7 +86,7 @@ events.connect('char_added',
events.connect('keypress',
function(code, shift, control, alt) -- removes matched chars on backspace
- if not AUTOPAIR or code ~= 0xff08 or buffer.selections ~= 1 then return end
+ if not AUTOPAIR or K[code] ~= '\b' or buffer.selections ~= 1 then return end
local buffer = buffer
local current_pos = buffer.current_pos
local c = buffer.char_at[current_pos - 1]
@@ -441,7 +442,7 @@ local function clear_highlighted_words()
buffer:indicator_clear_range(0, buffer.length)
end
events.connect('keypress',
- function(c) if c == 0xff1b then clear_highlighted_words() end end) -- Esc
+ function(c) if K[c] == 'esc' then clear_highlighted_words() end end)
---
-- Highlights all occurances of the word under the caret and adds markers to the
diff --git a/modules/textadept/find.lua b/modules/textadept/find.lua
index 3798ead9..5eadddd2 100644
--- a/modules/textadept/find.lua
+++ b/modules/textadept/find.lua
@@ -168,12 +168,13 @@ end
events.connect('command_entry_keypress',
function(code)
+ local K = _G.keys.KEYSYMS
if find.incremental then
- if code == 0xff1b then -- escape
+ if K[code] == 'esc' then
find.incremental = nil
- elseif code < 256 or code == 0xff08 then -- character or backspace
+ elseif code < 256 or K[code] == '\b' then
local text = gui.command_entry.entry_text
- if code == 0xff08 then
+ if K[code] == '\b' then
find_incremental(text:sub(1, -2))
else
find_incremental(text..string.char(code))
diff --git a/modules/textadept/keys.lua b/modules/textadept/keys.lua
index 490b31c8..a1960a19 100644
--- a/modules/textadept/keys.lua
+++ b/modules/textadept/keys.lua
@@ -1,134 +1,13 @@
-- Copyright 2007-2010 Mitchell mitchell<att>caladbolg.net. See LICENSE.
local L = _G.locale.localize
-local events = _G.events
---
--- Manages and defines key commands in Textadept.
+-- Defines key commands for Textadept.
-- This set of key commands is pretty standard among other text editors.
module('_m.textadept.keys', package.seeall)
--- Markdown:
--- ## Overview
---
--- Key commands are defined in the global table `keys`. Each key-value pair in
--- `keys` consists of either:
---
--- * A string representing a key command and an associated action table.
--- * A string language name and its associated `keys`-like table.
--- * A string style name and its associated `keys`-like table.
--- * A string representing a key command and its associated `keys`-like table.
--- (This is a keychain sequence.)
---
--- A key command string is built from a combination of the `CTRL`, `SHIFT`,
--- `ALT`, and `ADD` constants as well as the pressed key itself. The value of
--- `ADD` is inserted between each of `CTRL`, `SHIFT`, `ALT`, and the key.
--- For example:
---
--- -- keys.lua:
--- CTRL = 'Ctrl'
--- SHIFT = 'Shift'
--- ALT = 'Alt'
--- ADD = '+'
--- -- pressing control, shift, alt and 'a' yields: 'Ctrl+Shift+Alt+A'
---
--- For key values less than 255, Lua's [`string.char()`][string_char] is used to
--- determine the key's string representation. Otherwise, the
--- [`KEYSYMS`][keysyms] lookup table is used.
---
--- [string_char]: http://www.lua.org/manual/5.1/manual.html#pdf-string.char
--- [keysyms]: ../modules/_m.textadept.keys.html#KEYSYMS
---
--- An action table is a table consisting of either:
---
--- * A Lua function followed by a list of arguments to pass to that function.
--- * A string representing a [buffer][buffer] or [view][view] function followed
--- by its respective `'buffer'` or `'view'` string and then any arguments to
--- pass to the resulting function.
---
--- `buffer.`_`function`_ by itself cannot be used because at the time of
--- evaluation, `buffer.`_`function`_ would apply only to the current
--- buffer, not for all buffers. By using this string reference system, the
--- correct `buffer.`_`function`_ will be evaluated every time. The same
--- applies to `view`.
---
--- [buffer]: ../modules/buffer.html
--- [view]: ../modules/view.html
---
--- Language names are the names of the lexer files in `lexers/` such as `cpp`
--- and `lua`. Style names are different lexer styles, most of which are in
--- `lexers/lexer.lua`; examples are `whitespace`, `comment`, and `string`.
---
--- Key commands can be chained like in Emacs using keychain sequences. By
--- default, the `Esc` key cancels the current keychain, but it can be redefined
--- by setting the `keys.clear_sequence` field. Naturally, the clear sequence
--- cannot be chained.
---
--- ## Settings
---
--- * `SCOPES_ENABLED`: Flag indicating whether scopes/styles can be used for key
--- commands.
--- * `CTRL`: The string representing the Control key.
--- * `SHIFT`: The string representing the Shift key.
--- * `ALT`: The string representing the Alt key (the Apple key on Mac OSX).
--- * `ADD`: The string representing used to join together a sequence of Control,
--- Shift, or Alt modifier keys.
---
--- ## Key Command Precedence
---
--- When searching for a key command to execute in the `keys` table, key commands
--- in the current style have priority, followed by the ones in the current
--- lexer, and finally the ones in the global table.
---
--- ## Example
---
--- keys = {
--- ['ctrl+f'] = { 'char_right', 'buffer' },
--- ['ctrl+b'] = { 'char_left', 'buffer' },
--- lua = {
--- ['ctrl+c'] = { 'add_text', 'buffer', '-- ' },
--- comment = {
--- ['ctrl+f'] = { function() print('comment') end }
--- }
--- }
--- }
---
--- The first two key commands are global and call `buffer:char_right()` and
--- `buffer:char_left()` respectively. The last two commands apply only in the
--- Lua lexer with the very last one only being available in Lua's `comment`
--- style. If `ctrl+f` is pressed when the current style is `comment` in the
--- `lua` lexer, the global key command with the same shortcut is overridden and
--- `comment` is printed to standard out.
---
--- ## Problems
---
--- All Lua functions must be defined BEFORE they are reference in key commands.
--- Therefore, any module containing key commands should be loaded after all
--- other modules, whose functions are being referenced, have been loaded.
---
--- ## Events
---
--- The following is a list of all key events generated in
--- `event_name(arguments)` format:
---
--- * **keypress** (code, shift, control, alt)<br />
--- Called when a key is pressed.
--- - code: the key code (according to `<gdk/gdkkeysyms.h>`).
--- - shift: flag indicating whether or not the Shift key is pressed.
--- - control: flag indicating whether or not the Control key is pressed.
--- - alt: flag indicating whether or not the Alt/Apple key is pressed.
--- <br />
--- Note: The Alt-Option key in Mac OSX is not available.
-
--- settings
-local SCOPES_ENABLED = true
-local ADD = ''
-local CTRL = 'c'..ADD
-local SHIFT = 's'..ADD
-local ALT = 'a'..ADD
--- end settings
-
-local keys = _M
+local keys = _G.keys
local b, v = 'buffer', 'view'
local gui = gui
@@ -473,163 +352,3 @@ else
}
keys.cy = { 'paste', b }
end
-
----
--- Provides access to key commands from _G.
--- @class table
--- @name _G.keys
-_G.keys = _M
-
---------------------------------------------------------------------------------
-------------------------- Do not edit below this line. -------------------------
---------------------------------------------------------------------------------
-
--- Optimize for speed.
-local string = _G.string
-local string_char = string.char
-local string_format = string.format
-local pcall = _G.pcall
-local next = _G.next
-local type = _G.type
-local unpack = _G.unpack
-local OSX = _G.OSX
-
----
--- Lookup table for key values higher than 255.
--- If a key value given to 'keypress' is higher than 255, this table is used to
--- return a string representation of the key if it exists.
--- @class table
--- @name KEYSYMS
-KEYSYMS = { -- from <gdk/gdkkeysyms.h>
- [65056] = '\t', -- backtab; will be 'shift'ed
- [65288] = '\b',
- [65289] = '\t',
- [65293] = '\n',
- [65307] = 'esc',
- [65535] = 'del',
- [65360] = 'home',
- [65361] = 'left',
- [65362] = 'up',
- [65363] = 'right',
- [65364] = 'down',
- [65365] = 'pup',
- [65366] = 'pdown',
- [65367] = 'end',
- [65379] = 'ins',
- [65470] = 'f1', [65471] = 'f2', [65472] = 'f3', [65473] = 'f4',
- [65474] = 'f5', [65475] = 'f6', [65476] = 'f7', [65477] = 'f8',
- [65478] = 'f9', [65479] = 'f10', [65480] = 'f11', [65481] = 'f12',
-}
-
--- The current key sequence.
-local keychain = {}
-
--- Clears the current key sequence.
-local function clear_key_sequence()
- keychain = {}
- gui.statusbar_text = ''
-end
-
--- Return codes for run_key_command().
-local INVALID = -1
-local PROPAGATE = 0
-local CHAIN = 1
-local HALT = 2
-
--- Runs a key command associated with the current keychain.
--- @param lexer Optional lexer name for lexer-specific commands.
--- @param scope Optional scope name for scope-specific commands.
--- @return INVALID, PROPAGATE, CHAIN, or HALT.
-local function run_key_command(lexer, scope)
- local key = keys
- if lexer and type(key) == 'table' and key[lexer] then key = key[lexer] end
- if scope and type(key) == 'table' and key[scope] then key = key[scope] end
- if type(key) ~= 'table' then return INVALID end
-
- for i = 1, #keychain do
- key = key[keychain[i]]
- if type(key) ~= 'table' then return INVALID end
- end
- if #key == 0 and next(key) then
- gui.statusbar_text = L('Keychain:')..' '..table.concat(keychain, ' ')
- return CHAIN
- end
-
- local f, args = key[1], { unpack(key, 2) }
- if type(key[1]) == 'string' then
- if key[2] == 'buffer' then
- f, args = buffer[f], { buffer, unpack(key, 3) }
- elseif key[2] == 'view' then
- f, args = view[f], { view, unpack(key, 3) }
- end
- end
-
- if type(f) ~= 'function' then error(L('Unknown command:')..tostring(f)) end
- return f(unpack(args)) == false and PROPAGATE or HALT
-end
-
--- Key command order for lexer and scope args passed to run_key_command().
-local order = {
- { true, true }, -- lexer and scope-specific commands
- { true, false }, -- lexer-specific commands
- { false, false } -- general commands
-}
-
--- Handles Textadept keypresses.
--- It is called every time a key is pressed, and based on lexer and scope,
--- executes a command. The command is looked up in the global 'keys' key
--- command table.
--- @return whatever the executed command returns, true by default. A true
--- return value will tell Textadept not to handle the key afterwords.
-local function keypress(code, shift, control, alt)
- local buffer = buffer
- local key
- --print(code, string.char(code))
- if code < 256 then
- key = string_char(code)
- shift = false -- for printable characters, key is upper case
- else
- key = KEYSYMS[code]
- if not key then return end
- end
- control = control and CTRL or ''
- shift = shift and SHIFT or ''
- alt = alt and ALT or ''
- local key_seq = string_format('%s%s%s%s', control, shift, alt, key)
-
- if #keychain > 0 and key_seq == keys.clear_sequence then
- clear_key_sequence()
- return true
- end
- keychain[#keychain + 1] = key_seq
-
- local lexer, scope = buffer:get_lexer(), nil
- if SCOPES_ENABLED then
- scope = buffer:get_style_name(buffer.style_at[buffer.current_pos])
- end
- local success, status
- for i = SCOPES_ENABLED and 1 or 2, #order do
- status = run_key_command(order[i][1] and lexer, order[i][2] and scope)
- if status > 0 then -- CHAIN or HALT
- if status == HALT then
- -- Clear the key sequence, but keep any status messages from the key
- -- command itself.
- keychain = {}
- if gui.statusbar_text == L('Invalid sequence') or
- gui.statusbar_text:find('^'..L('Keychain:')) then
- gui.statusbar_text = ''
- end
- end
- return true
- end
- success = success or status ~= -1
- end
- local size = #keychain - 1
- clear_key_sequence()
- if not success and size > 0 then -- INVALID keychain sequence
- gui.statusbar_text = L('Invalid sequence')
- return true
- end
- -- PROPAGATE otherwise.
-end
-events.connect('keypress', keypress, 1)