martanne / vis

A vi-like editor based on Plan 9's structural regular expressions
Other
4.26k stars 258 forks source link

Autocomplete all selections with <C-n> #950

Closed sauterp closed 2 months ago

sauterp commented 3 years ago

fixes https://github.com/martanne/vis/issues/949

Autocomplete in INSERT mode by completes all selections based on the suggestions generated by the input at the primary selection's cursor.

Shugyousha commented 3 years ago

Refactoring out the common parts like this may be nicer:

diff --git a/lua/plugins/complete-word.lua b/lua/plugins/complete-word.lua
index f0a6ff5..737cabe 100644
--- a/lua/plugins/complete-word.lua
+++ b/lua/plugins/complete-word.lua
@@ -2,17 +2,25 @@
 -- all non-primary selections will be completed aswell if their cursor
 -- is located at the end of the same word

+local get_prefix = function (file, pos)
+       if not pos then return "", false end
+
+       local range = file:text_object_word(pos > 0 and pos-1 or pos);
+       if not range then return "", false end
+       if range.finish > pos then range.finish = pos end
+       if range.start == range.finish then return "", false end
+       local prefix = file:content(range)
+       if not prefix then return "", false end
+       return prefix, true
+end
+
 vis:map(vis.modes.INSERT, "<C-n>", function()
    local win = vis.win
    local file = win.file
    local pos = win.selection.pos
-   if not pos then return end
-   local range = file:text_object_word(pos > 0 and pos-1 or pos);
-   if not range then return end
-   if range.finish > pos then range.finish = pos end
-   if range.start == range.finish then return end
-   local prefix = file:content(range)
-   if not prefix then return end
+   prefix, ok = get_prefix(file, pos)
+   if not ok then return end
+
    local cmd = string.format("vis-complete --word '%s'", prefix:gsub("'", "'\\''"))
    local status, out, err = vis:pipe(file, { start = 0, finish = file.size }, cmd)
    if status ~= 0 or not out then
@@ -21,14 +29,8 @@ vis:map(vis.modes.INSERT, "<C-n>", function()
    end
    for selection in win:selections_iterator() do
        local pos = selection.pos
-       if not pos then goto continue end
-
-       local range = file:text_object_word(pos > 0 and pos-1 or pos);
-       if not range then goto continue end
-       if range.finish > pos then range.finish = pos end
-       if range.start == range.finish then goto continue end
-       local localprefix = file:content(range)
-       if not localprefix then goto continue end
+       localprefix, ok = get_prefix(file, pos)
+       if not ok then goto continue end
        if localprefix ~= prefix then goto continue end

        file:insert(pos, out)

Other than that it looks good to me (with very basic testing)!