michaelb / sniprun

A neovim plugin to run lines/blocs of code (independently of the rest of the file), supporting multiples languages
MIT License
1.43k stars 46 forks source link

api.run_string cant work as expected. #251

Closed soluty closed 11 months ago

soluty commented 11 months ago

Describe the bug as title

To Reproduce codestring = "echo 123" require("sniprun.api").run_string(codestring, "bash")

Expected behavior print 123 in configed display

Environment:

Additional context run_range works well

why i need run_string, because i am not familiar with rust, so as now, the only way i can change logic, is use run_string.

in bash, current the bash_original engine is useless because it only run selected code , so this code cant run

local a=1
echo a

the better way to wrap bash script is wrap the code in function like main or else. then run function, and bash can do more like cd to workdir by wrapping, and it can run nested function now, if i wrap selected code behind the hole buffer, in go it has the same problem, i can construct nested main.go file but i cant run_string to run it now.

michaelb commented 11 months ago

I can't reproduce the run_string() issue... be it in bash or go, both work. Could you share your sniprun version (:SnipInfo) and the logs associated with a failing run ? (:SnipReset + :lua require("sniprun.api").run_string(.....), then copy the content of ~/.cache/sniprun/sniprun.log ) I'm on the same neovim version and also Linux, so in theory there shouldn't be much difference

Mind that in the case of go, sniprun needs to know that "fmt" is a symbol coming from an import, so you would still need to have a go 'current buffer' with at least import "fmt". But you should have a meaningful error message at the least

what do you mean "if I wrap selected code behind the (w?)hole buffer ..." ?

PS: I'll fix Bash original like you suggested, though I'm actually thinking or removing it altogether soon: it's too easy to run something like "rm -rf $HOME/$tempfile" but with tempfile undefined

soluty commented 11 months ago

[00:00:00.043] (7f6b8d0bd700) INFO selected Bash_original [00:00:00.043] (7f6b8d0bd700) INFO [LAUNCHER] Selected interpreter: Bash_original, at level Bloc [00:00:00.046] (7f6b8d0bd700) INFO [RUN] Interpreter return a result [00:00:00.046] (7f6b8d0bd700) INFO Display type chosen: [VirtualText(Both), Terminal(OnlyErr), LongTempFloatingWindow(OnlyOk)] [00:00:00.046] (7f6b8d0bd700) INFO range is : [0, 0] [00:00:00.064] (7f6b8d0bd700) INFO namespace_id = 210 [00:00:00.073] (7f6b8d0bd700) INFO cleared previous virtual_text? Err(NeovimError(0, "Vim(call):E5555: API call: Invalid line number: out of range")) [00:00:00.073] (7f6b8d0bd700) INFO message '1234444' cleaned out [00:00:00.074] (7f6b8d0bd700) INFO message '1234444' cleaned out [00:00:00.075] (7f6b8d0bd700) INFO done displaying virtual text, Err(NeovimError(0, "Vim(lua):E5108: Error executing lua ...t/.local/share/nvim/lazy/sniprun/lua/sniprun/display.lua:159: Invalid 'line': out of range\nstack traceback:\n\t[C]: in function 'nvim_buf_set_extmark'\n\t...t/.local/share/nvim/lazy/sniprun/lua/sniprun/display.lua:159: in function 'display_extmark'\n\t[string \":lua\"]:1: in main chunk")) [00:00:00.075] (7f6b8d0bd700) INFO data_bloc = echo 1234444 [00:00:00.075] (7f6b8d0bd700) INFO length = 1 [00:00:00.075] (7f6b8d0bd700) INFO display terminal, with filter: = OnlyErr [00:00:00.075] (7f6b8d0bd700) INFO display terminal res = Ok(())

i see the log , it runs ok , but can not display in virtual text, so i think it cannot run ..

soluty commented 11 months ago

Since i change display to Classic , it runs ok, it looks like use run_string and virtual text donot know where to display virtual text , can i see the error in vim.notify than other errors? this is display error, so i cant get error from display TerminalErr, and i cant get any information except i know how and where the sniprun's log is.

soluty commented 11 months ago

suppose original bash code is this.

nest() {
   echo nest
}
main() {
   # some code
   # select two lines of code to get functions output
   local nest=$(nest)
   echo "hello $nest"
   # some code
}
main "$@"

suppose i select main function's code, your generate main.sh is

   local nest=$(nest)
   echo "hello $nest"

it is not valid code to run in bash.

i think this generate will work fine.

# now it can do file specific thing like i handy run the script 
cd  /to/i/select/buffers/dir
# just buffer  start
nest() {
   echo nest
}
main() {
   # some code
   # select two lines of code to get functions output
   local nest=$(nest)
   echo "hello $nest"
   # some code
}
# main "$@"   do not run main func
# just buffer end  
# wrap like this is realy the piece of scripts code can work. and it works like run the hole script.
___main___() {
   local nest=$(nest)
   echo "hello $nest"
} 
___main___
michaelb commented 11 months ago

Since i change display to Classic , it runs ok, it looks like use run_string and virtual text donot know where to display virtual text , can i see the error in vim.notify than other errors? this is display error, so i cant get error from display TerminalErr, and i cant get any information except i know how and where the sniprun's log is.

Hmm Indeed. Sniprun can't display virtual text if you don't have a line position, for sure. Silently failing is not very nice, though. I'll do something about that.

And since you've suffixed the display mode 'Terminal' with 'Err' in your config, right now it will only display errors, so: your run_string("echo 123", "bash") actually succeeds, but the result cannot be displayed by virtualtext (because you don't have a position where it's sensible to display at) nor by TerminalErr which only displays errors.

Solution:

run_string and run_range APIs have an optional 'config' argument, which looks just like the 'normal' config. You can for example set this argument to {display= {'Classic'} } to set that run_string's display mode to 'classic' only.

soluty commented 11 months ago

Since i change display to Classic , it runs ok, it looks like use run_string and virtual text donot know where to display virtual text , can i see the error in vim.notify than other errors? this is display error, so i cant get error from display TerminalErr, and i cant get any information except i know how and where the sniprun's log is.

Hmm Indeed. Sniprun can't display virtual text if you don't have a line position, for sure. Silently failing is not very nice, though. I'll do something about that.

And since you've suffixed the display mode 'Terminal' with 'Err' in your config, right now it will only display errors, so: your run_string("echo 123", "bash") actually succeeds, but the result cannot be displayed by virtualtext (because you don't have a position where it's sensible to display at) nor by TerminalErr which only displays errors.

Solution:

run_string and run_range APIs have an optional 'config' argument, which looks just like the 'normal' config. You can for example set this argument to {display= {'Classic'} } to set that run_string's display mode to 'classic' only.

can it use cursor line's line pos as virtual text's fallback? i think when i run with select a piece of code, my focus is always in my cursor, no matter if i use run_string or run_range api.

now i pass new config as third param, i realy like the virtual text, it could hold on last runs result except i run again. but i dont know how to clear it now, sniprun has no api to clear virtual text genrated. if i use direct api from nvim, i worry about it will clear other virtual text by other plugin, such like some plugin can fill param defination.

michaelb commented 11 months ago

sniprun has no api to clear virtual text genrated

It does: :SnipClose, aka `lua require'sniprun.display'.close_all()

can it use cursor line's line pos as virtual text's fallback?

sounds reasonable. I will change that in the upcoming release

michaelb commented 11 months ago

fixed in v1.3.7