From cf29a6a45f190c85ed3423a883307c3b9251e2d3 Mon Sep 17 00:00:00 2001 From: Guldoman Date: Sun, 14 Aug 2022 01:56:58 +0200 Subject: [PATCH] Allow command predicates to manage parameters passed to the commands When a command is performed with parameters, those are now passed to the predicate. The predicate can then return, after the validity boolean, any other value that will then be passed to the actual command. If the predicate only returns the validity boolean, the original parameters are passed through to the actual command. This allows predicates to manipulate the received parameters, and allows them to pass the result of an expensive computation to the actual command, which won't have to recalculate it. String and table predicates will now also return `core.active_view`. --- data/core/command.lua | 16 +- data/core/commands/command.lua | 20 +-- data/core/commands/dialog.lua | 15 +- data/core/commands/doc.lua | 297 ++++++++++++++++---------------- data/core/commands/root.lua | 35 ++-- data/plugins/autocomplete.lua | 7 +- data/plugins/contextmenu.lua | 4 +- data/plugins/detectindent.lua | 8 +- data/plugins/quote.lua | 4 +- data/plugins/reflow.lua | 4 +- data/plugins/tabularize.lua | 6 +- data/plugins/treeview.lua | 36 ++-- data/plugins/trimwhitespace.lua | 4 +- 13 files changed, 223 insertions(+), 233 deletions(-) diff --git a/data/core/command.lua b/data/core/command.lua index f54854a4..82f79b35 100644 --- a/data/core/command.lua +++ b/data/core/command.lua @@ -33,9 +33,9 @@ function command.generate_predicate(predicate) if type(predicate) == "table" then local class = predicate if not strict then - predicate = function() return core.active_view:extends(class) end + predicate = function(...) return core.active_view:extends(class), core.active_view, ... end else - predicate = function() return core.active_view:is(class) end + predicate = function(...) return core.active_view:is(class), core.active_view, ... end end end return predicate @@ -76,8 +76,16 @@ end local function perform(name, ...) local cmd = command.map[name] - if cmd and cmd.predicate(...) then - cmd.perform(...) + if not cmd then return false end + local res = { cmd.predicate(...) } + if table.remove(res, 1) then + if #res > 0 then + -- send values returned from predicate + cmd.perform(table.unpack(res)) + else + -- send original parameters + cmd.perform(...) + end return true end return false diff --git a/data/core/commands/command.lua b/data/core/commands/command.lua index 1a635a86..44e894f5 100644 --- a/data/core/commands/command.lua +++ b/data/core/commands/command.lua @@ -2,23 +2,23 @@ local core = require "core" local command = require "core.command" command.add("core.commandview", { - ["command:submit"] = function() - core.active_view:submit() + ["command:submit"] = function(active_view) + active_view:submit() end, - ["command:complete"] = function() - core.active_view:complete() + ["command:complete"] = function(active_view) + active_view:complete() end, - ["command:escape"] = function() - core.active_view:exit() + ["command:escape"] = function(active_view) + active_view:exit() end, - ["command:select-previous"] = function() - core.active_view:move_suggestion_idx(1) + ["command:select-previous"] = function(active_view) + active_view:move_suggestion_idx(1) end, - ["command:select-next"] = function() - core.active_view:move_suggestion_idx(-1) + ["command:select-next"] = function(active_view) + active_view:move_suggestion_idx(-1) end, }) diff --git a/data/core/commands/dialog.lua b/data/core/commands/dialog.lua index 90606abb..1f3b4e71 100644 --- a/data/core/commands/dialog.lua +++ b/data/core/commands/dialog.lua @@ -3,30 +3,25 @@ local command = require "core.command" local common = require "core.common" command.add("core.nagview", { - ["dialog:previous-entry"] = function() - local v = core.active_view + ["dialog:previous-entry"] = function(v) local hover = v.hovered_item or 1 v:change_hovered(hover == 1 and #v.options or hover - 1) end, - ["dialog:next-entry"] = function() - local v = core.active_view + ["dialog:next-entry"] = function(v) local hover = v.hovered_item or 1 v:change_hovered(hover == #v.options and 1 or hover + 1) end, - ["dialog:select-yes"] = function() - local v = core.active_view + ["dialog:select-yes"] = function(v) if v ~= core.nag_view then return end v:change_hovered(common.find_index(v.options, "default_yes")) command.perform "dialog:select" end, - ["dialog:select-no"] = function() - local v = core.active_view + ["dialog:select-no"] = function(v) if v ~= core.nag_view then return end v:change_hovered(common.find_index(v.options, "default_no")) command.perform "dialog:select" end, - ["dialog:select"] = function() - local v = core.active_view + ["dialog:select"] = function(v) if v.hovered_item then v.on_selected(v.options[v.hovered_item]) v:next() diff --git a/data/core/commands/doc.lua b/data/core/commands/doc.lua index ceaffff7..365c0d19 100644 --- a/data/core/commands/doc.lua +++ b/data/core/commands/doc.lua @@ -89,13 +89,13 @@ local function split_cursor(direction) core.blink_reset() end -local function set_cursor(x, y, snap_type) - local line, col = dv():resolve_screen_position(x, y) - doc():set_selection(line, col, line, col) +local function set_cursor(dv, x, y, snap_type) + local line, col = dv:resolve_screen_position(x, y) + dv.doc:set_selection(line, col, line, col) if snap_type == "word" or snap_type == "lines" then command.perform("doc:select-" .. snap_type) end - dv().mouse_selecting = { line, col, snap_type } + dv.mouse_selecting = { line, col, snap_type } core.blink_reset() end @@ -178,9 +178,9 @@ local function block_comment(comment, line1, col1, line2, col2) end local commands = { - ["doc:select-none"] = function() - local line, col = doc():get_selection() - doc():set_selection(line, col) + ["doc:select-none"] = function(dv) + local line, col = dv.doc:get_selection() + dv.doc:set_selection(line, col) end, ["doc:cut"] = function() @@ -191,15 +191,15 @@ local commands = { cut_or_copy(false) end, - ["doc:undo"] = function() - doc():undo() + ["doc:undo"] = function(dv) + dv.doc:undo() end, - ["doc:redo"] = function() - doc():redo() + ["doc:redo"] = function(dv) + dv.doc:redo() end, - ["doc:paste"] = function() + ["doc:paste"] = function(dv) local clipboard = system.get_clipboard() -- If the clipboard has changed since our last look, use that instead local external_paste = core.cursor_clipboard["full"] ~= clipboard @@ -208,8 +208,8 @@ local commands = { core.cursor_clipboard_whole_line = {} end local value, whole_line - for idx, line1, col1, line2, col2 in doc():get_selections() do - if #core.cursor_clipboard_whole_line == (#doc().selections/4) then + for idx, line1, col1, line2, col2 in dv.doc:get_selections() do + if #core.cursor_clipboard_whole_line == (#dv.doc.selections/4) then value = core.cursor_clipboard[idx] whole_line = core.cursor_clipboard_whole_line[idx] == true else @@ -217,172 +217,172 @@ local commands = { whole_line = not external_paste and clipboard:find("\n") ~= nil end if whole_line then - doc():insert(line1, 1, value:gsub("\r", "")) + dv.doc:insert(line1, 1, value:gsub("\r", "")) if col1 == 1 then - doc():move_to_cursor(idx, #value) + dv.doc:move_to_cursor(idx, #value) end else - doc():text_input(value:gsub("\r", ""), idx) + dv.doc:text_input(value:gsub("\r", ""), idx) end end end, - ["doc:newline"] = function() - for idx, line, col in doc():get_selections(false, true) do - local indent = doc().lines[line]:match("^[\t ]*") + ["doc:newline"] = function(dv) + for idx, line, col in dv.doc:get_selections(false, true) do + local indent = dv.doc.lines[line]:match("^[\t ]*") if col <= #indent then indent = indent:sub(#indent + 2 - col) end -- Remove current line if it contains only whitespace - if doc().lines[line]:match("^%s+$") then - doc():remove(line, 1, line, math.huge) + if dv.doc.lines[line]:match("^%s+$") then + dv.doc:remove(line, 1, line, math.huge) end - doc():text_input("\n" .. indent, idx) + dv.doc:text_input("\n" .. indent, idx) end end, - ["doc:newline-below"] = function() - for idx, line in doc():get_selections(false, true) do - local indent = doc().lines[line]:match("^[\t ]*") - doc():insert(line, math.huge, "\n" .. indent) - doc():set_selections(idx, line + 1, math.huge) + ["doc:newline-below"] = function(dv) + for idx, line in dv.doc:get_selections(false, true) do + local indent = dv.doc.lines[line]:match("^[\t ]*") + dv.doc:insert(line, math.huge, "\n" .. indent) + dv.doc:set_selections(idx, line + 1, math.huge) end end, - ["doc:newline-above"] = function() - for idx, line in doc():get_selections(false, true) do - local indent = doc().lines[line]:match("^[\t ]*") - doc():insert(line, 1, indent .. "\n") - doc():set_selections(idx, line, math.huge) + ["doc:newline-above"] = function(dv) + for idx, line in dv.doc:get_selections(false, true) do + local indent = dv.doc.lines[line]:match("^[\t ]*") + dv.doc:insert(line, 1, indent .. "\n") + dv.doc:set_selections(idx, line, math.huge) end end, - ["doc:delete"] = function() - for idx, line1, col1, line2, col2 in doc():get_selections() do - if line1 == line2 and col1 == col2 and doc().lines[line1]:find("^%s*$", col1) then - doc():remove(line1, col1, line1, math.huge) + ["doc:delete"] = function(dv) + for idx, line1, col1, line2, col2 in dv.doc:get_selections() do + if line1 == line2 and col1 == col2 and dv.doc.lines[line1]:find("^%s*$", col1) then + dv.doc:remove(line1, col1, line1, math.huge) end - doc():delete_to_cursor(idx, translate.next_char) + dv.doc:delete_to_cursor(idx, translate.next_char) end end, - ["doc:backspace"] = function() - local _, indent_size = doc():get_indent_info() - for idx, line1, col1, line2, col2 in doc():get_selections() do + ["doc:backspace"] = function(dv) + local _, indent_size = dv.doc:get_indent_info() + for idx, line1, col1, line2, col2 in dv.doc:get_selections() do if line1 == line2 and col1 == col2 then - local text = doc():get_text(line1, 1, line1, col1) + local text = dv.doc:get_text(line1, 1, line1, col1) if #text >= indent_size and text:find("^ *$") then - doc():delete_to_cursor(idx, 0, -indent_size) + dv.doc:delete_to_cursor(idx, 0, -indent_size) return end end - doc():delete_to_cursor(idx, translate.previous_char) + dv.doc:delete_to_cursor(idx, translate.previous_char) end end, - ["doc:select-all"] = function() - doc():set_selection(1, 1, math.huge, math.huge) + ["doc:select-all"] = function(dv) + dv.doc:set_selection(1, 1, math.huge, math.huge) -- avoid triggering DocView:scroll_to_make_visible - dv().last_line1 = 1 - dv().last_col1 = 1 - dv().last_line2 = #doc().lines - dv().last_col2 = #doc().lines[#doc().lines] + dv.last_line1 = 1 + dv.last_col1 = 1 + dv.last_line2 = #dv.doc.lines + dv.last_col2 = #dv.doc.lines[#dv.doc.lines] end, - ["doc:select-lines"] = function() - for idx, line1, _, line2 in doc():get_selections(true) do + ["doc:select-lines"] = function(dv) + for idx, line1, _, line2 in dv.doc:get_selections(true) do append_line_if_last_line(line2) - doc():set_selections(idx, line1, 1, line2 + 1, 1) + dv.doc:set_selections(idx, line1, 1, line2 + 1, 1) end end, - ["doc:select-word"] = function() - for idx, line1, col1 in doc():get_selections(true) do - local line1, col1 = translate.start_of_word(doc(), line1, col1) - local line2, col2 = translate.end_of_word(doc(), line1, col1) - doc():set_selections(idx, line2, col2, line1, col1) + ["doc:select-word"] = function(dv) + for idx, line1, col1 in dv.doc:get_selections(true) do + local line1, col1 = translate.start_of_word(dv.doc, line1, col1) + local line2, col2 = translate.end_of_word(dv.doc, line1, col1) + dv.doc:set_selections(idx, line2, col2, line1, col1) end end, - ["doc:join-lines"] = function() - for idx, line1, col1, line2, col2 in doc():get_selections(true) do + ["doc:join-lines"] = function(dv) + for idx, line1, col1, line2, col2 in dv.doc:get_selections(true) do if line1 == line2 then line2 = line2 + 1 end - local text = doc():get_text(line1, 1, line2, math.huge) + local text = dv.doc:get_text(line1, 1, line2, math.huge) text = text:gsub("(.-)\n[\t ]*", function(x) return x:find("^%s*$") and x or x .. " " end) - doc():insert(line1, 1, text) - doc():remove(line1, #text + 1, line2, math.huge) + dv.doc:insert(line1, 1, text) + dv.doc:remove(line1, #text + 1, line2, math.huge) if line1 ~= line2 or col1 ~= col2 then - doc():set_selections(idx, line1, math.huge) + dv.doc:set_selections(idx, line1, math.huge) end end end, - ["doc:indent"] = function() + ["doc:indent"] = function(dv) for idx, line1, col1, line2, col2 in doc_multiline_selections(true) do - local l1, c1, l2, c2 = doc():indent_text(false, line1, col1, line2, col2) + local l1, c1, l2, c2 = dv.doc:indent_text(false, line1, col1, line2, col2) if l1 then - doc():set_selections(idx, l1, c1, l2, c2) + dv.doc:set_selections(idx, l1, c1, l2, c2) end end end, - ["doc:unindent"] = function() + ["doc:unindent"] = function(dv) for idx, line1, col1, line2, col2 in doc_multiline_selections(true) do - local l1, c1, l2, c2 = doc():indent_text(true, line1, col1, line2, col2) + local l1, c1, l2, c2 = dv.doc:indent_text(true, line1, col1, line2, col2) if l1 then - doc():set_selections(idx, l1, c1, l2, c2) + dv.doc:set_selections(idx, l1, c1, l2, c2) end end end, - ["doc:duplicate-lines"] = function() + ["doc:duplicate-lines"] = function(dv) for idx, line1, col1, line2, col2 in doc_multiline_selections(true) do append_line_if_last_line(line2) local text = doc():get_text(line1, 1, line2 + 1, 1) - doc():insert(line2 + 1, 1, text) + dv.doc:insert(line2 + 1, 1, text) local n = line2 - line1 + 1 - doc():set_selections(idx, line1 + n, col1, line2 + n, col2) + dv.doc:set_selections(idx, line1 + n, col1, line2 + n, col2) end end, - ["doc:delete-lines"] = function() + ["doc:delete-lines"] = function(dv) for idx, line1, col1, line2, col2 in doc_multiline_selections(true) do append_line_if_last_line(line2) - doc():remove(line1, 1, line2 + 1, 1) - doc():set_selections(idx, line1, col1) + dv.doc:remove(line1, 1, line2 + 1, 1) + dv.doc:set_selections(idx, line1, col1) end end, - ["doc:move-lines-up"] = function() + ["doc:move-lines-up"] = function(dv) for idx, line1, col1, line2, col2 in doc_multiline_selections(true) do append_line_if_last_line(line2) if line1 > 1 then local text = doc().lines[line1 - 1] - doc():insert(line2 + 1, 1, text) - doc():remove(line1 - 1, 1, line1, 1) - doc():set_selections(idx, line1 - 1, col1, line2 - 1, col2) + dv.doc:insert(line2 + 1, 1, text) + dv.doc:remove(line1 - 1, 1, line1, 1) + dv.doc:set_selections(idx, line1 - 1, col1, line2 - 1, col2) end end end, - ["doc:move-lines-down"] = function() + ["doc:move-lines-down"] = function(dv) for idx, line1, col1, line2, col2 in doc_multiline_selections(true) do append_line_if_last_line(line2 + 1) - if line2 < #doc().lines then - local text = doc().lines[line2 + 1] - doc():remove(line2 + 1, 1, line2 + 2, 1) - doc():insert(line1, 1, text) - doc():set_selections(idx, line1 + 1, col1, line2 + 1, col2) + if line2 < #dv.doc.lines then + local text = dv.doc.lines[line2 + 1] + dv.doc:remove(line2 + 1, 1, line2 + 2, 1) + dv.doc:insert(line1, 1, text) + dv.doc:set_selections(idx, line1 + 1, col1, line2 + 1, col2) end end end, - ["doc:toggle-block-comments"] = function() - local comment = doc().syntax.block_comment + ["doc:toggle-block-comments"] = function(dv) + local comment = dv.doc.syntax.block_comment if not comment then - if doc().syntax.comment then + if dv.doc.syntax.comment then command.perform "doc:toggle-line-comments" end return @@ -392,32 +392,30 @@ local commands = { -- if nothing is selected, toggle the whole line if line1 == line2 and col1 == col2 then col1 = 1 - col2 = #doc().lines[line2] + col2 = #dv.doc.lines[line2] end - doc():set_selections(idx, block_comment(comment, line1, col1, line2, col2)) + dv.doc:set_selections(idx, block_comment(comment, line1, col1, line2, col2)) end end, - ["doc:toggle-line-comments"] = function() - local comment = doc().syntax.comment or doc().syntax.block_comment + ["doc:toggle-line-comments"] = function(dv) + local comment = dv.doc.syntax.comment or dv.doc.syntax.block_comment if comment then for idx, line1, col1, line2, col2 in doc_multiline_selections(true) do - doc():set_selections(idx, line_comment(comment, line1, col1, line2, col2)) + dv.doc:set_selections(idx, line_comment(comment, line1, col1, line2, col2)) end end end, - ["doc:upper-case"] = function() - doc():replace(string.uupper) + ["doc:upper-case"] = function(dv) + dv.doc:replace(string.uupper) end, - ["doc:lower-case"] = function() - doc():replace(string.ulower) + ["doc:lower-case"] = function(dv) + dv.doc:replace(string.ulower) end, - ["doc:go-to-line"] = function() - local dv = dv() - + ["doc:go-to-line"] = function(dv) local items local function init_items() if items then return end @@ -448,15 +446,15 @@ local commands = { }) end, - ["doc:toggle-line-ending"] = function() - doc().crlf = not doc().crlf + ["doc:toggle-line-ending"] = function(dv) + dv.doc.crlf = not dv.doc.crlf end, - ["doc:save-as"] = function() + ["doc:save-as"] = function(dv) local last_doc = core.last_active_view and core.last_active_view.doc local text - if doc().filename then - text = doc().filename + if dv.doc.filename then + text = dv.doc.filename elseif last_doc and last_doc.filename then local dirname, filename = core.last_active_view.doc.abs_filename:match("(.*)[/\\](.+)$") text = core.normalize_to_project_dir(dirname) .. PATHSEP @@ -472,20 +470,20 @@ local commands = { }) end, - ["doc:save"] = function() - if doc().filename then + ["doc:save"] = function(dv) + if dv.doc.filename then save() else command.perform("doc:save-as") end end, - ["doc:reload"] = function() - doc():reload() + ["doc:reload"] = function(dv) + dv.doc:reload() end, - ["file:rename"] = function() - local old_filename = doc().filename + ["file:rename"] = function(dv) + local old_filename = dv.doc.filename if not old_filename then core.error("Cannot rename unsaved doc") return @@ -506,13 +504,13 @@ local commands = { end, - ["file:delete"] = function() - local filename = doc().abs_filename + ["file:delete"] = function(dv) + local filename = dv.doc.abs_filename if not filename then core.error("Cannot remove unsaved doc") return end - for i,docview in ipairs(core.get_views_referencing_doc(doc())) do + for i,docview in ipairs(core.get_views_referencing_doc(dv.doc)) do local node = core.root_view.root_node:get_node_for_view(docview) node:close_view(core.root_view.root_node, docview) end @@ -520,56 +518,57 @@ local commands = { core.log("Removed \"%s\"", filename) end, - ["doc:select-to-cursor"] = function(x, y, clicks) + ["doc:select-to-cursor"] = function(dv, x, y, clicks) local line1, col1 = select(3, doc():get_selection()) - local line2, col2 = dv():resolve_screen_position(x, y) - dv().mouse_selecting = { line1, col1, nil } - doc():set_selection(line2, col2, line1, col1) + local line2, col2 = dv:resolve_screen_position(x, y) + dv.mouse_selecting = { line1, col1, nil } + dv.doc:set_selection(line2, col2, line1, col1) end, - ["doc:create-cursor-previous-line"] = function() + ["doc:create-cursor-previous-line"] = function(dv) split_cursor(-1) - doc():merge_cursors() + dv.doc:merge_cursors() end, - ["doc:create-cursor-next-line"] = function() + ["doc:create-cursor-next-line"] = function(dv) split_cursor(1) - doc():merge_cursors() + dv.doc:merge_cursors() end } command.add(function(x, y) - if x == nil or y == nil or not doc() then return false end - local x1,y1,x2,y2 = dv().position.x, dv().position.y, dv().position.x + dv().size.x, dv().position.y + dv().size.y - return x >= x1 + dv():get_gutter_width() and x < x2 and y >= y1 and y < y2 + if x == nil or y == nil or not core.active_view:is(DocView) then return false end + local dv = core.active_view + local x1,y1,x2,y2 = dv.position.x, dv.position.y, dv.position.x + dv.size.x, dv.position.y + dv.size.y + return x >= x1 + dv:get_gutter_width() and x < x2 and y >= y1 and y < y2, dv, x, y end, { - ["doc:set-cursor"] = function(x, y) - set_cursor(x, y, "set") + ["doc:set-cursor"] = function(dv, x, y) + set_cursor(dv, x, y, "set") end, - ["doc:set-cursor-word"] = function(x, y) - set_cursor(x, y, "word") + ["doc:set-cursor-word"] = function(dv, x, y) + set_cursor(dv, x, y, "word") end, - ["doc:set-cursor-line"] = function(x, y, clicks) - set_cursor(x, y, "lines") + ["doc:set-cursor-line"] = function(dv, x, y, clicks) + set_cursor(dv, x, y, "lines") end, - ["doc:split-cursor"] = function(x, y, clicks) - local line, col = dv():resolve_screen_position(x, y) + ["doc:split-cursor"] = function(dv, x, y, clicks) + local line, col = dv:resolve_screen_position(x, y) local removal_target = nil - for idx, line1, col1 in doc():get_selections(true) do + for idx, line1, col1 in dv.doc:get_selections(true) do if line1 == line and col1 == col and #doc().selections > 4 then removal_target = idx end end if removal_target then - doc():remove_selection(removal_target) + dv.doc:remove_selection(removal_target) else - doc():add_selection(line, col, line, col) + dv.doc:add_selection(line, col, line, col) end - dv().mouse_selecting = { line, col, "set" } + dv.mouse_selecting = { line, col, "set" } end }) @@ -594,27 +593,27 @@ local translations = { } for name, obj in pairs(translations) do - commands["doc:move-to-" .. name] = function() doc():move_to(obj[name:gsub("-", "_")], dv()) end - commands["doc:select-to-" .. name] = function() doc():select_to(obj[name:gsub("-", "_")], dv()) end - commands["doc:delete-to-" .. name] = function() doc():delete_to(obj[name:gsub("-", "_")], dv()) end + commands["doc:move-to-" .. name] = function(dv) dv.doc:move_to(obj[name:gsub("-", "_")], dv) end + commands["doc:select-to-" .. name] = function(dv) dv.doc:select_to(obj[name:gsub("-", "_")], dv) end + commands["doc:delete-to-" .. name] = function(dv) dv.doc:delete_to(obj[name:gsub("-", "_")], dv) end end -commands["doc:move-to-previous-char"] = function() - for idx, line1, col1, line2, col2 in doc():get_selections(true) do +commands["doc:move-to-previous-char"] = function(dv) + for idx, line1, col1, line2, col2 in dv.doc:get_selections(true) do if line1 ~= line2 or col1 ~= col2 then - doc():set_selections(idx, line1, col1) + dv.doc:set_selections(idx, line1, col1) else - doc():move_to_cursor(idx, translate.previous_char) + dv.doc:move_to_cursor(idx, translate.previous_char) end end end -commands["doc:move-to-next-char"] = function() - for idx, line1, col1, line2, col2 in doc():get_selections(true) do +commands["doc:move-to-next-char"] = function(dv) + for idx, line1, col1, line2, col2 in dv.doc:get_selections(true) do if line1 ~= line2 or col1 ~= col2 then - doc():set_selections(idx, line2, col2) + dv.doc:set_selections(idx, line2, col2) else - doc():move_to_cursor(idx, translate.next_char) + dv.doc:move_to_cursor(idx, translate.next_char) end end end diff --git a/data/core/commands/root.lua b/data/core/commands/root.lua index c75c3e90..deea858e 100644 --- a/data/core/commands/root.lua +++ b/data/core/commands/root.lua @@ -7,13 +7,11 @@ local config = require "core.config" local t = { - ["root:close"] = function() - local node = core.root_view:get_active_node() + ["root:close"] = function(node) node:close_active_view(core.root_view.root_node) end, - ["root:close-or-quit"] = function() - local node = core.root_view:get_active_node() + ["root:close-or-quit"] = function(node) if node and (not node:is_empty() or not node.is_primary_node) then node:close_active_view(core.root_view.root_node) else @@ -31,24 +29,21 @@ local t = { core.confirm_close_docs(docs, core.root_view.close_all_docviews, core.root_view, true) end, - ["root:switch-to-previous-tab"] = function() - local node = core.root_view:get_active_node() + ["root:switch-to-previous-tab"] = function(node) local idx = node:get_view_idx(core.active_view) idx = idx - 1 if idx < 1 then idx = #node.views end node:set_active_view(node.views[idx]) end, - ["root:switch-to-next-tab"] = function() - local node = core.root_view:get_active_node() + ["root:switch-to-next-tab"] = function(node) local idx = node:get_view_idx(core.active_view) idx = idx + 1 if idx > #node.views then idx = 1 end node:set_active_view(node.views[idx]) end, - ["root:move-tab-left"] = function() - local node = core.root_view:get_active_node() + ["root:move-tab-left"] = function(node) local idx = node:get_view_idx(core.active_view) if idx > 1 then table.remove(node.views, idx) @@ -56,8 +51,7 @@ local t = { end end, - ["root:move-tab-right"] = function() - local node = core.root_view:get_active_node() + ["root:move-tab-right"] = function(node) local idx = node:get_view_idx(core.active_view) if idx < #node.views then table.remove(node.views, idx) @@ -65,15 +59,13 @@ local t = { end end, - ["root:shrink"] = function() - local node = core.root_view:get_active_node() + ["root:shrink"] = function(node) local parent = node:get_parent_node(core.root_view.root_node) local n = (parent.a == node) and -0.1 or 0.1 parent.divider = common.clamp(parent.divider + n, 0.1, 0.9) end, - ["root:grow"] = function() - local node = core.root_view:get_active_node() + ["root:grow"] = function(node) local parent = node:get_parent_node(core.root_view.root_node) local n = (parent.a == node) and 0.1 or -0.1 parent.divider = common.clamp(parent.divider + n, 0.1, 0.9) @@ -82,8 +74,7 @@ local t = { for i = 1, 9 do - t["root:switch-to-tab-" .. i] = function() - local node = core.root_view:get_active_node() + t["root:switch-to-tab-" .. i] = function(node) local view = node.views[i] if view then node:set_active_view(view) @@ -93,8 +84,7 @@ end for _, dir in ipairs { "left", "right", "up", "down" } do - t["root:split-" .. dir] = function() - local node = core.root_view:get_active_node() + t["root:split-" .. dir] = function(node) local av = node.active_view node:split(dir) if av:is(DocView) then @@ -102,8 +92,7 @@ for _, dir in ipairs { "left", "right", "up", "down" } do end end - t["root:switch-to-" .. dir] = function() - local node = core.root_view:get_active_node() + t["root:switch-to-" .. dir] = function(node) local x, y if dir == "left" or dir == "right" then y = node.position.y + node.size.y / 2 @@ -123,7 +112,7 @@ end command.add(function() local node = core.root_view:get_active_node() local sx, sy = node:get_locked_size() - return not sx and not sy + return not sx and not sy, node end, t) command.add(nil, { diff --git a/data/plugins/autocomplete.lua b/data/plugins/autocomplete.lua index ca4a4cc6..2a9cff0f 100644 --- a/data/plugins/autocomplete.lua +++ b/data/plugins/autocomplete.lua @@ -621,12 +621,13 @@ end -- Commands -- local function predicate() - return get_active_view() and #suggestions > 0 + local active_docview = get_active_view() + return active_docview and #suggestions > 0, active_docview end command.add(predicate, { - ["autocomplete:complete"] = function() - local doc = core.active_view.doc + ["autocomplete:complete"] = function(dv) + local doc = dv.doc local line, col = doc:get_selection() local item = suggestions[suggestions_idx] local text = item.text diff --git a/data/plugins/contextmenu.lua b/data/plugins/contextmenu.lua index 03fb83dc..db6d28db 100644 --- a/data/plugins/contextmenu.lua +++ b/data/plugins/contextmenu.lua @@ -33,8 +33,8 @@ function RootView:draw(...) end command.add("core.docview!", { - ["context:show"] = function() - menu:show(core.active_view.position.x, core.active_view.position.y) + ["context:show"] = function(dv) + menu:show(dv.position.x, dv.position.y) end }) diff --git a/data/plugins/detectindent.lua b/data/plugins/detectindent.lua index e6634a9b..3ab0ee45 100644 --- a/data/plugins/detectindent.lua +++ b/data/plugins/detectindent.lua @@ -299,10 +299,10 @@ local function set_indent_type(doc, type) doc.indent_info = cache[doc] end -local function set_indent_type_command() +local function set_indent_type_command(dv) core.command_view:enter("Specify indent style for this file", { submit = function(value) - local doc = core.active_view.doc + local doc = dv.doc value = value:lower() set_indent_type(doc, value == "tabs" and "hard" or "soft") end, @@ -327,11 +327,11 @@ local function set_indent_size(doc, size) doc.indent_info = cache[doc] end -local function set_indent_size_command() +local function set_indent_size_command(dv) core.command_view:enter("Specify indent size for current file", { submit = function(value) value = math.floor(tonumber(value)) - local doc = core.active_view.doc + local doc = dv.doc set_indent_size(doc, value) end, validate = function(value) diff --git a/data/plugins/quote.lua b/data/plugins/quote.lua index 2f5a9b2b..60f0cf1e 100644 --- a/data/plugins/quote.lua +++ b/data/plugins/quote.lua @@ -19,8 +19,8 @@ end command.add("core.docview", { - ["quote:quote"] = function() - core.active_view.doc:replace(function(text) + ["quote:quote"] = function(dv) + dv.doc:replace(function(text) return '"' .. text:gsub("[\0-\31\\\"]", replace) .. '"' end) end, diff --git a/data/plugins/reflow.lua b/data/plugins/reflow.lua index be6e2562..e70b06f6 100644 --- a/data/plugins/reflow.lua +++ b/data/plugins/reflow.lua @@ -25,8 +25,8 @@ end command.add("core.docview", { - ["reflow:reflow"] = function() - local doc = core.active_view.doc + ["reflow:reflow"] = function(dv) + local doc = dv.doc doc:replace(function(text) local prefix_set = "[^%w\n%[%](){}`'\"]*" diff --git a/data/plugins/tabularize.lua b/data/plugins/tabularize.lua index 46d2d2be..5185fbf6 100644 --- a/data/plugins/tabularize.lua +++ b/data/plugins/tabularize.lua @@ -41,17 +41,17 @@ end command.add("core.docview", { - ["tabularize:tabularize"] = function() + ["tabularize:tabularize"] = function(dv) core.command_view:enter("Tabularize On Delimiter", { submit = function(delim) if delim == "" then delim = " " end - local doc = core.active_view.doc + local doc = dv.doc local line1, col1, line2, col2, swap = doc:get_selection(true) line1, col1 = doc:position_offset(line1, col1, translate.start_of_line) line2, col2 = doc:position_offset(line2, col2, translate.end_of_line) doc:set_selection(line1, col1, line2, col2, swap) - + doc:replace(function(text) local lines = gmatch_to_array(text, "[^\n]*\n?") tabularize_lines(lines, delim) diff --git a/data/plugins/treeview.lua b/data/plugins/treeview.lua index 272fcc9d..d3a7cf79 100644 --- a/data/plugins/treeview.lua +++ b/data/plugins/treeview.lua @@ -679,16 +679,16 @@ local function treeitem() return view.hovered_item or view.selected_item end command.add( function() - return treeitem() ~= nil + local item = treeitem() + return item ~= nil and ( core.active_view == view or core.active_view == menu or (view.toolbar and core.active_view == view.toolbar) -- sometimes the context menu is shown on top of statusbar or core.active_view == core.status_view - ) + ), item end, { - ["treeview:delete"] = function() - local item = treeitem() + ["treeview:delete"] = function(item) local filename = item.abs_filename local relfilename = item.filename if item.dir_name ~= core.project_dir then @@ -732,9 +732,11 @@ command.add( }) -command.add(function() return treeitem() ~= nil end, { - ["treeview:rename"] = function() +command.add(function() local item = treeitem() + return item ~= nil, item + end, { + ["treeview:rename"] = function(item) local old_filename = item.filename local old_abs_filename = item.abs_filename core.command_view:enter("Rename", { @@ -764,9 +766,8 @@ command.add(function() return treeitem() ~= nil end, { }) end, - ["treeview:new-file"] = function() + ["treeview:new-file"] = function(item) local text - local item = treeitem() if not is_project_folder(item.abs_filename) then text = item.filename .. PATHSEP end @@ -787,9 +788,8 @@ command.add(function() return treeitem() ~= nil end, { }) end, - ["treeview:new-folder"] = function() + ["treeview:new-folder"] = function(item) local text - local item = treeitem() if not is_project_folder(item.abs_filename) then text = item.filename .. PATHSEP end @@ -806,15 +806,13 @@ command.add(function() return treeitem() ~= nil end, { }) end, - ["treeview:open-in-system"] = function() - local hovered_item = treeitem() - + ["treeview:open-in-system"] = function(item) if PLATFORM == "Windows" then - system.exec(string.format("start \"\" %q", hovered_item.abs_filename)) + system.exec(string.format("start \"\" %q", item.abs_filename)) elseif string.find(PLATFORM, "Mac") then - system.exec(string.format("open %q", hovered_item.abs_filename)) + system.exec(string.format("open %q", item.abs_filename)) elseif PLATFORM == "Linux" or string.find(PLATFORM, "BSD") then - system.exec(string.format("xdg-open %q", hovered_item.abs_filename)) + system.exec(string.format("xdg-open %q", item.abs_filename)) end end }) @@ -823,10 +821,10 @@ command.add(function() local item = treeitem() return item and not is_primary_project_folder(item.abs_filename) - and is_project_folder(item.abs_filename) + and is_project_folder(item.abs_filename), item end, { - ["treeview:remove-project-directory"] = function() - core.remove_project_directory(treeitem().dir_name) + ["treeview:remove-project-directory"] = function(item) + core.remove_project_directory(item.dir_name) end, }) diff --git a/data/plugins/trimwhitespace.lua b/data/plugins/trimwhitespace.lua index 93db502a..d6057da8 100644 --- a/data/plugins/trimwhitespace.lua +++ b/data/plugins/trimwhitespace.lua @@ -24,8 +24,8 @@ end command.add("core.docview", { - ["trim-whitespace:trim-trailing-whitespace"] = function() - trim_trailing_whitespace(core.active_view.doc) + ["trim-whitespace:trim-trailing-whitespace"] = function(dv) + trim_trailing_whitespace(dv.doc) end, })