aboutsummaryrefslogtreecommitdiff
path: root/modules/textadept
diff options
context:
space:
mode:
authormitchell <70453897+667e-11@users.noreply.github.com>2016-04-15 20:43:48 -0400
committermitchell <70453897+667e-11@users.noreply.github.com>2016-04-15 20:43:48 -0400
commit25685922b5491703776d19259ed81f6ff7aaecd6 (patch)
tree9ee29e2253eb26b24e05a457db44284ea6001f34 /modules/textadept
parent70d0efc33c34dc3cbbc9ea4f54a0d87439e0ac83 (diff)
downloadtextadept-25685922b5491703776d19259ed81f6ff7aaecd6.tar.gz
textadept-25685922b5491703776d19259ed81f6ff7aaecd6.zip
Use function notation for menu and key commands.
As a result, the undocumented `textadept.keys.utils` has been removed. Those functions have been moved directly into menu definitions and their corresponding keys have been bound to those menu functions (this also shows menu key shortcuts properly). Therefore, "textadept.menu" should be loaded before "textadept.keys" now. Also, setting `textadept.menu.menubar = {}` must be done within an `events.INITIALIZED` handler.
Diffstat (limited to 'modules/textadept')
-rw-r--r--modules/textadept/command_entry.lua40
-rw-r--r--modules/textadept/init.lua2
-rw-r--r--modules/textadept/keys.lua459
-rw-r--r--modules/textadept/menu.lua394
4 files changed, 467 insertions, 428 deletions
diff --git a/modules/textadept/command_entry.lua b/modules/textadept/command_entry.lua
index fb8726cd..e511527a 100644
--- a/modules/textadept/command_entry.lua
+++ b/modules/textadept/command_entry.lua
@@ -18,10 +18,10 @@ local M = ui.command_entry
--
-- local function complete_lua() ... end
-- local function run_lua() ... end
--- keys['ce'] = {ui.command_entry.enter_mode, 'lua_command'}
+-- keys['ce'] = function() ui.command_entry.enter_mode('lua_command') end
-- keys.lua_command = {
-- ['\t'] = complete_lua,
--- ['\n'] = {ui.command_entry.finish_mode, run_lua}
+-- ['\n'] = function() return ui.command_entry.finish_mode(run_lua) end
-- }
--
-- In this case, `Ctrl+E` opens the command entry and enters "lua_command" key
@@ -43,18 +43,21 @@ module('ui.command_entry')]]
-- @class table
-- @name editing_keys
M.editing_keys = {__index = {
- [not OSX and 'cx' or 'mx'] = {buffer.cut, M},
- [not OSX and 'cc' or 'mc'] = {buffer.copy, M},
- [not OSX and 'cv' or 'mv'] = {buffer.paste, M},
- [not OSX and not CURSES and 'ca' or 'ma'] = {buffer.select_all, M},
- [not OSX and 'cz' or 'mz'] = {buffer.undo, M},
- [not OSX and 'cZ' or 'mZ'] = {buffer.redo, M}, cy = {buffer.redo, M},
+ -- Note: cannot use `M.cut`, `M.copy`, etc. since M is never considered the
+ -- global buffer.
+ [not OSX and 'cx' or 'mx'] = function() M:cut() end,
+ [not OSX and 'cc' or 'mc'] = function() M:copy() end,
+ [not OSX and 'cv' or 'mv'] = function() M:paste() end,
+ [not OSX and not CURSES and 'ca' or 'ma'] = function() M:select_all() end,
+ [not OSX and 'cz' or 'mz'] = function() M:undo() end,
+ [not OSX and 'cZ' or 'mZ'] = function() M:redo() end,
+ [not OSX and 'cy' or '\0'] = function() M:redo() end,
-- Movement keys.
- [(OSX or CURSES) and 'cf' or '\0'] = {buffer.char_right, M},
- [(OSX or CURSES) and 'cb' or '\0'] = {buffer.char_left, M},
- [(OSX or CURSES) and 'ca' or '\0'] = {buffer.vc_home, M},
- [(OSX or CURSES) and 'ce' or '\0'] = {buffer.line_end, M},
- [(OSX or CURSES) and 'cd' or '\0'] = {buffer.clear, M}
+ [(OSX or CURSES) and 'cf' or '\0'] = function() M:char_right() end,
+ [(OSX or CURSES) and 'cb' or '\0'] = function() M:char_left() end,
+ [(OSX or CURSES) and 'ca' or '\0'] = function() M:vc_home() end,
+ [(OSX or CURSES) and 'ce' or '\0'] = function() M:line_end() end,
+ [(OSX or CURSES) and 'cd' or '\0'] = function() M:clear() end
}}
---
@@ -69,7 +72,8 @@ M.editing_keys = {__index = {
-- default value is `'text'`.
-- @param height Optional number of lines to display in the command entry. The
-- default value is `1`.
--- @usage keys['ce'] = {ui.command_entry.enter_mode, 'command_entry'}
+-- @usage keys['ce'] =
+-- function() ui.command_entry.enter_mode('command_entry') end
-- @see _G.keys.MODE
-- @name enter_mode
function M.enter_mode(mode, lexer, height)
@@ -93,7 +97,8 @@ end
-- action with the entered text.
-- @param f Optional function to call. It should accept the command entry text
-- as an argument.
--- @usage keys['\n'] = {ui.command_entry.finish_mode, ui.print}
+-- @usage keys['\n'] =
+-- function() return ui.command_entry.finish_mode(ui.print) end
-- @name finish_mode
function M.finish_mode(f)
if M:auto_c_active() then return false end -- allow Enter to autocomplete
@@ -174,7 +179,10 @@ local function complete_lua()
end
-- Define key mode for entering Lua commands.
-keys.lua_command = {['\t'] = complete_lua, ['\n'] = {M.finish_mode, run_lua}}
+keys.lua_command = {
+ ['\t'] = complete_lua,
+ ['\n'] = function() return M.finish_mode(run_lua) end
+}
-- Configure the command entry's default properties.
events.connect(events.INITIALIZED, function()
diff --git a/modules/textadept/init.lua b/modules/textadept/init.lua
index d6db4cca..457cfa4e 100644
--- a/modules/textadept/init.lua
+++ b/modules/textadept/init.lua
@@ -19,7 +19,7 @@ M.session = require('textadept.session')
M.snippets = require('textadept.snippets')
-- These need to be loaded last.
-M.keys = require('textadept.keys')
M.menu = require('textadept.menu')
+M.keys = require('textadept.keys')
return M
diff --git a/modules/textadept/keys.lua b/modules/textadept/keys.lua
index 6e77911a..c392bc7e 100644
--- a/modules/textadept/keys.lua
+++ b/modules/textadept/keys.lua
@@ -5,9 +5,7 @@ local M = {}
--[[ This comment is for LuaDoc.
---
-- Defines key commands for Textadept.
--- This set of key commands is pretty standard among other text editors. If
--- applicable, load this module second to last in your *~/.textadept/init.lua*,
--- before `textadept.menu`.
+-- This set of key commands is pretty standard among other text editors.
--
-- ## Key Bindings
--
@@ -219,101 +217,6 @@ local M = {}
-- ‡: Ctrl+Enter in Win32 curses.
module('textadept.keys')]]
--- Utility functions.
-M.utils = {
- delete_word = function()
- textadept.editing.select_word()
- buffer:delete_back()
- end,
- autocomplete_symbol = function()
- textadept.editing.autocomplete(buffer:get_lexer(true))
- end,
- enclose_as_xml_tags = function()
- textadept.editing.enclose('<', '>')
- local pos = buffer.current_pos
- while buffer.char_at[pos - 1] ~= 60 do pos = pos - 1 end -- '<'
- buffer:insert_text(-1, '</'..buffer:text_range(pos, buffer.current_pos))
- end,
- find = function(in_files)
- ui.find.in_files = in_files
- ui.find.focus()
- end,
- select_command = function() textadept.menu.select_command() end,
- snapopen_filedir = function()
- if buffer.filename then io.snapopen(buffer.filename:match('^(.+)[/\\]')) end
- end,
- show_style = function()
- local pos = buffer.current_pos
- local char = buffer:text_range(pos, buffer:position_after(pos))
- local code = utf8.codepoint(char)
- local bytes = string.rep(' 0x%X', #char):format(char:byte(1, #char))
- local style = buffer.style_at[pos]
- local text = string.format("'%s' (U+%04X:%s)\n%s %s\n%s %s (%d)", char,
- code, bytes, _L['Lexer'], buffer:get_lexer(true),
- _L['Style'], buffer.style_name[style], style)
- buffer:call_tip_show(buffer.current_pos, text)
- end,
- set_indentation = function(i)
- buffer.tab_width = i
- events.emit(events.UPDATE_UI) -- for updating statusbar
- end,
- toggle_property = function(property, i)
- local state = buffer[property]
- if type(state) == 'boolean' then
- buffer[property] = not state
- elseif type(state) == 'number' then
- buffer[property] = state == 0 and (i or 1) or 0
- end
- events.emit(events.UPDATE_UI) -- for updating statusbar
- end,
- set_encoding = function(encoding)
- buffer:set_encoding(encoding)
- events.emit(events.UPDATE_UI) -- for updating statusbar
- end,
- set_eol_mode = function(mode)
- buffer.eol_mode = mode
- buffer:convert_eols(mode)
- events.emit(events.UPDATE_UI) -- for updating statusbar
- end,
- unsplit_all = function() while view:unsplit() do end end,
- grow = function()
- if view.size then view.size = view.size + buffer:text_height(0) end
- end,
- shrink = function()
- if view.size then view.size = view.size - buffer:text_height(0) end
- end,
- toggle_current_fold = function()
- buffer:toggle_fold(buffer:line_from_position(buffer.current_pos))
- end,
- reset_zoom = function() buffer.zoom = 0 end,
- open_webpage = function(url)
- local cmd = 'xdg-open "%s"'
- if WIN32 then
- cmd = 'start "" "%s"'
- elseif OSX then
- cmd = 'open "file://%s"'
- end
- spawn(cmd:format(url))
- end,
- cut_to_eol = function()
- buffer:line_end_extend()
- buffer:cut()
- end
-}
-
-local keys, buffer, view = keys, buffer, view
-local editing, utils = textadept.editing, M.utils
-local OSX, CURSES = OSX, CURSES
-
--- The following buffer functions need to be constantized in order for menu
--- items to identify the key associated with the functions.
-local menu_buffer_functions = {
- 'undo', 'redo', 'cut', 'copy', 'paste', 'line_duplicate', 'clear',
- 'select_all', 'upper_case', 'lower_case', 'move_selected_lines_up',
- 'move_selected_lines_down', 'zoom_in', 'zoom_out', 'colourise'
-}
-for _, f in ipairs(menu_buffer_functions) do buffer[f] = buffer[f] end
-
-- Windows and Linux key bindings.
--
-- Unassigned keys (~ denotes keys reserved by the operating system):
@@ -370,218 +273,228 @@ for _, f in ipairs(menu_buffer_functions) do buffer[f] = buffer[f] end
-- ADD = ''
-- Control, Meta, and 'a' = 'cma'
+local keys, OSX, GUI, CURSES, _L = keys, OSX, not CURSES, CURSES, _L
+
-- File.
-keys[not OSX and (not CURSES and 'cn' or 'cmn') or 'mn'] = buffer.new
+keys[not OSX and (GUI and 'cn' or 'cmn') or 'mn'] = buffer.new
keys[not OSX and 'co' or 'mo'] = io.open_file
-keys[not OSX and not CURSES and 'cao' or 'cmo'] = io.open_recent_file
-keys[not OSX and (not CURSES and 'cO' or 'mo') or 'mO'] = io.reload_file
+keys[not OSX and GUI and 'cao' or 'cmo'] = io.open_recent_file
+keys[not OSX and (GUI and 'cO' or 'mo') or 'mO'] = io.reload_file
keys[not OSX and 'cs' or 'ms'] = io.save_file
-keys[not OSX and (not CURSES and 'cS' or 'cms') or 'mS'] = io.save_file_as
+keys[not OSX and (GUI and 'cS' or 'cms') or 'mS'] = io.save_file_as
-- TODO: io.save_all_files
keys[not OSX and 'cw' or 'mw'] = io.close_buffer
-keys[not OSX and (not CURSES and 'cW' or 'cmw') or 'mW'] = io.close_all_buffers
+keys[not OSX and (GUI and 'cW' or 'cmw') or 'mW'] = io.close_all_buffers
-- TODO: textadept.sessions.load
-- TODO: textadept.sessions.save
keys[not OSX and 'cq' or 'mq'] = quit
-- Edit.
+local m_edit = textadept.menu.menubar[_L['_Edit']]
keys[not OSX and 'cz' or 'mz'] = buffer.undo
if CURSES then keys.mz = keys.cz end -- ^Z suspends in some terminals
if not OSX then keys.cy = buffer.redo end
-keys[not OSX and not CURSES and 'cZ' or 'mZ'] = buffer.redo
+keys[not OSX and GUI and 'cZ' or 'mZ'] = buffer.redo
keys[not OSX and 'cx' or 'mx'] = buffer.cut
keys[not OSX and 'cc' or 'mc'] = buffer.copy
keys[not OSX and 'cv' or 'mv'] = buffer.paste
-if not CURSES then keys[not OSX and 'cd' or 'md'] = buffer.line_duplicate end
+if GUI then keys[not OSX and 'cd' or 'md'] = buffer.line_duplicate end
keys.del = buffer.clear
-keys[not OSX and (not CURSES and 'adel' or 'mdel')
- or 'cdel'] = utils.delete_word
-keys[not OSX and not CURSES and 'ca' or 'ma'] = buffer.select_all
-keys[not CURSES and 'cm' or 'mm'] = editing.match_brace
-keys[not OSX and (not CURSES and 'c\n' or 'cmj')
- or 'cesc'] = {editing.autocomplete, 'word'}
-if CURSES and WIN32 then keys['c\n'] = keys['cmj'] end
-if not CURSES then
- keys[not OSX and 'caH' or 'mH'] = editing.highlight_word
+keys[not OSX and (GUI and 'adel' or 'mdel')
+ or 'cdel'] = m_edit[_L['D_elete Word']][2]
+keys[not OSX and GUI and 'ca' or 'ma'] = buffer.select_all
+keys[GUI and 'cm' or 'mm'] = textadept.editing.match_brace
+keys[not OSX and ((GUI or WIN32) and 'c\n' or 'cmj')
+ or 'cesc'] = m_edit[_L['Complete _Word']][2]
+if GUI then
+ keys[not OSX and 'caH' or 'mH'] = textadept.editing.highlight_word
end
-keys[not OSX and not CURSES and 'c/' or 'm/'] = editing.block_comment
-keys.ct = editing.transpose_chars
-keys[not OSX and (not CURSES and 'cJ' or 'mj') or 'cj'] = editing.join_lines
-keys[not OSX and (not CURSES and 'c|' or 'c\\')
- or 'm|'] = {ui.command_entry.enter_mode, 'filter_through', 'bash'}
+keys[not OSX and GUI and 'c/' or 'm/'] = textadept.editing.block_comment
+keys.ct = textadept.editing.transpose_chars
+keys[not OSX and (GUI and 'cJ' or 'mj') or 'cj'] = textadept.editing.join_lines
+keys[not OSX and (GUI and 'c|' or 'c\\')
+ or 'm|'] = m_edit[_L['_Filter Through']][2]
-- Select.
-keys[not CURSES and 'cM' or 'mM'] = {editing.match_brace, 'select'}
-keys[not OSX and not CURSES and 'c<'
- or 'm<'] = {editing.select_enclosed, '>', '<'}
-if not CURSES then
- keys[not OSX and 'c>' or 'm>'] = {editing.select_enclosed, '<', '>'}
+local m_sel = m_edit[_L['_Select']]
+keys[GUI and 'cM' or 'mM'] = m_sel[_L['Select to _Matching Brace']][2]
+keys[not OSX and GUI and 'c<'
+ or 'm<'] = m_sel[_L['Select between _XML Tags']][2]
+if GUI then
+ keys[not OSX and 'c>' or 'm>'] = m_sel[_L['Select in XML _Tag']][2]
end
-keys[not OSX and not CURSES and "c'"
- or "m'"] = {editing.select_enclosed, "'", "'"}
-keys[not OSX and not CURSES and 'c"'
- or 'm"'] = {editing.select_enclosed, '"', '"'}
-keys[not OSX and not CURSES and 'c('
- or 'm('] = {editing.select_enclosed, '(', ')'}
-keys[not OSX and not CURSES and 'c['
- or 'm['] = {editing.select_enclosed, '[', ']'}
-keys[not OSX and not CURSES and 'c{'
- or 'm{'] = {editing.select_enclosed, '{', '}'}
-keys[not OSX and (not CURSES and 'cD' or 'mW') or 'mD'] = editing.select_word
-keys[not OSX and not CURSES and 'cN' or 'mN'] = editing.select_line
-keys[not OSX and not CURSES and 'cP' or 'mP'] = editing.select_paragraph
+keys[not OSX and GUI and "c'"
+ or "m'"] = m_sel[_L['Select in _Single Quotes']][2]
+keys[not OSX and GUI and 'c"'
+ or 'm"'] = m_sel[_L['Select in _Double Quotes']][2]
+keys[not OSX and GUI and 'c(' or 'm('] = m_sel[_L['Select in _Parentheses']][2]
+keys[not OSX and GUI and 'c[' or 'm['] = m_sel[_L['Select in _Brackets']][2]
+keys[not OSX and GUI and 'c{' or 'm{'] = m_sel[_L['Select in B_races']][2]
+keys[not OSX and (GUI and 'cD' or 'mW') or 'mD'] = textadept.editing.select_word
+keys[not OSX and GUI and 'cN' or 'mN'] = textadept.editing.select_line
+keys[not OSX and GUI and 'cP' or 'mP'] = textadept.editing.select_paragraph
-- Selection.
-keys[not OSX and (not CURSES and 'cau' or 'cmu') or 'cu'] = buffer.upper_case
-keys[not OSX and (not CURSES and 'caU' or 'cml') or 'cU'] = buffer.lower_case
-keys[not OSX and (not CURSES and 'a<' or 'm>')
- or 'c<'] = utils.enclose_as_xml_tags
-if not CURSES then
- keys[not OSX and 'a>' or 'c>'] = {editing.enclose, '<', ' />'}
- keys[not OSX and "a'" or "c'"] = {editing.enclose, "'", "'"}
- keys[not OSX and 'a"' or 'c"'] = {editing.enclose, '"', '"'}
+m_sel = m_edit[_L['Selectio_n']]
+keys[not OSX and (GUI and 'cau' or 'cmu') or 'cu'] = buffer.upper_case
+keys[not OSX and (GUI and 'caU' or 'cml') or 'cU'] = buffer.lower_case
+keys[not OSX and (GUI and 'a<' or 'm>')
+ or 'c<'] = m_sel[_L['Enclose as _XML Tags']][2]
+if GUI then
+ keys[not OSX and 'a>' or 'c>'] = m_sel[_L['Enclose as Single XML _Tag']][2]
+ keys[not OSX and "a'" or "c'"] = m_sel[_L['Enclose in Single _Quotes']][2]
+ keys[not OSX and 'a"' or 'c"'] = m_sel[_L['Enclose in _Double Quotes']][2]
end
-keys[not OSX and (not CURSES and 'a(' or 'm)')
- or 'c('] = {editing.enclose, '(', ')'}
-keys[not OSX and (not CURSES and 'a[' or 'm]')
- or 'c['] = {editing.enclose, '[', ']'}
-keys[not OSX and (not CURSES and 'a{' or 'm}')
- or 'c{'] = {editing.enclose, '{', '}'}
+keys[not OSX and (GUI and 'a(' or 'm)')
+ or 'c('] = m_sel[_L['Enclose in _Parentheses']][2]
+keys[not OSX and (GUI and 'a[' or 'm]')
+ or 'c['] = m_sel[_L['Enclose in _Brackets']][2]
+keys[not OSX and (GUI and 'a{' or 'm}')
+ or 'c{'] = m_sel[_L['Enclose in B_races']][2]
keys.csup = buffer.move_selected_lines_up
keys.csdown = buffer.move_selected_lines_down
-- Search.
-keys[not OSX and not CURSES and 'cf' or 'mf'] = utils.find
-if CURSES then keys.mF = keys.mf end -- in case mf is used by GUI terminals
-keys[not OSX and not CURSES and 'cg' or 'mg'] = ui.find.find_next
-if not OSX and not CURSES then keys.f3 = keys.cg end
-keys[not OSX and not CURSES and 'cG' or 'mG'] = ui.find.find_prev
-if not OSX and not CURSES then keys.sf3 = keys.cG end
-keys[not OSX and (not CURSES and 'car' or 'mr') or 'cr'] = ui.find.replace
-keys[not OSX and (not CURSES and 'caR' or 'mR') or 'cR'] = ui.find.replace_all
+local m_search = textadept.menu.menubar[_L['_Search']]
+keys[not OSX and GUI and 'cf' or 'mf'] = m_search[_L['_Find']][2]
+if CURSES then keys.mF = keys.mf end -- mf is used by some GUI terminals
+keys[not OSX and GUI and 'cg' or 'mg'] = ui.find.find_next
+if not OSX and GUI then keys.f3 = keys.cg end
+keys[not OSX and GUI and 'cG' or 'mG'] = ui.find.find_prev
+if not OSX and GUI then keys.sf3 = keys.cG end
+keys[not OSX and (GUI and 'car' or 'mr') or 'cr'] = ui.find.replace
+keys[not OSX and (GUI and 'caR' or 'mR') or 'cR'] = ui.find.replace_all
-- Find Next is an when find pane is focused in GUI.
-- Find Prev is ap when find pane is focused in GUI.
-- Replace is ar when find pane is focused in GUI.
-- Replace All is aa when find pane is focused in GUI.
-keys[not OSX and not CURSES and 'caf' or 'cmf'] = ui.find.find_incremental
-if not CURSES then keys[not OSX and 'cF' or 'mF'] = {utils.find, true} end
+keys[not OSX and GUI and 'caf' or 'cmf'] = ui.find.find_incremental
+if GUI then
+ keys[not OSX and 'cF' or 'mF'] = m_search[_L['Find in Fi_les']][2]
+end
-- Find in Files is ai when find pane is focused in GUI.
-if not CURSES then
- keys[not OSX and 'cag' or 'cmg'] = {ui.find.goto_file_found, false, true}
- keys[not OSX and 'caG' or 'cmG'] = {ui.find.goto_file_found, false, false}
+if GUI then
+ keys[not OSX and 'cag' or 'cmg'] = m_search[_L['Goto Nex_t File Found']][2]
+ keys[not OSX and 'caG'
+ or 'cmG'] = m_search[_L['Goto Previou_s File Found']][2]
end
-keys[not OSX and 'cj' or 'mj'] = editing.goto_line
+keys[not OSX and 'cj' or 'mj'] = textadept.editing.goto_line
-- Tools.
-keys[not OSX and (not CURSES and 'ce' or 'mc')
- or 'me'] = {ui.command_entry.enter_mode, 'lua_command', 'lua'}
-keys[not OSX and (not CURSES and 'cE' or 'mC') or 'mE'] = utils.select_command
+local m_tools = textadept.menu.menubar[_L['_Tools']]
+keys[not OSX and (GUI and 'ce' or 'mc')
+ or 'me'] = m_tools[_L['Command _Entry']][2]
+keys[not OSX and (GUI and 'cE' or 'mC')
+ or 'mE'] = m_tools[_L['Select Co_mmand']][2]
keys[not OSX and 'cr' or 'mr'] = textadept.run.run
-keys[not OSX and (not CURSES and 'cR' or 'cmr') or 'mR'] = textadept.run.compile
-keys[not OSX and (not CURSES and 'cB' or 'cmb') or 'mB'] = textadept.run.build
-keys[not OSX and (not CURSES and 'cX' or 'cmx') or 'mX'] = textadept.run.stop
-keys[not OSX and (not CURSES and 'cae' or 'mx')
- or 'cme'] = {textadept.run.goto_error, false, true}
-keys[not OSX and (not CURSES and 'caE' or 'mX')
- or 'cmE'] = {textadept.run.goto_error, false, false}
+keys[not OSX and (GUI and 'cR' or 'cmr') or 'mR'] = textadept.run.compile
+keys[not OSX and (GUI and 'cB' or 'cmb') or 'mB'] = textadept.run.build
+keys[not OSX and (GUI and 'cX' or 'cmx') or 'mX'] = textadept.run.stop
+keys[not OSX and (GUI and 'cae' or 'mx')
+ or 'cme'] = m_tools[_L['_Next Error']][2]
+keys[not OSX and (GUI and 'caE' or 'mX')
+ or 'cmE'] = m_tools[_L['_Previous Error']][2]
+-- Bookmark.
+local m_bookmark = m_tools[_L['_Bookmark']]
+keys[not OSX and (GUI and 'cf2' or 'f1') or 'mf2'] = textadept.bookmarks.toggle
+keys[not OSX and (GUI and 'csf2' or 'f6') or 'msf2'] = textadept.bookmarks.clear
+keys.f2 = m_bookmark[_L['_Next Bookmark']][2]
+keys[GUI and 'sf2' or 'f3'] = m_bookmark[_L['_Previous Bookmark']][2]
+keys[GUI and 'af2' or 'f4'] = textadept.bookmarks.goto_mark
+-- Snapopen.
+local m_snapopen = m_tools[_L['Snap_open']]
+keys[not OSX and 'cu' or 'mu'] = m_snapopen[_L['Snapopen _User Home']][2]
+-- TODO: m_snapopen[_L['Snapopen _Textadept Home']][2]
+keys[not OSX and (GUI and 'caO' or 'mO')
+ or 'cmO'] = m_snapopen[_L['Snapopen _Current Directory']][2]
+keys[not OSX and (GUI and 'caP' or 'cmp') or 'cmP'] = io.snapopen
-- Snippets.
-keys[not OSX and (not CURSES and 'ck' or 'mk')
- or 'a\t'] = textadept.snippets._select
+keys[not OSX and (GUI and 'ck' or 'mk') or 'a\t'] = textadept.snippets._select
keys['\t'] = textadept.snippets._insert
keys['s\t'] = textadept.snippets._previous
-keys[not OSX and (not CURSES and 'cK' or 'mK')
+keys[not OSX and (GUI and 'cK' or 'mK')
or 'as\t'] = textadept.snippets._cancel_current
--- Bookmark.
-keys[not OSX and (not CURSES and 'cf2' or 'f1')
- or 'mf2'] = textadept.bookmarks.toggle
-keys[not OSX and (not CURSES and 'csf2' or 'f6')
- or 'msf2'] = textadept.bookmarks.clear
-keys.f2 = {textadept.bookmarks.goto_mark, true}
-keys[not CURSES and 'sf2' or 'f3'] = {textadept.bookmarks.goto_mark, false}
-keys[not CURSES and 'af2' or 'f4'] = textadept.bookmarks.goto_mark
--- Snapopen.
-keys[not OSX and 'cu' or 'mu'] = {io.snapopen, _USERHOME}
--- TODO: {io.snapopen, _HOME}
-keys[not OSX and (not CURSES and 'caO' or 'mO')
- or 'cmO'] = utils.snapopen_filedir
-keys[not OSX and (not CURSES and 'caP' or 'cmp') or 'cmP'] = io.snapopen
-- Other.
-keys[not OSX and ((not CURSES or WIN32) and 'c ' or 'c@')
- or 'aesc'] = utils.autocomplete_symbol
-keys[not CURSES and 'ch' or 'mh'] = textadept.editing.show_documentation
-if CURSES then keys.mH = keys.mh end -- in case mh is used by GUI terminals
-keys[not OSX and (not CURSES and 'ci' or 'mI') or 'mi'] = utils.show_style
+keys[not OSX and ((GUI or WIN32) and 'c ' or 'c@')
+ or 'aesc'] = m_tools[_L['_Complete Symbol']][2]
+keys[GUI and 'ch' or 'mh'] = textadept.editing.show_documentation
+if CURSES then keys.mH = keys.mh end -- mh is used by some GUI terminals
+keys[not OSX and (GUI and 'ci' or 'mI') or 'mi'] = m_tools[_L['Show St_yle']][2]
-- Buffer.
-keys[not CURSES and 'c\t' or 'mn'] = {view.goto_buffer, view, 1, true}
-keys[not CURSES and 'cs\t' or 'mp'] = {view.goto_buffer, view, -1, true}
-keys[not OSX and not CURSES and 'cb' or 'mb'] = ui.switch_buffer
-if CURSES then keys.mB = keys.mb end -- in case mb is used by GUI terminals
+local m_buffer = textadept.menu.menubar[_L['_Buffer']]
+keys[GUI and 'c\t' or 'mn'] = m_buffer[_L['_Next Buffer']][2]
+keys[GUI and 'cs\t' or 'mp'] = m_buffer[_L['_Previous Buffer']][2]
+keys[not OSX and GUI and 'cb' or 'mb'] = ui.switch_buffer
+if CURSES then keys.mB = keys.mb end -- mb is used by some GUI terminals
-- Indentation.
--- TODO: {utils.set_indentation, 2}
--- TODO: {utils.set_indentation, 3}
--- TODO: {utils.set_indentation, 4}
--- TODO: {utils.set_indentation, 8}
-keys[not OSX and (not CURSES and 'caT' or 'mt')
- or 'cT'] = {utils.toggle_property, 'use_tabs'}
-if CURSES then keys.mT = keys.mt end -- in case mt is used by GUI terminals
-keys[not OSX and (not CURSES and 'cai' or 'mi')
- or 'ci'] = editing.convert_indentation
+local m_indentation = m_buffer[_L['_Indentation']]
+-- TODO: m_indentation[_L['Tab width: _2']][2]
+-- TODO: m_indentation[_L['Tab width: _3']][2]
+-- TODO: m_indentation[_L['Tab width: _4']][2]
+-- TODO: m_indentation[_L['Tab width: _8']][2]
+keys[not OSX and (GUI and 'caT' or 'mt')
+ or 'cT'] = m_indentation[_L['_Toggle Use Tabs']][2]
+if CURSES then keys.mT = keys.mt end -- mt is used by some GUI terminals
+keys[not OSX and (GUI and 'cai' or 'mi')
+ or 'ci'] = textadept.editing.convert_indentation
-- EOL Mode.
--- TODO: {utils.set_eol_mode, buffer.EOL_CRLF}
--- TODO: {utils.set_eol_mode, buffer.EOL_CR}
--- TODO: {utils.set_eol_mode, buffer.EOL_LF}
+-- TODO: m_buffer[_L['_EOL Mode']][_L['CRLF']][2]
+-- TODO: m_buffer[_L['_EOL Mode']][_L['CR']][2]
+-- TODO: m_buffer[_L['_EOL Mode']][_L['LF']][2]
-- Encoding.
--- TODO: {utils.set_encoding, 'UTF-8'}
--- TODO: {utils.set_encoding, 'ASCII'}
--- TODO: {utils.set_encoding, 'ISO-8859-1'}
--- TODO: {utils.set_encoding, 'MacRoman'}
--- TODO: {utils.set_encoding, 'UTF-16LE'}
-keys[not OSX and not CURSES and 'cL'
- or 'mL'] = textadept.file_types.select_lexer
-keys.f5 = {buffer.colourise, buffer, 0, -1}
+-- TODO: m_buffer[_L['E_ncoding']][_L['_UTF-8 Encoding']][2]
+-- TODO: m_buffer[_L['E_ncoding']][_L['_ASCII Encoding']][2]
+-- TODO: m_buffer[_L['E_ncoding']][_L['_ISO-8859-1 Encoding']][2]
+-- TODO: m_buffer[_L['E_ncoding']][_L['_MacRoman Encoding']][2]
+-- TODO: m_buffer[_L['E_ncoding']][_L['UTF-1_6 Encoding']][2]
+if GUI then
+ keys[not OSX and 'ca\n' or 'c\n'] = m_buffer[_L['Toggle View _EOL']][2]
+ keys[not OSX and 'ca\\' or 'c\\'] = m_buffer[_L['Toggle _Wrap Mode']][2]
+ keys[not OSX and 'caS' or 'cS'] = m_buffer[_L['Toggle View White_space']][2]
+end
+keys[not OSX and GUI and 'cL' or 'mL'] = textadept.file_types.select_lexer
+keys.f5 = m_buffer[_L['_Refresh Syntax Highlighting']][2]
if CURSES then keys.cl = keys.f5 end
-- View.
-local view_next, view_prev = {ui.goto_view, 1, true}, {ui.goto_view, -1, true}
-local view_splith, view_splitv = {view.split, view}, {view.split, view, true}
-local view_unsplit = {view.unsplit, view}
-if not CURSES then
- keys[not OSX and 'can' or 'ca\t'] = view_next
- keys[not OSX and 'cap' or 'cas\t'] = view_prev
- keys[not OSX and 'cas' or 'cs'] = view_splith
- if not OSX then keys.cah = view_splith end
- keys[not OSX and 'cav' or 'cv'] = view_splitv
- keys[not OSX and 'caw' or 'cw'] = view_unsplit
- keys[not OSX and 'caW' or 'cW'] = utils.unsplit_all
- keys[not OSX and 'ca+' or 'c+'] = utils.grow
- keys[not OSX and 'ca=' or 'c='] = utils.grow
- keys[not OSX and 'ca-' or 'c-'] = utils.shrink
+local m_view = textadept.menu.menubar[_L['_View']]
+if GUI then
+ keys[not OSX and 'can' or 'ca\t'] = m_view[_L['_Next View']][2]
+ keys[not OSX and 'cap' or 'cas\t'] = m_view[_L['_Previous View']][2]
+ keys[not OSX and 'cas' or 'cs'] = m_view[_L['Split View _Horizontal']][2]
+ if not OSX then keys.cah = keys.cas end
+ keys[not OSX and 'cav' or 'cv'] = m_view[_L['Split View _Vertical']][2]
+ keys[not OSX and 'caw' or 'cw'] = m_view[_L['_Unsplit View']][2]
+ keys[not OSX and 'caW' or 'cW'] = m_view[_L['Unsplit _All Views']][2]
+ keys[not OSX and 'ca+' or 'c+'] = m_view[_L['_Grow View']][2]
+ keys[not OSX and 'ca=' or 'c='] = keys[not OSX and 'ca+' or 'c+']
+ keys[not OSX and 'ca-' or 'c-'] = m_view[_L['Shrin_k View']][2]
else
keys.cmv = {
- n = view_next, p = view_prev,
- s = view_splith, v = view_splitv,
- w = view_unsplit, W = utils.unsplit_all,
- ['+'] = utils.grow, ['='] = utils.grow, ['-'] = utils.shrink
+ n = m_view[_L['_Next View']][2],
+ p = m_view[_L['_Previous View']][2],
+ s = m_view[_L['Split View _Horizontal']][2],
+ v = m_view[_L['Split View _Vertical']][2],
+ w = m_view[_L['_Unsplit View']][2],
+ W = m_view[_L['Unsplit _All Views']][2],
+ ['+'] = m_view[_L['_Grow View']][2],
+ ['-'] = m_view[_L['Shrin_k View']][2]
}
- if not OSX then keys.cmv.h = view_splith end
+ if not OSX then keys.cmv.h = keys.cmv.s end
+ keys.cmv['='] = keys.cmv['+']
end
-keys[not OSX and not CURSES and 'c*' or 'm*'] = utils.toggle_current_fold
-if not CURSES then
- keys[not OSX and 'ca\n' or 'c\n'] = {utils.toggle_property, 'view_eol'}
- keys[not OSX and 'ca\\' or 'c\\'] = {utils.toggle_property, 'wrap_mode'}
- keys[not OSX and 'caI' or 'cI'] =
- {utils.toggle_property, 'indentation_guides'}
- keys[not OSX and 'caS' or 'cS'] = {utils.toggle_property, 'view_ws'}
- keys[not OSX and 'caV' or 'cV'] =
- {utils.toggle_property, 'virtual_space_options', buffer.VS_USERACCESSIBLE}
+keys[not OSX and GUI and 'c*' or 'm*'] = m_view[_L['Toggle Current _Fold']][2]
+if GUI then
+ keys[not OSX and 'caI' or 'cI'] = m_view[_L['Toggle Show In_dent Guides']][2]
+ keys[not OSX and 'caV' or 'cV'] = m_view[_L['Toggle _Virtual Space']][2]
end
-keys[not OSX and not CURSES and 'c=' or 'm='] = buffer.zoom_in
-keys[not OSX and not CURSES and 'c-' or 'm-'] = buffer.zoom_out
-keys[not OSX and not CURSES and 'c0' or 'm0'] = utils.reset_zoom
+keys[not OSX and GUI and 'c=' or 'm='] = buffer.zoom_in
+keys[not OSX and GUI and 'c-' or 'm-'] = buffer.zoom_out
+keys[not OSX and GUI and 'c0' or 'm0'] = m_view[_L['_Reset Zoom']][2]
-- Help.
-if not CURSES then
- keys.f1 = {utils.open_webpage, _HOME..'/doc/manual.html'}
- keys.sf1 = {utils.open_webpage, _HOME..'/doc/api.html'}
+if GUI then
+ keys.f1 = textadept.menu.menubar[_L['_Help']][_L['Show _Manual']][2]
+ keys.sf1 = textadept.menu.menubar[_L['_Help']][_L['Show _LuaDoc']][2]
end
-- Movement commands.
@@ -596,13 +509,16 @@ if OSX then
keys.ce, keys.cE = buffer.line_end, buffer.line_end_extend
keys.aright, keys.aleft = buffer.word_right, buffer.word_left
keys.cd = buffer.clear
- keys.ck = utils.cut_to_eol
+ keys.ck = function()
+ buffer:line_end_extend()
+ buffer:cut()
+ end
keys.cl = buffer.vertical_centre_caret
- -- GTKOSX reports Fn-key as a single keycode which confuses Scintilla. Do
+ -- GTK-OSX reports Fn-key as a single keycode which confuses Scintilla. Do
-- not propagate it.
keys.fn = function() return true end
elseif CURSES then
- keys['c^'] = function() _G.buffer.selection_mode = 0 end
+ keys['c^'] = function() buffer.selection_mode = 0 end
keys['c]'] = buffer.swap_main_anchor_caret
keys.cf, keys.cb = buffer.char_right, buffer.char_left
keys.cn, keys.cp = buffer.line_down, buffer.line_up
@@ -610,13 +526,18 @@ elseif CURSES then
keys.mA, keys.mE = buffer.vc_home_extend, buffer.line_end_extend
keys.mU, keys.mD = buffer.page_up_extend, buffer.page_down_extend
keys.cma, keys.cme = buffer.document_start, buffer.document_end
- keys.cd, keys.md = buffer.clear, utils.delete_word
- keys.ck = utils.cut_to_eol
+ keys.cd, keys.md = buffer.clear, keys.mdel
+ keys.ck = function()
+ buffer:line_end_extend()
+ buffer:cut()
+ end
end
-- Modes.
keys.filter_through = {
- ['\n'] = {ui.command_entry.finish_mode, editing.filter_through},
+ ['\n'] = function()
+ return ui.command_entry.finish_mode(textadept.editing.filter_through)
+ end,
}
keys.find_incremental = {
['\n'] = function()
@@ -638,7 +559,7 @@ setmetatable(keys.find_incremental, {__index = function(_, k)
ui.find.find_incremental(ui.command_entry:get_text()..k, true)
end})
-- Show documentation for symbols in the Lua command entry.
-keys.lua_command[not CURSES and 'ch' or 'mh'] = function()
+keys.lua_command[GUI and 'ch' or 'mh'] = function()
-- Temporarily change _G.buffer since ui.command_entry is the "active" buffer.
local orig_buffer = _G.buffer
_G.buffer = ui.command_entry
@@ -647,10 +568,16 @@ keys.lua_command[not CURSES and 'ch' or 'mh'] = function()
end
if OSX or CURSES then
-- UTF-8 input.
- keys.utf8_input = {['\n'] = {ui.command_entry.finish_mode, function(code)
- _G.buffer:add_text(utf8.char(tonumber(code, 16)))
- end}}
- keys[OSX and 'mU' or 'mu'] = {ui.command_entry.enter_mode, 'utf8_input'}
+ keys.utf8_input = {
+ ['\n'] = function()
+ return ui.command_entry.finish_mode(function(code)
+ buffer:add_text(utf8.char(tonumber(code, 16)))
+ end)
+ end
+ }
+ keys[OSX and 'mU' or 'mu'] = function()
+ ui.command_entry.enter_mode('utf8_input')
+ end
end
return M
diff --git a/modules/textadept/menu.lua b/modules/textadept/menu.lua
index f2bd2d17..acec62b3 100644
--- a/modules/textadept/menu.lua
+++ b/modules/textadept/menu.lua
@@ -10,25 +10,54 @@ local M = {}
-- place. A menu item itself is a table whose first element is a menu label and
-- whose second element is a menu command to run. Submenus have `title` keys
-- assigned to string text.
--- If applicable, load this module last in your *~/.textadept/init.lua*, after
--- [`textadept.keys`]() since it looks up defined key commands to show them in
--- menus.
module('textadept.menu')]]
-local _L, buffer, view = _L, buffer, view
-local editing, utils = textadept.editing, textadept.keys.utils
+local _L = _L
local SEPARATOR = {''}
+-- The following buffer functions need to be constantized in order for menu
+-- items to identify the key associated with the functions.
+local menu_buffer_functions = {
+ 'undo', 'redo', 'cut', 'copy', 'paste', 'line_duplicate', 'clear',
+ 'select_all', 'upper_case', 'lower_case', 'move_selected_lines_up',
+ 'move_selected_lines_down', 'zoom_in', 'zoom_out', 'colourise'
+}
+for i = 1, #menu_buffer_functions do
+ buffer[menu_buffer_functions[i]] = buffer[menu_buffer_functions[i]]
+end
+
+-- Commonly used functions in menu commands.
+local sel_enc = textadept.editing.select_enclosed
+local enc = textadept.editing.enclose
+local function set_indentation(i)
+ buffer.tab_width = i
+ events.emit(events.UPDATE_UI) -- for updating statusbar
+end
+local function set_eol_mode(mode)
+ buffer.eol_mode = mode
+ buffer:convert_eols(mode)
+ events.emit(events.UPDATE_UI) -- for updating statusbar
+end
+local function set_encoding(encoding)
+ buffer:set_encoding(encoding)
+ events.emit(events.UPDATE_UI) -- for updating statusbar
+end
+local function open_page(url)
+ local cmd = (WIN32 and 'start ""') or (OSX and 'open') or 'xdg-open'
+ spawn(string.format('%s "%s"', cmd, not OSX and url or 'file://'..url))
+end
+
---
-- The default main menubar.
-- Individual menus, submenus, and menu items can be retrieved by name in
-- addition to table index number.
-- @class table
-- @name menubar
--- @usage textadept.menubar[_L['_File']]['_New'] -- returns {'_New', buffer.new}
--- @usage textadept.menubar[_L['_File']]['_New'][2] = function() ... end
+-- @usage textadept.menu.menubar[_L['_File']][_L['_New']]
+-- @usage textadept.menu.menubar[_L['_File']][_L['_New']][2] = function() .. end
local default_menubar = {
- { title = _L['_File'],
+ {
+ title = _L['_File'],
{_L['_New'], buffer.new},
{_L['_Open'], io.open_file},
{_L['Open _Recent...'], io.open_recent_file},
@@ -43,9 +72,10 @@ local default_menubar = {
{_L['Loa_d Session...'], textadept.session.load},
{_L['Sav_e Session...'], textadept.session.save},
SEPARATOR,
- {_L['_Quit'], quit},
+ {_L['_Quit'], quit}
},
- { title = _L['_Edit'],
+ {
+ title = _L['_Edit'],
{_L['_Undo'], buffer.undo},
{_L['_Redo'], buffer.redo},
SEPARATOR,
@@ -54,161 +84,241 @@ local default_menubar = {
{_L['_Paste'], buffer.paste},
{_L['Duplicate _Line'], buffer.line_duplicate},
{_L['_Delete'], buffer.clear},
- {_L['D_elete Word'], utils.delete_word},
+ {_L['D_elete Word'], function()
+ textadept.editing.select_word()
+ buffer:delete_back()
+ end},
{_L['Select _All'], buffer.select_all},
SEPARATOR,
- {_L['_Match Brace'], editing.match_brace},
- {_L['Complete _Word'], {editing.autocomplete, 'word'}},
- {_L['_Highlight Word'], editing.highlight_word},
- {_L['Toggle _Block Comment'], editing.block_comment},
- {_L['T_ranspose Characters'], editing.transpose_chars},
- {_L['_Join Lines'], editing.join_lines},
- {_L['_Filter Through'],
- {ui.command_entry.enter_mode, 'filter_through', 'bash'}},
- { title = _L['_Select'],
- {_L['Select to _Matching Brace'], {editing.match_brace, 'select'}},
- {_L['Select between _XML Tags'], {editing.select_enclosed, '>', '<'}},
- {_L['Select in XML _Tag'], {editing.select_enclosed, '<', '>'}},
- {_L['Select in _Single Quotes'], {editing.select_enclosed, "'", "'"}},
- {_L['Select in _Double Quotes'], {editing.select_enclosed, '"', '"'}},
- {_L['Select in _Parentheses'], {editing.select_enclosed, '(', ')'}},
- {_L['Select in _Brackets'], {editing.select_enclosed, '[', ']'}},
- {_L['Select in B_races'], {editing.select_enclosed, '{', '}'}},
- {_L['Select _Word'], editing.select_word},
- {_L['Select _Line'], editing.select_line},
- {_L['Select Para_graph'], editing.select_paragraph},
+ {_L['_Match Brace'], textadept.editing.match_brace},
+ {_L['Complete _Word'], function()
+ textadept.editing.autocomplete('word')
+ end},
+ {_L['_Highlight Word'], textadept.editing.highlight_word},
+ {_L['Toggle _Block Comment'], textadept.editing.block_comment},
+ {_L['T_ranspose Characters'], textadept.editing.transpose_chars},
+ {_L['_Join Lines'], textadept.editing.join_lines},
+ {_L['_Filter Through'], function()
+ ui.command_entry.enter_mode('filter_through', 'bash')
+ end},
+ {
+ title = _L['_Select'],
+ {_L['Select to _Matching Brace'], function()
+ textadept.editing.match_brace('select')
+ end},
+ {_L['Select between _XML Tags'], function() sel_enc('>', '<') end},
+ {_L['Select in XML _Tag'], function() sel_enc('<', '>') end},
+ {_L['Select in _Single Quotes'], function() sel_enc("'", "'") end},
+ {_L['Select in _Double Quotes'], function() sel_enc('"', '"') end},
+ {_L['Select in _Parentheses'], function() sel_enc('(', ')') end},
+ {_L['Select in _Brackets'], function() sel_enc('[', ']') end},
+ {_L['Select in B_races'], function() sel_enc('{', '}') end},
+ {_L['Select _Word'], textadept.editing.select_word},
+ {_L['Select _Line'], textadept.editing.select_line},
+ {_L['Select Para_graph'], textadept.editing.select_paragraph}
},
- { title = _L['Selectio_n'],
+ {
+ title = _L['Selectio_n'],
{_L['_Upper Case Selection'], buffer.upper_case},
{_L['_Lower Case Selection'], buffer.lower_case},
SEPARATOR,
- {_L['Enclose as _XML Tags'], utils.enclose_as_xml_tags},
- {_L['Enclose as Single XML _Tag'], {editing.enclose, '<', ' />'}},
- {_L['Enclose in Single _Quotes'], {editing.enclose, "'", "'"}},
- {_L['Enclose in _Double Quotes'], {editing.enclose, '"', '"'}},
- {_L['Enclose in _Parentheses'], {editing.enclose, '(', ')'}},
- {_L['Enclose in _Brackets'], {editing.enclose, '[', ']'}},
- {_L['Enclose in B_races'], {editing.enclose, '{', '}'}},
+ {_L['Enclose as _XML Tags'], function()
+ enc('<', '>')
+ local pos = buffer.current_pos
+ while buffer.char_at[pos - 1] ~= 60 do pos = pos - 1 end -- '<'
+ buffer:insert_text(-1, '</'..buffer:text_range(pos, buffer.current_pos))
+ end},
+ {_L['Enclose as Single XML _Tag'], function() enc('<', ' />') end},
+ {_L['Enclose in Single _Quotes'], function() enc("'", "'") end},
+ {_L['Enclose in _Double Quotes'], function() enc('"', '"') end},
+ {_L['Enclose in _Parentheses'], function() enc('(', ')') end},
+ {_L['Enclose in _Brackets'], function() enc('[', ']') end},
+ {_L['Enclose in B_races'], function() enc('{', '}') end},
SEPARATOR,
{_L['_Move Selected Lines Up'], buffer.move_selected_lines_up},
- {_L['Move Selected Lines Do_wn'], buffer.move_selected_lines_down},
- },
+ {_L['Move Selected Lines Do_wn'], buffer.move_selected_lines_down}
+ }
},
- { title = _L['_Search'],
- {_L['_Find'], utils.find},
+ {
+ title = _L['_Search'],
+ {_L['_Find'], function()
+ ui.find.in_files = false
+ ui.find.focus()
+ end},
{_L['Find _Next'], ui.find.find_next},
{_L['Find _Previous'], ui.find.find_prev},
{_L['_Replace'], ui.find.replace},
{_L['Replace _All'], ui.find.replace_all},
{_L['Find _Incremental'], ui.find.find_incremental},
SEPARATOR,
- {_L['Find in Fi_les'], {utils.find, true}},
- {_L['Goto Nex_t File Found'], {ui.find.goto_file_found, false, true}},
- {_L['Goto Previou_s File Found'], {ui.find.goto_file_found, false, false}},
+ {_L['Find in Fi_les'], function()
+ ui.find.in_files = true
+ ui.find.focus()
+ end},
+ {_L['Goto Nex_t File Found'], function()
+ ui.find.goto_file_found(false, true)
+ end},
+ {_L['Goto Previou_s File Found'], function()
+ ui.find.goto_file_found(false, false)
+ end},
SEPARATOR,
- {_L['_Jump to'], editing.goto_line},
+ {_L['_Jump to'], textadept.editing.goto_line}
},
- { title = _L['_Tools'],
- {_L['Command _Entry'], {ui.command_entry.enter_mode, 'lua_command', 'lua'}},
- {_L['Select Co_mmand'], utils.select_command},
+ {
+ title = _L['_Tools'],
+ {_L['Command _Entry'], function()
+ ui.command_entry.enter_mode('lua_command', 'lua')
+ end},
+ {_L['Select Co_mmand'], function() M.select_command() end},
SEPARATOR,
{_L['_Run'], textadept.run.run},
{_L['_Compile'], textadept.run.compile},
{_L['Buil_d'], textadept.run.build},
{_L['S_top'], textadept.run.stop},
- {_L['_Next Error'], {textadept.run.goto_error, false, true}},
- {_L['_Previous Error'], {textadept.run.goto_error, false, false}},
+ {_L['_Next Error'], function() textadept.run.goto_error(false, true) end},
+ {_L['_Previous Error'], function()
+ textadept.run.goto_error(false, false)
+ end},
SEPARATOR,
- { title = _L['_Bookmark'],
+ {
+ title = _L['_Bookmark'],
{_L['_Toggle Bookmark'], textadept.bookmarks.toggle},
{_L['_Clear Bookmarks'], textadept.bookmarks.clear},
- {_L['_Next Bookmark'], {textadept.bookmarks.goto_mark, true}},
- {_L['_Previous Bookmark'], {textadept.bookmarks.goto_mark, false}},
+ {_L['_Next Bookmark'], function()
+ textadept.bookmarks.goto_mark(true)
+ end},
+ {_L['_Previous Bookmark'], function()
+ textadept.bookmarks.goto_mark(false)
+ end},
{_L['_Goto Bookmark...'], textadept.bookmarks.goto_mark},
},
- { title = _L['Snap_open'],
- {_L['Snapopen _User Home'], {io.snapopen, _USERHOME}},
- {_L['Snapopen _Textadept Home'], {io.snapopen, _HOME}},
- {_L['Snapopen _Current Directory'], utils.snapopen_filedir},
+ {
+ title = _L['Snap_open'],
+ {_L['Snapopen _User Home'], function() io.snapopen(_USERHOME) end},
+ {_L['Snapopen _Textadept Home'], function() io.snapopen(_HOME) end},
+ {_L['Snapopen _Current Directory'], function()
+ if buffer.filename then
+ io.snapopen(buffer.filename:match('^(.+)[/\\]'))
+ end
+ end},
{_L['Snapopen Current _Project'], io.snapopen},
},
- { title = _L['_Snippets'],
+ {
+ title = _L['_Snippets'],
{_L['_Insert Snippet...'], textadept.snippets._select},
{_L['_Expand Snippet/Next Placeholder'], textadept.snippets._insert},
{_L['_Previous Snippet Placeholder'], textadept.snippets._previous},
{_L['_Cancel Snippet'], textadept.snippets._cancel_current},
},
SEPARATOR,
- {_L['_Complete Symbol'], utils.autocomplete_symbol},
+ {_L['_Complete Symbol'], function()
+ textadept.editing.autocomplete(buffer:get_lexer(true))
+ end},
{_L['Show _Documentation'], textadept.editing.show_documentation},
- {_L['Show St_yle'], utils.show_style},
+ {_L['Show St_yle'], function()
+ local char = buffer:text_range(buffer.current_pos,
+ buffer:position_after(buffer.current_pos))
+ local bytes = string.rep(' 0x%X', #char):format(char:byte(1, #char))
+ local style = buffer.style_at[buffer.current_pos]
+ local text = string.format("'%s' (U+%04X:%s)\n%s %s\n%s %s (%d)", char,
+ utf8.codepoint(char), bytes, _L['Lexer'],
+ buffer:get_lexer(true), _L['Style'],
+ buffer.style_name[style], style)
+ buffer:call_tip_show(buffer.current_pos, text)
+ end}
},
- { title = _L['_Buffer'],
- {_L['_Next Buffer'], {view.goto_buffer, view, 1, true}},
- {_L['_Previous Buffer'], {view.goto_buffer, view, -1, true}},
+ {
+ title = _L['_Buffer'],
+ {_L['_Next Buffer'], function() view:goto_buffer(1, true) end},
+ {_L['_Previous Buffer'], function() view:goto_buffer(-1, true) end},
{_L['_Switch to Buffer...'], ui.switch_buffer},
SEPARATOR,
- { title = _L['_Indentation'],
- {_L['Tab width: _2'], {utils.set_indentation, 2}},
- {_L['Tab width: _3'], {utils.set_indentation, 3}},
- {_L['Tab width: _4'], {utils.set_indentation, 4}},
- {_L['Tab width: _8'], {utils.set_indentation, 8}},
+ {
+ title = _L['_Indentation'],
+ {_L['Tab width: _2'], function() set_indentation(2) end},
+ {_L['Tab width: _3'], function() set_indentation(3) end},
+ {_L['Tab width: _4'], function() set_indentation(4) end},
+ {_L['Tab width: _8'], function() set_indentation(8) end},
SEPARATOR,
- {_L['_Toggle Use Tabs'], {utils.toggle_property, 'use_tabs'}},
- {_L['_Convert Indentation'], editing.convert_indentation},
+ {_L['_Toggle Use Tabs'], function()
+ buffer.use_tabs = not buffer.use_tabs
+ events.emit(events.UPDATE_UI) -- for updating statusbar
+ end},
+ {_L['_Convert Indentation'], textadept.editing.convert_indentation}
},
- { title = _L['_EOL Mode'],
- {_L['CRLF'], {utils.set_eol_mode, buffer.EOL_CRLF}},
- {_L['CR'], {utils.set_eol_mode, buffer.EOL_CR}},
- {_L['LF'], {utils.set_eol_mode, buffer.EOL_LF}},
+ {
+ title = _L['_EOL Mode'],
+ {_L['CRLF'], function() set_eol_mode(buffer.EOL_CRLF) end},
+ {_L['CR'], function() set_eol_mode(buffer.EOL_CR) end},
+ {_L['LF'], function() set_eol_mode(buffer.EOL_LF) end}
},
- { title = _L['E_ncoding'],
- {_L['_UTF-8 Encoding'], {utils.set_encoding, 'UTF-8'}},
- {_L['_ASCII Encoding'], {utils.set_encoding, 'ASCII'}},
- {_L['_ISO-8859-1 Encoding'], {utils.set_encoding, 'ISO-8859-1'}},
- {_L['_MacRoman Encoding'], {utils.set_encoding, 'MacRoman'}},
- {_L['UTF-1_6 Encoding'], {utils.set_encoding, 'UTF-16LE'}},
+ {
+ title = _L['E_ncoding'],
+ {_L['_UTF-8 Encoding'], function() set_encoding('UTF-8') end},
+ {_L['_ASCII Encoding'], function() set_encoding('ASCII') end},
+ {_L['_ISO-8859-1 Encoding'], function() set_encoding('ISO-8859-1') end},
+ {_L['_MacRoman Encoding'], function() set_encoding('MacRoman') end},
+ {_L['UTF-1_6 Encoding'], function() set_encoding('UTF-16LE') end}
},
SEPARATOR,
- {_L['Toggle View _EOL'], {utils.toggle_property, 'view_eol'}},
- {_L['Toggle _Wrap Mode'], {utils.toggle_property, 'wrap_mode'}},
- {_L['Toggle View White_space'], {utils.toggle_property, 'view_ws'}},
+ {_L['Toggle View _EOL'], function()
+ buffer.view_eol = not buffer.view_eol
+ end},
+ {_L['Toggle _Wrap Mode'], function()
+ buffer.wrap_mode = buffer.wrap_mode == 0 and buffer.WRAP_WHITESPACE or 0
+ end},
+ {_L['Toggle View White_space'], function()
+ buffer.view_ws = buffer.view_ws == 0 and buffer.WS_VISIBLEALWAYS or 0
+ end},
SEPARATOR,
{_L['Select _Lexer...'], textadept.file_types.select_lexer},
- {_L['_Refresh Syntax Highlighting'], {buffer.colourise, buffer, 0, -1}},
+ {_L['_Refresh Syntax Highlighting'], function() buffer:colourise(0, -1) end}
},
- { title = _L['_View'],
- {_L['_Next View'], {ui.goto_view, 1, true}},
- {_L['_Previous View'], {ui.goto_view, -1, true}},
+ {
+ title = _L['_View'],
+ {_L['_Next View'], function() ui.goto_view(1, true) end},
+ {_L['_Previous View'], function() ui.goto_view(-1, true) end},
SEPARATOR,
- {_L['Split View _Horizontal'], {view.split, view}},
- {_L['Split View _Vertical'], {view.split, view, true}},
- {_L['_Unsplit View'], {view.unsplit, view}},
- {_L['Unsplit _All Views'], utils.unsplit_all},
- {_L['_Grow View'], utils.grow},
- {_L['Shrin_k View'], utils.shrink},
+ {_L['Split View _Horizontal'], function() view:split() end},
+ {_L['Split View _Vertical'], function() view:split(true) end},
+ {_L['_Unsplit View'], function() view:unsplit() end},
+ {_L['Unsplit _All Views'], function() while view:unsplit() do end end},
+ {_L['_Grow View'], function()
+ if view.size then view.size = view.size + buffer:text_height(0) end
+ end},
+ {_L['Shrin_k View'], function()
+ if view.size then view.size = view.size - buffer:text_height(0) end
+ end},
SEPARATOR,
- {_L['Toggle Current _Fold'], utils.toggle_current_fold},
+ {_L['Toggle Current _Fold'], function()
+ buffer:toggle_fold(buffer:line_from_position(buffer.current_pos))
+ end},
SEPARATOR,
- {_L['Toggle Show In_dent Guides'],
- {utils.toggle_property, 'indentation_guides'}},
- {_L['Toggle _Virtual Space'],
- {utils.toggle_property, 'virtual_space_options',
- buffer.VS_USERACCESSIBLE}},
+ {_L['Toggle Show In_dent Guides'], function()
+ local off = buffer.indentation_guides == 0
+ buffer.indentation_guides = off and buffer.IV_LOOKBOTH or 0
+ end},
+ {_L['Toggle _Virtual Space'], function()
+ local off = buffer.virtual_space_options == 0
+ buffer.virtual_space_options = off and buffer.VS_USERACCESSIBLE or 0
+ end},
SEPARATOR,
{_L['Zoom _In'], buffer.zoom_in},
{_L['Zoom _Out'], buffer.zoom_out},
- {_L['_Reset Zoom'], utils.reset_zoom},
+ {_L['_Reset Zoom'], function() buffer.zoom = 0 end}
},
- { title = _L['_Help'],
- {_L['Show _Manual'], {utils.open_webpage, _HOME..'/doc/manual.html'}},
- {_L['Show _LuaDoc'], {utils.open_webpage, _HOME..'/doc/api.html'}},
+ {
+ title = _L['_Help'],
+ {_L['Show _Manual'], function() open_page(_HOME..'/doc/manual.html') end},
+ {_L['Show _LuaDoc'], function() open_page(_HOME..'/doc/api.html') end},
SEPARATOR,
- {_L['_About'],
- {ui.dialogs.msgbox, {title = 'Textadept', text = _RELEASE,
- informative_text = _COPYRIGHT,
- icon_file = _HOME..'/core/images/ta_64x64.png'}}},
- },
+ {_L['_About'], function()
+ ui.dialogs.msgbox({
+ title = 'Textadept', text = _RELEASE, informative_text = _COPYRIGHT,
+ icon_file = _HOME..'/core/images/ta_64x64.png'
+ })
+ end}
+ }
}
---
@@ -311,27 +421,6 @@ local function read_menu_table(menu, contextmenu)
return gtkmenu
end
--- Builds the item and commands tables for the filtered list dialog.
--- @param menu The menu to read from.
--- @param title The title of the menu.
--- @param items The current list of items.
--- @param commands The current list of commands.
-local function build_command_tables(menu, title, items, commands)
- for i = 1, #menu do
- if menu[i].title then
- build_command_tables(menu[i], menu[i].title, items, commands)
- elseif menu[i][1] ~= '' then
- local label, f = menu[i][1], menu[i][2]
- if title then label = title..': '..label end
- items[#items + 1] = label:gsub('_([^_])', '%1')
- items[#items + 1] = key_shortcuts[get_id(f)] or ''
- commands[#commands + 1] = f
- end
- end
-end
-
-local items, commands
-
-- Returns a proxy table for menu table *menu* such that when a menu item is
-- changed or added, *update* is called to update the menu in the UI.
-- @param menu The menu or table of menus to create a proxy for.
@@ -343,7 +432,7 @@ local function proxy_menu(menu, update, menubar)
return setmetatable({}, {
__index = function(_, k)
local v
- if type(k) == 'number' then
+ if type(k) == 'number' or k == 'title' then
v = menu[k]
elseif type(k) == 'string' then
for i = 1, #menu do
@@ -378,11 +467,10 @@ local function set_menubar(menubar)
_menubar[#_menubar + 1] = ui.menu(read_menu_table(menubar[i]))
end
ui.menubar = _menubar
- items, commands = {}, {}
- build_command_tables(menubar, nil, items, commands)
proxies.menubar = proxy_menu(menubar, set_menubar)
end
-set_menubar(default_menubar)
+proxies.menubar = proxy_menu(default_menubar, function() end) -- for keys.lua
+events.connect(events.INITIALIZED, function() set_menubar(default_menubar) end)
-- Sets `ui.context_menu` and `ui.tab_context_menu` from menu item lists
-- *buffer_menu* and *tab_menu*, respectively.
@@ -408,12 +496,37 @@ local function set_contextmenus(buffer_menu, tab_menu)
set_contextmenus(nil, menu)
end)
end
-set_contextmenus()
+events.connect(events.INITIALIZED, set_contextmenus)
+
+-- Performs the appropriate action when clicking a menu item.
+events.connect(events.MENU_CLICKED, function(menu_id)
+ local actions = menu_id < 1000 and menu_actions or contextmenu_actions
+ local action = actions[menu_id < 1000 and menu_id or menu_id - 1000]
+ assert(type(action) == 'function' or type(action) == 'table',
+ _L['Unknown command:']..' '..tostring(action))
+ keys.run_command(action, type(action))
+end)
---
-- Prompts the user to select a menu command to run.
-- @name select_command
function M.select_command()
+ local items, commands = {}, {}
+ -- Builds the item and commands tables for the filtered list dialog.
+ -- @param menu The menu to read from.
+ local function build_command_tables(menu)
+ for i = 1, #menu do
+ if menu[i].title then
+ build_command_tables(menu[i])
+ elseif menu[i][1] ~= '' then
+ local label = menu.title and menu.title..': '..menu[i][1] or menu[i][1]
+ items[#items + 1] = label:gsub('_([^_])', '%1')
+ items[#items + 1] = key_shortcuts[get_id(menu[i][2])] or ''
+ commands[#commands + 1] = menu[i][2]
+ end
+ end
+ end
+ build_command_tables(getmetatable(M.menubar).menu)
local button, i = ui.dialogs.filteredlist{
title = _L['Run Command'], columns = {_L['Command'], _L['Key Command']},
items = items, width = CURSES and ui.size[1] - 2 or nil
@@ -422,15 +535,6 @@ function M.select_command()
keys.run_command(commands[i], type(commands[i]))
end
--- Performs the appropriate action when clicking a menu item.
-events.connect(events.MENU_CLICKED, function(menu_id)
- local actions = menu_id < 1000 and menu_actions or contextmenu_actions
- local action = actions[menu_id < 1000 and menu_id or menu_id - 1000]
- assert(type(action) == 'function' or type(action) == 'table',
- _L['Unknown command:']..' '..tostring(action))
- keys.run_command(action, type(action))
-end)
-
return setmetatable(M, {
__index = function(_, k) return proxies[k] or M[k] end,
__newindex = function(_, k, v)