aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md4
-rw-r--r--core/ui.lua43
-rw-r--r--doc/14_Appendix.md3
-rw-r--r--modules/textadept/menu.lua90
4 files changed, 95 insertions, 45 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 03925900..ce06ae03 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -179,8 +179,7 @@ Changes:
that do not flash the "black box" on Windows.
* Added read-only access to the current key chain via [`keys.keychain`][].
* Renamed "hypertext" lexer and its corresponding module to "html".
-* Added configurable tab context menus via
- [`textadept.menu.set_contextmenus()`][].
+* Added configurable tab context menus via `textadept.menu.set_contextmenus()`.
* New GUI theme for Mac OSX.
* [Experimental] Merged separate lexer states into Textadept's Lua state.
* Updated to [Lua][] 5.2.3.
@@ -194,7 +193,6 @@ Changes:
[`ui.maximized`]: api/ui.html#maximized
[OSX environment variables]: 02_Installation.html#Environment.Variables
[`keys.keychain`]: api/keys.html#keychain
-[`textadept.menu.set_contextmenus()`]: api/textadept.menu.html#set_contextmenus
[Lua]: http://lua.org
[Scintilla]: http://scintilla.org
diff --git a/core/ui.lua b/core/ui.lua
index 128e16bd..8f40e2fa 100644
--- a/core/ui.lua
+++ b/core/ui.lua
@@ -7,14 +7,6 @@ local ui = ui
-- Utilities for interacting with Textadept's user interface.
-- @field title (string, Write-only)
-- The title text of Textadept's window.
--- @field context_menu
--- The buffer's context menu, a [`ui.menu()`](#menu).
--- This is a low-level field. You probably want to use the higher-level
--- `textadept.menu.set_contextmenus()`.
--- @field tab_context_menu
--- The context menu for the buffer's tab, a [`ui.menu()`](#menu).
--- This is a low-level field. You probably want to use the higher-level
--- `textadept.menu.set_contextmenus()`.
-- @field clipboard_text (string)
-- The text on the clipboard.
-- @field statusbar_text (string, Write-only)
@@ -397,13 +389,33 @@ events_connect(events.ERROR, ui.print)
--[[ The tables below were defined in C.
---
--- A table of menus defining a menubar. (Write-only)
--- @see textadept.menu.set_menubar
+-- A table of menus defining a menubar.
+-- This is a low-level field. You probably want to use the higher-level
+-- `textadept.menu.menubar`.
+-- @see textadept.menu.menubar
-- @class table
-- @name menubar
local menubar
---
+-- A menu userdata that defines the buffer's context menu.
+-- This is a low-level field. You probably want to use the higher-level
+-- `textadept.menu.context_menu`.
+-- @see textadept.menu.context_menu
+-- @class table
+-- @name context_menu
+local context_menu
+
+---
+-- A menu userdata that defines the context menu for the buffer's tab.
+-- This is a low-level field. You probably want to use the higher-level
+-- `textadept.menu.tab_context_menu`.
+-- @see textadept.menu.tab_context_menu
+-- @class table
+-- @name tab_context_menu
+local tab_context_menu
+
+---
-- A table containing the width and height pixel values of Textadept's window.
-- @class table
-- @name size
@@ -459,9 +471,9 @@ local goto_view
---
-- Low-level function for creating a menu from table *menu_table* and returning
-- the userdata.
--- You probably want to use the higher-level `textadept.menu.set_menubar()`
--- or `textadept.menu.set_contextmenus()` functions. Emits a `MENU_CLICKED`
--- event when a menu item is selected.
+-- You probably want to use the higher-level `textadept.menu.menubar`,
+-- `textadept.menu.context_menu`, or `textadept.menu.tab_context_menu` tables.
+-- Emits a `MENU_CLICKED` event when a menu item is selected.
-- @param menu_table A table defining the menu. It is an ordered list of tables
-- with a string menu item, integer menu ID, and optional GDK keycode and
-- modifier mask. The latter two are used to display key shortcuts in the
@@ -471,8 +483,9 @@ local goto_view
-- @usage ui.menu{{'_New', 1}, {'_Open', 2}, {''}, {'_Quit', 4}}
-- @usage ui.menu{{'_New', 1, string.byte('n'), 4}} -- 'Ctrl+N'
-- @see events.MENU_CLICKED
--- @see textadept.menu.set_menubar
--- @see textadept.menu.set_contextmenus
+-- @see textadept.menu.menubar
+-- @see textadept.menu.context_menu
+-- @see textadept.menu.tab_context_menu
-- @class function
-- @name menu
local menu
diff --git a/doc/14_Appendix.md b/doc/14_Appendix.md
index 2abec6b7..7ab00297 100644
--- a/doc/14_Appendix.md
+++ b/doc/14_Appendix.md
@@ -422,7 +422,7 @@ remove() |Renamed |toggle(false)
**_M.textadept.editing** | |
prepare\_for\_save() |Removed |N/A
**_M.textadept.menu** | |
-rebuild\_command\_tables() |Replaced|[set\_menubar()][]
+rebuild\_command\_tables() |Replaced|set\_menubar()
**_M.textadept.run** | |
execute() |Replaced|[run()][] and [compile()][]
**_M.textadept.session** | |
@@ -431,7 +431,6 @@ prompt\_save() |Replaced|[save()][]
[menu()]: api/ui.html#menu
[toggle()]: api/textadept.bookmarks.html#toggle
-[set\_menubar()]: api/textadept.menu.html#set_menubar
[run()]: api/textadept.run.html#run
[compile()]: api/textadept.run.html#compile
[load()]: api/textadept.session.html#load
diff --git a/modules/textadept/menu.lua b/modules/textadept/menu.lua
index 55cf7ee6..dbb34292 100644
--- a/modules/textadept/menu.lua
+++ b/modules/textadept/menu.lua
@@ -6,6 +6,8 @@ local M = {}
--[[ This comment is for LuaDoc.
---
-- Defines the menus used by Textadept.
+-- Menus are simply tables and may be edited in place. Use the '#' operator
+-- (instead of `ipairs()`) for iteration.
-- 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.
@@ -15,7 +17,10 @@ local _L, buffer, view = _L, buffer, view
local editing, utils = textadept.editing, textadept.keys.utils
local SEPARATOR = {''}
+---
-- The default main menubar.
+-- @class table
+-- @name menubar
local menubar = {
{ title = _L['_File'],
{_L['_New'], buffer.new},
@@ -200,7 +205,10 @@ local menubar = {
},
}
+---
-- The default right-click context menu.
+-- @class table
+-- @name context_menu
local context_menu = {
{_L['_Undo'], buffer.undo},
{_L['_Redo'], buffer.redo},
@@ -213,7 +221,10 @@ local context_menu = {
{_L['Select _All'], buffer.select_all}
}
+---
-- The default tabbar context menu.
+-- @class table
+-- @name tab_context_menu
local tab_context_menu = {
{_L['_Close'], io.close_buffer},
SEPARATOR,
@@ -223,6 +234,11 @@ local tab_context_menu = {
{_L['Re_load'], io.reload_file},
}
+-- Table of proxy tables for menus.
+local proxies = {}
+
+local key_shortcuts, menu_actions, contextmenu_actions, items, commands
+
-- Returns the GDK integer keycode and modifier mask for a key sequence.
-- This is used for creating menu accelerators.
-- @param key_seq The string key sequence.
@@ -256,8 +272,6 @@ local function get_id(f)
return id
end
-local key_shortcuts, menu_actions, contextmenu_actions
-
-- Creates a menu suitable for `ui.menu()` from the menu table format.
-- Also assigns key commands.
-- @param menu The menu to create a GTK+ menu from.
@@ -305,9 +319,27 @@ local function build_command_tables(menu, title, items, commands)
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.
+-- @param update The function to call to update the menu in the UI when a menu
+-- item is changed or added.
+-- @param menubar Used internally to keep track of the top-level menu for
+-- calling *update* with.
+local function proxy_menu(menu, update, menubar)
+ return setmetatable({}, {
+ __index = function(t, k)
+ local v = menu[k]
+ return type(v) == 'table' and proxy_menu(v, update, menubar or menu) or v
+ end,
+ __newindex = function(t, k, v)
+ menu[k] = v
+ update(menubar or menu)
+ end,
+ __len = function(t) return #menu end,
+ })
+end
----
-- Sets `ui.menubar` from menu table *menubar*.
-- Each menu is an ordered list of menu items and has a `title` key for the
-- title text. Menu items are tables containing menu text and either a function
@@ -317,8 +349,7 @@ local items, commands
-- @param menubar The table of menu tables to create the menubar from.
-- @see ui.menubar
-- @see ui.menu
--- @name set_menubar
-function M.set_menubar(menubar)
+local function set_menubar(menubar)
key_shortcuts = {}
for key, f in pairs(keys) do key_shortcuts[get_id(f)] = key end
menu_actions = {}
@@ -329,18 +360,10 @@ function M.set_menubar(menubar)
ui.menubar = _menubar
items, commands = {}, {}
build_command_tables(menubar, nil, items, commands)
+ proxies.menubar = proxy_menu(menubar, set_menubar)
end
-M.set_menubar(menubar)
-
----
--- Sets `ui.context_menu` from menu item list *menu*.
--- Deprecated in favor of `set_contextmenus()`.
--- @param menu The menu table to create the context menu from.
--- @see set_contextmenus
--- @name set_contextmenu
-function M.set_contextmenu(menu) M.set_contextmenus(menu) end
+set_menubar(menubar)
----
-- Sets `ui.context_menu` and `ui.tab_context_menu` from menu item lists
-- *buffer_menu* and *tab_menu*, respectively.
-- Menu items are tables containing menu text and either a function to call or
@@ -354,14 +377,18 @@ function M.set_contextmenu(menu) M.set_contextmenus(menu) end
-- @see ui.context_menu
-- @see ui.tab_context_menu
-- @see ui.menu
--- @name set_contextmenus
-function M.set_contextmenus(buffer_menu, tab_menu)
+local function set_contextmenus(buffer_menu, tab_menu)
contextmenu_actions = {}
- ui.context_menu = ui.menu(read_menu_table(buffer_menu or context_menu, true))
- ui.tab_context_menu = ui.menu(read_menu_table(tab_menu or tab_context_menu,
- true))
+ local menu = buffer_menu or context_menu
+ ui.context_menu = ui.menu(read_menu_table(menu, true))
+ proxies.context_menu = proxy_menu(menu, set_contextmenus)
+ menu = tab_menu or tab_context_menu
+ ui.tab_context_menu = ui.menu(read_menu_table(menu, true))
+ proxies.tab_context_menu = proxy_menu(menu, function()
+ set_contextmenus(nil, menu)
+ end)
end
-if not CURSES then M.set_contextmenus() end
+if not CURSES then set_contextmenus() end
---
-- Prompts the user to select a menu command to run.
@@ -388,8 +415,8 @@ if not CURSES then
-- Set a language-specific context menu or the default one.
local function set_language_contextmenu()
local lang = _G.buffer:get_lexer()
- M.set_contextmenus(_M[lang] and _M[lang].context_menu,
- _M[lang] and _M[lang].tab_context_menu)
+ set_contextmenus(_M[lang] and _M[lang].context_menu,
+ _M[lang] and _M[lang].tab_context_menu)
end
events.connect(events.LEXER_LOADED, set_language_contextmenu)
events.connect(events.BUFFER_AFTER_SWITCH, set_language_contextmenu)
@@ -397,4 +424,17 @@ if not CURSES then
events.connect(events.BUFFER_NEW, set_language_contextmenu)
end
-return M
+return setmetatable(M, {
+ __index = function(t, k) return proxies[k] or M[k] end,
+ __newindex = function(t, k, v)
+ if k == 'menubar' then
+ set_menubar(v)
+ elseif k == 'context_menu' then
+ set_contextmenus(v)
+ elseif k == 'tab_context_menu' then
+ set_contextmenus(nil, v)
+ else
+ M[k] = v
+ end
+ end
+})