2

I am writing an RMarkdown file, which is a document that is a hybrid of text and R code. Here is an example of what that document could look like:

Here is an example of text within my Rmarkdown file. 
This is used to describe the code block below:

```{r}
dataframe <- outcome.df %>%
  na.omit() %>%
  group_by(Hospital, State) %>%
  arrange(desc(HeartAttackDeath)) %>%
```

Here is an example of another text block
And the following is an example of another code chunk:

```{r}
result <- lapply(names(dataframe), complete.cases)
```

I would like to move all of the code to another document. How would I go about selecting just the code, using vim? i.e. everything between ```{r} and ```

6
  • Is this question on topic?
    – Hotschke
    May 29, 2019 at 15:39
  • 5
    I'm voting to close this question as off-topic because It's not about Vi or Vim, but rather another editor, RStudio.
    – Herb
    May 29, 2019 at 17:13
  • Anyway, we could try to help him how to do that on Vim... May 30, 2019 at 0:58
  • I read the "on topic" page, and found this:" It need not be a stand-alone program; a plugin for Visual Studio that gives vi-like behavior is on-topic, but only the vi-like behavior is." I'll clarify that I would like to accomplish this through the vim bindings on RStudio. If mods still think this is off topic, feel free to close it.
    – JKing
    May 30, 2019 at 9:09
  • Like @JoãoA.Toledo said, I would still prefer to solve this in a vim way. If anyone could help me accomplish this in vim, that would be great as well!
    – JKing
    May 30, 2019 at 9:13

3 Answers 3

1

This seems like a prime case for a text object, but unfortunately, Vim doesn't recognize ```{R} or ``` as text object delimiters.

There's at least three options that do work:

1. Click and drag with the mouse. A bit blasphemous, perhaps, but it can get the job done if there's not too much needing to be selected and your Vim or equivalent was built with mouse support.


2. Position your cursor on the first line of what you want selected, press Shift + v, then use gg or j to jump down to the last line you want selected. Having visible line numbers can be helpful here. Absolute line numbers for the count for gg, relative line numbers for the count for j.


3. This requires a little set up, but doesn't require you to think about how many lines you're selecting, and makes repeated use almost trivial.

:let @/ = "```"
:let @a = gnVnkoj

This can then be used by positioning the cursor above the section you want to select (even above the delimiter, but after any preceding sections' delimiters), then just running @a.

Explanation:

The first line, simply sets the "last used" search pattern without actually jumping to it by directly setting the search register. The second line sets up a macro in the a register. gn jumps to the next item of the last used search pattern (should the the opening delimiter) and enters visual mode, selecting it. Shift+v switches to line-wise visual mode. n jumps to the next found instance of the search pattern (should be the closing delimiter). k moves up a line to deselect the delimiter. o moves the cursor to the other end of the selection and "reverses" the selection, so it starts at the bottom and ends at the top, where the cursor now is. j moves down a line to deselect the opening delimiter.

1
  • #3 seems to be the best solution for me. It makes the most sense to me, and is something I can do without spending too much time on setting up commands. Thanks!
    – JKing
    Jun 4, 2019 at 10:57
1

You can try this:

ggqrq

and then

:execute '/\%>' . line('.') . 'l^```{r}' | +1,/^```$/-1y R | normal @:

What it does:

gg goes to first position in the buffer;

qrq starts to record a macro on register r and ends it immediately; it simply clears the register r;

:execute '/\%>' . line('.') . 'l^```{r}' searches for a line after current one (see :help /\%>l) with the pattern ^```{r};

| separates this command from the next;

+1,/^```$/-1y R yanks to register R from the next line till the next one that starts with ^```$ less one; as we used capital R, the new content is appended to what was already there;

| separates this command from the next;

normal @: re-executes last : command (this whole line).

At the end you will have all the content you want in the r register.

1
  • Thanks! This seemed to work in vim (not in RStudio)
    – JKing
    Jun 4, 2019 at 10:53
1

if of vim-textobj-markdown

When you use vim and do not mind to use a plugin, you can always check

https://github.com/kana/vim-textobj-user/wiki

In your case you will find the plugin https://github.com/coachshea/vim-textobj-markdown

This plugin maps by default if to address the inner of a code block.

There are more plugins which you could consider, e.g.

Also creating your own textobject would be an option:

If you get fancy, you could write a plugin based on targets.vim similar to line-targets.vim to get a very comprehensive experience of textobjects, something like

 if  af  If  Af
inf anf Inf Anf
ilf alf Ilf Alf

There is a pending PR for vimtex (a LaTeX plugin) to define textobjects for LaTeX commands and environments based on targets.vim: see the cheatsheet for a quick look.

However, I doubt that any of this will help you in RStudio.

3
  • While this could be really useful in my own setup, I don't have the necessary permissions to install vim plugins in my current work environment. Thanks for your help!
    – JKing
    Jun 4, 2019 at 10:54
  • I am just curious: Are you sure you do not have write permissions in your home directory? If you can have a vimrc, then you can have also your own plugins. Plugins are so to speak vimrc files under $HOME/.vim/pack/....
    – Hotschke
    Jun 4, 2019 at 11:31
  • Looks like I do actually have write permissions! That just opened up a whole array of options for me. Thanks!
    – JKing
    Jun 4, 2019 at 12:59

Your Answer

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

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