jpalardy / vim-slime

A vim plugin to give you some slime. (Emacs)
http://technotales.wordpress.com/2007/10/03/like-slime-for-vim/
MIT License
1.87k stars 227 forks source link

let vim-slime ignore triple backtiks in markdown filles #380

Open pkyoung opened 1 year ago

pkyoung commented 1 year ago

Dear, Thank you for the helpful plugin.

I'd like to know how to used vim-slime with code block in md files. In example below, I like to execute cmd1 and cmd2 only by hitting c-c c-c.

cmd1 cmd2 <- cursor here

cmd3

This is similar issue with #209, and I made comment there also.

Thank you.

jpalardy commented 1 year ago

Hi @pkyoung

At the bottom of this section, there is a bit about g:slime_cell_delimiter

If you want to send blocks of code between two delimiters, emulating the cell-like mode of REPL environments like ipython, matlab, etc., you can set the cell delimiter on the g:slime_cell_delimiter variable and use the SlimeSendCell mapping to send the block of code

let g:slime_cell_delimiter = "#%%"
nmap <leader>s <Plug>SlimeSendCell

Can you try that and let me know if that works for you? (using triple backticks πŸ˜„ )

pvelayudhan commented 11 months ago

Hi @jpalardy , thank you for this amazing plugin and I just wanted to mention the g:slime_cell_delimiter functionality works fantastically.

I'd like to add on a suggestion that I think is still in line with the title of this issue: having functions other than slime#send_cell() be able to ignore the cell delimiter, just as you have done here: https://github.com/jpalardy/vim-slime/blob/ce6ffa7d5f3d5faf739c07c0409b5e2035c279cc/autoload/slime.vim#L100

My vimscript is pretty rough so I wanted to get an idea of your thoughts on this kind of functionality before really diving into it myself. I imagine that if that delimiter search and replace is evaluated further downstream (say, at send_range or even at the final send), it could make the code-block experience much nicer.

The reason for this is that occasionally, I do happen to want to run only the first few lines or last few lines of a chunk of code:

print(5)

# code that I don't to re-run

print("hi")

As the cell_delimiter is currently implemented, if I just wanted to run the first and last lines (for whatever reason), I would need to go back to resorting to temporarily adding blank lines between the delimiters:


print(5)

# code that I don't to re-run

print("hi")

That works decently well and honestly is not much of a big deal. Not much wrong with having the blank lines and if I really wanted to, I supposed splitting that code into multiple chunks is also an option.

I only bring this up because (with my minimal understanding) it looks like the lines of code used to strip out the delimiters when sending a cell through slime could very easily be relocated to apply to any slime send function. And I cannot really imagine a time where a user would specify a cell delimiter but only want that delimiter to be ignored during cell block sends, rather than any send.

What would you think about having all the slime send functions ignore the delimiters? If it sounds like a good idea to you but you don't have the time right now, I can try to see if I can implement this myself when I get a chance.

Thanks again for the stellar plugin!

jpalardy commented 11 months ago

Hi @pvelayudhan

I read your comment a few times, but I'm not sure I understand the situation and what you want to happen.

Could you make a bigger example and try to include:

Thanks πŸ‘

pvelayudhan commented 11 months ago

Definitely. Also I only just realized I forgot to escape the cell delimiters in the above example.

Let's say everything between the dashed lines is the contents of a .Rmd file (which has regular markdown interspersed with code blocks that begin with ``{r} and end with \```). And I have set in my configlet g:slime_cell_delimiter = "``"

------------- # This is the title of my file

This is a sentence.

```{r} 1 library(ggplot2) 2 library(dplyr) 3 4 print(1) 5 print(2) 6 7 print(10) 8 print(3) ``` -------------

If I try to slime send an entire cell, the behaviour is perfect:

------------- # This is the title of my file

This is a sentence.

