Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add option to force the visual mode #2

Merged
merged 1 commit into from
Oct 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 16 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,35 +22,35 @@ This includes lazy-loading on keymaps. If you install like this, you can ignore
keys = {
{
"ai",
"<Cmd>lua require'treesitter_indent_object.textobj'.select_indent_outer()<CR>",
function() require'treesitter_indent_object.textobj'.select_indent_outer() end,
mode = {"x", "o"},
desc = "Select context-aware indent (outer)",
},
{
"aI",
"<Cmd>lua require'treesitter_indent_object.textobj'.select_indent_outer(true)<CR>",
function() require'treesitter_indent_object.textobj'.select_indent_outer(true) end,
mode = {"x", "o"},
desc = "Select context-aware indent (outer, line-wise)",
},
{
"ii",
"<Cmd>lua require'treesitter_indent_object.textobj'.select_indent_inner()<CR>",
function() require'treesitter_indent_object.textobj'.select_indent_inner() end,
mode = {"x", "o"},
desc = "Select context-aware indent (inner, partial range)",
},
{
"iI",
"<Cmd>lua require'treesitter_indent_object.textobj'.select_indent_inner(true)<CR>",
function() require'treesitter_indent_object.textobj'.select_indent_inner(true, 'V') end,
mode = {"x", "o"},
desc = "Select context-aware indent (inner, entire range)",
desc = "Select context-aware indent (inner, entire range) in line-wise visual mode",
},
},
},
```

<details>
<summary>Click to see instructions for packer and vim-plug</summary>

#### Example with Packer

[wbthomason/packer.nvim](https://github.com/wbthomason/packer.nvim)
Expand Down Expand Up @@ -94,7 +94,7 @@ require("indent_blankline").setup {
require("treesitter_indent_object").setup()
```

Key bindings are not configured by default.
Key bindings are not configured by default.
Here are some examples.

```vim
Expand All @@ -107,22 +107,22 @@ omap aI <Cmd>lua require'treesitter_indent_object.textobj'.select_indent_outer(t
" vii to select inner block (only if block, only else block, etc.)
xmap ii <Cmd>lua require'treesitter_indent_object.textobj'.select_indent_inner()<CR>
omap ii <Cmd>lua require'treesitter_indent_object.textobj'.select_indent_inner()<CR>
" viI to select entire inner range (including if, else, etc.)
xmap iI <Cmd>lua require'treesitter_indent_object.textobj'.select_indent_inner(true)<CR>
omap iI <Cmd>lua require'treesitter_indent_object.textobj'.select_indent_inner(true)<CR>
" viI to select entire inner range (including if, else, etc.) in line-wise visual mode
xmap iI <Cmd>lua require'treesitter_indent_object.textobj'.select_indent_inner(true, 'V')<CR>
omap iI <Cmd>lua require'treesitter_indent_object.textobj'.select_indent_inner(true, 'V')<CR>
```

Lua equivalent:
Lua equivalent:

```lua
-- select context-aware indent
vim.keymap.set({"x", "o"}, "ai", "<Cmd>lua require'treesitter_indent_object.textobj'.select_indent_outer()<CR>")
vim.keymap.set({"x", "o"}, "ai", function() require'treesitter_indent_object.textobj'.select_indent_outer() end)
-- ensure selecting entire line (or just use Vai)
vim.keymap.set({"x", "o"}, "aI", "<Cmd>lua require'treesitter_indent_object.textobj'.select_indent_outer(true)<CR>")
vim.keymap.set({"x", "o"}, "aI", function() require'treesitter_indent_object.textobj'.select_indent_outer(true) end)
-- select inner block (only if block, only else block, etc.)
vim.keymap.set({"x", "o"}, "ii", "<Cmd>lua require'treesitter_indent_object.textobj'.select_indent_inner()<CR>")
-- select entire inner range (including if, else, etc.)
vim.keymap.set({"x", "o"}, "iI", "<Cmd>lua require'treesitter_indent_object.textobj'.select_indent_inner(true)<CR>")
vim.keymap.set({"x", "o"}, "ii", function() require'treesitter_indent_object.textobj'.select_indent_inner() end)
-- select entire inner range (including if, else, etc.) in line-wise visual mode
vim.keymap.set({"x", "o"}, "iI", function() require'treesitter_indent_object.textobj'.select_indent_inner(true, 'V') end)
```

</details>
29 changes: 21 additions & 8 deletions lua/treesitter_indent_object/textobj.lua
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,28 @@ local ts_indent_status, ts_indent = pcall(require, "nvim-treesitter.indent")
local M = {}


local enter_visual_mode = function()
local enter_visual_mode = function(force_mode)
-- enter visual mode if normal or operator-pending (no) mode
-- Why? According to https://learnvimscriptthehardway.stevelosh.com/chapters/15.html
-- If your operator-pending mapping ends with some text visually selected, Vim will operate on that text.
-- Otherwise, Vim will operate on the text between the original cursor position and the new position.
local mode = vim.api.nvim_get_mode()
--print(mode.mode, mode.blocking)
if mode.mode == 'no' or mode.mode == 'n' then
vim.cmd("normal! v")

-- If set to 'V', try to force line-wise visual mode
if force_mode == 'V' then
if mode.mode == 'no' or mode.mode == 'n' or mode.mode == 'v' then
vim.cmd("normal! V")
end
-- If set to 'v', try to force char-wise visual mode
elseif force_mode == 'v' then
if mode.mode == 'no' or mode.mode == 'n' or mode.mode == 'V' then
vim.cmd("normal! v")
end
-- If not specified, respect the current visual mode
else
if mode.mode == 'no' or mode.mode == 'n' then
vim.cmd("normal! v")
end
end
end

Expand All @@ -39,18 +52,18 @@ local update_selection = function (node, entire_line)
end
end

M.select_indent_outer = function(entire_line)
M.select_indent_outer = function(entire_line, force_mode)
entire_line = entire_line or false
-- We have to remember that end_col is end-exclusive
local context_status, context_node, context_pattern =
utils.get_current_context(vim.g.treesitter_indent_object_context_patterns, vim.g.treesitter_indent_object_use_treesitter_scope)
if not context_status then return false end

enter_visual_mode()
enter_visual_mode(force_mode)
update_selection(context_node, entire_line)
end

M.select_indent_inner = function(select_all)
M.select_indent_inner = function(select_all, force_mode)
select_all = select_all or false
local use_ts_indent = ts_query_status and ts_indent_status and ts_query.has_indents(vim.bo.filetype)
local indent_fn = nil
Expand Down Expand Up @@ -192,7 +205,7 @@ M.select_indent_inner = function(select_all)
-- end
end

enter_visual_mode()
enter_visual_mode(force_mode)
vim.api.nvim_win_set_cursor(0, {indented_row_start, 0})
vim.cmd("normal! ^o")
vim.api.nvim_win_set_cursor(0, {indented_row_end, 0})
Expand Down
Loading