Skip to content

Commit d408090

Browse files
authored
Merge pull request #5 from YaroSpace/develop
v1.2.1
2 parents b7ec0d1 + ff71b37 commit d408090

File tree

8 files changed

+116
-39
lines changed

8 files changed

+116
-39
lines changed

Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
set_lua_paths = eval $$(luarocks path --lua-version 5.1 --bin)
22
busted = $$(find /usr/local/lib/luarocks/*/busted/* -name busted)
3+
set_luals_path = PATH="$$PATH:/home/yaro/.local/share/nvim/mason/bin/lua-language-server"
34

45
test_unit = busted --run=unit
56
test_nvim = nvim --headless -i NONE -n -u spec/minimal_init.lua -l $(busted) --run=unit
@@ -15,7 +16,7 @@ api_documentation:
1516
nvim -u scripts/make_api_documentation/init.lua -l scripts/make_api_documentation/main.lua
1617

1718
llscheck:
18-
llscheck --configpath .luarc.json .
19+
@$(set_luals_path) && llscheck --configpath .luarc.json .
1920

2021
luacheck:
2122
luacheck lua spec scripts

README.md

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
**lua-console.nvim** - is a handy scratch pad / REPL / debug console for Lua development and Neovim exploration and configuration.
44
Acts as a user friendly replacement of command mode - messages loop and as a handy scratch pad to store and test your code gists.
55

6-
***Update: Although it originated as a tool for Lua development, it has now evolved into supporting other languages too. See [`evaluating other languages`](#evaluating-other-languages).***
6+
7+
***Update: although it originated as a tool for Lua development, it has now evolved into supporting other languages too. See [`evaluating other languages`](#evaluating-other-languages).***
78

89
<br/><img src="doc/demo.gif">
910

@@ -52,6 +53,7 @@ config. If you want to delete a mapping - set its value to `false`.
5253

5354
<!-- config:start -->
5455
`config.lua`
56+
5557
```lua
5658
opts = {
5759
buffer = {
@@ -139,10 +141,10 @@ There are two functions available within the console:
139141

140142
#### Setting up
141143

142-
- It is possible to setup external code executors for other languages. Evaluators for `ruby` and `racket` are working out of the box, support for other languages is coming.
144+
- It is possible to setup external code executors for other languages. Evaluators for `ruby`,`racket` and `python` are working out of the box, support for other languages is coming.
143145
Meanwhile, you can easily setup your own language.
144-
- Below is the default configuration which can be overridden or extended by your custom config (`default_process_opts` will be
145-
replaced by language specific opts), e.g. a possible config for `python` could be:
146+
- Below is the default configuration, which can be overridden or extended by your custom config, where `default_process_opts` will be
147+
replaced by language specific opts, e.g. a possible config for `python` could be:
146148

147149
```lua
148150
require('lua-console').setup {
@@ -157,12 +159,11 @@ There are two functions available within the console:
157159
}
158160
```
159161

160-
- You can also setup a custom formatter to format the evaluator output before appending results to the console or buffer. Example is in the config.
161-
162162
<details><summary>Default External Evaluators Settings</summary>
163163

164164
<!-- config:start -->
165165
`exev_config.lua`
166+
166167
```lua
167168
---Formats the output of external evaluator
168169
---@param result string[]
@@ -209,23 +210,24 @@ There are two functions available within the console:
209210
return external_evaluators
210211
```
211212
<!-- config:end -->
212-
213213
</details>
214214

215+
- You can also setup a custom formatter to format the evaluator output before appending results to the console or buffer. Example is in the config.
216+
217+
215218
#### Usage
216219

217220
- The language evaluator is determined either from (in order of precedence):
218221

219-
- The code prefix `===lang` on the line above your code snippet, in which case it only applies to the snippet directly below and it should be included in the selection
220-
for evaluation. The prefix can be changed in the config.
222+
- The code prefix `===lang` on the line above your code snippet, in which case it only applies to the snippet directly below. The prefix can be changed in the config.
221223
- The code prefix on the top line of the console/buffer, in which case it applies to the whole buffer.
222224
- The file type of the buffer.
225+
223226
<br/>
224227

225228
```racket
226229
===racket
227230
228-
229231
(define (log str)
230232
(displayln (format "~v" str)))
231233
@@ -243,6 +245,18 @@ There are two functions available within the console:
243245
5.times { puts 'Hey' }
244246
```
245247

248+
- Code inside Lua comments will be sytax highlighted.
249+
250+
251+
```python
252+
[[===python
253+
list = [1, 3, 5, 7, 9]
254+
255+
for val in a:
256+
print(list)
257+
]]
258+
```
259+
246260
## Alternatives and comparison
247261

248262
There are a number of alternatives available, notably:

lua/lua-console.lua

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
local config, mappings, utils
1+
local config, mappings, utils, injections
22

33
local get_or_create_buffer = function()
44
--- @type number
@@ -19,6 +19,7 @@ local get_or_create_buffer = function()
1919

2020
vim.api.nvim_buf_set_name(buf, buf_name) -- the name is only needed so the buffer is picked up by Lsp with correct root
2121

22+
injections.set_highlighting()
2223
vim.api.nvim_set_option_value('filetype', 'lua', { buf = buf })
2324
vim.diagnostic.enable(false, { bufnr = buf })
2425

@@ -77,6 +78,7 @@ local setup = function(opts)
7778
config = require('lua-console.config').setup(opts)
7879
mappings = require('lua-console.mappings')
7980
utils = require('lua-console.utils')
81+
injections = require('lua-console.injections')
8082

8183
mappings.set_global_mappings()
8284
mappings.set_console_commands()

lua/lua-console/injections.lua

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
local M = {}
2+
3+
---Allow syntax highlighting for languages embedded in Lua comments
4+
M.set_highlighting = function()
5+
local config = require('lua-console.config')
6+
local lang_prefix = config.external_evaluators.lang_prefix
7+
local lang_pattern = ('^%s([^\\n]-)\\n.+$'):format(lang_prefix)
8+
9+
vim.treesitter.query.add_directive('indent!', function(_, _, _, predicate, metadata)
10+
local capture_id = predicate[2]
11+
if not metadata[capture_id].range then return end
12+
13+
metadata[capture_id].range[2] = tonumber(predicate[3]) -- set indent col to 0
14+
end, { all = true, force = true })
15+
16+
local query = ([[ ;query
17+
; extends
18+
(string
19+
content: (string_content) @injection.language @injection.content
20+
(#lua-match? @injection.language "^@1")
21+
(#gsub! @injection.language "@2" "%1")
22+
(#offset! @injection.content 1 0 0 0)
23+
(#indent! @injection.content 0))
24+
]]):gsub('@1', lang_prefix):gsub('@2', lang_pattern)
25+
26+
vim.treesitter.query.set('lua', 'injections', query)
27+
end
28+
29+
return M

lua/lua-console/utils.lua

Lines changed: 24 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ local to_string = function(tbl, sep, trim)
1212
for _, pat in ipairs(patterns) do
1313
line = line:gsub(pat, '')
1414
end
15+
-- compact strings by removing redundant spaces
1516
line = line:gsub('(["\'])%s+', '%1'):gsub('%s+(["\'])', '%1'):gsub('%s%s+', ' ')
1617
end
1718

@@ -22,6 +23,13 @@ local to_table = function(str)
2223
return vim.split(str or '', '\n', { trimempty = true })
2324
end
2425

26+
local function remove_indentation(tbl)
27+
local indent = tbl[1]:match('(%s*)%w') or tbl[1]:match('(\t*)%w')
28+
return vim.tbl_map(function(line)
29+
return line:sub(#indent + 1)
30+
end, tbl)
31+
end
32+
2533
---Shows virtual text in the buffer
2634
---@param buf number buffer
2735
---@param id number namespace id
@@ -60,9 +68,9 @@ local toggle_help = function(buf)
6068
vim.api.nvim_buf_del_extmark(buf, ns, 1)
6169

6270
message =
63-
[[%s - eval a line or selection, %s - open file, %s - load messages, %s - save console, %s - load console, %s/%s - resize window, %s - toggle help]]
71+
[[%s - eval a line or selection, %s - eval buffer, %s - open file, %s - load messages, %s - save console, %s - load console, %s/%s - resize window, %s - toggle help]]
6472
message =
65-
string.format(message, cm.eval, cm.open, cm.messages, cm.save, cm.load, cm.resize_up, cm.resize_down, cm.help)
73+
string.format(message, cm.eval, cm.eval_buffer, cm.open, cm.messages, cm.save, cm.load, cm.resize_up, cm.resize_down, cm.help)
6674

6775
local visible_line = vim.fn.line('w0')
6876
show_virtual_text(buf, 2, message, visible_line - 1, 'overlay', 'Comment')
@@ -131,7 +139,7 @@ local print_buffer = {}
131139
local append_current_buffer = function(buf, lines)
132140
if not lines or #lines == 0 then return end
133141

134-
local lnum = vim.fn.line('.', vim.fn.bufwinid(buf))
142+
local lnum = vim.fn.line('.')
135143
local prefix = config.buffer.result_prefix
136144

137145
local virtual_text
@@ -331,7 +339,7 @@ local get_external_evaluator = function(buf, lang)
331339

332340
return function(lines)
333341
local cmd = vim.tbl_extend('force', {}, lang_config.cmd)
334-
local code = (lang_config.code_prefix or '') .. to_string(lines)
342+
local code = (lang_config.code_prefix or '') .. to_string(remove_indentation(lines)) -- some languages, like python are concerned with indentation
335343
table.insert(cmd, code)
336344

337345
local status, id = pcall(vim.system, cmd, opts, opts.on_exit)
@@ -346,42 +354,33 @@ end
346354
---Determines the language of the code/console/buffer
347355
---mutates lines array to remove the lang_prefix
348356
---@param buf number
349-
---@param lines string[]
357+
---@param range number[]
350358
---@return string
351-
local function get_lang(buf, lines)
352-
local pattern = '^.*' .. config.external_evaluators.lang_prefix .. '(.-)%s*$'
359+
local function get_lang(buf, range)
360+
local pattern = ('^.*' .. config.external_evaluators.lang_prefix .. '(.-)%s*$')
353361
local line, lang
354362

355-
line = lines[1]
363+
line = vim.api.nvim_buf_get_lines(buf, math.max(0, range[1] - 2), range[2], false)[1]
356364
lang = line:match(pattern)
357-
if lang then
358-
table.remove(lines, 1)
359-
return lang
360-
end
365+
if lang then return lang end
361366

362-
line = vim.fn.getbufline(buf, 1)[1]
367+
line = vim.api.nvim_buf_get_lines(buf, 0, 1, false)[1]
363368
lang = line:match(pattern)
364369
if lang then return lang end
365370

366371
return vim.bo[buf].filetype
367372
end
368373

369-
local get_evaluator = function(buf, lines)
370-
local evaluator, lang
371-
lang = get_lang(buf, lines)
374+
local get_evaluator = function(buf, range)
375+
local lang = get_lang(buf, range)
372376

373377
if lang == '' then
374378
vim.notify('Plese specify the language to evaluate or set the filetype', vim.log.levels.WARN)
375-
return
376-
end
377-
378-
if lang == 'lua' then
379-
evaluator = lua_evaluator
379+
elseif lang == 'lua' then
380+
return lua_evaluator
380381
else
381-
evaluator = get_external_evaluator(buf, lang)
382+
return get_external_evaluator(buf, lang)
382383
end
383-
384-
return evaluator
385384
end
386385

387386
---Evaluates code in the current line or visual selection and appends to buffer
@@ -409,7 +408,7 @@ local eval_code_in_buffer = function(buf, full)
409408
lines = remove_empty_lines(lines)
410409
if #lines == 0 then return end
411410

412-
local evaluator = get_evaluator(buf, lines)
411+
local evaluator = get_evaluator(buf, { v_start, v_end })
413412
if not evaluator then return end
414413

415414
local result = evaluator(lines)

spec/spec_helper.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ local function compare_strings(str_1, str_2)
155155
if char_1 ~= char_2 then break end
156156
end
157157

158+
if not pos then return '' end
158159
pos = pos + 1
159160

160161
local sub_1 = str_1:sub(pos - 5, pos - 1) .. '<< ' .. str_1:sub(pos, pos) .. ' >>' .. str_1:sub(pos + 1, pos + 5)

spec/unit/external_evals_spec.lua

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ describe('external evaluators', function()
8080

8181
h.set_buffer(buf, content)
8282

83-
h.send_keys('4gg')
83+
h.send_keys('5gg')
8484
h.send_keys('Vj')
8585
utils.eval_code_in_buffer()
8686

@@ -232,6 +232,37 @@ describe('external evaluators', function()
232232
end)
233233
end)
234234

235+
it('uses removes indentation from code', function()
236+
config.setup {
237+
external_evaluators = { ruby = { code_prefix = '' }, }, }
238+
239+
content = {
240+
' a = [1, 3, 5, 7, 9]',
241+
' for val in a:',
242+
' print(val)'
243+
}
244+
245+
expected = {
246+
'a = [1, 3, 5, 7, 9]',
247+
' for val in a:',
248+
' print(val)'
249+
}
250+
251+
h.set_buffer(buf, content)
252+
253+
h.send_keys('VG')
254+
utils.eval_code_in_buffer()
255+
256+
assert.stub(vim.system).was.called_with(
257+
match.assert_arg(function(arg)
258+
result = h.to_table(arg[3])
259+
assert.is_same(result, expected)
260+
end),
261+
_,
262+
_
263+
)
264+
end)
265+
235266
it('uses custom formatter to process results', function()
236267
vim.system = vim_system
237268
vim.g._wait_for_spec = false

spec/unit/lua-console_spec.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ describe('lua-console.nvim', function()
2323
it('sets up with custom config', function()
2424
config = {
2525
buffer = {
26-
result_prefix = '$$ ',
26+
result_prefix = '$$ '
2727
},
2828
window = {
2929
border = 'single',

0 commit comments

Comments
 (0)