From 85b9d0cbd4ff901abcda862b50dbb34e0901848b Mon Sep 17 00:00:00 2001 From: Phil Date: Sun, 31 Dec 2023 21:58:20 -0500 Subject: [PATCH] fix(select): patch #539 regression (#546) * fix(select): patch #539 regression * remove useless check * tests(select): add tests for selection mode * fix(select): handle possible "n" as selection_mode * fix(tests): adjust according to config keymaps * fix(tests): adjust params * fix(tests): do not compare the first command with itself --- lua/nvim-treesitter/textobjects/select.lua | 14 ++++++++--- scripts/minimal_init.lua | 3 +++ tests/select/common.lua | 27 ++++++++++++---------- tests/select/python/selection_mode.py | 8 +++++++ tests/select/python_spec.lua | 12 ++++++---- 5 files changed, 44 insertions(+), 20 deletions(-) create mode 100644 tests/select/python/selection_mode.py diff --git a/lua/nvim-treesitter/textobjects/select.lua b/lua/nvim-treesitter/textobjects/select.lua index c020382c..2f6dc885 100644 --- a/lua/nvim-treesitter/textobjects/select.lua +++ b/lua/nvim-treesitter/textobjects/select.lua @@ -134,11 +134,19 @@ function M.detect_selection_mode(query_string, keymap_mode) selection_mode = selection_modes or "v" end - if selection_mode == "n" then - selection_mode = "v" + local ret_value = selection_mode + local mode = vim.fn.mode(1) + local is_normal_or_charwise_v = mode == "n" or mode == "v" + + if not is_normal_or_charwise_v then + -- According to "mode()" mapping, if we are in operator pending mode or visual mode, + -- then last char is {v,V,}, exept for "no", which is "o", in which case we honor + -- last set `selection_mode` + local visual_mode = mode:sub(#mode) + ret_value = visual_mode == "o" and selection_mode or visual_mode end - return selection_mode + return ret_value == "n" and "v" or ret_value end M.keymaps_per_buf = {} diff --git a/scripts/minimal_init.lua b/scripts/minimal_init.lua index ddb29022..e017f8fe 100644 --- a/scripts/minimal_init.lua +++ b/scripts/minimal_init.lua @@ -66,6 +66,9 @@ require("nvim-treesitter.configs").setup { ["as"] = "@statement.outer", ["is"] = "@statement.outer", }, + selection_modes = { + ["@function.outer"] = "V", -- linewise + }, -- You can choose the select mode (default is charwise 'v') -- -- Can also be a function which gets passed a table with the keys diff --git a/tests/select/common.lua b/tests/select/common.lua index 861c9903..25718a25 100644 --- a/tests/select/common.lua +++ b/tests/select/common.lua @@ -3,13 +3,13 @@ local M = {} local assert = require "luassert" local Path = require "plenary.path" -function M.run_equal_cmds_test(file, spec) +function M.run_compare_cmds_test(file, spec, equal) assert.are.same(1, vim.fn.filereadable(file), string.format('File "%s" not readable', file)) -- load reference file vim.cmd(string.format("edit %s", file)) - local first_cmd_lines = nil + local to_compare_to = nil for _, cmd in pairs(spec.cmds) do -- set cursor pos vim.api.nvim_win_set_cursor(0, { spec.row, spec.col }) @@ -17,19 +17,22 @@ function M.run_equal_cmds_test(file, spec) vim.cmd([[normal ]] .. vim.api.nvim_replace_termcodes(cmd, true, true, true)) local lines = vim.api.nvim_buf_get_lines(0, 0, -1, true) - if first_cmd_lines == nil then - first_cmd_lines = lines - end -- clear any changes (avoid no write since last change) -- call before assert vim.cmd "edit!" - assert.are.same( - first_cmd_lines, - lines, - string.format("Commands %s and %s produces different results", spec.cmds[1], cmd) - ) + if to_compare_to == nil then + to_compare_to = lines + else + local assert_statement = equal and assert.are.same or assert.are.Not.same + local message = equal and "different" or "same" + assert_statement( + to_compare_to, + lines, + string.format("Commands %s and %s produces %s results", spec.cmds[1], cmd, message) + ) + end end end @@ -48,11 +51,11 @@ function Runner:new(it, base_dir, buf_opts) return setmetatable(runner, self) end -function Runner:equal_cmds(file, spec, title) +function Runner:compare_cmds(file, spec, title, equal) title = title and title or string.format("%s,%s", spec.row, spec.col) self.it(string.format("%s[%s]", file, title), function() local path = self.base_dir / file - M.run_equal_cmds_test(path.filename, spec) + M.run_compare_cmds_test(path.filename, spec, equal == nil and true or equal) end) end diff --git a/tests/select/python/selection_mode.py b/tests/select/python/selection_mode.py new file mode 100644 index 00000000..ecc3e1c9 --- /dev/null +++ b/tests/select/python/selection_mode.py @@ -0,0 +1,8 @@ +class Test: + def __init__(self, *arg): + my_list = [] + + for arg_ in arg: + my_list.append(arg_) + + self.my_list = my_list diff --git a/tests/select/python_spec.lua b/tests/select/python_spec.lua index fd68b688..5a32723a 100644 --- a/tests/select/python_spec.lua +++ b/tests/select/python_spec.lua @@ -8,9 +8,9 @@ local run = Runner:new(it, "tests/select/python", { }) describe("command equality Python:", function() - run:equal_cmds("aligned_indent.py", { row = 1, col = 0, cmds = { "daa", "vaad", "caa" } }) - run:equal_cmds("aligned_indent.py", { row = 1, col = 10, cmds = { "dia", "viad", "cia" } }) - run:equal_cmds("aligned_indent.py", { + run:compare_cmds("aligned_indent.py", { row = 1, col = 0, cmds = { "daa", "vaad", "caa" } }) + run:compare_cmds("aligned_indent.py", { row = 1, col = 10, cmds = { "dia", "viad", "cia" } }) + run:compare_cmds("aligned_indent.py", { row = 1, col = 0, cmds = { @@ -20,7 +20,9 @@ describe("command equality Python:", function() }, }) -- select using built-in finds (f, F, t, T) - run:equal_cmds("aligned_indent.py", { row = 1, col = 0, cmds = { "dfi", "vfid", "cfi" } }) + run:compare_cmds("aligned_indent.py", { row = 1, col = 0, cmds = { "dfi", "vfid", "cfi" } }) -- select using move - run:equal_cmds("aligned_indent.py", { row = 1, col = 0, cmds = { "d]a", "v]ad", "c]a" } }) + run:compare_cmds("aligned_indent.py", { row = 1, col = 0, cmds = { "d]a", "v]ad", "c]a" } }) + run:compare_cmds("selection_mode.py", { row = 2, col = 4, cmds = { "dam", "dVam", "vamd", "Vamd" } }) + run:compare_cmds("selection_mode.py", { row = 5, col = 8, cmds = { "dVao", "dao" } }, nil, false) end)