All Projects → kristijanhusak → vim-js-file-import

kristijanhusak / vim-js-file-import

Licence: MIT License
Import/require files in javascript and typescript with single button!

Programming Languages

Vim Script
2826 projects
javascript
184084 projects - #8 most used programming language
lua
6591 projects
python
139335 projects - #7 most used programming language
shell
77523 projects
typescript
32286 projects
Vue
7211 projects

Projects that are alternatives of or similar to vim-js-file-import

VimConfig
Configuration files for Vi-IMproved.
Stars: ✭ 23 (-82.31%)
Mutual labels:  vim-plugin, vim-plugins
Nerdtree
A tree explorer plugin for vim.
Stars: ✭ 16,380 (+12500%)
Mutual labels:  vim-plugin, vim-plugins
Exit Vim
Vim plugin that exits Vim on startup
Stars: ✭ 176 (+35.38%)
Mutual labels:  vim-plugin, vim-plugins
vim-bettergrep
A better way to grep in vim.
Stars: ✭ 15 (-88.46%)
Mutual labels:  vim-plugin, vim-plugins
swifty-vim
⌨️ A Vim plugin for Swift which provides file detection, syntax highlighting, support for compiling and running tests, and optional support for formatting and linting tools.
Stars: ✭ 18 (-86.15%)
Mutual labels:  vim-plugin, vim-plugins
Targets.vim
Vim plugin that provides additional text objects
Stars: ✭ 2,114 (+1526.15%)
Mutual labels:  vim-plugin, vim-plugins
Vifm.vim
Vim plugin that allows use of vifm as a file picker
Stars: ✭ 197 (+51.54%)
Mutual labels:  vim-plugin, vim-plugins
Vimpanel
A modern side panel for Vim
Stars: ✭ 97 (-25.38%)
Mutual labels:  vim-plugin, vim-plugins
vim-jsonc
⚠️Deprecated⚠️: Vim syntax highlighting plugin for JSON with C-style line (//) and block (/* */) comments.
Stars: ✭ 52 (-60%)
Mutual labels:  vim-plugin, vim-plugins
vim-phpstan
A Vim plugin for PHPStan - https://github.com/phpstan/phpstan. It calls `phpstan` to do static analysis of your PHP code and displays the errors in Vim's quickfix list.
Stars: ✭ 26 (-80%)
Mutual labels:  vim-plugin, vim-plugins
Vimux
easily interact with tmux from vim
Stars: ✭ 1,980 (+1423.08%)
Mutual labels:  vim-plugin, vim-plugins
vim-inccomplete
Vim plugin for #include directive completion.
Stars: ✭ 14 (-89.23%)
Mutual labels:  vim-plugin, vim-plugins
Ale
Check syntax in Vim asynchronously and fix files, with Language Server Protocol (LSP) support
Stars: ✭ 11,380 (+8653.85%)
Mutual labels:  vim-plugin, vim-plugins
Vim Dadbod Completion
Database autocompletion powered by https://github.com/tpope/vim-dadbod
Stars: ✭ 163 (+25.38%)
Mutual labels:  vim-plugin, vim-plugins
Vim Todo Lists
Vim plugin for TODO lists
Stars: ✭ 126 (-3.08%)
Mutual labels:  vim-plugin, vim-plugins
Visual Split.vim
Vim plugin to control splits with visual selections or text objects
Stars: ✭ 190 (+46.15%)
Mutual labels:  vim-plugin, vim-plugins
Vim Systemd Syntax
Syntax highlighting for systemd service files in Vim.
Stars: ✭ 57 (-56.15%)
Mutual labels:  vim-plugin, vim-plugins
Fzf Filemru
File MRU with fzf.vim
Stars: ✭ 76 (-41.54%)
Mutual labels:  vim-plugin, vim-plugins
vim-sass-colors
sass/scss/less/css color literal and color variable highlighting (works with imports)
Stars: ✭ 24 (-81.54%)
Mutual labels:  vim-plugin, vim-plugins
filestyle
filestyle is a Vim plugin that highlights unwanted whitespace and characters.
Stars: ✭ 30 (-76.92%)
Mutual labels:  vim-plugin, vim-plugins

Vim js file import

This plugin allows importing javascript and typescript files using ctags. Tested only with Universal ctags. There is also partial support for Vue.

It's similar to vim-import-js, but much faster because it's written in vimscript.

Why?

I tried using vim-import-js, but it didn't fullfill all my expectations. This is the list of things that this plugin handles, and vim-import-js is missing:

  • Performance - Importing is fast because everything is written in vimscript. No dependencies on any external CLI, only ctags which is used by most of people.
  • Only appends imports - import-js replaces the content of whole buffer when importing, which can cause undesired results.
  • Importing files with different naming convention - import-js doesn't find imports with different naming conventions. This plugin allows importing both snake_case and camelCase/CamelCase. This means that if you have a file named big_button.js, You can import it with these words: BigButton, bigButton, big_button
  • Smarter jump to definition - Solves same naming convention issues mentioned above, and removes obsolete tags generated by universal-ctags when trying to find the definition.
  • *repeat.vim support

Table of contents

Requirements

  • (N)vim with python support, any version (2 or 3) or node installed and available in $PATH
  • Universal ctags
  • Tested only on Neovim and Vim8+

Installation

Install Universal ctags

$ git clone https://github.com/universal-ctags/ctags
$ cd ctags && ./autogen.sh && ./configure && make && sudo make install

It's also recommended to install some plugin for auto-updating ctags, since this plugin heavily relies on it. gutentags is good choice.

Add plugin to vimrc

Plug 'ludovicchabant/vim-gutentags'
Plug 'kristijanhusak/vim-js-file-import', {'do': 'npm install'}

Examples

import React from 'react';

class App extends React.Component {
  render() {
    return (<div><MyButton>Submit</MyButton></div>)
  }
}

Setting cursor on MyButton and pressing <Leader>if finds the component and adds import at top

import React from 'react'
import MyButton from './components/MyButton'

class App extends React.Component {
  render() {
    return (<div><MyButton>Submit</MyButton></div>)
  }
}

By default import <name> from <file> is used. If file contains any const <name> = require(<file>), import will be added like that.

const React = require('react')
const MyButton = require('./components/MyButton');

class App extends React.Component {
  render() {
    return (<div><MyButton>Submit</MyButton></div>)
  }
}

Partial imports are also handled (import { <name> } from <file>)

import { MyButton } from './components/AllComponents';

class App extends React.Component {
  render() {
    return (<div><MyButton>Submit</MyButton></div>)
  }
}

Mappings

By default, following mappings are used if they are not already taken:

nnoremap <Leader>if <Plug>(JsFileImport)

nnoremap <Leader>iF <Plug>(JsFileImportList)

nnoremap <Leader>ig <Plug>(JsGotoDefinition)

nnoremap <Leader>iG <Plug>(JsGotoDefinition)

nnoremap <Leader>ip <Plug>(PromptJsFileImport)

nnoremap <Leader>is <Plug>(SortJsFileImport)

nnoremap <Leader>ic <Plug>(JsFixImport)

Goto definition

To jump to definition use <Leader>ig mapping, or if you want to leverage built in tag jumping functionality, use provided tagfunc (see :help tagfunc):

set tagfunc=jsfileimport#tagfunc

Sorting

To sort imports by the import path use SortJsFileImport mapping <Leader>is:

This:

  import Foo from './file_path'
  import moment from 'moment'

Becomes this:

  import moment from 'moment'
  import Foo from './file_path'

Note: Sorting is not behaving well when there are partial multi-line imports:

 import {
    one,
    two,
    three
  } from 'four'

This is due to limitation with :sort command. If anyone know how to get around this, please open up an issue.

If you want imports to be always sorted, add let g:js_file_import_sort_after_insert = 1 to your vimrc and plugin will automatically sort imports after every insert

let g:js_file_import_sort_after_insert = 1

Typedef imports

Note: This is still experimental.

Import dependencies as typedefs. Example:

// src/Models/User.js
class User {}


// index.js

/**          v cursor
 * @param {Us|er} user
 */
function main(user) {

}

Doing JsFileImportTypedef or pressing <leader>it will import the User as typedef:

/**
 * @typedef {import('./src/Models/User')} User
 */

/**
 * @param {User} user
 */
function main(user) {
  // Lsp properly handles autocompletion for user now
}

Removing unused imports

Unused imports can be cleared by ising command JsFixImport or mapping <Leader>ic. It relies on eslint to figure out which imports are unused and clears them out. Make sure to do npm install in the plugin directory.

Settings

In case tag is not found for the given word, you will be prompted to enter the file path manually. Path needs to be selected from the current (n)vim working directory. Plugin will take care of determining if it's full or partial import.

To disable this option, set g:js_file_import_prompt_if_no_tag to 0:

let g:js_file_import_prompt_if_no_tag = 0

You can use prompt whenever you want with mapping <Leader>ip

By default import [name] from [file] is used to add new imports, in case when there are no any other existing imports. If file contains at least one require([file]), it will use the require() to import files.

To force using require() always, add this flag to settings:

let g:js_file_import_force_require = 1

Absolute imports (packages) are always imported first, which is recommended by most style guides. To import package the same way as files (last), add this flag to settings:

let g:js_file_import_package_first = 0

Semicolons are added at the end of requires and imports. To disable this add this flag to settings:

let g:js_file_import_omit_semicolon = 0

Overriding mappings

If you want to use different mappings, you can disable them all with this setting:

let g:js_file_import_no_mappings = 1

And then add your mappings like this:

nmap <C-i> <Plug>(JsFileImport)
nmap <C-u> <Plug>(PromptJsFileImport)

Using double quotes

If you want to use double quotes instead of single quotes, add this setting:

let g:js_file_import_string_quote = '"'

Using FZF for prompts

By default, if there is a need for prompt (For example, to select from multiple import option), native inputlist() is used. If you want to use FZF, add this setting:

let g:js_file_import_use_fzf = 1

Using Telescope for prompts

By default, if there is a need for prompt (For example, to select from multiple import option), native inputlist() is used. If you want to use Telescope, add this setting:

let g:js_file_import_use_telescope = 1

Importing from files with extension

If you want to import files with extension, add this setting:

let g:js_file_import_strip_file_extension = 0

Check help docs for more information.

Deoplete strip file extension

If you are using deoplete.nvim and it's file autocomplete to import files, you probably noticed that the file extension is also part of the name when you autocomplete it, so you need to remove it manually each time. This plugin adds a small deoplete converter that strips that file extension out of the completion word and shows it separately. So instead of getting this in autocomplete:

user_service.js [F]
MyButton.jsx [F]

You get this:

user_service [F] [js]
MyButton [F] [jsx]

This is enabled by default (only for javascript and typescript syntax). To disable this option, add this to your vimrc:

let g:deoplete_strip_file_extension = 0

Vue support

There is some basic support for Vue:

  1. Supports importing js/ts files into *.vue file <script> tag
  2. Supports importing .vue file into another .vue file by matching filename. Imports may work better if custom ctags syntax file is used (https://gist.github.com/Fmajor/0024facc213087a3b4f296b50bf2c197)
  3. Webpack alias support with this config:
let g:js_file_import_from_root = 1
let g:js_file_import_root = getcwd().'/src'
let g:js_file_import_root_alias = '@/'

Performance issues

In case importing or jumping to definition is slow, make sure you have these set up:

  • ripgrep, silversearher or ack installed. Used for finding files and directories with a matching name. If none of those are installed, falls back to vimscript findfile() which is much slower.

  • node_modules excluded from ctags file and added to wildignore option:

    set wildignore+=*node_modules/**

    If you use gutentags it will automatically read your wildignore so you don't have to worry about ctags part.

    More info on issue #5

Contributing

There are no any special guidelines for contributing.

All types of contributions, suggestions and bug reports are very welcome!

Thanks to:

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].