From 430c3bdc15567c3a3c2cd3bade29500c7ab0d420 Mon Sep 17 00:00:00 2001 From: azan Date: Tue, 13 Aug 2024 03:38:34 +0300 Subject: [PATCH 01/11] Add CI --- .github/workflows/check-lua.yaml | 33 +++++++++++++++++++ .github/workflows/tests.yaml | 54 ++++++++++++++++++++++++++++++++ .luacheckrc | 33 +++++++++++++++++++ Makefile | 22 +++++++++++++ README.md | 1 + scripts/minimal_init.lua | 35 +++++++++++++++++++++ 6 files changed, 178 insertions(+) create mode 100644 .github/workflows/check-lua.yaml create mode 100644 .github/workflows/tests.yaml create mode 100644 .luacheckrc create mode 100644 Makefile create mode 100644 scripts/minimal_init.lua diff --git a/.github/workflows/check-lua.yaml b/.github/workflows/check-lua.yaml new file mode 100644 index 0000000..16a0789 --- /dev/null +++ b/.github/workflows/check-lua.yaml @@ -0,0 +1,33 @@ +--- +name: Linting and style checking + +on: + - push + +jobs: + luacheck: + name: Luacheck + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v2 + - name: Prepare + run: | + sudo apt-get update + sudo apt-get install -y luarocks + sudo luarocks install luacheck + - name: Lint + run: make lint_luacheck + + stylua: + name: stylua + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v2 + - name: Prepare + run: | + sudo apt-get update + sudo apt install -y nodejs npm + - name: Lint + run: "make lint_stylua" + env: + STYLUA: "npx @johnnymorganz/stylua-bin" diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml new file mode 100644 index 0000000..72ce39a --- /dev/null +++ b/.github/workflows/tests.yaml @@ -0,0 +1,54 @@ +--- +name: Tests + +on: + - push + +jobs: + lua-tests: + name: Lua Tests + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + include: + - os: ubuntu-24.04 + rev: nightly/nvim-linux64.tar.gz + manager: sudo apt-get + packages: -y ripgrep + - os: ubuntu-24.04 + rev: stable/nvim-linux64.tar.gz + manager: sudo apt-get + - os: macos-14 + rev: nightly/nvim-macos-x86_64.tar.gz + manager: brew + packages: ripgrep + - os: macos-14 + rev: stable/nvim-macos-x86_64.tar.gz + manager: brew + packages: ripgrep + steps: + - uses: actions/checkout@v3 + - run: date +%F > todays-date + - name: Restore from todays cache + uses: actions/cache@v3 + with: + path: _neovim + key: ${{ runner.os }}-${{ matrix.rev }}-${{ hashFiles('todays-date') }} + - name: Prepare + run: | + ${{ matrix.manager }} update + ${{ matrix.manager }} install ${{ matrix.packages }} + test -d _neovim || { + mkdir -p _neovim + curl -sL "https://github.com/neovim/neovim/releases/download/${{ matrix.rev }}" | tar xzf - --strip-components=1 -C "${PWD}/_neovim" + } + mkdir -p ~/.local/share/nvim/site/pack/vendor/start + git clone --depth 1 https://github.com/nvim-lua/plenary.nvim ~/.local/share/nvim/site/pack/vendor/start/plenary.nvim + ln -s $(pwd) ~/.local/share/nvim/site/pack/vendor/start + - name: Run tests + run: | + export PATH="${PWD}/_neovim/bin:${PATH}" + export VIM="${PWD}/_neovim/share/nvim/runtime" + nvim --version + make test diff --git a/.luacheckrc b/.luacheckrc new file mode 100644 index 0000000..56d22d0 --- /dev/null +++ b/.luacheckrc @@ -0,0 +1,33 @@ +std = luajit +codes = true + +self = false + +-- Glorious list of warnings: https://luacheck.readthedocs.io/en/stable/warnings.html +ignore = { + "212", -- Unused argument, In the case of callback function, _arg_name is easier to understand than _, so this option is set to off. + "122", -- Indirectly setting a readonly global +} + +globals = { + "_", + "TelescopeGlobalState", + "_TelescopeConfigurationValues", + "_TelescopeConfigurationPickers", + "__TelescopeKeymapStore", +} + +-- Global objects defined by the C code +read_globals = { + "vim", + "assert", + "describe", + "it", + "before_each", + "after_each", + "pending", + "clear", + + "G_P", + "G_R", +} diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..c83bfa8 --- /dev/null +++ b/Makefile @@ -0,0 +1,22 @@ +all: format lint test + +STYLUA ?= stylua + +.PHONY: test +test: + nvim --headless -u scripts/minimal_init.lua -c "PlenaryBustedDirectory tests { minimal_init='./scripts/minimal_init.lua', sequential=true, }" + +.PHONY: lint_stylua +lint_stylua: + ${STYLUA} --color always --check lua + +.PHONY: lint_luacheck +lint_luacheck: + luacheck lua + +.PHONY: lint +lint: lint_luacheck lint_stylua + +.PHONY: format +format: + ${STYLUA} lua diff --git a/README.md b/README.md index 0f2dfc5..6523f7a 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,7 @@ The plugin provides the following functionality: `esqueleto.nvim` requires the following: - Neovim 0.8+ + Install `esqueleto.nvim` with your preferred package manager: diff --git a/scripts/minimal_init.lua b/scripts/minimal_init.lua new file mode 100644 index 0000000..4e5509b --- /dev/null +++ b/scripts/minimal_init.lua @@ -0,0 +1,35 @@ +-- this file create separate XDG path +-- thus Lazy.nvim doesnt takes control over the loading +local M = {} + +function M.root(root) + local f = debug.getinfo(1, "S").source:sub(2) + return vim.fn.fnamemodify(f, ":p:h:h") .. "/" .. (root or "") +end + +---@param plugin string +function M.load(plugin) + local name = plugin:match(".*/(.*)") + local package_root = M.root(".tests/site/pack/deps/start/") + if not (vim.loop or vim.uv).fs_stat(package_root .. name) then + print("Installing " .. plugin) + vim.fn.mkdir(package_root, "p") + vim.fn.system({ + "git", + "clone", + "--depth=1", + "https://github.com/" .. plugin .. ".git", + package_root .. "/" .. name, + }) + end +end + +function M.setup() + vim.cmd([[set runtimepath=$VIMRUNTIME]]) + vim.opt.runtimepath:append(M.root()) + vim.opt.packpath = { M.root(".tests/site") } + + M.load("nvim-lua/plenary.nvim") +end + +M.setup() From cb9acc009b913f96c14c28b4c6cd3dc80259d3a0 Mon Sep 17 00:00:00 2001 From: azan Date: Thu, 15 Aug 2024 23:16:29 +0300 Subject: [PATCH 02/11] fix(type): Introduce type --- lua/esqueleto/autocmd.lua | 2 +- lua/esqueleto/config.lua | 7 ++++--- lua/esqueleto/init.lua | 18 +++++++++++++++++- lua/esqueleto/utils.lua | 21 ++++++++++++++------- lua/esqueleto/wildcards.lua | 6 +++--- 5 files changed, 39 insertions(+), 15 deletions(-) diff --git a/lua/esqueleto/autocmd.lua b/lua/esqueleto/autocmd.lua index 37dd293..bccd705 100644 --- a/lua/esqueleto/autocmd.lua +++ b/lua/esqueleto/autocmd.lua @@ -3,7 +3,7 @@ local utils = require("esqueleto.utils") local M = {} --- Create autocommands for `esqueleto.nvim` ----@param opts table Plugin configuration table +---@param opts Esqueleto.Config Plugin configuration table M.createautocmd = function(opts) -- create autocommands for skeleton insertion local group = vim.api.nvim_create_augroup("esqueleto", { clear = true }) diff --git a/lua/esqueleto/config.lua b/lua/esqueleto/config.lua index b9f4697..1271d01 100644 --- a/lua/esqueleto/config.lua +++ b/lua/esqueleto/config.lua @@ -2,6 +2,7 @@ local utils = require("esqueleto.utils") local M = {} +--@type Esqueleto.Config M.default_config = { autouse = true, directories = { vim.fn.stdpath("config") .. "/skeletons" }, @@ -38,9 +39,9 @@ M.default_config = { } } ---- Update default configuration table by merging with user's configuration table ----@param config table user configuration table ----@return table +---Update default configuration table by merging with user's configuration table +---@param config Esqueleto.Config user configuration table +---@return Esqueleto.Config M.updateconfig = function(config) vim.validate({ config = { config, "table", true } }) config = vim.tbl_deep_extend("force", M.default_config, config or {}) diff --git a/lua/esqueleto/init.lua b/lua/esqueleto/init.lua index df6c2af..39c795e 100644 --- a/lua/esqueleto/init.lua +++ b/lua/esqueleto/init.lua @@ -4,10 +4,26 @@ local autocmd = require('esqueleto.autocmd') local excmd = require('esqueleto.excmd') local config = require('esqueleto.config') +---@alias Wildcard { [string] : string | fun():string } +---@class Wildcards +---@field lookup Wildcard +---@field expand boolean Replace ${} with an instance of a wildcards array? + +---@class Esqueleto.Advanced +---@field ignored string[] | fun(file:string):boolean Array of glob file filters +---@field ignore_os_files boolean To ignore OS files? + +---@class Esqueleto.Config +---@field directories string[] The list of paths in which the search will be performed +---@field patterns string[] See: [vim.api.nvim_create_autocmd](lua://vim.api.nvim_create_autocmd) +---@field autouse boolean Auto-use a template? +---@field wildcards Wildcards +---@field advanced Esqueleto.Advanced + local M = {} --- Setup `esqueleto.nvim` ----@param opts table User configuration table +---@param opts Esqueleto.Config User configuration table M.setup = function(opts) -- update defaults opts = config.updateconfig(opts) diff --git a/lua/esqueleto/utils.lua b/lua/esqueleto/utils.lua index 4d408c3..42ec282 100644 --- a/lua/esqueleto/utils.lua +++ b/lua/esqueleto/utils.lua @@ -31,7 +31,7 @@ end --- Write template contents to current buffer ---@param file string Template file path ----@param opts table Plugin configuration table +---@param opts Esqueleto.Config Plugin configuration table M.writetemplate = function(file, opts) if file == nil then -- Do an early return if no files are specified @@ -69,7 +69,9 @@ M.writetemplate = function(file, opts) end end --- List ignored files under a directory, given a list of glob patterns +--- List ignored files under a directory, given a list of glob patterns +---Neovim version -10 +---@deprecated local listignored = function(dir, ignored_patterns) return vim.tbl_flatten( vim.tbl_map( @@ -78,6 +80,9 @@ local listignored = function(dir, ignored_patterns) ) ) end +---Returns a ignore checker +---@param advanced Esqueleto.Advanced +---@return fun(filepath:string):boolean -- Returns a ignore checker local getignorechecker = function(opts) @@ -104,11 +109,13 @@ end --- Get available templates for current buffer ---@param pattern string Pattern to use to find templates ----@param opts table Plugin configuration table ----@return table templates Available templates for current buffer +---@param opts Esqueleto.Config Plugin configuration table +---@return {[string]:string} templates Available templates for current buffer M.gettemplates = function(pattern, opts) local templates = {} local isignored = getignorechecker(opts) + ---@type {[string]:string} + ---@type string[] local alldirectories = vim.tbl_map( function(f) return vim.fn.fnamemodify(f, ":p") end, @@ -142,8 +149,8 @@ M.gettemplates = function(pattern, opts) end --- Select template to insert on current buffer ----@param templates table Available template table ----@param opts table Plugin configuration table +---@param templates {[string]:string} Available template table +---@param opts Esqueleto.Config Plugin configuration table M.selecttemplate = function(templates, opts) -- Check if templates exist if vim.tbl_isempty(templates) then @@ -175,7 +182,7 @@ M.selecttemplate = function(templates, opts) end --- Insert template on current buffer ----@param opts table Plugin configuration table +---@param opts Esqueleto.Config Plugin configuration table M.inserttemplate = function(opts) -- Get pattern alternatives for current file local filepath = vim.fn.expand("%:p") diff --git a/lua/esqueleto/wildcards.lua b/lua/esqueleto/wildcards.lua index e6d917a..d375992 100644 --- a/lua/esqueleto/wildcards.lua +++ b/lua/esqueleto/wildcards.lua @@ -2,14 +2,14 @@ local M = {} --- Parse template contents in order to expand wildcards ---@param str string String to parse ----@param lookup table Wildcards lookup table ----@return table parsed_str Table containing all lines with wildcards expanded table ----@return table cursor_pos Row-column position tuple of the last cursor wildcard found. +---@param lookup Wildcard Wildcards lookup table M.parse = function(str, lookup) local parsedstr = {} for _, l in ipairs(vim.split(str, "\n", { plain = true })) do for wildcard in l:gmatch("${([^{,^}]+)}") do local expansion = nil +---@return string[] parsed_str Table containing all lines with wildcards expanded table +---@return nil | [integer, integer] cursor_pos Row-column position tuple of the last cursor wildcard found. if vim.tbl_contains(vim.tbl_keys(lookup), wildcard) then expansion = lookup[wildcard] From 1b4e2650cb9ff8efe75ae1dc9864b633bfa25499 Mon Sep 17 00:00:00 2001 From: azan Date: Fri, 16 Aug 2024 00:03:35 +0300 Subject: [PATCH 03/11] fix: type error at wildcard parse Note(util): pattern = "" for type reason --- lua/esqueleto/autocmd.lua | 9 ++------- lua/esqueleto/config.lua | 15 +++++++-------- lua/esqueleto/init.lua | 6 +++--- lua/esqueleto/utils.lua | 30 ++++++++++++++++++++---------- lua/esqueleto/wildcards.lua | 20 ++++++++++++-------- 5 files changed, 44 insertions(+), 36 deletions(-) diff --git a/lua/esqueleto/autocmd.lua b/lua/esqueleto/autocmd.lua index bccd705..efbb966 100644 --- a/lua/esqueleto/autocmd.lua +++ b/lua/esqueleto/autocmd.lua @@ -13,15 +13,10 @@ M.createautocmd = function(opts) desc = "esqueleto.nvim :: Insert template", pattern = opts.patterns, callback = function() - if vim.bo.buftype == "nofile" then - return nil - end - + if vim.bo.buftype == "nofile" then return nil end local filepath = vim.fn.expand("%") local emptyfile = vim.fn.getfsize(filepath) < 4 - if emptyfile then - utils.inserttemplate(opts) - end + if emptyfile then utils.inserttemplate(opts) end end, }) end diff --git a/lua/esqueleto/config.lua b/lua/esqueleto/config.lua index 1271d01..1ecf17e 100644 --- a/lua/esqueleto/config.lua +++ b/lua/esqueleto/config.lua @@ -1,5 +1,4 @@ local utils = require("esqueleto.utils") - local M = {} --@type Esqueleto.Config @@ -36,7 +35,7 @@ M.default_config = { advanced = { ignored = {}, ignore_os_files = true, - } + }, } ---Update default configuration table by merging with user's configuration table @@ -48,13 +47,13 @@ M.updateconfig = function(config) -- Validate setup vim.validate({ - autouse = { config.autouse, 'boolean' }, - directories = { config.directories, 'table' }, - patterns = { config.patterns, 'table' }, + autouse = { config.autouse, "boolean" }, + directories = { config.directories, "table" }, + patterns = { config.patterns, "table" }, wildcards = { config.wildcards, "table" }, - advanced = { config.advanced, 'table' }, - ["advanced.ignored"] = { config.advanced.ignored, { 'table', 'function' } }, - ["advanced.ignore_os_files"] = { config.advanced.ignore_os_files, 'boolean' }, + advanced = { config.advanced, "table" }, + ["advanced.ignored"] = { config.advanced.ignored, { "table", "function" } }, + ["advanced.ignore_os_files"] = { config.advanced.ignore_os_files, "boolean" }, }) return config diff --git a/lua/esqueleto/init.lua b/lua/esqueleto/init.lua index 39c795e..af9749d 100644 --- a/lua/esqueleto/init.lua +++ b/lua/esqueleto/init.lua @@ -1,8 +1,8 @@ _G.esqueleto_inserted = {} -local autocmd = require('esqueleto.autocmd') -local excmd = require('esqueleto.excmd') -local config = require('esqueleto.config') +local autocmd = require("esqueleto.autocmd") +local config = require("esqueleto.config") +local excmd = require("esqueleto.excmd") ---@alias Wildcard { [string] : string | fun():string } ---@class Wildcards diff --git a/lua/esqueleto/utils.lua b/lua/esqueleto/utils.lua index 42ec282..c908c16 100644 --- a/lua/esqueleto/utils.lua +++ b/lua/esqueleto/utils.lua @@ -41,7 +41,7 @@ M.writetemplate = function(file, opts) local handler, message = io.open(file, "r") if handler == nil then -- Print error message and abort if no file handlers are created - vim.notify(message, vim.log.levels.ERROR) + vim.notify(message --[[@as string]], vim.log.levels.ERROR) return end @@ -80,11 +80,20 @@ local listignored = function(dir, ignored_patterns) ) ) end +-- ---List ignored files under a directory, given a list of glob patterns +-- ---@param dir string +-- ---@param ignored_patterns string[] +-- ---@return string[] +-- local listignore = function(dir, ignored_patterns) +-- return vim.iter(ignored_patterns) +-- :map(function(patterns) return vim.fn.globpath(dir, patterns, true, true, true) end) +-- :flatten() +-- :totable() +-- end + ---Returns a ignore checker ----@param advanced Esqueleto.Advanced +---@param opts Esqueleto.Config ---@return fun(filepath:string):boolean - --- Returns a ignore checker local getignorechecker = function(opts) local os_ignore_pats = opts.advanced.ignore_os_files and require("esqueleto.constants").ignored_os_patterns @@ -112,11 +121,10 @@ end ---@param opts Esqueleto.Config Plugin configuration table ---@return {[string]:string} templates Available templates for current buffer M.gettemplates = function(pattern, opts) + ---@type {[string]:string} local templates = {} local isignored = getignorechecker(opts) - ---@type {[string]:string} - ---@type string[] - + ---@type string[] local alldirectories = vim.tbl_map( function(f) return vim.fn.fnamemodify(f, ":p") end, opts.directories @@ -165,16 +173,17 @@ M.selecttemplate = function(templates, opts) local templatenames = vim.tbl_keys(templates) table.sort(templatenames, function(a, b) return a:lower() < b:lower() end) + local uv = vim.loop or vim.uv -- If only one template, write and return early if #templatenames == 1 and opts.autouse then - M.writetemplate(vim.loop.fs_realpath(templates[templatenames[1]]), opts) + M.writetemplate(uv.fs_realpath(templates[templatenames[1]])--[[@as string]], opts) return nil end -- Select template vim.ui.select(templatenames, { prompt = "Select skeleton to use:" }, function(choice) if templates[choice] then - M.writetemplate(vim.loop.fs_realpath(templates[choice]), opts) + M.writetemplate(uv.fs_realpath(templates[choice])--[[@as string]], opts) else vim.notify("[esqueleto] No template selected, leaving buffer empty", vim.log.levels.INFO) end @@ -190,7 +199,7 @@ M.inserttemplate = function(opts) local filetype = vim.bo.filetype -- Identify if pattern matches user configuration - local pattern = nil + local pattern = "" if not _G.esqueleto_inserted[filepath] then -- match either filename or extension. Filename has priority if vim.tbl_contains(opts.patterns, filename) then @@ -201,6 +210,7 @@ M.inserttemplate = function(opts) -- Get templates for selected pattern local templates = M.gettemplates(pattern, opts) + -- Identify if pattern matches user configuration -- Pop-up selection UI M.selecttemplate(templates, opts) diff --git a/lua/esqueleto/wildcards.lua b/lua/esqueleto/wildcards.lua index d375992..52f6623 100644 --- a/lua/esqueleto/wildcards.lua +++ b/lua/esqueleto/wildcards.lua @@ -3,16 +3,22 @@ local M = {} --- Parse template contents in order to expand wildcards ---@param str string String to parse ---@param lookup Wildcard Wildcards lookup table +---@return string[] parsed_str Table containing all lines with wildcards expanded table +---@return nil | [integer, integer] cursor_pos Row-column position tuple of the last cursor wildcard found. M.parse = function(str, lookup) + ---@type string[] local parsedstr = {} for _, l in ipairs(vim.split(str, "\n", { plain = true })) do for wildcard in l:gmatch("${([^{,^}]+)}") do - local expansion = nil ----@return string[] parsed_str Table containing all lines with wildcards expanded table ----@return nil | [integer, integer] cursor_pos Row-column position tuple of the last cursor wildcard found. - + ---@type string + local expansion if vim.tbl_contains(vim.tbl_keys(lookup), wildcard) then - expansion = lookup[wildcard] + local wild = lookup[wildcard] + if type(wild) == "function" then + expansion = wild() + else + expansion = wild + end elseif string.find(wildcard, "lua:") then local cmdstr = l:gsub(".*${lua:([^{,^}]+)}.*", "%1") local cmdout = load("return " .. cmdstr)() @@ -30,9 +36,7 @@ M.parse = function(str, lookup) local cursor_pos = nil for row, l in ipairs(parsedstr) do local col, _ = string.find(l, "${cursor}") - if col ~= nil then - cursor_pos = {row, col} - end + if col ~= nil then cursor_pos = { row, col } end parsedstr[row] = parsedstr[row]:gsub("${cursor}", "") end From a7a0f57fe295f4a68f19557d45f14206cb2277e2 Mon Sep 17 00:00:00 2001 From: azan Date: Fri, 16 Aug 2024 00:11:24 +0300 Subject: [PATCH 04/11] feat(template): select from suggested templatenames --- lua/esqueleto/config.lua | 26 +++++++++++++++++++------- lua/esqueleto/init.lua | 1 + lua/esqueleto/selectors/builtin.lua | 18 ++++++++++++++++++ lua/esqueleto/utils.lua | 12 +++++++----- 4 files changed, 45 insertions(+), 12 deletions(-) create mode 100644 lua/esqueleto/selectors/builtin.lua diff --git a/lua/esqueleto/config.lua b/lua/esqueleto/config.lua index 1ecf17e..8a4e0f9 100644 --- a/lua/esqueleto/config.lua +++ b/lua/esqueleto/config.lua @@ -1,7 +1,8 @@ +local selector = require("esqueleto.selectors.builtin") local utils = require("esqueleto.utils") local M = {} ---@type Esqueleto.Config +---@type Esqueleto.Config M.default_config = { autouse = true, directories = { vim.fn.stdpath("config") .. "/skeletons" }, @@ -17,21 +18,32 @@ M.default_config = { ["filetype"] = function() return vim.bo.filetype end, -- Date and time - ["date"] = function() return os.date("%Y%m%d", os.time()) end, - ["year"] = function() return os.date("%Y", os.time()) end, - ["month"] = function() return os.date("%m", os.time()) end, - ["day"] = function() return os.date("%d", os.time()) end, - ["time"] = function() return os.date("%T", os.time()) end, + ["date"] = function() + return os.date("%Y%m%d", os.time()) --[[@as string]] + end, + ["year"] = function() + return os.date("%Y", os.time()) --[[@as string]] + end, + ["month"] = function() + return os.date("%m", os.time()) --[[@as string]] + end, + ["day"] = function() + return os.date("%d", os.time()) --[[@as string]] + end, + ["time"] = function() + return os.date("%T", os.time()) --[[@as string]] + end, -- System ["host"] = utils.capture("hostname", false), - ["user"] = os.getenv("USER"), + ["user"] = os.getenv("USER") or "USER", -- Github ["gh-email"] = utils.capture("git config user.email", false), ["gh-user"] = utils.capture("git config user.name", false), }, }, + selector = selector, advanced = { ignored = {}, ignore_os_files = true, diff --git a/lua/esqueleto/init.lua b/lua/esqueleto/init.lua index af9749d..801fc19 100644 --- a/lua/esqueleto/init.lua +++ b/lua/esqueleto/init.lua @@ -17,6 +17,7 @@ local excmd = require("esqueleto.excmd") ---@field directories string[] The list of paths in which the search will be performed ---@field patterns string[] See: [vim.api.nvim_create_autocmd](lua://vim.api.nvim_create_autocmd) ---@field autouse boolean Auto-use a template? +---@field selector fun( templatenames: string[] ):string? Function that choose some of template ---@field wildcards Wildcards ---@field advanced Esqueleto.Advanced diff --git a/lua/esqueleto/selectors/builtin.lua b/lua/esqueleto/selectors/builtin.lua new file mode 100644 index 0000000..a899b07 --- /dev/null +++ b/lua/esqueleto/selectors/builtin.lua @@ -0,0 +1,18 @@ +return function(templatenames) + -- Sync call ui.select + -- See: https://github.com/mfussenegger/nvim-dap/blob/66d33b7585b42b7eac20559f1551524287ded353/lua/dap/ui.lua#L55 + local co = coroutine.running() + local choicer = function(choice) + if not choice then + vim.notify( + "[esqueleto] No template selected, leaving buffer empty", + vim.log.levels.INFO + ) + end + coroutine.resume(co, choice) + end + -- I don't know reason to use that + -- choicer = vim.schedule_wrap(choicer) + vim.ui.select(templatenames, { prompt = "Select skeleton to use:" }, choicer) + return coroutine.yield() +end diff --git a/lua/esqueleto/utils.lua b/lua/esqueleto/utils.lua index c908c16..de9e899 100644 --- a/lua/esqueleto/utils.lua +++ b/lua/esqueleto/utils.lua @@ -181,13 +181,15 @@ M.selecttemplate = function(templates, opts) end -- Select template - vim.ui.select(templatenames, { prompt = "Select skeleton to use:" }, function(choice) + + -- wrap to coroutine to have possibility to async function + ---@see esqueleto.selectors.builtin + coroutine.wrap(function() + local choice = opts.selector(templatenames) if templates[choice] then - M.writetemplate(uv.fs_realpath(templates[choice])--[[@as string]], opts) - else - vim.notify("[esqueleto] No template selected, leaving buffer empty", vim.log.levels.INFO) + M.writetemplate(uv.fs_realpath(templates[choice]) --[[@as string]], opts) end - end) + end)() end --- Insert template on current buffer From d071e49e1536fa61728cc5f0865943c7b5bcbe3a Mon Sep 17 00:00:00 2001 From: azan Date: Fri, 16 Aug 2024 00:19:37 +0300 Subject: [PATCH 05/11] revert: Add CI --- .github/workflows/check-lua.yaml | 33 ------------------- .github/workflows/tests.yaml | 54 -------------------------------- .luacheckrc | 33 ------------------- Makefile | 22 ------------- README.md | 1 - scripts/minimal_init.lua | 35 --------------------- 6 files changed, 178 deletions(-) delete mode 100644 .github/workflows/check-lua.yaml delete mode 100644 .github/workflows/tests.yaml delete mode 100644 .luacheckrc delete mode 100644 Makefile delete mode 100644 scripts/minimal_init.lua diff --git a/.github/workflows/check-lua.yaml b/.github/workflows/check-lua.yaml deleted file mode 100644 index 16a0789..0000000 --- a/.github/workflows/check-lua.yaml +++ /dev/null @@ -1,33 +0,0 @@ ---- -name: Linting and style checking - -on: - - push - -jobs: - luacheck: - name: Luacheck - runs-on: ubuntu-24.04 - steps: - - uses: actions/checkout@v2 - - name: Prepare - run: | - sudo apt-get update - sudo apt-get install -y luarocks - sudo luarocks install luacheck - - name: Lint - run: make lint_luacheck - - stylua: - name: stylua - runs-on: ubuntu-24.04 - steps: - - uses: actions/checkout@v2 - - name: Prepare - run: | - sudo apt-get update - sudo apt install -y nodejs npm - - name: Lint - run: "make lint_stylua" - env: - STYLUA: "npx @johnnymorganz/stylua-bin" diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml deleted file mode 100644 index 72ce39a..0000000 --- a/.github/workflows/tests.yaml +++ /dev/null @@ -1,54 +0,0 @@ ---- -name: Tests - -on: - - push - -jobs: - lua-tests: - name: Lua Tests - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - include: - - os: ubuntu-24.04 - rev: nightly/nvim-linux64.tar.gz - manager: sudo apt-get - packages: -y ripgrep - - os: ubuntu-24.04 - rev: stable/nvim-linux64.tar.gz - manager: sudo apt-get - - os: macos-14 - rev: nightly/nvim-macos-x86_64.tar.gz - manager: brew - packages: ripgrep - - os: macos-14 - rev: stable/nvim-macos-x86_64.tar.gz - manager: brew - packages: ripgrep - steps: - - uses: actions/checkout@v3 - - run: date +%F > todays-date - - name: Restore from todays cache - uses: actions/cache@v3 - with: - path: _neovim - key: ${{ runner.os }}-${{ matrix.rev }}-${{ hashFiles('todays-date') }} - - name: Prepare - run: | - ${{ matrix.manager }} update - ${{ matrix.manager }} install ${{ matrix.packages }} - test -d _neovim || { - mkdir -p _neovim - curl -sL "https://github.com/neovim/neovim/releases/download/${{ matrix.rev }}" | tar xzf - --strip-components=1 -C "${PWD}/_neovim" - } - mkdir -p ~/.local/share/nvim/site/pack/vendor/start - git clone --depth 1 https://github.com/nvim-lua/plenary.nvim ~/.local/share/nvim/site/pack/vendor/start/plenary.nvim - ln -s $(pwd) ~/.local/share/nvim/site/pack/vendor/start - - name: Run tests - run: | - export PATH="${PWD}/_neovim/bin:${PATH}" - export VIM="${PWD}/_neovim/share/nvim/runtime" - nvim --version - make test diff --git a/.luacheckrc b/.luacheckrc deleted file mode 100644 index 56d22d0..0000000 --- a/.luacheckrc +++ /dev/null @@ -1,33 +0,0 @@ -std = luajit -codes = true - -self = false - --- Glorious list of warnings: https://luacheck.readthedocs.io/en/stable/warnings.html -ignore = { - "212", -- Unused argument, In the case of callback function, _arg_name is easier to understand than _, so this option is set to off. - "122", -- Indirectly setting a readonly global -} - -globals = { - "_", - "TelescopeGlobalState", - "_TelescopeConfigurationValues", - "_TelescopeConfigurationPickers", - "__TelescopeKeymapStore", -} - --- Global objects defined by the C code -read_globals = { - "vim", - "assert", - "describe", - "it", - "before_each", - "after_each", - "pending", - "clear", - - "G_P", - "G_R", -} diff --git a/Makefile b/Makefile deleted file mode 100644 index c83bfa8..0000000 --- a/Makefile +++ /dev/null @@ -1,22 +0,0 @@ -all: format lint test - -STYLUA ?= stylua - -.PHONY: test -test: - nvim --headless -u scripts/minimal_init.lua -c "PlenaryBustedDirectory tests { minimal_init='./scripts/minimal_init.lua', sequential=true, }" - -.PHONY: lint_stylua -lint_stylua: - ${STYLUA} --color always --check lua - -.PHONY: lint_luacheck -lint_luacheck: - luacheck lua - -.PHONY: lint -lint: lint_luacheck lint_stylua - -.PHONY: format -format: - ${STYLUA} lua diff --git a/README.md b/README.md index 6523f7a..0f2dfc5 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,6 @@ The plugin provides the following functionality: `esqueleto.nvim` requires the following: - Neovim 0.8+ - Install `esqueleto.nvim` with your preferred package manager: diff --git a/scripts/minimal_init.lua b/scripts/minimal_init.lua deleted file mode 100644 index 4e5509b..0000000 --- a/scripts/minimal_init.lua +++ /dev/null @@ -1,35 +0,0 @@ --- this file create separate XDG path --- thus Lazy.nvim doesnt takes control over the loading -local M = {} - -function M.root(root) - local f = debug.getinfo(1, "S").source:sub(2) - return vim.fn.fnamemodify(f, ":p:h:h") .. "/" .. (root or "") -end - ----@param plugin string -function M.load(plugin) - local name = plugin:match(".*/(.*)") - local package_root = M.root(".tests/site/pack/deps/start/") - if not (vim.loop or vim.uv).fs_stat(package_root .. name) then - print("Installing " .. plugin) - vim.fn.mkdir(package_root, "p") - vim.fn.system({ - "git", - "clone", - "--depth=1", - "https://github.com/" .. plugin .. ".git", - package_root .. "/" .. name, - }) - end -end - -function M.setup() - vim.cmd([[set runtimepath=$VIMRUNTIME]]) - vim.opt.runtimepath:append(M.root()) - vim.opt.packpath = { M.root(".tests/site") } - - M.load("nvim-lua/plenary.nvim") -end - -M.setup() From 33d55268c74d6025d6a2b79590b5ae31495a6696 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Vigil=20V=C3=A1squez?= Date: Thu, 15 Aug 2024 20:38:48 -0400 Subject: [PATCH 06/11] refactor: use Iter-version --- lua/esqueleto/utils.lua | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/lua/esqueleto/utils.lua b/lua/esqueleto/utils.lua index de9e899..8a1d4c4 100644 --- a/lua/esqueleto/utils.lua +++ b/lua/esqueleto/utils.lua @@ -69,27 +69,17 @@ M.writetemplate = function(file, opts) end end ---- List ignored files under a directory, given a list of glob patterns ----Neovim version -10 ----@deprecated +---List ignored files under a directory, given a list of glob patterns +---@param dir string +---@param ignored_patterns string[] +---@return string[] local listignored = function(dir, ignored_patterns) - return vim.tbl_flatten( - vim.tbl_map( - function(patterns) return vim.fn.globpath(dir, patterns, true, true, true) end, - ignored_patterns - ) - ) + return vim + .iter(ignored_patterns) + :map(function(patterns) return vim.fn.globpath(dir, patterns, true, true, true) end) + :flatten() + :totable() end --- ---List ignored files under a directory, given a list of glob patterns --- ---@param dir string --- ---@param ignored_patterns string[] --- ---@return string[] --- local listignore = function(dir, ignored_patterns) --- return vim.iter(ignored_patterns) --- :map(function(patterns) return vim.fn.globpath(dir, patterns, true, true, true) end) --- :flatten() --- :totable() --- end ---Returns a ignore checker ---@param opts Esqueleto.Config From 44da5da7e9acf04a2a8922c38117ad996df9df9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Vigil=20V=C3=A1squez?= Date: Thu, 15 Aug 2024 20:38:57 -0400 Subject: [PATCH 07/11] refactor(ui): give templates name and paths to selectors --- lua/esqueleto/selectors/builtin.lua | 31 +++++++++++++---------------- lua/esqueleto/utils.lua | 2 +- 2 files changed, 15 insertions(+), 18 deletions(-) diff --git a/lua/esqueleto/selectors/builtin.lua b/lua/esqueleto/selectors/builtin.lua index a899b07..5196b53 100644 --- a/lua/esqueleto/selectors/builtin.lua +++ b/lua/esqueleto/selectors/builtin.lua @@ -1,18 +1,15 @@ -return function(templatenames) - -- Sync call ui.select - -- See: https://github.com/mfussenegger/nvim-dap/blob/66d33b7585b42b7eac20559f1551524287ded353/lua/dap/ui.lua#L55 - local co = coroutine.running() - local choicer = function(choice) - if not choice then - vim.notify( - "[esqueleto] No template selected, leaving buffer empty", - vim.log.levels.INFO - ) - end - coroutine.resume(co, choice) - end - -- I don't know reason to use that - -- choicer = vim.schedule_wrap(choicer) - vim.ui.select(templatenames, { prompt = "Select skeleton to use:" }, choicer) - return coroutine.yield() +return function(templates) + -- Sync call ui.select + -- See: https://github.com/mfussenegger/nvim-dap/blob/66d33b7585b42b7eac20559f1551524287ded353/lua/dap/ui.lua#L55 + local co = coroutine.running() + local choicer = function(choice) + if not choice then + vim.notify("[esqueleto] No template selected, leaving buffer empty", vim.log.levels.INFO) + end + coroutine.resume(co, choice) + end + -- I don't know reason to use that + -- choicer = vim.schedule_wrap(choicer) + vim.ui.select(vim.tbl_keys(templates), { prompt = "Select skeleton to use:" }, choicer) + return coroutine.yield() end diff --git a/lua/esqueleto/utils.lua b/lua/esqueleto/utils.lua index 8a1d4c4..481a60b 100644 --- a/lua/esqueleto/utils.lua +++ b/lua/esqueleto/utils.lua @@ -175,7 +175,7 @@ M.selecttemplate = function(templates, opts) -- wrap to coroutine to have possibility to async function ---@see esqueleto.selectors.builtin coroutine.wrap(function() - local choice = opts.selector(templatenames) + local choice = opts.selector(templates) if templates[choice] then M.writetemplate(uv.fs_realpath(templates[choice]) --[[@as string]], opts) end From 054c87ab0ee0552f6ab9ddd2490b164572dc5f49 Mon Sep 17 00:00:00 2001 From: azan Date: Wed, 2 Oct 2024 18:07:33 +0300 Subject: [PATCH 08/11] feat(default.finder): telescope --- lua/esqueleto/selectors/telescope.lua | 34 +++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 lua/esqueleto/selectors/telescope.lua diff --git a/lua/esqueleto/selectors/telescope.lua b/lua/esqueleto/selectors/telescope.lua new file mode 100644 index 0000000..2ad465e --- /dev/null +++ b/lua/esqueleto/selectors/telescope.lua @@ -0,0 +1,34 @@ +return function(templates) + local co = coroutine.running() + local pickers = require("telescope.pickers") + local finders = require("telescope.finders") + local actions = require("telescope.actions") + local action_state = require("telescope.actions.state") + pickers + .new({}, { + prompt_title = "Templates", + previewer = _TelescopeConfigurationValues.file_previewer({}), + finder = finders.new_table({ + results = vim.tbl_keys(templates), + entry_maker = function(entry) + return { + value = entry, + display = entry, + ordinal = entry, + filename = templates[entry], + } + end, + }), + sorter = _TelescopeConfigurationValues.generic_sorcer({}), + attach_mappings = function(prompt_bufnr) + actions.select_default:replace(function() + actions.close(prompt_bufnr) + local selection = action_state.get_selected_entry() + coroutine.resume(co, selection.value) + end) + return true + end, + }) + :find() + return coroutine.yield() +end From 3d808addf3d2b6e695a4a36b794103fbd2ad2ec5 Mon Sep 17 00:00:00 2001 From: azan Date: Wed, 2 Oct 2024 18:18:33 +0300 Subject: [PATCH 09/11] fix(telescope): misspell `generic_sorter` --- lua/esqueleto/selectors/telescope.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lua/esqueleto/selectors/telescope.lua b/lua/esqueleto/selectors/telescope.lua index 2ad465e..c428e0d 100644 --- a/lua/esqueleto/selectors/telescope.lua +++ b/lua/esqueleto/selectors/telescope.lua @@ -19,7 +19,7 @@ return function(templates) } end, }), - sorter = _TelescopeConfigurationValues.generic_sorcer({}), + sorter = _TelescopeConfigurationValues.generic_sorter({}), attach_mappings = function(prompt_bufnr) actions.select_default:replace(function() actions.close(prompt_bufnr) From e102cdfce8d377ec8317f5f7654d30362092e7fb Mon Sep 17 00:00:00 2001 From: azan Date: Wed, 2 Oct 2024 22:56:12 +0300 Subject: [PATCH 10/11] fix(pickers): builtin wrap into schedule --- lua/esqueleto/selectors/builtin.lua | 2 +- lua/esqueleto/utils.lua | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/lua/esqueleto/selectors/builtin.lua b/lua/esqueleto/selectors/builtin.lua index 5196b53..7b1d181 100644 --- a/lua/esqueleto/selectors/builtin.lua +++ b/lua/esqueleto/selectors/builtin.lua @@ -9,7 +9,7 @@ return function(templates) coroutine.resume(co, choice) end -- I don't know reason to use that - -- choicer = vim.schedule_wrap(choicer) + choicer = vim.schedule_wrap(choicer) vim.ui.select(vim.tbl_keys(templates), { prompt = "Select skeleton to use:" }, choicer) return coroutine.yield() end diff --git a/lua/esqueleto/utils.lua b/lua/esqueleto/utils.lua index 481a60b..6be49cb 100644 --- a/lua/esqueleto/utils.lua +++ b/lua/esqueleto/utils.lua @@ -176,6 +176,7 @@ M.selecttemplate = function(templates, opts) ---@see esqueleto.selectors.builtin coroutine.wrap(function() local choice = opts.selector(templates) + vim.ui.input({prompt = choice }, function(input) vim.print(input) end) if templates[choice] then M.writetemplate(uv.fs_realpath(templates[choice]) --[[@as string]], opts) end From 1994c1fffd58c6b04355b1da29919e47a5455d21 Mon Sep 17 00:00:00 2001 From: azan Date: Wed, 2 Oct 2024 23:01:04 +0300 Subject: [PATCH 11/11] chore: remove debug print --- lua/esqueleto/utils.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/lua/esqueleto/utils.lua b/lua/esqueleto/utils.lua index 6be49cb..481a60b 100644 --- a/lua/esqueleto/utils.lua +++ b/lua/esqueleto/utils.lua @@ -176,7 +176,6 @@ M.selecttemplate = function(templates, opts) ---@see esqueleto.selectors.builtin coroutine.wrap(function() local choice = opts.selector(templates) - vim.ui.input({prompt = choice }, function(input) vim.print(input) end) if templates[choice] then M.writetemplate(uv.fs_realpath(templates[choice]) --[[@as string]], opts) end