feat(sign): update signs and markadd ,markrm,markclean etc functions

This commit is contained in:
tomasky 2022-07-03 12:04:08 +08:00
parent 1ce6fdb40d
commit e71384a5ce
8 changed files with 204 additions and 68 deletions

View File

@ -8,7 +8,7 @@ A Bookmarks Plugin With Global File Store For Neovim Written In Lua.
## Installation
[packer.nvim] :
With [packer.nvim]:
```lua
use {
@ -43,6 +43,7 @@ require('bookmarks').setup {
- [gitsigns.nvim] most of lua functions come from this plugin
- [vim-bookmarks](https://github.com/MattesGroeger/vim-bookmarks) inspired by this vim plugin
- [possession.nvim](https://github.com/jedrzejboczar/possession.nvim) some util functions
[gitsigns.nvim]: https://github.com/lewis6991/gitsigns.nvim
[packer.nvim]: https://github.com/wbthomason/packer.nvim

View File

@ -5,11 +5,55 @@ local uv = vim.loop
local current_buf = api.nvim_get_current_buf
local config = require "bookmarks.config"
local signs = require "bookmarks.signs"
local nvim = require "bookmarks.nvim"
local hl = require "bookmarks.highlight"
local actions = require "bookmarks.actions"
local M = {}
local function wrap_func(fn, ...)
local args = { ... }
local nargs = select("#", ...)
return function()
fn(unpack(args, 1, nargs))
end
end
local function autocmd(event, opts)
local opts0 = {}
if type(opts) == "function" then
opts0.callback = wrap_func(opts)
else
opts0 = opts
end
opts0.group = "bookmarks"
nvim.autocmd(event, opts0)
end
M.attach = void(function(bufnr, aucmd)
scheduler()
actions.loadBookmarks()
if config.on_attach then
config.on_attach(bufnr)
end
end)
M.detach_all = void(function(bufnr)
scheduler()
signs.detach(bufnr)
actions.saveBookmarks()
end)
M.setup = void(function(cfg)
config.build(cfg)
signs.setup()
nvim.augroup "bookmarks"
autocmd("VimLeavePre", M.detach_all)
autocmd("ColorScheme", hl.setup_highlights)
autocmd("BufRead", wrap_func(M.attach, nil, "BufRead"))
end)
return M
return setmetatable(M, {
__index = function(_, f)
return actions[f]
end,
})

View File

@ -1,11 +1,34 @@
local config = require("bookmarks.config").config
local void = require("bookmarks.async").void
local uv = vim.loop
local signs = require "bookmarks.signs"
local utils = require "bookmarks.util"
local api = vim.api
local current_buf = api.nvim_get_current_buf
local M = {}
local function updateBookmarks(bufnr, line, mark, ann)
local filepath = uv.fs_realpath(api.nvim_buf_get_name(bufnr))
local marks = config.cache[filepath]
local isIns = false
if line == -1 then
marks = nil
-- check buffer auto_save to file
return
end
for i = 1, #marks do
if marks[i].l == line and mark == "" then
table.remove(marks, i)
elseif marks[i].l == line then
isIns = true
end
end
if isIns == false then
table.insert(marks, ann and { l = line, m = mark, a = ann } or { l = line, m = mark })
-- check buffer auto_save to file
-- M.saveBookmarks()
end
end
M.toggle_signs = function(value)
if value ~= nil then
config.signcolumn = value
@ -16,44 +39,78 @@ M.toggle_signs = function(value)
return config.signcolumn
end
M.bookmark_add = function(lnum)
local signlines = {}
M.bookmark_add = function()
local lnum = api.nvim_win_get_cursor(0)[1]
local bufnr = current_buf()
signlines[0] = {
local signlines = { {
type = "add",
count = 1,
lnum = lnum,
}
} }
signs:add(bufnr, signlines)
updateBookmarks(bufnr, lnum, "line ")
end
M.bookmark_rm = function()
local lnum = api.nvim_win_get_cursor(0)[1]
local bufnr = current_buf()
signs:remove(bufnr, lnum)
updateBookmarks(bufnr, lnum, "")
end
M.bookmark_clean = function()
local bufnr = current_buf()
updateBookmarks(bufnr, -1, "")
end
M.bookmark_ann = function(old_annotation)
local new_annotation = ""
local input_msg = old_annotation ~= "" and "Edit" or "Enter"
vim.ui.input(input_msg, old_annotation, function(answer)
new_annotation = answer
end)
local lnum = api.nvim_win_get_cursor(0)[1]
local bufnr = current_buf()
local signlines = { {
type = "ann",
lnum = lnum,
} }
signs:add(bufnr, signlines)
updateBookmarks(bufnr, lnum, "line ", new_annotation)
end
M.bookmark_rm = function() end
M.bookmark_clean = function() end
M.bookmark_ann = function() end
M.bookmark_prev = function() end
M.bookmark_next = function() end
M.refresh = function() end
M.bookmark_showall = function() end
local function saveBookmarks(filepath)
local content = {
index = 1,
data = {
[filepath] = {
{
i = 1, -- index
l = 1, -- line num
c = "", -- mark content
a = "", -- mark annotation
},
},
},
}
local data = vim.json.encode(content)
M.refresh = function()
local cache = config.cache
local bufnr = current_buf()
local file = uv.fs_realpath(api.nvim_buf_get_name(bufnr))
local marks = cache.data[file]
local signlines = {}
if marks then
for mark in marks do
local ma = {
type = mark.a and "ann" or "add",
lnum = mark.l,
}
signs:remove(bufnr, ma.lnum)
table.insert(signlines, ma)
end
signs:add(bufnr, signlines)
end
end
function M.loadBookmarks()
utils.read_file(config.save_file, function(data)
local contents = vim.json.decode(data)
config.cache = contents
end)
end
function M.saveBookmarks()
local data = vim.json.encode(config.cache)
utils.write_file(config.save_file, data)
end
local function loadBookmarks()
utils.read_file(config.save_file, function(data)
local marks = vim.json.decode(data)
end)
end
return M

View File

@ -1,7 +1,5 @@
local co = coroutine
local Async = {}
local async_thread = {
threads = {},
}

View File

@ -2,9 +2,34 @@ local M = {}
M.config = {}
M.schema = {
cache = {
type = "table",
deep_extend = true,
default = {},
},
save_file = {
type = "string",
default = vim.fn.expand "~/.bookmarks",
default = vim.fn.expand "$HOME/.bookmarks",
},
sign_priority = {
type = "number",
default = 6,
},
signcolumn = {
type = "boolean",
default = true,
},
numhl = {
type = "boolean",
default = false,
},
linehl = {
type = "boolean",
default = false,
},
on_attach = {
type = "function",
default = nil,
},
signs = {
type = "table",

View File

@ -48,3 +48,5 @@ end
function M.highlight(group, opts)
vim.api.nvim_set_hl(0, group, opts)
end
return M

View File

@ -13,41 +13,29 @@ function M.new(cfg, name)
return self
end
function M:on_lines(buf, _, last_orig, last_new)
if last_orig > last_new then
self:remove(buf, last_new + 1, last_orig)
end
function M:on_lines(buf, last_new)
self:remove(buf, last_new + 1)
end
function M:remove(bufnr, start_lnum, end_lnum)
function M:remove(bufnr, start_lnum)
if start_lnum then
api.nvim_buf_clear_namespace(bufnr, self.ns, start_lnum - 1, end_lnum or start_lnum)
api.nvim_buf_clear_namespace(bufnr, self.ns, start_lnum - 1, start_lnum)
else
api.nvim_buf_clear_namespace(bufnr, self.ns, 0, -1)
end
end
function M:add(bufnr, signs)
if not config.signcolumn and not config.numhl and not config.linehl then
return
end
local cfg = self.config
for _, s in ipairs(signs) do
if not self:contains(bufnr, s.lnum) then
local cs = cfg[s.type]
local text = cs.text
if config.signcolumn and cs.show_count and s.count then
local count = s.count
local cc = config.count_chars
local count_char = cc[count] or cc["+"] or ""
text = cs.text .. count_char
end
api.nvim_buf_set_extmark(bufnr, self.ns, s.lnum - 1, -1, {
id = s.lnum,
sign_text = config.signcolumn and text or "",
sign_text = text,
priority = config.sign_priority,
sign_hl_group = cs.hl,
number_hl_group = config.numhl and cs.numhl or nil,
@ -57,8 +45,8 @@ function M:add(bufnr, signs)
end
end
function M:contains(bufnr, start, last)
local marks = api.nvim_buf_get_extmarks(bufnr, self.ns, { start - 1, 0 }, { last or start, 0 }, { limit = 1 })
function M:contains(bufnr, start)
local marks = api.nvim_buf_get_extmarks(bufnr, self.ns, { start - 1, 0 }, { start, 0 }, { limit = 1 })
return #marks > 0
end

View File

@ -90,21 +90,23 @@ function M.emptytable()
})
end
function M.readfile(filename)
local data, ok
local fh, err, code = io.popen(filename, "r")
if fh then
data, err, code = fh:read "*a"
if data then
ok, err, code = fh:close()
else
fh:close()
end
function M.clear_prompt()
vim.api.nvim_command "normal! :"
end
function M.prompt_yes_no(prompt, callback, prompt_no_cr)
prompt = string.format("%s [y/N] ", prompt)
if prompt_no_cr then -- use getchar so no <cr> is required
print(prompt)
local ans = vim.fn.nr2char(vim.fn.getchar())
local is_confirmed = ans:lower():match "^y"
M.clear_prompt()
callback(is_confirmed)
else -- use vim.ui.input
vim.ui.input({ prompt = prompt }, function(answer)
callback(vim.tbl_contains({ "y", "yes" }, answer and answer:lower()))
end)
end
if not ok then
return err .. code
end
return data:gsub("\r", "")
end
M.write_file = function(path, content)
@ -150,4 +152,23 @@ function M.dump(o)
end
end
function M.warn(...)
vim.notify(string.format(...), vim.log.levels.WARN)
end
function M.error(...)
vim.notify(string.format(...), vim.log.levels.ERROR)
end
function M.lazy(fn)
local cached
return function(...)
if cached == nil then
cached = fn(...)
assert(cached ~= nil, "lazy: fn returned nil")
end
return cached
end
end
return M