Skip to content

Commit 9a6aaa9

Browse files
author
Andrew Ferrier
committed
feat: Pick up variable under cursor - closes #2
1 parent 7761a90 commit 9a6aaa9

File tree

3 files changed

+182
-34
lines changed

3 files changed

+182
-34
lines changed

README.md

+35-23
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@ particular language, to trace the output of a program during execution.
1111
appropriate to the language being edited, which include the filename/line number
1212
they are being inserted on, a counter which increases over the duration of a
1313
NeoVim session each time a statement is generated, as well as optionally
14-
printing out a variable. `debugprint` comes with the generation logic built in
15-
for many common programming languages, and can be extended to support more.
14+
printing out a variable, including automatically picking up an
15+
identifier/variable name under the cursor. `debugprint` comes with the
16+
generation logic built in for many common programming languages, and can be
17+
extended to support more.
1618

1719
`debugprint` is inspired by
1820
[vim-debugstring](https://github.com/bergercookie/vim-debugstring), which I've
@@ -24,6 +26,8 @@ It provides various improvements:
2426

2527
* It [dot-repeats](https://jovicailic.org/2018/03/vim-the-dot-command/) with NeoVim.
2628

29+
* It can pick up a variable name from under the cursor.
30+
2731
* It indents the lines it inserts more accurately.
2832

2933
* The output when printing a 'plain' debug line, or a variable, is more
@@ -37,10 +41,18 @@ It provides various improvements:
3741
<video src="https://user-images.githubusercontent.com/107015/184187236-34f80a31-9626-4a3b-8d03-0f52752781e6.mp4" type="video/mp4"></video>
3842
</div>
3943

44+
(This demo is not yet updated to show automatically picking up a variable name
45+
from under the cursor).
46+
4047
## Installation
4148

4249
**Requires NeoVim 0.7+.**
4350

51+
Optional dependency:
52+
[nvim-treesitter](https://github.com/nvim-treesitter/nvim-treesitter). If this
53+
is not installed, `debugprint` will not find variable names under the cursor and
54+
will always prompt for a variable name.
55+
4456
Example for [`packer.nvim`](https://github.com/wbthomason/packer.nvim):
4557

4658
```lua
@@ -75,20 +87,23 @@ The sections below detail the allowed options.
7587

7688
## Keymappings
7789

78-
By default, the plugin will create the following normal-mode keymappings, which
79-
are the standard way to use it:
90+
By default, the plugin will create some normal-mode keymappings, which are the
91+
standard way to use it. There are also some function invocations which are not
92+
mapped to any keymappings by default, but could be. This is all shown in the
93+
following table.
8094

81-
| Keymap | Purpose | Equivalent Lua Function |
82-
| ------ | ---------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------- |
83-
| `dqp` | Insert a 'plain' debug line appropriate to the filetype just below the current line | `require('debugprint').debugprint()` |
84-
| `dqP` | The same, but above the current line | `require('debugprint').debugprint({above = true})` |
85-
| `dQP` | Prompt for a variable name, and insert a debugging line just below the current line which outputs it | `require('debugprint').debugprint({variable = true})` |
86-
| `dQP` | The same, but above the current line | `require('debugprint').debugprint({above = true, variable = true})` |
95+
| Keymap | Purpose | Equivalent Lua Function |
96+
| ------ | ---------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------- |
97+
| `dqp` | Insert a 'plain' debug line appropriate to the filetype just below the current line | `require('debugprint').debugprint()` |
98+
| `dqP` | The same, but above the current line | `require('debugprint').debugprint({above = true})` |
99+
| `dQP` | Insert a variable debugging line below the current line. If the cursor is on a variable name, use that, otherwise prompt for one. | `require('debugprint').debugprint({variable = true})` |
100+
| `dQP` | The same, but above the current line | `require('debugprint').debugprint({above = true, variable = true})` |
101+
| None by default | Always prompt for a variable name, and insert a debugging line just below the current line which outputs it | `require('debugprint').debugprint({ignore_treesitter = true, variable = true})` |
102+
| None by default | Always prompt for a variable name, and insert a debugging line just above the current line which outputs it | `require('debugprint').debugprint({ignore_treesitter = true, above = true, variable = true})` |
87103

88104
These keybindings are chosen not to conflict with any standard Vim keys (or any
89105
common plugins, at least that I'm aware of). You can disable them from being
90-
created by setting `create_keymaps`, and map them yourself to something else if
91-
you prefer:
106+
created by setting `create_keymaps`, and map them yourself if you prefer:
92107

93108
```lua
94109
opts = {
@@ -115,13 +130,14 @@ end)
115130

116131
## Other Options
117132

118-
`debugprint` supports the following options in its `opts` object:
133+
`debugprint` supports the following options in its global `opts` object:
119134

120-
| Option | Default | Purpose |
121-
| - | - | - |
122-
| `create_keymaps` | `true` | Creates default keymappings - see above |
123-
| `move_to_debugline` | `false` | When adding a debug line, moves the cursor to that line |
124-
| `filetypes` | See below | Custom filetypes - see below |
135+
| Option | Default | Purpose |
136+
| - | - | - |
137+
| `create_keymaps` | `true` | Creates default keymappings - see above |
138+
| `move_to_debugline` | `false` | When adding a debug line, moves the cursor to that line |
139+
| `filetypes` | See below | Custom filetypes - see below |
140+
| `ignore_treesitter` | `false` | Never use treesitter to find a variable under the cursor, always prompt for it - overrides the same setting on `debugprint()` if set to true |
125141

126142
## Add Custom Filetypes
127143

@@ -201,9 +217,6 @@ If it helps to understand these, you can look at the built-in configurations in
201217
Markdown)
202218
([issue](https://github.com/andrewferrier/debugprint.nvim/issues/9))
203219

204-
* Using Treesitter to dynamically detect variable names the cursor is on so
205-
they don't have to be typed.
206-
207220
## Known Limitations
208221

209222
* `debugprint` only supports variable names or simple expressions when using
@@ -216,8 +229,7 @@ If it helps to understand these, you can look at the built-in configurations in
216229

217230
* [refactoring.nvim](https://github.com/ThePrimeagen/refactoring.nvim) -
218231
similar capabilities to debugprint, supports a slighter smaller set of
219-
languages. Can pick up treesitter identifiers as variables and remove
220-
added statements - these are on the debugprint roadmap.
232+
languages. Can remove added statement - this is on the debugprint roadmap.
221233

222234
* [logsitter](https://github.com/gaelph/logsitter.nvim) - supports a smaller
223235
set of languages and requires you to set up your own autocmds/keymappings.

lua/debugprint/init.lua

+38-1
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@ local opts
55
OPTION_DEFAULTS = {
66
create_keymaps = true,
77
move_to_debugline = false,
8+
ignore_treesitter = false,
89
filetypes = require("debugprint.filetypes"),
910
}
1011

1112
FUNCTION_OPTION_DEFAULTS = {
1213
above = false,
1314
variable = false,
15+
ignore_treesitter = false,
1416
}
1517

1618
local counter = 0
@@ -60,6 +62,31 @@ local indent_line = function(current_line)
6062
end
6163
end
6264

65+
local find_treesitter_variable = function()
66+
local function requiref(module)
67+
require(module)
68+
end
69+
70+
local ts_utils_test = pcall(requiref, "nvim-treesitter.ts_utils")
71+
72+
if not ts_utils_test then
73+
return nil
74+
else
75+
local ts_utils = require("nvim-treesitter.ts_utils")
76+
-- Once get_node_at_cursor() is in NeoVim core, the nvim-treesitter
77+
-- dependency can be removed: https://github.com/neovim/neovim/pull/18232
78+
local node = ts_utils.get_node_at_cursor()
79+
local node_type = node:type()
80+
local variable_name = vim.treesitter.query.get_node_text(node, 0)
81+
82+
if node_type ~= "identifier" then
83+
return nil
84+
else
85+
return variable_name
86+
end
87+
end
88+
end
89+
6390
local debugprint_logic = function(funcopts)
6491
local current_line = vim.api.nvim_win_get_cursor(0)[1]
6592
local filetype = vim.api.nvim_get_option_value(
@@ -119,7 +146,16 @@ local debugprint_cache = function(o)
119146
end
120147

121148
if o.variable == true then
122-
o.variable_name = vim.fn.input("Variable name: ")
149+
if
150+
o.ignore_treesitter ~= true
151+
and opts.ignore_treesitter ~= true
152+
then
153+
o.variable_name = find_treesitter_variable()
154+
end
155+
156+
if o.variable_name == nil then
157+
o.variable_name = vim.fn.input("Variable name: ")
158+
end
123159
end
124160

125161
cache_request = o
@@ -146,6 +182,7 @@ M.debugprint = function(o)
146182
vim.validate({
147183
above = { funcopts.above, "boolean" },
148184
variable = { funcopts.above, "boolean" },
185+
ignore_treesitter = { funcopts.ignore_treesitter, "boolean" },
149186
})
150187

151188
funcopts.prerepeat = true

tests/debugprint.lua

+109-10
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ end)
3535

3636
describe("can do basic debug statement insertion", function()
3737
before_each(function()
38-
debugprint.setup()
38+
debugprint.setup({ ignore_treesitter = true })
3939
end)
4040

4141
it("can insert a basic statement below", function()
@@ -111,7 +111,7 @@ end)
111111

112112
describe("can do variable debug statement insertion", function()
113113
before_each(function()
114-
debugprint.setup()
114+
debugprint.setup({ ignore_treesitter = true })
115115
end)
116116

117117
it("can insert a variable statement below", function()
@@ -155,7 +155,7 @@ end)
155155

156156
describe("can do various file types", function()
157157
before_each(function()
158-
debugprint.setup()
158+
debugprint.setup({ ignore_treesitter = true })
159159
end)
160160

161161
it("can handle a .vim file", function()
@@ -235,7 +235,7 @@ end)
235235

236236
describe("can do indenting correctly", function()
237237
before_each(function()
238-
debugprint.setup()
238+
debugprint.setup({ ignore_treesitter = true })
239239
end)
240240

241241
it("lua - inside function", function()
@@ -315,6 +315,7 @@ end)
315315
describe("add custom filetype with setup()", function()
316316
before_each(function()
317317
debugprint.setup({
318+
ignore_treesitter = true,
318319
filetypes = {
319320
["wibble"] = {
320321
left = "foo('",
@@ -366,7 +367,7 @@ end)
366367

367368
describe("add custom filetype with add_custom_filetypes()", function()
368369
before_each(function()
369-
debugprint.setup()
370+
debugprint.setup({ ignore_treesitter = true })
370371

371372
vim.api.nvim_set_option_value("expandtab", true, {})
372373
vim.api.nvim_set_option_value("shiftwidth", 4, {})
@@ -405,7 +406,10 @@ describe("move to new line", function()
405406
end)
406407

407408
it("true below", function()
408-
debugprint.setup({ move_to_debugline = true })
409+
debugprint.setup({
410+
ignore_treesitter = true,
411+
move_to_debugline = true,
412+
})
409413

410414
set_lines({
411415
"foo",
@@ -426,7 +430,10 @@ describe("move to new line", function()
426430
end)
427431

428432
it("true above", function()
429-
debugprint.setup({ move_to_debugline = true })
433+
debugprint.setup({
434+
ignore_treesitter = true,
435+
move_to_debugline = true,
436+
})
430437

431438
set_lines({
432439
"foo",
@@ -447,7 +454,10 @@ describe("move to new line", function()
447454
end)
448455

449456
it("false", function()
450-
debugprint.setup({ move_to_debugline = false })
457+
debugprint.setup({
458+
ignore_treesitter = true,
459+
move_to_debugline = false,
460+
})
451461

452462
set_lines({
453463
"foo",
@@ -470,7 +480,10 @@ end)
470480

471481
describe("can repeat", function()
472482
before_each(function()
473-
debugprint.setup()
483+
debugprint.setup({
484+
ignore_treesitter = true,
485+
ignore_treesitter = true,
486+
})
474487
end)
475488

476489
it("can insert a basic statement and repeat", function()
@@ -571,7 +584,10 @@ end)
571584

572585
describe("can repeat with move to line", function()
573586
it("true below", function()
574-
debugprint.setup({ move_to_debugline = true })
587+
debugprint.setup({
588+
ignore_treesitter = true,
589+
move_to_debugline = true,
590+
})
575591

576592
set_lines({
577593
"foo",
@@ -593,3 +609,86 @@ describe("can repeat with move to line", function()
593609
assert.are.same(vim.api.nvim_win_get_cursor(0), { 3, 0 })
594610
end)
595611
end)
612+
613+
describe("can handle treesitter identifiers", function()
614+
it("standard", function()
615+
debugprint.setup({})
616+
617+
set_lines({
618+
"function x() {",
619+
"local xyz = 3",
620+
"end",
621+
})
622+
623+
local filename = write_file("lua")
624+
vim.api.nvim_win_set_cursor(0, { 2, 6 })
625+
feedkeys("dQp")
626+
627+
check_lines({
628+
"function x() {",
629+
"local xyz = 3",
630+
"print('DEBUG[1]: " .. filename .. ":2: xyz=' .. vim.inspect(xyz))",
631+
"end",
632+
})
633+
634+
assert.are.same(vim.api.nvim_win_get_cursor(0), { 2, 6 })
635+
end)
636+
637+
it("non-identifier", function()
638+
debugprint.setup({})
639+
640+
set_lines({
641+
"function x() {",
642+
"local xyz = 3",
643+
"end",
644+
})
645+
646+
local filename = write_file("lua")
647+
vim.api.nvim_win_set_cursor(0, { 2, 6 })
648+
feedkeys("dQpapple<CR>")
649+
650+
check_lines({
651+
"function x() {",
652+
"local xyz = 3",
653+
"print('DEBUG[1]: "
654+
.. filename
655+
.. ":2: apple=' .. vim.inspect(apple))",
656+
"end",
657+
})
658+
659+
assert.are.same(vim.api.nvim_win_get_cursor(0), { 2, 6 })
660+
end)
661+
662+
it("disabled at function level", function()
663+
debugprint.setup({})
664+
665+
set_lines({
666+
"function x() {",
667+
"local xyz = 3",
668+
"end",
669+
})
670+
671+
local filename = write_file("lua")
672+
vim.api.nvim_win_set_cursor(0, { 2, 6 })
673+
vim.keymap.set("n", "zxa", function()
674+
return require("debugprint").debugprint({
675+
variable = true,
676+
ignore_treesitter = true,
677+
})
678+
end, {
679+
expr = true,
680+
})
681+
feedkeys("zxaapple<CR>")
682+
683+
check_lines({
684+
"function x() {",
685+
"local xyz = 3",
686+
"print('DEBUG[1]: "
687+
.. filename
688+
.. ":2: apple=' .. vim.inspect(apple))",
689+
"end",
690+
})
691+
692+
assert.are.same(vim.api.nvim_win_get_cursor(0), { 2, 6 })
693+
end)
694+
end)

0 commit comments

Comments
 (0)