Skip to main content
The UI API provides functions for displaying and navigating the Harpoon quick menu and switching between marked files.

toggle_quick_menu

Toggle the Harpoon quick menu popup window.
require("harpoon.ui").toggle_quick_menu()

Behavior

  • Opens the quick menu if closed
  • Closes the quick menu if already open
  • Displays all marks in an editable buffer
  • Highlights current file in the list
  • Auto-saves changes based on configuration

Quick Menu Features

Edit Marks

Edit filenames directly in the menu

Reorder

Cut and paste lines to reorder marks

Delete

Delete lines to remove marks

Navigate

Press Enter to jump to a mark

Keybindings

The quick menu includes these default keybindings:
  • <CR> (Enter): Select and navigate to mark
  • q: Close menu
  • <ESC>: Close menu

Example

local ui = require("harpoon.ui")

-- Toggle the menu
ui.toggle_quick_menu()

-- Common keymap setup
vim.keymap.set("n", "<leader>h", function()
    ui.toggle_quick_menu()
end)

Navigate to a marked file by index or filename.
require("harpoon.ui").nav_file(id)
id
number | string
required
Mark index (number) or filename (string)

Behavior

  • Switches to the marked file in the current window
  • Creates buffer if file is not already loaded
  • Restores cursor position to saved row/col
  • Deletes unnamed empty buffers automatically
  • Does nothing if mark doesn’t exist

Example

local ui = require("harpoon.ui")

-- Navigate to mark 1
ui.nav_file(1)

-- Navigate by filename
ui.nav_file("/path/to/file.lua")

-- Common keymap setup for quick navigation
vim.keymap.set("n", "<leader>1", function()
    ui.nav_file(1)
end)
vim.keymap.set("n", "<leader>2", function()
    ui.nav_file(2)
end)
vim.keymap.set("n", "<leader>3", function()
    ui.nav_file(3)
end)
vim.keymap.set("n", "<leader>4", function()
    ui.nav_file(4)
end)

Navigate to the next mark in the list (cycles).
require("harpoon.ui").nav_next()

Behavior

  • Moves to the next mark in sequence
  • Wraps around to first mark when at the end
  • If current file is not marked, navigates to mark 1
  • Cycles through all marks continuously

Example

local ui = require("harpoon.ui")

-- Navigate to next mark
ui.nav_next()

-- Common keymap setup for cycling
vim.keymap.set("n", "<C-n>", function()
    ui.nav_next()
end)

Navigate to the previous mark in the list (cycles).
require("harpoon.ui").nav_prev()

Behavior

  • Moves to the previous mark in sequence
  • Wraps around to last mark when at the beginning
  • If current file is not marked, navigates to the last mark
  • Cycles through all marks continuously

Example

local ui = require("harpoon.ui")

-- Navigate to previous mark
ui.nav_prev()

-- Common keymap setup for cycling
vim.keymap.set("n", "<C-p>", function()
    ui.nav_prev()
end)

select_menu_item

Select the mark at the current cursor line in the quick menu.
require("harpoon.ui").select_menu_item()

Behavior

  • Gets the mark index from current line number
  • Saves any menu changes
  • Closes the quick menu
  • Navigates to the selected mark
This function is automatically called when pressing <CR> in the quick menu.

Example

local ui = require("harpoon.ui")

-- This is typically bound in the quick menu buffer
-- Default binding: <CR>
vim.api.nvim_buf_set_keymap(
    bufnr,
    "n",
    "<CR>",
    "<Cmd>lua require('harpoon.ui').select_menu_item()<CR>",
    {}
)

Complete Navigation Workflow

Here’s a complete example showing typical Harpoon UI usage:
-- File marks
vim.keymap.set("n", "<leader>a", function()
    require("harpoon.mark").add_file()
end, { desc = "Add file to Harpoon" })

vim.keymap.set("n", "<leader>h", function()
    require("harpoon.ui").toggle_quick_menu()
end, { desc = "Toggle Harpoon menu" })

-- Quick navigation
vim.keymap.set("n", "<leader>1", function()
    require("harpoon.ui").nav_file(1)
end, { desc = "Go to mark 1" })

vim.keymap.set("n", "<leader>2", function()
    require("harpoon.ui").nav_file(2)
end, { desc = "Go to mark 2" })

vim.keymap.set("n", "<leader>3", function()
    require("harpoon.ui").nav_file(3)
end, { desc = "Go to mark 3" })

vim.keymap.set("n", "<leader>4", function()
    require("harpoon.ui").nav_file(4)
end, { desc = "Go to mark 4" })

-- Cycle through marks
vim.keymap.set("n", "<C-S-N>", function()
    require("harpoon.ui").nav_next()
end, { desc = "Next Harpoon mark" })

vim.keymap.set("n", "<C-S-P>", function()
    require("harpoon.ui").nav_prev()
end, { desc = "Previous Harpoon mark" })

Advanced Functions

on_menu_save

Manually trigger saving the quick menu state to marks.
require("harpoon.ui").on_menu_save()
This is called automatically when the menu is saved or when save_on_change is enabled.

location_window

Create a floating window (used internally by the quick menu).
local win_info = require("harpoon.ui").location_window(options)
options
table
Window configuration options (relative, width, height, row, col, etc.)
return
table
Returns table with:
  • bufnr: Buffer number
  • win_id: Window ID

notification

Show a notification window in the top-right corner.
local info = require("harpoon.ui").notification(text)
text
string
required
Text to display in the notification
return
table
Returns table with:
  • bufnr: Buffer number of notification window
  • win_id: Window ID of notification window
-- Example: Show notification
local ui = require("harpoon.ui")
local info = ui.notification("Mark added successfully!")

-- Close after 2 seconds
vim.defer_fn(function()
  ui.close_notification(info.bufnr)
end, 2000)

close_notification

Close a notification window.
require("harpoon.ui").close_notification(bufnr)
bufnr
number
required
Buffer number of the notification to close
-- Example: Show and auto-close notification
local ui = require("harpoon.ui")
local notification = ui.notification("Operation complete!")

vim.defer_fn(function()
  ui.close_notification(notification.bufnr)
end, 3000)  -- Close after 3 seconds

Build docs developers (and LLMs) love