diff --git a/TODO.md b/TODO.md new file mode 100644 index 0000000..c2125df --- /dev/null +++ b/TODO.md @@ -0,0 +1,10 @@ +### Manage A Mark 1.0 +* Logo +* linexcol offset in saved file + +### Harpoon (upon requests) +* Add hooks for vim so that someone can make it for me +* ackshual tests. +* interactive menu +* cycle + diff --git a/autoload/harpoon.vim b/autoload/harpoon.vim new file mode 100644 index 0000000..82ae350 --- /dev/null +++ b/autoload/harpoon.vim @@ -0,0 +1,7 @@ +fun harpoon#nav(id) + call luaeval("require('harpoon.ui').nav(_A[1])", [a:id]) +endfun + +fun harpoon#cmd(cmd) + " TODO: I am sure I'll use this +endfun diff --git a/lua/harpoon/manage-a-mark.lua b/lua/harpoon/manage-a-mark.lua new file mode 100644 index 0000000..9244f6d --- /dev/null +++ b/lua/harpoon/manage-a-mark.lua @@ -0,0 +1,189 @@ +local Path = require('plenary.path') + +local M = {} + +harpoon_win_id = nil +harpoon_bufh = nil + +local cwd = cwd or vim.loop.cwd() +local data_path = vim.fn.stdpath("data") + +cwd = cwd:gsub("/", "_") + +local file_name = string.format("%s/%s.cache", data_path, cwd) + +function get_id_or_current_buffer(id) + if id == nil then + return vim.fn.bufname(vim.fn.bufnr()) + end + + return id +end + +function hydrate_from_cache() + ok, res = pcall(function() + local results = Path:new(file_name):read() + if results == nil then + return {}, {} + end + return vim.fn.json_decode(results), {} + end) + + if ok then + return res, {} + end + + return {}, {} +end + +M.save = function() + Path:new(file_name):write(vim.fn.json_encode(marked_files), 'w') +end + +if not marked_files then + marked_files, marked_offsets = hydrate_from_cache() +end + +function get_index_of(item) + if item == nil then + error("You have provided a nil value to Harpoon, please provide a string rep of the file or the file idx.") + return + end + if type(item) == 'string' then + for idx = 1, #marked_files do + if marked_files[idx] == item then + return idx + end + end + + return nil + end + + if vim.g.manage_a_mark_zero_index then + item = item + 1 + end + + if item <= #marked_files and item >= 1 then + return item + end + + return nil +end + +function valid_index(idx) + return idx ~= nil and marked_files[idx] ~= nil +end + +M.get_index_of = get_index_of +M.valid_index = valid_index + +function swap(a_idx, b_idx) + local tmp = marked_files[a_idx] + marked_files[a_idx] = marked_files[b_idx] + marked_files[b_idx] = tmp +end + +M.add_file = function() + local buf_name = get_id_or_current_buffer() + if valid_index(get_index_of(buf_name)) then + -- we don't alter file layout. + return + end + + for idx = 1, #marked_files do + if marked_files[idx] == nil then + marked_files[idx] = buf_name + return + end + end + + table.insert(marked_files, buf_name) +end + +M.store_offset = function() + local idx = get_id_or_current_buffer() + if not valid_index(idx) then + return + end + + local line = vim.api.nvim_eval("line('.')"); +end + +M.swap = function(a, b) + a_idx = get_index_of(a) + b_idx = get_index_of(get_id_or_current_buffer(b)) + + if not valid_index(a_idx) or not valid_index(b_idx) then + return + end + + swap(a_idx, b_idx) +end + +M.rm_file = function() + id = get_id_or_current_buffer() + idx = get_index_of(id) + + if not valid_index(idx) then + return + end + + marked_files[idx] = nil +end + +M.clear_all = function() + marked_files = {} +end + +M.promote = function(id) + id = get_id_or_current_buffer(id) + idx = get_index_of(id) + + if not valid_index(idx) or idx == 1 then + return + end + + swap(idx - 1, idx) +end + +M.promote_to_front = function(id) + id = get_id_or_current_buffer(id) + + idx = get_index_of(id) + if not valid_index(idx) or idx == 1 then + return + end + + swap(1, idx) +end + +M.remove_nils = function() + local next = {} + for idx = 1, #marked_files do + if marked_files[idx] ~= nil then + table.insert(next, marked_files[idx]) + end + end + + marked_files = next +end + +M.shorten_list = function(count) + local next = {} + local up_to = math.min(count, #marked_files) + for idx = 1, up_to do + table.insert(next, marked_files[idx]) + end + marked_files = next +end + +M.get_marked_file = function(idx) + return marked_files[idx] +end + +M.get_length = function() + return #marked_files +end + +return M + diff --git a/lua/harpoon/test/manage-a-mark.lua b/lua/harpoon/test/manage-a-mark.lua new file mode 100644 index 0000000..2c79756 --- /dev/null +++ b/lua/harpoon/test/manage-a-mark.lua @@ -0,0 +1,5 @@ +-- TODO: Harpooned +local Marker = require('harpoon.manage-a-mark') +local eq = assert.are.same + + diff --git a/lua/harpoon/ui.lua b/lua/harpoon/ui.lua new file mode 100644 index 0000000..2986082 --- /dev/null +++ b/lua/harpoon/ui.lua @@ -0,0 +1,68 @@ +local Path = require('plenary.path') +local float = require('plenary.window.float') +local Marked = require('harpoon.manage-a-mark') + +local factorw = 0.42069 +local factorh = 0.69420 + +local M = {} + +win_id = nil +bufh = nil + +function create_window() + local win_info = float.percentage_range_window( + factorw, + factorh, + { + winblend = 0 + }) + + return win_info +end + +M.toggle_quick_menu = function() + if win_id ~= nil and vim.api.nvim_win_is_valid(win_id) then + vim.api.nvim_win_close(win_id, true) + + win_id = nil + bufh = nil + + return + end + + local win_info = create_window() + local contents = {} + + win_id = win_info.win_id + bufh = win_info.bufh + + for idx = 1, Marked.get_length() do + contents[idx] = string.format("%d %s", idx, Marked.get_marked_file(idx)) + end + + vim.api.nvim_buf_set_lines(bufh, 0, #contents, false, contents) +end + +M.nav_file = function(id) + idx = Marked.get_index_of(id) + if not Marked.valid_index(idx) then + return + end + + local buf_id = vim.fn.bufnr(Marked.get_marked_file(idx)) + + if vim.api.nvim_win_is_valid(buf_id) then + vim.api.nvim_win_close(win_id) + end + + if buf_id ~= nil and buf_id ~= -1 then + vim.api.nvim_set_current_buf(buf_id) + else + vim.cmd(string.format("e %s", Marked.get_marked_file(idx))) + end +end + +return M + + diff --git a/plugin/harpoon.vim b/plugin/harpoon.vim index 5ebaa23..1ab83e3 100644 --- a/plugin/harpoon.vim +++ b/plugin/harpoon.vim @@ -3,7 +3,7 @@ " How to do this but much better? let g:win_ctrl_buf_list = [0, 0, 0, 0] -fun! GotoBuffer(ctrlId) +fun! Harpoon_GotoTerminal(ctrlId) if (a:ctrlId > 9) || (a:ctrlId < 0) echo "CtrlID must be between 0 - 9" return @@ -13,7 +13,7 @@ fun! GotoBuffer(ctrlId) if type(l:contents) != v:t_list " Create the terminal exe has("nvim") ? "terminal" : "terminal ++curwin" - call SetBuffer(a:ctrlId) + call Harpoon_SetTerminal(a:ctrlId) end let contents = g:win_ctrl_buf_list[a:ctrlId] if type(l:contents) != v:t_list @@ -24,7 +24,7 @@ fun! GotoBuffer(ctrlId) if !bufexists(bufh) " Create the terminal exe has("nvim") ? "terminal" : "terminal ++curwin" - call SetBuffer(a:ctrlId) + call Harpoon_SetTerminal(a:ctrlId) endif let contents = g:win_ctrl_buf_list[a:ctrlId] @@ -32,7 +32,7 @@ fun! GotoBuffer(ctrlId) exe "b" . l:bufh endfun -fun! SetBuffer(ctrlId) +fun! Harpoon_SetTerminal(ctrlId) if &buftype != "terminal" echo "You must be in a terminal to execute this command" return @@ -45,7 +45,7 @@ fun! SetBuffer(ctrlId) let g:win_ctrl_buf_list[a:ctrlId] = [has_key(b:, "terminal_job_id") ? b:terminal_job_id : 0, bufnr()] endfun -fun! SendTerminalCommand(ctrlId, command) +fun! Harpoon_SendTerminalCommand(ctrlId, command) if (a:ctrlId > 9) || (a:ctrlId < 0) echo "CtrlID must be between 0 - 9" return diff --git a/plugin/manage-a-mark.vim b/plugin/manage-a-mark.vim new file mode 100644 index 0000000..796f1fc --- /dev/null +++ b/plugin/manage-a-mark.vim @@ -0,0 +1,7 @@ +com! -nargs=1 Harpoon call harpoon#cmd() + +augroup THE_PRIMEAGEN_HARPOON + autocmd! + autocmd VimLeave * :lua require('harpoon.manage-a-mark').save() + autocmd BufLeave * :lua require('harpoon.manage-a-mark').store_offset() +augroup END