Skip to content
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
15 changes: 0 additions & 15 deletions .busted

This file was deleted.

2 changes: 1 addition & 1 deletion .github/workflows/test_develop.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
name: develop
name: Tests
on:
pull_request: ~
push:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test_main.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
name: main
name: Tests
on:
pull_request: ~
push:
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.todo.md
.tests
16 changes: 6 additions & 10 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
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
test=nvim -l tests/minit.lua tests -o utfTerminal -Xoutput --color -v
#--shuffle-tests

tag ?= wip
watch = '*.lua'
Expand All @@ -19,19 +15,19 @@ llscheck:
@$(set_luals_path) && llscheck --configpath .luarc.json .

luacheck:
luacheck lua spec scripts
luacheck lua tests scripts

stylua:
stylua --check lua scripts spec

test:
@$(set_lua_paths); $(test_unit)
@$(test)

watch:
@$(set_lua_paths); while sleep 0.1; do find . -name $(watch) | entr -d -c $(test_unit); done
@while sleep 0.1; do find . -name $(watch) | entr -d -c $(test); done

watch_tag:
@$(set_lua_paths); while sleep 0.1; do find . -name $(watch) | entr -d -c $(test_unit) --tags=$(tag); done
@while sleep 0.1; do find . -name $(watch) | entr -d -c $(test) --tags=$(tag); done

test_nvim:
@$(test_nvim) spec/unit
44 changes: 14 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,10 @@
# 💻 Lua console ![main](https://github.com/yarospace/lua-console.nvim/actions/workflows/test_main.yml/badge.svg?branch=main) ![develop](https://github.com/yarospace/lua-console.nvim/actions/workflows/test_develop.yml/badge.svg?branch=develop) [![LuaRocks](https://img.shields.io/luarocks/v/YaroSpace/lua-console.nvim?logo=lua&color=purple)](https://luarocks.org/modules/YaroSpace/lua-console.nvim)

**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).
**lua-console.nvim** - is a REPL / scratch pad / debug console for Neovim.
Supports Lua natively and can be extended for other languages.

<br/><img src="https://github.com/YaroSpace/assets/blob/main/lua-console.nvim/demo.gif">

## 💡 Motivation

After installing Neovim, it took me some time to configure it, learn its settings, structure and API, while learning Lua in the process.
I got fed up of constantly hitting `:`, typing `lua= command`, then typing `:messages` to see the output, only to find out that a made a typo or a
syntax error and retyping the whole thing again, copying the paths from error stacktraces and so on. I needed something better, so there it is.

<br>

## ✨ Features

- Evaluate single line expressions and statements, visually selected lines or characters of code or the whole buffer
Expand All @@ -28,8 +17,6 @@ syntax error and retyping the whole thing again, copying the paths from error st
- Use as a scratch pad for code gists
- Attach code evaluators to any buffer

<br>

## 📦 Installation

