This is not fully baked, though used by several people. If you experience any issues, see some improvement you think would be amazing, or just have some feedback for harpoon (or me), make a ticket!
-- Image provided by Liberty_DevCap
The goal of Harpoon is to get you where you want with the fewest keystrokes.
You work on code. The code base is medium, large, tiny, whatever. You find yourself frequenting a small set of files (maybe it depends on task) and you are tired of using a fuzzy finder, :bnext/prev, alternate file doesn't quite cut it, etc etc.
You want to execute some project specific commands or have any number of persistent terminals that can be easily navigated to.
The ability to specify, or on the fly, mark and create persisting key strokes to go to the files you want.
Unlimited terminals and navigation.
Simply install via your favorite plugin manager.
Plug 'nvim-lua/plenary.nvim' " don't forget to add this one if you don't have it yet!
Plug 'nvim-lua/popup.nvim'
Plug 'ThePrimeagen/harpoon'
There are two modes of harpoon. File navigation and terminal navigation. Setup of harpoon configuration is at the bottom since its for more advanced use cases.
Marking a file is similar to vim global marks, but differ in a few key ways.
- They auto update their position
- They are unique per project.
- They can be hand edited vs replaced (swapping is easier)
To mark a file simply call the following lua function
:lua require("harpoon.mark").add_file()
This will mark the file and add it to the end of the mark list.
To navigate to any of the marked files simply call the navigation function with which index.
:lua require("harpoon.ui").nav_file(3) -- This will navigate to file 3
There is a quick menu that will allow for you to edit your marks. You can hand edit the name, its position within the list, or remove it from the list. To bring up the quick list execute the following lua command.
:lua require("harpoon.ui").toggle_quick_menu()
You can simply edit this list as if it were a document in vim. :wq
to save
the new edits or :q
to ignore the edits. There is to save upon call to
toggle if you prefer that way.
I want to use the terminal since I can gF and gF to any errors arising from execution that are within the terminal that are not appropriate for something like dispatch. (not just running tests but perhaps a server that runs for X amount of time before crashing).
I want the terminal to be persistent and I can return to one of many terminals with some finger wizardry and reparse any of the execution information that was not necessarily error related.
I would like to have commands that can be tied to terminals and sent them without much thinking. Some sort of middle ground between vim-test and just typing them into a terminal (configuring netflix's television project isn't quite building and there are tons of ways to configure).
To navigate to a terminal simply provide an index and it will go. If there is no terminal in that index or the terminal has been closed by some means, harpoon will create a new terminal at that location.
lua require("harpoon.term").gotoTerminal(1)
You can provide as high of a number as you would like. There is no terminal count limitation though I personally find anything beyond two oft confusing.
Sometimes you wish to send commands to terminals that have been preconfigured for a project. To make this work properly you must predefine a command or hard code it as part of the send process.
" This will send to terminal 1 either the predefined command 1 in the terminal
" config or "ls -la"
lua require("harpoon.term").sendCommand(1, 1)
lua require("harpoon.term").sendCommand(1, "ls -la")
Setup should be called once.
Yes... A todo in a readme. Deal with it.
You can configure harpoon via lua in your rc. Here is a simple example that will add a specific command to a project.
Here is the set of global settings and their default values.
require("harpoon").setup({
global_settings = {
save_on_toggle = false,
save_on_change = true,
enter_on_sendcmd = false,
},
... your other configs ...
})
save_on_toggle
will set the marks upon callingtoggle
on the ui, instead of require:w
.save_on_change
will save the harpoon file upon every change. If you don't enable this option (on by default) harpoon will not save any changes to your file. It is very unreliable to save your harpoon on exit (at least that is what I have found).enter_on_sendcmd
will set harpoon to run the command immediately as it's passed to the terminal when callingsendCommand
.
These are project specific commands that you wish to execute on the regular.
require("harpoon").setup({
projects = {
-- Yes $HOME works
["$HOME/personal/vim-with-me/server"] = {
term = {
cmds = {
"./env && npx ts-node src/index.ts"
}
}
},
Harpoon writes logs to a harpoon.log
file that resides in Neovim's cache
path. (:echo stdpath("cache")
to find where that is for you.)
By default, logging is enabled for warnings and above. This can be changed by
setting vim.g.harpoon_log_level
variable to one of the following log levels:
trace
, debug
, info
, warn
, error
, or fatal
. Note that this would
have to be done before harpoon's setup
call. Alternatively, it can be
more convenient to launch Neovim with an environment variable, e.g. > HARPOON_LOG=trace nvim
. In case both, vim.g
and an environment variable are
used, the log level set by the environment variable overrules. Supplying an
invalid log level defaults back to warnings.