diff --git a/README.md b/README.md index 63c4cbf..31be114 100644 --- a/README.md +++ b/README.md @@ -132,12 +132,20 @@ Here is the set of global settings and their default values. require("harpoon").setup({ global_settings = { - save_on_toggle = false + save_on_toggle = false, + save_on_change = true, }, ... your other configs ... }) ``` +* `save_on_toggle` will set the marks upon calling `toggle` 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). + #### Preconfigured Terminal Commands These are project specific commands that you wish to execute on the regular. diff --git a/lua/harpoon/init.lua b/lua/harpoon/init.lua index 8bcea1d..8c3d92b 100644 --- a/lua/harpoon/init.lua +++ b/lua/harpoon/init.lua @@ -130,7 +130,10 @@ M.setup = function(config) local complete_config = merge_tables( - {projects = {} , global_settings = {["save_on_toggle"] = false}}, + {projects = {} , global_settings = { + ["save_on_toggle"] = false, + ["save_on_change"] = true, + }}, expand_dir(c_config), expand_dir(u_config), expand_dir(config)) diff --git a/lua/harpoon/mark.lua b/lua/harpoon/mark.lua index 77e080c..82ac15f 100644 --- a/lua/harpoon/mark.lua +++ b/lua/harpoon/mark.lua @@ -1,7 +1,26 @@ local harpoon = require('harpoon') local utils = require('harpoon.utils') +-- I think that I may have to organize this better. I am not the biggest fan +-- of procedural all the things local M = {} +local callbacks = {} + +-- I am trying to avoid over engineering the whole thing. We will likely only +-- need one event emitted +local function emit_changed() + if not callbacks["changed"] then + return + end + + if harpoon.get_global_settings().save_on_change then + harpoon.save() + end + + for _, cb in pairs(callbacks) do + cb() + end +end local function filter_empty_string(list) local next = {} @@ -14,6 +33,17 @@ local function filter_empty_string(list) return next end +local function get_first_empty_slot() + for idx = 1, M.get_length() do + local filename = M.get_marked_file_name(idx) + if filename == "" then + return idx + end + end + + return M.get_length() + 1 +end + local function get_buf_name(id) if id == nil then return utils.normalize_path(vim.fn.bufname(vim.fn.bufnr())) @@ -112,22 +142,17 @@ M.add_file = function(file_name_or_buf_id) validate_buf_name(buf_name) - for idx = 1, M.get_length() do - local filename = M.get_marked_file_name(idx) - if filename == "" then - harpoon.get_mark_config().marks[idx] = create_mark(buf_name) - - M.remove_empty_tail() - return - end - end - - table.insert(harpoon.get_mark_config().marks, create_mark(buf_name)) - M.remove_empty_tail() + local found_idx = get_first_empty_slot() + harpoon.get_mark_config().marks[found_idx] = create_mark(buf_name) + M.remove_empty_tail(false) + emit_changed(); end -M.remove_empty_tail = function() +-- dont_emit_on_changed should only be used internally +M.remove_empty_tail = function(_emit_on_changed) + _emit_on_changed = _emit_on_changed == nil or _emit_on_changed local config = harpoon.get_mark_config() + local found = false for i = M.get_length(), 1, -1 do local filename = M.get_marked_file_name(i) @@ -137,8 +162,13 @@ M.remove_empty_tail = function() if filename == "" then table.remove(config.marks, i) + found = found or _emit_on_changed end end + + if found then + emit_changed() + end end M.store_offset = function() @@ -157,6 +187,8 @@ M.store_offset = function() -- TODO: Developer logs? print("M.store_offset#pcall failed:", res) end + + emit_changed() end M.rm_file = function(file_name_or_buf_id) @@ -168,11 +200,13 @@ M.rm_file = function(file_name_or_buf_id) end harpoon.get_mark_config().marks[idx] = create_mark("") - M.remove_empty_tail() + M.remove_empty_tail(false) + emit_changed() end M.clear_all = function() harpoon.get_mark_config().marks = {} + emit_changed() end --- ENTERPRISE PROGRAMMING @@ -199,7 +233,7 @@ M.set_current_at = function(idx) -- Remove it if it already exists if M.valid_index(current_idx) then - config.marks[current_idx] = "" + config.marks[current_idx] = create_mark("") end config.marks[idx] = create_mark(buf_name) @@ -209,6 +243,8 @@ M.set_current_at = function(idx) config.marks[i] = create_mark("") end end + + emit_changed() end M.to_quickfix_list = function() @@ -243,6 +279,7 @@ M.set_mark_list = function(new_list) end config.marks = new_list + emit_changed() end M.toggle_file = function(file_name_or_buf_id) @@ -263,5 +300,14 @@ M.get_current_index = function() return M.get_index_of(vim.fn.bufname(vim.fn.bufnr())) end +M.on = function(event, cb) + if not callbacks[event] then + callbacks[event] = {} + end + + table.insert(callbacks[event], cb) +end + return M + diff --git a/plugin/harpoon.vim b/plugin/harpoon.vim deleted file mode 100644 index 1763ec2..0000000 --- a/plugin/harpoon.vim +++ /dev/null @@ -1,73 +0,0 @@ -" TODO: Make this vim compatible. - -" How to do this but much better? -let g:win_ctrl_buf_list = [0, 0, 0, 0] - -fun! Harpoon_GotoTerminal(ctrlId) - if (a:ctrlId > 9) || (a:ctrlId < 0) - echo "CtrlID must be between 0 - 9" - return - end - - let contents = g:win_ctrl_buf_list[a:ctrlId] - if type(l:contents) != v:t_list - " Create the terminal - exe has("nvim") ? "terminal" : "terminal ++curwin" - call Harpoon_SetTerminal(a:ctrlId) - end - let contents = g:win_ctrl_buf_list[a:ctrlId] - if type(l:contents) != v:t_list - echo "Unable to create a terminal or find the terminal's information." - end - - let bufh = l:contents[1] - if !bufexists(bufh) - " Create the terminal - exe has("nvim") ? "terminal" : "terminal ++curwin" - call Harpoon_SetTerminal(a:ctrlId) - endif - - let contents = g:win_ctrl_buf_list[a:ctrlId] - let bufh = l:contents[1] - exe "b" . l:bufh -endfun - -fun! Harpoon_SetTerminal(ctrlId) - if &buftype != "terminal" - echo "You must be in a terminal to execute this command" - return - end - if (a:ctrlId > 9) || (a:ctrlId < 0) - echo "CtrlID must be between 0 - 3" - return - end - - let g:win_ctrl_buf_list[a:ctrlId] = [has_key(b:, "terminal_job_id") ? b:terminal_job_id : 0, bufnr()] -endfun - -fun! Harpoon_SendTerminalCommand(ctrlId, command) - if (a:ctrlId > 9) || (a:ctrlId < 0) - echo "CtrlID must be between 0 - 9" - return - end - let contents = g:win_ctrl_buf_list[a:ctrlId] - if type(l:contents) != v:t_list - echo "No terminal created, sorry for not creating this in the background..." - call Harpoon_GotoTerminal(a:ctrlId) - end - let contents = g:win_ctrl_buf_list[a:ctrlId] - if type(l:contents) != v:t_list - echo "Unable to send command to terminal" - end - - if has("nvim") - let job_id = l:contents[0] - call chansend(l:job_id, a:command) - else - let bufh = l:contents[1] - call term_sendkeys(l:bufh, a:command) - endif -endfun - -highlight default HarpoonWindow ctermbg=none -highlight default HarpoonBorder ctermbg=none ctermfg=white diff --git a/plugin/mark.vim b/plugin/mark.vim index f301ad7..901e445 100644 --- a/plugin/mark.vim +++ b/plugin/mark.vim @@ -1,10 +1,4 @@ -fun! HarpoonLeave() - lua require('harpoon.mark').store_offset() - lua require('harpoon').save() -endfun - augroup THE_PRIMEAGEN_HARPOON autocmd! - autocmd VimLeavePre * :call HarpoonLeave() autocmd BufLeave * :lua require('harpoon.mark').store_offset() augroup END