From 80984ebec5eb3557b1c849b362bdf26c430227cd Mon Sep 17 00:00:00 2001 From: phanium Date: Thu, 1 Aug 2024 18:01:11 +0800 Subject: [PATCH] release!: bug fixes --- lua/fzf-lua-overlay/config.lua | 6 +- lua/fzf-lua-overlay/providers/find_dots.lua | 2 +- lua/fzf-lua-overlay/providers/gitignore.lua | 41 ++++------ lua/fzf-lua-overlay/providers/license.lua | 60 +++++++------- lua/fzf-lua-overlay/util.lua | 89 ++++++++++++++++----- script/reset-cache.lua | 3 +- 6 files changed, 122 insertions(+), 79 deletions(-) diff --git a/lua/fzf-lua-overlay/config.lua b/lua/fzf-lua-overlay/config.lua index 747843b..27f62d9 100644 --- a/lua/fzf-lua-overlay/config.lua +++ b/lua/fzf-lua-overlay/config.lua @@ -8,6 +8,10 @@ M.opts = { cache_dir = vim.fs.joinpath(vim.g.state_path or vim.fn.stdpath 'state', 'fzf-lua-overlay'), } -M.setup = function(opts) M.opts = vim.tbl_deep_extend('force', M.opts, opts or {}) end +M.setup = function(opts) + M.opts = vim.tbl_deep_extend('force', M.opts, opts or {}) + + if not vim.uv.fs_stat(M.opts.cache_dir) then vim.fn.mkdir(M.opts.cache_dir) end +end return M diff --git a/lua/fzf-lua-overlay/providers/find_dots.lua b/lua/fzf-lua-overlay/providers/find_dots.lua index 33bbefe..70f6e5c 100644 --- a/lua/fzf-lua-overlay/providers/find_dots.lua +++ b/lua/fzf-lua-overlay/providers/find_dots.lua @@ -8,7 +8,7 @@ M.name = 'files' -- 'live_grep_native' M.opts = { prompt = 'find_dots> ', - formatter = 'path.filename_first', + -- formatter = 'path.filename_first', cwd = cfg.dot_dir, cmd = ([[rg --color=never --files --hidden %s --follow --no-messages -g "!.git"]]):format( table.concat({ cfg.dot_dir }, ' ') diff --git a/lua/fzf-lua-overlay/providers/gitignore.lua b/lua/fzf-lua-overlay/providers/gitignore.lua index 084d30e..d4d3206 100644 --- a/lua/fzf-lua-overlay/providers/gitignore.lua +++ b/lua/fzf-lua-overlay/providers/gitignore.lua @@ -1,10 +1,7 @@ ---@type FzfLuaOverlaySpec local M = {} -local base_url = 'https://api.github.com/gitignore/templates' - local cache_dir = require('fzf-lua-overlay.config').opts.cache_dir -local cache_path = vim.fs.joinpath(cache_dir, 'gitignore.json') local u = require('fzf-lua-overlay.util') M.name = 'fzf_exec' @@ -13,37 +10,33 @@ M.opts = { prompt = 'gitignore> ', actions = { ['default'] = function(selected) - local util = require('fzf-lua-overlay.util') - local gitroot = util.gitroot() - if not gitroot then u.warn('not in a git repository') end - local path = vim.fs.joinpath(gitroot, '.gitignore') - vim.print(path) + local root = u.gitroot() + if not root then return u.log('not in a git repo') end + local path = root .. '/.gitignore' if vim.uv.fs_stat(path) then local confirm = vim.fn.confirm('Override?', '&Yes\n&No') if confirm ~= 1 then return end end - local template_url = ('%s/%s'):format(base_url, selected[1]) - local _, tbl = u.gh_curl(template_url) - if not tbl then return u.warn('api limited') end - local str = vim.json.encode(tbl.source) - util.write_file(path, str) + + local filetype = selected[1] + if not filetype then return u.log('no filetype') end + + local ok, err_or_str, tbl = u.gh_cache( + vim.fs.joinpath('gitignore', 'templates', filetype), + vim.fs.joinpath(cache_dir, 'gitignore', filetype .. '.json'), + { tbl = true } + ) + if not ok or not tbl then return u.log(err_or_str) end + u.write_file(path, tbl.source) vim.cmd.e(path) end, }, } M.fzf_exec_arg = function(fzf_cb) - local util = require('fzf-lua-overlay.util') - - local tbl - if not vim.uv.fs_stat(cache_path) then - local str, _ = u.gh_curl(base_url) - if not str then return u.warn('api limited') end - util.write_file(cache_path, str) - tbl = vim.json.decode(str) - end - tbl = tbl or util.read_json(cache_path) - + local ok, errmsg, tbl = + u.gh_cache('gitignore/templates', cache_dir .. '/gitignore.json', { tbl = true }) + if not ok or not tbl then return u.log(errmsg) end coroutine.wrap(function() local co = coroutine.running() for _, item in ipairs(tbl) do diff --git a/lua/fzf-lua-overlay/providers/license.lua b/lua/fzf-lua-overlay/providers/license.lua index f3c2b3e..79b404c 100644 --- a/lua/fzf-lua-overlay/providers/license.lua +++ b/lua/fzf-lua-overlay/providers/license.lua @@ -1,50 +1,50 @@ -local base_url = 'https://api.github.com/licenses' +---@type FzfLuaOverlaySpec +local M = {} local cache_dir = require('fzf-lua-overlay.config').opts.cache_dir -local cache_path = vim.fs.joinpath(cache_dir, 'license.json') - local u = require('fzf-lua-overlay.util') ----@type FzfLuaOverlaySpec -local M = {} - M.name = 'fzf_exec' M.opts = { prompt = 'license> ', actions = { ['default'] = function(selected) - local util = require('fzf-lua-overlay.util') - local gitroot = util.gitroot() - if not gitroot then vim.notify('not in a git repository') end - local path = vim.fs.joinpath(gitroot, 'LICENSE') - vim.print(path) - if vim.uv.fs_stat(path) then - local confirm = vim.fn.confirm('Override?', '&Yes\n&No') - if confirm ~= 1 then return end + local root = u.gitroot() + if not root then return u.log('not in a git repo') end + local paths = { root .. '/LICENSE', root .. '/license' } + local path + for _, p in ipairs(paths) do + if vim.uv.fs_stat(p) then + local confirm = vim.fn.confirm('Override?', '&Yes\n&No') + if confirm ~= 1 then return end + path = p + break + end end - local url = ('%s/%s'):format(base_url, selected[1]) - local _, tbl = u.gh_curl(url) - if not tbl then return u.warn('api limited') end - local str = tbl.body - util.write_file(path, str) + vim.print(path) + + local license = selected[1] + if not license then return u.log('no filetype') end + + local ok, err_or_str, tbl = u.gh_cache( + vim.fs.joinpath('licenses', license), + vim.fs.joinpath(cache_dir, 'gitignore', license .. '.json'), + { tbl = true } + ) + if not ok or not tbl then return u.log(err_or_str) end + + local content = tbl.body + if not content then return u.log('unkown: no body field in json') end + u.write_file(path, content) vim.cmd.e(path) end, }, } M.fzf_exec_arg = function(fzf_cb) - local util = require('fzf-lua-overlay.util') - - local tbl - if not vim.uv.fs_stat(cache_path) then - local str = u.gh_curl(base_url) - if not str then return u.warn('api limited') end - util.write_file(cache_path, str) - tbl = vim.json.decode(str) - end - tbl = tbl or util.read_json(cache_path) - + local ok, err_or_str, tbl = u.gh_cache('licenses', cache_dir .. '/license.json', { tbl = true }) + if not ok or not tbl then return u.log(err_or_str) end coroutine.wrap(function() local co = coroutine.running() for _, item in ipairs(tbl) do diff --git a/lua/fzf-lua-overlay/util.lua b/lua/fzf-lua-overlay/util.lua index 2b1a498..4e0dcb6 100644 --- a/lua/fzf-lua-overlay/util.lua +++ b/lua/fzf-lua-overlay/util.lua @@ -1,4 +1,4 @@ -local u = {} +local M = {} local getregion = function(mode) local sl, sc = vim.fn.line 'v', vim.fn.col 'v' @@ -33,7 +33,7 @@ local getregion = function(mode) end -- get visual selected with no side effect -u.getregion = function(mode) +M.getregion = function(mode) mode = mode or vim.api.nvim_get_mode().mode if not vim.tbl_contains({ 'v', 'V', '\022' }, mode) then return {} end local ok, lines = pcall(vim.fn.getregion, vim.fn.getpos '.', vim.fn.getpos 'v', { type = mode }) @@ -41,20 +41,28 @@ u.getregion = function(mode) return getregion(mode) end -u.chdir = function(path) +M.chdir = function(path) if vim.fn.executable('zoxide') then vim.system { 'zoxide', 'add', path } end vim.api.nvim_set_current_dir(path) end -u.read_file = function(path) - local fd = io.open(path, 'r') +M.read_file = function(path, flag) + local fd = io.open(path, flag or 'r') if not fd then return nil end local content = fd:read('*a') fd:close() return content or '' end -u.write_file = function(path, str, flag) +-- path should normalized +-- optionally create parent directory +M.write_file = function(path, str, flag, opts) + opts = opts or { auto_create_dir = true } + if opts.auto_create_dir then + local dir = vim.fs.dirname(path) + if not vim.uv.fs_stat(dir) then vim.fn.mkdir(dir) end + end + local fd = io.open(path, flag or 'w') if not fd then return false end if str then fd:write(str) end @@ -62,20 +70,20 @@ u.write_file = function(path, str, flag) return true end -u.read_json = function(path, opts) +M.read_json = function(path, opts) opts = opts or {} - local str = u.read_file(path) + local str = M.read_file(path) local ok, tbl = pcall(vim.json.decode, str, opts) return ok and tbl or {} end -u.write_json = function(path, tbl) +M.write_json = function(path, tbl) local ok, str = pcall(vim.json.encode, tbl) if not ok then return false end - return u.write_file(path, str) + return M.write_file(path, str) end -u.gitroot = function(bufname) +M.gitroot = function(bufname) if not bufname then bufname = vim.api.nvim_buf_get_name(0) end local path = vim.fs.dirname(bufname) local root = vim.system { 'git', '-C', path, 'rev-parse', '--show-toplevel' }:wait().stdout @@ -93,7 +101,7 @@ u.gitroot = function(bufname) end ---@type fun(name: string?): table -u.get_lazy_plugins = (function() +M.get_lazy_plugins = (function() local plugins return function(name) if not plugins then @@ -111,17 +119,54 @@ u.get_lazy_plugins = (function() end end)() -u.warn = function(msg, ...) - msg = string.format(msg, ...) - vim.notify('[Fzf-lua-overlay] ' .. msg, vim.log.levels.WARN) +local log_level = vim.log.levels.WARN + +---@return nil +M.log = function(msg, ...) return vim.notify('[fzf] ' .. msg:format(...), log_level) end + +---@deprecated use `M.log` instead +M.warn = M.log + +---@return string +M.curl = function(url) return vim.fn.system { 'curl', '-sL', url } end + +---github restful api +--- ok -> false, msg +--- err -> true, str, tbl +---@param route string +---@return boolean?, string, table? +M.gh = function(route) + local url = ('https://api.github.com/' .. route) + local str = M.curl(url) + local ok, tbl = pcall(vim.json.decode, str) + + if not ok or not tbl then -- + return false, ('parsed json failed on:\n%s'):format(str) + end + if tbl.message and tbl.message:match('API rate limit exceeded') then + return false, ('API error: %s'):format(tbl.message) + end + return true, str, tbl end -u.gh_curl = function(url) - local str = vim.fn.system { 'curl', '-s', url } - local tbl = vim.json.decode(str) - -- gh api limit - if not tbl or (tbl.message and tbl.message:match('API rate limit exceeded')) then return end - return str, tbl +---gh but use local cache first +---(return json only now) +---@param route string +---@param path string +---@param opts table? +---@return boolean?, string?, table? +M.gh_cache = function(route, path, opts) + opts = opts or {} + if not vim.uv.fs_stat(path) then + local ok, err_or_str, tbl = M.gh(route) + if ok then + local file_ok = M.write_file(path, err_or_str) + if not file_ok then return file_ok, 'write failed', tbl end + end + return ok, err_or_str, tbl + else -- perf: `read_file` can be saved... + return true, opts.str and M.read_file(path), opts.tbl and M.read_json(path) + end end -return u +return M diff --git a/script/reset-cache.lua b/script/reset-cache.lua index ba3b997..ffaae4c 100644 --- a/script/reset-cache.lua +++ b/script/reset-cache.lua @@ -1,4 +1,5 @@ #!/bin/nvim -l package.path = package.path .. ';lua/?.lua' local cache_dir = require('fzf-lua-overlay.config').opts.cache_dir -require('fzf-lua-overlay.util').ls(cache_dir, function(path, _, _) vim.uv.fs_unlink(path) end) +-- require('fzf-lua-overlay.util').ls(cache_dir, function(path, _, _) vim.uv.fs_unlink(path) end) +u.fs.ls(cache_dir, function(path, _, _) vim.uv.fs_unlink(path) end)