local ls = require 'luasnip' local s = ls.snippet local sn = ls.snippet_node local fn = ls.function_node local ms = ls.multi_snippet local t = ls.text_node local c = ls.choice_node local i = ls.insert_node local f = ls.function_node local d = ls.dynamic_node local fmt = require('luasnip.extras.fmt').fmt local rep = require('luasnip.extras').rep local line_begin = require('luasnip.extras.conditions').line_begin local extend_decorator = require 'luasnip.util.extend_decorator' local fmta = extend_decorator.apply(fmt, { delimiters = '#~' }) local utils = {} --- Check if the trigger is at the beginning of a line ---@param line_to_cursor string ---@param matched_trigger string ---@return boolean utils.line_begin = function(line_to_cursor, matched_trigger) return line_to_cursor:sub(1, -(#matched_trigger + 1)):match '^%s*$' end --- Check if the trigger is on an empty line ---@param _ string ---@param matched_trigger string ---@return boolean utils.empty_line = function(_, matched_trigger) return vim.api.nvim_get_current_line():match('^%s*' .. vim.pesc(matched_trigger) .. '$') end --- Check if the trigger is at the start of a file ---@param line_to_cursor string ---@param matched_trigger string ---@return boolean utils.file_begin = function(line_to_cursor, matched_trigger) local line_number = vim.fn.line '.' return line_number == 1 and line_begin(line_to_cursor, matched_trigger) end --- Check if the trigger is inside a string ---@return boolean utils.in_string = function() local node_type = vim.treesitter.get_node():type() return node_type == 'string_content' or node_type == 'string' end --- Check if the trigger is inside a comment ---@return boolean utils.in_comment = function() local node_type = vim.treesitter.get_node():type() return node_type == 'comment' end --- Check if the trigger is not inside a string or a comment ---@return boolean utils.not_in_string_or_comment = function() return (not utils.in_string()) and (not utils.in_comment()) end --- Create a basic auto expand trigger ---@param trigger string ---@param description? string ---@param options? table ---@return table utils.tr = function(trigger, description, options) return vim.tbl_extend('force', { trig = trigger, desc = description, snippetType = 'autosnippet', }, options or {}) end --- Create a trigger for an empty line snippet ---@param trigger string ---@param description? string ---@param options? table ---@return table utils.etr = function(trigger, description, options) return utils.tr(trigger, description, vim.tbl_extend('force', { condition = utils.empty_line }, options or {})) end --- Create a trigger for a comment trigger ---@param trigger string ---@param description? string ---@param options? table ---@return table utils.ctr = function(trigger, description, options) return utils.tr(trigger, description, vim.tbl_extend('force', { condition = utils.in_comment }, options or {})) end --- Create a trigger for a snippet to expand anywhere outside a string/comment ---@param trigger string ---@param description? string ---@param options? table ---@return table utils.atr = function(trigger, description, options) return utils.tr( trigger, description, vim.tbl_extend('force', { regTrig = true, wordTrig = false, condition = utils.not_in_string_or_comment, }, options or {}) ) end --- Create a snippet that will expand anywhere but in the middle of a word ---@param trigger any ---@param nodes any ---@param options? any ---@return table utils.bs = function(trigger, nodes, options) local btrigger if type(trigger) == 'string' then btrigger = utils.atr('([^%w_-])' .. trigger) else btrigger = vim.tbl_extend('keep', utils.atr('([^%w_-])' .. trigger.trig), trigger) end return ms( { trigger, btrigger, }, vim.list_extend({ fn(function(args, snip) return snip.captures[1] or '' end) }, nodes), options ) end return utils