Skip to content

Instantly share code, notes, and snippets.

@rohitfarmer
Last active January 31, 2024 05:32
Show Gist options
  • Star 41 You must be signed in to star a gist
  • Fork 8 You must be signed in to fork a gist
  • Save rohitfarmer/68cdadeaeeb196e8a6ecdebdee6e76a5 to your computer and use it in GitHub Desktop.
Save rohitfarmer/68cdadeaeeb196e8a6ecdebdee6e76a5 to your computer and use it in GitHub Desktop.
Nvim-R Demo

How to use Neovim or VIM Editor as an IDE for R

Note: This tutorial is written for Linux based systems.

Requirements

R >= 3.0.0

To install the latest version of R please flollow the download and install instructions at https://cloud.r-project.org/

Neovim >= 0.2.0

Neovim (nvim) is the continuation and extension of Vim editor with the aim to keep the good parts of Vim and add more features. In this tutorial I will be using Neovim (nvim), however, most of the steps are equally applicable to Vim also. Please follow download and installation instructions on nvim's GitHub wiki https://github.com/neovim/neovim/wiki/Installing-Neovim.

OR

Vim >= 8.1

Vim usually comes installed in most of the Linux based operating system. However, it may not be the latest one. Therefore, to install the latest version please download and install it from Vim's GitHub repository as mentioned below or a method that is more confortable to you.

git clone https://github.com/vim/vim.git
make -C vim/
sudo make install -C vim/

Plugin Manager

There are more than one plugin manager's available for Vim that can be used to install the required plugins. In this tutorial I will be using vim-plug pluggin manager.

Plugins

In the end below are the plugins that we would need to convert Vim editor into a fully functional IDE for R.

  1. Nvim-R: https://github.com/jalvesaq/Nvim-R
    • Nvim-R is the main plugin that will add the functionality to execute R code from within the Vim editor.
  2. Ncm-R: https://github.com/gaalcaras/ncm-R
    • Ncm-R adds synchronous auto completion features for R.
    • It is based on ncm2 and nvim-yarp plugins.
  3. Nerd Tree: https://github.com/preservim/nerdtree
    • Nerd Tree will be used to toggle file explorer in the side panel.
  4. DelimitMate: https://github.com/Raimondi/delimitMate
    • This plug-in provides automatic closing of quotes, parenthesis, brackets, etc.
  5. Vim-monokai-tasty: https://github.com/patstockwell/vim-monokai-tasty
    • Monokai color scheme inspired by Sublime Text's interpretation of monokai.
  6. Lightline.vim: https://github.com/itchyny/lightline.vim
    • Lineline.vim adds asthetic enhancements to Vim's statusline/tabline.

Procedure

  1. Make sure that you have R >=3.0.0 installed.
  2. Make sure that you have Neovim >= 0.2.0 installed.
  3. Install the vim-plug plugin manager.
curl -fLo ~/.local/share/nvim/site/autoload/plug.vim --create-dirs \
    https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
  1. Install the required plugins.

