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

Seamlessly execute file scope "Global (file head declarations)" local variable to allow for future methods execution #286

Closed MikeLemo1 closed 2 months ago

MikeLemo1 commented 2 months ago

Is your feature request related to a problem? Please describe. Executing lua nvim function e.g. require("notify") which are usually declared as abbreviation e.g. local notify = require("notify") at top of the file (head) for ease of future use now if I want to snip run just a single function a wrote it the file using notify("Hello") would yield an error even if local notify = require("notify") is executed once since it's local it doesn't get saved in successive SnipRuns

Describe the solution you'd like There might be a cleaner solution the developers more experienced with code interperters but I think having the option to auto execute all local variable (Through treesitter) that are at the file head and the relevant once for "the selected execution scope" before :SnipRun automatically would suffice.

but a more proper solution of somehow loading the local variables like how global onces are loaded'd be more ideal.

michaelb commented 2 months ago

The Lua_nvim interpreter should remember variable declarations, even locals as long as they're in global scope...

Could you share a minimal reproducer (code, config) ?

MikeLemo1 commented 2 months ago

Yes Code Running both works running them seperately doesn't:

local notify = require("notify")
notify("Hello there")

Config:


local M = {
  "michaelb/sniprun",
  branch = "master",
  build = "sh install.sh",

  config = function()
    require("sniprun").setup({
      display = {"NvimNotify"},
      repl_enable = {'Python3_jupyter', "Lua_nvim"},
      selected_interpreters={'Python3_jupyter', "Lua_nvim"},
      live_mode_toggle='enable',
    })
  end,

return M

}
michaelb commented 2 months ago

I see... it indeed doesn't work, but also, so it is when you type it directly into neovim's cmd....

Treesitter has been experimented with but (at the time) was rather hit-or-miss. However detecting local <keyword> = require<stuff> and inserting <keyword> = require<stuff> instead is quite easy; other languages (python, mostly) do this for much more complex import patterns.

What are your thoughts about this ? Do you have a regex in mind that covers the relevant corner cases you're aware of (like, possible indentation, require syntax, etc...) ?

MikeLemo1 commented 2 months ago

I see... it indeed doesn't work, but also, so it is when you type it directly into neovim's cmd....

Treesitter has been experimented with but (at the time) was rather hit-or-miss. However detecting local <keyword> = require<stuff> and inserting <keyword> = require<stuff> instead is quite easy; other languages (python, mostly) do this for much more complex import patterns.

What are your thoughts about this ? Do you have a regex in mind that covers the relevant corner cases you're aware of (like, possible indentation, require syntax, etc...) ?

Since I still don't understand the philosophy of regex, treesitter, lsp and the philosophy of how to capture should one think when capturing elements using regex and treesitter and how to Perfectly (unlike heruistically(solving big chunk but not whole/perfectly)) parsing but I tend to stick to the idea of giving Fallbacks to Errors in our case from the compiler and based on that have out own middle man code interperter and resolver that add the local x_from_error declarations parsing based on treesitter or lsp basically having our middle man try to handle the compiler/interperter error and complete the execution successfully (while giving relevant notify warning when it doe's such thing)

Again there is probably be a faster(for the algorithem) more efficient way and philosophy to handle that but I only still understand the whole parsing , compiling and interpreting paradigms heuristically rather than perfectly as a whole to take complete responsibility for such task. In other words I don't feel like I'm knowlegefull / enough of an expert to make and stand behind such a thing.

michaelb commented 2 months ago

The 1.3.14 release is out with fixes for this issue.

The minimal example you shared now works, but maybe more complex patterns will need some adjustment.

If after updating you experience related problems, please reopen this issue

MikeLemo1 commented 2 months ago

Thanks already an improvement and a peace of mind, it'd be nice if it could also "remmember" local variables inside functions with the respectable context to maybe be able to check / recheck other call down the lines, running it with it's essentials "from the top" and skipping the rest of the "unselected" and "unrelated" functions but I might be talking ahead of myself because developing in nvim doesn't feel and smooth as the nvim ideal reflects, but it might be just me though it definitely gets better over time somewhat.

It'd also be nice to be able to "plugin cache" some code with visual selection from one file and be able to execute it in another (guess mostly useful for nvim dev) for testing purposes, though it might be easy to do but once's sniprun interpretation gets more involved it's gonna require some integration matching with whatever it does, but the meaning is more towards "run by reference" rather than "run by a copy"

michaelb commented 2 months ago

Hmm I feel like de-'local'izing variables from functions is bound to conflict with some other thing at some point in the dev' workflow. I rather have sniprun simply (and understandably) not work rather than produce weird/wrong behavior, so what you're asking for is a lot more involved. Though, for many other languages with REPL, there is no such 'local' barrier preventing function's variables to enter global scope.... I'll think about it

I can't reasonably build parsers for every language to select only "related" code from anywhere in the file/project, so I'll have to build a generic thing around either treesitter or a LSP, both of which have rather obscure APIs. They are in the roadmap but I don't personally feel like spending time on that