From 6d36b1df81994e10c753f1c02ac57ed459b634b9 Mon Sep 17 00:00:00 2001 From: Yaro Date: Tue, 3 Jun 2025 17:12:34 +0100 Subject: [PATCH 1/2] fix: remove locals for top-level declarations only --- .gitignore | 1 + README.md | 32 ++++++++++---------------------- lua/lua-console/config.lua | 2 +- lua/lua-console/utils.lua | 34 +++++++++++++++++++++++++--------- 4 files changed, 37 insertions(+), 32 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..02dc863 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.todo.md diff --git a/README.md b/README.md index 37ca59d..3a37058 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,9 @@ # 💻 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.
-## 💡 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. - -
- ## ✨ Features - Evaluate single line expressions and statements, visually selected lines or characters of code or the whole buffer @@ -74,7 +62,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 @@ -112,7 +100,7 @@ opts = { - 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 `` 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 `` 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. @@ -136,11 +124,13 @@ 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. +So, if you first execute `a = 1`, then `a = a + 1` and then `a` - you will get `2`. -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`. +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`. @@ -162,8 +152,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: @@ -291,7 +280,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.
diff --git a/lua/lua-console/config.lua b/lua/lua-console/config.lua index a4f85a4..f43a307 100644 --- a/lua/lua-console/config.lua +++ b/lua/lua-console/config.lua @@ -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 diff --git a/lua/lua-console/utils.lua b/lua/lua-console/utils.lua index 555d6e4..bb1e96f 100644 --- a/lua/lua-console/utils.lua +++ b/lua/lua-console/utils.lua @@ -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 @@ -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 @@ -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 @@ -358,6 +353,28 @@ 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 = vim.fn.line('.') - 1 - #lines + + for i, line in ipairs(lines) do + local col = line:find('^%s*local%s+') + + if col then + local node = ts.get_node { pos = { start_row + i, col } } + line = node and node:parent():type() == 'chunk' and line:gsub('^%s*local%s+', '') or line + 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 @@ -378,7 +395,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 @@ -549,7 +566,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) From 73521780270720f9271afe04ff390e82c373b256 Mon Sep 17 00:00:00 2001 From: Yaro Date: Tue, 3 Jun 2025 21:21:59 +0100 Subject: [PATCH 2/2] specs: update --- .busted | 15 -- .github/workflows/test_develop.yml | 2 +- .github/workflows/test_main.yml | 2 +- .gitignore | 1 + Makefile | 16 +- README.md | 18 +- lua/lua-console/utils.lua | 15 +- spec/log.lua | 46 ---- spec/minimal_init.lua | 2 - spec/nvim-shim.sh | 6 - spec/utfTerminal.lua | 250 ------------------- tests/minit.lua | 25 ++ {spec => tests}/spec_helper.lua | 8 +- {spec => tests}/unit/external_evals_spec.lua | 0 {spec => tests}/unit/lua-console_spec.lua | 4 +- {spec => tests}/unit/mappings_spec.lua | 7 +- {spec => tests}/unit/utils_spec.lua | 28 ++- 17 files changed, 81 insertions(+), 364 deletions(-) delete mode 100644 .busted delete mode 100644 spec/log.lua delete mode 100644 spec/minimal_init.lua delete mode 100755 spec/nvim-shim.sh delete mode 100644 spec/utfTerminal.lua create mode 100644 tests/minit.lua rename {spec => tests}/spec_helper.lua (97%) rename {spec => tests}/unit/external_evals_spec.lua (100%) rename {spec => tests}/unit/lua-console_spec.lua (98%) rename {spec => tests}/unit/mappings_spec.lua (97%) rename {spec => tests}/unit/utils_spec.lua (96%) diff --git a/.busted b/.busted deleted file mode 100644 index 36f4c5d..0000000 --- a/.busted +++ /dev/null @@ -1,15 +0,0 @@ -return { - _all = { - coverage = false, - lpath = "lua/?.lua;lua/?/init.lua;spec/?.lua", - lua = 'spec/nvim-shim.sh', - ROOT = {'spec'}, - output = 'spec/utfTerminal.lua', - verbose = true - }, - default = { - }, - unit = { - ROOT = {'spec/unit'}, - }, -} diff --git a/.github/workflows/test_develop.yml b/.github/workflows/test_develop.yml index 9d8b146..e427ec3 100644 --- a/.github/workflows/test_develop.yml +++ b/.github/workflows/test_develop.yml @@ -1,5 +1,5 @@ --- -name: develop +name: Tests on: pull_request: ~ push: diff --git a/.github/workflows/test_main.yml b/.github/workflows/test_main.yml index 4ea4191..5d3ba3e 100644 --- a/.github/workflows/test_main.yml +++ b/.github/workflows/test_main.yml @@ -1,5 +1,5 @@ --- -name: main +name: Tests on: pull_request: ~ push: diff --git a/.gitignore b/.gitignore index 02dc863..a5fd5a3 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ .todo.md +.tests diff --git a/Makefile b/Makefile index 149de5c..83113ba 100644 --- a/Makefile +++ b/Makefile @@ -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' @@ -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 diff --git a/README.md b/README.md index 3a37058..3f42d34 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # 💻 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 REPL / scratch pad / debug console for Neovim. Supports Lua natively and can be extended for other languages. +**lua-console.nvim** - is a REPL / scratch pad / debug console for Neovim. +Supports Lua natively and can be extended for other languages.
@@ -16,8 +17,6 @@ - Use as a scratch pad for code gists - Attach code evaluators to any buffer -
- ## 📦 Installation With [lazy.nvim](https://github.com/folke/lazy.nvim): @@ -46,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 - ``` ``. 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 - ``` ``. +All mappings can be overridden in your custom config. If you want to delete a mapping - set its value to `false`.
Default Settings @@ -93,8 +92,6 @@ opts = {
-
- ## 🚀 Basic usage (with default mappings) - Install, press the mapped key `` ` `` and start exploring. @@ -124,10 +121,11 @@ 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, 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 = ..`. +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. + 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. @@ -139,8 +137,6 @@ There are two functions available within the console: - `_ctx` - will print the contents of the context - `_ctx_clear()` - clears the context -
- ## ⭐ Extra features ### Attaching code evaluator to other buffers diff --git a/lua/lua-console/utils.lua b/lua/lua-console/utils.lua index bb1e96f..889c7da 100644 --- a/lua/lua-console/utils.lua +++ b/lua/lua-console/utils.lua @@ -359,14 +359,18 @@ local function strip_local(lines) local ts = vim.treesitter local ret = {} - local start_row = vim.fn.line('.') - 1 - #lines + local start_row = math.max(0, vim.fn.line('.') - 1 - #lines) for i, line in ipairs(lines) do - local col = line:find('^%s*local%s+') + local cs, ce = 1, 1 - if col then - local node = ts.get_node { pos = { start_row + i, col } } - line = node and node:parent():type() == 'chunk' and line:gsub('^%s*local%s+', '') or line + 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) @@ -470,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) diff --git a/spec/log.lua b/spec/log.lua deleted file mode 100644 index 9ea9090..0000000 --- a/spec/log.lua +++ /dev/null @@ -1,46 +0,0 @@ -local colors = require('term.colors') -local inspect = require('inspect') - -local log = function(...) --luacheck: ignore - local caller = debug.getinfo(2) - local caller_path = caller.short_src - - local time = os.date('*t', os.time()) - time.min, time.sec = 0, 0 - ----@diagnostic disable-next-line - time = os.time() - os.time(time) - - if caller_path then - local path_dirs = vim.split(vim.fs.dirname(caller_path), '/') - caller_path = path_dirs[#path_dirs] .. '/' .. vim.fs.basename(caller_path) - end - - local result = ('\nLOG #%s (%s:%s:%s) => '):format( - time, - caller_path or '', - caller.name or '', - caller.currentline or '' - ) - - local nargs = select('#', ...) - local var_no = '' - - for i = 1, nargs do - local o = select(i, ...) - - if i > 1 then result = result .. ',\n ' end - if nargs > 1 then var_no = string.format('[%s] ', i) end - - o = type(o) == 'function' and debug.getinfo(o) or o - result = result .. var_no .. inspect(o) - end - - io.write(colors.cyan(result)) - io.write('\n') - io.flush() - - return result -end - -return log diff --git a/spec/minimal_init.lua b/spec/minimal_init.lua deleted file mode 100644 index 32542a1..0000000 --- a/spec/minimal_init.lua +++ /dev/null @@ -1,2 +0,0 @@ -local cwd = vim.fs.root(debug.getinfo(1, 'S').source:sub(2), '.git') -vim.opt.rtp:append(cwd) diff --git a/spec/nvim-shim.sh b/spec/nvim-shim.sh deleted file mode 100755 index 488d2fc..0000000 --- a/spec/nvim-shim.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh - -nvim --headless -i NONE -n -u spec/minimal_init.lua -l "$@" -exit_code=$? - -exit $exit_code diff --git a/spec/utfTerminal.lua b/spec/utfTerminal.lua deleted file mode 100644 index 787d0fa..0000000 --- a/spec/utfTerminal.lua +++ /dev/null @@ -1,250 +0,0 @@ -local s = require('say') -local pretty = require('pl.pretty') -local term = require('term') -local luassert = require('luassert') -local io = io -local type = type -local string_format = string.format -local string_gsub = string.gsub -local io_write = io.write -local io_flush = io.flush -local pairs = pairs -local colors - -local isatty = io.type(io.stdout) == 'file' and term.isatty(io.stdout) - -return function(options) - local busted = require('busted') - local handler = require('busted.outputHandlers.base')() - local cli = require('cliargs') - local args = options.arguments - - cli:set_name('utfTerminal output handler') - cli:flag('--color', 'force use of color') - cli:flag('--plain', 'force use of no color') - - local cliArgs, err = cli:parse(args) - if not cliArgs and err then - io.stderr:write(string.format('%s: %s\n\n', cli.name, err)) - io.stderr:write(cli.printer.generate_help_and_usage() .. '\n') - os.exit(1) - end - - if cliArgs.plain then - colors = setmetatable({}, { - __index = function() - return function(s) - return s - end - end, - }) - luassert:set_parameter('TableErrorHighlightColor', 'none') - elseif cliArgs.color then - colors = require('term.colors') - luassert:set_parameter('TableErrorHighlightColor', 'red') - else - if package.config:sub(1, 1) == '\\' and not os.getenv('ANSICON') or not isatty then - -- Disable colors on Windows. - colors = setmetatable({}, { - __index = function() - return function(s) - return s - end - end, - }) - luassert:set_parameter('TableErrorHighlightColor', 'none') - else - colors = require('term.colors') - luassert:set_parameter('TableErrorHighlightColor', 'red') - end - end - - local successDot = colors.green('\226\151\143') -- '\226\151\143' = '●' = utf8.char(9679) - local failureDot = colors.red('\226\151\188') -- '\226\151\188' = '◼' = utf8.char(9724) - local errorDot = colors.magenta('\226\156\177') -- '\226\156\177' = '✱' = utf8.char(10033) - local pendingDot = colors.yellow('\226\151\140') -- '\226\151\140' = '◌' = utf8.char(9676) - - local pendingDescription = function(pending) - local name = pending.name - - -- '\226\134\146' = '→' = utf8.char('8594') - local string = colors.yellow(s('output.pending')) - .. ' \226\134\146 ' - .. colors.cyan(pending.trace.short_src) - .. ' @ ' - .. colors.cyan(pending.trace.currentline) - .. '\n' - .. colors.bright(name) - - if type(pending.message) == 'string' then - string = string .. '\n' .. pending.message - elseif pending.message ~= nil then - string = string .. '\n' .. pretty.write(pending.message) - end - - return string - end - - local failureMessage = function(failure) - local string = failure.randomseed and ('Random seed: ' .. failure.randomseed .. '\n') or '' - if type(failure.message) == 'string' then - string = string .. failure.message - elseif failure.message == nil then - string = string .. 'Nil error' - else - string = string .. pretty.write(failure.message) - end - - return string - end - - local failureDescription = function(failure, isError) - -- '\226\134\146' = '→' = utf8.char(8594) - local string = colors.red(s('output.failure')) .. ' \226\134\146 ' - if isError then string = colors.magenta(s('output.error')) .. ' \226\134\146 ' end - - if not failure.element.trace or not failure.element.trace.short_src then - string = string .. colors.red(failureMessage(failure)) .. '\n' .. colors.red(failure.name) - else - string = string - .. colors.cyan(failure.element.trace.short_src) - .. ' @ ' - .. colors.cyan(failure.element.trace.currentline) - .. '\n' - .. colors.bright(failure.name) - .. '\n' - .. colors.red(failureMessage(failure)) - end - - if options.verbose and failure.trace and failure.trace.traceback then - string = string .. '\n' .. colors.cyan(failure.trace.traceback) - end - - return string - end - - local statusString = function() - local successString = s('output.success_plural') - local failureString = s('output.failure_plural') - local pendingString = s('output.pending_plural') - local errorString = s('output.error_plural') - - local sec = handler.getDuration() - local successes = handler.successesCount - local pendings = handler.pendingsCount - local failures = handler.failuresCount - local errors = handler.errorsCount - - if successes == 0 then - successString = s('output.success_zero') - elseif successes == 1 then - successString = s('output.success_single') - end - - if failures == 0 then - failureString = s('output.failure_zero') - elseif failures == 1 then - failureString = s('output.failure_single') - end - - if pendings == 0 then - pendingString = s('output.pending_zero') - elseif pendings == 1 then - pendingString = s('output.pending_single') - end - - if errors == 0 then - errorString = s('output.error_zero') - elseif errors == 1 then - errorString = s('output.error_single') - end - - local formattedTime = string_gsub(string_format('%.6f', sec), '([0-9])0+$', '%1') - - return colors.green(successes) - .. ' ' - .. successString - .. ' / ' - .. colors.red(failures) - .. ' ' - .. failureString - .. ' / ' - .. colors.magenta(errors) - .. ' ' - .. errorString - .. ' / ' - .. colors.yellow(pendings) - .. ' ' - .. pendingString - .. ' : ' - .. colors.bright(formattedTime) - .. ' ' - .. s('output.seconds') - end - - handler.testEnd = function(element, parent, status, debug) - if not options.deferPrint then - local string = successDot - - if status == 'pending' then - string = pendingDot - elseif status == 'failure' then - string = failureDot - elseif status == 'error' then - string = errorDot - end - - io_write(string) - io_flush() - end - - return nil, true - end - - handler.suiteStart = function(suite, count, total) - local runString = (total > 1 and '\nRepeating all tests (run %u of %u) . . .\n\n' or '') - io_write(string_format(runString, count, total)) - io_flush() - - return nil, true - end - - handler.suiteEnd = function() - io_write('\n') - io_write(statusString() .. '\n') - - for i, pending in pairs(handler.pendings) do - io_write('\n') - io_write(pendingDescription(pending) .. '\n') - end - - for i, err in pairs(handler.failures) do - io_write('\n') - io_write(failureDescription(err) .. '\n') - end - - for i, err in pairs(handler.errors) do - io_write('\n') - io_write(failureDescription(err, true) .. '\n') - end - - return nil, true - end - - handler.error = function(element, parent, message, debug) - io_write(errorDot) - io_flush() - - return nil, true - end - - busted.subscribe({ 'test', 'end' }, handler.testEnd, { predicate = handler.cancelOnPending }) - busted.subscribe({ 'suite', 'start' }, handler.suiteStart) - busted.subscribe({ 'suite', 'end' }, handler.suiteEnd) - busted.subscribe({ 'error', 'file' }, handler.error) - busted.subscribe({ 'failure', 'file' }, handler.error) - busted.subscribe({ 'error', 'describe' }, handler.error) - busted.subscribe({ 'failure', 'describe' }, handler.error) - - return handler -end diff --git a/tests/minit.lua b/tests/minit.lua new file mode 100644 index 0000000..46ef5f1 --- /dev/null +++ b/tests/minit.lua @@ -0,0 +1,25 @@ +#!/usr/bin/env -S nvim -l + +vim.env.LAZY_STDPATH = '.tests' +load(vim.fn.system('curl -s https://raw.githubusercontent.com/folke/lazy.nvim/main/bootstrap.lua'))() + +package.path = './tests/?.lua;./tests/?/?.lua;' .. package.path +vim.opt.rtp:append(vim.uv.cwd()) + +_, _G.DevTools = pcall(require, 'log') + +-- Setup lazy.nvim +require('lazy.minit').busted { + headless = { + process = false, + -- show log messages + log = false, + -- show task start/end + task = false, + -- use ansi colors + colors = true, + }, + spec = { + { dir = vim.uv.cwd() }, + }, +} diff --git a/spec/spec_helper.lua b/tests/spec_helper.lua similarity index 97% rename from spec/spec_helper.lua rename to tests/spec_helper.lua index b2fe44c..8ac978b 100644 --- a/spec/spec_helper.lua +++ b/tests/spec_helper.lua @@ -1,8 +1,6 @@ local assert = require('luassert.assert') local match = require('luassert.match') -_G.LOG = require('log') - local M = {} --Remove tabs and spaces as tabs @@ -31,6 +29,12 @@ M.delete_buffer = function(buf) vim.api.nvim_buf_delete(buf, { force = true }) end +M.delete_all_bufs = function() + for _, buf in ipairs(vim.api.nvim_list_bufs()) do + M.delete_buffer(buf) + end +end + M.get_buffer = function(buf) ---@diagnostic disable-next-line return vim.fn.getbufline(buf, 0, '$') diff --git a/spec/unit/external_evals_spec.lua b/tests/unit/external_evals_spec.lua similarity index 100% rename from spec/unit/external_evals_spec.lua rename to tests/unit/external_evals_spec.lua diff --git a/spec/unit/lua-console_spec.lua b/tests/unit/lua-console_spec.lua similarity index 98% rename from spec/unit/lua-console_spec.lua rename to tests/unit/lua-console_spec.lua index a6eb067..f3a5768 100644 --- a/spec/unit/lua-console_spec.lua +++ b/tests/unit/lua-console_spec.lua @@ -30,7 +30,7 @@ describe('lua-console.nvim', function() }, mappings = { toggle = '!#', - attach = '!`', + attach = '@!', eval = '$#', kill_ps = '!K', }, @@ -49,7 +49,7 @@ describe('lua-console.nvim', function() it('sets a mapping for attaching to buffer', function() local maps = h.get_maps(buf) - assert.is.not_nil(maps['!`']) + assert.is_true(maps['@!'] == 'Lua-console - attach to buffer') end) describe('lua-console - open/close window', function() diff --git a/spec/unit/mappings_spec.lua b/tests/unit/mappings_spec.lua similarity index 97% rename from spec/unit/mappings_spec.lua rename to tests/unit/mappings_spec.lua index ed1f1fe..d8fa10a 100644 --- a/spec/unit/mappings_spec.lua +++ b/tests/unit/mappings_spec.lua @@ -50,6 +50,7 @@ describe('lua-console.nvim - mappings', function() end) after_each(function() + h.delete_all_bufs() require('lua-console').deactivate() buf, win = nil, nil end) @@ -202,7 +203,7 @@ describe('lua-console.nvim - mappings', function() it('opens a split with file from function definition', function() content = h.to_table([[ - vim.lsp.status + require("lua-console").toggle_console Test ]]) h.set_buffer(buf, content) @@ -212,10 +213,10 @@ describe('lua-console.nvim - mappings', function() h.send_keys(config.mappings.open) local new_buf = vim.fn.bufnr() - assert.has_string(vim.fn.bufname(new_buf), 'nvim/runtime/lua/vim/lsp.lua') + assert.has_string(vim.fn.bufname(new_buf), 'lua/lua-console.lua') local line = vim.fn.line('.') - assert.is_same(line, 652) + assert.is_same(line, 69) end) it('opens a split with file from stacktrace', function() diff --git a/spec/unit/utils_spec.lua b/tests/unit/utils_spec.lua similarity index 96% rename from spec/unit/utils_spec.lua rename to tests/unit/utils_spec.lua index 2f27656..aabb5b5 100644 --- a/spec/unit/utils_spec.lua +++ b/tests/unit/utils_spec.lua @@ -1,13 +1,15 @@ local assert = require('luassert.assert') local h = require('spec_helper') ---TODO: add multiple assigmnets andchar selection +--TODO: add multiple assignments and char selection +--TODO: fix shuffled tests describe('lua-console.utils', function() _G.Lua_console = {} - local buf, config, utils + local buf, console, config, utils setup(function() + console = require('lua-console') utils = require('lua-console.utils') config = require('lua-console.config') config.setup { buffer = { show_one_line_results = true } } @@ -120,6 +122,7 @@ describe('lua-console.utils', function() local code, result, expected it('preserves context between executions if config is set', function() + config.setup { buffer = { preserve_context = true } } code = { 'a = 5' } lua_evaluator(code) @@ -147,7 +150,7 @@ describe('lua-console.utils', function() end) it('provides access to context', function() - config.setup { buffer = { preserve_context = true, strip_local = false } } + config.setup { buffer = { preserve_context = true, strip_local = true } } code = { 'test_1 = 5; b = 10; local c = 100' } lua_evaluator(code) @@ -169,15 +172,20 @@ describe('lua-console.utils', function() end) it('strips local declaration', function() - config.setup { buffer = { preserve_context = true, strip_local = true } } + console.setup() + console.toggle_console() - code = { 'test_1 = 5; b = 10; local c = 100' } - lua_evaluator(code) + buf = vim.fn.bufnr('lua-console') + vim.api.nvim_set_current_win(vim.fn.bufwinid(buf)) - code = { 'test_1 = test_1 + 5; b = b * 10; c = c - 50' } - lua_evaluator(code) + h.set_buffer(buf, { + 'test_1 = 5; b = 10; local c = 100', + 'test_1 = test_1 + 5; b = b * 10; c = c - 50', + '_ctx', + }) - code = { '_ctx' } + vim.treesitter.get_parser(buf, 'lua'):parse() + utils.eval_code_in_buffer(buf, true) expected = h.to_string([[ { @@ -187,7 +195,7 @@ describe('lua-console.utils', function() } ]]) - result = lua_evaluator(code) + result = h.get_buffer(buf) assert.has_string(result, expected) end)