feat(docs): "yxx" runs Lua/Vimscript code examples #31904

`yxx` in Normal mode over a Lua or Vimscript code block section will execute the code.

Co-authored-by: Justin M. Keyes <justinkz@gmail.com>
This commit is contained in:
Riley Bruins
2025-01-09 08:36:16 -08:00
committed by GitHub
parent 1e47aa677a
commit 0c296ab224
9 changed files with 70 additions and 12 deletions

View File

@@ -193,6 +193,7 @@ Jump to specific subjects by using tags. This can be done in two ways:
Use CTRL-T or CTRL-O to jump back. Use CTRL-T or CTRL-O to jump back.
Use ":q" to close the help window. Use ":q" to close the help window.
Use `yxx` to execute the current Lua/Vimscript code block.
If there are several matches for an item you are looking for, this is how you If there are several matches for an item you are looking for, this is how you
can jump to each one of them: can jump to each one of them:

View File

@@ -161,7 +161,7 @@ languages like Python and C#. Example: >lua
local func_with_opts = function(opts) local func_with_opts = function(opts)
local will_do_foo = opts.foo local will_do_foo = opts.foo
local filename = opts.filename local filename = opts.filename
... -- ...
end end
func_with_opts { foo = true, filename = "hello.world" } func_with_opts { foo = true, filename = "hello.world" }
@@ -2428,7 +2428,7 @@ vim.validate({name}, {value}, {validator}, {optional}, {message})
function vim.startswith(s, prefix) function vim.startswith(s, prefix)
vim.validate('s', s, 'string') vim.validate('s', s, 'string')
vim.validate('prefix', prefix, 'string') vim.validate('prefix', prefix, 'string')
... -- ...
end end
< <
2. `vim.validate(spec)` (deprecated) where `spec` is of type 2. `vim.validate(spec)` (deprecated) where `spec` is of type
@@ -2442,7 +2442,7 @@ vim.validate({name}, {value}, {validator}, {optional}, {message})
age={age, 'number'}, age={age, 'number'},
hobbies={hobbies, 'table'}, hobbies={hobbies, 'table'},
} }
... -- ...
end end
< <

View File

@@ -276,6 +276,7 @@ LUA
supporting two new parameters, `encoding` and `strict_indexing`. supporting two new parameters, `encoding` and `strict_indexing`.
• |vim.json.encode()| has an option to enable forward slash escaping • |vim.json.encode()| has an option to enable forward slash escaping
• |vim.fs.abspath()| converts paths to absolute paths. • |vim.fs.abspath()| converts paths to absolute paths.
• Lua and vimscript code examples in docs can now be run using `yxx`.
OPTIONS OPTIONS

View File

@@ -165,8 +165,8 @@ directory indicated in the request. >lua
end end
}) })
To try it out, select the above code and source it with `:'<,'>lua`, then run To try it out, select the above code and source it with `:'<,'>lua` (or
this command in a :terminal buffer: > `yxx`), then run this command in a :terminal buffer: >
printf "\033]7;file://./foo/bar\033\\" printf "\033]7;file://./foo/bar\033\\"

View File

