/ncm-R

R autocompletion for Neovim and vim 8 :memo: :bar_chart: :zap:

Primary LanguagePythonGNU General Public License v3.0GPL-3.0

💜 for #rstats, my favorite editor and a nice completion framework

Asynchronous R completion for Neovim and vim 8

R completion for Neovim and vim 8 with ncm-R

ncm-R provides asynchronous, as-you-type completion for the R language, as well as R documents such as RMarkdown.

It relies on the great plugin nvim-R to get the completion data and extends ncm2 for the completion.

Table of contents:

Features

Completion

  • Objects from the global R environment
  • Variables of a dataframe when selecting columns inside brackets (dataframe[,]) or after a $
  • Functions from loaded packages or from specific package with package::
  • Packages inside library() and require()
  • Datasets inside data()
  • Arguments inside functions
  • Variables inside data transformation pipelines (%>%) and building ggplots (+)

Snippets

If UltiSnips and its ncm2 module is installed, pressing Tab after selecting a completion suggestion will expand syntax snippets. Snippets in ncm-R are designed to help you save a few keystrokes by writing some code for you. I find it particularly useful with function arguments.

You can see when a snippet is available for a suggestion when a [+] appears in the pop-up menu.

Here's a list of all available snippets:

  • dataframe -> dataframe %>%|
  • variable -> "variable"| (only when inside selecting columns of a dataframe inside brackets)
  • function -> function([arg1], arg2) (expands only arguments with no default value, you can then Tab to go to the next argument)
  • package -> package::|
  • argument (use Tab to go after the end of expanded text):
    • By default -> argument = [DEFAULT_VALUE]
    • If default value is inside quotes -> argument = "[default]"
    • If default value is a boolean, then use its negation. For instance, if TRUE by default then it will expand to argument = [FALSE]

| stands for the cursor position and [] shows the cursor selection after snippet expansion.

R Markdown and Rnoweb

  • R completion available in R code chunks
  • Completion for chunk options

Who should use this plugin?

You'll probably enjoy ncm-R:

  • If you like how RStudio does completion but won't use any editor other than Neovim
  • If you use a lot of data pipelines (%>%)
  • If you want a "suggest as you type" completion behavior

It should be noted that Nvim-R already comes with OmniCompletion. It's lightweight and it works well, but you need to ask for completion (<C-x><C-o>) and it doesn't support pipelines.

ncm-R is built on top of Nvim-R completion data to offer more features, while remaining as fast and as lightweight as possible.

Installation

Use your favorite plugin manager. For instance, with vim-plug :

Plug 'ncm2/ncm2'
Plug 'roxma/nvim-yarp'
Plug 'jalvesaq/Nvim-R'
Plug 'gaalcaras/ncm-R'

" Vim 8 only
if !has('nvim')
    Plug 'roxma/vim-hug-neovim-rpc'
endif

" Optional: for snippet support
" Further configuration might be required, read below
Plug 'sirver/UltiSnips'
Plug 'ncm2/ncm2-ultisnips'

" Optional: better Rnoweb support (LaTeX completion)
Plug 'lervag/vimtex'

Please make sure that you fulfill all ncm2 requirements, especially if you use vim 8.

If snippet completion does not work out of the box, read below.

Usage

General behavior

When you open an R file, first start an R session with nvim-R (default mapping is <localleader>rf, see :help Nvim-R-use). That's because completion suggestions only include objects from your global environment and functions from loaded packages (although Nvim-R loads some packages by default, see :help R_start_libs).

If you're familiar with completion in RStudio, you will feel at home with ncm-R. For instance, you won't see suggestions for your data.frames and their variables before you run the proper command in the R console to load them in the global environment. Likewise, you won't see dplyr functions if you forgot to run library(dplyr) first.

Pop-up menu configuration

The default pop-up menu follows a 3 column layout:

Type Column 1 Column 2 Column 3
Argument argument = DEFAULT_VALUE
Dataset {package} Type of dataset (e.g. tibble) Short dataset description
Functions {package} function Short function description
Package package Short package description
Variable variable Type of variable (e.g. integer)

The length of the two first columns can be changed in your .vimrc. Choosing a value below the minimum length will remove the column altogether:

Column Minimum length Default length Global variable
Column #1 7 13 g:ncm_r_column1_length
Column #2 7 11 g:ncm_r_column2_length

Finally, if you don't want the columns to be aligned, you can disable all column padding:

let g:ncm_r_column_layout = 0

Getting the snippets to work

ncm2-ultisnips might not work out of the box with your UltiSnips configuration, whether you want to use Enter or use Tab instead.

Contributing to ncm-R

Overview

Nvim-R is in charge of generating and updating the completion data:

Completion data Stored in
objects in the Global Environment GlobalEnvList_* file in the g:rplugin_tmpdir directory
loaded packages g:rplugin_loaded_libs
objects from packages pack_descriptions and omnils_* files in g:rplugin_compldir

ncm-R then retrieves the completion data, parses the buffer and feeds candidate matches to ncm2's API. For more information, please check out this section of Nvim-R's README and :help ncm2-API.

Debugging

You can run NVIM_PYTHON_LOG_FILE=/tmp/log NVIM_PYTHON_LOG_LEVEL=INFO nvim then look at nvim.log_py3_ncm_r. You can also tail -f nvim.log_py3_* | grep --color "\[ncmR\]" to get only ncm-R messages.

Some tests can be run. The idea is to have two windows side to side (using tmux, i3 or whatever you like). In one window, run ./test/nvim_init and monitor what happens in Neovim. On the other window, run python test/test_ncmr.py: it will guide you through the different test cases.

Contributors

Special thanks to @jalvesaq for making several improvements to Nvim-R's API.