aboutsummaryrefslogtreecommitdiff
path: root/data/core/commands
diff options
context:
space:
mode:
Diffstat (limited to 'data/core/commands')
-rw-r--r--data/core/commands/core.lua30
-rw-r--r--data/core/commands/doc.lua25
-rw-r--r--data/core/commands/findreplace.lua133
-rw-r--r--data/core/commands/root.lua8
4 files changed, 151 insertions, 45 deletions
diff --git a/data/core/commands/core.lua b/data/core/commands/core.lua
index feca573e..e836ea2f 100644
--- a/data/core/commands/core.lua
+++ b/data/core/commands/core.lua
@@ -66,9 +66,8 @@ command.add(nil, {
end,
["core:find-file"] = function()
- -- FIXME: core.project_files_limit was removed!
- if core.project_files_limit then
- return command.perform "core:open-file"
+ if not core.project_files_number() then
+ return command.perform "core:open-file"
end
local files = {}
for dir, item in core.get_project_files() do
@@ -105,11 +104,20 @@ command.add(nil, {
end, function (text)
return common.home_encode_list(common.path_suggest(common.home_expand(text)))
end, nil, function(text)
- local path_stat, err = system.get_file_info(common.home_expand(text))
+ local filename = common.home_expand(text)
+ local path_stat, err = system.get_file_info(filename)
if err then
- core.error("Cannot open file %q: %q", text, err)
+ if err:find("No such file", 1, true) then
+ -- check if the containing directory exists
+ local dirname = common.dirname(filename)
+ local dir_stat = dirname and system.get_file_info(dirname)
+ if not dirname or (dir_stat and dir_stat.type == 'dir') then
+ return true
+ end
+ end
+ core.error("Cannot open file %s: %s", text, err)
elseif path_stat.type == 'dir' then
- core.error("Cannot open %q, is a folder", text)
+ core.error("Cannot open %s, is a folder", text)
else
return true
end
@@ -139,6 +147,10 @@ command.add(nil, {
end,
["core:change-project-folder"] = function()
+ local dirname = common.dirname(core.project_dir)
+ if dirname then
+ core.command_view:set_text(common.home_encode(dirname) .. PATHSEP)
+ end
core.command_view:enter("Change Project Folder", function(text, item)
text = system.absolute_path(common.home_expand(item and item.text or text))
if text == core.project_dir then return end
@@ -147,11 +159,15 @@ command.add(nil, {
core.error("Cannot open folder %q", text)
return
end
- core.confirm_close_all(core.open_folder_project, text)
+ core.confirm_close_docs(core.docs, core.open_folder_project, text)
end, suggest_directory)
end,
["core:open-project-folder"] = function()
+ local dirname = common.dirname(core.project_dir)
+ if dirname then
+ core.command_view:set_text(common.home_encode(dirname) .. PATHSEP)
+ end
core.command_view:enter("Open Project", function(text, item)
text = common.home_expand(item and item.text or text)
local path_stat = system.get_file_info(text)
diff --git a/data/core/commands/doc.lua b/data/core/commands/doc.lua
index 815d9511..fb17e674 100644
--- a/data/core/commands/doc.lua
+++ b/data/core/commands/doc.lua
@@ -43,9 +43,13 @@ local function append_line_if_last_line(line)
end
local function save(filename)
- doc():save(filename and core.normalize_to_project_dir(filename))
+ local abs_filename
+ if filename then
+ filename = core.normalize_to_project_dir(filename)
+ abs_filename = core.project_absolute_path(filename)
+ end
+ doc():save(filename, abs_filename)
local saved_filename = doc().filename
- core.on_doc_save(saved_filename)
core.log("Saved \"%s\"", saved_filename)
end
@@ -63,13 +67,14 @@ local function cut_or_copy(delete)
doc().cursor_clipboard[idx] = ""
end
end
+ doc().cursor_clipboard["full"] = full_text
system.set_clipboard(full_text)
end
local function split_cursor(direction)
local new_cursors = {}
for _, line1, col1 in doc():get_selections() do
- if line1 > 1 and line1 < #doc().lines then
+ if line1 + direction >= 1 and line1 + direction <= #doc().lines then
table.insert(new_cursors, { line1 + direction, col1 })
end
end
@@ -95,8 +100,13 @@ local commands = {
end,
["doc:paste"] = function()
+ local clipboard = system.get_clipboard()
+ -- If the clipboard has changed since our last look, use that instead
+ if doc().cursor_clipboard["full"] ~= clipboard then
+ doc().cursor_clipboard = {}
+ end
for idx, line1, col1, line2, col2 in doc():get_selections() do
- local value = doc().cursor_clipboard[idx] or system.get_clipboard()
+ local value = doc().cursor_clipboard[idx] or clipboard
doc():text_input(value:gsub("\r", ""), idx)
end
end,
@@ -364,12 +374,14 @@ local commands = {
end
core.command_view:set_text(old_filename)
core.command_view:enter("Rename", function(filename)
- doc():save(filename)
+ save(common.home_expand(filename))
core.log("Renamed \"%s\" to \"%s\"", old_filename, filename)
if filename ~= old_filename then
os.remove(old_filename)
end
- end, common.path_suggest)
+ end, function (text)
+ return common.home_encode_list(common.path_suggest(common.home_expand(text)))
+ end)
end,
@@ -412,6 +424,7 @@ local translations = {
["start-of-line"] = translate.start_of_line,
["end-of-line"] = translate.end_of_line,
["start-of-word"] = translate.start_of_word,
+ ["start-of-indentation"] = translate.start_of_indentation,
["end-of-word"] = translate.end_of_word,
["previous-line"] = DocView.translate.previous_line,
["next-line"] = DocView.translate.next_line,
diff --git a/data/core/commands/findreplace.lua b/data/core/commands/findreplace.lua
index e5d7c70b..f8e8e45a 100644
--- a/data/core/commands/findreplace.lua
+++ b/data/core/commands/findreplace.lua
@@ -10,48 +10,62 @@ local StatusView = require "core.statusview"
local max_last_finds = 50
local last_finds, last_view, last_fn, last_text, last_sel
-local case_insensitive = config.find_case_insensitive or false
-local plain = config.find_plain or false
+local case_sensitive = config.find_case_sensitive or false
+local find_regex = config.find_regex or false
+local found_expression
local function doc()
- return last_view and last_view.doc or core.active_view.doc
+ return core.active_view:is(DocView) and core.active_view.doc or last_view.doc
end
local function get_find_tooltip()
local rf = keymap.get_binding("find-replace:repeat-find")
- local ti = keymap.get_binding("find-replace:toggle-insensitivity")
- local tr = keymap.get_binding("find-replace:toggle-plain")
- return (plain and "[Plain] " or "") ..
- (case_insensitive and "[Insensitive] " or "") ..
+ local ti = keymap.get_binding("find-replace:toggle-sensitivity")
+ local tr = keymap.get_binding("find-replace:toggle-regex")
+ return (find_regex and "[Regex] " or "") ..
+ (case_sensitive and "[Sensitive] " or "") ..
(rf and ("Press " .. rf .. " to select the next match.") or "") ..
(ti and (" " .. ti .. " toggles case sensitivity.") or "") ..
- (tr and (" " .. tr .. " toggles plain find.") or "")
+ (tr and (" " .. tr .. " toggles regex find.") or "")
end
local function update_preview(sel, search_fn, text)
- local ok, line1, col1, line2, col2 =
- pcall(search_fn, last_view.doc, sel[1], sel[2], text, case_insensitive, plain)
+ local ok, line1, col1, line2, col2 = pcall(search_fn, last_view.doc,
+ sel[1], sel[2], text, case_sensitive, find_regex)
if ok and line1 and text ~= "" then
last_view.doc:set_selection(line2, col2, line1, col1)
last_view:scroll_to_line(line2, true)
- return true
+ found_expression = true
else
last_view.doc:set_selection(unpack(sel))
- return false
+ found_expression = false
end
end
+
+local function insert_unique(t, v)
+ local n = #t
+ for i = 1, n do
+ if t[i] == v then return end
+ end
+ t[n + 1] = v
+end
+
+
local function find(label, search_fn)
last_view, last_sel, last_finds = core.active_view,
{ core.active_view.doc:get_selection() }, {}
- local text, found = last_view.doc:get_text(unpack(last_sel)), false
+ local text = last_view.doc:get_text(unpack(last_sel))
+ found_expression = false
core.command_view:set_text(text, true)
core.status_view:show_tooltip(get_find_tooltip())
- core.command_view:enter(label, function(text)
+ core.command_view:set_hidden_suggestions()
+ core.command_view:enter(label, function(text, item)
+ insert_unique(core.previous_find, text)
core.status_view:remove_tooltip()
- if found then
+ if found_expression then
last_fn, last_text = search_fn, text
else
core.error("Couldn't find %q", text)
@@ -59,8 +73,9 @@ local function find(label, search_fn)
last_view:scroll_to_make_visible(unpack(last_sel))
end
end, function(text)
- found = update_preview(last_sel, search_fn, text)
+ update_preview(last_sel, search_fn, text)
last_fn, last_text = search_fn, text
+ return core.previous_find
end, function(explicit)
core.status_view:remove_tooltip()
if explicit then
@@ -75,18 +90,25 @@ local function replace(kind, default, fn)
core.command_view:set_text(default, true)
core.status_view:show_tooltip(get_find_tooltip())
+ core.command_view:set_hidden_suggestions()
core.command_view:enter("Find To Replace " .. kind, function(old)
+ insert_unique(core.previous_find, old)
core.command_view:set_text(old, true)
local s = string.format("Replace %s %q With", kind, old)
+ core.command_view:set_hidden_suggestions()
core.command_view:enter(s, function(new)
+ core.status_view:remove_tooltip()
+ insert_unique(core.previous_replace, new)
local n = doc():replace(function(text)
return fn(text, old, new)
end)
core.log("Replaced %d instance(s) of %s %q with %q", n, kind, old, new)
- end, function() end, function()
+ end, function() return core.previous_replace end, function()
core.status_view:remove_tooltip()
end)
+ end, function() return core.previous_find end, function()
+ core.status_view:remove_tooltip()
end)
end
@@ -94,29 +116,78 @@ local function has_selection()
return core.active_view:is(DocView) and core.active_view.doc:has_selection()
end
-command.add(has_selection, {
+local function has_unique_selection()
+ if not core.active_view:is(DocView) then return false end
+ local text = nil
+ for idx, line1, col1, line2, col2 in doc():get_selections(true, true) do
+ if line1 == line2 and col1 == col2 then return false end
+ local selection = doc():get_text(line1, col1, line2, col2)
+ if text ~= nil and text ~= selection then return false end
+ text = selection
+ end
+ return text ~= nil
+end
+
+local function is_in_selection(line, col, l1, c1, l2, c2)
+ if line < l1 or line > l2 then return false end
+ if line == l1 and col <= c1 then return false end
+ if line == l2 and col > c2 then return false end
+ return true
+end
+
+local function is_in_any_selection(line, col)
+ for idx, l1, c1, l2, c2 in doc():get_selections(true, false) do
+ if is_in_selection(line, col, l1, c1, l2, c2) then return true end
+ end
+ return false
+end
+
+local function select_next(all)
+ local il1, ic1 = doc():get_selection(true)
+ for idx, l1, c1, l2, c2 in doc():get_selections(true, true) do
+ local text = doc():get_text(l1, c1, l2, c2)
+ repeat
+ l1, c1, l2, c2 = search.find(doc(), l2, c2, text, { wrap = true })
+ if l1 == il1 and c1 == ic1 then break end
+ if l2 and (all or not is_in_any_selection(l2, c2)) then
+ doc():add_selection(l2, c2, l1, c1)
+ if not all then
+ core.active_view:scroll_to_make_visible(l2, c2)
+ return
+ end
+ end
+ until not all or not l2
+ if all then break end
+ end
+end
+
+command.add(has_unique_selection, {
["find-replace:select-next"] = function()
local l1, c1, l2, c2 = doc():get_selection(true)
local text = doc():get_text(l1, c1, l2, c2)
l1, c1, l2, c2 = search.find(doc(), l2, c2, text, { wrap = true })
if l2 then doc():set_selection(l2, c2, l1, c1) end
- end
+ end,
+ ["find-replace:select-add-next"] = function() select_next(false) end,
+ ["find-replace:select-add-all"] = function() select_next(true) end
})
command.add("core.docview", {
["find-replace:find"] = function()
- find("Find Text", function(doc, line, col, text, case_insensitive, plain)
- local opt = { wrap = true, no_case = case_insensitive, regex = not plain }
+ find("Find Text", function(doc, line, col, text, case_sensitive, find_regex)
+ local opt = { wrap = true, no_case = not case_sensitive, regex = find_regex }
return search.find(doc, line, col, text, opt)
end)
end,
["find-replace:replace"] = function()
- replace("Text", doc():get_text(doc():get_selection(true)), function(text, old, new)
- if plain then
+ local l1, c1, l2, c2 = doc():get_selection()
+ local selected_text = doc():get_text(l1, c1, l2, c2)
+ replace("Text", l1 == l2 and selected_text or "", function(text, old, new)
+ if not find_regex then
return text:gsub(old:gsub("%W", "%%%1"), new:gsub("%%", "%%%%"), nil)
end
- local result, matches = regex.gsub(regex.compile(old), text, new)
+ local result, matches = regex.gsub(regex.compile(old, "m"), text, new)
return result, #matches
end)
end,
@@ -150,7 +221,7 @@ command.add(valid_for_finding, {
core.error("No find to continue from")
else
local sl1, sc1, sl2, sc2 = doc():get_selection(true)
- local line1, col1, line2, col2 = last_fn(doc(), sl1, sc2, last_text, case_insensitive, plain)
+ local line1, col1, line2, col2 = last_fn(doc(), sl1, sc2, last_text, case_sensitive, find_regex)
if line1 then
if last_view.doc ~= doc() then
last_finds = {}
@@ -177,15 +248,15 @@ command.add(valid_for_finding, {
})
command.add("core.commandview", {
- ["find-replace:toggle-insensitivity"] = function()
- case_insensitive = not case_insensitive
+ ["find-replace:toggle-sensitivity"] = function()
+ case_sensitive = not case_sensitive
core.status_view:show_tooltip(get_find_tooltip())
- update_preview(last_sel, last_fn, last_text)
+ if last_sel then update_preview(last_sel, last_fn, last_text) end
end,
- ["find-replace:toggle-plain"] = function()
- plain = not plain
+ ["find-replace:toggle-regex"] = function()
+ find_regex = not find_regex
core.status_view:show_tooltip(get_find_tooltip())
- update_preview(last_sel, last_fn, last_text)
+ if last_sel then update_preview(last_sel, last_fn, last_text) end
end
})
diff --git a/data/core/commands/root.lua b/data/core/commands/root.lua
index 7bc13283..e41c723d 100644
--- a/data/core/commands/root.lua
+++ b/data/core/commands/root.lua
@@ -21,9 +21,15 @@ local t = {
end,
["root:close-all"] = function()
- core.confirm_close_all(core.root_view.close_all_docviews, core.root_view)
+ core.confirm_close_docs(core.docs, core.root_view.close_all_docviews, core.root_view)
end,
+ ["root:close-all-others"] = function()
+ local active_doc, docs = core.active_view and core.active_view.doc, {}
+ for i, v in ipairs(core.docs) do if v ~= active_doc then table.insert(docs, v) end end
+ 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()
local idx = node:get_view_idx(core.active_view)