Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions lua/luasnip/extras/conditions/expand.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ local function line_begin(line_to_cursor, matched_trigger)
-- +1 because `string.sub("abcd", 1, -2)` -> abc
return line_to_cursor:sub(1, -(#matched_trigger + 1)):match("^%s*$")
end
--- A condition obj that is true when the trigger is at start of line (maybe after indent).
M.line_begin = cond_obj.make_condition(line_begin)

--- The wordTrig flag will only expand the snippet if
Expand Down Expand Up @@ -41,16 +42,16 @@ M.line_begin = cond_obj.make_condition(line_begin)
--- I think the character wordTrig=true uses should be customized
--- A condtion seems like the best way to do it
---
--- @param pattern string should be a character class eg `[%w]`
---@param pattern string should be a character class eg `[%w]`
---@return LuaSnip.SnipContext.ConditionObj
function M.trigger_not_preceded_by(pattern)
local condition = function(line_to_cursor, matched_trigger)
local line_to_trigger_len = #line_to_cursor - #matched_trigger
if line_to_trigger_len == 0 then
return true
end
return not string
.sub(line_to_cursor, line_to_trigger_len, line_to_trigger_len)
:match(pattern)
local char_before_trigger = line_to_cursor:sub(line_to_trigger_len, line_to_trigger_len)
return not char_before_trigger:match(pattern)
end
return cond_obj.make_condition(condition)
end
Expand Down
142 changes: 93 additions & 49 deletions lua/luasnip/extras/conditions/init.lua
Original file line number Diff line number Diff line change
@@ -1,55 +1,99 @@
local M = {}

-----------------------
-- CONDITION OBJECTS --
-----------------------
local condition_mt = {
-- logic operators
-- not '-'
__unm = function(o1)
return M.make_condition(function(...)
return not o1(...)
end)
end,
-- or '+'
__add = function(o1, o2)
return M.make_condition(function(...)
return o1(...) or o2(...)
end)
end,
__sub = function(o1, o2)
return M.make_condition(function(...)
return o1(...) and not o2(...)
end)
end,
-- and '*'
__mul = function(o1, o2)
return M.make_condition(function(...)
return o1(...) and o2(...)
end)
end,
-- xor '^'
__pow = function(o1, o2)
return M.make_condition(function(...)
return o1(...) ~= o2(...)
end)
end,
-- xnor '%'
-- might be counter intuitive, but as we can't use '==' (must return bool)
-- it's best to use something weird (doesn't have to be used)
__mod = function(o1, o2)
return function(...)
return o1(...) == o2(...)
end
end,
--- A composable condition object, can be used for `condition` in a snippet
--- context.
---
---@class LuaSnip.SnipContext.ConditionObj
---@field func LuaSnip.SnipContext.ConditionFn
---
---@overload fun(line_to_cursor: string, matched_trigger: string, captures: string[]): boolean
--- (note: same signature as `func` field)
---
---@operator unm: LuaSnip.SnipContext.ConditionObj
---@operator add(LuaSnip.SnipContext.Condition): LuaSnip.SnipContext.ConditionObj
---@operator sub(LuaSnip.SnipContext.Condition): LuaSnip.SnipContext.ConditionObj
---@operator mul(LuaSnip.SnipContext.Condition): LuaSnip.SnipContext.ConditionObj
---@operator pow(LuaSnip.SnipContext.Condition): LuaSnip.SnipContext.ConditionObj
---@operator mod(LuaSnip.SnipContext.Condition): LuaSnip.SnipContext.ConditionObj
local ConditionObj = {}
local ConditionObj_mt = {
__index = ConditionObj,
-- use table like a function by overloading __call
__call = function(tab, line_to_cursor, matched_trigger, captures)
return tab.func(line_to_cursor, matched_trigger, captures)
__call = function(self, line_to_cursor, matched_trigger, captures)
return self.func(line_to_cursor, matched_trigger, captures)
end,
}

function M.make_condition(func)
return setmetatable({ func = func }, condition_mt)
--- Wrap the given `condition` function in a composable condition object.
---@param func LuaSnip.SnipContext.Condition
---@return LuaSnip.SnipContext.ConditionObj
function ConditionObj.make_condition(func)
return setmetatable({ func = func }, ConditionObj_mt)
end

--- Returns a condition object equivalent to `not self(...)`
---@return LuaSnip.SnipContext.ConditionObj
function ConditionObj:inverted()
return ConditionObj.make_condition(function(...)
return not self(...)
end)
end
-- (e.g. `-cond`)
ConditionObj_mt.__unm = ConditionObj.inverted

--- Returns a condition object equivalent to `self(...) or other(...)`
---@param other LuaSnip.SnipContext.Condition
---@return LuaSnip.SnipContext.ConditionObj
function ConditionObj:or_(other)
return ConditionObj.make_condition(function(...)
return self(...) or other(...)
end)
end
-- (e.g. `cond1 + cond2`)
ConditionObj_mt.__add = ConditionObj.or_

--- Returns a condition object equivalent to `self(...) and not other(...)`
---@param other LuaSnip.SnipContext.Condition
---@return LuaSnip.SnipContext.ConditionObj
function ConditionObj:and_not(other)
return ConditionObj.make_condition(function(...)
return self(...) and not other(...)
end)
end
-- (e.g. `cond1 - cond2`)
ConditionObj_mt.__sub = ConditionObj.and_not

--- Returns a condition object equivalent to `self(...) and other(...)`
---@param other LuaSnip.SnipContext.Condition
---@return LuaSnip.SnipContext.ConditionObj
function ConditionObj:and_(other)
return ConditionObj.make_condition(function(...)
return self(...) and other(...)
end)
end
-- (e.g. `cond1 * cond2`)
ConditionObj_mt.__mul = ConditionObj.and_

--- Returns a condition object equivalent to `self(...) ~= other(...)`
---@param other LuaSnip.SnipContext.Condition
---@return LuaSnip.SnipContext.ConditionObj
function ConditionObj:not_same_as(other)
return ConditionObj.make_condition(function(...)
return self(...) ~= other(...)
end)
end
-- (e.g. `cond1 ^ cond2`)
ConditionObj_mt.__pow = ConditionObj.not_same_as

--- Returns a condition object equivalent to `self(...) == other(...)`
---@param other LuaSnip.SnipContext.Condition
---@return LuaSnip.SnipContext.ConditionObj
function ConditionObj:same_as(other)
return ConditionObj.make_condition(function(...)
return self(...) == other(...)
end)
end
-- (e.g. `cond1 % cond2`)
-- This operator might be counter intuitive, but '==' can't be used as it must
-- return a boolean. It's best to use something weird (doesn't have to be used)
ConditionObj_mt.__mod = ConditionObj.same_as

return M
return ConditionObj
14 changes: 10 additions & 4 deletions lua/luasnip/nodes/snippet.lua
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ local Snippet = node_mod.Node:new()
---@field docTrig? string
---@field trig_matcher LuaSnip.SnipContext.TrigMatcher
---@field resolveExpandParams LuaSnip.ResolveExpandParamsFn
---@field show_condition LuaSnip.SnipContext.ShowCondition
---@field show_condition LuaSnip.SnipContext.ShowConditionFn
---@field condition LuaSnip.SnipContext.Condition
---@field invalidated boolean

Expand Down Expand Up @@ -530,8 +530,9 @@ end
---@field env_override? {[string]: string[]|string} Override or extend
--- the snippet's environment (`snip.env`)

---@alias LuaSnip.SnipContext.Condition fun(line_to_cursor: string, matched_trigger: string, captures: string[]): boolean
---@alias LuaSnip.SnipContext.ShowCondition fun(line_to_cursor: string): boolean
---@alias LuaSnip.SnipContext.ConditionFn fun(line_to_cursor: string, matched_trigger: string, captures: string[]): boolean
---@alias LuaSnip.SnipContext.Condition LuaSnip.SnipContext.ConditionFn|LuaSnip.SnipContext.ConditionObj
---@alias LuaSnip.SnipContext.ShowConditionFn fun(line_to_cursor: string): boolean

---@class LuaSnip.SnipContext
---
Expand Down Expand Up @@ -615,7 +616,7 @@ end
--- This function can prevent manual snippet expansion via `ls.expand()`.
--- Return `true` to allow expansion, and `false` to prevent it.
---
---@field show_condition? LuaSnip.SnipContext.ShowCondition
---@field show_condition? LuaSnip.SnipContext.ShowConditionFn
--- This function is (should be) evaluated by completion engines, indicating
--- whether the snippet should be included in current completion candidates.
--- Defaults to a function returning `true`.
Expand All @@ -630,6 +631,11 @@ end

---@class LuaSnip.Opts.Snippet: LuaSnip.Opts.SnippetNode
---@field stored? {[string]: LuaSnip.Node} Snippet-level state for restore node.
---
---@field show_condition? LuaSnip.SnipContext.ShowConditionFn Same as
--- `show_condition` in snippet context. (here for backward compat)
---@field condition? LuaSnip.SnipContext.Condition Same as `condition` in
--- snippet context. (here for backward compat)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure about why these are possible to specify in the snippet opts, is it for backward compat?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah exactly, they used to be in that table, and until now I don't think there's been a big reason to actually remove them. Best put something about them being deprecated in there? Unfortunately @deprecated only works for functions 😒


---@param context string|LuaSnip.SnipContext The snippet context.
--- Passing a string is equivalent to passing `{ trig = <the string> }`.
Expand Down