relastle
vim-nayvy
Python

:new_moon: Enriching python coding in Vim :snake:

Last updated Dec 9, 2025
67
Stars
4
Forks
1
Issues
0
Stars/day
Attention Score
20
Language breakdown
Python 93.4%
Vim Script 3.5%
Lua 2.0%
Shell 0.6%
Vim Snippet 0.3%
Makefile 0.3%
โ–ธ Files click to expand
README

vim-nayvy

Enriching python coding.

1. Installation

Using vim-plug

Plugโ€‡'relastle/vim-nayvy'

2. Usage

2.1 Commands

NayvyImports

nayvy_imports

NayvyImportFZF

nayvy<em>import</em>fzf

NayvyTestGenerate & NayvyTestGenerateFZF

nayvy<em>test</em>generate

2.2 Use with other plugin.

2.2.1 ALE

ALE, Asynchronous Lint Engine, is one of the SOTA plugins of Vim. Even though LSP is becoming more and more popular, the plugin provides brilliant features, including great abstraction against code fixer.

Thus, vim-nayvy provides code fixer funciton nayvy#ale_fixer.

Vim script Below is a example of using nayvy#ale_fixer with autopep8 and isort.

let g:ale_fixers = {
      \ 'python': ['nayvy#ale_fixer', 'autopep8', 'isort'],
      \ }

" or if you already defined g:ale_fixer, write let g:alefixers['python'] = ['nayvy#alefixer', 'autopep8', 'isort']

And here is demonstrations.

ale_fixer

2.2.2 ultisnips

Auto import when snippet expansion

vim-nayvy provides auto_import function used with UltiSnips' snippet. UltiSnips provides post_expand trigger for each single snippet, which executes prerefined command when the snippet is expanded.

The snippet fragment below import auto_import function from nayvy, and defines pretty print post fix completion that add import statement from pprint import pprint as pp if not exists.

global !p
from nayvyvimif.ultisnips import (
	auto_import,
)
endglobal

postexpand "autoimport(snip, 'from pprint import pprint as pp', 0)" snippet '((\S|\.)+)\.pp' "pprint postfix completion" r !p var_name = match.group(1) snip.rv = &quot;pp(&quot; + var_name + &quot;)&quot; endsnippet

(The sample snippet is here and tested with a vader script)

Note that three arguments of auto_import are

  • Snip object of UltiSnips. you should always pass snip
  • Import statement string
  • The import level
- 0: Standard library imports. - 1: Related third party imports. - 2: Local application/library specific imports.

