From 43d6abad480185f1285be19f9516269882eaa686 Mon Sep 17 00:00:00 2001 From: Dane Sabo Date: Wed, 20 May 2026 10:59:08 -0400 Subject: [PATCH] Split markdown_and_tex into per-language modules; add cadquery autorun - Split lua/custom/language_specific_commands/markdown_and_tex.lua into markdown.lua, tex.lua, and a shared nabla_setup.lua - Add cadquery.lua: auto-render on save for ~/Documents/cad scripts via the project venv, with notifications and a cr manual trigger - tex.lua: add \textcolor{blue|red|green}{...} operator + visual maps (t{b,r,g}, tx to remove); set textwidth=80, spell on - markdown.lua: spell on, textwidth=60, nabla setup hook - vimtex: switch to latexmk + lualatex with continuous compile and synctex; PDF viewer = skim with sync/activate - lspconfig: enable julia_ls and texlab; add julialsp + texlab to Mason ensure_installed - chadrc: theme -> ayu_dark - init.lua: ghcup PATH to macOS location; load cadquery module; comment out taskwarrior (replaced by openclaw agent); add updatetime and sessionoptions for CursorHold + auto-session --- lazy-lock.json | 36 ++--- lua/custom/chadrc.lua | 4 +- lua/custom/configs/lspconfig.lua | 56 +++---- lua/custom/init.lua | 7 +- .../language_specific_commands/cadquery.lua | 76 +++++++++ .../language_specific_commands/markdown.lua | 36 +++++ .../markdown_and_tex.lua | 65 -------- .../language_specific_commands/matlab.lua | 3 +- .../nabla_setup.lua | 45 ++++++ .../language_specific_commands/rust.lua | 2 +- lua/custom/language_specific_commands/tex.lua | 153 ++++++++++++++++++ lua/custom/plugins.lua | 27 +++- lua/plugins/configs/lspconfig.lua | 135 ++++++++-------- 13 files changed, 459 insertions(+), 186 deletions(-) create mode 100644 lua/custom/language_specific_commands/cadquery.lua create mode 100644 lua/custom/language_specific_commands/markdown.lua delete mode 100644 lua/custom/language_specific_commands/markdown_and_tex.lua create mode 100644 lua/custom/language_specific_commands/nabla_setup.lua create mode 100644 lua/custom/language_specific_commands/tex.lua diff --git a/lazy-lock.json b/lazy-lock.json index b00281c..e0fc12b 100644 --- a/lazy-lock.json +++ b/lazy-lock.json @@ -1,39 +1,39 @@ { "Comment.nvim": { "branch": "master", "commit": "e30b7f2008e52442154b66f7c519bfd2f1e32acb" }, - "LuaSnip": { "branch": "master", "commit": "21f74f7ba8c49f95f9d7c8293b147c2901dd2d3a" }, - "auto-session": { "branch": "main", "commit": "3b5d8947cf16ac582ef00443ede4cdd3dfa23af9" }, + "LuaSnip": { "branch": "master", "commit": "dae4f5aaa3574bd0c2b9dd20fb9542a02c10471c" }, + "auto-session": { "branch": "main", "commit": "292492ab7af4bd8b9e37e28508bc8ce995722fd5" }, "base46": { "branch": "v2.0", "commit": "85de6cdb2d3c85d0aee53aea0569e73fdaf3df4e" }, "cmp-buffer": { "branch": "main", "commit": "b74fab3656eea9de20a9b8116afa3cfc4ec09657" }, - "cmp-nvim-lsp": { "branch": "main", "commit": "bd5a7d6db125d4654b50eeae9f5217f24bb22fd3" }, - "cmp-nvim-lua": { "branch": "main", "commit": "f12408bdb54c39c23e67cab726264c10db33ada8" }, + "cmp-nvim-lsp": { "branch": "main", "commit": "cbc7b02bb99fae35cb42f514762b89b5126651ef" }, + "cmp-nvim-lua": { "branch": "main", "commit": "e3a22cb071eb9d6508a156306b102c45cd2d573d" }, "cmp-path": { "branch": "main", "commit": "c642487086dbd9a93160e1679a1327be111cbc25" }, "cmp_luasnip": { "branch": "master", "commit": "98d9cb5c2c38532bd9bdb481067b20fea8f32e90" }, - "conform.nvim": { "branch": "master", "commit": "b4aab989db276993ea5dcb78872be494ce546521" }, + "conform.nvim": { "branch": "master", "commit": "c2526f1cde528a66e086ab1668e996d162c75f4f" }, "crates.nvim": { "branch": "main", "commit": "ac9fa498a9edb96dc3056724ff69d5f40b898453" }, "friendly-snippets": { "branch": "main", "commit": "572f5660cf05f8cd8834e096d7b4c921ba18e175" }, - "gitsigns.nvim": { "branch": "main", "commit": "6e3c66548035e50db7bd8e360a29aec6620c3641" }, + "gitsigns.nvim": { "branch": "main", "commit": "42d6aed4e94e0f0bbced16bbdcc42f57673bd75e" }, "indent-blankline.nvim": { "branch": "master", "commit": "b7aa0aed55887edfaece23f7b46ab22232fc8741" }, - "lazy.nvim": { "branch": "main", "commit": "6c3bda4aca61a13a9c63f1c1d1b16b9d3be90d7a" }, - "mason.nvim": { "branch": "main", "commit": "7dc4facca9702f95353d5a1f87daf23d78e31c2a" }, + "lazy.nvim": { "branch": "main", "commit": "306a05526ada86a7b30af95c5cc81ffba93fef97" }, + "mason.nvim": { "branch": "main", "commit": "44d1e90e1f66e077268191e3ee9d2ac97cc18e65" }, "nabla.nvim": { "branch": "master", "commit": "9b69b709063ccf40ac36fabb4fff7d90b3736475" }, - "nvim-autopairs": { "branch": "master", "commit": "23320e75953ac82e559c610bec5a90d9c6dfa743" }, - "nvim-cmp": { "branch": "main", "commit": "b5311ab3ed9c846b585c0c15b7559be131ec4be9" }, - "nvim-colorizer.lua": { "branch": "master", "commit": "51cf7c995ed1eb6642aecf19067ee634fa1b6ba2" }, - "nvim-dap": { "branch": "master", "commit": "7523676a4be17644587aa47e4d42f6f7646d4727" }, + "nvim-autopairs": { "branch": "master", "commit": "c2a0dd0d931d0fb07665e1fedb1ea688da3b80b4" }, + "nvim-cmp": { "branch": "main", "commit": "85bbfad83f804f11688d1ab9486b459e699292d6" }, + "nvim-colorizer.lua": { "branch": "master", "commit": "81e676d3203c9eb6e4c0ccf1eba1679296ef923f" }, + "nvim-dap": { "branch": "master", "commit": "085386b9359ddf8d76ad89b98973b8e332dc5ba3" }, "nvim-dap-virtual-text": { "branch": "master", "commit": "fbdb48c2ed45f4a8293d0d483f7730d24467ccb6" }, - "nvim-lspconfig": { "branch": "master", "commit": "c8b90ae5cbe21d547b342b05c9266dcb8ca0de8f" }, + "nvim-lspconfig": { "branch": "master", "commit": "92ee7d42320edfbb81f3cad851314ab197fa324a" }, "nvim-notify": { "branch": "master", "commit": "8701bece920b38ea289b457f902e2ad184131a5d" }, - "nvim-tree.lua": { "branch": "master", "commit": "e179ad2f83b5955ab0af653069a493a1828c2697" }, + "nvim-tree.lua": { "branch": "master", "commit": "ca8d82fff26cb12ced239713e3222f4a9dcd0da0" }, "nvim-treesitter": { "branch": "master", "commit": "42fc28ba918343ebfd5565147a42a26580579482" }, - "nvim-web-devicons": { "branch": "master", "commit": "6e51ca170563330e063720449c21f43e27ca0bc1" }, + "nvim-web-devicons": { "branch": "master", "commit": "803353450c374192393f5387b6a0176d0972b848" }, "nvterm": { "branch": "main", "commit": "9d7ba3b6e368243175d38e1ec956e0476fd86ed9" }, "plenary.nvim": { "branch": "master", "commit": "b9fd5226c2f76c951fc8ed5923d85e4de065e509" }, "rust.vim": { "branch": "master", "commit": "889b9a7515db477f4cb6808bef1769e53493c578" }, "rustaceanvim": { "branch": "master", "commit": "047f9c9d8cd2861745eb9de6c1570ee0875aa795" }, - "telescope.nvim": { "branch": "master", "commit": "b4da76be54691e854d3e0e02c36b0245f945c2c7" }, + "telescope.nvim": { "branch": "master", "commit": "0d8b6eaa0b5ae6bb3d9785f7a3ba4a4c6c1b1af2" }, "tla.nvim": { "branch": "master", "commit": "1752abe9b7dec23a26ff11a629e2ee88e66c366b" }, "ui": { "branch": "v2.0", "commit": "d4f7e64892a24075d5fdd5a58bd0db45e86e38ed" }, "vim-tla": { "branch": "master", "commit": "220145ef791ac8d64d2c319eb2940b59da17d6ca" }, - "vimtex": { "branch": "master", "commit": "dc90feacb86f7b85b0b791d8073eefc769a23725" }, - "which-key.nvim": { "branch": "main", "commit": "370ec46f710e058c9c1646273e6b225acf47cbed" } + "vimtex": { "branch": "master", "commit": "f707368022cdb851716be0d2970b90599c84a6a6" }, + "which-key.nvim": { "branch": "main", "commit": "3aab2147e74890957785941f0c1ad87d0a44c15a" } } diff --git a/lua/custom/chadrc.lua b/lua/custom/chadrc.lua index 92e3002..207acc1 100644 --- a/lua/custom/chadrc.lua +++ b/lua/custom/chadrc.lua @@ -7,8 +7,8 @@ M.ui = { hl_add = {}, hl_override = {}, changed_themes = {}, - theme_toggle = { "tokyodark", "one_light" }, - theme = "tokyodark", -- default theme + theme_toggle = { "ayu_dark", "ayu_dark" }, + theme = "ayu_dark", -- default theme transparency = false, lsp_semantic_tokens = false, -- needs nvim v0.9, just adds highlight groups for lsp semantic tokens diff --git a/lua/custom/configs/lspconfig.lua b/lua/custom/configs/lspconfig.lua index ba179fd..9d45d53 100644 --- a/lua/custom/configs/lspconfig.lua +++ b/lua/custom/configs/lspconfig.lua @@ -3,43 +3,45 @@ local config = require "plugins.configs.lspconfig" local on_attach = config.on_attach local capabilities = config.capabilities -local lspconfig = require "lspconfig" - -lspconfig.jedi_language_server.setup { +local common = { on_attach = on_attach, capabilities = capabilities, +} + +vim.lsp.config("jedi_language_server", vim.tbl_extend("force", common, { filetypes = { "python" }, -} +})) +vim.lsp.enable("jedi_language_server") -lspconfig.hls.setup { - on_attach = on_attach, - capabilities = capabilities, +vim.lsp.config("hls", vim.tbl_extend("force", common, { filetypes = { "haskell", "lhaskell", "cabal" }, -} +})) +vim.lsp.enable("hls") -lspconfig.matlab_ls.setup { - on_attach = on_attach, - capabilities = capabilities, +require "custom.language_specific_commands.matlab" +vim.lsp.config("matlab_ls", vim.tbl_extend("force", common, { filetypes = { "matlab" }, - require "custom.language_specific_commands.matlab", -} +})) +vim.lsp.enable("matlab_ls") -lspconfig.clangd.setup { - on_attach = on_attach, - capabilities = capabilities, +vim.lsp.config("clangd", vim.tbl_extend("force", common, { filetypes = { "c", "cpp" }, -} +})) +vim.lsp.enable("clangd") -lspconfig.marksman.setup { - on_attach = on_attach, - capabilities = capabilities, +require "custom.language_specific_commands.markdown" +vim.lsp.config("marksman", vim.tbl_extend("force", common, { filetypes = { "markdown" }, - require "custom.language_specific_commands.markdown_and_tex", -} +})) +vim.lsp.enable("marksman") -lspconfig.texlab.setup { - on_attach = on_attach, - capabilities = capabilities, +require "custom.language_specific_commands.tex" +vim.lsp.config("texlab", vim.tbl_extend("force", common, { filetypes = { "tex" }, - require "custom.language_specific_commands.markdown_and_tex", -} +})) +vim.lsp.enable("texlab") + +vim.lsp.config("julia_ls", vim.tbl_extend("force", common, { + filetypes = { "julia" }, +})) +vim.lsp.enable("julia_ls") diff --git a/lua/custom/init.lua b/lua/custom/init.lua index ebbfe84..6fe5dbf 100644 --- a/lua/custom/init.lua +++ b/lua/custom/init.lua @@ -1,12 +1,15 @@ vim.g.dap_virtual_text = false vim.g.tlaplus_mappings_enable = true -vim.env.PATH = vim.env.PATH .. ":/home/danesabo/.ghcup/bin" +vim.env.PATH = vim.env.PATH .. ":/Users/danesabo/.ghcup/bin" vim.g.loaded_python3_provider = 1 vim.g.python3_host_prog = vim.fn.expand "~/.config/nvim/nvim_venv/bin/python" vim.keymap.set("i", "jj", "") +vim.opt.updatetime = 1000 -- 1 second delay for CursorHold events +vim.o.sessionoptions = "blank,buffers,curdir,folds,help,tabpages,winsize,winpos,terminal,localoptions" +require "custom.language_specific_commands.cadquery" require "custom.zk" require "custom.git_quickpush" require "custom.journal" -require "custom.taskwarrior" +-- require "custom.taskwarrior" -- replaced by openclaw agent print "Custom init settings loaded." diff --git a/lua/custom/language_specific_commands/cadquery.lua b/lua/custom/language_specific_commands/cadquery.lua new file mode 100644 index 0000000..0da5e07 --- /dev/null +++ b/lua/custom/language_specific_commands/cadquery.lua @@ -0,0 +1,76 @@ +-- ~/.config/nvim/lua/custom/language_specific_commands/cadquery.lua +-- Auto-run CadQuery scripts on save, sending output to the OCP viewer. + +local GRP = vim.api.nvim_create_augroup("CadQueryViewer", { clear = true }) + +local cad_venv = vim.fn.expand "~/Documents/cad/.venv/bin/python" +local cad_dir = vim.fn.expand "~/Documents/cad" + +local function is_cad_file(filepath) + return filepath:match("%.py$") and filepath:find(cad_dir, 1, true) == 1 +end + +local function run_cadquery(buf) + local filepath = vim.api.nvim_buf_get_name(buf) + if filepath == "" or not is_cad_file(filepath) then + return + end + + vim.notify("Rendering: " .. vim.fn.fnamemodify(filepath, ":t"), vim.log.levels.INFO, { title = "CadQuery" }) + + vim.fn.jobstart({ cad_venv, filepath }, { + stdout_buffered = true, + stderr_buffered = true, + on_stdout = function(_, data) + if data and data[1] ~= "" then + vim.schedule(function() + vim.notify(table.concat(data, "\n"), vim.log.levels.INFO, { title = "CadQuery" }) + end) + end + end, + on_stderr = function(_, data) + if data and data[1] ~= "" then + local msg = table.concat(data, "\n") + -- Filter out noisy OCP viewer warnings + if msg:match("CameraKeep") or msg:match("reset_camera") or msg:match("collapse value") then + return + end + vim.schedule(function() + vim.notify(msg, vim.log.levels.WARN, { title = "CadQuery" }) + end) + end + end, + on_exit = function(_, code) + vim.schedule(function() + if code == 0 then + vim.notify("Model updated", vim.log.levels.INFO, { title = "CadQuery" }) + else + vim.notify("Render failed (exit " .. code .. ")", vim.log.levels.ERROR, { title = "CadQuery" }) + end + end) + end, + }) +end + +-- Auto-run on save for any .py file under ~/Documents/cad/ +vim.api.nvim_create_autocmd("BufWritePost", { + group = GRP, + pattern = "*.py", + callback = function(args) + run_cadquery(args.buf) + end, +}) + +-- Manual trigger: cr (cad render) +vim.api.nvim_create_autocmd("BufEnter", { + group = GRP, + pattern = "*.py", + callback = function(args) + local filepath = vim.api.nvim_buf_get_name(args.buf) + if is_cad_file(filepath) then + vim.keymap.set("n", "cr", function() + run_cadquery(args.buf) + end, { buffer = args.buf, desc = "CadQuery: render model" }) + end + end, +}) diff --git a/lua/custom/language_specific_commands/markdown.lua b/lua/custom/language_specific_commands/markdown.lua new file mode 100644 index 0000000..e47f8f4 --- /dev/null +++ b/lua/custom/language_specific_commands/markdown.lua @@ -0,0 +1,36 @@ +-- ~/.config/nvim/lua/custom/language_specific_commands/markdown.lua + +local GRP = vim.api.nvim_create_augroup("MarkdownWithNabla", { clear = true }) +local nabla_setup = require "custom.language_specific_commands.nabla_setup" + +-- Buffer-local settings for Markdown +vim.api.nvim_create_autocmd("FileType", { + group = GRP, + pattern = { "markdown" }, + callback = function(args) + -- Buffer-local basics + vim.opt_local.spell = true + vim.opt_local.spelllang = "en_us" + vim.opt_local.formatoptions:append "t" + vim.opt_local.textwidth = 60 + + -- Setup Nabla (conceal settings + keymaps) + nabla_setup.setup(args.buf) + end, +}) + +-- Re-enable Nabla virtual text after writes (if cleared) +vim.api.nvim_create_autocmd("BufWritePost", { + group = GRP, + pattern = { "*.md", "*.mdx", "*.markdown" }, + callback = function(args) + local ft = vim.bo[args.buf].filetype + if ft ~= "markdown" or not vim.b[args.buf].nabla_enabled then + return + end + local ok_nabla, nabla = pcall(require, "nabla") + if ok_nabla then + nabla.enable_virt() + end + end, +}) diff --git a/lua/custom/language_specific_commands/markdown_and_tex.lua b/lua/custom/language_specific_commands/markdown_and_tex.lua deleted file mode 100644 index b563224..0000000 --- a/lua/custom/language_specific_commands/markdown_and_tex.lua +++ /dev/null @@ -1,65 +0,0 @@ --- ~/.config/nvim/lua/custom/language_specific_commands/markdown_and_tex.lua - -local GRP = vim.api.nvim_create_augroup("MarkdownTexWithNabla", { clear = true }) - --- 1) Buffer-local settings: set ONCE per buffer -vim.api.nvim_create_autocmd("FileType", { - group = GRP, - pattern = { "markdown", "tex" }, - callback = function(args) - local ft = vim.bo[args.buf].filetype - - -- Buffer-local basics - vim.opt_local.spell = true - vim.opt_local.spelllang = "en_us" - vim.opt_local.formatoptions:append "t" - - if ft == "markdown" then - vim.opt_local.textwidth = 60 - else - vim.opt_local.textwidth = 80 - end - - -- Buffer-local conceal (instead of window-local) - vim.opt_local.conceallevel = 2 - vim.opt_local.concealcursor = "ic" -- reveal on hover in normal mode - - -- Buffer-local Nabla keymaps (define once per buffer) - if not vim.b[args.buf].nabla_keys then - local ok_nabla, nabla = pcall(require, "nabla") - if ok_nabla then - local bufopts = { buffer = args.buf, silent = true } - vim.keymap.set("n", "mnve", function() - nabla.enable_virt() - end, vim.tbl_extend("force", bufopts, { desc = "Nabla: render math (virtual text)" })) - vim.keymap.set("n", "mnvd", function() - nabla.disable_virt() - end, vim.tbl_extend("force", bufopts, { desc = "Nabla: clear rendering" })) - vim.keymap.set("n", "mnp", function() - nabla.popup() - end, vim.tbl_extend("force", bufopts, { desc = "Nabla: popup under cursor" })) - - -- initial enable - nabla.enable_virt() - vim.b[args.buf].nabla_enabled = true - end - vim.b[args.buf].nabla_keys = true - end - end, -}) - --- 2) Re-enable Nabla virtual text after writes (if cleared) -vim.api.nvim_create_autocmd("BufWritePost", { - group = GRP, - pattern = { "*.md", "*.mdx", "*.markdown", "*.tex", "*.ltx" }, - callback = function(args) - local ft = vim.bo[args.buf].filetype - if (ft ~= "markdown" and ft ~= "tex") or not vim.b[args.buf].nabla_enabled then - return - end - local ok_nabla, nabla = pcall(require, "nabla") - if ok_nabla then - nabla.enable_virt() - end - end, -}) diff --git a/lua/custom/language_specific_commands/matlab.lua b/lua/custom/language_specific_commands/matlab.lua index b2f8dd8..0bfa5a2 100644 --- a/lua/custom/language_specific_commands/matlab.lua +++ b/lua/custom/language_specific_commands/matlab.lua @@ -58,8 +58,7 @@ end, { desc = "Prepend '%[' to each line (MATLAB Live Script style)", }) --- map mc in normal+visual to comment -vim.keymap.set("n", "mc", ":'<,'>CommentLive", { noremap = true, silent = true }) +-- map mc in visual mode to comment (only works with selection) vim.keymap.set("v", "mc", ":CommentLive", { noremap = true, silent = true }) print "MATLAB Keybinds & Live‑Script Commenter Loaded" diff --git a/lua/custom/language_specific_commands/nabla_setup.lua b/lua/custom/language_specific_commands/nabla_setup.lua new file mode 100644 index 0000000..334468e --- /dev/null +++ b/lua/custom/language_specific_commands/nabla_setup.lua @@ -0,0 +1,45 @@ +-- ~/.config/nvim/lua/custom/language_specific_commands/nabla_setup.lua + +local M = {} + +-- Setup Nabla for a buffer +function M.setup(bufnr) + -- Skip if already set up + if vim.b[bufnr].nabla_keys then + return + end + + -- Buffer-local conceal settings (disabled so you always see raw LaTeX) + vim.opt_local.conceallevel = 0 + vim.opt_local.concealcursor = "" -- always reveal when cursor is on line + + -- Try to load Nabla + local ok_nabla, nabla = pcall(require, "nabla") + if not ok_nabla then + return + end + + local bufopts = { buffer = bufnr, silent = true } + + -- Toggle keymap - turns Nabla rendering on/off + vim.keymap.set("n", "mnt", function() + if vim.b[bufnr].nabla_enabled then + nabla.disable_virt() + vim.b[bufnr].nabla_enabled = false + else + nabla.enable_virt() + vim.b[bufnr].nabla_enabled = true + end + end, vim.tbl_extend("force", bufopts, { desc = "Nabla: toggle math rendering" })) + + -- Popup for spot-checking (great for multi-line math) + vim.keymap.set("n", "mnp", function() + nabla.popup() + end, vim.tbl_extend("force", bufopts, { desc = "Nabla: popup under cursor" })) + + -- Don't auto-enable, let user toggle when needed + vim.b[bufnr].nabla_enabled = false + vim.b[bufnr].nabla_keys = true +end + +return M diff --git a/lua/custom/language_specific_commands/rust.lua b/lua/custom/language_specific_commands/rust.lua index 516d58e..884c06b 100644 --- a/lua/custom/language_specific_commands/rust.lua +++ b/lua/custom/language_specific_commands/rust.lua @@ -1,7 +1,7 @@ local function open_float_terminal_with_command(cmd) -- 1. Create a scratch buffer (not listed, no file) local buf = vim.api.nvim_create_buf(false, true) - vim.api.nvim_buf_set_option(buf, "bufhidden", "wipe") + vim.bo[buf].bufhidden = "wipe" -- 2. Get the dimensions of the current window (the active split) local cur_width = vim.api.nvim_win_get_width(0) diff --git a/lua/custom/language_specific_commands/tex.lua b/lua/custom/language_specific_commands/tex.lua new file mode 100644 index 0000000..8969818 --- /dev/null +++ b/lua/custom/language_specific_commands/tex.lua @@ -0,0 +1,153 @@ +-- ~/.config/nvim/lua/custom/language_specific_commands/tex.lua + +local GRP = vim.api.nvim_create_augroup("TeXWithNabla", { clear = true }) +local nabla_setup = require "custom.language_specific_commands.nabla_setup" + +-- Textcolor highlight operator: wraps motions/selections in \textcolor{color}{...} +local function make_textcolor_op(color) + return function(type) + local s = vim.api.nvim_buf_get_mark(0, "[") + local e = vim.api.nvim_buf_get_mark(0, "]") + local lines = vim.api.nvim_buf_get_lines(0, s[1] - 1, e[1], false) + if #lines == 0 then return end + + if type == "char" then + lines[#lines] = lines[#lines]:sub(1, e[2] + 1) + lines[1] = lines[1]:sub(s[2] + 1) + local text = table.concat(lines, "\n") + local wrapped = string.format("\\textcolor{%s}{%s}", color, text) + vim.api.nvim_buf_set_text(0, s[1] - 1, s[2], e[1] - 1, e[2] + 1, vim.split(wrapped, "\n")) + elseif type == "line" then + local text = table.concat(lines, "\n") + local wrapped = string.format("\\textcolor{%s}{%s}", color, text) + vim.api.nvim_buf_set_lines(0, s[1] - 1, e[1], false, vim.split(wrapped, "\n")) + end + end +end + +local textcolor_colors = { + b = "blue", + r = "red", + g = "green", +} + +-- Register global functions so operatorfunc can reference them via v:lua +for key, color in pairs(textcolor_colors) do + _G["_textcolor_" .. color] = make_textcolor_op(color) +end + +-- Check if cursor is currently inside a \textcolor{...}{...} block +local function cursor_in_textcolor() + local save = vim.fn.winsaveview() + if vim.fn.search("\\\\textcolor{", "bcW") == 0 then + vim.fn.winrestview(save) + return false + end + -- Navigate through both brace pairs to find the end of the block + vim.fn.search("{", "cW") + vim.cmd("normal! %") + vim.fn.search("{", "W") + vim.cmd("normal! %") + local end_pos = vim.api.nvim_win_get_cursor(0) + vim.fn.winrestview(save) + -- Original cursor must be at or before the closing } + if save.lnum < end_pos[1] or (save.lnum == end_pos[1] and save.col <= end_pos[2]) then + return true + end + return false +end + +-- Change color of surrounding \textcolor{old}{...} to a new color +local function change_textcolor(new_color) + local save = vim.fn.winsaveview() + vim.fn.search("\\\\textcolor{", "bcW") + vim.fn.search("{", "cW") + local bpos = vim.api.nvim_win_get_cursor(0) + local color_row, color_col = bpos[1] - 1, bpos[2] + 1 + vim.cmd("normal! %") + local epos = vim.api.nvim_win_get_cursor(0) + local end_row, end_col = epos[1] - 1, epos[2] + vim.api.nvim_buf_set_text(0, color_row, color_col, end_row, end_col, { new_color }) + vim.fn.winrestview(save) +end + +-- Remove \textcolor{...}{content} wrapper, keeping content +local function remove_textcolor() + if not cursor_in_textcolor() then + vim.notify("No \\textcolor found", vim.log.levels.WARN) + return + end + local save = vim.fn.winsaveview() + vim.fn.search("\\\\textcolor{", "bcW") + local pos = vim.api.nvim_win_get_cursor(0) + local start_row, start_col = pos[1] - 1, pos[2] + vim.fn.search("{", "cW") + vim.cmd("normal! %") + vim.fn.search("{", "W") + local cpos = vim.api.nvim_win_get_cursor(0) + local content_row, content_col = cpos[1] - 1, cpos[2] + vim.cmd("normal! %") + local epos = vim.api.nvim_win_get_cursor(0) + local end_row, end_col = epos[1] - 1, epos[2] + local content = vim.api.nvim_buf_get_text(0, content_row, content_col + 1, end_row, end_col, {}) + vim.api.nvim_buf_set_text(0, start_row, start_col, end_row, end_col + 1, content) + vim.fn.winrestview(save) +end + +-- Buffer-local settings for TeX +vim.api.nvim_create_autocmd("FileType", { + group = GRP, + pattern = { "tex" }, + callback = function(args) + local buf = args.buf + + -- Buffer-local basics + vim.opt_local.spell = true + vim.opt_local.spelllang = "en_us" + vim.opt_local.formatoptions:append "t" + vim.opt_local.textwidth = 80 + + -- Textcolor keymaps: t{b,r,g} + -- Normal: if inside a \textcolor, switch color; otherwise operator + motion + -- Visual: always wrap selection + for key, color in pairs(textcolor_colors) do + local fname = "v:lua._textcolor_" .. color + + vim.keymap.set("n", "t" .. key, function() + if cursor_in_textcolor() then + change_textcolor(color) + else + vim.o.operatorfunc = fname + vim.api.nvim_feedkeys("g@", "n", false) + end + end, { buffer = buf, desc = "\\textcolor{" .. color .. "} (or switch)" }) + + vim.keymap.set("x", "t" .. key, function() + vim.o.operatorfunc = fname + return "g@" + end, { expr = true, buffer = buf, desc = "\\textcolor{" .. color .. "}" }) + end + + -- Remove textcolor wrapper entirely + vim.keymap.set("n", "tx", remove_textcolor, { buffer = buf, desc = "Remove \\textcolor wrapper" }) + + -- Setup Nabla (conceal settings + keymaps) + nabla_setup.setup(buf) + end, +}) + +-- Re-enable Nabla virtual text after writes (if cleared) +vim.api.nvim_create_autocmd("BufWritePost", { + group = GRP, + pattern = { "*.tex", "*.ltx" }, + callback = function(args) + local ft = vim.bo[args.buf].filetype + if ft ~= "tex" or not vim.b[args.buf].nabla_enabled then + return + end + local ok_nabla, nabla = pcall(require, "nabla") + if ok_nabla then + nabla.enable_virt() + end + end, +}) diff --git a/lua/custom/plugins.lua b/lua/custom/plugins.lua index 8f413a8..6741581 100644 --- a/lua/custom/plugins.lua +++ b/lua/custom/plugins.lua @@ -14,6 +14,8 @@ local plugins = { "marksman", "ruff", "jedi-language-server", + "julialsp", + "texlab", --- formatters "stylua", @@ -27,6 +29,7 @@ local plugins = { }, { "neovim/nvim-lspconfig", + event = "User FilePost", config = function() require "plugins.configs.lspconfig" require "custom.configs.lspconfig" @@ -185,8 +188,28 @@ local plugins = { lazy = false, -- we don't want to lazy load VimTeX -- tag = "v2.15", -- uncomment to pin to a specific release init = function() - -- VimTeX configuration goes here, e.g. - vim.g.vimtex_view_method = "zathura" + -- Set the compiler to latexmk which will respect the % !TEX program directive + vim.g.vimtex_compiler_method = "latexmk" + + -- Configure latexmk to use lualatex by default + vim.g.vimtex_compiler_latexmk = { + build_dir = "", + callback = 1, + continuous = 1, + executable = "latexmk", + options = { + "-lualatex", -- Use lualatex + "-verbose", + "-file-line-error", + "-synctex=1", + "-interaction=nonstopmode", + }, + } + + -- Set PDF viewer (optional - adjust for your system) + vim.g.vimtex_view_method = "skim" -- or 'zathura', 'general', etc. + vim.g.vimtex_view_skim_sync = 1 + vim.g.vimtex_view_skim_activate = 1 end, }, diff --git a/lua/plugins/configs/lspconfig.lua b/lua/plugins/configs/lspconfig.lua index 706c3a9..83e5124 100644 --- a/lua/plugins/configs/lspconfig.lua +++ b/lua/plugins/configs/lspconfig.lua @@ -1,67 +1,68 @@ -dofile(vim.g.base46_cache .. "lsp") -require "nvchad.lsp" - -local M = {} -local utils = require "core.utils" - --- export on_attach & capabilities for custom lspconfigs -M.on_attach = function(client, bufnr) - utils.load_mappings("lspconfig", { buffer = bufnr }) - - if client.server_capabilities.signatureHelpProvider then - require("nvchad.signature").setup(client) - end -end - --- disable semantic tokens -M.on_init = function(client, _) - if not utils.load_config().ui.lsp_semantic_tokens and client.supports_method "textDocument/semanticTokens" then - client.server_capabilities.semanticTokensProvider = nil - end -end - -M.capabilities = vim.lsp.protocol.make_client_capabilities() - -M.capabilities.textDocument.completion.completionItem = { - documentationFormat = { "markdown", "plaintext" }, - snippetSupport = true, - preselectSupport = true, - insertReplaceSupport = true, - labelDetailsSupport = true, - deprecatedSupport = true, - commitCharactersSupport = true, - tagSupport = { valueSet = { 1 } }, - resolveSupport = { - properties = { - "documentation", - "detail", - "additionalTextEdits", - }, - }, -} - -require("lspconfig").lua_ls.setup { - on_init = M.on_init, - on_attach = M.on_attach, - capabilities = M.capabilities, - - settings = { - Lua = { - diagnostics = { - globals = { "vim" }, - }, - workspace = { - library = { - [vim.fn.expand "$VIMRUNTIME/lua"] = true, - [vim.fn.expand "$VIMRUNTIME/lua/vim/lsp"] = true, - [vim.fn.stdpath "data" .. "/lazy/ui/nvchad_types"] = true, - [vim.fn.stdpath "data" .. "/lazy/lazy.nvim/lua/lazy"] = true, - }, - maxPreload = 100000, - preloadFileSize = 10000, - }, - }, - }, -} - -return M +dofile(vim.g.base46_cache .. "lsp") +require "nvchad.lsp" + +local M = {} +local utils = require "core.utils" + +-- export on_attach & capabilities for custom lspconfigs +M.on_attach = function(client, bufnr) + utils.load_mappings("lspconfig", { buffer = bufnr }) + + if client.server_capabilities.signatureHelpProvider then + require("nvchad.signature").setup(client) + end +end + +-- disable semantic tokens +M.on_init = function(client, _) + if not utils.load_config().ui.lsp_semantic_tokens and client.supports_method "textDocument/semanticTokens" then + client.server_capabilities.semanticTokensProvider = nil + end +end + +M.capabilities = vim.lsp.protocol.make_client_capabilities() + +M.capabilities.textDocument.completion.completionItem = { + documentationFormat = { "markdown", "plaintext" }, + snippetSupport = true, + preselectSupport = true, + insertReplaceSupport = true, + labelDetailsSupport = true, + deprecatedSupport = true, + commitCharactersSupport = true, + tagSupport = { valueSet = { 1 } }, + resolveSupport = { + properties = { + "documentation", + "detail", + "additionalTextEdits", + }, + }, +} + +vim.lsp.config("lua_ls", { + on_init = M.on_init, + on_attach = M.on_attach, + capabilities = M.capabilities, + + settings = { + Lua = { + diagnostics = { + globals = { "vim" }, + }, + workspace = { + library = { + [vim.fn.expand "$VIMRUNTIME/lua"] = true, + [vim.fn.expand "$VIMRUNTIME/lua/vim/lsp"] = true, + [vim.fn.stdpath "data" .. "/lazy/ui/nvchad_types"] = true, + [vim.fn.stdpath "data" .. "/lazy/lazy.nvim/lua/lazy"] = true, + }, + maxPreload = 100000, + preloadFileSize = 10000, + }, + }, + }, +}) +vim.lsp.enable("lua_ls") + +return M