Skip to content

Commit

Permalink
Merge pull request #5 from YaroSpace/develop
Browse files Browse the repository at this point in the history
v1.2.1
  • Loading branch information
YaroSpace authored Dec 14, 2024
2 parents b7ec0d1 + ff71b37 commit d408090
Show file tree
Hide file tree
Showing 8 changed files with 116 additions and 39 deletions.
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
set_lua_paths = eval $$(luarocks path --lua-version 5.1 --bin)
busted = $$(find /usr/local/lib/luarocks/*/busted/* -name busted)
set_luals_path = PATH="$$PATH:/home/yaro/.local/share/nvim/mason/bin/lua-language-server"

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

llscheck:
llscheck --configpath .luarc.json .
@$(set_luals_path) && llscheck --configpath .luarc.json .

luacheck:
luacheck lua spec scripts
Expand Down
34 changes: 24 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
**lua-console.nvim** - is a handy scratch pad / REPL / debug console for Lua development and Neovim exploration and configuration.
Acts as a user friendly replacement of command mode - messages loop and as a handy scratch pad to store and test your code gists.

***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).***

***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).***

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

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

<!-- config:start -->
`config.lua`

```lua
opts = {
buffer = {
Expand Down Expand Up @@ -139,10 +141,10 @@ There are two functions available within the console:

#### Setting up

- 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.
- 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.
Meanwhile, you can easily setup your own language.
- Below is the default configuration which can be overridden or extended by your custom config (`default_process_opts` will be
replaced by language specific opts), e.g. a possible config for `python` could be:
- Below is the default configuration, which can be overridden or extended by your custom config, where `default_process_opts` will be
replaced by language specific opts, e.g. a possible config for `python` could be:

```lua
require('lua-console').setup {
Expand All @@ -157,12 +159,11 @@ There are two functions available within the console:
}
```

- 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.

<details><summary>Default External Evaluators Settings</summary>

<!-- config:start -->
`exev_config.lua`

```lua
---Formats the output of external evaluator
---@param result string[]
Expand Down Expand Up @@ -209,23 +210,24 @@ There are two functions available within the console:
return external_evaluators
```
<!-- config:end -->

</details>

- 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.


#### Usage

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

- 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
for evaluation. The prefix can be changed in the config.
- 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.
- The code prefix on the top line of the console/buffer, in which case it applies to the whole buffer.
- The file type of the buffer.

<br/>

```racket
===racket
(define (log str)
(displayln (format "~v" str)))
Expand All @@ -243,6 +245,18 @@ There are two functions available within the console:
5.times { puts 'Hey' }
```

- Code inside Lua comments will be sytax highlighted.


```python
[[===python
list = [1, 3, 5, 7, 9]

for val in a:
print(list)
]]
```

## Alternatives and comparison

There are a number of alternatives available, notably:
Expand Down
4 changes: 3 additions & 1 deletion lua/lua-console.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
local config, mappings, utils
local config, mappings, utils, injections

local get_or_create_buffer = function()
--- @type number
Expand All @@ -19,6 +19,7 @@ local get_or_create_buffer = function()

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

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

Expand Down Expand Up @@ -77,6 +78,7 @@ local setup = function(opts)
config = require('lua-console.config').setup(opts)
mappings = require('lua-console.mappings')
utils = require('lua-console.utils')
injections = require('lua-console.injections')

mappings.set_global_mappings()
mappings.set_console_commands()
Expand Down
29 changes: 29 additions & 0 deletions lua/lua-console/injections.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
local M = {}

---Allow syntax highlighting for languages embedded in Lua comments
M.set_highlighting = function()
local config = require('lua-console.config')
local lang_prefix = config.external_evaluators.lang_prefix
local lang_pattern = ('^%s([^\\n]-)\\n.+$'):format(lang_prefix)

vim.treesitter.query.add_directive('indent!', function(_, _, _, predicate, metadata)
local capture_id = predicate[2]
if not metadata[capture_id].range then return end

metadata[capture_id].range[2] = tonumber(predicate[3]) -- set indent col to 0
end, { all = true, force = true })

local query = ([[ ;query
; extends
(string
content: (string_content) @injection.language @injection.content
(#lua-match? @injection.language "^@1")
(#gsub! @injection.language "@2" "%1")
(#offset! @injection.content 1 0 0 0)
(#indent! @injection.content 0))
]]):gsub('@1', lang_prefix):gsub('@2', lang_pattern)

vim.treesitter.query.set('lua', 'injections', query)
end

return M
49 changes: 24 additions & 25 deletions lua/lua-console/utils.lua
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ local to_string = function(tbl, sep, trim)
for _, pat in ipairs(patterns) do
line = line:gsub(pat, '')
end
-- compact strings by removing redundant spaces
line = line:gsub('(["\'])%s+', '%1'):gsub('%s+(["\'])', '%1'):gsub('%s%s+', ' ')
end

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

local function remove_indentation(tbl)
local indent = tbl[1]:match('(%s*)%w') or tbl[1]:match('(\t*)%w')
return vim.tbl_map(function(line)
return line:sub(#indent + 1)
end, tbl)
end

---Shows virtual text in the buffer
---@param buf number buffer
---@param id number namespace id
Expand Down Expand Up @@ -60,9 +68,9 @@ local toggle_help = function(buf)
vim.api.nvim_buf_del_extmark(buf, ns, 1)

message =
[[%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]]
[[%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]]
message =
string.format(message, cm.eval, cm.open, cm.messages, cm.save, cm.load, cm.resize_up, cm.resize_down, cm.help)
string.format(message, cm.eval, cm.eval_buffer, cm.open, cm.messages, cm.save, cm.load, cm.resize_up, cm.resize_down, cm.help)

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

local lnum = vim.fn.line('.', vim.fn.bufwinid(buf))
local lnum = vim.fn.line('.')
local prefix = config.buffer.result_prefix

local virtual_text
Expand Down Expand Up @@ -331,7 +339,7 @@ local get_external_evaluator = function(buf, lang)

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

local status, id = pcall(vim.system, cmd, opts, opts.on_exit)
Expand All @@ -346,42 +354,33 @@ end
---Determines the language of the code/console/buffer
---mutates lines array to remove the lang_prefix
---@param buf number
---@param lines string[]
---@param range number[]
---@return string
local function get_lang(buf, lines)
local pattern = '^.*' .. config.external_evaluators.lang_prefix .. '(.-)%s*$'
local function get_lang(buf, range)
local pattern = ('^.*' .. config.external_evaluators.lang_prefix .. '(.-)%s*$')
local line, lang

line = lines[1]
line = vim.api.nvim_buf_get_lines(buf, math.max(0, range[1] - 2), range[2], false)[1]
lang = line:match(pattern)
if lang then
table.remove(lines, 1)
return lang
end
if lang then return lang end

line = vim.fn.getbufline(buf, 1)[1]
line = vim.api.nvim_buf_get_lines(buf, 0, 1, false)[1]
lang = line:match(pattern)
if lang then return lang end

return vim.bo[buf].filetype
end

local get_evaluator = function(buf, lines)
local evaluator, lang
lang = get_lang(buf, lines)
local get_evaluator = function(buf, range)
local lang = get_lang(buf, range)

if lang == '' then
vim.notify('Plese specify the language to evaluate or set the filetype', vim.log.levels.WARN)
return
end

if lang == 'lua' then
evaluator = lua_evaluator
elseif lang == 'lua' then
return lua_evaluator
else
evaluator = get_external_evaluator(buf, lang)
return get_external_evaluator(buf, lang)
end

return evaluator
end

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

local evaluator = get_evaluator(buf, lines)
local evaluator = get_evaluator(buf, { v_start, v_end })
if not evaluator then return end

local result = evaluator(lines)
Expand Down
1 change: 1 addition & 0 deletions spec/spec_helper.lua
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ local function compare_strings(str_1, str_2)
if char_1 ~= char_2 then break end
end

if not pos then return '' end
pos = pos + 1

local sub_1 = str_1:sub(pos - 5, pos - 1) .. '<< ' .. str_1:sub(pos, pos) .. ' >>' .. str_1:sub(pos + 1, pos + 5)
Expand Down
33 changes: 32 additions & 1 deletion spec/unit/external_evals_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ describe('external evaluators', function()

h.set_buffer(buf, content)

h.send_keys('4gg')
h.send_keys('5gg')
h.send_keys('Vj')
utils.eval_code_in_buffer()

Expand Down Expand Up @@ -232,6 +232,37 @@ describe('external evaluators', function()
end)
end)

it('uses removes indentation from code', function()
config.setup {
external_evaluators = { ruby = { code_prefix = '' }, }, }

content = {
' a = [1, 3, 5, 7, 9]',
' for val in a:',
' print(val)'
}

expected = {
'a = [1, 3, 5, 7, 9]',
' for val in a:',
' print(val)'
}

h.set_buffer(buf, content)

h.send_keys('VG')
utils.eval_code_in_buffer()

assert.stub(vim.system).was.called_with(
match.assert_arg(function(arg)
result = h.to_table(arg[3])
assert.is_same(result, expected)
end),
_,
_
)
end)

it('uses custom formatter to process results', function()
vim.system = vim_system
vim.g._wait_for_spec = false
Expand Down
2 changes: 1 addition & 1 deletion spec/unit/lua-console_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ describe('lua-console.nvim', function()
it('sets up with custom config', function()
config = {
buffer = {
result_prefix = '$$ ',
result_prefix = '$$ '
},
window = {
border = 'single',
Expand Down

0 comments on commit d408090

Please sign in to comment.