LuaSnip icon indicating copy to clipboard operation
LuaSnip copied to clipboard

[ Help ] Trying to make custom condition function in markdown replicating VimTex plugin

Open JxJxxJxJ opened this issue 1 year ago • 1 comments

Hi, I'm trying to use my snippets which I used in my LaTeX workflow but now in markdown. Thing is I had many ones using functions like in_mathzone provided by the VimTex plugin. I'm trying to replicate that for markdown but I admit my lua skills are not good enough...

My setup is the following, first I create a ~/.config/lvim/lua/user/my-things/luasnips/locals.lua

---@diagnostic disable: undefined-global

-- functions used in .tex files with vimtex plugin
local in_mathzone = function()
  return vim.fn["vimtex#syntax#in_mathzone"]() == 1
end

local in_comment = function()
  return vim.fn["vimtex#syntax#in_comment"]() == 1
end

local in_text = function()
  return not in_mathzone() and not in_comment()
end

local in_align = function()
  return vim.fn["vimtex#env#is_inside"]("align")[1] ~= 0
end

local in_enumerate = function()
  return vim.fn["vimtex#env#is_inside"]("enumerate")[1] ~= 0
end

local in_itemize = function()
  return vim.fn["vimtex#env#is_inside"]("itemize")[1] ~= 0
end

local begins_line = function()
  local cur_line = vim.api.nvim_get_current_line()
  -- Checks if the current line consists of whitespace and then the snippet
  -- TODO: Fix limitation that the snippet cannot contain whitespace itself
  return #cur_line == #string.match(cur_line, "%s*[^%s]+")
end

local get_env = function(name)
  return {
    t({ "\\begin{" .. name .. "}", "\t" }),
    i(0),
    t({ "", "\\end{" .. name .. "}" }),
  }
end



-- functions used in markdown files without vimtex plugin

local function vimtex_syntax_stack(line, col)
  line = line or vim.fn.line('.')
  col = col or vim.fn.col('.')

  if vim.fn.mode() == 'i' then
    col = tonumber(col) - 1
  else
    col = tonumber(col)
  end

  line = tonumber(line) or 1
  col = tonumber(col) or 0

  line = math.max(line, 1)
  col = math.max(col, 0)

  local stack = vim.fn.synstack(line, col)
  return vim.fn.map(stack, function(val) return vim.fn.synIDattr(val, "name") end)
end

local function vimtex_syntax_in(name, ...)
  local stack = vimtex_syntax_stack(...)
  return vim.fn.match(stack[1], '^' .. name) >= 0
end

local function vimtex_syntax_in_comment(...)
  return vimtex_syntax_in('texComment', ...)
end

local function vimtex_syntax_in_mathzone(...)
  local groups = vim.fn.reverse(vimtex_syntax_stack(...))
  local group = vim.fn.matchstr(groups, '\\v^tex\\%(Math%(Zone\\|Text\\|Tag\\)\\|RefArg\\)')
  return vim.fn.match(group, '^texMathZone') ~= -1
end


