Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

code bloc evaluatation via sniprun #73

michaelb started this conversation in Ideas
Discussion options

I'm adding support to org-mode code bloc evaluation to my plugin sniprun. (Currently on the dev branch, so the binary has to be compiled locally)

I though you might find it interesting, and maybe, who knows, usable?

You must be logged in to vote

Replies: 5 comments 14 replies

Comment options

I'm definitely interested! I'll give it a try in following days, and then I'll add it to docs/readme. Thanks!

You must be logged in to vote
4 replies
Comment options

Don't hesitate to submit feeback and request (especially since it's not released yet) !

Comment options

(btw) recently released sniprun v0.5.10 has support for orgmode in stable.

(minus some convenience things having to do with lower/uppercase markers, inline outputing and converting a final return to 'print' that are still in dev)

I don't think I will get down to it with the long and complex OrgMode specification though, like accepting input/arguments... 😅 too much work

Comment options

Hey, sorry for not testing this yet. I got sick so didn't do much work last week. I hope I'll give it a try this week.

Comment options

Haha, no worries, take care of yourself

It's not like I need feedback anyway, my coming here just a freebie for your project if you think sniprun is interesting

Comment options

@michaelb I feel a little dumb, but how do I use this in orgmode? I wasn't able to find any documentation around it, and I tried with this org content:

* TODO Testing
 #+BEGIN_SRC lua
 print('Test')
 #+END_SRC

Tried running :SnipRun in the block, tried selecting whole block and running visually :'<,'>SnipRun, tried selecting only the print statement and running visually :'<,'>SnipRun, but I get Failed to determine language of code bloc every time.

You must be logged in to vote
3 replies
Comment options

I feel a little dumb

please don't, this kind of failure is definitively due to me not documenting the feature well enough

I think this specific thing is due to the whole thing being indented? (Is this allowed in OrgMode?). Aside from that it should be okay

Screenshot_41

Comment options

Yeah, removing indentation makes it work. Orgmode allows indentation on these, so you can remove that limitation.

Comment options

Okay, will do :-)

Comment options

Works like a charm! Added it to readme to plugins section. Thanks!

You must be logged in to vote
0 replies
Comment options

@michaelb is it possible to add the org #+RESULTS: block to the file using the API output?

You must be logged in to vote
2 replies
Comment options

Yes (but).

but: it's not an official feature, and won't be one. The neovim 0.6+ way may be to use virtual lines, however, you may want to have an actual, editable, savable line with the results.

In this case, someone has actually done that; for markdown though. I think you'll have to at least modify the code bloc delimiters ( ``` in markdown): michaelb/sniprun#111 (comment)

Comment options

Thanks! That's very useful. I will see if I can tweak it to work with org. I am not yet very familiar with lua but I will give it a try over the holidays.

Comment options

@michaelb I have managed to adapt the script that you shared with me such that it prints the output to the org file. Under the #+Results affiliated keyword.

