Skip to content

About

A vim plugin to manage projects and sessions

Topics

Resources

Contributing

Stars

27 stars

Watchers

1 watching

Forks

Latest commit

 

History

795 Commits

Folders and files

Repository files navigation

vim-project logo

vim-project

Projects for Vim and Neovim: switch between them, find files and text, replace across files, run tasks and work with git, all scoped to the project you are in.

Tests License: Unlicense

Open a project, search files, find in files, run lint and fix, git changes

Why vim-project

  • Vim and Neovim: plain Vimscript, Vim 8.2+ and Neovim 0.5+.
  • No freezing: searches run in the background.
  • Git like an IDE: changelists, shelves, background pull and push.
  • Per project: session, history, config and tasks.
  • Fast search: with fd, rg or ag (recommended), or find and grep.

Quick start

Needs Vim 8.2.3591+ or Neovim 0.5.1+, and git for the git features. fd and rg (or ag) are recommended for fast search; without them, find, grep and Vim's :vimgrep are used.

Install with lazy.nvim, vim-plug or Vim packages
-- lazy.nvim
{ 'leafOfTree/vim-project', lazy = false }
" vim-plug
Plug 'leafOfTree/vim-project'
# Vim's built-in packages
git clone https://github.com/leafOfTree/vim-project ~/.vim/pack/plugins/start/vim-project

For icons, add a Nerd Font with nerdfont.vim, and glyph-palette.vim to color them.

To uninstall, remove the plugin and config_home (~/.vim/vim-project-config by default).

Add a project and start working:

:Project ~/code/my-app      " add a folder as a project and open it
:ProjectList                " switch to another project
:ProjectSearchFiles         " find a file by name
:ProjectFindInFiles         " find text in the project

Mapping the commands you use most is worth it, for example:

nnoremap <leader>p :ProjectList<CR>
nnoremap <leader>f :ProjectSearchFiles<CR>
noremap  <leader>g :ProjectFindInFiles<CR>

For the full reference: :help vim-project (run :helptags ALL first if your plugin manager does not).

The config of the demos, and how to run them

The demos use this config, with npm in place of their scripts. project_root opens each project at its README.md rather than its folder:

let g:vim_project_config = {
      \'project_base': ['~/code'],
      \'project_root': './README.md',
      \'tasks': [
      \  {'name': 'test', 'cmd': 'npm test'},
      \  {'name': 'dev', 'cmd': 'npm run dev'},
      \  {'name': 'lint', 'cmd': 'npm run lint'},
      \],
      \}

" joshdick/onedark.vim
colorscheme onedark
" The file on the left, the project and its branch on the right
let &statusline = "%f%m%=%{empty(g:vim_project) ? '' : g:vim_project.name.'  '.get(g:vim_project, 'branch', '')} "

To try the projects of the demos, without changing your own config:

git clone https://github.com/leafOfTree/vim-project && cd vim-project
docs/demo/setup.sh    # webshop and five other projects in /tmp/vim-project-demo
vimrc=$PWD/docs/demo/vimrc && cd /tmp/vim-project-demo/projects && nvim -u "$vimrc"

Then :ProjectList and pick webshop.

Features

In every list, type to filter. Ctrl-j / Ctrl-k (or the arrow keys) move, Enter opens and Esc closes. See keys in lists.

Projects

Watch the demo

Switch between projects

:ProjectList filters projects by name, note or path. Opening a project quits the current one (saving its session if enabled) and opens the new one's root.

  • :Project <path> ["note"] adds a folder. A relative path is looked up in project_base.
  • :ProjectNew <path> creates a new project from a template task, e.g. git clone.
  • :ProjectRename, :ProjectRemove, :ProjectQuit manage them.
  • project_views define views of the list, switched with Tab and Shift-Tab.

Search files

Watch the demo

Search files by name

:ProjectSearchFiles matches fuzzily, so typing a few letters of each part is enough:

Input Finds
pcard ProductCard.vue file names
store/c src/store/cart.js with /, the path too
comp/pcard src/components/ProductCard.vue both parts can be shortened
store/ the store directory ending with /, directories only

Recently opened files come first. Ctrl-s, Ctrl-v and Ctrl-t open in a split, vertical split or tab.

The file list is cached and refreshed in the background, so new files show up without waiting.

Find and replace in files

Watch the demo

Find and replace in files

:ProjectFindInFiles searches as you type; with a visual selection it starts with the selected text. The input is literal and case insensitive: start it with \C to match case, or \E for a regular expression.

To replace, press Ctrl-r, type the replacement after =>, check the preview, and confirm with Ctrl-y. Ctrl-d leaves out a line or file.

Run tasks

Watch the demo

Run tasks

:ProjectRun lists the tasks of the project and shows their output as they run. Enter runs or reruns a task, Ctrl-q stops it and Ctrl-o opens its terminal.

let g:vim_project_local_config = {
      \'tasks': [
      \  {'name': 'test', 'cmd': 'npm test'},
      \  {'name': 'dev', 'cmd': 'npm run dev'},
      \  {'name': 'script', 'cmd': 'npm run', 'args': 'script name'},
      \  {'name': 'terminal', 'cmd': ''},
      \],
      \}

args asks for input appended to the command, cd runs it in a sub folder, show and hide filter its output by patterns, and an empty cmd opens a terminal.

Git changes

Watch the demo

Local changes, changelists and shelves

