From 710d723d463c505eb52eff7b245608cb3cf306b3 Mon Sep 17 00:00:00 2001 From: Walter Jenkins Date: Thu, 19 Feb 2026 14:40:20 -0600 Subject: [PATCH] add all md updates to nvim --- lua/core/options.lua | 50 ++++++++++++++ lua/plugins/markdown.lua | 142 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 192 insertions(+) create mode 100644 lua/plugins/markdown.lua diff --git a/lua/core/options.lua b/lua/core/options.lua index 81f3b431..b24555bf 100644 --- a/lua/core/options.lua +++ b/lua/core/options.lua @@ -60,6 +60,56 @@ vim.opt.foldlevel = 99 -- Keep folds open by default +-- Markdown: enable concealment for render-markdown.nvim rendering +vim.api.nvim_create_autocmd("FileType", { + pattern = "markdown", + callback = function() + vim.opt_local.conceallevel = 2 + vim.opt_local.wrap = true + vim.opt_local.linebreak = true + vim.opt_local.spell = true + vim.opt_local.spelllang = "en_us" + + -- ]e/[e and ]w/[w navigate spell errors (mirrors diagnostic nav in code files) + vim.keymap.set("n", "]e", "]s", { buffer = true, remap = true, desc = "Next spell error" }) + vim.keymap.set("n", "[e", "[s", { buffer = true, remap = true, desc = "Prev spell error" }) + vim.keymap.set("n", "]w", "]s", { buffer = true, remap = true, desc = "Next spell error" }) + vim.keymap.set("n", "[w", "[s", { buffer = true, remap = true, desc = "Prev spell error" }) + + -- K: spell suggestions picker when on a misspelled word, fallback to LSP hover + vim.keymap.set("n", "K", function() + local bad = vim.fn.spellbadword() + if bad[1] ~= "" then + local word = bad[1] + local suggestions = vim.fn.spellsuggest(word, 10) + local items = {} + for _, s in ipairs(suggestions) do + table.insert(items, s) + end + table.insert(items, "── dictionary ──") + table.insert(items, "Add to dictionary: " .. word) + table.insert(items, "Mark as bad: " .. word) + + vim.ui.select(items, { + prompt = "Spell: '" .. word .. "'", + }, function(choice) + if not choice or choice == "── dictionary ──" then return end + if choice == "Add to dictionary: " .. word then + vim.cmd("normal! zg") + elseif choice == "Mark as bad: " .. word then + vim.cmd("normal! zw") + else + vim.cmd("normal! ciw" .. choice) + end + end) + return + end + -- fallback: LSP hover (e.g. if marksman is installed later) + pcall(vim.lsp.buf.hover) + end, { buffer = true, desc = "Spell suggestions / hover" }) + end, +}) + vim.api.nvim_create_autocmd("FileType", { pattern = "templ", callback = function() diff --git a/lua/plugins/markdown.lua b/lua/plugins/markdown.lua new file mode 100644 index 00000000..4f9045a4 --- /dev/null +++ b/lua/plugins/markdown.lua @@ -0,0 +1,142 @@ +-- lua/plugins/markdown.lua +return { + -- In-buffer markdown rendering: styled headers, bullet symbols, visual checkboxes + { + "MeanderingProgrammer/render-markdown.nvim", + dependencies = { "nvim-treesitter/nvim-treesitter", "nvim-tree/nvim-web-devicons" }, + ft = { "markdown" }, + opts = { + render_modes = { "n", "c" }, -- render in normal and command mode only (not insert) + heading = { + enabled = true, + sign = false, -- no sign column icons + icons = { "󰲡 ", "󰲣 ", "󰲥 ", "󰲧 ", "󰲩 ", "󰲫 " }, + }, + bullet = { + enabled = true, + icons = { "●", "○", "◆", "◇" }, + }, + checkbox = { + enabled = true, + unchecked = { icon = "󰄱 " }, + checked = { icon = "󰱒 " }, + }, + code = { + enabled = true, + sign = false, + style = "full", + }, + pipe_table = { enabled = true }, + }, + }, + + -- Auto-continue lists: press Enter at end of a list item to get the next bullet/number + { + "gaoDean/autolist.nvim", + ft = { "markdown" }, + config = function() + require("autolist").setup() + + -- Scope all keymaps to markdown buffers only + vim.api.nvim_create_autocmd("FileType", { + pattern = "markdown", + callback = function() + local map = function(mode, lhs, rhs, desc) + vim.keymap.set(mode, lhs, rhs, { buffer = true, desc = desc }) + end + + -- Continue list on Enter / new line + map("i", "", "AutolistNewBullet", "Continue list") + map("n", "o", "oAutolistNewBullet", "New list item below") + map("n", "O", "OAutolistNewBulletBefore", "New list item above") + + -- Toggle checkbox + map("n", "", "AutolistToggleCheckbox", "Toggle checkbox") + + -- Recalculate numbered list after reordering/deleting + map("n", "mr", "AutolistRecalculate", "Recalculate list numbers") + + -- Indent/dedent list item in insert mode + map("i", "", "AutolistTab", "Indent list item") + map("i", "", "AutolistShiftTab", "Dedent list item") + end, + }) + end, + }, + + -- Full Obsidian-like note-taking + { + "epwalsh/obsidian.nvim", + version = "*", + ft = "markdown", + dependencies = { "nvim-lua/plenary.nvim" }, + opts = { + -- Default vault; new notes always land in the current working directory + workspaces = { + { + name = "default", + path = "~/notes", + }, + }, + new_notes_location = "current_dir", + + -- Note naming: use the title as filename + note_id_func = function(title) + local suffix = "" + if title ~= nil then + suffix = title:gsub(" ", "-"):gsub("[^A-Za-z0-9-]", ""):lower() + else + for _ = 1, 4 do + suffix = suffix .. string.char(math.random(65, 90)) + end + end + return suffix + end, + + -- wiki-link style [[...]] + preferred_link_style = "wiki", + + -- Let render-markdown.nvim handle rendering + ui = { enable = false }, + + -- Open URLs with macOS `open` + follow_url_func = function(url) + vim.fn.jobstart({ "open", url }) + end, + + -- nvim-cmp completion for wiki links + completion = { + nvim_cmp = true, + min_chars = 2, + }, + + mappings = { + -- Follow link or create note under cursor + ["gf"] = { + action = function() return require("obsidian").util.gf_passthrough() end, + opts = { noremap = false, expr = true, buffer = true, desc = "Follow link" }, + }, + -- Toggle checkbox + [""] = { + action = function() return require("obsidian").util.toggle_checkbox() end, + opts = { buffer = true, desc = "Toggle checkbox" }, + }, + }, + }, + + config = function(_, opts) + require("obsidian").setup(opts) + + -- m prefix for markdown/notes commands + vim.keymap.set("n", "mn", "ObsidianNew", { desc = "New note" }) + vim.keymap.set("n", "mf", "ObsidianSearch", { desc = "Find/search notes" }) + vim.keymap.set("n", "mo", "ObsidianOpen", { desc = "Open in Obsidian app" }) + vim.keymap.set("n", "mb", "ObsidianBacklinks", { desc = "Backlinks" }) + vim.keymap.set("n", "ml", "ObsidianLinks", { desc = "Links in note" }) + vim.keymap.set("n", "md", "ObsidianToday", { desc = "Daily note" }) + vim.keymap.set("n", "mt", "ObsidianTags", { desc = "Search by tag" }) + vim.keymap.set("n", "mp", "ObsidianPasteImg", { desc = "Paste image" }) + vim.keymap.set("n", "mk", "ObsidianLinkNew", { desc = "Create link from selection" }) + end, + }, +}