0

I'm new to Vim and trying to create a book how practical applications of Vim key bindings to R and Quarto based workflows.

Using R with Quarto we will typically encourage two code blocks:

```{r}
#| label: something
#| fig-width: 10
#| fig-cap: "something"
#| echo: false
#| eval: true

plot<- diamonds %>%
ggplot(aes(x=price,y=carat))+
geom_point()

```

I really like the key binding of vi{tag} e.g. vi{the thing you want to grab between} to quickly highlight to yank, edit or copy.

However, I don't know how to do that with the below scenarios (referencing the above code chunk)

  1. how to grab everything between the opening ``` and the closing ```
  2. how to grab the code meta data (everything that has #|)
  3. how to grab just the code section within the code junk (e.g. plot downwards)
1

1 Answer 1

1

The 'tag' concept in your question is called text-object in the Vim documentation.

There are various text objects defined. Some standard text-object can be used to address part of your question (Paragraph), some plugin defined text-object can be used for some other part (Multi Line String) and some custom text objects are needed to address the rest.

Paragraph

To select an entire paragraph (all the lines separated by blank lines) you can do: vip (using the underlying ip text-object. More information with :help text-objects)

Multi Lines String

To select everything between ``` and ``` you need an extension of the i` text-object that support multi-lines strings.

If you install the target plugin, to select everything between ` you can do: vi`.

Remark: Since on some keyboards the backtick character: ` is a dead key (i.e.: it produce a character only in combination to the next character you type) you may need to type vi` with a trailing space (i.e.: vi`space).

Custom Text Object

To select the set of contiguous lines that starts with #| you need to define a specific text object for that.

If you add the following lines to your .vimrc file a new im text-object will be defined.

vnoremap im <ESC>$?\v(^#\\|.*$\n)@<!^#\\|<CR>:normal! V<CR>/\v^#\\|.*$(\n^#\\|)@!<CR>
omap im :normal Vim<CR>

With this im text object you could select the block with: vim.

Explanation

The first line makes im extend the selection to the entire block in Visual mode:

vnoremap im <ESC>$?\v(^#\\|.*$\n)@<!^#\\|<CR>:normal! V<CR>/\v^#\\|.*$(\n^#\\|)@!<CR>
  1. <ESC> leaves Visual mode
  2. $ goes at the end of the line
  3. ?\v(^#\|.*$)@<!^#\|<CR> search for the previous occurrence of a line starting with #| that is not preceded by a line starting with #| (in the vnoremap the | need to be escaped \|)
  4. :normal! V<CR> enter in Visual mode
  5. /\v^#\|(\n^#\|)@!<CR> search for the next occurrence of a line starting with #| that is not followed by a line starting with #|

The total extend the visual selection to the set of contiguous lines starting with #|.

The second line defines an operator pending action for im

omap im :normal Vim<CR>

You enter the operator pending mode when Vim is waiting keys to complete an action (e.g. when you type y in normal mode Vim is waiting a move or a text object specifier to know what to yank exactly)

Remark: Since this mapping make use of the previously defined im mapping we can't use the non-recursive version of omap. If we would we should have to repeat the sequence previously defined.

With this one it select the entire block. Hence yim will yank the entire block, cim will change the entire block, dim will deleted the entire block.

6
  • Thanks for the education! The vi’ combo doesn’t work for me though. Does my cursor need to be in a special place? Feb 19, 2023 at 20:43
  • The combo need to use the back thick vi` which is different from vi'. Since ` is a deadkey on my keyboard I have to type: vi` (including a trailing space) Feb 19, 2023 at 21:08
  • I'll explain more about the text object tomorrow ;-) Feb 19, 2023 at 21:13
  • 1
    @VivianDeSmedt is the backtick text object standard? I feel like I might have a mapping for that, or at least that it doesn’t work perfectly with triple-backticks.
    – D. Ben Knoble
    Feb 19, 2023 at 22:39
  • 1
    i` is indeed standard but it only works if the backticks are on the same line.
    – romainl
    Feb 20, 2023 at 11:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.