diff options
author | mitchell <70453897+orbitalquark@users.noreply.github.com> | 2021-04-11 09:34:17 -0400 |
---|---|---|
committer | mitchell <70453897+orbitalquark@users.noreply.github.com> | 2021-04-11 09:34:17 -0400 |
commit | de3a745e1af2e441de868c2aa4849102d376acb5 (patch) | |
tree | c2d7767600dc519b2613ddecaf7e53fb5e8867a2 /core/ui.lua | |
parent | 03fab17277fee7387fd93a9c2774b1ebf3f80fe4 (diff) |
Initial pass reformatting all code.
Use clang-format, LuaFormatter, and 100 character limit on lines.
Diffstat (limited to 'core/ui.lua')
-rw-r--r-- | core/ui.lua | 350 |
1 files changed, 162 insertions, 188 deletions
diff --git a/core/ui.lua b/core/ui.lua index 19bf5881..eb366c93 100644 --- a/core/ui.lua +++ b/core/ui.lua @@ -26,15 +26,14 @@ local ui = ui -- @field tabs (bool) -- Whether or not to display the tab bar when multiple buffers are open. -- The default value is `true`. --- A third option, `ui.SHOW_ALL_TABS` may be used to always show the tab bar, --- even if only one buffer is open. +-- A third option, `ui.SHOW_ALL_TABS` may be used to always show the tab bar, even if only +-- one buffer is open. -- @field silent_print (bool) -- Whether or not to print messages to buffers silently. --- This is not guaranteed to be a constant value, as Textadept may change it --- for the editor's own purposes. This flag should be used only in conjunction --- with a group of [`ui.print()`]() and [`ui._print()`]() function calls. --- The default value is `false`, and focuses buffers when messages are printed --- to them. +-- This is not guaranteed to be a constant value, as Textadept may change it for the editor's +-- own purposes. This flag should be used only in conjunction with a group of [`ui.print()`]() +-- and [`ui._print()`]() function calls. +-- The default value is `false`, and focuses buffers when messages are printed to them. -- @field SHOW_ALL_TABS (number) -- module('ui')]] @@ -43,10 +42,14 @@ ui.SHOW_ALL_TABS = 2 -- ui.tabs options must be greater than 1 ui.silent_print = false --- Helper function for jumping to another view to print to, or creating a new --- view to print to (the latter depending on settings). +-- Helper function for jumping to another view to print to, or creating a new view to print to +-- (the latter depending on settings). local function prepare_view() - if #_VIEWS > 1 then ui.goto_view(1) elseif not ui.tabs then view:split() end + if #_VIEWS > 1 then + ui.goto_view(1) + elseif not ui.tabs then + view:split() + end end -- Helper function for printing messages to buffers. @@ -54,7 +57,10 @@ end local function _print(buffer_type, ...) local buffer for _, buf in ipairs(_BUFFERS) do - if buf._type == buffer_type then buffer = buf break end + if buf._type == buffer_type then + buffer = buf + break + end end if not buffer then prepare_view() @@ -80,17 +86,14 @@ local function _print(buffer_type, ...) end --- -- Prints the given string messages to the buffer of string type *buffer_type*. --- Opens a new buffer for printing messages to if necessary. If the message --- buffer is already open in a view, the message is printed to that view. --- Otherwise the view is split (unless `ui.tabs` is `true`) and the message --- buffer is displayed before being printed to. +-- Opens a new buffer for printing messages to if necessary. If the message buffer is already +-- open in a view, the message is printed to that view. Otherwise the view is split (unless +-- `ui.tabs` is `true`) and the message buffer is displayed before being printed to. -- @param buffer_type String type of message buffer. -- @param ... Message strings. -- @usage ui._print(_L['[Message Buffer]'], message) -- @name _print -function ui._print(buffer_type, ...) - _print(assert_type(buffer_type, 'string', 1), ...) -end +function ui._print(buffer_type, ...) _print(assert_type(buffer_type, 'string', 1), ...) end --- -- Prints the given string messages to the message buffer. @@ -99,8 +102,7 @@ end -- @name print function ui.print(...) ui._print(_L['[Message Buffer]'], ...) end --- Returns 0xBBGGRR colors transformed into "#RRGGBB" for the colorselect --- dialog. +-- Returns 0xBBGGRR colors transformed into "#RRGGBB" for the colorselect dialog. -- @param value Number color to transform. -- @return string or nil if the transform failed local function torgb(value) @@ -110,89 +112,83 @@ local function torgb(value) end -- Documentation is in core/.ui.dialogs.luadoc. -ui.dialogs = setmetatable({}, {__index = function(_, k) - -- Wrapper for `ui.dialog(k)`, transforming the given table of arguments into - -- a set of command line arguments and transforming the resulting standard - -- output into Lua objects. - -- @param options Table of key-value command line options for gtdialog. - -- @param f Work function for progressbar dialogs. - -- @return Lua objects depending on the dialog kind - return function(options, f) - if not options.button1 then options.button1 = _L['OK'] end - if k == 'filteredlist' and not options.width then - options.width = ui.size[1] - 2 * (CURSES and 1 or 100) - end - -- Transform key-value pairs into command line arguments. - local args = {} - for option, value in pairs(options) do - if assert_type(value, 'string/number/table/boolean', option) then - args[#args + 1] = '--' .. option:gsub('_', '-') - if type(value) == 'table' then - for i, val in ipairs(value) do - local narg = string.format('%s[%d]', option, i) - assert_type(val, 'string/number', narg) - if option == 'palette' and type(val) == 'number' then - value[i] = torgb(val) -- nil return is okay - elseif option == 'select' and assert_type(val, 'number', narg) then - value[i] = val - 1 -- convert from 1-based index to 0-based index +ui.dialogs = setmetatable({}, { + __index = function(_, k) + -- Wrapper for `ui.dialog(k)`, transforming the given table of arguments into a set of + -- command line arguments and transforming the resulting standard output into Lua objects. + -- @param options Table of key-value command line options for gtdialog. + -- @param f Work function for progressbar dialogs. + -- @return Lua objects depending on the dialog kind + return function(options, f) + if not options.button1 then options.button1 = _L['OK'] end + if k == 'filteredlist' and not options.width then + options.width = ui.size[1] - 2 * (CURSES and 1 or 100) + end + -- Transform key-value pairs into command line arguments. + local args = {} + for option, value in pairs(options) do + if assert_type(value, 'string/number/table/boolean', option) then + args[#args + 1] = '--' .. option:gsub('_', '-') + if type(value) == 'table' then + for i, val in ipairs(value) do + local narg = string.format('%s[%d]', option, i) + assert_type(val, 'string/number', narg) + if option == 'palette' and type(val) == 'number' then + value[i] = torgb(val) -- nil return is okay + elseif option == 'select' and assert_type(val, 'number', narg) then + value[i] = val - 1 -- convert from 1-based index to 0-based index + end end + elseif option == 'color' and type(value) == 'number' then + value = torgb(value) + elseif option == 'select' and assert_type(value, 'number', option) then + value = value - 1 -- convert from 1-based index to 0-based index end - elseif option == 'color' and type(value) == 'number' then - value = torgb(value) - elseif option == 'select' and assert_type(value, 'number', option) then - value = value - 1 -- convert from 1-based index to 0-based index + if type(value) ~= 'boolean' then args[#args + 1] = value end end - if type(value) ~= 'boolean' then args[#args + 1] = value end - end - end - if k == 'progressbar' then - args[#args + 1] = assert_type(f, 'function', 2) - end - -- Call gtdialog, stripping any trailing newline in the output. - local result = ui.dialog( - k:gsub('_', '-'), table.unpack(args)):match('^(.-)\n?$') - -- Depending on the dialog type, transform the result into Lua objects. - if k == 'fileselect' or k == 'filesave' then - if result == '' then return nil end - if WIN32 and not CURSES then result = result:iconv(_CHARSET, 'UTF-8') end - if k == 'filesave' or not options.select_multiple then return result end - local filenames = {} - for filename in result:gmatch('[^\n]+') do - filenames[#filenames + 1] = filename - end - return filenames - elseif k == 'filteredlist' or k == 'optionselect' or - k:find('input') and result:match('^[^\n]+\n?(.*)$'):find('\n') then - local button, value = result:match('^([^\n]+)\n?(.*)$') - if not options.string_output then button = tonumber(button) end - if k == 'optionselect' then - options.select_multiple = true - elseif k:find('input') then - options.string_output, options.select_multiple = true, true end - local items, patt = {}, not k:find('input') and '[^\n]+' or '([^\n]*)\n' - for item in (value .. '\n'):gmatch(patt) do - items[#items + 1] = options.string_output and item or tonumber(item) + 1 - end - return button, options.select_multiple and items or items[1] - elseif k == 'colorselect' then - if options.string_output then return result ~= '' and result or nil end - local r, g, b = result:match('^#(%x%x)(%x%x)(%x%x)$') - local bgr = r and g and b and string.format('0x%s%s%s', b, g, r) or nil - return tonumber(bgr) - elseif k == 'fontselect' or k == 'progressbar' then - return result ~= '' and result or nil - elseif not options.string_output then - local i, value = result:match('^(%-?%d+)\n?(.*)$') - i = tonumber(i) - if k:find('dropdown') then - value = i > 0 and tonumber(value) + 1 or nil + if k == 'progressbar' then args[#args + 1] = assert_type(f, 'function', 2) end + -- Call gtdialog, stripping any trailing newline in the output. + local result = ui.dialog(k:gsub('_', '-'), table.unpack(args)):match('^(.-)\n?$') + -- Depending on the dialog type, transform the result into Lua objects. + if k == 'fileselect' or k == 'filesave' then + if result == '' then return nil end + if WIN32 and not CURSES then result = result:iconv(_CHARSET, 'UTF-8') end + if k == 'filesave' or not options.select_multiple then return result end + local filenames = {} + for filename in result:gmatch('[^\n]+') do filenames[#filenames + 1] = filename end + return filenames + elseif k == 'filteredlist' or k == 'optionselect' or + (k:find('input') and result:match('^[^\n]+\n?(.*)$'):find('\n')) then + local button, value = result:match('^([^\n]+)\n?(.*)$') + if not options.string_output then button = tonumber(button) end + if k == 'optionselect' then + options.select_multiple = true + elseif k:find('input') then + options.string_output, options.select_multiple = true, true + end + local items, patt = {}, not k:find('input') and '[^\n]+' or '([^\n]*)\n' + for item in (value .. '\n'):gmatch(patt) do + items[#items + 1] = options.string_output and item or tonumber(item) + 1 + end + return button, options.select_multiple and items or items[1] + elseif k == 'colorselect' then + if options.string_output then return result ~= '' and result or nil end + local r, g, b = result:match('^#(%x%x)(%x%x)(%x%x)$') + local bgr = r and g and b and string.format('0x%s%s%s', b, g, r) or nil + return tonumber(bgr) + elseif k == 'fontselect' or k == 'progressbar' then + return result ~= '' and result or nil + elseif not options.string_output then + local i, value = result:match('^(%-?%d+)\n?(.*)$') + i = tonumber(i) + if k:find('dropdown') then value = i > 0 and tonumber(value) + 1 or nil end + return i, value end - return i, value + return result:match('([^\n]+)\n?(.*)$') end - return result:match('([^\n]+)\n?(.*)$') end -end}) +}) local buffers_zorder = {} @@ -218,18 +214,15 @@ events.connect(events.VIEW_AFTER_SWITCH, update_zorder) events.connect(events.BUFFER_DELETED, update_zorder) -- Saves and restores buffer zorder data during a reset. -events.connect( - events.RESET_BEFORE, function(persist) persist.ui_zorder = buffers_zorder end) -events.connect( - events.RESET_AFTER, function(persist) buffers_zorder = persist.ui_zorder end) +events.connect(events.RESET_BEFORE, function(persist) persist.ui_zorder = buffers_zorder end) +events.connect(events.RESET_AFTER, function(persist) buffers_zorder = persist.ui_zorder end) --- -- Prompts the user to select a buffer to switch to. --- Buffers are listed in the order they were opened unless `zorder` is `true`, --- in which case buffers are listed by their z-order (most recently viewed to --- least recently viewed). --- @param zorder Flag that indicates whether or not to list buffers by their --- z-order. The default value is `false`. +-- Buffers are listed in the order they were opened unless `zorder` is `true`, in which case +-- buffers are listed by their z-order (most recently viewed to least recently viewed). +-- @param zorder Flag that indicates whether or not to list buffers by their z-order. The +-- default value is `false`. -- @name switch_buffer function ui.switch_buffer(zorder) local buffers = not zorder and _BUFFERS or buffers_zorder @@ -251,29 +244,26 @@ end --- -- Switches to the existing view whose buffer's filename is *filename*. --- If no view was found and *split* is `true`, splits the current view in order --- to show the requested file. If *split* is `false`, shifts to the next or --- *preferred_view* view in order to show the requested file. If *sloppy* is --- `true`, requires only the basename of *filename* to match a buffer's --- `filename`. If the requested file was not found, it is opened in the desired --- view. +-- If no view was found and *split* is `true`, splits the current view in order to show the +-- requested file. If *split* is `false`, shifts to the next or *preferred_view* view in order +-- to show the requested file. If *sloppy* is `true`, requires only the basename of *filename* +-- to match a buffer's `filename`. If the requested file was not found, it is opened in the +-- desired view. -- @param filename The filename of the buffer to go to. --- @param split Optional flag that indicates whether or not to open the buffer --- in a split view if there is only one view. The default value is `false`. --- @param preferred_view Optional view to open the desired buffer in if the --- buffer is not visible in any other view. --- @param sloppy Optional flag that indicates whether or not to not match --- *filename* to `buffer.filename` exactly. When `true`, matches *filename* to --- only the last part of `buffer.filename` This is useful for run and compile --- commands which output relative filenames and paths instead of full ones and --- it is likely that the file in question is already open. The default value --- is `false`. +-- @param split Optional flag that indicates whether or not to open the buffer in a split view +-- if there is only one view. The default value is `false`. +-- @param preferred_view Optional view to open the desired buffer in if the buffer is not +-- visible in any other view. +-- @param sloppy Optional flag that indicates whether or not to not match *filename* to +-- `buffer.filename` exactly. When `true`, matches *filename* to only the last part of +-- `buffer.filename` This is useful for run and compile commands which output relative filenames +-- and paths instead of full ones and it is likely that the file in question is already open. +-- The default value is `false`. -- @name goto_file function ui.goto_file(filename, split, preferred_view, sloppy) assert_type(filename, 'string', 1) - local patt = string.format( -- TODO: escape filename properly - '%s%s$', not sloppy and '^' or '', - not sloppy and filename or filename:match('[^/\\]+$')) + local patt = string.format('%s%s$', not sloppy and '^' or '', + not sloppy and filename or filename:match('[^/\\]+$')) -- TODO: escape filename properly if WIN32 then patt = patt:gsub('%a', function(letter) return string.format('[%s%s]', letter:upper(), letter:lower()) @@ -285,13 +275,19 @@ function ui.goto_file(filename, split, preferred_view, sloppy) local other_view = _VIEWS[preferred_view] for _, view in ipairs(_VIEWS) do local filename = view.buffer.filename or '' - if filename:find(patt) then ui.goto_view(view) return end + if filename:find(patt) then + ui.goto_view(view) + return + end if not other_view and view ~= _G.view then other_view = view end end if other_view then ui.goto_view(other_view) end end for _, buf in ipairs(_BUFFERS) do - if (buf.filename or ''):find(patt) then view:goto_buffer(buf) return end + if (buf.filename or ''):find(patt) then + view:goto_buffer(buf) + return + end end io.open_file(filename) end @@ -300,18 +296,14 @@ end events.connect(events.VIEW_NEW, function() events.emit(events.UPDATE_UI, 3) end) -- Switches between buffers when a tab is clicked. -events.connect( - events.TAB_CLICKED, function(index) view:goto_buffer(_BUFFERS[index]) end) +events.connect(events.TAB_CLICKED, function(index) view:goto_buffer(_BUFFERS[index]) end) -- Sets the title of the Textadept window to the buffer's filename. local function set_title() local filename = buffer.filename or buffer._type or _L['Untitled'] - if buffer.filename then - filename = select(2, pcall(string.iconv, filename, 'UTF-8', _CHARSET)) - end + if buffer.filename then filename = select(2, pcall(string.iconv, filename, 'UTF-8', _CHARSET)) end local basename = buffer.filename and filename:match('[^/\\]+$') or filename - ui.title = string.format( - '%s %s Textadept (%s)', basename, buffer.modify and '*' or '-', filename) + ui.title = string.format('%s %s Textadept (%s)', basename, buffer.modify and '*' or '-', filename) buffer.tab_label = basename .. (buffer.modify and '*' or '') end @@ -322,9 +314,8 @@ events.connect(events.SAVE_POINT_LEFT, set_title) -- Open uri(s). events.connect(events.URI_DROPPED, function(utf8_uris) for utf8_path in utf8_uris:gmatch('file://([^\r\n]+)') do - local path = utf8_path:gsub('%%(%x%x)', function(hex) - return string.char(tonumber(hex, 16)) - end):iconv(_CHARSET, 'UTF-8') + local path = utf8_path:gsub('%%(%x%x)', function(hex) return string.char(tonumber(hex, 16)) end) + :iconv(_CHARSET, 'UTF-8') -- In WIN32, ignore a leading '/', but not '//' (network path). if WIN32 and not path:match('^//') then path = path:sub(2, -1) end local mode = lfs.attributes(path, 'mode') @@ -332,9 +323,8 @@ events.connect(events.URI_DROPPED, function(utf8_uris) end ui.goto_view(view) -- work around any view focus synchronization issues end) -events.connect(events.APPLEEVENT_ODOC, function(uri) - return events.emit(events.URI_DROPPED, 'file://' .. uri) -end) +events.connect(events.APPLEEVENT_ODOC, + function(uri) return events.emit(events.URI_DROPPED, 'file://' .. uri) end) -- Sets buffer statusbar text. events.connect(events.UPDATE_UI, function(updated) @@ -346,11 +336,11 @@ events.connect(events.UPDATE_UI, function(updated) local col = buffer.column[pos] local lang = buffer:get_lexer() local eol = buffer.eol_mode == buffer.EOL_CRLF and _L['CRLF'] or _L['LF'] - local tabs = string.format( - '%s %d', buffer.use_tabs and _L['Tabs:'] or _L['Spaces:'], buffer.tab_width) + local tabs = string.format('%s %d', buffer.use_tabs and _L['Tabs:'] or _L['Spaces:'], + buffer.tab_width) local encoding = buffer.encoding or '' - ui.buffer_statusbar_text = string.format( - text, _L['Line:'], line, max, _L['Col:'], col, lang, eol, tabs, encoding) + ui.buffer_statusbar_text = string.format(text, _L['Line:'], line, max, _L['Col:'], col, lang, eol, + tabs, encoding) end) -- Save buffer properties. @@ -420,8 +410,7 @@ end events.connect(events.BUFFER_AFTER_SWITCH, restore_view_state) events.connect(events.VIEW_AFTER_SWITCH, restore_view_state) -events.connect( - events.RESET_AFTER, function() ui.statusbar_text = _L['Lua reset'] end) +events.connect(events.RESET_AFTER, function() ui.statusbar_text = _L['Lua reset'] end) -- Prompts for confirmation if any buffers are modified. events.connect(events.QUIT, function() @@ -435,19 +424,16 @@ events.connect(events.QUIT, function() end if #utf8_list == 0 then return end local button = ui.dialogs.msgbox{ - title = _L['Quit without saving?'], - text = _L['The following buffers are unsaved:'], - informative_text = table.concat(utf8_list, '\n'), - icon = 'gtk-dialog-question', button1 = _L['Cancel'], - button2 = _L['Quit without saving'], + title = _L['Quit without saving?'], text = _L['The following buffers are unsaved:'], + informative_text = table.concat(utf8_list, '\n'), icon = 'gtk-dialog-question', + button1 = _L['Cancel'], button2 = _L['Quit without saving'], width = CURSES and ui.size[1] - 2 or nil } if button ~= 2 then return true end -- prevent quit end) -- Keeps track of, and switches back to the previous buffer after buffer close. -events.connect( - events.BUFFER_BEFORE_SWITCH, function() view._prev_buffer = buffer end) +events.connect(events.BUFFER_BEFORE_SWITCH, function() view._prev_buffer = buffer end) events.connect(events.BUFFER_DELETED, function() if _BUFFERS[view._prev_buffer] and buffer ~= view._prev_buffer then restore_view_state() -- events.BUFFER_AFTER_SWITCH is not emitted in time @@ -455,15 +441,11 @@ events.connect(events.BUFFER_DELETED, function() end end) --- Properly handle clipboard text between views in curses, enables and disables --- mouse mode, and focuses and resizes views based on mouse events. +-- Properly handle clipboard text between views in curses, enables and disables mouse mode, +-- and focuses and resizes views based on mouse events. if CURSES then - events.connect(events.VIEW_BEFORE_SWITCH, function() - ui._clipboard_text = ui.clipboard_text - end) - events.connect(events.VIEW_AFTER_SWITCH, function() - ui.clipboard_text = ui._clipboard_text - end) + events.connect(events.VIEW_BEFORE_SWITCH, function() ui._clipboard_text = ui.clipboard_text end) + events.connect(events.VIEW_AFTER_SWITCH, function() ui.clipboard_text = ui._clipboard_text end) if not WIN32 then local function enable_mouse() io.stdout:write("\x1b[?1002h"):flush() end @@ -485,8 +467,7 @@ if CURSES then return get_view(view[1], y, x) elseif vertical and x > size or not vertical and y > size then -- Zero y or x relative to the other view based on split orientation. - return get_view( - view[2], vertical and y or y - size - 1, vertical and x - size - 1 or x) + return get_view(view[2], vertical and y or y - size - 1, vertical and x - size - 1 or x) else return view -- in-between views; return the split itself end @@ -516,8 +497,8 @@ end events.connect(events.INITIALIZED, function() local lua_error = (not WIN32 and '^/' or '^%a:[/\\]') .. '.-%.lua:%d+:' -- Print internal Lua error messages as they are reported. - -- Attempt to mimic the Lua interpreter's error message format so tools that - -- look for it can recognize these errors too. + -- Attempt to mimic the Lua interpreter's error message format so tools that look for it can + -- recognize these errors too. events.connect(events.ERROR, function(text) if text and text:find(lua_error) then text = 'lua: ' .. text end ui.print(text) @@ -528,8 +509,7 @@ end) --- -- A table of menus defining a menubar. (Write-only). --- This is a low-level field. You probably want to use the higher-level --- `textadept.menu.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 @@ -544,13 +524,11 @@ local size The functions below are Lua C functions. --- --- Low-level function for prompting the user with a [gtdialog][] of kind *kind* --- with the given string and table arguments, returning a formatted string of --- the dialog's output. --- You probably want to use the higher-level functions in the [`ui.dialogs`]() --- module. --- Table arguments containing strings are allowed and expanded in place. This is --- useful for filtered list dialogs with many items. +-- Low-level function for prompting the user with a [gtdialog][] of kind *kind* with the given +-- string and table arguments, returning a formatted string of the dialog's output. +-- You probably want to use the higher-level functions in the [`ui.dialogs`]() module. +-- Table arguments containing strings are allowed and expanded in place. This is useful for +-- filtered list dialogs with many items. -- -- [gtdialog]: https://orbitalquark.github.io/gtdialog/manual.html -- @param kind The kind of gtdialog. @@ -563,18 +541,16 @@ local dialog --- -- Returns a split table that contains Textadept's current split view structure. -- This is primarily used in session saving. --- @return table of split views. Each split view entry is a table with 4 --- fields: `1`, `2`, `vertical`, and `size`. `1` and `2` have values of either --- nested split view entries or the views themselves; `vertical` is a flag --- that indicates if the split is vertical or not; and `size` is the integer --- position of the split resizer. +-- @return table of split views. Each split view entry is a table with 4 fields: `1`, `2`, +-- `vertical`, and `size`. `1` and `2` have values of either nested split view entries or +-- the views themselves; `vertical` is a flag that indicates if the split is vertical or not; +-- and `size` is the integer position of the split resizer. -- @class function -- @name get_split_table local get_split_table --- --- Shifts to view *view* or the view *view* number of views relative to the --- current one. +-- Shifts to view *view* or the view *view* number of views relative to the current one. -- Emits `VIEW_BEFORE_SWITCH` and `VIEW_AFTER_SWITCH` events. -- @param view A view or relative view number (typically 1 or -1). -- @see _G._VIEWS @@ -585,17 +561,15 @@ local get_split_table local goto_view --- --- Low-level function for creating a menu from table *menu_table* and returning --- the userdata. +-- 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.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 --- menu. '_' characters are treated as a menu mnemonics. If the menu item is --- empty, a menu separator item is created. Submenus are just nested --- menu-structure tables. Their title text is defined with a `title` key. +-- @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 menu. '_' characters are treated as a menu +-- mnemonics. If the menu item is empty, a menu separator item is created. Submenus are just +-- nested menu-structure tables. Their title text is defined with a `title` key. -- @usage ui.menu{ {'_New', 1}, {'_Open', 2}, {''}, {'_Quit', 4} } -- @usage ui.menu{ {'_New', 1, string.byte('n'), 4} } -- 'Ctrl+N' -- @see events.MENU_CLICKED |