astrocommunity icon indicating copy to clipboard operation
astrocommunity copied to clipboard

Add latex pack

Open aliresool621 opened this issue 10 months ago • 12 comments

Is your feature related to a problem?

Lack of niceties when working with latex

Describe the new feature

https://github.com/latex-lsp/texlab

https://github.com/ltex-plus/ltex-ls-plus

https://www.reddit.com/r/neovim/s/IMynDbihZo

Additional context

Why is texlab not offered by many vimtex users seems odd

The inline math display is nice though

Anyway i just felt sharing my finding here, do with it what you like

aliresool621 avatar Feb 18 '25 18:02 aliresool621

Feel free to open a PR. :)

Uzaaft avatar Feb 18 '25 19:02 Uzaaft

Going to create a latex pack.

Uzaaft avatar Apr 24 '25 17:04 Uzaaft

Ltex plus should be added as a separate module, because it is not just for latex, it support markdown and such

aliresool621 avatar Apr 25 '25 07:04 aliresool621

Ill probably just to a vimtex + texlab in the pack. I dont have the time to look at ltex plus and add it. Perhaps some other day.

Uzaaft avatar Apr 25 '25 07:04 Uzaaft

https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/plugins/extras/lang/tex.lua Looks like a good one to branch off from and add texlab

azdanov avatar May 02 '25 03:05 azdanov

https://github.com/jdujava/nvim-jd/blob/master/lua/plugins/vimtex.lua also this

https://github.com/jdujava/nvim-jd/blob/master/lua/jd/latex_zones.lua and this

aliresool621 avatar Jun 04 '25 03:06 aliresool621

https://github.com/jdujava/nvim-jd/blob/master/lua/plugins/vimtex.lua also this

https://github.com/jdujava/nvim-jd/blob/master/lua/jd/latex_zones.lua and this

