diff options
-rw-r--r-- | core/args.lua | 15 | ||||
-rw-r--r-- | core/events.lua | 37 | ||||
-rw-r--r-- | core/file_io.lua | 58 | ||||
-rw-r--r-- | core/gui.lua | 363 | ||||
-rw-r--r-- | core/init.lua | 10 | ||||
-rw-r--r-- | core/keys.lua | 10 | ||||
-rw-r--r-- | modules/textadept/adeptsense.lua | 14 | ||||
-rw-r--r-- | modules/textadept/command_entry.lua | 105 | ||||
-rw-r--r-- | modules/textadept/editing.lua | 134 | ||||
-rw-r--r-- | modules/textadept/filter_through.lua | 80 | ||||
-rw-r--r-- | modules/textadept/find.lua | 68 | ||||
-rw-r--r-- | modules/textadept/keys.lua | 4 | ||||
-rw-r--r-- | modules/textadept/menu.lua | 52 | ||||
-rw-r--r-- | modules/textadept/mime_types.lua | 2 | ||||
-rw-r--r-- | modules/textadept/session.lua | 4 | ||||
-rw-r--r-- | modules/textadept/snippets.lua | 61 |
16 files changed, 485 insertions, 532 deletions
diff --git a/core/args.lua b/core/args.lua index b57c69ec..d9f959e1 100644 --- a/core/args.lua +++ b/core/args.lua @@ -59,17 +59,10 @@ end -- Shows all registered command line switches in a help dialog. local function show_help() - local line = "%s [%d args] -- %s" - local help = {} - for key, switch in pairs(switches) do - help[#help + 1] = line:format(key, unpack(switch, 2)) - end - table.sort(help) - gui.dialog('textbox', - '--title', 'Command line parameters', - '--text', table.concat(help, '\n'), - '--button1', 'gtk-ok') - events.emit('arg_none') + _G.print('Usage: textadept [args] [filenames]') + local line = " %s [%d args]: %s" + for k, v in pairs(switches) do _G.print(line:format(k, unpack(v, 2))) end + os.exit() end register('-h', '--help', 0, show_help, 'Displays this') diff --git a/core/events.lua b/core/events.lua index 91e82a83..19b556b1 100644 --- a/core/events.lua +++ b/core/events.lua @@ -122,6 +122,8 @@ module('events', package.seeall) -- events.connect('my_event', my_event_handler) -- events.emit('my_event', 'my message') +local handlers = {} + --- -- Adds a handler function to an event. -- @param event The string event name. It is arbitrary and need not be defined @@ -131,15 +133,10 @@ module('events', package.seeall) -- @return Index of handler. -- @see disconnect function connect(event, f, index) - local plural = event..'s' - if not _M[plural] then _M[plural] = {} end - local handlers = _M[plural] - if index then - table.insert(handlers, index, f) - else - handlers[#handlers + 1] = f - end - return index or #handlers + if not handlers[event] then handlers[event] = {} end + local h = handlers[event] + if index then table.insert(h, index, f) else h[#h + 1] = f end + return index or #h end --- @@ -148,10 +145,8 @@ end -- @param index Index of the handler (returned by events.connect). -- @see connect function disconnect(event, index) - local plural = event..'s' - if not events[plural] then return end - local handlers = events[plural] - table.remove(handlers, index) + if not handlers[event] then return end + table.remove(handlers[event], index) end local error_emitted = false @@ -165,10 +160,9 @@ local error_emitted = false -- @param ... Arguments passed to the handler. -- @return true or false if any handler explicitly returned such; nil otherwise. function emit(event, ...) - local plural = event..'s' - local handlers = _M[plural] - if not handlers then return end - for _, f in ipairs(handlers) do + local h = handlers[event] + if not h then return end + for _, f in ipairs(h) do local ok, result = pcall(f, unpack{...}) if not ok then if not error_emitted then @@ -204,9 +198,8 @@ local scnnotifications = { -- @return true or false if any handler explicitly returned such; nil otherwise. function notification(n) local f = scnnotifications[n.code] - if f then - local args = { unpack(f, 2) } - for k, v in ipairs(args) do args[k] = n[v] end - return emit(f[1], unpack(args)) - end + if not f then return end + local args = { unpack(f, 2) } + for i, v in ipairs(args) do args[i] = n[v] end + return emit(f[1], unpack(args)) end diff --git a/core/file_io.lua b/core/file_io.lua index 7b0b61e9..c583e365 100644 --- a/core/file_io.lua +++ b/core/file_io.lua @@ -92,10 +92,7 @@ end -- @class table -- @name try_encodings try_encodings = { - 'UTF-8', - 'ASCII', - 'ISO-8859-1', - 'MacRoman' + 'UTF-8', 'ASCII', 'ISO-8859-1', 'MacRoman' } -- Opens a file or goes to its already open buffer. @@ -118,7 +115,7 @@ local function open_helper(utf8_filename) if not f then error(err) end text = f:read('*all') f:close() - if not text then return end -- filename exists, but can't read it + if not text then return end -- filename exists, but cannot read it local buffer = new_buffer() -- Tries to detect character encoding and convert text from it to UTF-8. local encoding, encoding_bom = detect_encoding(text) @@ -171,9 +168,8 @@ end --- -- Opens a list of files. --- @param utf8_filenames A '\n' separated list of filenames to open. If none --- specified, the user is prompted to open files from a dialog. These paths --- must be encoded in UTF-8. +-- @param utf8_filenames A '\n' separated list of UTF-8-encoded filenames to +-- open. If nil, the user is prompted with a fileselect dialog. -- @usage io.open_file(utf8_encoded_filename) function open_file(utf8_filenames) utf8_filenames = utf8_filenames or @@ -189,8 +185,7 @@ end local function reload(buffer) gui.check_focused_buffer(buffer) if not buffer.filename then return end - local pos = buffer.current_pos - local first_visible_line = buffer.first_visible_line + local pos, first_visible_line = buffer.current_pos, buffer.first_visible_line local filename = buffer.filename:iconv(_CHARSET, 'UTF-8') local f, err = io.open(filename, 'rb') if not f then error(err) end @@ -211,8 +206,7 @@ end local function set_encoding(buffer, encoding) gui.check_focused_buffer(buffer) if not buffer.encoding then error(L('Cannot change binary file encoding')) end - local pos = buffer.current_pos - local first_visible_line = buffer.first_visible_line + local pos, first_visible_line = buffer.current_pos, buffer.first_visible_line local text = buffer:get_text(buffer.length) text = text:iconv(buffer.encoding, 'UTF-8') text = text:iconv(encoding, buffer.encoding) @@ -268,8 +262,7 @@ end -- Saves all dirty buffers to their respective files. -- @usage io.save_all() function save_all() - local current_buffer = buffer - local current_index + local current_buffer, current_index = buffer, 1 for i, buffer in ipairs(_BUFFERS) do view:goto_buffer(i) if buffer == current_buffer then current_index = i end @@ -315,6 +308,7 @@ end -- of Textadept. local function update_modified_file() if not buffer.filename then return end + local buffer = buffer local utf8_filename = buffer.filename local filename = utf8_filename:iconv(_CHARSET, 'UTF-8') local attributes = lfs.attributes(filename) @@ -336,22 +330,22 @@ end events.connect('buffer_after_switch', update_modified_file) events.connect('view_after_switch', update_modified_file) -events.connect('buffer_new', - function() -- set additional buffer functions - local buffer = buffer - buffer.reload = reload - buffer.set_encoding = set_encoding - buffer.save = save - buffer.save_as = save_as - buffer.close = close - buffer.encoding = 'UTF-8' - end) +-- Set additional buffer functions. +events.connect('buffer_new', function() + local buffer = buffer + buffer.reload = reload + buffer.set_encoding = set_encoding + buffer.save = save + buffer.save_as = save_as + buffer.close = close + buffer.encoding = 'UTF-8' +end) -events.connect('file_opened', - function(utf8_filename) -- close initial 'Untitled' buffer - local b = _BUFFERS[1] - if #_BUFFERS == 2 and not (b.filename or b._type or b.dirty) then - view:goto_buffer(1, true) - buffer:close() - end - end) +-- Close initial 'Untitled' buffer. +events.connect('file_opened', function(utf8_filename) + local b = _BUFFERS[1] + if #_BUFFERS == 2 and not (b.filename or b._type or b.dirty) then + view:goto_buffer(1, true) + buffer:close() + end +end) diff --git a/core/gui.lua b/core/gui.lua index ed609929..a7725e29 100644 --- a/core/gui.lua +++ b/core/gui.lua @@ -15,35 +15,38 @@ end -- LuaDoc is in core/.gui.luadoc. function gui._print(buffer_type, ...) local function safe_print(...) - local message_buffer, message_buffer_index - local message_view, message_view_index - for i, buffer in ipairs(_BUFFERS) do - if buffer._type == buffer_type then - message_buffer, message_buffer_index = buffer, i - for j, view in ipairs(_VIEWS) do - if view.doc_pointer == message_buffer.doc_pointer then - message_view, message_view_index = view, j - break + if buffer._type ~= buffer_type then + -- Try to find a message buffer to print to. Otherwise create one. + local message_buffer, message_buffer_index + local message_view, message_view_index + for i, buffer in ipairs(_BUFFERS) do + if buffer._type == buffer_type then + message_buffer, message_buffer_index = buffer, i + for j, view in ipairs(_VIEWS) do + if view.doc_pointer == message_buffer.doc_pointer then + message_view, message_view_index = view, j + break + end end + break end - break end - end - if not message_view then - local _, message_view = view:split(false) -- horizontal split - if not message_buffer then - message_buffer = new_buffer() - message_buffer._type = buffer_type - events.emit('file_opened') + if not message_view then + local _, message_view = view:split(false) -- horizontal split + if not message_buffer then + message_buffer = new_buffer() + message_buffer._type = buffer_type + events.emit('file_opened') + else + message_view:goto_buffer(message_buffer_index, true) + end else - message_view:goto_buffer(message_buffer_index, true) + gui.goto_view(message_view_index, true) end - else - gui.goto_view(message_view_index, true) end - message_buffer:append_text(table.concat({...}, '\t')) - message_buffer:append_text('\n') - message_buffer:set_save_point() + buffer:append_text(table.concat({...}, '\t')) + buffer:append_text('\n') + buffer:set_save_point() end pcall(safe_print, ...) -- prevent endless loops on error end @@ -61,7 +64,7 @@ function gui.filteredlist(title, columns, items, int_return, ...) int_return and '' or '--string-output', '--columns', columns, '--items', items, - unpack{...}) + ...) local patt = int_return and '(%-?%d+)\n(%d+)$' or '([^\n]+)\n([^\n]+)$' local response, value = out:match(patt) if response == (int_return and '1' or 'gtk-ok') then @@ -74,8 +77,7 @@ function gui.switch_buffer() local columns, items = { 'Name', 'File' }, {} for _, buffer in ipairs(_BUFFERS) do local filename = buffer.filename or buffer._type or L('Untitled') - local dirty = buffer.dirty and '*' or '' - items[#items + 1] = dirty..filename:match('[^/\\]+$') + items[#items + 1] = (buffer.dirty and '*' or '')..filename:match('[^/\\]+$') items[#items + 1] = filename end local i = gui.filteredlist(L('Switch Buffers'), columns, items, true) @@ -84,202 +86,197 @@ end local connect = _G.events.connect -connect('view_new', - function() -- sets default properties for a Scintilla window - local buffer = buffer - local c = _SCINTILLA.constants +-- Sets default properties for a Scintilla window. +connect('view_new', function() + local buffer = buffer + local c = _SCINTILLA.constants - -- Allow redefinitions of these Scintilla key commands. - local ctrl_keys = { - '[', ']', '/', '\\', 'Z', 'Y', 'X', 'C', 'V', 'A', 'L', 'T', 'D', 'U' - } - local ctrl_shift_keys = { 'L', 'T', 'U' } - for _, key in ipairs(ctrl_keys) do - buffer:clear_cmd_key(string.byte(key), c.SCMOD_CTRL) - end - for _, key in ipairs(ctrl_shift_keys) do - buffer:clear_cmd_key(string.byte(key), c.SCMOD_CTRL + c.SCMOD_SHIFT) - end + -- Allow redefinitions of these Scintilla key commands. + local ctrl_keys = { + '[', ']', '/', '\\', 'Z', 'Y', 'X', 'C', 'V', 'A', 'L', 'T', 'D', 'U' + } + local ctrl_shift_keys = { 'L', 'T', 'U' } + for _, key in ipairs(ctrl_keys) do + buffer:clear_cmd_key(string.byte(key), c.SCMOD_CTRL) + end + for _, key in ipairs(ctrl_shift_keys) do + buffer:clear_cmd_key(string.byte(key), c.SCMOD_CTRL + c.SCMOD_SHIFT) + end - if _THEME and #_THEME > 0 then - local ok, err = pcall(dofile, _THEME..'/view.lua') - if ok then return end - io.stderr:write(err) - end - end) + if _THEME and #_THEME > 0 then + local ok, err = pcall(dofile, _THEME..'/view.lua') + if not ok then io.stderr:write(err) end + end +end) connect('view_new', function() events.emit('update_ui') end) local SETDIRECTFUNCTION = _SCINTILLA.properties.direct_function[1] local SETDIRECTPOINTER = _SCINTILLA.properties.doc_pointer[2] local SETLEXERLANGUAGE = _SCINTILLA.functions.set_lexer_language[1] -connect('buffer_new', - function() -- sets default properties for a Scintilla document - local function run() - local buffer = buffer +-- Sets default properties for a Scintilla document. +connect('buffer_new', function() + local function run() + local buffer = buffer - -- Lexer. - buffer:set_lexer_language('lpeg') - buffer:private_lexer_call(SETDIRECTFUNCTION, buffer.direct_function) - buffer:private_lexer_call(SETDIRECTPOINTER, buffer.direct_pointer) - buffer:private_lexer_call(SETLEXERLANGUAGE, 'container') - buffer.style_bits = 8 + -- Lexer. + buffer:set_lexer_language('lpeg') + buffer:private_lexer_call(SETDIRECTFUNCTION, buffer.direct_function) + buffer:private_lexer_call(SETDIRECTPOINTER, buffer.direct_pointer) + buffer:private_lexer_call(SETLEXERLANGUAGE, 'container') + buffer.style_bits = 8 - -- Properties. - buffer.property['textadept.home'] = _HOME - buffer.property['lexer.lpeg.home'] = _LEXERPATH - buffer.property['lexer.lpeg.script'] = _HOME..'/lexers/lexer.lua' - if _THEME and #_THEME > 0 then - buffer.property['lexer.lpeg.color.theme'] = _THEME..'/lexer.lua' - end + -- Properties. + buffer.property['textadept.home'] = _HOME + buffer.property['lexer.lpeg.home'] = _LEXERPATH + buffer.property['lexer.lpeg.script'] = _HOME..'/lexers/lexer.lua' + if _THEME and #_THEME > 0 then + buffer.property['lexer.lpeg.color.theme'] = _THEME..'/lexer.lua' + end - -- Buffer. - buffer.code_page = _SCINTILLA.constants.SC_CP_UTF8 + -- Buffer. + buffer.code_page = _SCINTILLA.constants.SC_CP_UTF8 - if _THEME and #_THEME > 0 then - local ok, err = pcall(dofile, _THEME..'/buffer.lua') - if ok then return end - io.stderr:write(err) - end + if _THEME and #_THEME > 0 then + local ok, err = pcall(dofile, _THEME..'/buffer.lua') + if not ok then io.stderr:write(err) end end - -- Normally when an error occurs, a new buffer is created with the error - -- message, but if an error occurs here, this event would be called again - -- and again, erroring each time resulting in an infinite loop; print error - -- to stderr instead. - local ok, err = pcall(run) - if not ok then io.stderr:write(err) end - end) + end + -- Normally when an error occurs, a new buffer is created with the error + -- message, but if an error occurs here, this event would be called again and + -- again, erroring each time resulting in an infinite loop; print error to + -- stderr instead. + local ok, err = pcall(run) + if not ok then io.stderr:write(err) end +end) connect('buffer_new', function() events.emit('update_ui') end) -- Sets the title of the Textadept window to the buffer's filename. -- @param buffer The currently focused buffer. local function set_title(buffer) - local buffer = buffer local filename = buffer.filename or buffer._type or L('Untitled') - local dirty = buffer.dirty and '*' or '-' gui.title = string.format('%s %s Textadept (%s)', filename:match('[^/\\]+$'), - dirty, filename) + buffer.dirty and '*' or '-', filename) end -connect('save_point_reached', - function() -- changes Textadept title to show 'clean' buffer - buffer.dirty = false - set_title(buffer) - end) +-- Changes Textadept title to show 'clean' buffer. +connect('save_point_reached', function() + buffer.dirty = false + set_title(buffer) +end) -connect('save_point_left', - function() -- changes Textadept title to show 'dirty' buffer - buffer.dirty = true - set_title(buffer) - end) +-- Changes Textadept title to show 'dirty' buffer. +connect('save_point_left', function() + buffer.dirty = true + set_title(buffer) +end) -connect('uri_dropped', - function(utf8_uris) -- open uri(s) - for utf8_uri in utf8_uris:gmatch('[^\r\n]+') do - if utf8_uri:find('^file://') then - utf8_uri = utf8_uri:match('^file://([^\r\n]+)') - utf8_uri = utf8_uri:gsub('%%(%x%x)', - function(hex) return string.char(tonumber(hex, 16)) end) - if WIN32 then utf8_uri = utf8_uri:sub(2, -1) end -- ignore leading '/' - local uri = utf8_uri:iconv(_CHARSET, 'UTF-8') - if lfs.attributes(uri).mode ~= 'directory' then - io.open_file(utf8_uri) - end - end +-- Open uri(s). +connect('uri_dropped', function(utf8_uris) + for utf8_uri in utf8_uris:gmatch('[^\r\n]+') do + if utf8_uri:find('^file://') then + utf8_uri = utf8_uri:match('^file://([^\r\n]+)') + utf8_uri = utf8_uri:gsub('%%(%x%x)', function(hex) + return string.char(tonumber(hex, 16)) + end) + if WIN32 then utf8_uri = utf8_uri:sub(2, -1) end -- ignore leading '/' + local uri = utf8_uri:iconv(_CHARSET, 'UTF-8') + if lfs.attributes(uri).mode ~= 'directory' then io.open_file(utf8_uri) end end - end) + end +end) connect('appleevent_odoc', - function(uri) return events.emit('uri_dropped', 'file://'..uri) end) + function(uri) return events.emit('uri_dropped', 'file://'..uri) end) local string_format = string.format local EOLs = { L('CRLF'), L('CR'), L('LF') } local GETLEXERLANGUAGE = _SCINTILLA.functions.get_lexer_language[1] -connect('update_ui', - function() -- sets docstatusbar text - local buffer = buffer - local pos = buffer.current_pos - local line, max = buffer:line_from_position(pos) + 1, buffer.line_count - local col = buffer.column[pos] + 1 - local lexer = buffer:private_lexer_call(GETLEXERLANGUAGE) - local eol = EOLs[buffer.eol_mode + 1] - local tabs = string_format('%s %d', buffer.use_tabs and L('Tabs:') or - L('Spaces:'), buffer.indent) - local enc = buffer.encoding or '' - gui.docstatusbar_text = - string_format('%s %d/%d %s %d %s %s %s %s', L('Line:'), - line, max, L('Col:'), col, lexer, eol, tabs, enc) - end) +-- Sets docstatusbar text. +connect('update_ui', function() + local buffer = buffer + local pos = buffer.current_pos + local line, max = buffer:line_from_position(pos) + 1, buffer.line_count + local col = buffer.column[pos] + 1 + local lexer = buffer:private_lexer_call(GETLEXERLANGUAGE) + local eol = EOLs[buffer.eol_mode + 1] + local tabs = string_format('%s %d', buffer.use_tabs and L('Tabs:') or + L('Spaces:'), buffer.indent) + local enc = buffer.encoding or '' + gui.docstatusbar_text = + string_format('%s %d/%d %s %d %s %s %s %s', L('Line:'), line, + max, L('Col:'), col, lexer, eol, tabs, enc) +end) -connect('margin_click', - function(margin, modifiers, position) -- toggles folding - buffer:toggle_fold(buffer:line_from_position(position)) - end) +-- Toggles folding. +connect('margin_click', function(margin, modifiers, position) + buffer:toggle_fold(buffer:line_from_position(position)) +end) connect('buffer_new', function() set_title(buffer) end) -connect('buffer_before_switch', - function() -- save buffer properties - local buffer = buffer - -- Save view state. - buffer._anchor = buffer.anchor - buffer._current_pos = buffer.current_pos - buffer._first_visible_line = buffer.first_visible_line - -- Save fold state. - buffer._folds = {} - local folds = buffer._folds - local i = buffer:contracted_fold_next(0) - while i >= 0 do - folds[#folds + 1] = i - i = buffer:contracted_fold_next(i + 1) - end - end) +-- Save buffer properties. +connect('buffer_before_switch', function() + local buffer = buffer + -- Save view state. + buffer._anchor = buffer.anchor + buffer._current_pos = buffer.current_pos + buffer._first_visible_line = buffer.first_visible_line + -- Save fold state. + buffer._folds = {} + local folds = buffer._folds + local i = buffer:contracted_fold_next(0) + while i >= 0 do + folds[#folds + 1] = i + i = buffer:contracted_fold_next(i + 1) + end +end) -connect('buffer_after_switch', - function() -- restore buffer properties - local buffer = buffer - if not buffer._folds then return end - -- Restore fold state. - for _, i in ipairs(buffer._folds) do buffer:toggle_fold(i) end - -- Restore view state. - buffer:set_sel(buffer._anchor, buffer._current_pos) - buffer:line_scroll(0, - buffer:visible_from_doc_line(buffer._first_visible_line) - - buffer.first_visible_line) - end) +-- Restore buffer properties. +connect('buffer_after_switch', function() + local buffer = buffer + if not buffer._folds then return end + -- Restore fold state. + for _, i in ipairs(buffer._folds) do buffer:toggle_fold(i) end + -- Restore view state. + buffer:set_sel(buffer._anchor, buffer._current_pos) + buffer:line_scroll(0, + buffer:visible_from_doc_line(buffer._first_visible_line) - + buffer.first_visible_line) +end) -connect('buffer_after_switch', - function() -- updates titlebar and statusbar - set_title(buffer) - events.emit('update_ui') - end) +-- Updates titlebar and statusbar. +connect('buffer_after_switch', function() + set_title(buffer) + events.emit('update_ui') +end) -connect('view_after_switch', - function() -- updates titlebar and statusbar - set_title(buffer) - events.emit('update_ui') - end) +-- Updates titlebar and statusbar. +connect('view_after_switch', function() + set_title(buffer) + events.emit('update_ui') +end) connect('reset_after', function() gui.statusbar_text = 'Lua reset' end) -connect('quit', - function() -- prompts for confirmation if any buffers are dirty - local list = {} - for _, buffer in ipairs(_BUFFERS) do - if buffer.dirty then - list[#list + 1] = buffer.filename or buffer._type or L('Untitled') - end - end - if #list > 0 and - gui.dialog('msgbox', - '--title', L('Quit without saving?'), - '--text', L('The following buffers are unsaved:'), - '--informative-text', - string.format('%s', table.concat(list, '\n')), - '--button1', 'gtk-cancel', - '--button2', L('Quit _without saving'), - '--no-newline') ~= '2' then - return false +-- Prompts for confirmation if any buffers are dirty. +connect('quit', function() + local list = {} + for _, buffer in ipairs(_BUFFERS) do + if buffer.dirty then + list[#list + 1] = buffer.filename or buffer._type or L('Untitled') end - return true - end) + end + if #list > 0 and + gui.dialog('msgbox', + '--title', L('Quit without saving?'), + '--text', L('The following buffers are unsaved:'), + '--informative-text', + string.format('%s', table.concat(list, '\n')), + '--button1', 'gtk-cancel', + '--button2', L('Quit _without saving'), + '--no-newline') ~= '2' then + return false + end + return true +end) connect('error', function(...) gui._print(L('[Error Buffer]'), ...) end) diff --git a/core/init.lua b/core/init.lua index 3daaf7df..fe235f53 100644 --- a/core/init.lua +++ b/core/init.lua @@ -30,10 +30,8 @@ end -- LuaDoc is in core/._G.luadoc. function _G.user_dofile(filename) - if lfs.attributes(_USERHOME..'/'..filename) then - local ok, err = pcall(dofile, _USERHOME..'/'..filename) - if not ok then gui.print(err) end - return ok - end - return false + if not lfs.attributes(_USERHOME..'/'..filename) then return false end + local ok, err = pcall(dofile, _USERHOME..'/'..filename) + if not ok then gui.print(err) end + return ok end diff --git a/core/keys.lua b/core/keys.lua index a5e47662..29a06d6d 100644 --- a/core/keys.lua +++ b/core/keys.lua @@ -134,7 +134,6 @@ 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. @@ -198,12 +197,9 @@ local function run_key_command(lexer, scope) 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 + if type(key[1]) == 'string' and (key[2] == 'buffer' or key[2] == 'view') then + local v = _G[key[2]] + f, args = v[f], { v, unpack(key, 3) } end if type(f) ~= 'function' then error(L('Unknown command:')..tostring(f)) end diff --git a/modules/textadept/adeptsense.lua b/modules/textadept/adeptsense.lua index 132875d3..e12b9d55 100644 --- a/modules/textadept/adeptsense.lua +++ b/modules/textadept/adeptsense.lua @@ -201,13 +201,13 @@ function show_apidoc(sense) apidocs[i] = doc end buffer:call_tip_show(buffer.current_pos, apidocs[apidocs.pos or 1]) - local event_id = events.connect('call_tip_click', - function(position) -- cycle through calltips - apidocs.pos = apidocs.pos + (position == 1 and -1 or 1) - if apidocs.pos > #apidocs then apidocs.pos = 1 end - if apidocs.pos < 1 then apidocs.pos = #apidocs end - buffer:call_tip_show(buffer.current_pos, apidocs[apidocs.pos]) - end) + -- Cycle through calltips. + local event_id = events.connect('call_tip_click', function(position) + apidocs.pos = apidocs.pos + (position == 1 and -1 or 1) + if apidocs.pos > #apidocs then apidocs.pos = 1 end + if apidocs.pos < 1 then apidocs.pos = #apidocs end + buffer:call_tip_show(buffer.current_pos, apidocs[apidocs.pos]) + end) _G.timeout(1, function() if buffer:call_tip_active() then return true end events.disconnect('call_tip_click', event_id) diff --git a/modules/textadept/command_entry.lua b/modules/textadept/command_entry.lua index c2a20d92..eac4c99e 100644 --- a/modules/textadept/command_entry.lua +++ b/modules/textadept/command_entry.lua @@ -27,66 +27,63 @@ local env = setmetatable({}, { end, }) -events.connect('command_entry_command', - function(command) -- execute a Lua command - local f, err = loadstring(command) - if err then error(err) end - gui.command_entry.focus() -- toggle focus to hide - setfenv(f, env) - f() - events.emit('update_ui') - end) +-- Execute a Lua command. +events.connect('command_entry_command', function(command) + local f, err = loadstring(command) + if err then error(err) end + gui.command_entry.focus() -- toggle focus to hide + setfenv(f, env) + f() + events.emit('update_ui') +end) -events.connect('command_entry_keypress', - function(code) - local ce = gui.command_entry - local KEYSYMS = keys.KEYSYMS - if KEYSYMS[code] == 'esc' then - ce.focus() -- toggle focus to hide - return true - elseif KEYSYMS[code] == '\t' then - local substring = ce.entry_text:match('[%w_.:]+$') or '' - local path, o, prefix = substring:match('^([%w_.:]-)([.:]?)([%w_]*)$') - local f, err = loadstring('return ('..path..')') - if type(f) == "function" then setfenv(f, env) end - 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 +events.connect('command_entry_keypress', function(code) + local ce = gui.command_entry + local KEYSYMS = keys.KEYSYMS + if KEYSYMS[code] == 'esc' then + ce.focus() -- toggle focus to hide + return true + elseif KEYSYMS[code] == '\t' then + local substring = ce.entry_text:match('[%w_.:]+$') or '' + local path, o, prefix = substring:match('^([%w_.:]-)([.:]?)([%w_]*)$') + local f, err = loadstring('return ('..path..')') + if type(f) == "function" then setfenv(f, env) end + 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 - 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 + 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' 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 - table.sort(cmpls) - ce.show_completions(cmpls) - return true end - end) + table.sort(cmpls) + ce.show_completions(cmpls) + return true + end +end) diff --git a/modules/textadept/editing.lua b/modules/textadept/editing.lua index df3b1951..c26ed082 100644 --- a/modules/textadept/editing.lua +++ b/modules/textadept/editing.lua @@ -58,8 +58,7 @@ comment_string = {} -- @class table -- @name char_matches local char_matches = { - [40] = ')', [91] = ']', [123] = '}', - [39] = "'", [34] = '"' + [40] = ')', [91] = ']', [123] = '}', [39] = "'", [34] = '"' } -- Brace characters. @@ -77,67 +76,67 @@ local braces = { -- () [] {} <> -- @name current_call_tip local current_call_tip = {} -events.connect('char_added', - function(c) -- matches characters specified in char_matches - if AUTOPAIR and char_matches[c] and buffer.selections == 1 then - buffer:insert_text(-1, char_matches[c]) - end - end) +-- Matches characters specified in char_matches. +events.connect('char_added', function(c) + if AUTOPAIR and char_matches[c] and buffer.selections == 1 then + buffer:insert_text(-1, char_matches[c]) + end +end) -events.connect('keypress', - function(code, shift, control, alt) -- removes matched chars on backspace - 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] - if char_matches[c] and - buffer.char_at[current_pos] == string.byte(char_matches[c]) then - buffer:clear() - end - end) +-- Removes matched chars on backspace. +events.connect('keypress', function(code, shift, control, alt) + 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] + if char_matches[c] and + buffer.char_at[current_pos] == string.byte(char_matches[c]) then + buffer:clear() + end +end) -events.connect('update_ui', - function() -- highlights matching braces - if not HIGHLIGHT_BRACES then return end - local buffer = buffer - local current_pos = buffer.current_pos - if braces[buffer.char_at[current_pos]] and - buffer:get_style_name(buffer.style_at[current_pos]) == 'operator' then - local pos = buffer:brace_match(current_pos) - if pos ~= -1 then - buffer:brace_highlight(current_pos, pos) - else - buffer:brace_bad_light(current_pos) - end +-- Highlights matching braces. +events.connect('update_ui', function() + if not HIGHLIGHT_BRACES then return end + local buffer = buffer + local current_pos = buffer.current_pos + if braces[buffer.char_at[current_pos]] and + buffer:get_style_name(buffer.style_at[current_pos]) == 'operator' then + local pos = buffer:brace_match(current_pos) + if pos ~= -1 then + buffer:brace_highlight(current_pos, pos) else - buffer:brace_bad_light(-1) + buffer:brace_bad_light(current_pos) end - end) + else + buffer:brace_bad_light(-1) + end +end) -events.connect('char_added', - function(char) -- auto-indent on return - if not AUTOINDENT or char ~= 10 then return end - local buffer = buffer - local anchor, caret = buffer.anchor, buffer.current_pos - local line = buffer:line_from_position(caret) - local pline = line - 1 - while pline >= 0 and #buffer:get_line(pline) == 1 do pline = pline - 1 end - if pline >= 0 then - local indentation = buffer.line_indentation[pline] - local s = buffer.line_indent_position[line] - buffer.line_indentation[line] = indentation - local e = buffer.line_indent_position[line] - local diff = e - s - if e > s then -- move selection on - if anchor >= s then anchor = anchor + diff end - if caret >= s then caret = caret + diff end - elseif e < s then -- move selection back - if anchor >= e then anchor = anchor >= s and anchor + diff or e end - if caret >= e then caret = caret >= s and caret + diff or e end - end - buffer:set_sel(anchor, caret) +-- Auto-indent on return. +events.connect('char_added', function(char) + if not AUTOINDENT or char ~= 10 then return end + local buffer = buffer + local anchor, caret = buffer.anchor, buffer.current_pos + local line = buffer:line_from_position(caret) + local pline = line - 1 + while pline >= 0 and #buffer:get_line(pline) == 1 do pline = pline - 1 end + if pline >= 0 then + local indentation = buffer.line_indentation[pline] + local s = buffer.line_indent_position[line] + buffer.line_indentation[line] = indentation + local e = buffer.line_indent_position[line] + local diff = e - s + if e > s then -- move selection on + if anchor >= s then anchor = anchor + diff end + if caret >= s then caret = caret + diff end + elseif e < s then -- move selection back + if anchor >= e then anchor = anchor >= s and anchor + diff or e end + if caret >= e then caret = caret >= s and caret + diff or e end end - end) + buffer:set_sel(anchor, caret) + end +end) --- -- Goes to a matching brace position, selecting the text inside if specified. @@ -226,12 +225,11 @@ end -- @param line Optional line number to go to. function goto_line(line) if not line then - line = gui.dialog('standard-inputbox', - '--title', L('Go To'), - '--text', L('Line Number:'), - '--no-newline') - line = tonumber(line:match('%-?%d+$')) - if not line or line < 0 then return end + line = tonumber(gui.dialog('standard-inputbox', + '--title', L('Go To'), + '--text', L('Line Number:'), + '--no-newline'):match('%-?%d+$')) + if not line then return end end buffer:ensure_visible_enforce_policy(line - 1) buffer:goto_line(line - 1) @@ -264,7 +262,7 @@ function prepare_for_save() -- Ensure ending newline. local e = buffer:position_from_line(lines) if lines == 1 or - lines > 1 and e > buffer:position_from_line(lines - 1) then + lines > 1 and e > buffer:position_from_line(lines - 1) then buffer:insert_text(e, '\n') end -- Convert non-consistent EOLs @@ -384,15 +382,14 @@ function select_indented_block() if indent < 0 then return end if buffer:get_sel_text() ~= '' then if buffer.line_indentation[s - 1] == indent and - buffer.line_indentation[e + 1] == indent then + buffer.line_indentation[e + 1] == indent then s, e = s - 1, e + 1 indent = indent + buffer.indent -- do not run while loops end end while buffer.line_indentation[s - 1] > indent do s = s - 1 end while buffer.line_indentation[e + 1] > indent do e = e + 1 end - s = buffer:position_from_line(s) - e = buffer.line_end_position[e] + s, e = buffer:position_from_line(s), buffer.line_end_position[e] buffer:set_sel(s, e) end @@ -426,8 +423,7 @@ function convert_indentation() new_indentation = (' '):rep(indent) end if current_indentation ~= new_indentation then - buffer.target_start = s - buffer.target_end = indent_pos + buffer.target_start, buffer.target_end = s, indent_pos buffer:replace_target(new_indentation) end end diff --git a/modules/textadept/filter_through.lua b/modules/textadept/filter_through.lua index a3094c0c..6861166f 100644 --- a/modules/textadept/filter_through.lua +++ b/modules/textadept/filter_through.lua @@ -26,47 +26,45 @@ function filter_through() gui.command_entry.focus() end -events.connect('command_entry_keypress', - function(code) - if filter_through_active and code == 0xff1b then -- escape - filter_through_active = false - end - end, 1) -- place before command_entry.lua's handler (if necessary) +events.connect('command_entry_keypress', function(code) + if filter_through_active and code == 0xff1b then -- escape + filter_through_active = false + end +end, 1) -- place before command_entry.lua's handler (if necessary) -events.connect('command_entry_command', - function(text) -- filter through - 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 = table.concat({ 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) +-- Filter through. +events.connect('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 - 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 = table.concat({ 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) + end + p:close() + os.remove(tmpfile) + filter_through_active = false + return true + end +end, 1) -- place before command_entry.lua's handler (if necessary) diff --git a/modules/textadept/find.lua b/modules/textadept/find.lua index 68fcfaf7..e4b1d967 100644 --- a/modules/textadept/find.lua +++ b/modules/textadept/find.lua @@ -166,31 +166,30 @@ function find.find_incremental() gui.command_entry.focus() end -events.connect('command_entry_keypress', - function(code) - local K = _G.keys.KEYSYMS - if find.incremental then - if K[code] == 'esc' then - find.incremental = nil - elseif code < 256 or K[code] == '\b' then - local text = gui.command_entry.entry_text - if K[code] == '\b' then - find_incremental(text:sub(1, -2)) - else - find_incremental(text..string.char(code)) - end +events.connect('command_entry_keypress', function(code) + local K = _G.keys.KEYSYMS + if find.incremental then + if K[code] == 'esc' then + find.incremental = nil + elseif code < 256 or K[code] == '\b' then + local text = gui.command_entry.entry_text + if K[code] == '\b' then + find_incremental(text:sub(1, -2)) + else + find_incremental(text..string.char(code)) end end - end, 1) -- place before command_entry.lua's handler (if necessary) + end +end, 1) -- place before command_entry.lua's handler (if necessary) -events.connect('command_entry_command', - function(text) -- 'find next' for incremental search - 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) +-- 'Find next' for incremental search. +events.connect('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) -- Replaces found text. -- 'find_' is called first, to select any found text. The selected text is then @@ -212,19 +211,18 @@ local function replace(rtext) rtext = rtext:gsub('%%'..i, v) end end - local ok, rtext = pcall(rtext.gsub, rtext, '%%(%b())', - function(code) - local ok, val = pcall(loadstring('return '..code)) - if not ok then - gui.dialog('ok-msgbox', - '--title', L('Error'), - '--text', L('An error occured:'), - '--informative-text', val:gsub('"', '\\"'), - '--no-cancel') - error() - end - return val - end) + local ok, rtext = pcall(rtext.gsub, rtext, '%%(%b())', function(code) + local ok, val = pcall(loadstring('return '..code)) + if not ok then + gui.dialog('ok-msgbox', + '--title', L('Error'), + '--text', L('An error occured:'), + '--informative-text', val:gsub('"', '\\"'), + '--no-cancel') + error() + end + return val + end) if ok then rtext = rtext:gsub('\\037', '%%') -- unescape '%' buffer:replace_target(rtext:gsub('\\[abfnrtv\\]', escapes)) diff --git a/modules/textadept/keys.lua b/modules/textadept/keys.lua index 584f37f0..257b6842 100644 --- a/modules/textadept/keys.lua +++ b/modules/textadept/keys.lua @@ -36,9 +36,7 @@ local function toggle_setting(setting, i) end local RECENT_FILES = 1 events.connect('user_list_selection', - function(type, text) - if type == RECENT_FILES then io.open_file(text) end - end) + function(type, text) if type == RECENT_FILES then io.open_file(text) end end) local function show_recent_file_list() local buffer = buffer local files = {} diff --git a/modules/textadept/menu.lua b/modules/textadept/menu.lua index e3ef2576..a914cb83 100644 --- a/modules/textadept/menu.lua +++ b/modules/textadept/menu.lua @@ -366,32 +366,30 @@ set_menubar(menubar) set_contextmenu(context_menu) -- Most of this handling code comes from keys.lua. -events.connect('menu_clicked', - function(menu_id) - local active_table - if menu_id > 1000 then - active_table = context_actions[menu_id - 1000] - else - active_table = menu_actions[menu_id] - end - local f, args - if active_table and #active_table > 0 then - local func = active_table[1] - if type(func) == 'function' then - f, args = func, { unpack(active_table, 2) } - elseif type(func) == 'string' then - local object = active_table[2] - if object == 'buffer' then - f, args = buffer[func], { buffer, unpack(active_table, 3) } - elseif object == 'view' then - f, args = view[func], { view, unpack(active_table, 3) } - end - end - if f and args then - local ret, retval = pcall(f, unpack(args)) - if not ret then error(retval) end - else - error(L('Unknown command:')..' '..tostring(func)) +events.connect('menu_clicked', function(menu_id) + local active_table + if menu_id > 1000 then + active_table = context_actions[menu_id - 1000] + else + active_table = menu_actions[menu_id] + end + local f, args + if active_table and #active_table > 0 then + local func = active_table[1] + if type(func) == 'function' then + f, args = func, { unpack(active_table, 2) } + elseif type(func) == 'string' then + local object = active_table[2] + if object == 'buffer' or object == 'view' then + local v = _G[object] + f, args = v[func], { v, unpack(active_table, 3) } end end - end) + if f and args then + local ret, retval = pcall(f, unpack(args)) + if not ret then error(retval) end + else + error(L('Unknown command:')..' '..tostring(func)) + end + end +end) diff --git a/modules/textadept/mime_types.lua b/modules/textadept/mime_types.lua index eaa4302a..534b2fcd 100644 --- a/modules/textadept/mime_types.lua +++ b/modules/textadept/mime_types.lua @@ -151,7 +151,7 @@ events.connect('buffer_new', function() buffer.set_lexer, buffer.get_lexer = set_lexer, get_lexer buffer.get_style_name = get_style_name end) --- Scintilla's first buffer doesn't have these +-- Scintilla's first buffer doesn't have these. if not RESETTING then buffer.set_lexer, buffer.get_lexer = set_lexer, get_lexer buffer.get_style_name = get_style_name diff --git a/modules/textadept/session.lua b/modules/textadept/session.lua index 6127c779..503ee248 100644 --- a/modules/textadept/session.lua +++ b/modules/textadept/session.lua @@ -93,8 +93,8 @@ function load(filename) end return true end -events.connect('arg_none', -- load session when no args are present - function() if SAVE_ON_QUIT then load() end end) +-- Load session when no args are present. +events.connect('arg_none', function() if SAVE_ON_QUIT then load() end end) --- -- Saves a Textadept session to a file. diff --git a/modules/textadept/snippets.lua b/modules/textadept/snippets.lua index 4ee3d85f..648909e4 100644 --- a/modules/textadept/snippets.lua +++ b/modules/textadept/snippets.lua @@ -140,7 +140,7 @@ local snippet_stack = {} -- @return string with escapes handled. local function handle_escapes(s) return s:gsub('%%([%%`%)|#])', - function(char) return ("\\%03d"):format(char:byte()) end) + function(char) return ("\\%03d"):format(char:byte()) end) end -- Replaces octal characters with their escaped equivalents in a given string. @@ -203,26 +203,25 @@ local function next_tab_stop() local function transform_mirror(mirror) local pattern, replacement = mirror:match('^%(([^|]+)|(.+)%)$') if not pattern and not replacement then return ph_text end - return ph_text:gsub(unhandle_escapes(pattern), - function(...) - local arg = {...} - local repl = replacement:gsub('%%(%d+)', - function(i) return arg[tonumber(i)] or '' end) - return repl:gsub('#(%b())', run_lua_code) - end, 1) + return ph_text:gsub(unhandle_escapes(pattern), function(...) + local arg = {...} + local repl = replacement:gsub('%%(%d+)', function(i) + return arg[tonumber(i)] or '' + end) + return repl:gsub('#(%b())', run_lua_code) + end, 1) end s_text = s_text:gsub('%%'..index..'(%b())', transform_mirror) -- Regular mirror. - s_text = s_text:gsub('()%%'..index, - function(pos) - for mirror, e in s_text:gmatch('%%%d+(%b())()') do - local s = mirror:find('|') - -- If inside transform, do not do anything. - if s and pos > s and pos < e then return nil end - end - return ph_text - end) + s_text = s_text:gsub('()%%'..index, function(pos) + for mirror, e in s_text:gmatch('%%%d+(%b())()') do + local s = mirror:find('|') + -- If inside transform, do not do anything. + if s and pos > s and pos < e then return nil end + end + return ph_text + end) buffer:set_sel(s_start, s_end) buffer:replace_sel(s_text) @@ -269,14 +268,13 @@ local function next_tab_stop() end -- Place additional carets at mirrors. local _, _, text = snippet_info() - text = text:gsub('(%%%d+%b())', - function(mirror) - -- Lua code in replacement mirrors may contain '%' - -- sequences; do not treat as mirrors - if mirror:find('|') then - return string.rep('_', #mirror) - end - end) + text = text:gsub('(%%%d+%b())', function(mirror) + -- Lua code in replacement mirrors may contain '%' + -- sequences; do not treat as mirrors + if mirror:find('|') then + return string.rep('_', #mirror) + end + end) for s, e in text:gmatch('()%%'..index..'()[^(]') do buffer:add_selection(s_start + s - 1, s_start + e - 1) end @@ -345,13 +343,12 @@ function _insert(s_text) -- Execute Lua and shell code. s_text = s_text:gsub('%%(%b())', run_lua_code) - s_text = s_text:gsub('`([^`]+)`', - function(code) - local p = io.popen(code) - local out = p:read('*all'):sub(1, -2) - p:close() - return out - end) + s_text = s_text:gsub('`([^`]+)`', function(code) + local p = io.popen(code) + local out = p:read('*all'):sub(1, -2) + p:close() + return out + end) -- Initialize the new snippet. If one is running, push it onto the stack. if snippet.index then snippet_stack[#snippet_stack + 1] = snippet end |