diff options
author | 2020-03-14 12:27:34 -0400 | |
---|---|---|
committer | 2020-03-14 12:27:34 -0400 | |
commit | 51a9603065419f64e1fd191bdf4d8cd95c003064 (patch) | |
tree | 4697bcce2094e29eead5fbe3280aa0365f062a0a | |
parent | e51c41469c3717804ae45848194bd8da641c68c5 (diff) | |
download | textadept-51a9603065419f64e1fd191bdf4d8cd95c003064.tar.gz textadept-51a9603065419f64e1fd191bdf4d8cd95c003064.zip |
More code cleanup, refactoring, and reformatting.
-rw-r--r-- | core/keys.lua | 5 | ||||
-rw-r--r-- | modules/ansi_c/init.lua | 64 | ||||
-rw-r--r-- | modules/lua/init.lua | 41 | ||||
-rw-r--r-- | modules/textadept/macros.lua | 5 | ||||
-rw-r--r-- | modules/textadept/snippets.lua | 104 |
5 files changed, 102 insertions, 117 deletions
diff --git a/core/keys.lua b/core/keys.lua index f5002ae5..2d5a1033 100644 --- a/core/keys.lua +++ b/core/keys.lua @@ -209,9 +209,8 @@ local function keypress(code, shift, control, alt, meta, caps_lock) if shift and code >= 32 and code < 256 then shift = false end -- For composed keys on OSX, ignore alt. if OSX and alt and code < 256 then alt = false end - local key_seq = string.format( - '%s%s%s%s%s', control and CTRL or '', alt and ALT or '', - meta and OSX and META or '', shift and SHIFT or '', key) + local key_seq = (control and CTRL or '') .. (alt and ALT or '') .. + (meta and OSX and META or '') .. (shift and SHIFT or '') .. key --print(key_seq) ui.statusbar_text = '' diff --git a/modules/ansi_c/init.lua b/modules/ansi_c/init.lua index d4f9bf7d..72cd88b2 100644 --- a/modules/ansi_c/init.lua +++ b/modules/ansi_c/init.lua @@ -19,8 +19,8 @@ module('_M.ansi_c')]] -- @class table -- @name tags M.tags = { - _HOME..'/modules/ansi_c/tags', _HOME..'/modules/ansi_c/lua_tags', - _USERHOME..'/modules/ansi_c/tags' + _HOME .. '/modules/ansi_c/tags', _HOME .. '/modules/ansi_c/lua_tags', + _USERHOME .. '/modules/ansi_c/tags' } M.autocomplete_snippets = true @@ -40,8 +40,7 @@ textadept.editing.autocompleters.ansi_c = function() if op ~= '' and op ~= '.' and op ~= '->' then return nil end -- Attempt to identify the symbol type. if symbol ~= '' then - local buffer = buffer - local decl = '([%w_]+)[%s%*&]+'..symbol:gsub('%p', '%%%0')..'[^%w_]' + local decl = '([%w_]+)[%s%*&]+' .. symbol:gsub('%p', '%%%0') .. '[^%w_]' for i = buffer:line_from_position(buffer.current_pos) - 1, 0, -1 do local class = buffer:get_line(i):match(decl) if class then symbol = class break end @@ -50,33 +49,33 @@ textadept.editing.autocompleters.ansi_c = function() -- Search through ctags for completions for that symbol. local tags_files = {} for i = 1, #M.tags do tags_files[#tags_files + 1] = M.tags[i] end - tags_files[#tags_files + 1] = (io.get_project_root(buffer.filename) or - lfs.currentdir())..'/tags' - local name_patt = '^'..part + tags_files[#tags_files + 1] = + (io.get_project_root(buffer.filename) or lfs.currentdir()) .. '/tags' + local name_patt = '^' .. part local sep = string.char(buffer.auto_c_type_separator) ::rescan:: local list = {} for i = 1, #tags_files do - if lfs.attributes(tags_files[i]) then - for tag_line in io.lines(tags_files[i]) do - local name = tag_line:match('^%S+') - if (name:find(name_patt) and not name:find('^!') and not list[name]) or - name == symbol and op == '' then - local fields = tag_line:match(';"\t(.*)$') - if (fields:match('class:(%S+)') or fields:match('enum:(%S+)') or - fields:match('struct:(%S+)') or '') == symbol then - list[#list + 1] = string.format('%s%s%d', name, sep, - xpms[fields:sub(1, 1)]) - list[name] = true - elseif name == symbol and fields:match('typeref:') then - -- For typeref, change the lookup symbol to the referenced name and - -- rescan tags files. - symbol = fields:match('[^:]+$') - goto rescan - end + if not lfs.attributes(tags_files[i]) then goto continue end + for tag_line in io.lines(tags_files[i]) do + local name = tag_line:match('^%S+') + if (name:find(name_patt) and not name:find('^!') and not list[name]) or + name == symbol and op == '' then + local fields = tag_line:match(';"\t(.*)$') + local type = fields:match('class:(%S+)') or + fields:match('enum:(%S+)') or fields:match('struct:(%S+)') or '' + if type == symbol then + list[#list + 1] = name .. sep .. xpms[fields:sub(1, 1)] + list[name] = true + elseif name == symbol and fields:match('typeref:') then + -- For typeref, change the lookup symbol to the referenced name and + -- rescan tags files. + symbol = fields:match('[^:]+$') + goto rescan end end end + ::continue:: end if symbol == '' and M.autocomplete_snippets then local _, snippets = textadept.editing.autocompleters.snippet() @@ -86,26 +85,17 @@ textadept.editing.autocompleters.ansi_c = function() end local api_files = textadept.editing.api_files -api_files.ansi_c[#api_files.ansi_c + 1] = _HOME..'/modules/ansi_c/api' -api_files.ansi_c[#api_files.ansi_c + 1] = _HOME..'/modules/ansi_c/lua_api' -api_files.ansi_c[#api_files.ansi_c + 1] = _USERHOME..'/modules/ansi_c/api' +api_files.ansi_c[#api_files.ansi_c + 1] = _HOME .. '/modules/ansi_c/api' +api_files.ansi_c[#api_files.ansi_c + 1] = _HOME .. '/modules/ansi_c/lua_api' +api_files.ansi_c[#api_files.ansi_c + 1] = _USERHOME .. '/modules/ansi_c/api' -- Commands. --- -- Table of C-specific key bindings. --- --- + `Shift+Enter` (`⇧↩` | `S-Enter`) --- Add ';' to the end of the current line and insert a newline. -- @class table -- @name _G.keys.ansi_c -keys.ansi_c = { - ['s\n'] = function() - buffer:line_end() - buffer:add_text(';') - buffer:new_line() - end, -} +keys.ansi_c = {} -- Snippets. diff --git a/modules/lua/init.lua b/modules/lua/init.lua index 7609dc9b..113e065c 100644 --- a/modules/lua/init.lua +++ b/modules/lua/init.lua @@ -18,8 +18,8 @@ module('_M.lua')]] -- Textadept tags or API file for use in autocompletion and documentation. -- @param filename Textadept tags or api file to return. local function ta_api(filename) - local home = '^'.._HOME:gsub('%p', '%%%0'):gsub('%%[/\\]', '[/\\]') - local userhome = '^'.._USERHOME:gsub('%p', '%%%0'):gsub('%%[/\\]', '[/\\]') + local home = '^' .. _HOME:gsub('%p', '%%%0'):gsub('%%[/\\]', '[/\\]') + local userhome = '^' .. _USERHOME:gsub('%p', '%%%0'):gsub('%%[/\\]', '[/\\]') return function() local buffer_filename = buffer.filename or '' if buffer_filename:find(home) or buffer_filename:find(userhome) or @@ -39,8 +39,8 @@ end -- @class table -- @name tags M.tags = { - _HOME..'/modules/lua/tags', _USERHOME..'/modules/lua/tags', - ta_api(_HOME..'/modules/lua/ta_tags') + _HOME .. '/modules/lua/tags', _USERHOME .. '/modules/lua/tags', + ta_api(_HOME .. '/modules/lua/ta_tags') } --- @@ -69,8 +69,7 @@ textadept.editing.autocompleters.lua = function() end symbol, part = symbol:gsub('^_G%.?', ''), part ~= '_G' and part or '' -- Attempt to identify string type and file type symbols. - local buffer = buffer - local assignment = '%f[%w_]'..symbol:gsub('(%p)', '%%%1')..'%s*=%s*(.*)$' + local assignment = '%f[%w_]' .. symbol:gsub('(%p)', '%%%1') .. '%s*=%s*(.*)$' for i = buffer:line_from_position(buffer.current_pos) - 1, 0, -1 do local expr = buffer:get_line(i):match(assignment) if expr then @@ -80,32 +79,32 @@ textadept.editing.autocompleters.lua = function() end end -- Search through ctags for completions for that symbol. - local name_patt = '^'..part + local name_patt = '^' .. part local sep = string.char(buffer.auto_c_type_separator) for _, file in ipairs(M.tags) do if type(file) == 'function' then file = file() end - if file and lfs.attributes(file) then - for tag_line in io.lines(file) do - local name = tag_line:match('^%S+') - if name:find(name_patt) and not list[name] then - local fields = tag_line:match(';"\t(.*)$') - local k, class = fields:sub(1, 1), fields:match('class:(%S+)') or '' - if class == symbol and (op ~= ':' or k == 'f') then - list[#list + 1] = string.format('%s%s%d', name, sep, xpms[k]) - list[name] = true - end + if not file or not lfs.attributes(file) then goto continue end + for tag_line in io.lines(file) do + local name = tag_line:match('^%S+') + if name:find(name_patt) and not list[name] then + local fields = tag_line:match(';"\t(.*)$') + local k, class = fields:sub(1, 1), fields:match('class:(%S+)') or '' + if class == symbol and (op ~= ':' or k == 'f') then + list[#list + 1] = name .. sep .. xpms[k] + list[name] = true end end end + ::continue:: end - if #list == 1 and list[1]:find(name_patt..'%?') then return nil end + if #list == 1 and list[1]:find(name_patt .. '%?') then return nil end return #part, list end local api_files = textadept.editing.api_files -api_files.lua[#api_files.lua + 1] = _HOME..'/modules/lua/api' -api_files.lua[#api_files.lua + 1] = _USERHOME..'/modules/lua/api' -api_files.lua[#api_files.lua + 1] = ta_api(_HOME..'/modules/lua/ta_api') +api_files.lua[#api_files.lua + 1] = _HOME .. '/modules/lua/api' +api_files.lua[#api_files.lua + 1] = _USERHOME .. '/modules/lua/api' +api_files.lua[#api_files.lua + 1] = ta_api(_HOME .. '/modules/lua/ta_api') -- Commands. diff --git a/modules/textadept/macros.lua b/modules/textadept/macros.lua index b8fe7f63..d02f8786 100644 --- a/modules/textadept/macros.lua +++ b/modules/textadept/macros.lua @@ -35,9 +35,8 @@ local event_recorders = { local key = code < 256 and string.char(code) or keys.KEYSYMS[code] if key then if shift and code >= 32 and code < 256 then shift = false end - local key_seq = string.format( - '%s%s%s%s%s', control and 'c' or '', alt and 'a' or '', - meta and OSX and 'm' or '', shift and 's' or '', key) + local key_seq = (control and 'c' or '') .. (alt and 'a' or '') .. + (meta and OSX and 'm' or '') .. (shift and 's' or '') .. key for i = 1, #ignore do if keys[key_seq] == ignore[i] then return end end end macro[#macro + 1] = {events.KEYPRESS, code, shift, control, alt, meta} diff --git a/modules/textadept/snippets.lua b/modules/textadept/snippets.lua index e59bc223..9e002348 100644 --- a/modules/textadept/snippets.lua +++ b/modules/textadept/snippets.lua @@ -146,20 +146,21 @@ local snippets = {} -- @return trigger word, snippet text or table of matching snippets local function find_snippet(grep, no_trigger) local matching_snippets = {} - local pos = buffer.current_pos - local trigger = buffer:text_range(buffer:word_start_position(pos), pos) - if no_trigger then grep, trigger = true, '' end + local trigger = not no_trigger and buffer:text_range( + buffer:word_start_position(buffer.current_pos), buffer.current_pos) or '' + if no_trigger then grep = true end local lexer = buffer:get_lexer(true) - local name_patt = '^'..trigger - -- Search in the snippet tables, ignoring this module's non-string members. - local s = snippets - for _, v in ipairs{type(s[lexer]) == 'table' and s[lexer] or {}, s} do - if not grep and v[trigger] then - return trigger, v[trigger] - elseif grep then - for name, text in pairs(v) do - if name:find(name_patt) and - (type(text) == 'string' or type(text) == 'function') then + local name_patt = '^' .. trigger + -- Search in the snippet tables. + local snippet_tables = {snippets} + if type(snippets[lexer]) == 'table' then + table.insert(snippet_tables, 1, snippets[lexer]) + end + for _, snippets in ipairs(snippet_tables) do + if not grep and snippets[trigger] then return trigger, snippets[trigger] end + if grep then + for name, text in pairs(snippets) do + if name:find(name_patt) and type(text) ~= 'table' then matching_snippets[name] = tostring(text) end end @@ -171,11 +172,12 @@ local function find_snippet(grep, no_trigger) -- Snippet files are either of the form "lexer.trigger.ext" or -- "trigger.ext". Prefer "lexer."-prefixed snippets. local p1, p2, p3 = basename:match('^([^.]+)%.?([^.]*)%.?([^.]*)$') - if not grep and (p1 == lexer and p2 == trigger or - p1 == trigger and p3 == '') or - grep and (p1 == lexer and p2 and p2:find(name_patt) or - p1 and p1:find(name_patt) and p3 == '') then - local f = io.open(M.paths[i]..'/'..basename) + if not grep and + (p1 == lexer and p2 == trigger or p1 == trigger and p3 == '') or + grep and + (p1 == lexer and p2 and p2:find(name_patt) or + p1 and p1:find(name_patt) and p3 == '') then + local f = io.open(string.format('%s/%s', M.paths[i], basename)) text = f:read('a') f:close() if not grep then return trigger, text end @@ -233,7 +235,7 @@ local function new_snippet(text, trigger) local pos = buffer:indicator_end(INDIC_CURRENTPLACEHOLDER, self.start_pos) if pos == 0 then pos = self.start_pos end return buffer:indicator_all_on_for(pos) & - 1 << INDIC_CURRENTPLACEHOLDER > 0 and pos + 1 or pos + 1 << INDIC_CURRENTPLACEHOLDER > 0 and pos + 1 or pos else return snippet_mt[k] end @@ -244,7 +246,7 @@ local function new_snippet(text, trigger) local lines = {} local indent = {[true] = '\t', [false] = string.rep(' ', buffer.tab_width)} local use_tabs = buffer.use_tabs - for line in (text..'\n'):gmatch('([^\r\n]*)\r?\n') do + for line in (text .. '\n'):gmatch('([^\r\n]*)\r?\n') do lines[#lines + 1] = line:gsub('^(%s*)', function(indentation) return indentation:gsub(indent[not use_tabs], indent[use_tabs]) end) @@ -254,7 +256,7 @@ local function new_snippet(text, trigger) local line = buffer:line_from_position(buffer.current_pos) local level = buffer.line_indentation[line] // buffer.tab_width local additional_indent = indent[use_tabs]:rep(level) - for i = 2, #lines do lines[i] = additional_indent..lines[i] end + for i = 2, #lines do lines[i] = additional_indent .. lines[i] end end text = table.concat(lines, ({[0] = '\r\n', '\r', '\n'})[buffer.eol_mode]) @@ -265,10 +267,9 @@ local function new_snippet(text, trigger) local patt = P{ V('plain_text') * V('placeholder') * Cp() + V('plain_text') * -1, plain_text = C(((P(1) - '%' + '%' * S('({'))^1 + '%%')^0), - placeholder = Ct('%' * (V('index')^-1 * (V('angles') + V('brackets') + - V('braces')) * - V('transform') + - V('index') * (V('parens') + V('simple')))), + placeholder = Ct( + '%' * (V('index')^-1 * (V('angles') + V('brackets') + V('braces')) * + V('transform') + V('index') * (V('parens') + V('simple')))), index = Cg(R('09')^1 / tonumber, 'index'), parens = '(' * Cg((1 - S('()') + V('parens'))^0, 'default') * ')', simple = Cg(Cc(true), 'simple'), transform = Cg(Cc(true), 'transform'), @@ -305,7 +306,7 @@ local function new_snippet(text, trigger) snapshot.placeholders[#snapshot.placeholders + 1] = placeholder end if text_part ~= '' then - snapshot.text = snapshot.text..text_part:gsub('%%(%p)', '%1') + snapshot.text = snapshot.text .. text_part:gsub('%%(%p)', '%1') end placeholder.position = #snapshot.text if placeholder.default then @@ -325,8 +326,8 @@ local function new_snippet(text, trigger) position = start_pos + position - 1 if default then -- Process sub-placeholders starting at the index after '%n('. - default = process_placeholders(default:sub(2, -2), - position + #index + 2) + default = process_placeholders( + default:sub(2, -2), position + #index + 2) end index = tonumber(index) if index > snippet.max_index then snippet.max_index = index end @@ -336,7 +337,7 @@ local function new_snippet(text, trigger) length = #(default or ' '), position = snippet.start_pos + position, } - return default or ' ' + return default or ' ' -- fill empty placeholder for display end local ph_patt = P{ lpeg.Cs((Cp() * '%' * C(R('09')^1) * C(V('parens'))^-1 / ph + 1)^0), @@ -344,21 +345,21 @@ local function new_snippet(text, trigger) } return ph_patt:match(s) end - placeholder.default = process_placeholders(placeholder.default, - placeholder.position) + placeholder.default = process_placeholders( + placeholder.default, placeholder.position) end - snapshot.text = snapshot.text..placeholder.default + snapshot.text = snapshot.text .. placeholder.default elseif placeholder.transform and not placeholder.index then - snapshot.text = snapshot.text..snippet:execute_code(placeholder) + snapshot.text = snapshot.text .. snippet:execute_code(placeholder) else - snapshot.text = snapshot.text..' ' -- fill empty placeholders for display + snapshot.text = snapshot.text .. ' ' -- fill empty placeholder for display end placeholder.length = #snapshot.text - placeholder.position placeholder.position = snippet.start_pos + placeholder.position -- absolute text_part, placeholder, e = patt:match(text, e) end if text_part ~= '' then - snapshot.text = snapshot.text..text_part:gsub('%%(%p)', '%1') + snapshot.text = snapshot.text .. text_part:gsub('%%(%p)', '%1') end snippet.snapshots[0] = snapshot @@ -415,9 +416,9 @@ snippet_mt = { -- Find the default placeholder, which may be the first mirror. local ph = select(2, self:each_placeholder(self.index, 'default')()) or - select(2, self:each_placeholder(self.index, 'choice')()) or - select(2, self:each_placeholder(self.index, 'simple')()) or - self.index == 0 and {position = self.end_pos, length = 0} + select(2, self:each_placeholder(self.index, 'choice')()) or + select(2, self:each_placeholder(self.index, 'simple')()) or + self.index == 0 and {position = self.end_pos, length = 0} if not ph then self:next() return end -- try next placeholder -- Mark the position of the placeholder so transforms can identify it. @@ -498,8 +499,8 @@ snippet_mt = { -- @param index Optional placeholder index to constrain results to. -- @param type Optional placeholder type to constrain results to. each_placeholder = function(self, index, type) - local snapshot = self.snapshots[self.index > 0 and self.index - 1 or - #self.snapshots] + local snapshot = + self.snapshots[self.index > 0 and self.index - 1 or #self.snapshots] local i = self.start_pos return function() local s = buffer:indicator_end(M.INDIC_PLACEHOLDER, i) @@ -527,12 +528,12 @@ snippet_mt = { -- @param placeholder The placeholder that contains code to execute. execute_code = function(self, placeholder) local s, e = self.placeholder_pos, buffer.selection_end - local text = s < e and buffer:text_range(s, e) or buffer:text_range(e, s) - if not self.index then text = '' end -- %<...> or %[...] + if s > e then s, e = e, s end + local text = self.index and buffer:text_range(s, e) or '' -- %<...>, %[...] if placeholder.lua_code then - local env = {text = text, selected_text = self.original_sel_text} - local f, result = load('return '..placeholder.lua_code, nil, 'bt', - setmetatable(env, {__index = _G})) + local env = setmetatable( + {text = text, selected_text = self.original_sel_text}, {__index = _G}) + local f, result = load('return ' .. placeholder.lua_code, nil, 't', env) return f and select(2, pcall(f)) or result or '' elseif placeholder.sh_code then -- Note: cannot use spawn since $env variables are not expanded. @@ -567,7 +568,7 @@ snippet_mt = { buffer:indicator_clear_range(s, e - s) if buffer:text_range(s, e) == ' ' then buffer:set_target_range(s, e) - buffer:replace_target('') + buffer:replace_target('') -- delete filler ' ' goto redo end end @@ -591,11 +592,11 @@ function M.insert(text) local trigger if not assert_type(text, 'string/nil', 1) then trigger, text = find_snippet(trigger) - if type(text) == 'function' and not trigger:find('^_') then text = text() end + if type(text) == 'function' then text = text() end assert_type(text, 'string/nil', trigger or '?') end local snippet = type(text) == 'string' and new_snippet(text, trigger) or - snippet_stack[#snippet_stack] + snippet_stack[#snippet_stack] if snippet then snippet:next() else return false end end @@ -657,19 +658,16 @@ end) -- @see textadept.editing.autocomplete textadept.editing.autocompleters.snippet = function() local list = {} - local trigger, matching_snippets = find_snippet(true) + local trigger, snippets = find_snippet(true) local sep = string.char(buffer.auto_c_type_separator) local xpm = textadept.editing.XPM_IMAGES.NAMESPACE - for name in pairs(matching_snippets) do - list[#list + 1] = string.format('%s%s%d', name, sep, xpm) - end + for name in pairs(snippets) do list[#list + 1] = name .. sep .. xpm end return #trigger, list end --- -- Map of snippet triggers with their snippet text or functions that return such -- text, with language-specific snippets tables assigned to a lexer name key. --- This table also contains the `textadept.snippets` module. -- @class table -- @name _G.snippets _G.snippets = snippets |