return {  
    {  
    "mason-org/mason.nvim",  
    optional = true,  
    opts = { ensure_installed = {"bibtex-tidy",  "texlab", "tectonic", "tex-fmt" } },  
    },  
    {  
    "nvim-treesitter/nvim-treesitter",  
    optional = true,  
    opts = { ensure_installed = { "bibtex", "latex" } },  
    },  
    {  
        'lervag/vimtex',  
        lazy = false, -- otherwise reverse search does not work  
        config = function()  
            vim.g.tex_flavor = 'latex'  
            vim.g.vimtex_view_method = 'zathura'  
            vim.g.vimtex_compiler_method = "tectonic"  
    },  
    {  
    "stevearc/conform.nvim",  
    optional = true,  
    opts = function(_, opts)  
      local Util = require "conform.util"  
      local opts_tex = {  
        formatters_by_ft = {  
          tex = { "tex-fmt" },  
          bib = { "bibtex-tidy" },  
        }  
    },  
{  
    "neovim/nvim-lspconfig",  
    optional = true,  
    opts = {  
      servers = {  
        texlab = {  
          keys = {  
            { "<Leader>K", "<plug>(vimtex-doc-package)", desc = "Vimtex Docs", silent = true },  
          },  
        },  
      },  
    },  
  },

this is what i come up with based on the example, keep in mind i am new to vim and lua.

aliresool621 avatar Jun 17 '25 05:06 aliresool621

return {
  "lervag/vimtex",
  lazy = false,
  init = function()
    vim.g.tex_flavor = "latex"

    vim.g.vimtex_compiler_method = vim.fn.executable "latexmk" == 1 and "latexmk" or "tectonic"
    -- Configuration for latexmk compiler (primary)
    vim.g.vimtex_compiler_latexmk = {
      executable = "latexmk",
      options = {
        "-synctex=1",
        "-interaction=nonstopmode",
        "-lualatex", -- Use LuaLaTeX engine (recommended)
        -- "-pdflatex", -- Use PDFLaTeX engine
      },
    }
    -- Configuration for tectonic compiler (fallback)
    vim.g.vimtex_compiler_tectonic = {
      executable = "tectonic",
      options = {
        "-X",
        "compile",
        "--synctex",
        "--keep-logs",
        "--keep-intermediates",
      },
    }

    -- vim.g.vimtex_view_method = vim.fn.executable "zathura" == 1 and "zathura" or "general"

    vim.g.vimtex_quickfix_method = vim.fn.executable "pplatex" == 1 and "pplatex" or "latexlog"
    vim.g.vimtex_quickfix_mode = 2 -- Auto-open quickfix window on compilation errors
    vim.g.vimtex_quickfix_open_on_warning = 0 -- Don't open quickfix for warnings only

    vim.g.vimtex_doc_handlers = { "vimtex#doc#handlers#texdoc" } -- Use texdoc for documentation lookup

    vim.g.vimtex_matchparen_enabled = 0 -- Disable automatic parentheses matching highlight
    vim.g.vimtex_syntax_enabled = 0 -- Disable VimTeX syntax highlighting (use treesitter instead)
    vim.g.vimtex_syntax_conceal_disable = 1 -- Disable command concealing (show raw LaTeX)
    vim.g.vimtex_imaps_enabled = 0 -- Disable insert mode key mappings
    vim.g.vimtex_imaps_leader = ";" -- Set leader key for insert mappings (if enabled)
    vim.g.vimtex_mappings_disable = { ["n"] = { "K" } } -- Disable 'K' key mapping in normal mode
    vim.g.vimtex_fold_enabled = 0 -- Disable code folding for better performance
    vim.g.vimtex_echo_verbose_input = 0 -- Reduce command echoing verbosity
    vim.g.vimtex_env_change_autofill = 1 -- Auto-fill environment names when changing
    vim.g.vimtex_complete_enabled = 0 -- Disable built-in completion (use LSP instead)
  end,

  dependencies = {
    { -- Mason package manager integration
      "williamboman/mason.nvim",
      opts = function(_, opts)
        opts.ensure_installed = opts.ensure_installed or {}
        vim.list_extend(opts.ensure_installed, {
          "tectonic", -- Backup LaTeX compiler
          "texlab", -- LSP
          "latexindent", -- Code formatter
          "bibtex-tidy", -- Bibliography formatter
        })
      end,
    },
    -- LSP
    {
      "AstroNvim/astrolsp",
      opts = {
        config = {
          texlab = {
            settings = {
              texlab = {
                chktex = {
                  onOpenAndSave = true,
                  onEdit = true,
                },
              },
            },
          },
        },
      },
    },
    -- Treesitter
    {
      "nvim-treesitter/nvim-treesitter",
      opts = function(_, opts)
        opts.ensure_installed = opts.ensure_installed or {} -- Initialize parser list
        vim.list_extend(opts.ensure_installed, { -- Add LaTeX parsers
          "latex", -- LaTeX syntax parser
          "bibtex", -- BibTeX bibliography parser
        })
      end,
    },
    -- formatter
    {
      "stevearc/conform.nvim",
      opts = function(_, opts)
        opts.formatters_by_ft = opts.formatters_by_ft or {} -- Initialize filetype formatters
        opts.formatters = opts.formatters or {} -- Initialize formatter configurations

        opts.formatters_by_ft.tex = { "latexindent" } -- Use latexindent for .tex files
        opts.formatters_by_ft.sty = { "latexindent" } -- Use latexindent for .sty files
        opts.formatters_by_ft.cls = { "latexindent" } -- Use latexindent for .cls files
        opts.formatters_by_ft.bib = { "bibtex-tidy" } -- Use bibtex-tidy for .bib files

        opts.formatters.latexindent = {
          command = "latexindent",
          args = { "-" },
          stdin = true,
        }
        opts.formatters["bibtex-tidy"] = {
          command = "bibtex-tidy",
          args = { "--" },
          stdin = true,
        }
      end,
    },
  },
}

I asked DeepSeek to add comments to each line :)

This is the solution I come up with based on the example above, it works even if texlive isn't installed. But I couldn't find a way to make snacks.image to render math equations like in the example above.

assururuk avatar Aug 14 '25 10:08 assururuk

Just a FIY @assururuk, those comments are pretty much useless.

Uzaaft avatar Aug 14 '25 19:08 Uzaaft

Besides that. Lots of good ideas here, feel free to open a PR.

Uzaaft avatar Aug 14 '25 19:08 Uzaaft

Just a FIY @assururuk, those comments are pretty much useless.

yeah agreed

assururuk avatar Aug 15 '25 11:08 assururuk

Besides that. Lots of good ideas here, feel free to open a PR.

Final version

return {
  "lervag/vimtex",
  lazy = false,
  init = function()
    vim.g.tex_flavor = "latex"

    vim.g.vimtex_compiler_method = vim.fn.executable "latexmk" == 1 and "latexmk" or "tectonic"
    vim.g.vimtex_compiler_latexmk = { -- primary compiler
      executable = "latexmk",
      options = {
        "-verbose",
        "-file-line-error",
        "-synctex=1",
        "-interaction=nonstopmode",
        "-lualatex", -- Use LuaLaTeX engine (recommended)
        -- "-pdflatex", -- Use PDFLaTeX engine
      },
    }
    vim.g.vimtex_compiler_tectonic = { -- fallback compiler
      executable = "tectonic",
      options = {  
        "-X",
        "compile",
        "--synctex",
        "--keep-logs",
        "--keep-intermediates",
      },
    }

    vim.g.vimtex_view_method = vim.fn.executable "zathura" == 1 and "zathura" or "general"
    vim.g.vimtex_view_forward_search_on_start = false

    vim.g.vimtex_quickfix_method = vim.fn.executable "pplatex" == 1 and "pplatex" or "latexlog"
    vim.g.vimtex_quickfix_mode = 2
    vim.g.vimtex_quickfix_open_on_warning = 0

    vim.g.vimtex_doc_handlers = { "vimtex#doc#handlers#texdoc" } -- Use texdoc for documentation lookup
    vim.g.vimtex_matchparen_enabled = 0 -- Disable automatic parentheses matching highlight
    vim.g.vimtex_syntax_enabled = 0 -- Disable VimTeX syntax highlighting (use treesitter instead)
    vim.g.vimtex_syntax_conceal_disable = 1 -- Disable command concealing (show raw LaTeX)
    vim.g.vimtex_imaps_enabled = 0 -- Disable insert mode key mappings
    vim.g.vimtex_imaps_leader = ";" -- Set leader key for insert mappings (if enabled)
    vim.g.vimtex_mappings_disable = { ["n"] = { "K" } } -- Disable 'K' key mapping in normal mode
    vim.g.vimtex_fold_enabled = 0 -- Disable code folding for better performance
    vim.g.vimtex_echo_verbose_input = 0 -- Reduce command echoing verbosity
    vim.g.vimtex_env_change_autofill = 1 -- Auto-fill environment names when changing
    vim.g.vimtex_complete_enabled = 0 -- Disable built-in completion (use LSP instead)
  end,

  dependencies = {
    {
      "williamboman/mason.nvim",
      opts = function(_, opts)
        opts.ensure_installed = opts.ensure_installed or {}
        vim.list_extend(opts.ensure_installed, {
          "tectonic", -- fallback LaTeX compiler
          "texlab", -- LSP
          "latexindent", -- Code formatter
          "bibtex-tidy", -- bibliography formatter
        })
      end,
    },
    -- LSP
    {
      "AstroNvim/astrolsp",
      opts = {
        config = {
          texlab = {
            settings = {
              texlab = {
                chktex = {
                  onOpenAndSave = true,
                  onEdit = true,
                },
              },
            },
          },
        },
      },
    },
    -- Treesitter
    {
      "nvim-treesitter/nvim-treesitter",
      opts = function(_, opts)
        opts.ensure_installed = opts.ensure_installed or {}
        vim.list_extend(opts.ensure_installed, {
          "latex",
          "bibtex",
        })
      end,
    },
    -- formatter
    {
      "stevearc/conform.nvim",
      opts = function(_, opts)
        opts.formatters_by_ft = opts.formatters_by_ft or {}
        opts.formatters = opts.formatters or {}

        opts.formatters_by_ft.tex = { "latexindent" }
        opts.formatters_by_ft.sty = { "latexindent" }
        opts.formatters_by_ft.cls = { "latexindent" }
        opts.formatters_by_ft.bib = { "bibtex-tidy" }

        opts.formatters.latexindent = {
          command = "latexindent",
          args = { "-" },
          stdin = true,
        }
        opts.formatters["bibtex-tidy"] = {
          command = "bibtex-tidy",
          args = { "--" },
          stdin = true,
        }
      end,
    },
  },
}

This is based on this config, but it is incomplete as I am new to Neovim and programming, so I don't know what problems I created along the way, also it still requires:

  • integration with astrovim which-key and fixes for the conflicting keybinding. (even the old vimtex plugin keybinding doesn't work BTW)
  • beautiful inline Math Display like this.
  • the formatters are incomplete and left as is.
  • using markview.nvim, if it were loaded by the user maybe?

assururuk avatar Aug 15 '25 11:08 assururuk

return {
  { -- VimTeX
    "lervag/vimtex",
    ft = { "tex", "sty", "cls" },
    init = function()
      vim.g.vimtex_compiler_method = vim.fn.executable "latexmk" == 1 and "latexmk" or "tectonic"
      vim.g.vimtex_compiler_latexmk = { -- Primary compiler: latexmk
        executable = "latexmk",
        options = {
          "-synctex=1",
          "-interaction=nonstopmode",
          "-lualatex", -- LuaLaTeX (recommended for modern features)
          -- "-pdflatex", -- Alternative
        },
      }
      vim.g.vimtex_compiler_tectonic = { -- Fallback compiler: tectonic
        executable = "tectonic",
        options = {
          "--synctex",
          "--keep-logs",
          "--keep-intermediates",
        },
      }

      vim.g.vimtex_view_method = vim.fn.executable "zathura" == 1 and "zathura" or "general"
      vim.g.vimtex_view_forward_search_on_compile = true

      vim.g.vimtex_quickfix_method = vim.fn.executable "pplatex" == 1 and "pplatex" or "latexlog"
      vim.g.vimtex_quickfix_mode = 2

      vim.g.vimtex_syntax_enabled = 0
      vim.g.vimtex_indent_enabled = 0
    end,
  },

  { -- ensure all tools are installed
    "mason-org/mason.nvim",
    opts = function(_, opts)
      opts.ensure_installed = opts.ensure_installed or {}
      vim.list_extend(opts.ensure_installed, {
        "texlab",
        "tectonic",
        "latexindent",
        "bibtex-tidy",
        "ltex-ls-plus",
      })
    end,
  },

  { -- LSP
    "AstroNvim/astrolsp",
    opts = {
      config = {
        texlab = {
          settings = {
            texlab = {
              build = { executable = "false", onSave = false },
              forwardSearch = { executable = "false", onSave = false },
              latexFormatter = { executable = "false", onSave = false },
              chktex = { onOpenAndSave = true, onEdit = false },
            },
          },
        },
        ltex_plus = {
          filetypes = { "tex", "sty", "cls", "bib" },
          settings = {
            ltex = {
              enabled = { "tex", "sty", "cls", "bib" },
              language = "en",
              additionalRules = {
                enablePickyRules = true,
                motherTongue = "en",
              },
              diagnostics = { severity = "information" },
              completion = { enabled = false },
            },
          },
        },
      },
    },
  },

  { -- Formatting
    "stevearc/conform.nvim",
    opts = {
      formatters_by_ft = {
        tex = { "latexindent" },
        sty = { "latexindent" },
        cls = { "latexindent" },
        bib = { "bibtex-tidy" },
      },
      formatters = {
        latexindent = { prepend_args = { "-g", "/dev/null" } },
      },
    },
    init = function()
      vim.api.nvim_create_autocmd("BufWritePre", {
        pattern = { "*.tex", "*.sty", "*.cls", "*.bib" },
        callback = function(args) require("conform").format { bufnr = args.buf } end,
      })
    end,
  },

  { -- Treesitter
    "nvim-treesitter/nvim-treesitter",
    opts = function(_, opts)
      opts.ensure_installed = opts.ensure_installed or {}
      vim.list_extend(opts.ensure_installed, { "latex", "bibtex" })
    end,
  },

  { -- inline math / images rendring
    "folke/snacks.nvim",
    dependencies = { "nvim-treesitter/nvim-treesitter" },
    opts = {
      image = {
        enabled = true,
        doc = {
          enabled = true,
          inline = false,
          float = true,
          max_width = 80,
          max_height = 40,
        },
        math = {
          enabled = true,
          latex = {
            font_size = "Large",
            packages = { "amsmath", "amssymb", "amsfonts", "amscd", "mathtools" },
          },
        },
      },
    },
  },
}

This still needs integration with which-key for the keybindings and the formatters are incomplete.

As for snacks.image i couldn't get it to conceal the text under the images / math equation, but it worked perfectly on lazyvim for some reason 🤷 ... in the end, i put all images in a floating window.

you could use markview for text conceal or anything you prefer.

assur-akad avatar Nov 15 '25 10:11 assur-akad