From 36f9e5d0b33cbe6d9cd27e240e8c9630be11af6b Mon Sep 17 00:00:00 2001 From: Pratik Tripathy Date: Mon, 6 Jan 2025 17:04:44 +0530 Subject: [PATCH] feat(nvim): Markdown: QoL plugins and settings - Link creation: autocommand to add ml shortcut for converting selected text to link - Formatting: Use markdown-toc to format available TOC - LSP: Add markdown-toc & markdownlint to Mason ensure_installed - Plugin: render-markdown.nvim with pretty colors to make Obsidian-esk rendering - Plugin: bullets.nvim for easier bullet-point operations (auto indent, auto increment numbers, etc.) - Chore: Move all markdown plugins to lang-markdown.lua - Plugin: img-clip.nvim: Paste screenshots from system-clipboard to markdown (also create store the image as webp) - Plugin: image.nvim: Show images across neovim. Renders image tags on markdown --- .../lua/config/filetype-based-keymaps.lua | 21 +++ .../nvim/lua/plugins/code-formatting.lua | 12 +- common/.config/nvim/lua/plugins/code-lsp.lua | 29 +--- .../nvim/lua/plugins/lang-markdown.lua | 158 ++++++++++++++++++ common/.config/nvim/lua/plugins/ui.lua | 55 ------ 5 files changed, 197 insertions(+), 78 deletions(-) create mode 100644 common/.config/nvim/lua/plugins/lang-markdown.lua diff --git a/common/.config/nvim/lua/config/filetype-based-keymaps.lua b/common/.config/nvim/lua/config/filetype-based-keymaps.lua index c377eec..dd931ac 100644 --- a/common/.config/nvim/lua/config/filetype-based-keymaps.lua +++ b/common/.config/nvim/lua/config/filetype-based-keymaps.lua @@ -35,3 +35,24 @@ vim.api.nvim_create_autocmd("FileType", { end, nested = true, }) + +vim.api.nvim_create_autocmd("FileType", { + group = vim.api.nvim_create_augroup("markdown-keymaps", { clear = true }), + pattern = { "markdown", "gitcommit", "text" }, + callback = function() + vim.keymap.set("v", "ml", function() + -- Save visually selected text to register 'v' + vim.cmd('normal! "vy') + -- Delete the selected text + vim.cmd("normal! gvd") + -- Get the content of the system clipboard + local clipboard_content = vim.fn.getreg("+") + -- Insert the markdown link + local link = string.format("[%s](%s)", vim.fn.getreg("v"), clipboard_content) + vim.api.nvim_put({ link }, "c", false, true) + -- Move cursor inside the square brackets + vim.cmd("normal! F[l") + end, { desc = "Markdown: Make link" }) + end, + nested = true, +}) diff --git a/common/.config/nvim/lua/plugins/code-formatting.lua b/common/.config/nvim/lua/plugins/code-formatting.lua index 088e7c4..8855b49 100644 --- a/common/.config/nvim/lua/plugins/code-formatting.lua +++ b/common/.config/nvim/lua/plugins/code-formatting.lua @@ -17,7 +17,7 @@ return { json = { "prettierd", "prettier", stop_after_first = true }, graphql = { "prettierd", "prettier", stop_after_first = true }, yaml = { "yamlfmt", "prettierd", stop_after_first = true }, - markdown = { "markdownlint" }, + markdown = { "markdownlint", "markdown-toc" }, lua = { "stylua" }, python = { "black" }, sh = { "shfmt", "shellharden", stop_after_first = true }, @@ -53,6 +53,16 @@ return { "~/.config/templates/markdownlint.json", }, }, + ["markdown-toc"] = { + -- Format only if TOC present in the file + condition = function(_, ctx) + for _, line in ipairs(vim.api.nvim_buf_get_lines(ctx.buf, 0, -1, false)) do + if line:find("") then + return true + end + end + end, + }, yamlfmt = { prepend_args = { "-formatter", diff --git a/common/.config/nvim/lua/plugins/code-lsp.lua b/common/.config/nvim/lua/plugins/code-lsp.lua index abb22e0..d8a320a 100644 --- a/common/.config/nvim/lua/plugins/code-lsp.lua +++ b/common/.config/nvim/lua/plugins/code-lsp.lua @@ -212,26 +212,6 @@ return { sqlls = {}, dockerls = {}, docker_compose_language_service = {}, - - -- ltex = { - -- filetypes = { "markdown", "text" }, - -- flags = { debounce_text_changes = 3000 }, - -- settings = { - -- ltex = { - -- language = "en", - -- markdown = { - -- nodes = { - -- CodeBlock = "ignore", - -- FencedCodeBlock = "ignore", - -- Code = "ignore", - -- AutoLink = "ignore", - -- }, - -- checkFrequency = "save", - -- languageToolHttpServerUri = "https://api.languagetool.org", - -- }, - -- }, - -- }, - -- }, } -- Ensure the servers and tools above are installed @@ -244,17 +224,22 @@ return { -- Add other tools here that you want Mason to install for you local ensure_installed = vim.tbl_keys(servers or {}) vim.list_extend(ensure_installed, { - "shfmt", "stylua", - "codespell", "bash-language-server", "html-lsp", "css-lsp", "dockerfile-language-server", "python-lsp-server", + "markdownlint", + "markdown-toc", "csharpier", "netcoredbg", }) + + -- TODO: Remove all installations through Mason + -- i.e. Remove mason.nvim, mason-lspconfig and mason-tool-installer + -- We should install those globally on the system + -- That would make it easier to work with on FreeBSD require("mason-tool-installer").setup({ ensure_installed = ensure_installed }) ---@diagnostic disable-next-line: missing-fields diff --git a/common/.config/nvim/lua/plugins/lang-markdown.lua b/common/.config/nvim/lua/plugins/lang-markdown.lua new file mode 100644 index 0000000..b429224 --- /dev/null +++ b/common/.config/nvim/lua/plugins/lang-markdown.lua @@ -0,0 +1,158 @@ +return { + -- Render Markdown on Neovim + { + "MeanderingProgrammer/render-markdown.nvim", + cond = require("config.util").is_not_vscode(), + init = function() + -- Define color variables + local color1_bg = "#295715" + local color2_bg = "#8d8200" + local color3_bg = "#a56106" + local color4_bg = "#7e0000" + local color5_bg = "#1e0b7b" + local color6_bg = "#560b7b" + local color_fg = "white" + + -- Heading colors (when not hovered over), extends through the entire line + vim.cmd(string.format([[highlight Headline1Bg guifg=%s guibg=%s]], color_fg, color1_bg)) + vim.cmd(string.format([[highlight Headline2Bg guifg=%s guibg=%s]], color_fg, color2_bg)) + vim.cmd(string.format([[highlight Headline3Bg guifg=%s guibg=%s]], color_fg, color3_bg)) + vim.cmd(string.format([[highlight Headline4Bg guifg=%s guibg=%s]], color_fg, color4_bg)) + vim.cmd(string.format([[highlight Headline5Bg guifg=%s guibg=%s]], color_fg, color5_bg)) + vim.cmd(string.format([[highlight Headline6Bg guifg=%s guibg=%s]], color_fg, color6_bg)) + + -- Highlight for the heading and sign icons (symbol on the left) + vim.cmd(string.format([[highlight Headline1Fg cterm=bold gui=bold guifg=%s]], color1_bg)) + vim.cmd(string.format([[highlight Headline2Fg cterm=bold gui=bold guifg=%s]], color2_bg)) + vim.cmd(string.format([[highlight Headline3Fg cterm=bold gui=bold guifg=%s]], color3_bg)) + vim.cmd(string.format([[highlight Headline4Fg cterm=bold gui=bold guifg=%s]], color4_bg)) + vim.cmd(string.format([[highlight Headline5Fg cterm=bold gui=bold guifg=%s]], color5_bg)) + vim.cmd(string.format([[highlight Headline6Fg cterm=bold gui=bold guifg=%s]], color6_bg)) + end, + opts = { + code = { + render_modes = true, + sign = false, + width = "block", + border = "thick", + position = "right", + language_name = false, + right_pad = 1, + }, + heading = { + sign = false, + icons = {}, + backgrounds = { + "Headline1Bg", + "Headline2Bg", + "Headline3Bg", + "Headline4Bg", + "Headline5Bg", + "Headline6Bg", + }, + foregrounds = { + "Headline1Fg", + "Headline2Fg", + "Headline3Fg", + "Headline4Fg", + "Headline5Fg", + "Headline6Fg", + }, + }, + pipe_table = { + preset = "round", + }, + indent = { + enabled = true, + skip_heading = true, + }, + }, + ft = { "markdown", "norg", "rmd", "org" }, + config = function(_, opts) + require("render-markdown").setup(opts) + Snacks.toggle({ + name = "Markdown Render", + get = function() + return require("render-markdown.state").enabled + end, + set = function(enabled) + local m = require("render-markdown") + if enabled then + m.enable() + else + m.disable() + end + end, + }):map("cM") + end, + }, + + { + "bullets-vim/bullets.vim", + cond = require("config.util").is_not_vscode(), + ft = { "markdown", "text", "gitcommit", "scratch" }, + config = function() + vim.g.bullets_enabled_file_types = { + "markdown", + "text", + "gitcommit", + "scratch", + } + vim.g.bullets_enable_in_empty_buffers = 0 + vim.g.bullets_set_mappings = 1 + vim.g.bullets_delete_last_bullet_if_empty = 1 + vim.g.bullets_line_spacing = 1 + vim.g.bullets_pad_right = 1 + vim.g.bullets_auto_indent_after_colon = 1 + end, + }, + + -- Paste clipboard image to markdown files + { + "HakonHarnes/img-clip.nvim", + event = "VeryLazy", + opts = { + default = { + use_absolute_path = false, ---@type boolean + relative_to_current_file = false, ---@type boolean + + dir_path = function() + -- TODO: Find a path consistent for both Obsidian and github + return vim.fn.expand("%:t:r") .. "-img" + end, + + prompt_for_file_name = false, ---@type boolean + file_name = "%y%m%d-%H%M%S", ---@type string + + -- Format of the image to be saved, must convert it as well + -- https://stackoverflow.com/a/27269260 + extension = "webp", ---@type string + process_cmd = "convert - -quality 75 webp:-", ---@type string + }, + + filetypes = { + markdown = { + url_encode_path = true, ---@type boolean + + -- The template is what specifies how the alternative text and path + -- of the image will appear in your file + -- I want to use blink.cmp to easily find images with the LSP, so adding ./ + template = "![Image](./$FILE_PATH)", + + -- template = "![$FILE_NAME]($FILE_PATH)", ---@type string + }, + }, + }, + -- TIP: Use :PasteImage + }, + + -- View images in Neovim + { + "3rd/image.nvim", + build = false, + opts = { + -- Use ImageMagick (Fedora) or imagemagick (Debian) installed + processor = "magick_cli", + }, + }, +} diff --git a/common/.config/nvim/lua/plugins/ui.lua b/common/.config/nvim/lua/plugins/ui.lua index 1a736cc..096dbcc 100644 --- a/common/.config/nvim/lua/plugins/ui.lua +++ b/common/.config/nvim/lua/plugins/ui.lua @@ -19,61 +19,6 @@ return { { "machakann/vim-highlightedyank" }, - -- Render Markdown on Neovim - { - "MeanderingProgrammer/render-markdown.nvim", - opts = { - code = { - sign = false, - width = "block", - border = "thick", - position = "right", - language_name = false, - right_pad = 1, - }, - heading = { - sign = false, - icons = {}, - }, - pipe_table = { - preset = "round", - }, - indent = { - enabled = true, - skip_heading = true, - }, - }, - ft = { "markdown", "norg", "rmd", "org" }, - config = function(_, opts) - require("render-markdown").setup(opts) - Snacks.toggle({ - name = "Render Markdown", - get = function() - return require("render-markdown.state").enabled - end, - set = function(enabled) - local m = require("render-markdown") - if enabled then - m.enable() - else - m.disable() - end - end, - }):map("cM") - end, - }, - - -- colorscheme - { - "projekt0n/github-nvim-theme", - cond = require("config.util").is_not_vscode(), - lazy = false, - priority = 1000, - config = function() - -- vim.cmd("colorscheme github_dark_dimmed") - end, - }, - { "catppuccin/nvim", name = "catppuccin",