aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--modules/cpp/adeptsense.lua32
-rw-r--r--modules/cpp/commands.lua57
-rw-r--r--modules/cpp/init.lua164
-rw-r--r--modules/cpp/snippets.lua75
-rw-r--r--modules/lua/adeptsense.lua47
-rw-r--r--modules/lua/commands.lua124
-rw-r--r--modules/lua/init.lua193
-rw-r--r--modules/lua/snippets.lua19
-rw-r--r--modules/textadept/adeptsense.lua19
-rw-r--r--modules/textadept/bookmarks.lua2
10 files changed, 336 insertions, 396 deletions
diff --git a/modules/cpp/adeptsense.lua b/modules/cpp/adeptsense.lua
deleted file mode 100644
index 92890ea3..00000000
--- a/modules/cpp/adeptsense.lua
+++ /dev/null
@@ -1,32 +0,0 @@
--- Copyright 2007-2011 Mitchell mitchell<att>caladbolg.net. See LICENSE.
-
----
--- Adeptsense for the cpp module.
--- User tags are loaded from _USERHOME/modules/cpp/tags and user apis are loaded
--- from _USERHOME/modules/cpp/api.
-module('_m.cpp.adeptsense', package.seeall)
-
-sense = _m.textadept.adeptsense.new('cpp')
-sense.ctags_kinds = {
- c = 'classes',
- d = 'functions',
- e = 'fields',
- f = 'functions',
- g = 'classes',
- m = 'fields',
- s = 'classes',
- t = 'classes'
-}
-sense.syntax.type_declarations = {
- '(%u[%w_%.]+)[%s%*&]+%_[^%w_]', -- Foo bar, Foo *bar, Foo* bar, Foo &bar, etc.
-}
-sense:add_trigger('.')
-sense:add_trigger('->')
-
--- Load user tags and apidoc.
-if lfs.attributes(_USERHOME..'/modules/cpp/tags') then
- sense:load_ctags(_USERHOME..'/modules/cpp/tags')
-end
-if lfs.attributes(_USERHOME..'/modules/cpp/api') then
- sense.api_files[#sense.api_files + 1] = _USERHOME..'/modules/cpp/api'
-end
diff --git a/modules/cpp/commands.lua b/modules/cpp/commands.lua
deleted file mode 100644
index a74d83a5..00000000
--- a/modules/cpp/commands.lua
+++ /dev/null
@@ -1,57 +0,0 @@
--- Copyright 2007-2011 Mitchell mitchell<att>caladbolg.net. See LICENSE.
-
----
--- Commands for the cpp module.
-module('_m.cpp.commands', package.seeall)
-
--- Markdown:
--- ## Key Commands
---
--- + `Alt+L, M`: Open this module for editing.
--- + `.`: When to the right of a known symbol, show an autocompletion list of
--- fields and functions.
--- + `->`: When to the right of a known symbol, show an autocompletion list of
--- fields and functions.
--- + `Ctrl+I`: (Windows and Linux) Autocomplete symbol.
--- + `~`: (Mac OSX) Autocomplete symbol.
--- + `Ctrl+H`: Show documentation for the selected symbol or the symbol under
--- the caret.
--- + `Shift+Return`: Add ';' to line end and insert newline.
-
-local m_editing, m_run = _m.textadept.editing, _m.textadept.run
--- Comment string tables use lexer names.
-m_editing.comment_string.cpp = '//'
--- Compile and Run command tables use file extensions.
-m_run.compile_command.c =
- 'gcc -pedantic -Os -o "%(filename_noext)" %(filename)'
-m_run.compile_command.cpp =
- 'g++ -pedantic -Os -o "%(filename_noext)" %(filename)'
-m_run.run_command.c = '%(filedir)%(filename_noext)'
-m_run.run_command.cpp = '%(filedir)%(filename_noext)'
-m_run.error_detail.c = {
- pattern = '^(.-):(%d+): (.+)$',
- filename = 1, line = 2, message = 3
-}
-
--- C++-specific key commands.
-local cppsense = _m.cpp.adeptsense.sense
-local keys = _G.keys
-if type(keys) == 'table' then
- keys.cpp = {
- al = {
- m = { io.open_file,
- (_HOME..'/modules/cpp/init.lua'):iconv('UTF-8', _CHARSET) },
- },
- ['s\n'] = { function()
- buffer:line_end()
- buffer:add_text(';')
- buffer:new_line()
- end },
- [not OSX and 'ci' or '~'] = { cppsense.complete, cppsense },
- ch = { cppsense.show_apidoc, cppsense },
- }
-end
-
----
--- This module contains no functions.
-function no_functions() end no_functions = nil
diff --git a/modules/cpp/init.lua b/modules/cpp/init.lua
index cce101a8..55555a65 100644
--- a/modules/cpp/init.lua
+++ b/modules/cpp/init.lua
@@ -3,28 +3,166 @@
---
-- The cpp module.
-- It provides utilities for editing C/C++ code.
+-- User tags are loaded from _USERHOME/modules/cpp/tags and user apis are loaded
+-- from _USERHOME/modules/cpp/api.
module('_m.cpp', package.seeall)
-if type(_G.snippets) == 'table' then
+-- Markdown:
+-- ## Key Commands
+--
+-- + `Alt+L, M`: Open this module for editing.
+-- + `.`: When to the right of a known symbol, show an autocompletion list of
+-- fields and functions.
+-- + `->`: When to the right of a known symbol, show an autocompletion list of
+-- fields and functions.
+-- + `Ctrl+I`: (Windows and Linux) Autocomplete symbol.
+-- + `~`: (Mac OSX) Autocomplete symbol.
+-- + `Ctrl+H`: Show documentation for the selected symbol or the symbol under
+-- the caret.
+-- + `Shift+Return`: Add ';' to line end and insert newline.
+--
+-- ## Fields
+--
+-- * `sense`: The C/C++ [Adeptsense](_m.textadept.adeptsense.html).
+
+local m_editing, m_run = _m.textadept.editing, _m.textadept.run
+-- Comment string tables use lexer names.
+m_editing.comment_string.cpp = '//'
+-- Compile and Run command tables use file extensions.
+m_run.compile_command.c =
+ 'gcc -pedantic -Os -o "%(filename_noext)" %(filename)'
+m_run.compile_command.cpp =
+ 'g++ -pedantic -Os -o "%(filename_noext)" %(filename)'
+m_run.run_command.c = '%(filedir)%(filename_noext)'
+m_run.run_command.cpp = '%(filedir)%(filename_noext)'
+m_run.error_detail.c = {
+ pattern = '^(.-):(%d+): (.+)$',
+ filename = 1, line = 2, message = 3
+}
+
---
--- Container for C/C++-specific snippets.
--- @class table
--- @name snippets.cpp
- _G.snippets.cpp = {}
+-- Sets default buffer properties for C/C++ files.
+function set_buffer_properties()
+
end
-if type(_G.keys) == 'table' then
+-- Adeptsense.
+
+sense = _m.textadept.adeptsense.new('cpp')
+sense.ctags_kinds = {
+ c = 'classes',
+ d = 'functions',
+ e = 'fields',
+ f = 'functions',
+ g = 'classes',
+ m = 'fields',
+ s = 'classes',
+ t = 'classes'
+}
+sense.syntax.type_declarations = {
+ '(%u[%w_%.]+)[%s%*&]+%_[^%w_]', -- Foo bar, Foo *bar, Foo* bar, Foo &bar, etc.
+}
+sense:add_trigger('.')
+sense:add_trigger('->')
+
+-- Load user tags and apidoc.
+if lfs.attributes(_USERHOME..'/modules/cpp/tags') then
+ sense:load_ctags(_USERHOME..'/modules/cpp/tags')
+end
+if lfs.attributes(_USERHOME..'/modules/cpp/api') then
+ sense.api_files[#sense.api_files + 1] = _USERHOME..'/modules/cpp/api'
+end
+
+-- Commands.
+
---
-- Container for C/C++-specific key commands.
-- @class table
--- @name keys.cpp
- _G.keys.cpp = {}
-end
+-- @name _G.keys.cpp
+_G.keys.cpp = {
+ al = {
+ m = { io.open_file,
+ (_HOME..'/modules/cpp/init.lua'):iconv('UTF-8', _CHARSET) },
+ },
+ ['s\n'] = { function()
+ buffer:line_end()
+ buffer:add_text(';')
+ buffer:new_line()
+ end },
+ [not OSX and 'ci' or '~'] = { sense.complete, sense },
+ ch = { sense.show_apidoc, sense },
+}
-require 'cpp.adeptsense'
-require 'cpp.commands'
-require 'cpp.snippets'
+-- Snippets.
-function set_buffer_properties()
+---
+-- Container for C/C++-specific snippets.
+-- @class table
+-- @name _G.snippets.cpp
+if type(_G.snippets) == 'table' then
+ _G.snippets.cpp = {
+ rc = 'reinterpret_cast<%1>(%2(%(selected_text)))',
+ sc = 'static_cast<%1>(%2(%(selected_text)))',
+ cc = 'const_cast<%1>(%2(%(selected_text)))',
+ -- Lua snippets
+ lf = 'static int %1(function)(lua_State *%2(lua)) {\n\t%0\n\treturn 0;\n}',
+ ls = 'lua_State',
+ lgf = 'lua_getfield(%1(lua), %2(-1), %3(field));',
+ lgg = 'lua_getglobal(%1(lua), %2(global));',
+ lgt = 'lua_gettable(%1(lua), %2(-2));',
+ ltop = 'lua_gettop(%1(lua));',
+ lib = 'lua_isboolean(%1(lua), %2(-1))',
+ licf = 'lua_iscfunction(%1(lua), %2(-1))',
+ lif = 'lua_isfunctionu(%1(lua), %2(-1))',
+ linil = 'lua_isnil(%1(lua), %2(-1))',
+ linone = 'lua_isnone(%1(lua), %2(-1))',
+ linonen = 'lua_isnoneornil(%1(lua), %2(-1))',
+ lin = 'lua_isnumber(%1(lua), %2(-1))',
+ lis = 'lua_isstring(%1(lua), %2(-1))',
+ lit = 'lua_istable(%1(lua), %2(-1))',
+ lith = 'lua_isthread(%1(lua), %2(-1))',
+ liu = 'lua_isuserdata(%1(lua), %2(-1))',
+ llen = 'lua_objlen(%1(lua), %2(-1))',
+ lpop = 'lua_pop(%1(lua), %2(1));',
+ lpb = 'lua_pushboolean(%1(lua), %2(boolean));',
+ lpcc = 'lua_pushcclosure(%1(lua), %2(closure_func), %3(num_values));',
+ lpcf = 'lua_pushcfunction(%1(lua), %2(cfunction));',
+ lpi = 'lua_pushinteger(%1(lua), %2(integer));',
+ lplu = 'lua_pushlightuserdata(%1(lua), %2(userdata));',
+ lpnil = 'lua_pushnil(%1(lua));',
+ lpn = 'lua_pushnumber(%1(lua), %2(number));',
+ lps = 'lua_pushstring(%1(lua), %2(string));',
+ lpth = 'lua_pushthread(%1(lua));',
+ lpv = 'lua_pushvalue(%1(lua), %2(-1));',
+ lrg = 'lua_rawget(%1(lua), %2(-2));',
+ lrgi = 'lua_rawgeti(%1(lua), %2(-2), %3(1));',
+ lrs = 'lua_rawset(%1(lua), %2(-3));',
+ lrsi = 'lua_rawseti(%1(lua), %2(-2), %3(1));',
+ lr = 'lua_register(%1(lua), %2(fname), %3(cfunction));',
+ lsf = 'lua_setfield(%1(lua), %2(-2), %3(field));',
+ lsg = 'lua_setglobal(%1(lua), %2(global));',
+ lst = 'lua_settable(%1(lua), %2(-3));',
+ ltb = 'lua_toboolean(%1(lua), %2(-1))',
+ ltcf = 'lua_tocfunction(%1(lua), %2(-1))',
+ lti = 'lua_tointeger(%1(lua), %2(-1))',
+ ltn = 'lua_tonumber(%1(lua), %2(-1))',
+ ltp = 'lua_topointer(%1(lua), %2(-1))',
+ lts = 'lua_tostring(%1(lua), %2(-1))',
+ ltth = 'lua_tothread(%1(lua), %2(-1))',
+ ltu = 'lua_touserdata(%1(lua), %2(-1))',
+ lt = 'lua_type(%1(lua), %2(-1))',
+ llcint = 'luaL_checkint(%1(lua), %2(-1))',
+ llci = 'luaL_checkinteger(%1(lua), %2(-1))',
+ llcl = 'luaL_checklong(%1(lua), %2(-1))',
+ llcn = 'luaL_checknumber(%1(lua), %2(-1))',
+ llcs = 'luaL_checkstring(%1(lua), %2(-1))',
+ llcu = 'luaL_checkudata(%1(lua), %2(-1), %3(mt_name))',
+ llerr = 'luaL_error(%1(lua), %2(errorstring)%3(, %4(arg)));',
+ lloint = 'luaL_optint(%1(lua), %2(-1), %3(default))',
+ lloi = 'luaL_optinteger(%1(lua), %2(-1), %3(default))',
+ llol = 'luaL_optlong(%1(lua), %2(-1), %3(default))',
+ llon = 'luaL_optnumber(%1(lua), %2(-1), %3(default))',
+ llos = 'luaL_optstring(%1(lua), %2(-1), %3(default))',
+ }
end
diff --git a/modules/cpp/snippets.lua b/modules/cpp/snippets.lua
deleted file mode 100644
index 68e4ef24..00000000
--- a/modules/cpp/snippets.lua
+++ /dev/null
@@ -1,75 +0,0 @@
--- Copyright 2007-2011 Mitchell mitchell<att>caladbolg.net. See LICENSE.
-
----
--- Snippets for the cpp module.
-module('_m.cpp.snippets', package.seeall)
-
-local snippets = _G.snippets
-
-if type(snippets) == 'table' then
- snippets.cpp = {
- rc = 'reinterpret_cast<%1>(%2(%(selected_text)))',
- sc = 'static_cast<%1>(%2(%(selected_text)))',
- cc = 'const_cast<%1>(%2(%(selected_text)))',
-
- -- Lua snippets
- lf = 'static int %1(function)(lua_State *%2(lua)) {\n\t%0\n\treturn 0;\n}',
- ls = 'lua_State',
- lgf = 'lua_getfield(%1(lua), %2(-1), %3(field));',
- lgg = 'lua_getglobal(%1(lua), %2(global));',
- lgt = 'lua_gettable(%1(lua), %2(-2));',
- ltop = 'lua_gettop(%1(lua));',
- lib = 'lua_isboolean(%1(lua), %2(-1))',
- licf = 'lua_iscfunction(%1(lua), %2(-1))',
- lif = 'lua_isfunctionu(%1(lua), %2(-1))',
- linil = 'lua_isnil(%1(lua), %2(-1))',
- linone = 'lua_isnone(%1(lua), %2(-1))',
- linonen = 'lua_isnoneornil(%1(lua), %2(-1))',
- lin = 'lua_isnumber(%1(lua), %2(-1))',
- lis = 'lua_isstring(%1(lua), %2(-1))',
- lit = 'lua_istable(%1(lua), %2(-1))',
- lith = 'lua_isthread(%1(lua), %2(-1))',
- liu = 'lua_isuserdata(%1(lua), %2(-1))',
- llen = 'lua_objlen(%1(lua), %2(-1))',
- lpop = 'lua_pop(%1(lua), %2(1));',
- lpb = 'lua_pushboolean(%1(lua), %2(boolean));',
- lpcc = 'lua_pushcclosure(%1(lua), %2(closure_func), %3(num_values));',
- lpcf = 'lua_pushcfunction(%1(lua), %2(cfunction));',
- lpi = 'lua_pushinteger(%1(lua), %2(integer));',
- lplu = 'lua_pushlightuserdata(%1(lua), %2(userdata));',
- lpnil = 'lua_pushnil(%1(lua));',
- lpn = 'lua_pushnumber(%1(lua), %2(number));',
- lps = 'lua_pushstring(%1(lua), %2(string));',
- lpth = 'lua_pushthread(%1(lua));',
- lpv = 'lua_pushvalue(%1(lua), %2(-1));',
- lrg = 'lua_rawget(%1(lua), %2(-2));',
- lrgi = 'lua_rawgeti(%1(lua), %2(-2), %3(1));',
- lrs = 'lua_rawset(%1(lua), %2(-3));',
- lrsi = 'lua_rawseti(%1(lua), %2(-2), %3(1));',
- lr = 'lua_register(%1(lua), %2(fname), %3(cfunction));',
- lsf = 'lua_setfield(%1(lua), %2(-2), %3(field));',
- lsg = 'lua_setglobal(%1(lua), %2(global));',
- lst = 'lua_settable(%1(lua), %2(-3));',
- ltb = 'lua_toboolean(%1(lua), %2(-1))',
- ltcf = 'lua_tocfunction(%1(lua), %2(-1))',
- lti = 'lua_tointeger(%1(lua), %2(-1))',
- ltn = 'lua_tonumber(%1(lua), %2(-1))',
- ltp = 'lua_topointer(%1(lua), %2(-1))',
- lts = 'lua_tostring(%1(lua), %2(-1))',
- ltth = 'lua_tothread(%1(lua), %2(-1))',
- ltu = 'lua_touserdata(%1(lua), %2(-1))',
- lt = 'lua_type(%1(lua), %2(-1))',
- llcint = 'luaL_checkint(%1(lua), %2(-1))',
- llci = 'luaL_checkinteger(%1(lua), %2(-1))',
- llcl = 'luaL_checklong(%1(lua), %2(-1))',
- llcn = 'luaL_checknumber(%1(lua), %2(-1))',
- llcs = 'luaL_checkstring(%1(lua), %2(-1))',
- llcu = 'luaL_checkudata(%1(lua), %2(-1), %3(mt_name))',
- llerr = 'luaL_error(%1(lua), %2(errorstring)%3(, %4(arg)));',
- lloint = 'luaL_optint(%1(lua), %2(-1), %3(default))',
- lloi = 'luaL_optinteger(%1(lua), %2(-1), %3(default))',
- llol = 'luaL_optlong(%1(lua), %2(-1), %3(default))',
- llon = 'luaL_optnumber(%1(lua), %2(-1), %3(default))',
- llos = 'luaL_optstring(%1(lua), %2(-1), %3(default))',
- }
-end
diff --git a/modules/lua/adeptsense.lua b/modules/lua/adeptsense.lua
deleted file mode 100644
index 9e6d86a2..00000000
--- a/modules/lua/adeptsense.lua
+++ /dev/null
@@ -1,47 +0,0 @@
--- Copyright 2007-2011 Mitchell mitchell<att>caladbolg.net. See LICENSE.
-
----
--- Adeptsense for the lua module.
--- User tags are loaded from _USERHOME/modules/lua/tags and user apis are loaded
--- from _USERHOME/modules/lua/api.
-module('_m.lua.adeptsense', package.seeall)
-
-sense = _m.textadept.adeptsense.new('lua')
-sense.syntax.class_definition = 'module%s*%(?%s*[\'"]([%w_%.]+)'
-sense.syntax.symbol_chars = '[%w_%.:]'
-sense.syntax.type_declarations = {}
-sense.syntax.type_assignments = {
- ['^[\'"]'] = 'string', -- foo = 'bar' or foo = "bar"
- ['^([%w_%.]+)%s*$'] = '%1' -- foo = _m.textadept.adeptsense
-}
-sense.api_files = { _HOME..'/modules/lua/api' }
-sense:add_trigger('.')
-sense:add_trigger(':', false, true)
-
--- script/update_doc generates a fake set of ctags used for autocompletion.
-sense.ctags_kinds = {
- f = 'functions',
- F = 'fields',
- m = 'classes',
- t = 'fields',
-}
-sense:load_ctags(_HOME..'/modules/lua/tags', true)
-
----
--- Shows an autocompletion list for the symbol behind the caret.
--- @param only_fields If true, returns list of only fields; defaults to false.
--- @param only_functions If true, returns list of only functions; defaults to
--- false.
-function sense:complete(only_fields, only_functions)
- local line, pos = buffer:get_cur_line()
- local symbol = line:sub(1, pos):match(self.syntax.symbol_chars..'*$')
- return self.super.complete(self, false, symbol:find(':'))
-end
-
--- Load user tags and apidoc.
-if lfs.attributes(_USERHOME..'/modules/lua/tags') then
- sense:load_ctags(_USERHOME..'/modules/lua/tags')
-end
-if lfs.attributes(_USERHOME..'/modules/lua/api') then
- sense.api_files[#sense.api_files + 1] = _USERHOME..'/modules/lua/api'
-end
diff --git a/modules/lua/commands.lua b/modules/lua/commands.lua
deleted file mode 100644
index 06e1944c..00000000
--- a/modules/lua/commands.lua
+++ /dev/null
@@ -1,124 +0,0 @@
--- Copyright 2007-2011 Mitchell mitchell<att>caladbolg.net. See LICENSE.
-
----
--- Commands for the lua module.
-module('_m.lua.commands', package.seeall)
-
--- Markdown:
--- ## Key Commands
---
--- + `Alt+L, M`: Open this module for editing.
--- + `Alt+L, G`: Goto file being 'require'd on the current line.
--- + `Shift+Return`: Try to autocomplete an `if`, `for`, etc. statement with
--- `end`.
--- + `.`: When to the right of a known symbol, show an autocompletion list of
--- fields and functions.
--- + `:`: When to the right of a known symbol, show an autocompletion list of
--- functions only.
--- + `Ctrl+I`: (Windows and Linux) Autocomplete symbol.
--- + `~`: (Mac OSX) Autocomplete symbol.
--- + `Ctrl+H`: Show documentation for the selected symbol or the symbol under
--- the caret.
-
-local m_editing, m_run = _m.textadept.editing, _m.textadept.run
--- Comment string tables use lexer names.
-m_editing.comment_string.lua = '--'
--- Compile and Run command tables use file extensions.
-m_run.run_command.lua = 'lua %(filename)'
-m_run.error_detail.lua = {
- pattern = '^lua: (.-):(%d+): (.+)$',
- filename = 1, line = 2, message = 3
-}
-
----
--- Patterns for auto 'end' completion for control structures.
--- @class table
--- @name control_structure_patterns
--- @see try_to_autocomplete_end
-local control_structure_patterns = {
- '^%s*for', '^%s*function', '^%s*if', '^%s*repeat', '^%s*while',
- 'function%s*%b()%s*$', '^%s*local%s*function'
-}
-
----
--- Tries to autocomplete Lua's 'end' keyword for control structures like 'if',
--- 'while', 'for', etc.
--- @see control_structure_patterns
-function try_to_autocomplete_end()
- local buffer = buffer
- local line_num = buffer:line_from_position(buffer.current_pos)
- local line = buffer:get_line(line_num)
- for _, patt in ipairs(control_structure_patterns) do
- if line:find(patt) then
- local indent = buffer.line_indentation[line_num]
- buffer:begin_undo_action()
- buffer:new_line()
- buffer:new_line()
- buffer:add_text(patt:find('repeat') and 'until' or 'end')
- buffer.line_indentation[line_num + 1] = indent + buffer.indent
- buffer:line_up()
- buffer:line_end()
- buffer:end_undo_action()
- return true
- end
- end
- return false
-end
-
----
--- Determines the Lua file being 'require'd, searches through package.path for
--- that file, and opens it in Textadept.
-function goto_required()
- local line = buffer:get_cur_line()
- local patterns = { 'require%s*(%b())', 'require%s*(([\'"])[^%2]+%2)' }
- local file
- for _, patt in ipairs(patterns) do
- file = line:match(patt)
- if file then break end
- end
- if not file then return end
- file = file:sub(2, -2):gsub('%.', '/')
- for path in package.path:gmatch('[^;]+') do
- path = path:gsub('?', file)
- if lfs.attributes(path) then
- io.open_file(path:iconv('UTF-8', _CHARSET))
- break
- end
- end
-end
-
-events.connect('file_after_save',
- function() -- show syntax errors as annotations
- if buffer:get_lexer() == 'lua' then
- local buffer = buffer
- buffer:annotation_clear_all()
- local text = buffer:get_text()
- text = text:gsub('^#![^\n]+', '') -- ignore shebang line
- local _, err = loadstring(text)
- if err then
- local line, msg = err:match('^.-:(%d+):%s*(.+)$')
- if line then
- buffer.annotation_visible = 2
- buffer:annotation_set_text(line - 1, msg)
- buffer.annotation_style[line - 1] = 8 -- error style number
- buffer:goto_line(line - 1)
- end
- end
- end
- end)
-
--- Lua-specific key commands.
-local keys = _G.keys
-local luasense = _m.lua.adeptsense.sense
-if type(keys) == 'table' then
- keys.lua = {
- al = {
- m = { io.open_file,
- (_HOME..'/modules/lua/init.lua'):iconv('UTF-8', _CHARSET) },
- g = { goto_required },
- },
- ['s\n'] = { try_to_autocomplete_end },
- [not OSX and 'ci' or '~'] = { luasense.complete, luasense },
- ch = { luasense.show_apidoc, luasense },
- }
-end
diff --git a/modules/lua/init.lua b/modules/lua/init.lua
index eb633a95..5ec8d005 100644
--- a/modules/lua/init.lua
+++ b/modules/lua/init.lua
@@ -3,28 +3,195 @@
---
-- The lua module.
-- It provides utilities for editing Lua code.
+-- User tags are loaded from _USERHOME/modules/lua/tags and user apis are loaded
+-- from _USERHOME/modules/lua/api.
module('_m.lua', package.seeall)
-if type(_G.snippets) == 'table' then
+-- Markdown:
+-- ## Key Commands
+--
+-- + `Alt+L, M`: Open this module for editing.
+-- + `Alt+L, G`: Goto file being 'require'd on the current line.
+-- + `Shift+Return`: Try to autocomplete an `if`, `for`, etc. statement with
+-- `end`.
+-- + `.`: When to the right of a known symbol, show an autocompletion list of
+-- fields and functions.
+-- + `:`: When to the right of a known symbol, show an autocompletion list of
+-- functions only.
+-- + `Ctrl+I`: (Windows and Linux) Autocomplete symbol.
+-- + `~`: (Mac OSX) Autocomplete symbol.
+-- + `Ctrl+H`: Show documentation for the selected symbol or the symbol under
+-- the caret.
+--
+-- ## Fields
+--
+-- * `sense`: The Lua [Adeptsense](_m.textadept.adeptsense.html).
+
+local m_editing, m_run = _m.textadept.editing, _m.textadept.run
+-- Comment string tables use lexer names.
+m_editing.comment_string.lua = '--'
+-- Compile and Run command tables use file extensions.
+m_run.run_command.lua = 'lua %(filename)'
+m_run.error_detail.lua = {
+ pattern = '^lua: (.-):(%d+): (.+)$',
+ filename = 1, line = 2, message = 3
+}
+
---
--- Container for Lua-specific snippets.
--- @class table
--- @name snippets.lua
- _G.snippets.lua = {}
+-- Sets default buffer properties for Lua files.
+function set_buffer_properties()
+
end
-if type(_G.keys) == 'table' then
+-- Adeptsense.
+
+sense = _m.textadept.adeptsense.new('lua')
+sense.syntax.class_definition = 'module%s*%(?%s*[\'"]([%w_%.]+)'
+sense.syntax.symbol_chars = '[%w_%.:]'
+sense.syntax.type_declarations = {}
+sense.syntax.type_assignments = {
+ ['^[\'"]'] = 'string', -- foo = 'bar' or foo = "bar"
+ ['^([%w_%.]+)%s*$'] = '%1', -- foo = _m.textadept.adeptsense
+ ['^(_m%.textadept%.adeptsense)%.new'] = '%1'
+}
+sense.api_files = { _HOME..'/modules/lua/api' }
+sense:add_trigger('.')
+sense:add_trigger(':', false, true)
+
+-- script/update_doc generates a fake set of ctags used for autocompletion.
+sense.ctags_kinds = {
+ f = 'functions',
+ F = 'fields',
+ m = 'classes',
+ t = 'fields',
+}
+sense:load_ctags(_HOME..'/modules/lua/tags', true)
+
---
--- Container for Lua-specific key commands.
+-- Shows an autocompletion list for the symbol behind the caret.
+-- If the symbol contains a ':', only display functions. Otherwise, display
+-- both functions and fields.
+function sense:complete(only_fields, only_functions)
+ local line, pos = buffer:get_cur_line()
+ local symbol = line:sub(1, pos):match(self.syntax.symbol_chars..'*$')
+ return self.super.complete(self, false, symbol:find(':'))
+end
+
+-- Load user tags and apidoc.
+if lfs.attributes(_USERHOME..'/modules/lua/tags') then
+ sense:load_ctags(_USERHOME..'/modules/lua/tags')
+end
+if lfs.attributes(_USERHOME..'/modules/lua/api') then
+ sense.api_files[#sense.api_files + 1] = _USERHOME..'/modules/lua/api'
+end
+
+-- Commands.
+
+---
+-- Patterns for auto 'end' completion for control structures.
-- @class table
--- @name keys.lua
- _G.keys.lua = {}
+-- @name control_structure_patterns
+-- @see try_to_autocomplete_end
+local control_structure_patterns = {
+ '^%s*for', '^%s*function', '^%s*if', '^%s*repeat', '^%s*while',
+ 'function%s*%b()%s*$', '^%s*local%s*function'
+}
+
+---
+-- Tries to autocomplete Lua's 'end' keyword for control structures like 'if',
+-- 'while', 'for', etc.
+-- @see control_structure_patterns
+function try_to_autocomplete_end()
+ local buffer = buffer
+ local line_num = buffer:line_from_position(buffer.current_pos)
+ local line = buffer:get_line(line_num)
+ for _, patt in ipairs(control_structure_patterns) do
+ if line:find(patt) then
+ local indent = buffer.line_indentation[line_num]
+ buffer:begin_undo_action()
+ buffer:new_line()
+ buffer:new_line()
+ buffer:add_text(patt:find('repeat') and 'until' or 'end')
+ buffer.line_indentation[line_num + 1] = indent + buffer.indent
+ buffer:line_up()
+ buffer:line_end()
+ buffer:end_undo_action()
+ return true
+ end
+ end
+ return false
end
-require 'lua.adeptsense'
-require 'lua.commands'
-require 'lua.snippets'
+---
+-- Determines the Lua file being 'require'd, searches through package.path for
+-- that file, and opens it in Textadept.
+function goto_required()
+ local line = buffer:get_cur_line()
+ local patterns = { 'require%s*(%b())', 'require%s*(([\'"])[^%2]+%2)' }
+ local file
+ for _, patt in ipairs(patterns) do
+ file = line:match(patt)
+ if file then break end
+ end
+ if not file then return end
+ file = file:sub(2, -2):gsub('%.', '/')
+ for path in package.path:gmatch('[^;]+') do
+ path = path:gsub('?', file)
+ if lfs.attributes(path) then
+ io.open_file(path:iconv('UTF-8', _CHARSET))
+ break
+ end
+ end
+end
-function set_buffer_properties()
+events.connect('file_after_save',
+ function() -- show syntax errors as annotations
+ if buffer:get_lexer() == 'lua' then
+ local buffer = buffer
+ buffer:annotation_clear_all()
+ local text = buffer:get_text()
+ text = text:gsub('^#![^\n]+', '') -- ignore shebang line
+ local _, err = loadstring(text)
+ if err then
+ local line, msg = err:match('^.-:(%d+):%s*(.+)$')
+ if line then
+ buffer.annotation_visible = 2
+ buffer:annotation_set_text(line - 1, msg)
+ buffer.annotation_style[line - 1] = 8 -- error style number
+ buffer:goto_line(line - 1)
+ end
+ end
+ end
+ end)
+
+---
+-- Container for Lua-specific key commands.
+-- @class table
+-- @name _G.keys.lua
+_G.keys.lua = {
+ al = {
+ m = { io.open_file,
+ (_HOME..'/modules/lua/init.lua'):iconv('UTF-8', _CHARSET) },
+ g = { goto_required },
+ },
+ ['s\n'] = { try_to_autocomplete_end },
+ [not OSX and 'ci' or '~'] = { sense.complete, sense },
+ ch = { sense.show_apidoc, sense },
+}
+
+-- Snippets.
+if type(_G.snippets) == 'table' then
+---
+-- Container for Lua-specific snippets.
+-- @class table
+-- @name _G.snippets.lua
+ _G.snippets.lua = {
+ l = "local %1(expr)%2( = %3(value))",
+ p = "print(%0)",
+ f = "function %1(name)(%2(args))\n\t%0\nend",
+ ['for'] = "for i=%1(1), %2(10)%3(, -1) do\n\t%0\nend",
+ fori = "for %1(i), %2(val) in ipairs(%3(table)) do\n\t%0\nend",
+ forp = "for %1(k), %2(v) in pairs(%3(table)) do\n\t%0\nend",
+ }
end
diff --git a/modules/lua/snippets.lua b/modules/lua/snippets.lua
deleted file mode 100644
index 57b0ce89..00000000
--- a/modules/lua/snippets.lua
+++ /dev/null
@@ -1,19 +0,0 @@
--- Copyright 2007-2011 Mitchell mitchell<att>caladbolg.net. See LICENSE.
-
----
--- Snippets for the lua module.
-module('_m.lua.snippets', package.seeall)
-
-local snippets = _G.snippets
-
-if type(snippets) == 'table' then
- snippets.lua = {
- l = "local %1(expr)%2( = %3(value))",
- p = "print(%0)",
- f = "function %1(name)(%2(args))\n\t%0\nend",
- ['for'] = "for i=%1(1), %2(10)%3(, -1) do\n\t%0\nend",
- fori = "for %1(i), %2(val) in ipairs(%3(table)) do\n\t%0\nend",
- forp = "for %1(k), %2(v) in pairs(%3(table)) do\n\t%0\nend",
- }
-end
-
diff --git a/modules/textadept/adeptsense.lua b/modules/textadept/adeptsense.lua
index 560b20cb..01fb1ced 100644
--- a/modules/textadept/adeptsense.lua
+++ b/modules/textadept/adeptsense.lua
@@ -40,28 +40,17 @@ module('_m.textadept.adeptsense', package.seeall)
--
-- #### Introduction
--
--- In the language-specific module, create an Adeptsense module.
+-- Open the language-specific module for editing and create a new instance of an
+-- Adeptsense.
--
-- $> # from either _HOME or _USERHOME:
-- $> cd modules/lua/
--- $> textadept adeptsense.lua
---
--- The Adeptsense should look like the following:
+-- $> textadept init.lua
--
--- --- Adeptsense for the lua module.
--- module('_m.lua.adeptsense', package.seeall)
-- sense = _m.textadept.adeptsense.new('lua')
--
-- Where 'lua' is replaced by your language's name.
--
--- Then edit the module's `init.lua` to include the Adeptsense.
---
--- $> textadept init.lua
---
--- require 'lua.adeptsense' -- add this line
--- require 'lua.commands'
--- require 'lua.snippets'
---
-- #### Syntax Options
--
-- The syntax of different languages varies so the Adeptsense must be configured
@@ -261,7 +250,7 @@ module('_m.textadept.adeptsense', package.seeall)
-- Since Adeptsense ignores any tags not mapped to `classes`, `functions`, or
-- `fields` in [`ctags_kinds`](#ctags_kinds), it passes an unknown tag to the
-- [`handle_ctag()`](#handle_ctag) function. In this case, package (`p`) tags
--- are need to be handled.
+-- need to be handled.
--
-- function sense:handle_ctag(tag_name, file_name, ex_cmd, ext_fields)
-- if ext_fields:sub(1, 1) ~= 'p' then return end -- not a package
diff --git a/modules/textadept/bookmarks.lua b/modules/textadept/bookmarks.lua
index 072cca67..97121547 100644
--- a/modules/textadept/bookmarks.lua
+++ b/modules/textadept/bookmarks.lua
@@ -85,7 +85,7 @@ function goto()
line = buffer:marker_next(line + 1, 2^MARK_BOOKMARK)
until line < 0
local line = gui.filteredlist(L('Select Bookmark'), 'Bookmark', markers)
- if line then _m.textadept.editing.goto_line(tonumber(line:match('^%d+'))) end
+ if line then _m.textadept.editing.goto_line(line:match('^%d+')) end
end
if buffer then buffer:marker_set_back(MARK_BOOKMARK, MARK_BOOKMARK_COLOR) end