diff options
-rw-r--r-- | core/file_io.lua | 37 | ||||
-rw-r--r-- | core/init.lua | 2 | ||||
-rw-r--r-- | core/keys.lua | 45 | ||||
-rw-r--r-- | core/ui.lua | 1 | ||||
-rw-r--r-- | doc/markdowndoc.lua | 10 | ||||
-rw-r--r-- | modules/textadept/command_entry.lua | 47 | ||||
-rw-r--r-- | modules/textadept/editing.lua | 4 | ||||
-rw-r--r-- | modules/textadept/file_types.lua | 45 | ||||
-rw-r--r-- | modules/textadept/find.lua | 5 | ||||
-rw-r--r-- | modules/textadept/init.lua | 2 | ||||
-rw-r--r-- | modules/textadept/session.lua | 9 | ||||
-rw-r--r-- | modules/textadept/snippets.lua | 24 | ||||
-rwxr-xr-x | scripts/gen_plist.lua | 2 |
13 files changed, 96 insertions, 137 deletions
diff --git a/core/file_io.lua b/core/file_io.lua index a79f907c..7ddfee00 100644 --- a/core/file_io.lua +++ b/core/file_io.lua @@ -98,6 +98,8 @@ io.boms = { -- @name encodings io.encodings = {'UTF-8', 'ASCII', 'ISO-8859-1', 'MacRoman'} +local c = _SCINTILLA.constants +local EOLs = {['\r\n'] = c.EOL_CRLF, ['\r'] = c.EOL_CR, ['\n'] = c.EOL_LF} --- -- Opens *filenames*, a string filename or list of filenames, or the -- user-selected filenames. @@ -122,7 +124,7 @@ function io.open_file(filenames) local text = '' local f, err = io.open(filename, 'rb') if f then - text = f:read('*all') + text = f:read('*a') f:close() if not text then return end -- filename exists, but cannot read it elseif lfs.attributes(filename) then @@ -147,12 +149,8 @@ function io.open_file(filenames) end buffer.code_page = buffer.encoding and buffer.CP_UTF8 or 0 -- Detect EOL mode. - local s, e = text:find('\r\n?') - if s and e then - buffer.eol_mode = (s == e and buffer.EOL_CR or buffer.EOL_CRLF) - else - buffer.eol_mode = buffer.EOL_LF - end + buffer.eol_mode = EOLs[text:match('\r\n?')] or buffer.EOL_LF + -- Insert buffer text and set properties. buffer:add_text(text, #text) buffer:goto_pos(0) buffer:empty_undo_buffer() @@ -176,9 +174,8 @@ end function io.reload_file() if not buffer.filename then return end local pos, first_visible_line = buffer.current_pos, buffer.first_visible_line - local f, err = io.open(buffer.filename, 'rb') - assert(f, err) - local text = f:read('*all') + local f = assert(io.open(buffer.filename, 'rb')) + local text = f:read('*a') f:close() local encoding, encoding_bom = buffer.encoding, buffer.encoding_bom if encoding_bom then text = text:sub(#encoding_bom + 1, -1) end @@ -221,8 +218,7 @@ function io.save_file() if buffer.encoding then text = (buffer.encoding_bom or '')..text:iconv(buffer.encoding, 'UTF-8') end - local f, err = io.open(buffer.filename, 'wb') - assert(f, err) + local f = assert(io.open(buffer.filename, 'wb')) f:write(text) f:close() buffer:set_save_point() @@ -269,15 +265,14 @@ end -- @name close_buffer function io.close_buffer() local filename = buffer.filename or buffer._type or _L['Untitled'] - if buffer.modify and ui.dialogs.msgbox{ - title = _L['Close without saving?'], - text = _L['There are unsaved changes in'], - informative_text = filename:iconv('UTF-8', _CHARSET), - icon = 'gtk-dialog-question', button1 = _L['_Cancel'], - button2 = _L['Close _without saving'] - } ~= 2 then - return nil -- returning false can cause unwanted key command propagation - end + local confirm = not buffer.modify or ui.dialogs.msgbox{ + title = _L['Close without saving?'], + text = _L['There are unsaved changes in'], + informative_text = filename:iconv('UTF-8', _CHARSET), + icon = 'gtk-dialog-question', button1 = _L['_Cancel'], + button2 = _L['Close _without saving'] + } == 2 + if not confirm then return nil end -- nil return won't propagate a key command buffer:delete() return true end diff --git a/core/init.lua b/core/init.lua index e8ca6545..23d64b40 100644 --- a/core/init.lua +++ b/core/init.lua @@ -32,7 +32,7 @@ if CURSES or OSX then local current_dir = lfs.currentdir() lfs.chdir(working_dir) local p = io.popen(argv..' 2>&1') - stdout_cb(p:read('*all')) + stdout_cb(p:read('*a')) exit_cb(select(3, p:close())) lfs.chdir(current_dir) return p diff --git a/core/keys.lua b/core/keys.lua index 1c8a6997..7d658a57 100644 --- a/core/keys.lua +++ b/core/keys.lua @@ -134,38 +134,23 @@ M.KEYSYMS = { -- From curses.h. [263] = '\b', [343] = '\n', -- From Scintilla.h. - [300] = 'down', [301] = 'up', [302] = 'left', [303] = 'right', - [304] = 'home', [305] = 'end', - [306] = 'pgup', [307] = 'pgdn', - [308] = 'del', - [309] = 'ins', + [300] = 'down', [301] = 'up', [302] = 'left', [303] = 'right', [304] = 'home', + [305] = 'end', [306] = 'pgup', [307] = 'pgdn', [308] = 'del', [309] = 'ins', -- From <gdk/gdkkeysyms.h>. [0xFE20] = '\t', -- backtab; will be 'shift'ed - [0xFF08] = '\b', - [0xFF09] = '\t', - [0xFF0D] = '\n', - [0xFF1B] = 'esc', - [0xFFFF] = 'del', - [0xFF50] = 'home', - [0xFF51] = 'left', [0xFF52] = 'up', - [0xFF53] = 'right', [0xFF54] = 'down', - [0xFF55] = 'pgup', [0xFF56] = 'pgdn', - [0xFF57] = 'end', - [0xFF63] = 'ins', - [0xFF95] = 'kphome', - [0xFF96] = 'kpleft', [0xFF97] = 'kpup', - [0xFF98] = 'kpright', [0xFF99] = 'kpdown', - [0xFF9A] = 'kppgup', [0xFF9B] = 'kppgdn', - [0xFF9C] = 'kpend', - [0xFFAA] = 'kpmul', [0xFFAB] = 'kpadd', - [0xFFAD] = 'kpsub', [0xFFAF] = 'kpdiv', - [0xFFAE] = 'kpdec', - [0xFFB0] = 'kp0', [0xFFB1] = 'kp1', [0xFFB2] = 'kp2', [0xFFB3] = 'kp3', - [0xFFB4] = 'kp4', [0xFFB5] = 'kp5', [0xFFB6] = 'kp6', [0xFFB7] = 'kp7', - [0xFFB8] = 'kp8', [0xFFB9] = 'kp9', - [0xFFBE] = 'f1', [0xFFBF] = 'f2', [0xFFC0] = 'f3', [0xFFC1] = 'f4', - [0xFFC2] = 'f5', [0xFFC3] = 'f6', [0xFFC4] = 'f7', [0xFFC5] = 'f8', - [0xFFC6] = 'f9', [0xFFC7] = 'f10', [0xFFC8] = 'f11', [0xFFC9] = 'f12', + [0xFF08] = '\b', [0xFF09] = '\t', [0xFF0D] = '\n', [0xFF1B] = 'esc', + [0xFFFF] = 'del', [0xFF50] = 'home', [0xFF51] = 'left', [0xFF52] = 'up', + [0xFF53] = 'right', [0xFF54] = 'down', [0xFF55] = 'pgup', [0xFF56] = 'pgdn', + [0xFF57] = 'end', [0xFF63] = 'ins', [0xFF95] = 'kphome', [0xFF9C] = 'kpend', + [0xFF96] = 'kpleft', [0xFF97] = 'kpup', [0xFF98] = 'kpright', + [0xFF99] = 'kpdown', [0xFF9A] = 'kppgup', [0xFF9B] = 'kppgdn', + [0xFFAA] = 'kpmul', [0xFFAB] = 'kpadd', [0xFFAD] = 'kpsub', + [0xFFAF] = 'kpdiv', [0xFFAE] = 'kpdec', [0xFFB0] = 'kp0', [0xFFB1] = 'kp1', + [0xFFB2] = 'kp2', [0xFFB3] = 'kp3', [0xFFB4] = 'kp4', [0xFFB5] = 'kp5', + [0xFFB6] = 'kp6', [0xFFB7] = 'kp7', [0xFFB8] = 'kp8', [0xFFB9] = 'kp9', + [0xFFBE] = 'f1', [0xFFBF] = 'f2', [0xFFC0] = 'f3', [0xFFC1] = 'f4', + [0xFFC2] = 'f5', [0xFFC3] = 'f6', [0xFFC4] = 'f7', [0xFFC5] = 'f8', + [0xFFC6] = 'f9', [0xFFC7] = 'f10', [0xFFC8] = 'f11', [0xFFC9] = 'f12', } -- The current key sequence. diff --git a/core/ui.lua b/core/ui.lua index 7e5f56ed..e78e6c29 100644 --- a/core/ui.lua +++ b/core/ui.lua @@ -211,7 +211,6 @@ end -- @usage ui.set_theme('light', {font = 'Monospace', fontsize = 12}) -- @name set_theme function ui.set_theme(name, props) - if not name then return end name = name:find('[/\\]') and name or package.searchpath(name, _USERHOME..'/themes/?.lua;'.. _HOME..'/themes/?.lua') diff --git a/doc/markdowndoc.lua b/doc/markdowndoc.lua index eb9e4803..dbc15864 100644 --- a/doc/markdowndoc.lua +++ b/doc/markdowndoc.lua @@ -144,10 +144,10 @@ function M.start(doc) local header, footer = '', '' if M.options.template_dir ~= 'luadoc/doclet/html/' then local p = io.popen('markdown "'..M.options.template_dir..'.header.md"') - template.header = p:read('*all') + template.header = p:read('*a') p:close() p = io.popen('markdown "'..M.options.template_dir..'.footer.md"') - template.footer = p:read('*all') + template.footer = p:read('*a') p:close() end @@ -168,7 +168,7 @@ function M.start(doc) write_nav(f, hierarchy) f:close() local p = io_popen('markdown "'..navfile..'"') - local nav = p:read('*all') + local nav = p:read('*a') p:close() os.remove(navfile) @@ -177,7 +177,7 @@ function M.start(doc) local api_index = M.options.output_dir..'/.api_index.md' if require('lfs').attributes(api_index) then local p = io_popen('markdown -f toc -T "'..api_index..'"') - template.toc, template.main = p:read('*all'):match('^(.-\n</ul>\n)(.+)$') + template.toc, template.main = p:read('*a'):match('^(.-\n</ul>\n)(.+)$') p:close() end f = io_open(M.options.output_dir..'/api/index.html', 'wb') @@ -265,7 +265,7 @@ function M.start(doc) template.title = name..' - Textadept API' template.nav = nav:gsub('<a[^>]+>('..name:match('[^%.]+$')..')</a>', '%1') local p = io_popen('markdown -f toc -T "'..mdfile..'"') - template.toc, template.main = p:read('*all'):match('^(.-\n</ul>\n)(.+)$') + template.toc, template.main = p:read('*a'):match('^(.-\n</ul>\n)(.+)$') p:close() template.toc = template.toc:gsub('(<a.-)%b()(</a>)', '%1%2') -- strip params :gsub('<code>([^<]+)</code>', '%1') -- sans serif diff --git a/modules/textadept/command_entry.lua b/modules/textadept/command_entry.lua index c2fa414c..6d495199 100644 --- a/modules/textadept/command_entry.lua +++ b/modules/textadept/command_entry.lua @@ -98,11 +98,9 @@ local env = setmetatable({}, { -- Prints the results of '=' expressions like in the Lua prompt. -- @param code The Lua code to execute. local function execute_lua(code) - if code:sub(1, 1) == '=' then code = 'return '..code:sub(2) end - local f, err = load(code, nil, 'bt', env) - assert(f, err) - local result = f() - if result ~= nil then ui.print(result) end + if code:find('^=') then code = 'return '..code:sub(2) end + local result = assert(load(code, nil, 'bt', env))() + if result ~= nil or code:find('^return ') then ui.print(result) end events.emit(events.UPDATE_UI) end args.register('-e', '--execute', 1, execute_lua, 'Execute Lua code') @@ -113,36 +111,32 @@ args.register('-e', '--execute', 1, execute_lua, 'Execute Lua code') -- @param code The Lua code to complete. The default value is the value of -- `entry_text`. local function 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, result = pcall(f) + if not code then code = M.entry_text end + local symbol, op, part = code:match('([%w_.]-)([%.:]?)([%w_]*)$') + local ok, result = pcall((load('return ('..symbol..')', nil, 'bt', env))) local cmpls = {} - prefix = '^'..prefix + part = '^'..part + if (not ok or type(result) ~= 'table') and symbol ~= '' then return end if not ok then -- shorthand notation - for _, t in ipairs{buffer, view, ui, _G} do - for k in pairs(t) do - if type(k) == 'string' and k:find(prefix) then cmpls[#cmpls + 1] = k end + local pool = { + buffer, view, ui, _G, _SCINTILLA.functions, _SCINTILLA.properties + } + for i = 1, #pool do + for k in pairs(pool[i]) do + if type(k) == 'string' and k:find(part) 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(result) ~= 'table' then return end for k in pairs(result) do - if type(k) == 'string' and k:find(prefix) then cmpls[#cmpls + 1] = k end + if type(k) == 'string' and k:find(part) then cmpls[#cmpls + 1] = k end end - if path == 'buffer' and op == ':' then + if symbol == 'buffer' and op == ':' then for f in pairs(_SCINTILLA.functions) do - if f:find(prefix) then cmpls[#cmpls + 1] = f end + if f:find(part) then cmpls[#cmpls + 1] = f end end - elseif path == 'buffer' and op == '.' then + elseif symbol == 'buffer' and op == '.' then for p in pairs(_SCINTILLA.properties) do - if p:find(prefix) then cmpls[#cmpls + 1] = p end + if p:find(part) then cmpls[#cmpls + 1] = p end end end end @@ -152,8 +146,7 @@ end -- Define key mode for entering Lua commands. keys.lua_command = { - ['\t'] = complete_lua, - ['\n'] = {M.finish_mode, execute_lua} + ['\t'] = complete_lua, ['\n'] = {M.finish_mode, execute_lua} } -- Pass command entry keys to the default keypress handler. diff --git a/modules/textadept/editing.lua b/modules/textadept/editing.lua index b6235195..4533d43c 100644 --- a/modules/textadept/editing.lua +++ b/modules/textadept/editing.lua @@ -506,10 +506,10 @@ function M.filter_through(command) local p = io.popen(cmd) if s ~= e then buffer.target_start, buffer.target_end = s, e - buffer:replace_target(p:read('*all')) + buffer:replace_target(p:read('*a')) buffer:set_sel(buffer.target_start, buffer.target_end) else - buffer:set_text(p:read('*all')) + buffer:set_text(p:read('*a')) buffer:goto_pos(s) end p:close() diff --git a/modules/textadept/file_types.lua b/modules/textadept/file_types.lua index 9d7e4600..4433dc04 100644 --- a/modules/textadept/file_types.lua +++ b/modules/textadept/file_types.lua @@ -54,33 +54,32 @@ local function get_lexer(buffer, current) return current and lexer:match('[^/]+$') or lexer:match('^[^/]+') end +-- Attempts to detect the language based on a buffer's first line of text or +-- that buffer's filename. +-- @param buffer The buffer to detect the language of. +-- @return lexer language +local function detect_language(buffer) + local line = buffer:get_line(0) + -- Detect from shebang line. + if line:find('^#!') then + for word in line:gsub('[/\\]', ' '):gmatch('%S+') do + if M.shebangs[word] then return M.shebangs[word] end + end + end + -- Detect from first line. + for patt, lexer in pairs(M.patterns) do + if line:find(patt) then return lexer end + end + -- Detect from file extension. + return buffer.filename and M.extensions[buffer.filename:match('[^/\\.]+$')] or + 'text' +end + local SETDIRECTPOINTER = _SCINTILLA.properties.doc_pointer[2] local SETLEXERLANGUAGE = _SCINTILLA.properties.lexer_language[2] -- LuaDoc is in core/.buffer.luadoc. local function set_lexer(buffer, lang) - -- If no language was given, attempt to detect it. - if not lang then - local line = buffer:get_line(0) - -- Detect from shebang line. - if line:find('^#!') then - for word in line:gsub('[/\\]', ' '):gmatch('%S+') do - if M.shebangs[word] then lang = M.shebangs[word] break end - end - end - -- Detect from first line. - if not lang then - for patt, lexer in pairs(M.patterns) do - if line:find(patt) then lang = lexer break end - end - end - -- Detect from file extension. - if not lang and buffer.filename then - lang = M.extensions[buffer.filename:match('[^/\\.]+$')] - end - if not lang then lang = 'text' end - end - - -- Set the lexer and load its language module. + if not lang then lang = detect_language(buffer) end buffer:private_lexer_call(SETDIRECTPOINTER, buffer.direct_pointer) buffer:private_lexer_call(SETLEXERLANGUAGE, lang) buffer._lexer = lang diff --git a/modules/textadept/find.lua b/modules/textadept/find.lua index bd9c8825..e293a7c4 100644 --- a/modules/textadept/find.lua +++ b/modules/textadept/find.lua @@ -231,7 +231,7 @@ function M.find_in_files(dir) 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 + if M.whole_word then text = '%f[%w_]'..text..'%f[^%w_]' end -- TODO: wordchars local matches = {_L['Find:']..' '..text} lfs.dir_foreach(dir, function(file) local match_case = M.match_case @@ -271,8 +271,7 @@ local function replace(rtext) end local ok, rtext = pcall(rtext.gsub, rtext, '%%(%b())', function(code) code = code:gsub('[\a\b\f\n\r\t\v\\]', escapes) - local ok, result = pcall(load('return '..code)) - assert(ok, result) + local result = assert(load('return '..code))() return result:gsub('\\[abfnrtv\\]', escapes) end) if ok then diff --git a/modules/textadept/init.lua b/modules/textadept/init.lua index 795768b6..4d1618c3 100644 --- a/modules/textadept/init.lua +++ b/modules/textadept/init.lua @@ -12,8 +12,8 @@ module('textadept')]] M.bookmarks = require('textadept.bookmarks') require('textadept.command_entry') M.editing = require('textadept.editing') -require('textadept.find') M.file_types = require('textadept.file_types') +require('textadept.find') M.run = require('textadept.run') M.session = require('textadept.session') M.snippets = require('textadept.snippets') diff --git a/modules/textadept/session.lua b/modules/textadept/session.lua index d2e1a921..fd5a595d 100644 --- a/modules/textadept/session.lua +++ b/modules/textadept/session.lua @@ -52,8 +52,8 @@ function M.load(filename) local lfs_attributes = lfs.attributes for line in f:lines() do if line:find('^buffer:') then - local anchor, current_pos, first_visible_line, filename = - line:match('^buffer: (%d+) (%d+) (%d+) (.+)$') + local patt = '^buffer: (%d+) (%d+) (%d+) (.+)$' + local anchor, current_pos, first_visible_line, filename = line:match(patt) if not filename:find('^%[.+%]$') then if lfs_attributes(filename) then io.open_file(filename) @@ -65,9 +65,8 @@ function M.load(filename) events.emit(events.FILE_OPENED, filename) end -- Restore saved buffer selection and view. - local anchor = tonumber(anchor) or 0 - local current_pos = tonumber(current_pos) or 0 - local first_visible_line = tonumber(first_visible_line) or 0 + anchor, current_pos = tonumber(anchor) or 0, tonumber(current_pos) or 0 + first_visible_line = tonumber(first_visible_line) or 0 buffer._anchor, buffer._current_pos = anchor, current_pos buffer._first_visible_line = first_visible_line buffer:line_scroll(0, buffer:visible_from_doc_line(first_visible_line)) diff --git a/modules/textadept/snippets.lua b/modules/textadept/snippets.lua index 54127fb5..e373e6aa 100644 --- a/modules/textadept/snippets.lua +++ b/modules/textadept/snippets.lua @@ -86,9 +86,7 @@ local newlines = {[0] = '\r\n', '\r', '\n'} -- @param trigger The trigger text used to expand the snippet, if any. local function new_snippet(text, trigger) local snippet = setmetatable({ - trigger = trigger, - original_sel_text = buffer:get_sel_text(), - snapshots = {} + trigger = trigger, original_sel_text = buffer:get_sel_text(), snapshots = {} }, {__index = M._snippet_mt}) snippet_stack[#snippet_stack + 1] = snippet @@ -139,13 +137,10 @@ function M._insert(text) local lexer = buffer:get_lexer(true) trigger = buffer:text_range(buffer:word_start_position(buffer.current_pos), buffer.current_pos) - local snip = snippets - text = snip[trigger] - if type(snip) == 'table' and snip[lexer] then snip = snip[lexer] end - text = snip[trigger] or text + text = type(M[lexer]) == 'table' and M[lexer][trigger] or M[trigger] end - local snippet = snippet_stack[#snippet_stack] - if type(text) == 'string' then snippet = new_snippet(text, trigger) end + local snippet = text and new_snippet(text, trigger) or + snippet_stack[#snippet_stack] if not snippet then return false end snippet:next() end @@ -174,7 +169,6 @@ end -- @name _select function M._select() local list, t = {}, {} - local type = type for trigger, text in pairs(snippets) do if type(text) == 'string' then list[#list + 1] = trigger..'\0 \0'..text end end @@ -214,17 +208,13 @@ M._snippet_mt = { -- Gets a snippet's end position in the buffer. -- @param snippet The snippet returned by `new_snippet()`. get_end_position = function(snippet) - local e = buffer:indicator_end(INDIC_SNIPPET, snippet.start_position + 1) - if e == 0 then e = snippet.start_position end - return e + return buffer:indicator_end(INDIC_SNIPPET, snippet.start_position + 1) end, -- Gets the text for a snippet. -- @param snippet The snippet returned by `new_snippet()`. get_text = function(snippet) - local s, e = snippet.start_position, snippet:get_end_position() - local ok, text = pcall(buffer.text_range, buffer, s, e) - return ok and text or '' + return buffer:text_range(snippet.start_position, snippet:get_end_position()) end, -- Sets the text for a snippet. @@ -272,7 +262,7 @@ M._snippet_mt = { -- Shell code. escaped_text = escaped_text:gsub('%%'..index..'%[([^%]]*)%]', function(code) local p = io.popen(snippet.unescape_text(code, true)) - local result = p:read('*all'):sub(1, -2) -- chop '\n' + local result = p:read('*a'):sub(1, -2) -- chop '\n' p:close() return result end) diff --git a/scripts/gen_plist.lua b/scripts/gen_plist.lua index f96c2a57..f8337d43 100755 --- a/scripts/gen_plist.lua +++ b/scripts/gen_plist.lua @@ -8,7 +8,7 @@ local languages, extensions = {}, {} -- Read languages and extensions. local f = io.open('../modules/textadept/file_types.lua') -local types = f:read('*all'):match('M.extensions = (%b{})'):sub(2) +local types = f:read('*a'):match('M.extensions = (%b{})'):sub(2) f:close() for type in types:gmatch('(.-)[%],}]+') do if type:find('^%-%-') then |