harpoon dynamic commands for projects

This commit is contained in:
Rishabh Dwivedi 2021-08-30 02:28:47 +05:30
parent d8610fdc12
commit 323027715f
3 changed files with 345 additions and 0 deletions

146
lua/harpoon/cmd-ui.lua Normal file
View File

@ -0,0 +1,146 @@
local harpoon = require("harpoon")
local popup = require("popup")
local log = require("harpoon.dev").log
local term = require("harpoon.term")
local M = {}
Harpoon_cmd_win_id = nil
Harpoon_cmd_bufh = nil
local function close_menu(force_save)
force_save = force_save or false
local global_config = harpoon.get_global_settings()
if global_config.save_on_toggle or force_save then
require("harpoon.cmd-ui").on_menu_save()
end
vim.api.nvim_win_close(Harpoon_cmd_win_id, true)
Harpoon_cmd_win_id = nil
Harpoon_cmd_bufh = nil
end
local function create_window()
log.trace("_create_window()")
local config = harpoon.get_menu_config()
local width = config.width or 60
local height = config.height or 10
local borderchars = config.borderchars
or { "", "", "", "", "", "", "", "" }
local bufnr = vim.api.nvim_create_buf(false, false)
local Harpoon_cmd_win_id, win = popup.create(bufnr, {
title = "Harpoon Commands",
highlight = "HarpoonWindow",
line = math.floor(((vim.o.lines - height) / 2) - 1),
col = math.floor((vim.o.columns - width) / 2),
minwidth = width,
minheight = height,
borderchars = borderchars,
})
vim.api.nvim_win_set_option(
win.border.win_id,
"winhl",
"Normal:HarpoonBorder"
)
return {
bufnr = bufnr,
win_id = Harpoon_cmd_win_id,
}
end
local function is_white_space(str)
local white_space_chars = {
[" "] = true,
["\t"] = true,
["\r"] = true,
["\f"] = true,
["\v"] = true
}
for i = 1, string.len(str) do
if white_space_chars[string.sub(str, i, i)] == nil then
return false
end
end
return true
end
local function get_menu_items()
log.trace("_get_menu_items()")
local lines = vim.api.nvim_buf_get_lines(Harpoon_cmd_bufh, 0, -1, true)
local indices = {}
for _, line in pairs(lines) do
if not is_white_space(line) then
table.insert(indices, line)
end
end
return indices
end
M.toggle_quick_menu = function()
log.trace("toggle_quick_menu()")
if Harpoon_cmd_win_id ~= nil and vim.api.nvim_win_is_valid(Harpoon_cmd_win_id) then
close_menu()
return
end
local win_info = create_window()
local contents = {}
local global_config = harpoon.get_global_settings()
Harpoon_cmd_win_id = win_info.win_id
Harpoon_cmd_bufh = win_info.bufnr
for idx, cmd in pairs(harpoon.get_term_config().cmds) do
contents[idx] = cmd
end
vim.api.nvim_win_set_option(Harpoon_cmd_win_id, "number", true)
vim.api.nvim_buf_set_name(Harpoon_cmd_bufh, "harpoon-cmd-menu")
vim.api.nvim_buf_set_lines(Harpoon_cmd_bufh, 0, #contents, false, contents)
vim.api.nvim_buf_set_option(Harpoon_cmd_bufh, "filetype", "harpoon")
vim.api.nvim_buf_set_option(Harpoon_cmd_bufh, "buftype", "acwrite")
vim.api.nvim_buf_set_option(Harpoon_cmd_bufh, "bufhidden", "delete")
-- TODO: maybe vim.fn.input() can be used to implement some select_menu_item
-- vim.api.nvim_buf_set_keymap(
-- Harpoon_cmd_bufh,
-- "n",
-- "<CR>",
-- ":lua require('harpoon.cmd-ui').select_menu_item()<CR>",
-- {}
-- )
vim.cmd(
string.format(
"autocmd BufWriteCmd <buffer=%s> :lua require('harpoon.cmd-ui').on_menu_save()",
Harpoon_cmd_bufh
)
)
if global_config.save_on_change then
vim.cmd(
string.format(
"autocmd TextChanged,TextChangedI <buffer=%s> :lua require('harpoon.cmd-ui').on_menu_save()",
Harpoon_cmd_bufh
)
)
end
vim.cmd(
string.format(
"autocmd BufModifiedSet <buffer=%s> set nomodified",
Harpoon_cmd_bufh
)
)
end
M.on_menu_save = function()
log.trace("on_menu_save()")
term.set_cmd_list(get_menu_items())
end
return M

View File

@ -51,6 +51,17 @@ local function find_terminal(args)
return term_handle
end
local function get_first_empty_slot()
log.trace("_get_first_empty_slot()")
for idx, cmd in pairs(harpoon.get_term_config().cmds) do
if cmd == "" then
return idx
end
end
return M.get_length() + 1;
end
M.gotoTerminal = function(idx)
log.trace("gotoTerminal(): Terminal:", idx)
local term_handle = find_terminal(idx)
@ -80,4 +91,51 @@ M.clear_all = function()
terminals = {}
end
M.get_length = function()
log.trace("_get_length()")
return table.maxn(harpoon.get_term_config().cmds)
end
M.valid_index = function(idx)
if idx == nil or idx > M.get_length() or idx <= 0 then
return false
end
return true
end
M.emit_changed = function()
log.trace("_emit_changed()")
if harpoon.get_global_settings().save_on_change then
harpoon.save()
end
end
M.add_cmd = function(cmd)
log.trace("add_cmd()")
local found_idx = get_first_empty_slot();
harpoon.get_term_config().cmds[found_idx] = cmd
M.emit_changed()
end
M.rm_cmd = function(idx)
log.trace("rm_cmd()")
if not M.valid_index(idx) then
log.debug("rm_cmd(): no cmd exists for index", idx)
return
end
table.remove(harpoon.get_term_config().cmds, idx)
M.emit_changed()
end
M.set_cmd_list = function(new_list)
log.trace("set_cmd_list(): New list:", new_list)
for k in pairs(harpoon.get_term_config().cmds) do
harpoon.get_term_config().cmds[k] = nil
end
for k, v in pairs(new_list) do
harpoon.get_term_config().cmds[k] = v
end
M.emit_changed()
end
return M

View File

@ -0,0 +1,141 @@
local harpoon = require("harpoon")
local term = require("harpoon.term")
local function assert_table_equals(tbl1, tbl2)
if #tbl1 ~= #tbl2 then
assert(false, ""..#tbl1.." != "..#tbl2)
end
for i = 1, #tbl1 do
if tbl1[i] ~= tbl2[i] then
assert.equals(tbl1[i], tbl2[i])
end
end
end
describe("basic functionalities", function()
local emitted
local cmds
before_each(function()
emitted = false
cmds = {}
harpoon.get_term_config = function()
return {
cmds = cmds
}
end
term.emit_changed = function()
emitted = true
end
end)
it("add_cmd for empty", function()
term.add_cmd("cmake ..")
local expected_result = {
"cmake .."
}
assert_table_equals(harpoon.get_term_config().cmds, expected_result)
assert.equals(emitted, true)
end)
it("add_cmd for non_empty", function()
term.add_cmd("cmake ..")
term.add_cmd("make")
term.add_cmd("ninja")
local expected_result = {
"cmake ..",
"make",
"ninja",
}
assert_table_equals(harpoon.get_term_config().cmds, expected_result)
assert.equals(emitted, true)
end)
it("rm_cmd: removing a valid element", function()
term.add_cmd("cmake ..")
term.add_cmd("make")
term.add_cmd("ninja")
term.rm_cmd(2)
local expected_result = {
"cmake ..",
"ninja",
}
assert_table_equals(harpoon.get_term_config().cmds, expected_result)
assert.equals(emitted, true)
end)
it("rm_cmd: remove first element", function()
term.add_cmd("cmake ..")
term.add_cmd("make")
term.add_cmd("ninja")
term.rm_cmd(1)
local expected_result = {
"make",
"ninja",
}
assert_table_equals(harpoon.get_term_config().cmds, expected_result)
assert.equals(emitted, true)
end)
it("rm_cmd: remove last element", function()
term.add_cmd("cmake ..")
term.add_cmd("make")
term.add_cmd("ninja")
term.rm_cmd(3)
local expected_result = {
"cmake ..",
"make",
}
assert_table_equals(harpoon.get_term_config().cmds, expected_result)
assert.equals(emitted, true)
end)
it("rm_cmd: trying to remove invalid element", function()
term.add_cmd("cmake ..")
term.add_cmd("make")
term.add_cmd("ninja")
term.rm_cmd(5)
local expected_result = {
"cmake ..",
"make",
"ninja",
}
assert_table_equals(harpoon.get_term_config().cmds, expected_result)
assert.equals(emitted, true)
term.rm_cmd(0)
assert_table_equals(harpoon.get_term_config().cmds, expected_result)
term.rm_cmd(-1)
assert_table_equals(harpoon.get_term_config().cmds, expected_result)
end)
it("get_length", function()
term.add_cmd("cmake ..")
term.add_cmd("make")
term.add_cmd("ninja")
assert.equals(term.get_length(), 3)
end)
it("valid_index", function()
term.add_cmd("cmake ..")
term.add_cmd("make")
term.add_cmd("ninja")
assert(term.valid_index(1))
assert(term.valid_index(2))
assert(term.valid_index(3))
assert(not term.valid_index(0))
assert(not term.valid_index(-1))
assert(not term.valid_index(4))
end)
it("set_cmd_list", function()
term.add_cmd("cmake ..")
term.add_cmd("make")
term.add_cmd("ninja")
term.set_cmd_list({"make uninstall", "make install",})
local expected_result = {
"make uninstall",
"make install",
}
assert_table_equals(expected_result, harpoon.get_term_config().cmds)
end)
end)