```{r} # line 1-8 sends if cursor is here 1 library(ggplot2) # line 1-8 sends if cursor is here 2 library(dplyr) # line 1-8 sends if cursor is here 3 # line 1-8 sends if cursor is here 4 print(1) # line 1-8 sends if cursor is here 5 print(2) # line 1-8 sends if cursor is here 6 # line 1-8 sends if cursor is here 7 print(10) # line 1-8 sends if cursor is here 8 print(3) # line 1-8 sends if cursor is here ``` # line 1-8 sends if cursor is here -------------

If I try to send the paragraph im on with vip followed by slime region send, I get:

------------- # This is the title of my file

This is a sentence.

```{r} # this fails because backticks 1 library(ggplot2) # this fails because backticks 2 library(dplyr) # this fails because backticks 3 # nothing happens 4 print(1) # this sends 4-5 5 print(2) # this sends 4-5 6 # nothing happens 7 print(10) # this fails because backticks 8 print(3) # this fails because backticks ``` # this fails because backticks -------------

What I want to get is:

------------- # This is the title of my file

This is a sentence.

```{r} # this sends 1-2 1 library(ggplot2) # this sends 1-2 2 library(dplyr) # this sends 1-2 3 # nothing happens 4 print(1) # this sends 4-5 5 print(2) # this sends 4-5 6 # nothing happens 7 print(10) # sends 7-8 8 print(3) # this sends 7-8 ``` # this sends 7-8 -------------

My workaround in the mean time has been to add in bonus blank space before the first paragraph of code and after the last paragraph of code:

------------- # This is the title of my file

This is a sentence.

```{r} 0 1 library(ggplot2) # this sends 1-2 2 library(dplyr) # this sends 1-2 3 # nothing happens 4 print(1) # this sends 4-5 5 print(2) # this sends 4-5 6 # nothing happens 7 print(10) # sends 7-8 8 print(3) # this sends 7-8 9 ``` -------------

And then I remove lines 0 and 9 later. Let me know if it is still a little unclear!

jpalardy commented 11 months ago

Hi @pvelayudhan

Super clear now πŸŽ‰

I can relate to this example … especially since I'm a big Rmd user myself. But, interestingly, I did converge on "cheating" with empty lines, I can think of 2 reasons:

So, now I tend to structure my code in semi-logical paragraphs…

…

The mid-level solution is to pre-select your code before hitting ctrl-c, ctrl-c. A combination of paragraph movements (with { and }) with the o key and some tweaking can get you there.

But it's easy to break out of flow, if you have to think about block boundaries πŸ€”

…

A more final solution is to write some custom logic to "do what you mean", selection-wise:

In practice, I don't know if "what you mean" and what other people would mean/want is the same πŸ˜„

If you want to give it a try β€” let me know how that goes. You can also consider posting your solution here for others.

…

Another solution is to modify the text before the send. πŸ’‘

pvelayudhan commented 11 months ago

Thank you for the response and it is very fair that your Rmd habits were developed for this to not really be an issue lol. I switched over to vim-slime from Nvim-R (also a great plugin, but just for R) where I became used to slinging paragraphs right out of the gates of the cells.

I've opted for the "pre-select" code option that I'll share here. This is like "vip" command but will ignore the starting and ending triple backticks. It's not pretty but it works πŸ˜„:

function paragraph_select()
    vim.cmd.normal("{j")
    local line_start = vim.api.nvim_get_current_line()
    local has_cell_start = (line_start == "```{r}")
    vim.cmd.normal("}k")
    local line_end = vim.api.nvim_get_current_line()
    local has_cell_end = (line_end == "```")
    if (has_cell_start and has_cell_end) then
        vim.cmd.normal("{jjV}kk")
    elseif (has_cell_start) then
        vim.cmd.normal("{jjV}k")
    elseif (has_cell_end) then
        vim.cmd.normal("vipk")
    else
        vim.cmd.normal("vip")
    end
end

Then back in vimscript I have:

nnoremap ; :lua paragraph_select()<CR>:SlimeSend<CR>}j

To send the current paragraph with ";". Works perfectly fine for my purposes : )

Cheers!