(cf. https://www.python.org/dev/peps/pep-0008/#imports)

And here is demonstrations.

ultisnips<em>auto</em>import_demo

Pydocstring expansionn

global !p
from nayvyvimif.ultisnips import (
	generate_pydocstring,
)
endglobal

postjump "generatepydocstring(snip)" snippet """ "Pydocstring" w endsnippet

The snippet above enables the pydocstring expansion when the triple-quotes are triggered in a function.

Here is a demonstration.

nayvy<em>ultisnips</em>pydocstring

2.2.3 coc.nvim

This plugins also provide auto-completion of importable items, follewd by auto-importing of the completed items. This is thanks to coc's ability to easily creating new coc sources Create custom source ยท neoclide/coc.nvim Wiki.

You can see how auto-importing is conducted in the GIF below.

nayvy_coc

When you auto-complete Class/Function inside the current python project, the signature and docstring will also be shown like this.

nayvy<em>coc</em>info

To use this function, please bundle neoclide/coc.nvim as well as relastle/vim-nayvy.

Plug 'neoclide/coc.nvim', {'branch': 'release'}
Plugโ€‡'relastle/vim-nayvy'

The automatic import in completion is conducted by the item-selected event. By default, the event is fired by Ctrl + y (when the item is focused in pmenu).

If you use the following settings described here,

" Use <cr> to confirm completion, &lt;C-g&gt;u means break undo chain at current
" position. Coc only does snippet and additional edit on confirm.
" <cr> could be remapped by other vim plugin, try :verbose imap &lt;CR&gt;.
if exists('*complete_info')
  inoremap <expr> <cr> complete_info()["selected"] != "-1" ? "\<C-y>" : "\<C-g>u\<CR>"
else
  inoremap <expr> <cr> pumvisible() ? "\<C-y>" : "\<C-g>u\<CR>"
endif

the completion event can be trigger by just Enter (, which I personally recommend ๐Ÿ‘).

3. Configurations

3.1 Configuration with vim g: variable or environment variable.

All configurable settings can be configured through vim script variables and environment variables.

This is because you may set some project-specific settings different from your global vim settings. Thus, the priority of load settings is as follows.

Environment variable -> Vim script variable -> Default variable

| Vim Script variable name | Environment variable name | Description | | --- | --- | --- | | g:nayvyimportpathformat | $NAYVYIMPORTPATHFORMAT | Define the import statement format when importing the class/function inside the same package. | | g:nayvylinterforfix | $NAYVYLINTERFORFIX | Define the linter to use when autofixing the missing imports or unused imports. | | g:nayvypyprojectrootmarkers | $NAYVYPYPROJECTROOTMARKERS | Define marker (filenames) indicating the python project root directory. | | g:nayvyimportconfigpath | $NAYVYIMPORTCONFIGPATH | Define the file path containing your own import statement lines. | | g:nayvycocenabled | $NAYVYCOCENABLED | Define whether coc is enabled (1) or not (0). | | g:nayvycoccompletionicon | $NAYVYCOCCOMPLETIONICON | Define icon rendered in the completion item fron nayvy coc sources. | | g:nayvycocmenumaxwidth | $NAYVYCOCMENUMAXWIDTH | Define max length of menu represented in completion menu by the coc source. | | g:nayvycmpenabled | $NAYVYCMPENABLED | Define whether cmp is enabled (1) or not (0). |

g:nayvyimportpathformat ($NAYVYIMPORTPATHFORMAT)

  • all_absolute (Prefer all project classes/functions are imported with absolute path.)
  • all_relative (Prefer all project classes/functions are imported with relative path.)
  • under_relative (Prefer sub-package classes/functions are imported with relative path and ther other with absolute path)
default: all_absolute

g:nayvylinterforfix ($NAYVYLINTERFORFIX)

  • ruff
  • pyflakes
  • flake8
default: ruff

g:nayvypyprojectrootmarkers ($NAYVYPYPROJECTROOTMARKERS)

Example of vim

let g:nayvypyprojectroot_markers = [
  \ 'pyproject.toml',
  \ 'setup.py',
  \ 'setup.cfg',
  \ 'requirements.txt',
\ ]

Example of environment variable

export NAYVYPYPROJECTROOT_MARKERS='pyproject.toml,setup.py'  # comma-separated format
default: ['pyproject.toml', 'setup.py', 'setup.cfg', 'requirements.txt']

g:nayvyimportconfigpath ($NAYVYIMPORTCONFIGPATH)

see the section below (3.2 Import configration).

default: `

g:nayvycocenabled ($NAYVYCOCENABLED)

  • 1: enabled
  • 0: disabled
> default:
1

g:nayvycoccompletionicon ($NAYVYCOCCOMPLETIONICON)

nayvy<em>coc</em>completion_icon

Please set any string as you like ๐Ÿ˜„.

> default: ๏ Ÿ nayvy

g:nayvycocmenumaxwidth ($NAYVYCOCMENUMAXWIDTH)

If the completion menu gets too wide, it may bother you. So you can specify the max length of whole import statement. If the statement length gets longer than the value, the from part of import statement(, which typically tends to be longer) will be trimmed.

nayvy<em>coc</em>completion_menu

> default: -1 (no limit)

3.2 Importing configuration

Nayvy detects import statement should be used by looking into $XDGCONFIGPATH/nayvy/import_config.nayvy. (if $XDGCONFIGPATH is not set, ~/.config/nayvy/import_config.nayvy)

If you set g:nayvyimportconfigpath or $NAYVYIMPORTCONFIGPATH, the file will be used.

You can use environment variable in the path like,

<pre><code class="lang-vim">let g:nayvyimportconfig_path = &#39;$HOME/nayvy.py&#39;</code></pre>

In the file, you can write any python import statements like this.

<pre><code class="lang-python">from typing import List, Optional from pprint import pprint as pp import sys import os

import numpy as np

from .hoge import HogeHogeHoge as hoge</code></pre>

Line breaks seperating python import blocks are important, cause nayvy determines the line where a statement inserted by it.

My own setting is here. Feel free to copy and paste and use it.

4. Feature roadmap

  • [x] Auto imports (add and remove) based on pre-defined rules.
  • [x] Importing multiple modules using fzf.
  • [x] Touching or jumping to test script.
  • [x] Auto generating or jump to test function.
  • [x] Generating test functions using fzf.
  • [x] Providing some domain objects useful in creating ultisnips snippets.
  • [x] Providing coc custom source which can insert import statement automatically.
  • [x] Utility function of converting function arguments to docstring (for UltiSnips).
  • [ ] Make auto generated Test template configurable. (Now unittest, standard library, is supported)

5. Philosophy

Most python code parsing algorithms of vim-nayvy is not strict, and it contains some heuristics ( In other words, it is not based on AST, or hierarchical module structure). However, it is intentional. I personally think the heuristics works well for most real-world usecases, and has benefit in terms of performance. The strategy is also robust against partially broken codes. Some code actions (such as implementing test function and jumping) should be executable when python code in current buffer is incomplete (cannot parsed via AST, or unimportable by importlib).

Now, it is the era of LSP. I do not think prividing aid for code completion via non-LSP plugin is demanded, as I personally think code completion is one of the most powerful and stable features privided by LSP. Thus, the main aim of vim-nayvy` is providing a little bit utility functions :smile:

6. Note

:construction:

  • Please note that any destructive change (backward incompatible) can be done without any announcement.
  • This plugin is in a very early stage of development. Feel free to report problems or submit feature requests in Issues, or make PRs.

7. LICENSE

MIT

๐Ÿ”— More in this category

ยฉ 2026 GitRepoTrend ยท relastle/vim-nayvy ยท Updated daily from GitHub