This commit is contained in:
parent
9992d5cd31
commit
f48217a7fc
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,3 +1,4 @@
|
||||
/.lux/
|
||||
lux.lock
|
||||
*.src.rock
|
||||
*.aider*
|
||||
|
4
Makefile
4
Makefile
@ -3,8 +3,8 @@ PLENARY_DIR=~/.local/share/nvim/site/pack/test/opt/plenary.nvim
|
||||
all: lint test
|
||||
|
||||
lint:
|
||||
lua-language-server --check=lua/u/ --checklevel=Hint
|
||||
lux check
|
||||
lua-language-server --check=lua/u/ --checklevel=Error
|
||||
lx check
|
||||
|
||||
fmt:
|
||||
stylua .
|
||||
|
@ -231,8 +231,10 @@ function M.create_picker(opts) -- {{{
|
||||
local formatted_items = s_formatted_items:get()
|
||||
local filter_text = vim.trim(s_filter_text:get()):lower()
|
||||
|
||||
local filter_pattern = ''
|
||||
local use_plain_pattern = false
|
||||
--- @type string
|
||||
local filter_pattern
|
||||
--- @type boolean
|
||||
local use_plain_pattern
|
||||
if #formatted_items > 250 and #filter_text <= 3 then
|
||||
filter_pattern = filter_text
|
||||
use_plain_pattern = true
|
||||
|
@ -38,7 +38,8 @@ function CodeWriter.from_line(line, bufnr)
|
||||
local expandtab = vim.api.nvim_get_option_value('expandtab', { buf = bufnr })
|
||||
local shiftwidth = vim.api.nvim_get_option_value('shiftwidth', { buf = bufnr })
|
||||
|
||||
local indent_level = 0
|
||||
--- @type number
|
||||
local indent_level
|
||||
local indent_str = ''
|
||||
if expandtab then
|
||||
while #indent_str < shiftwidth do
|
||||
|
@ -8,7 +8,7 @@ local __U__OpKeymapOpFunc_rhs = nil
|
||||
--- @type nil|fun(range: u.Range): fun():any|nil
|
||||
--- @param ty 'line'|'char'|'block'
|
||||
-- selene: allow(unused_variable)
|
||||
function __U__OpKeymapOpFunc(ty)
|
||||
function _G.__U__OpKeymapOpFunc(ty)
|
||||
if __U__OpKeymapOpFunc_rhs ~= nil then
|
||||
local range = Range.from_op_func(ty)
|
||||
__U__OpKeymapOpFunc_rhs(range)
|
||||
|
@ -459,6 +459,7 @@ end
|
||||
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
|
||||
function Range:line(l)
|
||||
if l < 0 then l = self:line_count() + l + 1 end
|
||||
|
@ -5,6 +5,7 @@ local H = {}
|
||||
--- @alias u.renderer.Node nil | boolean | string | u.renderer.Tag
|
||||
--- @alias u.renderer.Tree u.renderer.Node | u.renderer.Node[]
|
||||
|
||||
-- luacheck: ignore
|
||||
--- @type table<string, fun(attributes: table<string, any>, children: u.renderer.Tree): u.renderer.Tag> & fun(name: string, attributes: table<string, any>, children: u.renderer.Tree): u.renderer.Tag>
|
||||
M.h = setmetatable({}, {
|
||||
__call = function(_, name, attributes, children)
|
||||
@ -108,7 +109,7 @@ function Renderer.markup_to_lines(opts) -- {{{
|
||||
-- newlines are not controlled by array entries, do NOT output a line here:
|
||||
visit(child)
|
||||
end
|
||||
else
|
||||
else -- luacheck: ignore
|
||||
visit(node.children)
|
||||
end
|
||||
|
||||
@ -178,13 +179,13 @@ function Renderer.patch_lines(bufnr, old_lines, new_lines)
|
||||
_set_text(lnum0, cnum0, lnum0, cnum0 + 1, { col_change.to })
|
||||
elseif col_change.kind == 'delete' then
|
||||
_set_text(lnum0, cnum0, lnum0, cnum0 + 1, {})
|
||||
else
|
||||
else -- luacheck: ignore
|
||||
-- No change
|
||||
end
|
||||
end
|
||||
elseif line_change.kind == 'delete' then
|
||||
_set_lines(lnum0, lnum0 + 1, true, {})
|
||||
else
|
||||
else -- luacheck: ignore
|
||||
-- No change
|
||||
end
|
||||
end
|
||||
@ -464,6 +465,7 @@ function TreeBuilder:tree() return self.nodes end
|
||||
-- }}}
|
||||
|
||||
-- Levenshtein utility {{{
|
||||
-- luacheck: ignore
|
||||
--- @alias LevenshteinChange<T> ({ kind: 'add'; item: T; index: number; } | { kind: 'delete'; item: T; index: number; } | { kind: 'change'; from: T; to: T; index: number; })
|
||||
--- @private
|
||||
--- @generic T
|
||||
|
@ -202,7 +202,7 @@ end
|
||||
-- class ExecutionContext
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
CURRENT_CONTEXT = nil
|
||||
local CURRENT_CONTEXT = nil
|
||||
|
||||
--- @class u.ExecutionContext
|
||||
--- @field signals table<u.Signal, boolean>
|
||||
@ -211,7 +211,7 @@ M.ExecutionContext = ExecutionContext
|
||||
ExecutionContext.__index = ExecutionContext
|
||||
|
||||
--- @return u.ExecutionContext
|
||||
function ExecutionContext:new()
|
||||
function ExecutionContext.new()
|
||||
return setmetatable({
|
||||
signals = {},
|
||||
subscribers = {},
|
||||
@ -222,7 +222,7 @@ function ExecutionContext.current() return CURRENT_CONTEXT end
|
||||
|
||||
--- @param fn function
|
||||
--- @param ctx u.ExecutionContext
|
||||
function ExecutionContext:run(fn, ctx)
|
||||
function ExecutionContext.run(fn, ctx)
|
||||
local oldCtx = CURRENT_CONTEXT
|
||||
CURRENT_CONTEXT = ctx
|
||||
local result
|
||||
@ -289,8 +289,8 @@ end
|
||||
--- @param fn function
|
||||
--- @param name? string
|
||||
function M.create_effect(fn, name)
|
||||
local ctx = M.ExecutionContext:new()
|
||||
M.ExecutionContext:run(fn, ctx)
|
||||
local ctx = M.ExecutionContext.new()
|
||||
M.ExecutionContext.run(fn, ctx)
|
||||
return ctx:subscribe(function()
|
||||
if name and M.debug then
|
||||
local deps = vim
|
||||
|
@ -6,6 +6,7 @@ local M = {}
|
||||
|
||||
--- @alias QfItem { col: number, filename: string, kind: string, lnum: number, text: string }
|
||||
--- @alias KeyMaps table<string, fun(): any | string> }
|
||||
-- luacheck: ignore
|
||||
--- @alias CmdArgs { args: string; bang: boolean; count: number; fargs: string[]; line1: number; line2: number; mods: string; name: string; range: 0|1|2; reg: string; smods: any; info: u.Range|nil }
|
||||
|
||||
--- @generic T
|
||||
@ -34,6 +35,7 @@ end
|
||||
--- ```
|
||||
--- @param name string
|
||||
--- @param cmd string | fun(args: CmdArgs): any
|
||||
-- luacheck: ignore
|
||||
--- @param opts? { nargs?: 0|1|'*'|'?'|'+'; range?: boolean|'%'|number; count?: boolean|number, addr?: string; completion?: string }
|
||||
function M.ucmd(name, cmd, opts)
|
||||
local Range = require 'u.range'
|
||||
|
@ -58,66 +58,66 @@ describe('Signal', function()
|
||||
|
||||
describe('Signal:map', function()
|
||||
it('should transform the signal value', function()
|
||||
local signal = Signal:new(5)
|
||||
local mapped_signal = signal:map(function(value) return value * 2 end)
|
||||
local test_signal = Signal:new(5)
|
||||
local mapped_signal = test_signal:map(function(value) return value * 2 end)
|
||||
|
||||
assert.is.equal(mapped_signal:get(), 10) -- Initial transformation
|
||||
signal:set(10)
|
||||
test_signal:set(10)
|
||||
assert.is.equal(mapped_signal:get(), 20) -- Updated transformation
|
||||
end)
|
||||
|
||||
it('should handle empty transformations', function()
|
||||
local signal = Signal:new(nil)
|
||||
local mapped_signal = signal:map(function(value) return value or 'default' end)
|
||||
local test_signal = Signal:new(nil)
|
||||
local mapped_signal = test_signal:map(function(value) return value or 'default' end)
|
||||
|
||||
assert.is.equal(mapped_signal:get(), 'default') -- Return default
|
||||
signal:set 'new value'
|
||||
test_signal:set 'new value'
|
||||
assert.is.equal(mapped_signal:get(), 'new value') -- Return new value
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('Signal:filter', function()
|
||||
it('should only emit values that pass the filter', function()
|
||||
local signal = Signal:new(5)
|
||||
local filtered_signal = signal:filter(function(value) return value > 10 end)
|
||||
local test_signal = Signal:new(5)
|
||||
local filtered_signal = test_signal:filter(function(value) return value > 10 end)
|
||||
|
||||
assert.is.equal(filtered_signal:get(), nil) -- Initial value should not pass
|
||||
signal:set(15)
|
||||
test_signal:set(15)
|
||||
assert.is.equal(filtered_signal:get(), 15) -- Now filtered
|
||||
signal:set(8)
|
||||
test_signal:set(8)
|
||||
assert.is.equal(filtered_signal:get(), 15) -- Does not pass the filter
|
||||
end)
|
||||
|
||||
it('should handle empty initial values', function()
|
||||
local signal = Signal:new(nil)
|
||||
local filtered_signal = signal:filter(function(value) return value ~= nil end)
|
||||
local test_signal = Signal:new(nil)
|
||||
local filtered_signal = test_signal:filter(function(value) return value ~= nil end)
|
||||
|
||||
assert.is.equal(filtered_signal:get(), nil) -- Should be nil
|
||||
signal:set(10)
|
||||
test_signal:set(10)
|
||||
assert.is.equal(filtered_signal:get(), 10) -- Should pass now
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('create_memo', function()
|
||||
it('should compute a derived value and update when dependencies change', function()
|
||||
local signal = Signal:new(2)
|
||||
local memoized_signal = tracker.create_memo(function() return signal:get() * 2 end)
|
||||
local test_signal = Signal:new(2)
|
||||
local memoized_signal = tracker.create_memo(function() return test_signal:get() * 2 end)
|
||||
|
||||
assert.is.equal(memoized_signal:get(), 4) -- Initially compute 2 * 2
|
||||
|
||||
signal:set(3)
|
||||
test_signal:set(3)
|
||||
assert.is.equal(memoized_signal:get(), 6) -- Update to 3 * 2 = 6
|
||||
|
||||
signal:set(5)
|
||||
test_signal:set(5)
|
||||
assert.is.equal(memoized_signal:get(), 10) -- Update to 5 * 2 = 10
|
||||
end)
|
||||
|
||||
it('should not recompute if the dependencies do not change', function()
|
||||
local call_count = 0
|
||||
local signal = Signal:new(10)
|
||||
local test_signal = Signal:new(10)
|
||||
local memoized_signal = tracker.create_memo(function()
|
||||
call_count = call_count + 1
|
||||
return signal:get() + 1
|
||||
return test_signal:get() + 1
|
||||
end)
|
||||
|
||||
assert.is.equal(memoized_signal:get(), 11) -- Compute first value
|
||||
@ -126,11 +126,11 @@ describe('Signal', function()
|
||||
memoized_signal:get() -- Call again, should use memoized value
|
||||
assert.is.equal(call_count, 1) -- Still should only be one call
|
||||
|
||||
signal:set(10) -- Set the same value
|
||||
test_signal:set(10) -- Set the same value
|
||||
assert.is.equal(memoized_signal:get(), 11)
|
||||
assert.is.equal(call_count, 2)
|
||||
|
||||
signal:set(20)
|
||||
test_signal:set(20)
|
||||
assert.is.equal(memoized_signal:get(), 21)
|
||||
assert.is.equal(call_count, 3)
|
||||
end)
|
||||
@ -138,31 +138,31 @@ describe('Signal', function()
|
||||
|
||||
describe('create_effect', function()
|
||||
it('should track changes and execute callback', function()
|
||||
local signal = Signal:new(5)
|
||||
local test_signal = Signal:new(5)
|
||||
local call_count = 0
|
||||
|
||||
tracker.create_effect(function()
|
||||
signal:get() -- track as a dependency
|
||||
test_signal:get() -- track as a dependency
|
||||
call_count = call_count + 1
|
||||
end)
|
||||
|
||||
assert.is.equal(call_count, 1)
|
||||
signal:set(10)
|
||||
test_signal:set(10)
|
||||
assert.is.equal(call_count, 2)
|
||||
end)
|
||||
|
||||
it('should clean up signals and not call after dispose', function()
|
||||
local signal = Signal:new(5)
|
||||
local test_signal = Signal:new(5)
|
||||
local call_count = 0
|
||||
|
||||
local unsubscribe = tracker.create_effect(function()
|
||||
call_count = call_count + 1
|
||||
return signal:get() * 2
|
||||
return test_signal:get() * 2
|
||||
end)
|
||||
|
||||
assert.is.equal(call_count, 1) -- Initially calls
|
||||
unsubscribe() -- Unsubscribe the effect
|
||||
signal:set(10) -- Update signal value
|
||||
test_signal:set(10) -- Update signal value
|
||||
assert.is.equal(call_count, 1) -- Callback should not be called again
|
||||
end)
|
||||
end)
|
||||
|
Loading…
x
Reference in New Issue
Block a user