diff options
Diffstat (limited to 'modules')
-rw-r--r-- | modules/textadept/command_entry.lua | 172 | ||||
-rw-r--r-- | modules/textadept/filter_through.lua | 87 | ||||
-rw-r--r-- | modules/textadept/find.lua | 129 | ||||
-rw-r--r-- | modules/textadept/keys.lua | 28 | ||||
-rw-r--r-- | modules/textadept/menu.lua | 4 |
5 files changed, 249 insertions, 171 deletions
diff --git a/modules/textadept/command_entry.lua b/modules/textadept/command_entry.lua index 7e52282b..005af837 100644 --- a/modules/textadept/command_entry.lua +++ b/modules/textadept/command_entry.lua @@ -1,13 +1,79 @@ -- Copyright 2007-2013 Mitchell mitchell.att.foicica.com. See LICENSE. --- Modified by Jay Gould. +-- Abbreviated environment and commands from Jay Gould. + +local M = gui.command_entry --[[ This comment is for LuaDoc. --- -- Textadept's Command Entry. +-- +-- ## Modes +-- +-- The command entry supports multiple [modes][] that have their own sets of key +-- bindings stored in a separate table in `_G.keys` under a mode prefix key. +-- Mode names are arbitrary, but cannot conflict with lexer names or key +-- sequence strings (e.g. `'lua'` or `'send'`) due to the method used for +-- looking up key bindings. An example mode is "lua_command" mode for executing +-- Lua commands: +-- +-- local gui_ce = gui.command_entry +-- keys['ce'] = {gui_ce.enter_mode, 'lua_command'} +-- keys.lua_command = { +-- ['\t'] = gui_ce.complete_lua, +-- ['\n'] = {gui_ce.finish_mode, gui_ce.execute_lua} +-- } +-- +-- In this case, `Ctrl+E` opens the command entry and enters "lua_command" key +-- mode where the `Tab` and `Enter` keys have special, defined functionality. +-- (By default, `Esc` is pre-defined to exit any command entry mode.) `Tab` +-- shows a list of Lua completions for the entry text and `Enter` exits +-- "lua_command" key mode and executes the entered code. All other keys are +-- handled normally by the command entry. +-- +-- It is important to note that while in any command entry key mode, all editor +-- key bindings are ignored -- even if the editor, not the command entry, has +-- focus. You must first exit the key mode by pressing `Esc` (or `Enter` in the +-- case of the above "lua_command" key mode). +-- +-- [modes]: keys.html#Modes -- @field entry_text (string) -- The text in the entry. module('gui.command_entry')]] +--- +-- Opens the command entry in key mode *mode*. +-- Key bindings will be looked up in `keys[mode]` instead of `keys`. The `Esc` +-- (`⎋` on Mac OSX | `Esc` in curses) key exits the current mode, closes the +-- command entry, and restores normal key lookup. +-- This function is useful for binding keys to enter a command entry mode. +-- @param mode The key mode to enter into, or `nil` to exit the current mode. +-- @usage keys['ce'] = {gui.command_entry.enter_mode, 'command_entry'} +-- @see _G.keys.MODE +-- @name enter_mode +function M.enter_mode(mode) + keys.MODE = mode + if mode then keys[mode]['esc'] = M.enter_mode end + -- In curses, M.focus() does not return immediately, so the key sequence that + -- called M.focus() is still on the keychain. Clear it. + if CURSES then keys.clear_key_sequence() end + M.focus() +end + +--- +-- Exits the current key mode, closes the command entry, and calls function *f* +-- with the command entry text as an argument. +-- This is useful for binding keys to exit a command entry mode and perform an +-- action with the entered text. +-- @param f The function to call. It should accept the command entry text as an +-- argument. +-- @usage keys['\n'] = {gui.command_entry.finish_mode, gui.print} +-- @name finish_mode +function M.finish_mode(f) + M.enter_mode(nil) + f(M.entry_text) + if CURSES then return false end -- propagate to exit CDK entry on Enter +end + -- Environment for abbreviated commands. -- @class table -- @name env @@ -29,71 +95,73 @@ local env = setmetatable({}, { end, }) -local events = events - --- Execute a Lua command. -events.connect(events.COMMAND_ENTRY_COMMAND, function(command) - local f, err = load(command, nil, 'bt', env) +--- +-- Executes string *code* as Lua code. +-- Code is subject to an "abbreviated" environment where the `buffer`, `view`, +-- and `gui` tables are also considered as globals. +-- @param code The Lua code to execute. +-- @name execute_lua +function M.execute_lua(code) + local f, err = load(code, nil, 'bt', env) if err then error(err) end - if not CURSES then gui.command_entry.focus() end -- toggle focus to hide f() events.emit(events.UPDATE_UI) -end) +end +args.register('-e', '--execute', 1, M.execute_lua, 'Execute Lua code') -events.connect(events.COMMAND_ENTRY_KEYPRESS, function(code) - if keys.KEYSYMS[code] == 'esc' then - gui.command_entry.focus() -- toggle focus to hide - elseif keys.KEYSYMS[code] == '\t' then - local substring = gui.command_entry.entry_text:match('[%w_.:]+$') or '' - local path, o, prefix = substring:match('^([%w_.:]-)([.:]?)([%w_]*)$') - local f, err = load('return ('..path..')', nil, 'bt', env) - local ok, tbl = pcall(f) - local cmpls = {} - prefix = '^'..prefix - if not ok then -- shorthand notation - for _, t in ipairs{buffer, view, gui, _G} do - for k in pairs(t) do - if type(k) == 'string' and k:find(prefix) then - cmpls[#cmpls + 1] = k - end - end +--- +-- Shows a set of Lua code completions for string *code* or `entry_text`. +-- Completions are subject to an "abbreviated" environment where the `buffer`, +-- `view`, and `gui` tables are also considered as globals. +-- @param code The Lua code to complete. The default value is the value of +-- `entry_text`. +-- @name complete_lua +function M.complete_lua(code) + local substring = (code or M.entry_text):match('[%w_.:]+$') or '' + local path, op, prefix = substring:match('^([%w_.:]-)([.:]?)([%w_]*)$') + local f, err = load('return ('..path..')', nil, 'bt', env) + local ok, tbl = pcall(f) + local cmpls = {} + prefix = '^'..prefix + if not ok then -- shorthand notation + for _, t in ipairs{buffer, view, gui, _G} do + for k in pairs(t) do + if type(k) == 'string' and k:find(prefix) then cmpls[#cmpls + 1] = k end end + end + for f in pairs(_SCINTILLA.functions) do + if f:find(prefix) then cmpls[#cmpls + 1] = f end + end + for p in pairs(_SCINTILLA.properties) do + if p:find(prefix) then cmpls[#cmpls + 1] = p end + end + else + if type(tbl) ~= 'table' then return end + for k in pairs(tbl) do + if type(k) == 'string' and k:find(prefix) then cmpls[#cmpls + 1] = k end + end + if path == 'buffer' and op == ':' then for f in pairs(_SCINTILLA.functions) do if f:find(prefix) then cmpls[#cmpls + 1] = f end end + elseif path == 'buffer' and op == '.' then for p in pairs(_SCINTILLA.properties) do if p:find(prefix) then cmpls[#cmpls + 1] = p end end - else - if type(tbl) ~= 'table' then return end - for k in pairs(tbl) do - if type(k) == 'string' and k:find(prefix) then cmpls[#cmpls + 1] = k end - end - if path == 'buffer' then - if o == ':' then - for f in pairs(_SCINTILLA.functions) do - if f:find(prefix) then cmpls[#cmpls + 1] = f end - end - else - for p in pairs(_SCINTILLA.properties) do - if p:find(prefix) then cmpls[#cmpls + 1] = p end - end - end - end end - table.sort(cmpls) - gui.command_entry.show_completions(cmpls) - return true end -end) - --- Executes Lua code on startup. -local function execute(command) - local f, err = load(command, nil, 'bt', env) - if err then error(err) end - f() + table.sort(cmpls) + M.show_completions(cmpls) + return true end -args.register('-e', '--execute', 1, execute, 'Execute Lua code') + +local events = events +-- Pass command entry keys to the default keypress handler. +-- Since the command entry is designed to be modal, command entry key bindings +-- should stay separate from editor key bindings. +events.connect(events.COMMAND_ENTRY_KEYPRESS, function(...) + if keys.MODE then return events.emit(events.KEYPRESS, ...) end +end) --[[ The function below is a Lua C function. diff --git a/modules/textadept/filter_through.lua b/modules/textadept/filter_through.lua index fbff074c..59cb77b0 100644 --- a/modules/textadept/filter_through.lua +++ b/modules/textadept/filter_through.lua @@ -9,11 +9,12 @@ module('_M.textadept.filter_through')]] local cat = not WIN32 and 'cat' or 'type' local tmpfile = _USERHOME..'/.ft' -local filter_through_active = false --- --- Prompts the user for a Linux, BSD, Mac OSX, or Windows shell command to --- filter text through with standard input (stdin) as follows: +-- Passes selected or all buffer text to string shell command *cmd* as standard +-- input (stdin) and replaces the input text with the command's standard output +-- (stdout). +-- Standard input is as follows: -- -- 1. If text is selected and spans multiple lines, all text on the lines -- containing the selection is used. However, if the end of the selection is at @@ -22,57 +23,39 @@ local filter_through_active = false -- 2. If text is selected and spans a single line, only the selected text is -- used. -- 3. If no text is selected, the entire buffer is used. --- --- The input text is replaced with the standard output (stdout) of the command. +-- @param cmd The Linux, BSD, Mac OSX, or Windows shell command to filter text +-- through. -- @name filter_through -function M.filter_through() - filter_through_active = true - gui.command_entry.focus() -end - -local events = events - -events.connect(events.COMMAND_ENTRY_KEYPRESS, function(code) - if filter_through_active and keys.KEYSYMS[code] == 'esc' then - filter_through_active = false - end -end, 1) -- place before command_entry.lua's handler (if necessary) - --- Filter through. -events.connect(events.COMMAND_ENTRY_COMMAND, function(text) - if filter_through_active then - local buffer = buffer - local s, e = buffer.selection_start, buffer.selection_end - local input - if s ~= e then -- use selected lines as input - local i, j = buffer:line_from_position(s), buffer:line_from_position(e) - if i < j then - s = buffer:position_from_line(i) - if buffer.column[e] > 0 then e = buffer:position_from_line(j + 1) end - end - input = buffer:text_range(s, e) - else -- use whole buffer as input - input = buffer:get_text() - end - local f = io.open(tmpfile, 'wb') - f:write(input) - f:close() - local cmd = cat..' "'..tmpfile..'" | '..text - if WIN32 then cmd = cmd:gsub('/', '\\') end - local p = io.popen(cmd) - if s ~= e then - buffer.target_start, buffer.target_end = s, e - buffer:replace_target(p:read('*all')) - buffer:set_sel(buffer.target_start, buffer.target_end) - else - buffer:set_text(p:read('*all')) - buffer:goto_pos(s) +function M.filter_through(cmd) + local buffer = buffer + local s, e = buffer.selection_start, buffer.selection_end + local input + if s ~= e then -- use selected lines as input + local i, j = buffer:line_from_position(s), buffer:line_from_position(e) + if i < j then + s = buffer:position_from_line(i) + if buffer.column[e] > 0 then e = buffer:position_from_line(j + 1) end end - p:close() - os.remove(tmpfile) - filter_through_active = false - return true + input = buffer:text_range(s, e) + else -- use whole buffer as input + input = buffer:get_text() end -end, 1) -- place before command_entry.lua's handler (if necessary) + local f = io.open(tmpfile, 'wb') + f:write(input) + f:close() + local cmd = cat..' "'..tmpfile..'" | '..cmd + if WIN32 then cmd = cmd:gsub('/', '\\') end + local p = io.popen(cmd) + if s ~= e then + buffer.target_start, buffer.target_end = s, e + buffer:replace_target(p:read('*all')) + buffer:set_sel(buffer.target_start, buffer.target_end) + else + buffer:set_text(p:read('*all')) + buffer:goto_pos(s) + end + p:close() + os.remove(tmpfile) +end return M diff --git a/modules/textadept/find.lua b/modules/textadept/find.lua index d1105a7b..801c333f 100644 --- a/modules/textadept/find.lua +++ b/modules/textadept/find.lua @@ -1,6 +1,6 @@ -- Copyright 2007-2013 Mitchell mitchell.att.foicica.com. See LICENSE. -local find = gui.find +local M = gui.find --[[ This comment is for LuaDoc. --- @@ -60,17 +60,17 @@ local find = gui.find module('gui.find')]] local _L = _L -find.find_label_text = not CURSES and _L['_Find:'] or _L['Find:'] -find.replace_label_text = not CURSES and _L['R_eplace:'] or _L['Replace:'] -find.find_next_button_text = not CURSES and _L['Find _Next'] or _L['[Next]'] -find.find_prev_button_text = not CURSES and _L['Find _Prev'] or _L['[Prev]'] -find.replace_button_text = not CURSES and _L['_Replace'] or _L['[Replace]'] -find.replace_all_button_text = not CURSES and _L['Replace _All'] or _L['[All]'] -find.match_case_label_text = not CURSES and _L['_Match case'] or _L['Case(F1)'] -find.whole_word_label_text = not CURSES and _L['_Whole word'] or _L['Word(F2)'] -find.lua_pattern_label_text = not CURSES and _L['_Lua pattern'] or - _L['Pattern(F3)'] -find.in_files_label_text = not CURSES and _L['_In files'] or _L['Files(F4)'] +M.find_label_text = not CURSES and _L['_Find:'] or _L['Find:'] +M.replace_label_text = not CURSES and _L['R_eplace:'] or _L['Replace:'] +M.find_next_button_text = not CURSES and _L['Find _Next'] or _L['[Next]'] +M.find_prev_button_text = not CURSES and _L['Find _Prev'] or _L['[Prev]'] +M.replace_button_text = not CURSES and _L['_Replace'] or _L['[Replace]'] +M.replace_all_button_text = not CURSES and _L['Replace _All'] or _L['[All]'] +M.match_case_label_text = not CURSES and _L['_Match case'] or _L['Case(F1)'] +M.whole_word_label_text = not CURSES and _L['_Whole word'] or _L['Word(F2)'] +M.lua_pattern_label_text = not CURSES and _L['_Lua pattern'] or + _L['Pattern(F3)'] +M.in_files_label_text = not CURSES and _L['_In files'] or _L['Files(F4)'] -- Events. local events, events_connect = events, events.connect @@ -94,7 +94,7 @@ local preferred_view -- @see find_in_files -- @class table -- @name FILTER -find.FILTER = lfs.FILTER +M.FILTER = lfs.FILTER -- Text escape sequences with their associated characters. -- @class table @@ -114,7 +114,7 @@ local escapes = { -- the user is prompted for one. -- @see FILTER -- @name find_in_files -function find.find_in_files(utf8_dir) +function M.find_in_files(utf8_dir) if not utf8_dir then utf8_dir = gui.dialog('fileselect', '--title', _L['Find in Files'], @@ -125,13 +125,13 @@ function find.find_in_files(utf8_dir) end if utf8_dir == '' then return end - local text = find.find_entry_text - if not find.lua then text = text:gsub('([().*+?^$%%[%]-])', '%%%1') end - if not find.match_case then text = text:lower() end - if find.whole_word then text = '%f[%w_]'..text..'%f[^%w_]' end + local text = M.find_entry_text + if not M.lua then text = text:gsub('([().*+?^$%%[%]-])', '%%%1') end + if not M.match_case then text = text:lower() end + if M.whole_word then text = '%f[%w_]'..text..'%f[^%w_]' end local matches = {_L['Find:']..' '..text} lfs.dir_foreach(utf8_dir, function(file) - local match_case = find.match_case + local match_case = M.match_case local line_num = 1 for line in io.lines(file) do if (match_case and line or line:lower()):find(text) then @@ -140,7 +140,7 @@ function find.find_in_files(utf8_dir) end line_num = line_num + 1 end - end, find.FILTER, true) + end, M.FILTER, true) if #matches == 1 then matches[2] = _L['No results found'] end matches[#matches + 1] = '' if buffer._type ~= _L['[Files Found Buffer]'] then preferred_view = view end @@ -174,14 +174,14 @@ local function find_(text, next, flags, nowrap, wrapped) if not flags then flags = 0 - if find.match_case then flags = flags + c.SCFIND_MATCHCASE end - if find.whole_word then flags = flags + c.SCFIND_WHOLEWORD end - if find.lua then flags = flags + 8 end - if find.in_files then flags = flags + 16 end + if M.match_case then flags = flags + c.SCFIND_MATCHCASE end + if M.whole_word then flags = flags + c.SCFIND_WHOLEWORD end + if M.lua then flags = flags + 8 end + if M.in_files then flags = flags + 16 end end local result - find.captures = nil + M.captures = nil if flags < 8 then buffer:goto_pos(buffer[next and 'current_pos' or 'anchor'] + increment) @@ -193,12 +193,12 @@ local function find_(text, next, flags, nowrap, wrapped) local buffer_text = buffer:get_text(buffer.length) local results = {buffer_text:find(text, buffer.anchor + increment + 1)} if #results > 0 then - find.captures = {table.unpack(results, 3)} + M.captures = {table.unpack(results, 3)} buffer:set_sel(results[2], results[1] - 1) end result = results[1] or -1 else -- find in files - find.find_in_files() + M.find_in_files() return end @@ -222,47 +222,52 @@ local function find_(text, next, flags, nowrap, wrapped) end events_connect(events.FIND, find_) --- Finds and selects text incrementally in the current buffer from a start --- point. +-- Finds and selects text incrementally in the current buffer from a starting +-- position. -- Flags other than `SCFIND_MATCHCASE` are ignored. -- @param text The text to find. -local function find_incremental(text) - local flags = find.match_case and c.SCFIND_MATCHCASE or 0 - buffer:goto_pos(find.incremental_start or 0) - find_(text, true, flags) +-- @param next Flag indicating whether or not the search direction is forward. +local function find_incremental(text, next) + buffer:goto_pos(M.incremental_start or 0) + find_(text, next, M.match_case and c.SCFIND_MATCHCASE or 0) end --- --- Begins an incremental find using the command entry. +-- Begins an incremental search using the command entry if *text* is `nil`; +-- otherwise continues an incremental search by searching for the next instance +-- of string *text*. -- Only the `match_case` find option is recognized. Normal command entry --- functionality will be unavailable until the search is finished by pressing --- `Esc` (`⎋` on Mac OSX | `Esc` in curses). +-- functionality is unavailable until the search is finished by pressing `Esc` +-- (`⎋` on Mac OSX | `Esc` in curses). +-- @param text The text to incrementally search for, or `nil` to begin an +-- incremental search. -- @name find_incremental -function find.find_incremental() - find.incremental, find.incremental_start = true, buffer.current_pos +function M.find_incremental(text) + if text then find_incremental(text, true) return end + M.incremental_start = buffer.current_pos gui.command_entry.entry_text = '' - gui.command_entry.focus() + gui.command_entry.enter_mode('find_incremental') end -events_connect(events.COMMAND_ENTRY_KEYPRESS, function(code) - if not find.incremental then return end - if keys.KEYSYMS[code] == 'esc' then - find.incremental = nil - elseif keys.KEYSYMS[code] == '\b' then - find_incremental(gui.command_entry.entry_text:sub(1, -2)) - elseif code < 256 then - find_incremental(gui.command_entry.entry_text..string.char(code)) - end -end, 1) -- place before command_entry.lua's handler (if necessary) - --- "Find next" for incremental search. -events_connect(events.COMMAND_ENTRY_COMMAND, function(text) - if find.incremental then - find.incremental_start = buffer.current_pos + 1 - find_incremental(text) - return true - end -end, 1) -- place before command_entry.lua's handler (if necessary) +--- +-- Continues an incremental search by searching for the next match starting from +-- the current position. +-- @see find_incremental +-- @name find_incremental_next +function M.find_incremental_next() + M.incremental_start = buffer.current_pos + 1 + find_incremental(gui.command_entry.entry_text, true) +end + +--- +-- Continues an incremental search by searching for the previous match starting +-- from the current position. +-- @see find_incremental +-- @name find_incremental_prev +function M.find_incremental_prev() + M.incremental_start = buffer.current_pos - 1 + find_incremental(gui.command_entry.entry_text, false) +end -- Optimize for speed. local load, pcall = load, pcall @@ -295,11 +300,11 @@ end -- @see find local function replace(rtext) if buffer:get_sel_text() == '' then return end - if find.in_files then find.in_files = false end + if M.in_files then M.in_files = false end local buffer = buffer buffer:target_from_selection() rtext = rtext:gsub('%%%%', '\\037') -- escape '%%' - local captures = find.captures + local captures = M.captures if captures then for i = 1, #captures do rtext = rtext:gsub('%%'..i, (captures[i]:gsub('%%', '%%%%'))) @@ -326,7 +331,7 @@ events_connect(events.REPLACE, replace) -- @see find local function replace_all(ftext, rtext) if ftext == '' then return end - if find.in_files then find.in_files = false end + if M.in_files then M.in_files = false end local buffer = buffer buffer:begin_undo_action() local count = 0 @@ -389,7 +394,7 @@ events_connect(events.DOUBLE_CLICK, goto_file) -- @param next Optional flag indicating whether or not to go to the next file. -- The default value is `false`. -- @name goto_file_in_list -function find.goto_file_in_list(next) +function M.goto_file_in_list(next) local orig_view = _VIEWS[view] for _, buffer in ipairs(_BUFFERS) do if buffer._type == _L['[Files Found Buffer]'] then diff --git a/modules/textadept/keys.lua b/modules/textadept/keys.lua index 8fa15a19..e2d41770 100644 --- a/modules/textadept/keys.lua +++ b/modules/textadept/keys.lua @@ -298,7 +298,8 @@ events.connect(events.BUFFER_NEW, constantize_menu_buffer_functions) if not RESETTING then constantize_menu_buffer_functions() end local keys = keys -local io, gui, gui_find, buffer, view = io, gui, gui.find, buffer, view +local io, gui, gui_find, gui_ce = io, gui, gui.find, gui.command_entry +local buffer, view = buffer, view local m_textadept, m_editing = _M.textadept, _M.textadept.editing local m_bookmarks, m_snippets = m_textadept.bookmarks, m_textadept.snippets local OSX, c = OSX, _SCINTILLA.constants @@ -466,13 +467,13 @@ keys[not OSX and 'cj' or 'mj'] = m_editing.goto_line -- Tools. keys[not OSX and (not CURSES and 'ce' or 'mc') - or 'me'] = gui.command_entry.focus + or 'me'] = {gui_ce.enter_mode, 'lua_command'} keys[not OSX and (not CURSES and 'cE' or 'mC') or 'mE'] = utils.select_command keys[not OSX and 'cr' or 'mr'] = m_textadept.run.run keys[not OSX and (not CURSES and 'cR' or 'cmr') or 'mR'] = m_textadept.run.compile keys[not OSX and (not CURSES and 'c|' or 'c\\') - or 'm|'] = m_textadept.filter_through.filter_through + or 'm|'] = {gui_ce.enter_mode, 'filter_through'} -- Adeptsense. keys[not OSX and (not CURSES and 'c ' or 'c@') or 'aesc'] = m_textadept.adeptsense.complete @@ -594,4 +595,25 @@ elseif CURSES then keys.ck = utils.cut_to_eol end +-- Modes. +keys.lua_command = { + ['\t'] = gui_ce.complete_lua, + ['\n'] = {gui_ce.finish_mode, gui_ce.execute_lua} +} +keys.filter_through = { + ['\n'] = {gui_ce.finish_mode, m_textadept.filter_through.filter_through}, +} +keys.find_incremental = { + ['\n'] = gui_find.find_incremental_next, + ['cr'] = gui_find.find_incremental_prev, + ['\b'] = function() + gui_find.find_incremental(gui_ce.entry_text:sub(1, -2)) + return false -- propagate + end +} +setmetatable(keys.find_incremental, {__index = function(t, k) + if #k > 1 and k:find('^[cams]*.+$') then return end + gui_find.find_incremental(gui_ce.entry_text..k) + end}) + return M diff --git a/modules/textadept/menu.lua b/modules/textadept/menu.lua index f4784b5d..583b3f46 100644 --- a/modules/textadept/menu.lua +++ b/modules/textadept/menu.lua @@ -119,12 +119,12 @@ M.menubar = { {_L['_Jump to'], m_editing.goto_line}, }, { title = _L['_Tools'], - {_L['Command _Entry'], gui.command_entry.focus}, + {_L['Command _Entry'], {gui.command_entry.enter_mode, 'lua_command'}}, {_L['Select Co_mmand'], utils.select_command}, SEPARATOR, {_L['_Run'], m_textadept.run.run}, {_L['_Compile'], m_textadept.run.compile}, - {_L['_Filter Through'], _M.textadept.filter_through.filter_through}, + {_L['_Filter Through'], {gui.command_entry.enter_mode, 'filter_through'}}, SEPARATOR, { title = _L['_Adeptsense'], {_L['_Complete Symbol'], m_textadept.adeptsense.complete}, |