A Neovim plugin that adds a bunch of refactoring tools for Javascript/TypeScript. Namely:
- extract variable
- extract function/method
- extract class/function/variable declaration into a separate file
- declare undefined variable/method/function/class
- list imports for current file
- update imports when moving file (also works in NERDTree)
- autocomplete
require
/import
paths - turn a string into a template string once
${}
detected
Requires treesitter.
Use a plugin manager:
Plug 'artemave/vjs'
Vjs comes with an omnifunc
for require
/import
path completion:
Set it up:
autocmd FileType {javascript,typescript} setlocal omnifunc=vjs#ModuleComplete
Rename/move file and update imports. It updates both imports in current file and all files that import current file.
It's also possible to batch rename files by calling vjs#imports#RenameFile
directly. For example, assuming there is a bunch of .mjs
files in quickfix window that I want to rename to .jsx
, the following command will perform batch rename and update all the imports:
:cdo call vjs#imports#RenameFile({ 'new_name': expand('%:r') . '.jsx' })
There is an experimental integration with NERDTree project explorer. Renaming/moving javascript/typescript files in NERDTree automatically updates imports (watch demo).
Extracts selected code into a variable.
Extracts selected code into a global function.
Extracts enclosing function/class into a separate file. Inserts import into the original file.
If a reference under cursor happens to be undefined, this will insert a declaration for it. The appropriate declaration - variable, class or function - is automatically picked.
In a similar manner, if a method/property is not defined for this
in the current scope, this will insert its declaration.
Shows list of modules that require/import current file in quickfix window.
Vjs can automatically convert normal string to template string once the string contains ${}
. To enable this:
autocmd TextChanged * if &ft =~ 'javascript\|typescript' | call luaeval("require'vjs'.to_template_string()") | endif
autocmd InsertLeave * if &ft =~ 'javascript\|typescript' | call luaeval("require'vjs'.to_template_string()") | endif
Import update on rename, list dependants and gf
follow package references. E.g, in the following example, pressing gf
when the cursor is within 'abc'
in ./lib/index.js
, jumps to ./packages/abc/index.js
:
// ./packages/abc/index.js
module.exports = 'abc'
// ./lib/index.js
const moduleA = require('abc')
There are no default bindings. But you can use these:
au FileType {javascript,javascript.jsx,typescript} vmap <leader>vv :VjsExtractVariable<cr>
au FileType {javascript,javascript.jsx,typescript} vmap <leader>vf :VjsExtractFunctionOrMethod<cr>
au FileType {javascript,javascript.jsx,typescript} nmap <leader>ve :VjsExtractDeclarationIntoFile<cr>
au FileType {javascript,javascript.jsx,typescript} nmap <leader>vd :VjsCreateDeclaration<cr>
au FileType {javascript,javascript.jsx,typescript} nmap <leader>vr :VjsRenameFile<cr>
au FileType {javascript,javascript.jsx,typescript} nmap <leader>vl :VjsListDependents<cr>
If you don't like binding explosion, then perhaps you could add those as code actions via null-ls.
g:vjs_es_modules_complete
- don't strip out file extension from autocompleted modules and also show index
modules. Defaults to 0
.
g:vjs_nerd_tree_overriden
- if truthy, disables nerdtree integration. Defaults to 0
.
git clone https://github.com/artemave/vjs.git
cd vjs
./run_tests