diff --git a/.emmyrc.json b/.emmyrc.json new file mode 100644 index 0000000..36adf7e --- /dev/null +++ b/.emmyrc.json @@ -0,0 +1,17 @@ +{ + "$schema": "https://raw.githubusercontent.com/EmmyLuaLs/emmylua-analyzer-rust/refs/heads/main/crates/emmylua_code_analysis/resources/schema.json", + "diagnostics": { + "enable": true, + "globals": ["vim", "it", "describe", "before_each", "after_each"] + }, + "runtime": { + "version": "LuaJIT" + }, + "workspace": { + "library": [ + "$VIMRUNTIME", + "library/busted", + "library/luassert" + ] + } +} diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..435ce42 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,20 @@ +; [submodule "library/busted"] +; path = library/busted +; url = https://github.com/LuaCATS/busted +; branch = main +; [submodule "library/luassert"] +; path = library/luassert +; url = https://github.com/LuaCATS/luassert +; branch = main +; [submodule "library/luv"] +; path = library/luv +; url = https://github.com/LuaCATS/luv +; branch = main +[submodule "library/busted"] + path = library/busted + url = https://github.com/LuaCATS/busted + branch = main +[submodule "library/luassert"] + path = library/luassert + url = https://github.com/LuaCATS/luassert + branch = main diff --git a/.luacheckrc b/.luacheckrc deleted file mode 100644 index 8317fde..0000000 --- a/.luacheckrc +++ /dev/null @@ -1,2 +0,0 @@ --- :vim set ft=lua -globals = { "vim" } diff --git a/Makefile b/Makefile index 4e5b84f..2779587 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,10 @@ +export VIMRUNTIME := $(shell nvim -u NORC --headless +'echo $$VIMRUNTIME' +'quitall' 2>&1) + all: lint fmt-check test lint: @echo "## Typechecking" - @lua-language-server --check=lua/u/ --checklevel=Error + @emmylua_check . fmt-check: @echo "## Checking code format" diff --git a/examples/filetree.lua b/examples/filetree.lua index ed175b0..7c49165 100644 --- a/examples/filetree.lua +++ b/examples/filetree.lua @@ -10,8 +10,8 @@ -- change on the underlying filesystem. -------------------------------------------------------------------------------- ---- @alias u.examples.FsDir { kind: 'dir'; path: string; expanded: boolean; children: u.examples.FsNode[] } ---- @alias u.examples.FsFile { kind: 'file'; path: string } +--- @alias u.examples.FsDir { kind: 'dir', path: string, expanded: boolean, children: u.examples.FsNode[] } +--- @alias u.examples.FsFile { kind: 'file', path: string } --- @alias u.examples.FsNode u.examples.FsDir | u.examples.FsFile --- @alias u.examples.ShowOpts { root_path?: string, width?: number, focus_path?: string } @@ -58,7 +58,7 @@ function H.relative(path, base) end --- @param root_path string ---- @return { tree: u.examples.FsDir; path_to_node: table } +--- @return { tree: u.examples.FsDir, path_to_node: table } function H.get_tree_inf(root_path) logger:info { 'get_tree_inf', root_path } --- @type table @@ -113,10 +113,10 @@ function H.populate_dir_children(tree, path_to_node) end --- @param opts { ---- bufnr: number; ---- prev_winnr: number; ---- root_path: string; ---- focus_path?: string; +--- bufnr: number, +--- prev_winnr: number, +--- root_path: string, +--- focus_path?: string --- } --- --- @return { expand: fun(path: string), collapse: fun(path: string) } @@ -310,7 +310,7 @@ local function _render_in_buffer(opts) -- local renderer = Renderer.new(opts.bufnr) tracker.create_effect(function() - --- @type { tree: u.examples.FsDir; path_to_node: table } + --- @type { tree: u.examples.FsDir, path_to_node: table } local tree_inf = s_tree_inf:get() local tree = tree_inf.tree @@ -407,9 +407,9 @@ end -------------------------------------------------------------------------------- --- @type { ---- bufnr: number; ---- winnr: number; ---- controller: { expand: fun(path: string), collapse: fun(path: string) }; +--- bufnr: number, +--- winnr: number, +--- controller: { expand: fun(path: string), collapse: fun(path: string) } --- } | nil local current_inf = nil diff --git a/examples/notify.lua b/examples/notify.lua index bce6db3..3ec68c7 100644 --- a/examples/notify.lua +++ b/examples/notify.lua @@ -23,10 +23,10 @@ vim.api.nvim_create_autocmd('VimResized', { }) --- @alias u.examples.Notification { ---- kind: number; ---- id: number; ---- text: string; ---- timer: uv.uv_timer_t; +--- kind: number, +--- id: number, +--- text: string, +--- timer: uv.uv_timer_t --- } local M = {} diff --git a/examples/picker.lua b/examples/picker.lua index 1075f46..6f72eba 100644 --- a/examples/picker.lua +++ b/examples/picker.lua @@ -44,22 +44,22 @@ local function shallow_copy_arr(arr) return vim.iter(arr):totable() end -- shortest portion of this function. -------------------------------------------------------------------------------- ---- @alias u.examples.SelectController { ---- get_items: fun(): T[]; ---- set_items: fun(items: T[]); ---- set_filter_text: fun(filter_text: string); ---- get_selected_indices: fun(): number[]; ---- get_selected_items: fun(): T[]; ---- set_selected_indices: fun(indicies: number[], ephemeral?: boolean); ---- close: fun(); +--- @alias u.examples.SelectController { +--- get_items: fun(): T[], +--- set_items: fun(items: T[]), +--- set_filter_text: fun(filter_text: string), +--- get_selected_indices: fun(): number[], +--- get_selected_items: fun(): T[], +--- set_selected_indices: fun(indicies: number[], ephemeral?: boolean), +--- close: fun() --- } --- @alias u.examples.SelectOpts { ---- items: `T`[]; ---- multi?: boolean; ---- format_item?: fun(item: T): u.renderer.Tree; ---- on_finish?: fun(items: T[], indicies: number[]); ---- on_selection_changed?: fun(items: T[], indicies: number[]); ---- mappings?: table; +--- items: `T`[], +--- multi?: boolean, +--- format_item?: (fun(item: T): u.renderer.Tree), +--- on_finish?: (fun(items: T[], indicies: number[])), +--- on_selection_changed?: fun(items: T[], indicies: number[]), +--- mappings?: table --- } --- @generic T @@ -326,7 +326,7 @@ function M.create_picker(opts) -- {{{ safe_wrap(function() local items = s_items:get() local selected_indices = s_selected_indices:get() - --- @type { orig_idx: number; item: T }[] + --- @type { orig_idx: number, item: T }[] local filtered_items = s_filtered_items:get() local cursor_index = s_cursor_index:get() local indices = shallow_copy_arr(selected_indices) @@ -477,7 +477,7 @@ function M.create_picker(opts) -- {{{ local selected_indices = s_selected_indices:get() local top_offset = s_top_offset:get() local cursor_index = s_cursor_index:get() - --- @type { filtered_idx: number; orig_idx: number; item: T; formatted: string }[] + --- @type { filtered_idx: number, orig_idx: number, item: T, formatted: string }[] local visible_items = s_visible_items:get() -- The above has to run in the execution context for the signaling to work, but @@ -791,14 +791,14 @@ function M.buffers() -- {{{ -- ensure that `cwd` ends with a trailing slash: if cwd[#cwd] ~= '/' then cwd = cwd .. '/' end - --- @type { name: string; changed: number; bufnr: number }[] + --- @type { name: string, changed: number, bufnr: number }[] local bufs = vim.fn.getbufinfo { buflisted = 1 } M.create_picker { multi = true, items = bufs, - --- @param item { name: string; changed: number; bufnr: number } + --- @param item { name: string, changed: number, bufnr: number } format_item = function(item) local item_name = item.name if item_name == '' then item_name = '[No Name]' end diff --git a/examples/surround.lua b/examples/surround.lua index 1b1c1fc..db4aa31 100644 --- a/examples/surround.lua +++ b/examples/surround.lua @@ -21,10 +21,10 @@ local surrounds = { ['`'] = { left = '`', right = '`' }, } ---- @type { left: string; right: string } | nil +--- @type { left: string, right: string } | nil local CACHED_BOUNDS = nil ---- @return { left: string; right: string }|nil +--- @return { left: string, right: string }|nil local function prompt_for_bounds() if vim_repeat.is_repeating() then -- If we are repeating, we don't want to prompt for bounds, because @@ -55,7 +55,7 @@ local function prompt_for_bounds() end --- @param range u.Range ---- @param bounds { left: string; right: string } +--- @param bounds { left: string, right: string } local function do_surround(range, bounds) local left = bounds.left local right = bounds.right diff --git a/library/busted b/library/busted new file mode 160000 index 0000000..5ed85d0 --- /dev/null +++ b/library/busted @@ -0,0 +1 @@ +Subproject commit 5ed85d0e016a5eb5eca097aa52905eedf1b180f1 diff --git a/library/luassert b/library/luassert new file mode 160000 index 0000000..d3528bb --- /dev/null +++ b/library/luassert @@ -0,0 +1 @@ +Subproject commit d3528bb679302cbfdedefabb37064515ab95f7b9 diff --git a/lua/u/buffer.lua b/lua/u/buffer.lua index b380a61..f27f5c0 100644 --- a/lua/u/buffer.lua +++ b/lua/u/buffer.lua @@ -62,7 +62,7 @@ end function Buffer:lines(start, stop) return Range.from_lines(self.bufnr, start, stop) end --- @param motion string ---- @param opts? { contains_cursor?: boolean; pos?: u.Pos } +--- @param opts? { contains_cursor?: boolean, pos?: u.Pos } function Buffer:motion(motion, opts) opts = vim.tbl_extend('force', opts or {}, { bufnr = self.bufnr }) return Range.from_motion(motion, opts) diff --git a/lua/u/opkeymap.lua b/lua/u/opkeymap.lua index 0942495..282727e 100644 --- a/lua/u/opkeymap.lua +++ b/lua/u/opkeymap.lua @@ -5,7 +5,6 @@ local __U__OpKeymapOpFunc_rhs = nil --- This is the global utility function used for operatorfunc --- in opkeymap ---- @type nil|fun(range: u.Range): fun():any|nil --- @param ty 'line'|'char'|'block' -- selene: allow(unused_variable) function _G.__U__OpKeymapOpFunc(ty) diff --git a/lua/u/range.lua b/lua/u/range.lua index 6baed0d..1625925 100644 --- a/lua/u/range.lua +++ b/lua/u/range.lua @@ -112,7 +112,7 @@ function Range.from_lines(bufnr, start_line, stop_line) end --- @param motion string ---- @param opts? { bufnr?: number; contains_cursor?: boolean; pos?: u.Pos, user_defined?: boolean } +--- @param opts? { bufnr?: number, contains_cursor?: boolean, pos?: u.Pos, user_defined?: boolean } --- @return u.Range|nil function Range.from_motion(motion, opts) -- Options handling: @@ -513,7 +513,7 @@ function Range:text() return vim.fn.join(self:lines(), '\n') end --- @param l number -- luacheck: ignore ---- @return { line: string; idx0: { start: number; stop: number; }; lnum: number; range: fun():u.Range; text: fun():string }|nil +--- @return { line: string, idx0: { start: number, stop: number }, lnum: number, range: (fun():u.Range), text: fun():string }|nil function Range:line(l) if l < 0 then l = self:line_count() + l + 1 end if l > self:line_count() then return end diff --git a/shell.nix b/shell.nix index bb24309..fcebe49 100644 --- a/shell.nix +++ b/shell.nix @@ -1,10 +1,10 @@ { pkgs ? import - # nixos-25.05 (neovim@0.11.2): + # nixos-unstable (neovim@0.11.4): (fetchTarball { - url = "https://github.com/nixos/nixpkgs/archive/1c1c9b3f5ec0421eaa0f22746295466ee6a8d48f.tar.gz"; - sha256 = "0szvq1swpzyjmyyw929ngxy1khdnd9ba96qds2bm6l6kg4iq3cq0"; + url = "https://github.com/nixos/nixpkgs/archive/0b4defa2584313f3b781240b29d61f6f9f7e0df3.tar.gz"; + sha256 = "0p3rrd8wwlk0iwgzm7frkw1k98ywrh0avi7fqjjk87i68n3inxrs"; }) { }, }: @@ -12,7 +12,7 @@ pkgs.mkShell { packages = [ pkgs.git pkgs.gnumake - pkgs.lua-language-server + pkgs.emmylua-ls pkgs.lua51Packages.busted pkgs.lua51Packages.luacov pkgs.lua51Packages.luarocks