vim-imp is a plugin for managing import statements in the Vim text editor. Its
core purpose is to insert a fully-qualified import statement for a symbol in
your program. For example, :ImpSuggest List
in a Java file might prompt the
developer with options
import java.util.List;
import java.awt.List;
import com.lowagie.text.List;
import com.example.api.MyService.Method.List;
while :ImpFirst
would insert the java.util.List
version without prompting.
This can be used while adding a new identifier to your program, or when running
through quickfix errors because the compiler yelled at you for not importing
something.
Both :ImpSuggest
and :ImpFirst
accept multiple symbols in one command, e.g.
:ImpSuggest Model View Controller
, which will make a suggestion for each in
turn. Partially-qualified imports are also supported, e.g. :ImpFirst Math.min
to get import static java.lang.Math.min;
.
This README is meant to help you get started; for extensive documentation see
:help imp
.
One of Imp's goals is to have a language-agnostic interface; the commands and mappings should work the same if you're importing a symbol in Java, TypeScript, Python, BUILD files, etc. Imp additionally avoids MxN tool–language explosions by providing generic Suggest and Pick handlers while delegating regex generation and statement insertion to language-specific but tool-agnostic handlers.
A non-goal is doing anything with wildcard imports like import java.util.*;
.
Such imports make it hard to know what symbols are available, and they're
generally not needed if your editor has good support for importing specific
symbols. (Note that ES6 wildcard imports like import * as foo from 'foolib';
are supported, on the assumption that a consistent name is used for a
particular library and this doesn't actually pollute your namespace, it just
lets you call foo.whatever()
rather than importing whatever
by name.)
Imp requires Vim 8.0 or higher. If you have Vim 8+ but see an error about an unknown function, file a GitHub issue.
This plugin depends on the Maktaba library and is best configured using Glaive. To install them, use your favorite plugin manager, e.g.
" vim-plug:
Plug 'google/vim-maktaba' | Plug 'google/vim-glaive'
Plug 'flwyd/vim-imp'
" Vundle:
Plugin 'google/vim-maktaba'
Plugin 'google/vim-glaive'
Plugin 'flwyd/vim-imp'
" This line goes after vundle#end()
call glaive#Install()
" vim-addon-manager:
call vam#ActivateAddons(['glaive', 'github:flwyd/vim-imp'])
or git clone https://github.com/flwyd/vim-imp
and set runtimepath+=/path/to/vim-imp
in your .vimrc
or as a vim8 package:
mkdir -p ~/vim/pack/vim-imp/start
git clone https://github.com/google/vim-maktaba ~/vim/pack/vim-maktaba/start
git clone https://github.com/google/vim-glaive ~/vim/pack/vim-glaive/start
git clone https://github.com/flwyd/vim-imp ~/vim/pack/vim-imp/start
Imp consists of several types of handlers; there are several implementations
of each handler. Importing a symbol happens in several stages—one per handler
type—and each stage calls handler implementations in order until one returns a
value. The order of handlers is configured using Maktaba settings, with
Glaive as the easy way to do this.
Handler order can be specified for a specific language; the default
handlers
are used if none are configured for the language. You can see a list of all
handlers by running :ImpHandlers
once the plugin is installed. An example
configuration in your .vimrc
after plugins are loaded:
Glaive imp plugin[mappings]
\ Suggest[default]=buffer,ripgrep,prompt
\ Location[default]=packageroot
\ Pick[default]=window Pick[python]=lucky
\ Insert[bzl]=top
\ Report[default]=popupnotify
Explanation:
Glaive imp
activates the Imp plugin.plugin[mappings]
installs the default mappings,:help imp-mappings
(useplugin[mappings]=_
to use a different character like underscore rather than<Leader>i
as a prefix).Suggest[default]=buffer,ripgrep,prompt
will first look for import statements in other open buffers, then use ripgrep to find possible imports in nearby files. Ifrg
doesn't return any results then it will prompt for a statement, using a language-specific template. TheSuggest
default isbuffer,known,prompt
.Location[default]=packageroot
instructs handlers likeripgrep
,ag
,ack
, andgrep
to look in files in a hierarchy which shares a build system config file (e.g. find the nearest BazelBUILD
file). TheLocation
default isvcsroot,pwd
(search the whole version control repository directory, or the current working directory if not in a VCS repo).Pick[default]=window Pick[python]=lucky
will present a split window to pick from multiple import options in most languages, but will use thelucky
handler for Python, inserting the first match found without prompting. ThePick
default isinputlist
which shows numbered options at the bottom of the screen.Insert[bzl]=top
will addload
statements to the first line of.bzl
/BUILD
files rather than inserting them in sorted order. This example does not override the defaultInsert
handler list, which islang,top
, which uses a language-specific insertion strategy before falling back to first-line behavior.Report[default]=popupnotify
shows the added import statement in a popup window at the top of the screen which will disappear after a few seconds. The defaultReport
handler isecho
which prints the import statement at the bottom of the screen (and requires hitting return if multiple statements are imported).
Some handlers have additional settings, e.g. to specify a path to a command or
add additional arguments. See :help imp-config
for details.
Use Imp in command mode:
:ImpSuggest List
to use the Prompt handler if more than one match forList
is found:ImpFirst Optional
to insert the first/best match forOptional
.
In normal mode, the default mapping \ii
will run :ImpSuggest
on the symbol
under the cursor while \if
will run :ImpFirst
. (If you have mapleader
in
your .vimrc then replace \
with your chosen leader.) There aren't any default
insert-mode mappings, but I recommend something like this, which lets you hit
ctrl-X twice in insert mode to add the symbol next to your cursor and then keep
typing.
inoremap <C-X><C-X> <Plug>(imp-suggest-current)
inoremap <F3> <Plug>(imp-first-current)
Some of the handlers can work without any language support. If you edit a text
file and run :ImpSuggest foo
then the prompt
Suggest handler will ask you
for an import statement for foo
and the top
Insert handler will put that
line on the first line of the file. But the plugin is most effective when
there's an available lang
plugin for the filetype you're editing. As of early
October 2023, the supported languages are
bzl
(load()
statements in Bazel BUILD files and Starlark .bzl files)es6
(static imports in JavaScript, TypeScript, and .jsx/.tsx; no dynamicimport("…")
orgoog.require()
support; TODO: assertions)java
(static and non-static imports in Java)kotlin
(Kotlin imports, including aliases)php
(use
statements for PHP imports of classes, functions, and constants; does not supportuse trait
or closure variables)python
(import foo
andfrom foo import bar
support including aliases)
I would like to have "compatible languages" be able to import from each other if
the main language didn't have any matches. For example, we should be able to
import MyJavaUtil
from Kotlin even if you're the first person to import it in
a .kt
file. I haven't decided exactly how to do this yet, though; I'm
considering a jvm
handler.
Imp, via Maktaba and Glaive, provides plugin hooks for developers to add
support for other languages or generic handlers. Supporting a new language
generally requires implementing Pattern
and Insert
handler functions for
the language. The Pattern
handler provides a set of regular expressions
which are passed to regex engines like vim
, grep
, or ag
to search source
code files for possible import statements. A set of functions under imp#re
are provided to make such regular expressions more readable and reusable; see
:help imp-regex
. The Import
handler determines where to add the import
statement in the current buffer; this often reuses regex patterns from the
Pattern
handler or may build a basic lexer for the language in question. See
[autoload/imp/lang/java.vim] for an example of the reusable regex approach or
[autoload/impp/lang/python.vim] for an example with a lexer.
See :help imp-handlers
for general instructions on how to write a handler.
If you add support for a language or using a tool that’s publicly available, please consider contributing the handler as open source, either in the vim-imp repository or as a separate Vim plugin. If you add support for a language or DSL used only inside your own organization, you are certainly welcome to keep the work private. I’ve tested extensibility support by writing handlers for both a private source code search tool and a company-internal language.
Questions about writing handlers are welcome via GitHub issues or email.
I've been using this plugin on a daily basis for over a year (mostly with Java and Kotlin code) and it feels pretty ergonomic, but I would love more feedback. Are the defaults sensible? Are there ways the commands could be improved? Are there imports the regex patterns fail to find? Is the documentation clear enough? Please open a GitHub issue if you have feedback about the way things work.
The languages supported so far are mostly a subset ones I've needed to use in
my day job. If you'd like support for your favorite programming language please
open a GitHub issue with examples of how import statements work in that
language. If you'd like to implement support, see the
contributor documentation. Some attractive languages include
C#, D, Elixir, Go, Groovy, Haskell, Julia, Rust, Sass, Scala, and Swift. I
haven't yet addressed languages where symbols aren't named explicitly: it's
hard to know what symbols #include
could bring into a C or C++ program,
though C++ using
statements could be handled; this problem also applies to
Ruby, Dart, R, Ada, and Protocol Buffers.
There is a running list of potential enhancements at the bottom of :help imp
.
Vim Imp is copyright 2023 Google LLC. It is made available under the Apache 2.0
license, see LICENSE
for details.
This project is not an official Google project. It is not supported by Google and Google specifically disclaims all warranties as to its quality, merchantability, or fitness for a particular purpose.