:ProjectGitStatus shows local changes with a diff of the file under the cursor. Group them in changelists, then commit one at a time: only its files are committed.

Key Action
Enter open a file, expand or collapse a changelist
a / r / d new, rename, delete a changelist
m move files or a changelist to another changelist
c commit the changelist or selected files (write amend alone on a line to amend)
R roll back the selected files
s shelve: save the changes as a patch and revert them
S unshelve a shelf or one of its files
u / p / P pull, push, pull then push, in the background

Git log, file history, branches and tags

Watch the demo

Git log, file history and merging a branch

  • :ProjectGitLog searches commits by message, author or hash, with the changed files of the selected one beside it.
  • :ProjectGitFileHistory shows the commits of the current file, or of the selected lines, with their diffs.
  • :ProjectGitBranch switches, creates and merges branches.
  • :ProjectGitTag checks out and creates tags.
List Key Action
log Enter show the changed files, and the diff of the one under the cursor
log, file history Ctrl-o check out
file history Enter show the diff
branches Enter switch to it, or create one from New Branch
branches Ctrl-o merge into the current branch (asks first)
tags Enter check out, or create one from New Tag

Sessions and project config

  • use_session saves and restores the windows and buffers of each project; with check_branch_when_use_session, one per git branch.
  • use_viminfo keeps command and search history, marks and recent files per project.
  • :ProjectConfig opens the project's init.vim, sourced when it opens and reloaded when saved. Set g:vim_project_local_config there to override options for that project.
  • file_mappings jump to files you edit often, e.g. 'r for README.md. See :help vim-project-file-mappings.

Configuration

Set g:vim_project_config before the plugin loads (with lazy.nvim, in init). Only the keys you set change:

let g:vim_project_config = {
      \'project_base': ['~/code'],
      \'use_session': 1,
      \'exclude': ['.git', 'node_modules', 'dist'],
      \}
Option Default Description
config_home '~/.vim/vim-project-config' where projects, sessions and per-project config are kept
project_base ['~'] where relative paths of :Project are looked up
project_root './' folder or file to open with a project
include / exclude [] / ['.git', 'node_modules', ...] what search and find in files look at
use_session / use_viminfo 0 per project session and history
auto_detect 'no' 'ask' or 'always' to add folders with .git you open
tasks [] tasks for :ProjectRun
find_replace_separator ' => ' separator of search and replace text
file_mappings_prefix "'" key before file_mappings keys

Every option, key mapping and the per-project config are in :help vim-project-config.

Status line

g:vim_project holds the current project (name, path, branch, ...) and $vim_project its path, e.g.

set statusline=%f%=%{empty(g:vim_project)?'':g:vim_project.name}

Keys in lists

Key Action
Enter open
Esc close
Ctrl-j / Ctrl-k, ↓ / ↑ next / previous item
Ctrl-h / Ctrl-l first / last item
Ctrl-n / Ctrl-p scroll down / up
Backspace / Ctrl-w / Ctrl-u delete a character / word / everything
Ctrl-b paste
Ctrl-o go to the list window (in lists without their own Ctrl-o)

All of them can be changed with list_mappings. Typed characters are highlighted with the VimProjectMatch group, e.g. highlight VimProjectMatch guifg=#f9e2af gui=bold.

Commands

Command Description
:Project <path> ["note"] add a folder as a project and open it
:ProjectNew <path> create a new project
:ProjectList list and open projects
:ProjectOpen <name> open a project by name
:ProjectQuit quit the current project
:ProjectRename <name> <new_name> rename a project and its folder
:ProjectRemove <name> remove a project from the list
:ProjectIgnore <path> never offer a folder in auto_detect
:ProjectSearchFiles search files by name
:ProjectSearchFilesReset forget the cached file list
:ProjectFindInFiles [text] find and replace in files
:ProjectRun run tasks
:ProjectGitStatus, :ProjectGitCommit local changes and changelists
:ProjectGitLog search the git log
:ProjectGitFileHistory history of the file or selected lines
:ProjectGitBranch / :ProjectGitTag branches / tags
:ProjectRoot open the project root
:ProjectConfig / :ProjectAllConfig edit the project's init.vim / the project list
:ProjectConfigReload write all buffers and reopen the project
:ProjectInfo / :ProjectAllInfo show the project and config in use
:ProjectOutput [filter] print the projects

Troubleshooting

  • A command is much slower than in a terminal. Try setting shell to sh (or cmd.exe on Windows).
  • 'a no longer jumps to mark a. file_mappings use ' by default; set file_mappings_prefix to e.g. '<leader>'.
  • Git push or pull fails asking for credentials. They run in the background without a terminal; use a credential helper or ssh-agent.
  • Something else. :ProjectInfo, :ProjectAllInfo and let g:vim_project_config.debug = 1 show what is going on.

Development

bash test/run.sh                                # tests with every editor found (or: nvim, vim)
VIM_PROJECT_TEST_CASES=perf bash test/run.sh    # time budgets of the code run on every key
vint --error plugin autoload
docs/demo/render.sh                             # re-record the animations above with VHS

See CONTRIBUTING.md for how the tests, time budgets and demos work.

Credits

Thanks to timsofteng for the great idea. It all started with that.

About

A vim plugin to manage projects and sessions

Topics

Resources

Contributing

Stars

27 stars

Watchers

1 watching

Forks

Contributors

Languages