With [lazy.nvim](https://github.com/folke/lazy.nvim):
Expand Down Expand Up @@ -58,8 +45,8 @@ require('lua-console').setup { your_custom_options }
> [!NOTE]
> All settings are self explanatory, but please read below about [`preserve_context`](#-notes-on-globals-locals-and-preserving-execution-context) option.

Mappings are local to the console, except the ones for toggling the console - `` ` `` and attaching to a buffer - ``<Leader>` ``. All mappings can be overridden in your custom
config. If you want to delete a mapping - set its value to `false`.
Mappings are local to the console, except the ones for toggling the console - `` ` `` and attaching to a buffer - ``<Leader>` ``.
All mappings can be overridden in your custom config. If you want to delete a mapping - set its value to `false`.

<details><summary>Default Settings</summary>

Expand All @@ -74,7 +61,7 @@ opts = {
autosave = true, -- autosave on console hide / close
load_on_start = true, -- load saved session on start
preserve_context = true, -- preserve results between evaluations
strip_local = true, -- remove local identifier from source code
strip_local = true, -- strip `local` from top-level variable declarations
show_one_line_results = true, -- prints one line results, even if already shown as virtual text
notify_result = false, -- notify result
clear_before_eval = false, -- clear output below result prefix before evaluation of the whole buffer
Expand Down Expand Up @@ -105,14 +92,12 @@ opts = {

</details>

<br>

## 🚀 Basic usage (with default mappings)

- Install, press the mapped key `` ` `` and start exploring.
- Enter code as normal, in insert mode.
- Hit `Enter` in normal mode to evaluate a variable, statement or an expression in the current line.
- Visually select a region or a range of lines and press `Enter` to evaluate the code in the range or use `<S-Enter>` to evaluate the whole console.
- Visually select a region or a range of lines and press `Enter` to evaluate the code in the range or use `<S-Enter>` to evaluate the whole buffer.
- The evaluation of the last line is returned and printed, so no `return` is needed in most cases.
To avoid noise, if the return of your execution is `nil`, e.g. from a loop or a function without return, it will not be printed, but shown as virtual text.
The result of assignments on the last line will be also shown as virtual text.
Expand All @@ -136,11 +121,14 @@ opts = {
> [!IMPORTANT]
> By default, the option `preserve_context` is on, which means that the execution context is preserved between evaluations.

All the code executed in the console is evaluated in isolated environment. This means that any variables you declare without the `local` keyword will not be persisted
in Neovim's global environment, although all global variables are accessible. If you want purposefully to alter the global state, use `_G.My_variable = ..`.
All the code executed in the console is evaluated in isolated environment, which means that any global variables that you declare will not be persisted in Neovim's global environment.
If you purposefully want to alter the global state, use `_G.My_variable = ..`.

The option `preserve_context` implies that variables without `local` will be stored in the console's local context and preserved between executions.

The option `preserve_context` means that although you declare variables without `local`, they will be stored in console's local context and preserved between separate executions.
So, if you first execute `a = 1`, then `a = a + 1` and then `a` - you will get `2`. Variables with `local` are also preserved, unless you set the `strip_local` option to `false`.
So, if you first execute `a = 1`, then `a = a + 1` and then `a` - you will get `2`.

Also, by default, the option `strip_local` is on, which means that `local` modifier is stripped from top-level variable declarations and these variables are also stored in the context.

If you want the context to be cleared before every execution, set `preserve_context = false`.

Expand All @@ -149,8 +137,6 @@ There are two functions available within the console:
- `_ctx` - will print the contents of the context
- `_ctx_clear()` - clears the context

<br>

## ⭐ Extra features

### Attaching code evaluator to other buffers
Expand All @@ -162,8 +148,7 @@ There are two functions available within the console:

#### Setting up

- 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.
- 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 can be easily added.
- 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:

Expand Down Expand Up @@ -291,7 +276,6 @@ There are a number of alternatives available, notably:
- [Luadev](https://github.com/bfredl/nvim-luadev)
- [SnipRun](https://github.com/michaelb/sniprun)

Initially, when starting with Lua and Neovim, I tried all the REPLs/code runners I could find. However, I was not satisfied with all of them in one way or another.
Lua-console is an attempt to combine the best features of all of them, like REPL / scratch pad / code runner / debug console, while leaving the UX and config simple.

<br>
Expand Down
2 changes: 1 addition & 1 deletion lua/lua-console/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ local default_config = {
autosave = true, -- autosave on console hide / close
load_on_start = true, -- load saved session on start
preserve_context = true, -- preserve results between evaluations
strip_local = true, -- remove local identifier from source code
strip_local = true, -- strip "local" modifier from top level variables
show_one_line_results = true, -- prints one line results, even if already shown as virtual text
notify_result = false, -- notify result
clear_before_eval = false, -- clear output below result prefix before evaluation of the whole buffer
Expand Down
39 changes: 30 additions & 9 deletions lua/lua-console/utils.lua
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ end
local get_line_assignment = function(line)
if not line or #line == 0 then return end

local lhs = line[1]:match('^(.-)%s*=')
local lhs = line[1]:gsub('^%s*local%s+', ''):match('^(.-)%s*=')
local ret

if lhs then
Expand All @@ -177,6 +177,7 @@ local get_last_assignment = function()

for i = lnum - 1, 0, -1 do
line = vim.api.nvim_buf_get_lines(0, i, i + 1, false)[1]
line = line:gsub('^%s*local%s+', '')

if line:match('^%s*' .. last_var .. '%s*,?[^=]-=') then break end
offset = offset + 1
Expand Down Expand Up @@ -265,12 +266,6 @@ local append_current_buffer = function(buf, lines, lnum)
vim.api.nvim_buf_set_lines(buf, lnum, lnum, false, lines)
end

local function remove_empty_lines(tbl)
return vim.tbl_filter(function(el)
return vim.fn.trim(el) ~= ''
end, tbl)
end

local function trim_empty_lines(tbl)
if #tbl == 0 then return tbl end

Expand Down Expand Up @@ -358,6 +353,32 @@ local function run_code(code)
return result
end

local function strip_local(lines)
lines = vim.split(lines, '\n')

local ts = vim.treesitter
local ret = {}

local start_row = math.max(0, vim.fn.line('.') - 1 - #lines)

for i, line in ipairs(lines) do
local cs, ce = 1, 1

while cs do
cs, ce = line:find('local%s', ce)

if cs then
local node = ts.get_node { pos = { start_row + i - 1, cs } }
if node and node:parent():type() == 'chunk' then line = line:sub(1, cs - 1) .. line:sub(ce + 1) end
end
end

table.insert(ret, line)
end

return table.concat(ret, '\n')
end

--- Evaluates Lua code and returns pretty printed result with errors if any
--- @param lines string[] table with lines of Lua code
--- @param ctx? table environment to execute code in
Expand All @@ -378,7 +399,7 @@ function lua_evaluator(lines, ctx)
end

lines = to_string(lines)
lines = config.buffer.strip_local and lines:gsub('local ', '') or lines
lines = config.buffer.strip_local and strip_local(lines) or lines

local code, errors = load(lines, 'Lua console: ', 't', env)
if errors then return to_table(errors) end
Expand Down Expand Up @@ -453,6 +474,7 @@ local get_external_evaluator = function(buf, lang)
local fun = opts.on_exit
opts.on_exit = function(system_completed)
vim.schedule(function()
if not vim.api.nvim_buf_is_valid(buf) then return end
vim.api.nvim_buf_del_extmark(buf, ns, 10)
_ = fun and fun(system_completed)
end)
Expand Down Expand Up @@ -549,7 +571,6 @@ local eval_code_in_buffer = function(buf, full)
vim.fn.cursor(v_end, 0)

lines = lines or vim.api.nvim_buf_get_lines(buf, v_start - 1, v_end, false)
lines = remove_empty_lines(lines)
if #lines == 0 then return end

local evaluator = get_evaluator(buf, v_start - 1)
Expand Down
46 changes: 0 additions & 46 deletions spec/log.lua

This file was deleted.

2 changes: 0 additions & 2 deletions spec/minimal_init.lua

This file was deleted.

6 changes: 0 additions & 6 deletions spec/nvim-shim.sh

This file was deleted.

Loading