@@ -1336,7 +1336,7 @@ parse({lang}, {query}) *vim.treesitter.query.parse()*
`info.captures`). `info.captures`).
• `info.patterns`: information about predicates. • `info.patterns`: information about predicates.
Example (select the code then run `:'<,'>lua` to try it): >lua Example (to try it, use `yxx` or select the code then run `:'<,'>lua`): >lua
local query = vim.treesitter.query.parse('vimdoc', [[ local query = vim.treesitter.query.parse('vimdoc', [[
; query ; query
((h1) @str ((h1) @str
@@ -1422,7 +1422,7 @@ Query:iter_matches({node}, {source}, {start}, {stop}, {opts})
-- `node` was captured by the `name` capture in the match -- `node` was captured by the `name` capture in the match
local node_data = metadata[id] -- Node level metadata local node_data = metadata[id] -- Node level metadata
... use the info here ... -- ... use the info here ...
end end
end end
end end

View File

@@ -554,6 +554,11 @@ gO Show a filetype-specific, navigable "outline" of the
*:sl!* *:sleep!* *:sl!* *:sleep!*
:[N]sl[eep]! [N][m] Same as above, but hide the cursor. :[N]sl[eep]! [N][m] Same as above, but hide the cursor.
*yxx*
yxx Executes the current code block.
Works in |help| buffers.
============================================================================== ==============================================================================
2. Using Vim like less or more *less* 2. Using Vim like less or more *less*

View File

@@ -31,5 +31,56 @@ vim.keymap.set('n', 'gO', function()
require('vim.vimhelp').show_toc() require('vim.vimhelp').show_toc()
end, { buffer = 0, silent = true }) end, { buffer = 0, silent = true })
vim.b.undo_ftplugin = (vim.b.undo_ftplugin or '') .. '\n exe "nunmap <buffer> gO"' -- Add "runnables" for Lua/Vimscript code examples.
---@type table<integer, { lang: string, code: string }>
local code_blocks = {}
local tree = vim.treesitter.get_parser():parse()[1]
local query = vim.treesitter.query.parse(
'vimdoc',
[[
(codeblock
(language) @_lang
.
(code) @code
(#any-of? @_lang "lua" "vim")
(#set! @code lang @_lang))
]]
)
local run_message_ns = vim.api.nvim_create_namespace('vimdoc/run_message')
vim.api.nvim_buf_clear_namespace(0, run_message_ns, 0, -1)
for _, match, metadata in query:iter_matches(tree:root(), 0, 0, -1) do
for id, nodes in pairs(match) do
local name = query.captures[id]
local node = nodes[1]
local start, _, end_ = node:parent():range() --[[@as integer]]
if name == 'code' then
vim.api.nvim_buf_set_extmark(0, run_message_ns, start, 0, {
virt_text = { { 'Run with `yxx`', 'LspCodeLens' } },
})
local code = vim.treesitter.get_node_text(node, 0)
local lang_node = match[metadata[id].lang][1] --[[@as TSNode]]
local lang = vim.treesitter.get_node_text(lang_node, 0)
for i = start + 1, end_ do
code_blocks[i] = { lang = lang, code = code }
end
end
end
end
vim.keymap.set('n', 'yxx', function()
local pos = vim.api.nvim_win_get_cursor(0)[1]
local code_block = code_blocks[pos]
if not code_block then
vim.print('No code block found')
elseif code_block.lang == 'lua' then
vim.cmd.lua(code_block.code)
elseif code_block.lang == 'vim' then
vim.cmd(code_block.code)
end
end, { buffer = true })
vim.b.undo_ftplugin = (vim.b.undo_ftplugin or '')
.. '\n exe "nunmap <buffer> gO" | exe "nunmap <buffer> yxx"'
vim.b.undo_ftplugin = vim.b.undo_ftplugin .. ' | call v:lua.vim.treesitter.stop()' vim.b.undo_ftplugin = vim.b.undo_ftplugin .. ' | call v:lua.vim.treesitter.stop()'

View File

@@ -959,7 +959,7 @@ do
--- function vim.startswith(s, prefix) --- function vim.startswith(s, prefix)
--- vim.validate('s', s, 'string') --- vim.validate('s', s, 'string')
--- vim.validate('prefix', prefix, 'string') --- vim.validate('prefix', prefix, 'string')
--- ... --- -- ...
--- end --- end
--- ``` --- ```
--- ---
@@ -979,7 +979,7 @@ do
--- age={age, 'number'}, --- age={age, 'number'},
--- hobbies={hobbies, 'table'}, --- hobbies={hobbies, 'table'},
--- } --- }
--- ... --- -- ...
--- end --- end
--- ``` --- ```
--- ---

View File

@@ -292,7 +292,7 @@ end)
--- - `captures`: a list of unique capture names defined in the query (alias: `info.captures`). --- - `captures`: a list of unique capture names defined in the query (alias: `info.captures`).
--- - `info.patterns`: information about predicates. --- - `info.patterns`: information about predicates.
--- ---
--- Example (select the code then run `:'<,'>lua` to try it): --- Example (to try it, use `yxx` or select the code then run `:'<,'>lua`):
--- ```lua --- ```lua
--- local query = vim.treesitter.query.parse('vimdoc', [[ --- local query = vim.treesitter.query.parse('vimdoc', [[
--- ; query --- ; query
@@ -983,7 +983,7 @@ end
--- -- `node` was captured by the `name` capture in the match --- -- `node` was captured by the `name` capture in the match
--- ---
--- local node_data = metadata[id] -- Node level metadata --- local node_data = metadata[id] -- Node level metadata
--- ... use the info here ... --- -- ... use the info here ...
--- end --- end
--- end --- end
--- end --- end