First, create an init.vim file in ~/.config/nvim folder (create the folder if it doesn't exist). This file is equivalent to a .vimrc file in the traditional Vim environment. To init.vim file start adding:

" Specify a directory for plugins
" - Avoid using standard Vim directory names like 'plugin'
call plug#begin('~/.vim/plugged')

" List of plugins.
" Make sure you use single quotes

" Shorthand notation
Plug 'jalvesaq/Nvim-R'
Plug 'ncm2/ncm2'
Plug 'roxma/nvim-yarp'
Plug 'gaalcaras/ncm-R'
Plug 'preservim/nerdtree'
Plug 'Raimondi/delimitMate'
Plug 'patstockwell/vim-monokai-tasty'
Plug 'itchyny/lightline.vim'

" Initialize plugin system
call plug#end()
  1. Update and add more features to the init.vim file.
" Set a Local Leader

" With a map leader it's possible to do extra key combinations
" like <leader>w saves the current file
let mapleader = ","
let g:mapleader = ","


" Plugin Related Settings

" NCM2
autocmd BufEnter * call ncm2#enable_for_buffer()    " To enable ncm2 for all buffers.
set completeopt=noinsert,menuone,noselect           " :help Ncm2PopupOpen for more
                                                    " information.

" NERD Tree
map <leader>nn :NERDTreeToggle<CR>                  " Toggle NERD tree.

" Monokai-tasty
let g:vim_monokai_tasty_italic = 1                  " Allow italics.
colorscheme vim-monokai-tasty                       " Enable monokai theme.

" LightLine.vim 
set laststatus=2              " To tell Vim we want to see the statusline.
let g:lightline = {
   \ 'colorscheme':'monokai_tasty',
   \ }


" General NVIM/VIM Settings

" Mouse Integration
set mouse=i                   " Enable mouse support in insert mode.

" Tabs & Navigation
map <leader>nt :tabnew<cr>    " To create a new tab.
map <leader>to :tabonly<cr>     " To close all other tabs (show only the current tab).
map <leader>tc :tabclose<cr>    " To close the current tab.
map <leader>tm :tabmove<cr>     " To move the current tab to next position.
map <leader>tn :tabn<cr>        " To swtich to next tab.
map <leader>tp :tabp<cr>        " To switch to previous tab.


" Line Numbers & Indentation
set backspace=indent,eol,start  " To make backscape work in all conditions.
set ma                          " To set mark a at current cursor location.
set number                      " To switch the line numbers on.
set expandtab                   " To enter spaces when tab is pressed.
set smarttab                    " To use smart tabs.
set autoindent                  " To copy indentation from current line 
                                " when starting a new line.
set si                          " To switch on smart indentation.


" Search
set ignorecase                  " To ignore case when searching.
set smartcase                   " When searching try to be smart about cases.
set hlsearch                    " To highlight search results.
set incsearch                   " To make search act like search in modern browsers.
set magic                       " For regular expressions turn magic on.


" Brackets
set showmatch                   " To show matching brackets when text indicator 
                                " is over them.
set mat=2                       " How many tenths of a second to blink 
                                " when matching brackets.


" Errors
set noerrorbells                " No annoying sound on errors.


" Color & Fonts
syntax enable                   " Enable syntax highlighting.
set encoding=utf8                " Set utf8 as standard encoding and 
                                 " en_US as the standard language.

" Enable 256 colors palette in Gnome Terminal.
if $COLORTERM == 'gnome-terminal'
    set t_Co=256
endif

try
    colorscheme desert
catch
endtry


" Files & Backup
set nobackup                     " Turn off backup.
set nowb                         " Don't backup before overwriting a file.
set noswapfile                   " Don't create a swap file.
set ffs=unix,dos,mac             " Use Unix as the standard file type.


" Return to last edit position when opening files
au BufReadPost * if line("'\"") > 1 && line("'\"") <= line("$") | exe "normal! g'\"" | endif

Frequently Used Keyboard Shortcuts/Commands

Note: The commands below are according to the init.vim settings mentioned in this Gist.

# Nvim-R
\rf               " Connect to R console.
\rq               " Quit R console.
\ro               " Open object bowser.
\d                " Execute current line of code and move to the next line.
\ss               " Execute a block of selected code.
\aa               " Execute the entire script. This is equivalent to source().
\xx               " Toggle comment in an R script.

# NERDTree
,nn               " Toggle NERDTree.

Example Code

library(tidyverse)
# \rf               " Connect to R console.
# \rq               " Quit R console.
# \ro               " Open object bowser.
# \d \ss \aa        " Execution modes. 
# ?help
# ,nn               " NERDTree.
# ,nt, tp, tn       " Tab navigation.

theme_set(theme_bw())
data("midwest", package = "ggplot2")

gg  <- ggplot(midwest, aes(x=area, y = poptotal)) +
        geom_point(aes(col = state, size = popdensity)) +
        geom_smooth(method = "loess", se = F) +
        xlim(c(0, 0.1)) +
        ylim(c(0, 500000)) +
        labs(subtitle = "Area Vs Population",
             y = "Population",
             x = "Area",
             title = "Scatterplot",
             caption = "Source: midwest")

plot(gg) # Opens an external window with the plot.

midwest$county # To show synchronous auto completion. 

View(midwest) # Opens an external window to display a portion of the tibble.

Add Colour etc. to VIM in a Screen Session (optional)

Add these lines to ~/.screenrc file.

# Use 256 colors
attrcolor b ".I"    # allow bold colors - necessary for some reason
termcapinfo xterm 'Co#256:AB=\E[48;5;%dm:AF=\E[38;5;%dm'   # tell screen how to set colors. AB = background, AF=foreground
defbce on    # use current bg color for erased chars]]'

# Informative statusbar
hardstatus off
hardstatus alwayslastline
hardstatus string '%{= kG}[ %{G}%H %{g}][%= %{= kw}%?%-Lw%?%{r}(%{W}%n*%f%t%?(%u)%?%{r})%{w}%?%+Lw%?%?%= %{g}][%{B} %m-%d %{W} %c %{g}]'

# Use X scrolling mechanism
termcapinfo xterm* ti@:te@

# Fix for residual editor text
altscreen on
@mmahmoudian
Copy link

Your Youtube video and this gist solved many of the confusions I had. Here I have a suggestion for one minimal additional feature:
Although Nvim-R is great, when you want to send a block, it uses it's backend R package to handle it. I found this plugin that is super minimal (only 116 lines of vim script) and its only task is to send the lines, characters, blocks of code to :terminal in (n)vim:

https://github.com/KKPMW/vim-sendtowindow

KKPMW/vim-sendtowindow

@rohitfarmer
Copy link
Author

Your Youtube video and this gist solved many of the confusions I had. Here I have a suggestion for one minimal additional feature:
Although Nvim-R is great, when you want to send a block, it uses it's backend R package to handle it. I found this plugin that is super minimal (only 116 lines of vim script) and its only task is to send the lines, characters, blocks of code to :terminal in (n)vim:

https://github.com/KKPMW/vim-sendtowindow

KKPMW/vim-sendtowindow

Cool, I will try that. I am glad that my video was helpful.

@deanerik
Copy link

Your Youtube video and this gist solved many of the confusions I had. Here I have a suggestion for one minimal additional feature:
Although Nvim-R is great, when you want to send a block, it uses it's backend R package to handle it. I found this plugin that is super minimal (only 116 lines of vim script) and its only task is to send the lines, characters, blocks of code to :terminal in (n)vim:

https://github.com/KKPMW/vim-sendtowindow

KKPMW/vim-sendtowindow

Wow thanks for sharing, this is much faster than using /d! I'm new to this vim as IDE setup, and found the initial speed of execution from Nvim-R a bit of a turn off.

@chunyunma
Copy link

Thank you for sharing this! One small typo: the hyperlink for lightline was incorrectly directed to nerdtree.

@HugoGit39
Copy link

Hi I get an E492: Not a editor command: PluginInstall error...how come?

Copy link

ghost commented Jan 25, 2021

Thank you so much

@nwwangnan
Copy link

Hi Rohit,

I hope you are doing good!

I configured my init.vim based on your sample. Everything works fine by now except the autocompletion part for R code. I meant the synchronous autocompletion.

I meant the following part:
########################################################################
" NCM2
autocmd BufEnter * call ncm2#enable_for_buffer() " To enable ncm2 for all buffers.
set completeopt=noinsert,menuone,noselect " :help Ncm2PopupOpen for more information.
########################################################################

You know, when I put this part in my init.vim to to run the R code, it also give me error like "
[ncm_r@yarp] Job is dead. cmd=['/Library/Framewor...m5dxqjhks1dgbpr0000gn/T/nvimf4mIQt/0', 3, 'ncm_r']"

Do you know what I can do about this?

best
Nan

@phmpacheco-ufjf
Copy link

Hi Rohit,

I hope you are doing good!

I configured my init.vim based on your sample. Everything works fine by now except the autocompletion part for R code. I meant the synchronous autocompletion.

I meant the following part:
########################################################################
" NCM2
autocmd BufEnter * call ncm2#enable_for_buffer() " To enable ncm2 for all buffers.
set completeopt=noinsert,menuone,noselect " :help Ncm2PopupOpen for more information.
########################################################################

You know, when I put this part in my init.vim to to run the R code, it also give me error like "
[ncm_r@yarp] Job is dead. cmd=['/Library/Framewor...m5dxqjhks1dgbpr0000gn/T/nvimf4mIQt/0', 3, 'ncm_r']"

Do you know what I can do about this?

best
Nan

Hey! I'm having the same issue. Don't know what's happening! Did you solve the problem?

@lf-araujo
Copy link

The trick to avoid this is using a previous version of Nvim-R:

Plug 'wsdjeg/Nvim-R'

My full neovim config is here

@phmpacheco-ufjf
Copy link

It worked! Thanks!!

@ryan-heslin
Copy link

The trick to avoid this is using a previous version of Nvim-R:

Plug 'wsdjeg/Nvim-R'

My full neovim config is here

I tried this (Ubuntu 20.04 virtual machine on a Windows 10 host), but the error message remains. Plug installing 'wsdjeg/Nvim-R' just creates an empty directory with the README and a file called path_to_nvimcom with the path to my R library.

I couldn't quite understand from this thread exactly what's causing the problem.
gaalcaras/ncm-R#17

Here is the complete error message:

[ncm_r@yarp] Traceback (most recent call last):
[ncm_r@yarp]   File "/home/rheslin/.local/share/nvim/plugged/nvim-yarp/pythonx/yarp.py", line 63, in <module>
[ncm_r@yarp]     module_obj = importlib.import_module(module)
[ncm_r@yarp]   File "/usr/lib/python3.8/importlib/__init__.py", line 127, in import_module
[ncm_r@yarp]     return _bootstrap._gcd_import(name[level:], package, level)
[ncm_r@yarp]   File "<frozen importlib._bootstrap>", line 1014, in _gcd_import
[ncm_r@yarp]   File "<frozen importlib._bootstrap>", line 991, in _find_and_load
[ncm_r@yarp]   File "<frozen importlib._bootstrap>", line 975, in _find_and_load_unlocked
[ncm_r@yarp]   File "<frozen importlib._bootstrap>", line 671, in _load_unlocked
[ncm_r@yarp]   File "<frozen importlib._bootstrap_external>", line 848, in exec_module
[ncm_r@yarp]   File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
[ncm_r@yarp]   File "/home/rheslin/.local/share/nvim/plugged/ncm-R/pythonx/ncm_r.py", line 303, in <module>
[ncm_r@yarp]     SOURCE = Source(vim)
[ncm_r@yarp]   File "/home/rheslin/.local/share/nvim/plugged/ncm-R/pythonx/ncm_r.py", line 37, in __init__
[ncm_r@yarp]     self.get_all_pkg_matches()
[ncm_r@yarp]   File "/home/rheslin/.local/share/nvim/plugged/ncm-R/pythonx/ncm_r.py", line 131, in get_all_pkg_matches
[ncm_r@yarp]     raise FileNotFoundError('Could not find any omnils_* files '
[ncm_r@yarp] FileNotFoundError
[ncm_r@yarp] : Could not find any omnils_* files in /home/rheslin/.cache/Nvim-R.
[ncm_r@yarp] Job is dead. cmd=['/usr/bin/python3', '-u', '/home/rheslin/.local/share/nvim/plugged/nvim-yarp/pythonx/yarp.py', '/tmp/nvimoQ2CZr/0', 5, 'ncm_r']


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment