feat(nvim): Markdown: QoL plugins and settings

- Link creation: autocommand to add <leader>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
This commit is contained in:
Pratik Tripathy
2025-01-06 17:04:44 +05:30
parent d4f25554e1
commit 36f9e5d0b3
5 changed files with 197 additions and 78 deletions

View File

@@ -35,3 +35,24 @@ vim.api.nvim_create_autocmd("FileType", {
end, end,
nested = true, 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", "<leader>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,
})

View File

@@ -17,7 +17,7 @@ return {
json = { "prettierd", "prettier", stop_after_first = true }, json = { "prettierd", "prettier", stop_after_first = true },
graphql = { "prettierd", "prettier", stop_after_first = true }, graphql = { "prettierd", "prettier", stop_after_first = true },
yaml = { "yamlfmt", "prettierd", stop_after_first = true }, yaml = { "yamlfmt", "prettierd", stop_after_first = true },
markdown = { "markdownlint" }, markdown = { "markdownlint", "markdown-toc" },
lua = { "stylua" }, lua = { "stylua" },
python = { "black" }, python = { "black" },
sh = { "shfmt", "shellharden", stop_after_first = true }, sh = { "shfmt", "shellharden", stop_after_first = true },
@@ -53,6 +53,16 @@ return {
"~/.config/templates/markdownlint.json", "~/.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("<!%-%- toc %-%->") then
return true
end
end
end,
},
yamlfmt = { yamlfmt = {
prepend_args = { prepend_args = {
"-formatter", "-formatter",

View File

@@ -212,26 +212,6 @@ return {
sqlls = {}, sqlls = {},
dockerls = {}, dockerls = {},
docker_compose_language_service = {}, 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 -- 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 -- Add other tools here that you want Mason to install for you
local ensure_installed = vim.tbl_keys(servers or {}) local ensure_installed = vim.tbl_keys(servers or {})
vim.list_extend(ensure_installed, { vim.list_extend(ensure_installed, {
"shfmt",
"stylua", "stylua",
"codespell",
"bash-language-server", "bash-language-server",
"html-lsp", "html-lsp",
"css-lsp", "css-lsp",
"dockerfile-language-server", "dockerfile-language-server",
"python-lsp-server", "python-lsp-server",
"markdownlint",
"markdown-toc",
"csharpier", "csharpier",
"netcoredbg", "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 }) require("mason-tool-installer").setup({ ensure_installed = ensure_installed })
---@diagnostic disable-next-line: missing-fields ---@diagnostic disable-next-line: missing-fields

View File

@@ -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("<leader>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",
},
},
}

View File

@@ -19,61 +19,6 @@ return {
{ "machakann/vim-highlightedyank" }, { "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("<leader>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", "catppuccin/nvim",
name = "catppuccin", name = "catppuccin",