-- all returns in one place
return {
  s = require("luasnip.nodes.snippet").S,
  sn = require("luasnip.nodes.snippet").SN,
  isn = require("luasnip.nodes.snippet").ISN,
  t = require("luasnip.nodes.textNode").T,
  i = require("luasnip.nodes.insertNode").I,
  f = require("luasnip.nodes.functionNode").F,
  c = require("luasnip.nodes.choiceNode").C,
  d = require("luasnip.nodes.dynamicNode").D,
  r = require("luasnip.nodes.restoreNode").R,
  events = require("luasnip.util.events"),
  ai = require("luasnip.nodes.absolute_indexer"),
  extras = require("luasnip.extras"),
  l = require("luasnip.extras").lambda,
  rep = require("luasnip.extras").rep,
  p = require("luasnip.extras").partial,
  m = require("luasnip.extras").match,
  n = require("luasnip.extras").nonempty,
  dl = require("luasnip.extras").dynamic_lambda,
  fmt = require("luasnip.extras.fmt").fmt,
  fmta = require("luasnip.extras.fmt").fmta,
  conds = require("luasnip.extras.expand_conditions"),
  postfix = require("luasnip.extras.postfix").postfix,
  types = require("luasnip.util.types"),
  parse = require("luasnip.util.parser").parse_snippet,

  -- my locals from the part using vimtex functions
  in_mathzone = in_mathzone,
  in_comment = in_comment,
  in_text = in_text,
  in_align = in_align,
  in_enumerate = in_enumerate,
  in_itemize = in_itemize,
  begins_line = begins_line,
  get_env = get_env,

  -- my locals from the part using vimtex functions
  vimtex_syntax_stack = vimtex_syntax_stack,
  vimtex_syntax_in = vimtex_syntax_in,
  vimtex_syntax_in_comment = vimtex_syntax_in_comment,
  vimtex_syntax_in_mathzone = vimtex_syntax_in_mathzone,
}

Then I import this file in my ~/.config/lvim/config.lua as such

reload("user.luasnips")    -- luasnippets related configs

Then I create my snippets in ~/.config/lvim/luasnippets/markdown/test.lua using the functions I made

---@diagnostic disable: undefined-global

return {
  -- LaTeX: Inline math mode
  s({ trig = "mm", snippetType = "autosnippet" },
    {
      t("$ "),
      i(1),
      t(" $ "),
    }),
  -- LaTeX: Display math mode
  s({ trig = ";dm", snippetType = "autosnippet" }, {
    t({ "$$", "\t" }),
    i(1),
    t({ "", "$$" }),
  }),

  -- test in mathzone but markdown
  s({ trig = "rangle", snippetType = "autosnippet" }, { t(" \\rangle ") }, { condition = vimtex_syntax_in_mathzone }),
}

but the rangle snippet is triggered ignoring the condition.

Now, is it because the condition function is badly implemented? Or am I importing the functions wrongly? Is it possible to just use VimTex plugin in markdown files to "load" all the functions and use the same conditions in markdown files?

Edit: If I do

local vimtex_syntax_in_mathzone = require("user.my-things.luasnips.locals").vimtex_syntax_in_mathzone

in my test.lua file it now typing rangle in a markdown file gives me the following error, it's getting loaded now but the function in locals.lua seems to be wrong

Error executing lua callback: ...e/jx/.config/lvim/lua/user/my-things/luasnips/locals.lua:52: attempt to perform arithmetic on a nil value
stack traceback:
        ...e/jx/.config/lvim/lua/user/my-things/luasnips/locals.lua:52: in function 'vimtex_syntax_stack'
        ...e/jx/.config/lvim/lua/user/my-things/luasnips/locals.lua:80: in function 'condition'
        ...site/pack/lazy/opt/LuaSnip/lua/luasnip/nodes/snippet.lua:546: in function 'matches'
        ...y/opt/LuaSnip/lua/luasnip/session/snippet_collection.lua:174: in function 'match_snippet'
        ...lunarvim/site/pack/lazy/opt/LuaSnip/lua/luasnip/init.lua:325: in function 'expand_auto'
        ...narvim/site/pack/lazy/opt/LuaSnip/lua/luasnip/config.lua:264: in function <...narvim/site/pack/lazy/opt/LuaSnip/lua/luasnip/config.lua:262>

JxJxxJxJ avatar Jan 30 '24 19:01 JxJxxJxJ

Aw man, I don't think I can help much here :/ A few troubleshooting ideas:

  • put the function-definition into the snippet-file to rule out something going wrong with importing
  • call the vimtex-function manually when inside a markdown-file to make sure it's returning the results you expect.

The snippets look correct at least :D

L3MON4D3 avatar Feb 14 '24 19:02 L3MON4D3

@JxJxxJxJ did you got it to work? i'm also looking for reusing my math latex snippets on markdown :face_exhaling:

juanolon avatar Apr 28 '24 20:04 juanolon