aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/keys.lua5
-rw-r--r--modules/ansi_c/init.lua64
-rw-r--r--modules/lua/init.lua41
-rw-r--r--modules/textadept/macros.lua5
-rw-r--r--modules/textadept/snippets.lua104
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