mirror of
https://github.com/gosticks/bookmarks.nvim.git
synced 2025-10-16 11:55:38 +00:00
feat!: ✨ init proj , add some lua functions the proj need
This commit is contained in:
parent
d05b554d54
commit
810abbfa32
48
README.md
48
README.md
@ -1,2 +1,48 @@
|
||||
# bookmarks.nvim
|
||||
A Bookmarks Plugin With Global File Store For Neovim Written In Lua.
|
||||
|
||||
A Bookmarks Plugin With Global File Store For Neovim Written In Lua.
|
||||
|
||||
## Requirements
|
||||
|
||||
- Neovim >= 0.7.0
|
||||
|
||||
## Installation
|
||||
|
||||
[packer.nvim] :
|
||||
|
||||
```lua
|
||||
use {
|
||||
'tomasky/bookmarks.nvim',
|
||||
-- tag = 'release' -- To use the latest release
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
For basic setup with all default configs using [packer.nvim]
|
||||
|
||||
```lua
|
||||
use {
|
||||
'tomasky/bookmarks.nvim',
|
||||
config = function()
|
||||
require('bookmarks').setup()
|
||||
end
|
||||
}
|
||||
```
|
||||
|
||||
Here is an example with most of the default settings:
|
||||
|
||||
```lua
|
||||
require('bookmarks').setup {
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
## Credits
|
||||
|
||||
- [gitsigns.nvim] most lua functions come from this plugin
|
||||
- [vim-bookmarks](https://github.com/MattesGroeger/vim-bookmarks) inspired by this vim plugin
|
||||
|
||||
[gitsigns.nvim]: https://github.com/lewis6991/gitsigns.nvim
|
||||
[packer.nvim]: https://github.com/wbthomason/packer.nvim
|
||||
|
||||
12
lua/bookmarks.lua
Normal file
12
lua/bookmarks.lua
Normal file
@ -0,0 +1,12 @@
|
||||
local void = require('gitsigns.async').void
|
||||
local scheduler = require('gitsigns.async').scheduler
|
||||
local api = vim.api
|
||||
local uv = vim.loop
|
||||
local current_buf = api.nvim_get_current_buf
|
||||
|
||||
local M = {}
|
||||
M.setup = void(function(cfg)
|
||||
|
||||
end)
|
||||
|
||||
return M
|
||||
19
lua/bookmarks/actions.lua
Normal file
19
lua/bookmarks/actions.lua
Normal file
@ -0,0 +1,19 @@
|
||||
local config = require("bookmarks.config").config
|
||||
local void = require("gitsigns.async").void
|
||||
local M = {}
|
||||
|
||||
M.toggle_signs = function(value)
|
||||
if value ~= nil then
|
||||
config.signcolumn = value
|
||||
else
|
||||
config.signcolumn = not config.signcolumn
|
||||
end
|
||||
M.refresh()
|
||||
return config.signcolumn
|
||||
end
|
||||
|
||||
M.bookmark_add = function() end
|
||||
M.bookmark_rm = function() end
|
||||
M.bookmark_clean = function() end
|
||||
M.bookmark_ann = function() end
|
||||
M.refresh = function() end
|
||||
87
lua/bookmarks/async.lua
Normal file
87
lua/bookmarks/async.lua
Normal file
@ -0,0 +1,87 @@
|
||||
local co = coroutine
|
||||
|
||||
local Async = {}
|
||||
|
||||
local async_thread = {
|
||||
threads = {},
|
||||
}
|
||||
|
||||
local function threadtostring(x)
|
||||
if jit then
|
||||
return string.format("%p", x)
|
||||
else
|
||||
return tostring(x):match "thread: (.*)"
|
||||
end
|
||||
end
|
||||
|
||||
function async_thread.running()
|
||||
local thread = co.running()
|
||||
local id = threadtostring(thread)
|
||||
return async_thread.threads[id]
|
||||
end
|
||||
|
||||
function async_thread.create(fn)
|
||||
local thread = co.create(fn)
|
||||
local id = threadtostring(thread)
|
||||
async_thread.threads[id] = true
|
||||
return thread
|
||||
end
|
||||
|
||||
function async_thread.finished(x)
|
||||
if co.status(x) == "dead" then
|
||||
local id = threadtostring(x)
|
||||
async_thread.threads[id] = nil
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function execute(async_fn, ...)
|
||||
local thread = async_thread.create(async_fn)
|
||||
|
||||
local function step(...)
|
||||
local ret = { co.resume(thread, ...) }
|
||||
local stat, err_or_fn, nargs = unpack(ret)
|
||||
|
||||
if not stat then
|
||||
error(string.format("The coroutine failed with this message: %s\n%s", err_or_fn, debug.traceback(thread)))
|
||||
end
|
||||
|
||||
if async_thread.finished(thread) then
|
||||
return
|
||||
end
|
||||
|
||||
assert(type(err_or_fn) == "function", "type error :: expected func")
|
||||
|
||||
local ret_fn = err_or_fn
|
||||
local args = { select(4, unpack(ret)) }
|
||||
args[nargs] = step
|
||||
ret_fn(unpack(args, 1, nargs))
|
||||
end
|
||||
|
||||
step(...)
|
||||
end
|
||||
|
||||
local M = {}
|
||||
|
||||
function M.wrap(func, argc)
|
||||
return function(...)
|
||||
if not async_thread.running() then
|
||||
return func(...)
|
||||
end
|
||||
return co.yield(func, argc, ...)
|
||||
end
|
||||
end
|
||||
|
||||
function M.void(func)
|
||||
return function(...)
|
||||
if async_thread.running() then
|
||||
return func(...)
|
||||
end
|
||||
execute(func, ...)
|
||||
end
|
||||
end
|
||||
|
||||
M.scheduler = M.wrap(vim.schedule, 1)
|
||||
|
||||
return M
|
||||
47
lua/bookmarks/config.lua
Normal file
47
lua/bookmarks/config.lua
Normal file
@ -0,0 +1,47 @@
|
||||
local M = {}
|
||||
M.config = {}
|
||||
|
||||
M.schema = {}
|
||||
|
||||
local function validate_config(config)
|
||||
for k, v in pairs(config) do
|
||||
local kschema = M.schema[k]
|
||||
if kschema == nil then
|
||||
warn("gitsigns: Ignoring invalid configuration field '%s'", k)
|
||||
elseif kschema.type then
|
||||
if type(kschema.type) == "string" then
|
||||
vim.validate {
|
||||
[k] = { v, kschema.type },
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function resolve_default(v)
|
||||
if type(v.default) == "function" and v.type ~= "function" then
|
||||
return (v.default)()
|
||||
else
|
||||
return v.default
|
||||
end
|
||||
end
|
||||
|
||||
function M.build(user_config)
|
||||
user_config = user_config or {}
|
||||
validate_config(user_config)
|
||||
local config = M.config
|
||||
for k, v in pairs(M.schema) do
|
||||
if user_config[k] ~= nil then
|
||||
if v.deep_extend then
|
||||
local d = resolve_default(v)
|
||||
config[k] = vim.tbl_deep_extend("force", d, user_config[k])
|
||||
else
|
||||
config[k] = user_config[k]
|
||||
end
|
||||
else
|
||||
config[k] = resolve_default(v)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return M
|
||||
32
lua/bookmarks/highlight.lua
Normal file
32
lua/bookmarks/highlight.lua
Normal file
@ -0,0 +1,32 @@
|
||||
local api = vim.api
|
||||
local nvim = require "bookmarks.nvim"
|
||||
|
||||
local M = {}
|
||||
|
||||
local hls = {
|
||||
{ BookMarksAdd = { "MarkAdd" } },
|
||||
}
|
||||
|
||||
local function is_hl_set(hl_name)
|
||||
local exists, hl = pcall(api.nvim_get_hl_by_name, hl_name, true)
|
||||
local color = hl.foreground or hl.background or hl.reverse
|
||||
return exists and color ~= nil
|
||||
end
|
||||
|
||||
M.setup_highlights = function()
|
||||
for _, hlg in ipairs(hls) do
|
||||
for hl, candidates in pairs(hlg) do
|
||||
if is_hl_set(hl) then
|
||||
else
|
||||
for _, d in ipairs(candidates) do
|
||||
if is_hl_set(d) then
|
||||
nvim.highlight(hl, { default = true, link = d })
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return M
|
||||
50
lua/bookmarks/nvim.lua
Normal file
50
lua/bookmarks/nvim.lua
Normal file
@ -0,0 +1,50 @@
|
||||
local M = {}
|
||||
|
||||
function M.autocmd(event, opts)
|
||||
vim.api.nvim_create_autocmd(event, opts)
|
||||
end
|
||||
|
||||
function M.augroup(name, opts)
|
||||
vim.api.nvim_create_augroup(name, opts or {})
|
||||
end
|
||||
|
||||
local callbacks = {}
|
||||
|
||||
function M._exec(id, ...)
|
||||
callbacks[id](...)
|
||||
end
|
||||
|
||||
local F = M
|
||||
|
||||
function M.set(fn, is_expr, args)
|
||||
local id
|
||||
|
||||
if jit then
|
||||
id = "cb" .. string.format("%p", fn)
|
||||
else
|
||||
id = "cb" .. tostring(fn):match "function: (.*)"
|
||||
end
|
||||
|
||||
if is_expr then
|
||||
F[id] = fn
|
||||
return string.format("v:lua.require'bookmarks.nvim.callbacks'." .. id)
|
||||
else
|
||||
if args then
|
||||
callbacks[id] = fn
|
||||
return string.format('lua require("bookmarks.nvim.callbacks")._exec("%s", %s)', id, args)
|
||||
else
|
||||
callbacks[id] = function()
|
||||
fn()
|
||||
end
|
||||
return string.format('lua require("bookmarks.nvim.callbacks")._exec("%s")', id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function M.command(name, fn, opts)
|
||||
vim.api.nvim_create_user_command(name, fn, opts)
|
||||
end
|
||||
|
||||
function M.highlight(group, opts)
|
||||
vim.api.nvim_set_hl(0, group, opts)
|
||||
end
|
||||
71
lua/bookmarks/signs.lua
Normal file
71
lua/bookmarks/signs.lua
Normal file
@ -0,0 +1,71 @@
|
||||
local api = vim.api
|
||||
local config = require("bookmarks.config").config
|
||||
|
||||
local M = {}
|
||||
|
||||
local group_base = "bookmarks_extmark_signs_"
|
||||
|
||||
function M.new(cfg, name)
|
||||
local self = setmetatable({}, { __index = M })
|
||||
self.config = cfg
|
||||
self.group = group_base .. (name or "")
|
||||
self.ns = api.nvim_create_namespace(self.group)
|
||||
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
|
||||
end
|
||||
|
||||
function M:remove(bufnr, start_lnum, end_lnum)
|
||||
if start_lnum then
|
||||
api.nvim_buf_clear_namespace(bufnr, self.ns, start_lnum - 1, end_lnum or 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 "",
|
||||
priority = config.sign_priority,
|
||||
sign_hl_group = cs.hl,
|
||||
number_hl_group = config.numhl and cs.numhl or nil,
|
||||
line_hl_group = config.linehl and cs.linehl or nil,
|
||||
})
|
||||
end
|
||||
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 })
|
||||
return #marks > 0
|
||||
end
|
||||
|
||||
function M:reset()
|
||||
for _, buf in ipairs(api.nvim_list_bufs()) do
|
||||
self:remove(buf)
|
||||
end
|
||||
end
|
||||
|
||||
return M
|
||||
141
lua/bookmarks/util.lua
Normal file
141
lua/bookmarks/util.lua
Normal file
@ -0,0 +1,141 @@
|
||||
local M = {}
|
||||
|
||||
function M.path_exists(path)
|
||||
return vim.loop.fs_stat(path) and true or false
|
||||
end
|
||||
|
||||
local jit_os
|
||||
|
||||
if jit then
|
||||
jit_os = jit.os:lower()
|
||||
end
|
||||
|
||||
local is_unix = false
|
||||
if jit_os then
|
||||
is_unix = jit_os == "linux" or jit_os == "osx" or jit_os == "bsd"
|
||||
else
|
||||
local binfmt = package.cpath:match "%p[\\|/]?%p(%a+)"
|
||||
is_unix = binfmt ~= "dll"
|
||||
end
|
||||
|
||||
function M.dirname(file)
|
||||
return file:match(string.format("^(.+)%s[^%s]+", M.path_sep, M.path_sep))
|
||||
end
|
||||
|
||||
function M.file_lines(file)
|
||||
local text = {}
|
||||
for line in io.lines(file) do
|
||||
text[#text + 1] = line
|
||||
end
|
||||
return text
|
||||
end
|
||||
|
||||
M.path_sep = package.config:sub(1, 1)
|
||||
|
||||
function M.buf_lines(bufnr)
|
||||
local buftext = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false)
|
||||
if vim.bo[bufnr].fileformat == "dos" then
|
||||
for i = 1, #buftext do
|
||||
buftext[i] = buftext[i] .. "\r"
|
||||
end
|
||||
end
|
||||
return buftext
|
||||
end
|
||||
|
||||
function M.set_lines(bufnr, start_row, end_row, lines)
|
||||
if vim.bo[bufnr].fileformat == "dos" then
|
||||
for i = 1, #lines do
|
||||
lines[i] = lines[i]:gsub("\r$", "")
|
||||
end
|
||||
end
|
||||
vim.api.nvim_buf_set_lines(bufnr, start_row, end_row, false, lines)
|
||||
end
|
||||
|
||||
function M.tmpname()
|
||||
if is_unix then
|
||||
return os.tmpname()
|
||||
end
|
||||
return vim.fn.tempname()
|
||||
end
|
||||
|
||||
function M.copy_array(x)
|
||||
local r = {}
|
||||
for i, e in ipairs(x) do
|
||||
r[i] = e
|
||||
end
|
||||
return r
|
||||
end
|
||||
|
||||
function M.strip_cr(xs0)
|
||||
for i = 1, #xs0 do
|
||||
if xs0[i]:sub(-1) ~= "\r" then
|
||||
return xs0
|
||||
end
|
||||
end
|
||||
|
||||
local xs = vim.deepcopy(xs0)
|
||||
for i = 1, #xs do
|
||||
xs[i] = xs[i]:sub(1, -2)
|
||||
end
|
||||
return xs
|
||||
end
|
||||
|
||||
function M.emptytable()
|
||||
return setmetatable({}, {
|
||||
__index = function(t, k)
|
||||
t[k] = {}
|
||||
return t[k]
|
||||
end,
|
||||
})
|
||||
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
|
||||
end
|
||||
if not ok then
|
||||
return err .. code
|
||||
end
|
||||
return data:gsub("\r", "")
|
||||
end
|
||||
|
||||
function M.writefile(filename, data)
|
||||
local ok
|
||||
local fh, err, code = io.popen(filename, "w")
|
||||
if fh then
|
||||
ok, err, code = fh:write(data)
|
||||
if ok then
|
||||
ok, err, code = fh:close()
|
||||
else
|
||||
fh:close()
|
||||
end
|
||||
end
|
||||
if not ok then
|
||||
return err .. code
|
||||
end
|
||||
return data
|
||||
end
|
||||
|
||||
function M.dump(o)
|
||||
if type(o) == "table" then
|
||||
local s = "{ "
|
||||
for k, v in pairs(o) do
|
||||
if type(k) ~= "number" then
|
||||
k = '"' .. k .. '"'
|
||||
end
|
||||
s = s .. "[" .. k .. "] = " .. M.dump(v) .. ","
|
||||
end
|
||||
return s .. "} "
|
||||
else
|
||||
return tostring(o)
|
||||
end
|
||||
end
|
||||
|
||||
return M
|
||||
Loading…
Reference in New Issue
Block a user