Click to check the code
local ok, sa = pcall(require, "sniprun.api")
if not ok then error("Snipun not installed") end
local M = {}
local code_block = {}
M.setup = {
 parse_pattern = {
 code_opening = [[\v^#\+(BEGIN_SRC|begin_src)]],
 code_closing = [[\v^#\+(END_SRC|end_src)]],
 -- #+RESULTS is an affiliated keyword
 -- it can precede any element, except those listed in the manual
 -- for now I use a simple regex that should detect the end of a fixed
 -- delimited block, a table or an unnested block
 -- https://orgmode.org/worg/dev/org-syntax.html#Affiliated_keywords
 result_opening = [[\v^#\+(RESULTS|results):]],
 result_closing = [[^\(\([:|]\|#+END_\).*\)\?\n\([:|]\s\?\)\@!]],
 },
 result_block_name = "#+RESULTS:",
}
function parse_block (opening, closing)
 local save_cursor = vim.fn.getpos('.')
 -- get line number of beginning of code block
 -- we want to go to the beginning of the block to avoid matching between two blocks
 local blk_beg_line_nr = vim.fn.search(opening, "bcW")
 if blk_beg_line_nr == 0 then
 print("Not in a block")
 return
 end
 -- get line number of closing of code block
 local blk_end_line_nr = vim.fn.search(closing, "nW")
 if blk_end_line_nr == 0 then
 print("Not in a block")
 return
 end
 print(blk_beg_line_nr, blk_end_line_nr)
 vim.fn.setpos(".", save_cursor)
 if blk_end_line_nr < save_cursor[2] then
 print("Not in a block")
 return
 end
 return {
 blk_beg_line_nr = blk_beg_line_nr,
 blk_end_line_nr = blk_end_line_nr
 }
end
function insert_result (result)
 result = vim.fn.split(result, "\n")
 for i = 1, #result do
 result[i] = ": " .. result[i]
 end
 local save_cursor = vim.fn.getpos('.')
 -- remove existing results if present
 vim.fn.setpos(".", { 0, code_block.blk_end_line_nr + 1, 1, 0 })
 non_empty_line_nr = vim.fn.search([[\S]], "W")
 result_block = parse_block(M.setup.parse_pattern.result_opening,
 M.setup.parse_pattern.result_closing)
 if result_block then
 vim.fn.deletebufline(vim.fn.bufname(), result_block.blk_beg_line_nr,
 result_block.blk_end_line_nr)
 end
 if vim.fn.getline(code_block.blk_end_line_nr + 1) ~= '' then
 vim.fn.append(code_block.blk_end_line_nr, '')
 end
 vim.fn.append(code_block.blk_end_line_nr + 1, M.setup.result_block_name)
 if #result > 0 then
 vim.fn.append(code_block.blk_end_line_nr + 2, result)
 end
 if vim.fn.getline(code_block.blk_end_line_nr + 2 + #result + 1) ~= '' then
 vim.fn.append(code_block.blk_end_line_nr + 2 + #result, '')
 end
 vim.fn.setpos(".", save_cursor)
 code_block = {}
end
function M.snip_org_run ()
 code_block = parse_block(M.setup.parse_pattern.code_opening, M.setup.parse_pattern.code_closing)
 if code_block then
 config_values = require"sniprun".config_values
 original_display = config_values["display"]
 original_display[#original_display + 1] = "Api"
 config_values["display"] = { "Api" }
 sa.run_range(code_block.blk_beg_line_nr, code_block.blk_end_line_nr, nil, config_values)
 config_values["display"] = original_display
 end
end
function api_listener (d)
 if d.status == "ok" then
 insert_result(d.message)
 elseif d.status == "error" then
 print("Error: ", d.message)
 end
end
sa.register_listener(api_listener)
return M

Unfortunately, the API listener is not called when there is a multi-line result. All my attempts were unsuccessful when fixing this problem. Any help to get this fixed would be appreciated.

I think there might be something wrong with the backend because the following return:

:lua require'sniprun.api'.run_string('print(1+2)\nprint(4+5)', 'python', {display = {'Classic'}})
3
9
Press ENTER or type command to continue

Whereas, the following returns nothing

:lua require'sniprun.api'.run_string('print(1+2)\nprint(4+5)', 'python', {display = {'Api'}})

But, the following returns

:lua require'sniprun.api'.run_string('print(1+2)', 'python', {display = {'Api'}})
Sniprun: No listener registered
You must be logged in to vote
5 replies
Comment options

I'll look into it when I can (rather sooner than later I hope), though it's a bit strange: Sniprun shouldn't even know about the number of lines in the output...

With some luck it'll be a trivial corner case, as this part clearly lack decent testing

Comment options

Well it's been a while and I (presumably) didn't receive notifications for all this time.

It appears the issue described about multi-line output in Api has been solved, and your script works quite well for the (quite simple) cases I can think of.
I intentionnally let some leeway to things I may not find 'natural' (errors displayed only in the command area, or printing the range of the results when ok, for example) but that probably match your design decisions.

Screenshot_135

We can probably mark this discussion as 'solved'

Comment options

That's awesome! It was worth the wait. I can confirm that the basic examples I set up are working perfectly. It's now my turn to polish the script a bit to add more babel-like functionalities to org in neovim. Btw, what was causing the problem?

Comment options

well actually I haven't the slightest clue.
I probably half-fixed (read: broke) this just after we last exchanged messages, and then a user probably opened an issue and I finished (fixed) it, but forgot to report back

About mutli-lines output breaking the API, I'd bet my money on bad escaping (of newline characters), since it rings a bell from a few month ago, and that would explain how even the lua code broke.

Though, I also opened this discussion at the very moment sniprun supported orgmode, and there have been countless occasions to polish/bugfix both orgmode support and sniprun itself since then, so these various improvements might also have helped.

Comment options

Thanks for the explanation! Bad escaping easily sneaks in the wrong places.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Category
Ideas
Labels
None yet

AltStyle によって変換されたページ (->オリジナル) /