Skip to content

Commit

Permalink
feat: Implement change_line mapping.
Browse files Browse the repository at this point in the history
Resolves #244.

* Implement preliminary change_line mapping

As of this commit, given the input, where `|` denotes the cursor
position:
```
let x = foo(args|);
```

`cS)(` yields:
```
let x = foo(|
    args
);
```

The indentation of `args` depends on the indentation rules for the filetype.

We still need to iron out behavior for complex surrounds like HTML tags
and functions. Currently, given the input, where `|` denotes the cursor
position:
```
let x = foo(args|);
```

Both `csf` AND `cSf` with `bar` would yield:
```
let x = |bar(args);
```

This follows because the change target selection is just the `foo`.
However, users may instead want the result to be:
```
let x = |bar(
    args
);
```

This is more useful because otherwise, `cs` and `cS` would be exhibiting
the same behavior.

* Write basic tests for change_line

* Add missing `delimiters` type annotation for normal cache

This is unrelated to the PR, but Kyle caught this while reviewing it and
asked me to put it in.
  • Loading branch information
srithon authored and kylechui committed May 28, 2023
1 parent 26b5067 commit ff9c981
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 7 deletions.
4 changes: 2 additions & 2 deletions lua/nvim-surround/cache.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ local M = {}

-- These variables hold cache values for dot-repeating the three actions

---@type { line_mode: boolean }
---@type { delimiters: string[][]|nil, line_mode: boolean }
M.normal = {}
---@type { char: string }
M.delete = {}
---@type { del_char: string, add_delimiters: add_func }
---@type { del_char: string, add_delimiters: add_func, line_mode: boolean }
M.change = {}

-- Sets the callback function for dot-repeating.
Expand Down
27 changes: 26 additions & 1 deletion lua/nvim-surround/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ M.default_opts = {
visual_line = "gS",
delete = "ds",
change = "cs",
change_line = "cS",
},
surrounds = {
["("] = {
Expand Down Expand Up @@ -706,14 +707,29 @@ M.set_keymaps = function(args)
M.set_keymap({
mode = "n",
lhs = "<Plug>(nvim-surround-change)",
rhs = require("nvim-surround").change_surround,
rhs = function()
return require("nvim-surround").change_surround({ line_mode = false })
end,
opts = {
buffer = args.buffer,
desc = "Change a surrounding pair",
expr = true,
silent = true,
},
})
M.set_keymap({
mode = "n",
lhs = "<Plug>(nvim-surround-change-line)",
rhs = function()
return require("nvim-surround").change_surround({ line_mode = true })
end,
opts = {
buffer = args.buffer,
desc = "Change a surrounding pair, putting replacements on new lines",
expr = true,
silent = true,
},
})

-- Set up user-defined keymaps
M.set_keymap({
Expand Down Expand Up @@ -806,6 +822,15 @@ M.set_keymaps = function(args)
desc = "Change a surrounding pair",
},
})
M.set_keymap({
name = "change",
mode = "n",
lhs = M.get_opts().keymaps.change_line,
rhs = "<Plug>(nvim-surround-change-line)",
opts = {
desc = "Change a surrounding pair, putting replacements on new lines",
},
})
end

-- Setup the global user options for all files.
Expand Down
16 changes: 12 additions & 4 deletions lua/nvim-surround/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -176,13 +176,13 @@ M.delete_surround = function(args)
end

-- Change a surrounding delimiter pair, if it exists.
---@param args { curpos: position, del_char: string, add_delimiters: add_func }|nil
---@param args { curpos: position, del_char: string, add_delimiters: add_func, line_mode: boolean }
---@return "g@l"|nil
M.change_surround = function(args)
-- Call the operatorfunc if it has not been called yet
if not args then
if not args.del_char or not args.add_delimiters then
-- Clear the change cache (since it was user-called)
cache.change = {}
cache.change = { line_mode = args.line_mode }

vim.go.operatorfunc = "v:lua.require'nvim-surround'.change_callback"
return "g@l"
Expand Down Expand Up @@ -222,6 +222,13 @@ M.change_surround = function(args)
first_pos = selections.left.first_pos,
old_pos = args.curpos,
})

if args.line_mode then
local first_pos = selections.left.first_pos
local last_pos = selections.right.last_pos

config.get_opts().indent_lines(first_pos[1], last_pos[1] + #delimiters[1] + #delimiters[2] - 2)
end
end

cache.set_callback("v:lua.require'nvim-surround'.change_callback")
Expand Down Expand Up @@ -328,7 +335,7 @@ M.change_callback = function()
delimiters = change.replacement()
else
ins_char = input.get_char()
delimiters = config.get_delimiters(ins_char, false) -- TODO: Maybe add line-wise change surround?
delimiters = config.get_delimiters(ins_char, cache.change.line_mode)
end

-- Clear the highlights after getting the replacement surround
Expand All @@ -343,6 +350,7 @@ M.change_callback = function()
add_delimiters = function()
return delimiters
end,
line_mode = cache.change.line_mode,
}
end
local args = vim.deepcopy(cache.change)
Expand Down
42 changes: 42 additions & 0 deletions tests/basics_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,48 @@ describe("nvim-surround", function()
check_lines({ "[", "", "]" })
end)

it("can change delimiter pairs on new lines", function()
set_lines({
"require'nvim-surround'.setup(args)",
})
set_curpos({ 1, 29 })
vim.cmd("normal cS))")
check_lines({
"require'nvim-surround'.setup(",
"args",
")",
})
set_curpos({ 2, 1 })
vim.cmd([[normal ysab}]])
set_curpos({ 1, 29 })
vim.cmd("normal cS}]")
check_lines({
"require'nvim-surround'.setup[",
"(",
"args",
")",
"]",
})
vim.cmd("normal cS]{")
check_lines({
"require'nvim-surround'.setup{",
"",
"(",
"args",
")",
"",
"}",
})

set_lines({ "()" })
vim.cmd("normal cSbb")
check_lines({ "(", "", ")" })

set_lines({ "{", "", "}" })
vim.cmd("normal cSBB")
check_lines({ "{", "", "", "", "}" })
end)

it("can handle invalid key behavior", function()
set_lines({ "sample text" })
vim.cmd("normal yss|")
Expand Down

0 comments on commit ff9c981

Please sign in to comment.