Share your setups #36
Replies: 41 comments 121 replies
-
|
Hi, my config https://github.com/axpira/dotfiles/blob/main/nvim/init.lua |
Beta Was this translation helpful? Give feedback.
-
require("mini.base16").setup {
palette = {
base00 = "#000000",
base01 = "#111111",
base02 = "#333333",
base03 = "#bbbbbb",
base04 = "#dddddd",
base05 = "#ffffff",
base06 = "#ffffff",
base07 = "#ffffff",
base09 = "#ff2222",
base08 = "#ff9922",
base0A = "#ff22ff",
base0B = "#22ff22",
base0C = "#4444ff",
base0D = "#22ffff",
base0E = "#ffff22",
base0F = "#999999",
},
use_cterm = false,
}
require("mini.comment").setup {}
require("mini.completion").setup {}
require("mini.jump").setup {
mappings = {
repeat_jump = "",
},
highlight_delay = 0,
}
require("mini.pairs").setup {}
require("mini.sessions").setup {
directory = vim.fn.stdpath "config" .. "/sessions",
}
require("mini.starter").setup {
evaluate_single = true,
}
require("mini.statusline").setup {}
require("mini.surround").setup {
n_lines = 100,
mappings = {
add = "S",
delete = "ds",
find_left = "[s",
find = "]s",
highlight = "",
replace = "cs",
update_n_lines = "",
},
}
require("mini.tabline").setup {} |
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
-
|
I had a go at getting mini.ai to work with treesitter text objects. It seems to work alright with the little testing I've done, but I'm sure there are some edge cases that will break this. Credit for most of the work goes to the nvim-treesitter-textobjects plugin, the One other thing I added is the ability to use a table of queries instead of just one. Most of the logic was already there, it should just find the best match of any of the given queries. I'm 99% sure this is more complicated than it needs to be, as I've just kinda smooshed the two things together. UpdateThanks to the amazing update to the api (seriously, thanks so much @echasnovski), I have massively simplified this to the below function. My approach does come with the dependency on the nvim-treesitter plugin, but it supports multiple queries in one object and should have full support for all queries defined by nvim-treesitter-textobjects. local queries = require "nvim-treesitter.query"
local miniAiTreesitter = function(ai_type, _, _, query_list)
ai_type = ai_type == "a" and ".outer" or ".inner"
query_list = vim.tbl_map(function(query) return query .. ai_type end, query_list)
local matches = {}
for _, query in pairs(query_list) do
vim.list_extend(matches, queries.get_capture_matches_recursively(0, query, "textobjects"))
end
matches = vim.tbl_map(function(match)
local from_line, from_col, to_line, to_col = match.node:range()
return {
from = { line = from_line + 1, col = from_col + 1 },
to = { line = to_line + 1, col = to_col + 1 }
}
end, matches)
return matches
end
local miniAiTreeWrapper = function(query_list)
if type(query_list) ~= "table" then
query_list = { query_list }
end
return function(ai_type, _, opts)
return miniAiTreesitter(ai_type, _, opts, query_list)
end
end
require("mini.ai").setup({
custom_textobjects = {
o = miniAiTreeWrapper({"@block", "@conditional", "@loop"}),
s = miniAiTreeWrapper({"@function", "@class"}),
c = miniAiTreeWrapper("@comment"),
},
})If I make any further changes to this you should be able to find them here |
Beta Was this translation helpful? Give feedback.
-
|
mini.nvim is beautifull one set plugin, here is my setup |
Beta Was this translation helpful? Give feedback.
-
|
This is my config It's still a work in progress (I started a couple of days ago, switching from vscode after I decided, finally, to go 100% neovim). So mini is currently 90% of my plugins, if not more. 🤣 This is amazing, I said in reddit and I need to say that again: thank you for this impressive work. |
Beta Was this translation helpful? Give feedback.
-
|
An idea that maybe could be of interest of more people: https://www.reddit.com/r/neovim/comments/x0hf25/nicer_jupyter_notebook_workflow_with_neovim/ |
Beta Was this translation helpful? Give feedback.
This comment was marked as off-topic.
This comment was marked as off-topic.
-
|
Very nice. (Minimap scrolls to the sides - not necessary.) |
Beta Was this translation helpful? Give feedback.
-
|
Mini is my favourite plugin. My neovim setup is minimal, so I really enjoy that I can setup all my mini modules of choice without setting any preferences, because the defaults are just so solid for me. The proof is that I can just loop an array to initialise them. |
Beta Was this translation helpful? Give feedback.
-
|
You can look at mine in here |
Beta Was this translation helpful? Give feedback.
-
|
Here is my setup: The border colors for the notify window seem to be both fore- and background to be the same: |
Beta Was this translation helpful? Give feedback.
-
|
Here is how { -- Split parameters, simpler version of treesj.lua
url = 'https://github.com/echasnovski/mini.splitjoin',
version = '*',
opts = {
mappings = {}, -- Configured in treesj => treesitter.lua
detect = {
separator = '[,;]'
}
}
},
{ -- Split/Join, integrated with mini.splitjoin
url = 'https://github.com/Wansmer/treesj',
dependencies = { 'https://github.com/nvim-treesitter/nvim-treesitter/' },
keys = {
{ '<leader>m', mode = { 'n', 'v' }, desc = 'Toggle split' }
},
config = function()
local tsj = require('treesj')
tsj.setup({
use_default_keymaps = false,
max_join_length = 512,
})
local function get_pos_lang(node)
local c = vim.api.nvim_win_get_cursor(0)
local range = { c[1] - 1, c[2], c[1] - 1, c[2] }
local buf = vim.api.nvim_get_current_buf()
local ok, parser = pcall(
vim.treesitter.get_parser,
buf,
vim.treesitter.language.get_lang(vim.bo[buf].ft)
)
if not ok then
return ""
end
local current_tree = parser:language_for_range(range)
return current_tree:lang()
end
vim.keymap.set({ 'n', 'v' }, "<leader>m", function()
local tsj_langs = require("treesj.langs")["presets"]
local lang = get_pos_lang()
if lang ~= "" and tsj_langs[lang] then
require("treesj").toggle()
else
require("mini.splitjoin").toggle()
end
end)
end
} |
Beta Was this translation helpful? Give feedback.
-
|
I spent this morning tweaking the look of my mini.statusline: My changes from the default:
I spent a couple hours (yes, sadly), experimenting with lots of other variations:
I love I love I also enabled The only packages I've tried thus far that I did not care for were With regards to Overall, love all the hard work you've put into the mini packages. Simply amazing! |
Beta Was this translation helpful? Give feedback.
-
|
Recently migrated to Highlights: Lazy stats (startup time). Currently updated via auto command due to stats not being available when `mini.starter` starts. -- Set starter footer and refresh after `startuptime` is available
vim.api.nvim_create_autocmd("User", {
pattern = "MiniStarterOpened",
callback = function()
vim.api.nvim_create_autocmd("User", {
pattern = "LazyVimStarted",
callback = function()
local starter = require "mini.starter"
local stats = require("lazy").stats()
local ms = (math.floor(stats.startuptime * 100 + 0.5) / 100)
starter.config.footer = function()
return "⚡ Loaded plugins: "
.. stats.loaded
.. "/"
.. stats.count
.. "\n⚡ Startup time: "
.. ms
.. " ms"
end
starter.refresh()
end,
})
end,
})A dedicated section for workspaces from `workspaces.nvim`. local workspace_items = function()
local workspaces = require "workspaces"
local items = {}
for _, w in pairs(workspaces.get()) do
table.insert(items, {
name = w.name .. " " .. vim.fn.fnamemodify(w.path, ":~:."),
action = "WorkspacesOpen " .. w.name,
section = "Workspaces",
})
end
return items
endA workaround for centralizing header and justifying select sections. -- A workaround to centralize everything.
-- `aligning("center", "center")` will centralize the longest line in
-- `content`, then left align other items to its beginning.
-- It causes the header to not be truly centralized and have a variable
-- shift to the left.
-- This function will use `aligning` and pad the header accordingly.
-- It also goes over `justified_sections`, goes over all their items names
-- and justifies them by padding existing space in them.
-- Since `item_bullet` are separated from the items themselves, their
-- width is measured separately and deducted from the padding.
local centralize = function(justified_sections, centralize_header)
return function(content, buf_id)
-- Get max line width, same as in `aligning`
local max_line_width = math.max(unpack(vim.tbl_map(function(l)
return vim.fn.strdisplaywidth(l)
end, starter.content_to_lines(content))))
-- Align
content = starter.gen_hook.aligning("center", "center")(content, buf_id)
-- Iterate over header items and pad with relative missing spaces
if centralize_header == true then
local coords = starter.content_coords(content, "header")
for _, c in ipairs(coords) do
local unit = content[c.line][c.unit]
local pad = (max_line_width - vim.fn.strdisplaywidth(unit.string))
/ 2
if unit.string ~= "" then
unit.string = string.rep(" ", pad) .. unit.string
end
end
end
-- Justify recent files and workspaces
if justified_sections ~= nil and #justified_sections > 0 then
-- Check if `adding_bullet` has mutated the `content`
local coords = starter.content_coords(content, "item_bullet")
local bullet_len = 0
if coords ~= nil then
-- Bullet items are defined, compensate for bullet prefix width
bullet_len = vim.fn.strdisplaywidth(
content[coords[1].line][coords[1].unit].string
)
end
coords = starter.content_coords(content, "item")
for _, c in ipairs(coords) do
local unit = content[c.line][c.unit]
if vim.tbl_contains(justified_sections, unit.item.section) then
local one, two = unpack(vim.split(unit.string, " "))
unit.string = one
.. string.rep(
" ",
max_line_width
- vim.fn.strdisplaywidth(unit.string)
- bullet_len
+ 1
)
.. two
end
end
end
return content
end
endHow it is used in `MiniStarter.setup`. starter.setup {
-- evaluate_single = true,
header = "███████████████████████████\n"
.. "███████▀▀▀░░░░░░░▀▀▀███████\n"
.. "████▀░░░░░░░░░░░░░░░░░▀████\n"
.. "███│░░░░░░░░░░░░░░░░░░░│███\n"
.. "██▌│░░░░░░░░░░░░░░░░░░░│▐██\n"
.. "██░└┐░░░░░░░░░░░░░░░░░┌┘░██\n"
.. "██░░└┐░░░░░░░░░░░░░░░┌┘░░██\n"
.. "██░░┌┘▄▄▄▄▄░░░░░▄▄▄▄▄└┐░░██\n"
.. "██▌░│██████▌░░░▐██████│░▐██\n"
.. "███░│▐███▀▀░░▄░░▀▀███▌│░███\n"
.. "██▀─┘░░░░░░░▐█▌░░░░░░░└─▀██\n"
.. "██▄░░░▄▄▄▓░░▀█▀░░▓▄▄▄░░░▄██\n"
.. "████▄─┘██▌░░░░░░░▐██└─▄████\n"
.. "█████░░▐█─┬┬┬┬┬┬┬─█▌░░█████\n"
.. "████▌░░░▀┬┼┼┼┼┼┼┼┬▀░░░▐████\n"
.. "█████▄░░░└┴┴┴┴┴┴┴┘░░░▄█████\n"
.. "███████▄░░░░░░░░░░░▄███████\n"
.. "██████████▄▄▄▄▄▄▄██████████\n"
.. "pwd: "
.. vim.fn.fnamemodify(vim.fn.getcwd(), ":~:."),
items = {
workspace_items,
starter.sections.recent_files(10, false, function(path)
-- Bring back trailing slash after `dirname`
return " " .. vim.fn.fnamemodify(path, ":~:.:h") .. "/"
end),
{ section = "Tools", name = "Lazy", action = "Lazy" },
{ section = "Tools", name = "Telescope", action = "Telescope" },
starter.sections.builtin_actions(),
},
content_hooks = {
-- starter.gen_hook.adding_bullet(),
centralize({ "Recent files", "Workspaces" }, true),
},
}
workspaces.nvim |
Beta Was this translation helpful? Give feedback.
-
|
This is what I've got so far, still WIP: https://gist.github.com/luisdavim/b985e141310567969d90114d9cbd15b8 |
Beta Was this translation helpful? Give feedback.
-
|
Hi I just found this discussion and here is my swahpy/mvim. Looking forward to your feedback! |
Beta Was this translation helpful? Give feedback.
-
|
Hello, I would also like to share and get feedback from my configuration: |
Beta Was this translation helpful? Give feedback.
-
|
My entire nvim dots are in one file and is great for java development right now. I had a version with lazy a while back with 30 plugins and now I have around 10 and some can be removed. Mini.nvim made life so much easier here is the repo: https://github.com/DarthMooMancer/MacOS-Dots |
Beta Was this translation helpful? Give feedback.
-
|
Here is my config: https://github.com/aorith/dotfiles/tree/master/topics/neovim/nvim I really like the consistency of |
Beta Was this translation helpful? Give feedback.
-
|
Hope I'm not late to the party. I read through mini files and IN LOVE with the bookmarks function. Perf for navigation in large projects. However, I'd prefer to have that in per project approach rather than in-memory solution where the bookmarks is lost when closing neovim. So I took the liberty to fork and modify it a little bit to store the data to 'mini.files' setupreturn {
"liketoeatcheese/mini.files",
branch = "main",
dependencies = {},
config = function()
require("mini.files").setup( -- No need to copy this inside `setup()`. Will be used automatically.
{
-- Customization of shown content
content = {
-- Predicate for which file system entries to show
filter = nil,
-- What prefix to show to the left of file system entry
prefix = nil,
-- In which order to show file system entries
sort = nil,
},
-- Module mappings created only inside explorer.
-- Use `''` (empty string) to not create one.
mappings = {
close = "<space>q",
go_in_plus = "L",
--[[ go_in_plus = "L", ]]
go_in = "",
go_out = "H",
mark_goto = "'",
mark_set = "m",
reset = "<BS>",
reveal_cwd = "@",
show_help = "g?",
synchronize = "=",
trim_left = "<",
trim_right = ">",
},
-- General options
options = {
-- Whether to delete permanently or move into module-specific trash
permanent_delete = true,
-- Whether to use for editing directories
use_as_default_explorer = true,
},
-- Customization of explorer windows
windows = {
-- Maximum number of windows to show side by side
max_number = math.huge,
-- Whether to show preview of file/directory under cursor
preview = true,
-- Width of focused window
width_focus = 30,
-- Width of non-focused window
width_nofocus = 35,
-- Width of preview window
width_preview = 55,
},
}
)
vim.api.nvim_create_autocmd("User", {
pattern = "MiniFilesWindowUpdate",
callback = function(args)
vim.cmd([[
setlocal relativenumber
]])
local config = vim.api.nvim_win_get_config(args.data.win_id)
-- Ensure fixed height
config.height = vim.o.lines - 2
--[[ config.height = 10 ]]
-- Ensure title padding
if config.title[#config.title][1] ~= " " then
table.insert(config.title, { " ", "NormalFloat" })
end
if config.title[1][1] ~= " " then
table.insert(config.title, 1, { " ", "NormalFloat" })
end
vim.api.nvim_win_set_config(args.data.win_id, config)
end,
})
local mini_utils = {}
-- Copy just the filename
function mini_utils.copy_filename()
local entry = MiniFiles.get_fs_entry()
if not entry then
return
end
local filename = vim.fs.basename(entry.path)
if vim.fn.has("wsl") == 1 then
vim.fn.setreg("+", filename)
vim.fn.system("wslcopy", vim.fn.getreg("+"))
else
vim.fn.setreg("+", filename)
end
vim.notify("Copied: " .. filename)
end
-- Copy the full path in Windows format (for WSL)
function mini_utils.copy_windows_path()
local entry = MiniFiles.get_fs_entry()
if not entry then
return
end
local filepath = entry.path
-- Convert WSL path to Windows drive letter format
local win_path = filepath:gsub("^/mnt/(%w)", function(drive)
return string.upper(drive) .. ":/"
end)
win_path = win_path:gsub("/", "\\")
if vim.fn.has("wsl") == 1 then
vim.fn.setreg("+", win_path)
vim.fn.system("wslcopy", vim.fn.getreg("+"))
else
vim.fn.setreg("+", win_path)
end
vim.notify("Copied: " .. win_path)
end
-- Copy the full path
function mini_utils.copy_filepath()
local entry = MiniFiles.get_fs_entry()
if not entry then
return
end
local filepath = entry.path
--[[ filepath = filepath:gsub("/", "\\") ]]
if vim.fn.has("wsl") == 1 then
vim.fn.setreg("+", filepath)
vim.fn.system("wslcopy", vim.fn.getreg("+"))
else
vim.fn.setreg("+", filepath)
end
vim.notify("Copied: " .. filepath)
end
-- Copy relative path from current working directory
function mini_utils.copy_relative_path_forward_slash()
local entry = MiniFiles.get_fs_entry()
if not entry then
return
end
local filepath = entry.path
-- Get the current working directory
local cwd = vim.fn.getcwd()
-- Convert both paths to absolute paths
local abs_filepath = vim.fn.fnamemodify(filepath, ":p")
local abs_cwd = vim.fn.fnamemodify(cwd, ":p")
-- Get the relative path
local relative_path = vim.fn.fnamemodify(abs_filepath, ":." .. abs_cwd .. ":~")
-- Remove leading './' if present
relative_path = relative_path:gsub("^%./", "")
relative_path = relative_path:gsub("\\", "/")
if vim.fn.has("wsl") == 1 then
vim.fn.setreg("+", relative_path)
vim.fn.system("wslcopy", vim.fn.getreg("+"))
else
vim.fn.setreg("+", relative_path)
end
vim.notify("Copied: " .. relative_path)
end
-- Copy relative path from current working directory
function mini_utils.copy_relative_path()
local entry = MiniFiles.get_fs_entry()
if not entry then
return
end
local filepath = entry.path
-- Get the current working directory
local cwd = vim.fn.getcwd()
-- Convert both paths to absolute paths
local abs_filepath = vim.fn.fnamemodify(filepath, ":p")
local abs_cwd = vim.fn.fnamemodify(cwd, ":p")
-- Get the relative path
local relative_path = vim.fn.fnamemodify(abs_filepath, ":." .. abs_cwd .. ":~")
-- Remove leading './' if present
relative_path = relative_path:gsub("^%./", "")
if vim.fn.has("wsl") == 1 then
vim.fn.setreg("+", relative_path)
vim.fn.system("wslcopy", vim.fn.getreg("+"))
else
vim.fn.setreg("+", relative_path)
end
vim.notify("Copied: " .. relative_path)
end
-- Set root directory to current directory (equivalent to Neotree's set_root)
function mini_utils.set_root()
-- Works only if cursor is on the valid file system entry
local cur_entry_path = MiniFiles.get_fs_entry().path
local cur_directory = vim.fs.dirname(cur_entry_path)
vim.fn.chdir(cur_directory)
vim.api.nvim_set_current_dir(cur_directory)
MiniFiles.trim_left()
end
local go_in_plus = function()
for _ = 1, vim.v.count1 do
MiniFiles.go_in({ close_on_file = true })
end
end
vim.api.nvim_create_autocmd("User", {
pattern = "MiniFilesBufferCreate",
callback = function(args)
local map_buf = function(lhs, rhs)
vim.keymap.set("n", lhs, rhs, { buffer = args.data.buf_id })
end
map_buf("<Esc>", MiniFiles.close)
map_buf("q", MiniFiles.close)
map_buf("<c-h>", MiniFiles.go_out)
map_buf("<c-l>", go_in_plus)
vim.keymap.set("n", ".", mini_utils.set_root, { buffer = args.data.buf_id })
vim.keymap.set("n", "a", "o", { buffer = args.data.buf_id })
--[[ vim.keymap.set("n", "y", mini_utils.copy_filename, { buffer = args.data.buf_id }) ]]
vim.keymap.set("n", "gm", mini_utils.copy_relative_path_forward_slash, { buffer = args.data.buf_id })
vim.keymap.set("n", "gy", mini_utils.copy_filepath, { buffer = args.data.buf_id })
vim.keymap.set("n", "<s-y>", mini_utils.copy_relative_path, { buffer = args.data.buf_id })
end,
})
local go_in_plus = function()
for _ = 1, vim.v.count1 do
MiniFiles.go_in({ close_on_file = true })
end
end
local map_split = function(buf_id, lhs, direction)
local rhs = function()
-- Make new window and set it as target
local cur_target = MiniFiles.get_explorer_state().target_window
local new_target = vim.api.nvim_win_call(cur_target, function()
vim.cmd(direction .. " split")
return vim.api.nvim_get_current_win()
end)
MiniFiles.set_target_window(new_target)
go_in_plus()
-- This intentionally doesn't act on file under cursor in favor of
-- explicit "go in" action (`l` / `L`). To immediately open file,
-- add appropriate `MiniFiles.go_in()` call instead of this comment.
end
-- Adding `desc` will result into `show_help` entries
local desc = "Split " .. direction
vim.keymap.set("n", lhs, rhs, { buffer = buf_id, desc = desc })
end
vim.api.nvim_create_autocmd("User", {
pattern = "MiniFilesBufferCreate",
callback = function(args)
local buf_id = args.data.buf_id
-- Tweak keys to your liking
vim.keymap.set("n", "<C-A-v>", "<C-v>", { noremap = true, desc = "Enter visual block mode" })
map_split(buf_id, "<C-v>", "vertical")
end,
})
end,
}For the bonus. This is not really related to mini at all. I wrote this since I use search and replace a lot and there's no plugin out there that do this (Not that I know off at least). This basically allows you to visually select the text you one and escape all special characters that sed needs snap it into :%s/ or do the same for the word that you are on, and some other nuggets of searching within buffer, within the project, etc...: search_and_replace.lualocal M = {}
-- Escape special characters in the string
local function escape(str)
return str:gsub("([~\\^$.*\\/%[%]])", "\\%1"):gsub("\n", "\\n")
end
-- Escape special characters in the string
local function escapeFzf(str)
--[[ return str:gsub('([~\\^$*\\/%[%]\'\\])"', "\\%1") ]]
return str:gsub("([\\'])", "\\%1"):gsub("\n", "\\n")
end
local function get_visual_selection()
local start_pos = vim.fn.getpos("'<")
local end_pos = vim.fn.getpos("'>")
-- Adjust for Lua's 1-indexing
local start_col = start_pos[3]
local end_col = end_pos[3]
-- If selection is within a single line
if start_pos[2] == end_pos[2] then
return vim.fn.getline(start_pos[2]):sub(start_col, end_col)
end
local lines = vim.fn.getline(start_pos[2], end_pos[2])
if #lines == 0 then
return ""
end
-- Adjust first and last line of the selection
lines[1] = lines[1]:sub(start_col)
lines[#lines] = lines[#lines]:sub(1, end_col)
return table.concat(lines, "\n")
end
-- Function to be called from Neovim command
function M.SaveWithHighlight()
-- Get the current visual selection
local text = get_visual_selection()
text = escape(text) -- Escape the text for regex
-- Put the text into the command line
vim.fn.setreg("h", text)
end
-- Function to be called from Neovim command
function M.SubstituteWithPreviousHightlightHighlightMakeGroup()
-- Get the current visual selection
local content = vim.fn.getreg("h")
-- Put the text into the command line
local cmd = ":'<,'>s/\\(" .. content .. "\\)/"
vim.fn.feedkeys(vim.api.nvim_replace_termcodes(cmd, true, false, false))
end
-- Function to be called from Neovim command
function M.SubstituteWithHighlightMakeGroup()
-- Get the current visual selection
local text = get_visual_selection()
text = escape(text) -- Escape the text for regex
-- Put the text into the command line
local cmd = ":%s/\\(" .. text .. "\\)/"
vim.fn.feedkeys(vim.api.nvim_replace_termcodes(cmd, true, false, false))
end
-- Function to substitute with the word under the cursor
function M.SubstituteWithWord()
local word = vim.fn.expand("<cword>")
word = escape(word)
local cmd = ":%s/\\(" .. word .. "\\)/"
vim.fn.feedkeys(vim.api.nvim_replace_termcodes(cmd, true, false, true))
end
-- Function to substitute with the word under the cursor
function M.SearchWithWord()
local word = vim.fn.expand("<cword>")
word = escape(word)
local cmd = "/" .. word .. "<cr>"
vim.fn.feedkeys(vim.api.nvim_replace_termcodes(cmd, true, false, true))
end
-- Function to substitute with the word under the cursor
function M.SearchWithWORD()
local word = vim.fn.expand("<cWORD>")
word = escape(word)
local cmd = "/" .. word .. "<cr>"
vim.fn.feedkeys(vim.api.nvim_replace_termcodes(cmd, true, false, true))
end
-- Function to be called from Neovim command
function M.SearchWithHighlight()
-- Get the current visual selection
local text = get_visual_selection()
text = escape(text) -- Escape the text for regex
-- Put the text into the command line
local cmd = "/" .. text
vim.fn.feedkeys(vim.api.nvim_replace_termcodes(cmd, true, false, false))
end
-- Function to be called from Neovim command
function M.SearchWorkSpaceWithHighlight()
-- Get the current visual selection
local text = get_visual_selection()
text = escapeFzf(text) -- Escape the text for regex
-- Put the text into the command line
local cmd = ":lua require('fzf-lua').live_grep_native({multiprocess=true,search = '" .. text .. "'})<CR>"
vim.fn.feedkeys(vim.api.nvim_replace_termcodes(cmd, true, false, true))
end
return MMappingskeymap("v", "<Leader>rp", ':lua require"utils.search_and_replace".SubstituteWithHighlightMakeGroup()<CR>', opts)
keymap("v", "<Leader>rs", ':lua require"utils.search_and_replace".SaveWithHighlight()<CR>', opts)
keymap(
"v",
"<Leader>rh",
':lua require"utils.search_and_replace".SubstituteWithPreviousHightlightHighlightMakeGroup()<CR>',
opts
)
keymap("n", "<Leader>rp", ':lua require"utils.search_and_replace".SubstituteWithWord()<CR>', opts)
keymap("v", "<Leader>lh", ':lua require"utils.search_and_replace".SearchWithHighlight()<CR>', opts)
keymap("v", "<Leader>lf", ':lua require"utils.search_and_replace".SearchWithHighlight()<CR>', opts)
keymap("n", "<Leader>lw", ':lua require"utils.search_and_replace".SearchWithWord()<CR>', opts)
keymap("n", "<Leader>lW", ':lua require"utils.search_and_replace".SearchWithWORD()<CR>', opts)
keymap("v", "<Leader>lw", ':lua require"utils.search_and_replace".SearchWorkSpaceWithHighlight()<CR>', opts) |
Beta Was this translation helpful? Give feedback.
-
|
Loving mini so far, honestly no complaints :) |
Beta Was this translation helpful? Give feedback.
-
|
Hey! I wanted to share a small experience I had while configuring MiniStarter in Neovim. I customized the header colors and tweaked every detail to better match the overall colorscheme. MiniStarter:local header = require("config/header")
MiniStarter.setup({
evaluate_single = true,
header = table.concat(header.header.val, "\n"),
footer = function()
local stats = require("lazy").stats()
local ms = (math.floor(stats.startuptime * 100 + 0.5) / 100)
return "⚡ Neovim loaded " .. stats.count .. " plugins in " .. ms .. "ms"
end,
items = {
MiniStarter.sections.pick(),
},
content_hooks = {
-- MiniStarter.gen_hook.adding_bullet(""),
},
})
vim.api.nvim_create_autocmd("User", {
pattern = "MiniStarterOpened",
callback = function(ev)
local ns = vim.api.nvim_create_namespace("MiniStarterOpenedHeader")
if vim.bo.filetype == "ministarter" then
for i, x in ipairs(header.header.opts.hl) do
for _, z in ipairs(x) do
vim.api.nvim_buf_set_extmark(ev.buf, ns, i - 1, z[2], { end_col = z[3] - 1, hl_group = z[1] })
end
end
return
end
vim.api.nvim_buf_clear_namespace(ev.buf, ns, 0, -1)
end,
})
|
Beta Was this translation helpful? Give feedback.
-
|
Heya, it's actually my first time switching from vscode to neovim and i were told to use some IDE distro such as NvimChad and lazynvim but i stumbled on this godsend while browsing through lazy's plugin dependencies. And i'm loving it so far 💕 |
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
-
|
I have tried to make it as minimal as possible Nvim |
Beta Was this translation helpful? Give feedback.
-
|
My config is here. After trying multiple distros and rebuilding my configuration from scratch several times, I finally achieved what I wanted with mini.nvim: a minimal yet powerful setup that meets my needs. |
Beta Was this translation helpful? Give feedback.
-
|
Relatively new to mini.nvim setup---@module 'lazy'
---@type LazyPluginSpec[]
return {
{
"nvim-mini/mini.nvim",
version = false,
event = "BufEnter", -- required for setup_auto_root
config = function()
-- :help mini.ai
-- - va) - [V]isually select [A]round [)]paren
-- - yinq - [Y]ank [I]nside [N]ext [Q]uote
-- - ci' - [C]hange [I]nside [']quote
require("mini.ai").setup() -- repeatable text motions
-- :help mini.surround
-- - saiw) - [S]urround [A]dd [I]nner [W]ord [)]Paren
-- - sd' - [S]urround [D]elete [']quotes
-- - sr)' - [S]urround [R]eplace [)] [']
require("mini.surround").setup()
-- automatically change buffer cwd to the root of the project (vim-rooter-esque)
require("mini.misc").setup_auto_root({ ".git", "Makefile", "stylua.toml" })
-- move visual selection in Visual mode
require("mini.move").setup({
mappings = {
left = "<S-h>",
right = "<S-l>",
down = "<S-j>",
up = "<S-k>",
},
})
local wk = require("which-key")
wk.add({
{
"<leader>z",
function()
require("mini.misc").zoom()
end,
desc = "zoom",
icon = "",
},
})
end,
},
-- this is split so that we can lazy load on filetype effectively
--
-- the default 'gc' (:help commenting) binding works for most things, but react/web frameworks
-- have a different comment syntax, so this plugin only loads on those filetypes
{
"nvim-mini/mini.comment",
dependencies = {
"JoosepAlviste/nvim-ts-context-commentstring",
---@module 'ts_context_commentstring'
---@type ts_context_commentstring.Config
opts = { enable_autocmd = false },
},
ft = {
"javascript",
"typescript",
"javascriptreact",
"typescriptreact",
},
keys = { { "gc", mode = { "n", "x" } }, { "gbc", mode = { "n", "x" } } },
--- NOTE: no setup types
opts = {
options = {
custom_commentstring = function()
return require("ts_context_commentstring").calculate_commentstring() or vim.bo.commentstring
end,
},
},
},
} |
Beta Was this translation helpful? Give feedback.
-
|
I felt like I had to do really battle with very hacky setup-- maximum width of notify
local NOTIFY_WIDTH = 60
--- to display progress when the server supports percentages
local PROGRESS = { '⡀', '⣀', '⣄', '⣤', '⣦', '⣶', '⣷', '⣿' }
--- to display infinite progress, when percentage is unavailable
local INFINITE_PROGRESS = { '⣾', '⣽', '⣻', '⢿', '⡿', '⣟', '⣯', '⣷' }
--- @param str string
--- @param length integer
--- @return string truncated string
local function trunc(str, length)
str = str or ''
-- remove "..." present in messages/titles as it only wastes space (looking at you JDTLS)
local smaller = str:gsub('[.][.][.]', '')
-- truncate to length and use "..." to indicate we truncated
return #smaller > length and (smaller:sub(1, length - 3) .. '...') or smaller
end
--- @param item table
--- @return string icon
local function icon(item)
local value = item.data.response.value --[[@as table]]
if value.kind == 'end' then
return '✔'
elseif value.percentage and value.percentage > 0 then
return PROGRESS[math.ceil(math.max(1, value.percentage) / 100 * #PROGRESS)] or '?'
else
local index = assert(vim.uv.gettimeofday()) % #INFINITE_PROGRESS
return INFINITE_PROGRESS[1 + index] or '?'
end
end
--- @param item table
--- @return string message
local function message(item)
local value = item.data.response.value --[[@as table]]
if value.kind == 'end' then
-- when complete, indicate how much time it took the operation
return string.format('%.2fs', item.ts_update - item.ts_add)
elseif value.message and value.title and vim.startswith(value.message, value.title) then
-- best effort to remove redundancy (title == message, title startswith message, etc)
return vim.trim(value.message:sub(#value.title + 1))
else
return value.message or ''
end
end
--- Format LSP message as "message title [client] ICON",
--- this results in the least "movement", only the "message" really changes width
--- @param item table
--- @return string result
local function format_lsp(item)
local client_name = trunc(item.data.client_name, 13) --[[@as string]]
local remaining = NOTIFY_WIDTH - 6 - #client_name
local value = item.data.response.value --[[@as table]]
local title = trunc(value.title, remaining - 10)
remaining = remaining - #title
local msg = trunc(message(item), remaining)
local output = string.format('%s %s [%s] %s', msg, title, client_name, icon(item))
local width = vim.fn.strdisplaywidth(output)
return string.rep(' ', NOTIFY_WIDTH - width) .. output
end
-- replace refresh with one that only happens every 150ms
-- especially rust-based analyzers tend to overexert here.
local notify = require('mini.notify')
local refresh = notify.refresh
local timer = assert(vim.uv.new_timer())
--- @diagnostic disable-next-line: duplicate-set-field
notify.refresh = function()
if not timer:is_active() then
timer:start(150, 0, vim.schedule_wrap(refresh))
end
end
notify.setup({
content = {
format = function(item)
if item.data.source == 'lsp_progress' then
return format_lsp(item)
elseif item.data.source == 'vim.notify' then
local output = string.format('%s ■', trunc(item.msg, NOTIFY_WIDTH - 6))
local width = vim.fn.strdisplaywidth(output)
return string.rep(' ', NOTIFY_WIDTH - width) .. output
else
return notify.default_format(item)
end
end,
-- Sort strictly by recency, this reduces overall movement hence flicker
sort = function(items)
--- @param a table
--- @param b table
--- @return boolean if a > b
table.sort(items, function(a, b)
return a.ts_add > b.ts_add
end)
return items
end,
},
window = {
-- Undo the adjusted height since we aren't wrapping but instead truncating
-- Place at bottom right of screen
config = function(buffer)
local count = vim.api.nvim_buf_line_count(buffer)
local has_statusline = vim.o.laststatus > 0
local pad = vim.o.cmdheight + (has_statusline and 1 or 0)
return {
anchor = 'SE',
col = vim.o.columns,
row = vim.o.lines - pad,
width = NOTIFY_WIDTH,
height = count,
border = 'none',
}
end,
},
lsp_progress = {
duration_last = 2500,
},
}) |
Beta Was this translation helpful? Give feedback.
-
AboutNothing special — just a single-file configuration with a few custom tweaks. The current version isn’t ideal, and I probably won’t update it here too often. See https://github.com/drowning-cat/nvim-lean. Relatedmini.nvim
Other
Code~2000 lines (version 4)if vim.fn.has("nvim-0.12") == 0 then
return vim.notify("Install Neovim 0.12+", vim.log.levels.ERROR)
end
vim.g.mapleader = " "
vim.g.maplocalleader = " "
vim.o.number = true
vim.o.relativenumber = true
vim.o.signcolumn = "yes"
vim.o.updatetime = 250
vim.o.timeoutlen = 300
vim.o.splitbelow = true
vim.o.splitright = true
vim.o.tabclose = "uselast"
vim.o.expandtab = true
vim.o.tabstop = 4
vim.o.shiftwidth = 2
vim.o.softtabstop = 2
vim.o.foldmethod = "indent"
vim.o.foldtext = ""
vim.o.foldlevel = 99
vim.o.foldlevelstart = 99
vim.o.foldnestmax = 10
vim.o.undofile = true
vim.o.undolevels = 10000
vim.o.ignorecase = true
vim.o.smartcase = true
vim.o.list = true
vim.o.listchars = "tab:▷ ,trail:·,nbsp:○"
-- Custom settings
vim.g.session_center_cursor = false
vim.g.ts_install = {
"bash",
"c",
"css",
"diff",
"go",
"html",
"javascript",
"json",
"lua",
"python",
"toml",
"tsx",
"typescript",
"yaml",
"zig",
}
vim.g.mason_install = {
"delve",
"deno",
"gopls",
"lua-language-server",
"prettier",
"shfmt",
"stylua",
}
vim.g.lsp_enable = {
"gopls",
"lua_ls",
}
local buf_name = function(buf)
return vim.api.nvim_buf_get_name(buf or 0)
end
---@type table<string, fun(line1:integer,line2:integer):FormatOpts|FormatOpts[]>
local formatters = {
stylua = function()
return { cmd = { "stylua", "--indent-type=Spaces", "--indent-width=2", "--stdin-filepath", buf_name(), "-" } }
end,
prettier = function()
return { cmd = { "prettier", "--stdin-filepath", buf_name() } }
end,
shfmt = function()
return { cmd = { "shfmt", "-" } }
end,
}
vim.g.formatconf = {
["javascript"] = formatters["prettier"],
["javascriptreact"] = formatters["prettier"],
["json"] = formatters["prettier"],
["jsonc"] = formatters["prettier"],
["lua"] = formatters["stylua"],
["markdown"] = formatters["prettier"],
["scss"] = formatters["prettier"],
["sh"] = formatters["shfmt"],
["typescript"] = formatters["prettier"],
["typescriptreact"] = formatters["prettier"],
["yaml"] = formatters["prettier"],
}
-- Core
require("vim._extui").enable({
msg = {
target = "cmd",
timeout = 4000,
},
})
-- -- Commands
vim.api.nvim_create_user_command("Mkdir", function(o)
local path = vim.fn.expand(o.args ~= "" and o.args or "%:p:h")
vim.fn.mkdir(path, "p")
end, { nargs = "?", complete = "dir" })
-- -- Mappings
vim.keymap.set("i", "<C-l>", "<Right>")
vim.keymap.set("n", "<Esc>", "<Cmd>nohlsearch<Enter>")
vim.keymap.set("n", "<Leader>w", "<Cmd>write<Enter>", { desc = "Save" })
vim.keymap.set("n", "<Leader>q", "<Cmd>quit<Enter>", { desc = "Quit" })
vim.keymap.set("n", "<Leader>Q", "<Cmd>quitall!<Enter>", { desc = "Quit all" })
vim.keymap.set("n", "<Leader>R", "<Cmd>write | restart<Enter>", { desc = "Restart" })
vim.keymap.set("n", "gA", "<Cmd>tabnew<Enter>", { desc = "Add tab" })
vim.keymap.set("n", "gC", "<Cmd>tabclose<Enter>", { desc = "Close tab" })
vim.keymap.set("n", "gy", function()
local copy = vim.fn.getreg('"')
if copy == "" then
return
end
local msg = ""
local _, ln = string.gsub(copy, "\n", "")
if ln > 0 then
msg = string.format('%s %s yanked into "+', ln, ln > 1 and "lines" or "line")
else
local ch = #copy
msg = string.format('%s %s yanked into "+', ch, ch > 1 and "chars" or "char")
end
vim.fn.setreg("+", copy)
vim.api.nvim_echo({ { msg } }, false, {})
end, { desc = "Yank last into clipboard" })
local qf_height = { l = 10, c = 10 }
local toggle_list = function(nr)
local mods = { split = "botright" }
local type, win
if nr then
type, win = "l", vim.fn.getloclist(nr, { winid = true }).winid
else
type, win = "c", vim.fn.getqflist({ winid = true }).winid
end
if win > 0 then
qf_height[type] = vim.api.nvim_win_get_height(win)
vim.cmd({ cmd = type .. "close", mods = mods })
else
vim.cmd({ cmd = type .. "open" })
vim.api.nvim_win_set_height(0, qf_height[type])
end
end
-- stylua: ignore
vim.keymap.set("n", "<Leader>L", function() toggle_list(0) end, { desc = "Toggle loc" })
-- stylua: ignore
vim.keymap.set("n", "<Leader>l", function() toggle_list() end, { desc = "Toggle qf" })
-- -- Autocmds
vim.api.nvim_create_autocmd("TextYankPost", {
desc = "Highlight yanking text",
group = vim.api.nvim_create_augroup("yank_highlight", { clear = true }),
callback = function()
vim.hl.on_yank()
end,
})
-- Plugins
vim.api.nvim_create_autocmd("PackChanged", {
pattern = "blink.cmp",
desc = "Run `:BlinkCmp build` after pack update",
group = vim.api.nvim_create_augroup("blink_update", { clear = true }),
callback = function(e)
if e.data.kind == "install" or e.data.kind == "update" then
vim.cmd.packadd({ args = { e.data.spec.name }, bang = false })
require("blink.cmp.fuzzy.build").build()
end
end,
})
vim.api.nvim_create_autocmd("PackChanged", {
pattern = "nvim-treesitter",
desc = "Run `:TSUpdate` after pack update",
group = vim.api.nvim_create_augroup("ts_update", { clear = true }),
callback = function(e)
if e.data.kind == "update" then
require("nvim-treesitter").update()
end
end,
})
vim.pack.add({
{ src = "https://github.com/folke/tokyonight.nvim" },
{ src = "https://github.com/akinsho/git-conflict.nvim" },
{ src = "https://github.com/Saghen/blink.cmp", version = "main" },
{ src = "https://github.com/MeanderingProgrammer/render-markdown.nvim" },
{ src = "https://github.com/nvim-mini/mini.nvim" },
{ src = "https://github.com/nvim-treesitter/nvim-treesitter", version = "main" },
{ src = "https://github.com/nvim-treesitter/nvim-treesitter-textobjects", version = "main" },
{ src = "https://github.com/mason-org/mason.nvim" },
{ src = "https://github.com/neovim/nvim-lspconfig" },
{ src = "https://github.com/mfussenegger/nvim-dap" },
{ src = "https://github.com/igorlfs/nvim-dap-view" },
{ src = "https://github.com/theHamsta/nvim-dap-virtual-text" },
})
-- -- Colorscheme
vim.api.nvim_create_autocmd("ColorScheme", {
pattern = "*",
desc = "Set the highlights for the `LspProgress` notify window",
group = vim.api.nvim_create_augroup("lsp_progress_hl", { clear = true }),
callback = function(e)
local hls = {
["habamax"] = "Normal",
["*"] = "Comment",
}
vim.api.nvim_set_hl(0, "LspProgress", { default = true, link = hls[e.match] or hls["*"] })
end,
})
require("tokyonight").setup({
on_highlights = function(hl, c)
hl.DiagnosticUnnecessary = {}
hl.LspProgress = { fg = c.comment }
end,
})
-- vim.cmd.colorscheme("miniwinter")
vim.cmd.colorscheme("tokyonight")
-- -- Completion
require("blink.cmp").setup({
keymap = {
["<C-n>"] = { "show_and_insert", "select_next" },
["<C-p>"] = { "show_and_insert", "select_prev" },
["<C-j>"] = { "select_and_accept" },
},
})
vim.keymap.set("i", "<C-x><C-o>", function()
require("blink.cmp").show()
require("blink.cmp").show_documentation()
require("blink.cmp").hide_documentation()
end, { desc = "Show completion" })
-- -- Markdown
require("render-markdown").setup({
checkbox = { enabled = false },
code = { sign = false, width = "full" },
heading = { icons = {} },
})
-- -- Mini
local MiniAi = require("mini.ai")
MiniAi.setup({
mappings = {
around_next = "",
inside_next = "",
around_last = "",
inside_last = "",
},
custom_textobjects = {
a = MiniAi.gen_spec.argument({ separator = ",%s*" }),
C = MiniAi.gen_spec.treesitter({ a = "@class.outer", i = "@class.inner" }),
F = MiniAi.gen_spec.treesitter({ a = "@function.outer", i = "@function.inner" }),
g = function()
local from = { line = 1, col = 1 }
local to = {
line = vim.fn.line("$"),
col = math.max(vim.fn.getline("$"):len(), 1),
}
return { from = from, to = to }
end,
t = { "<([%p%w]-)%f[^<%w][^<>]->.-</%1>", "^<.->().*()</[^/]->$" },
e = {
{
"%f[%a]%l+%d*",
"%f[%w]%d+",
"%f[%u]%u%f[%A]%d*",
"%f[%u]%u%l+%d*",
"%f[%u]%u%u+%d*",
},
},
},
})
local expand_separator = function(range)
local from, to = range.from, range.to
local line = function(r)
return assert(vim.api.nvim_buf_get_lines(0, r.line - 1, r.line, true)[1])
end
local left = line(from):sub(1, from.col - 1):find("[_%-]+$")
local _, right = line(to):find("^[_%-]+", to.col + 1)
-- stylua: ignore
if left then from.col = left elseif right then to.col = right end
return from, to
end
vim.keymap.set("o", "ae", function()
local range = MiniAi.find_textobject("i", "e")
if range then
local from, to = expand_separator(range)
vim.api.nvim_win_set_cursor(0, { from.line, from.col - 1 })
vim.cmd("normal! v")
vim.api.nvim_win_set_cursor(0, { to.line, to.col - 1 })
end
end)
local MiniSurround = require("mini.surround")
local surround_sel = function()
local mark1, mark2
if vim.v.operator == ":" then
mark1, mark2 = "<", ">"
else
mark1, mark2 = "[", "]"
end
local pos1 = vim.api.nvim_buf_get_mark(0, mark1)
local pos2 = vim.api.nvim_buf_get_mark(0, mark2)
local text = vim.api.nvim_buf_get_text(0, pos1[1] - 1, pos1[2], pos2[1] - 1, pos2[2] + 1, {})
return text, pos1, pos2
end
MiniSurround.setup({
mappings = {
find = "",
find_left = "",
highlight = "",
update_n_lines = "",
suffix_last = "",
suffix_next = "",
},
custom_surroundings = {
l = {
output = function()
if vim.b.minisurround_log_insert then
local sel_lines = surround_sel()
local sel = vim.trim(table.concat(sel_lines, "\n"))
local row = vim.fn.line(".")
local log = string.format(vim.b.minisurround_log_insert, sel, sel)
vim.api.nvim_buf_set_lines(0, row, row, true, { log })
vim.cmd("normal j==0^")
end
end,
},
},
})
local MiniClue = require("mini.clue")
vim.keymap.set("n", "<C-w>rq", "<nop>", { desc = "Quit" })
vim.keymap.set("n", "<C-w>rH", "<C-w>h", { remap = true, desc = "Move left" })
vim.keymap.set("n", "<C-w>rJ", "<C-w>j", { remap = true, desc = "Move down" })
vim.keymap.set("n", "<C-w>rK", "<C-w>k", { remap = true, desc = "Move up" })
vim.keymap.set("n", "<C-w>rL", "<C-w>l", { remap = true, desc = "Move right" })
local resize = function(dir)
local step = { h = 4, v = 2 }
if dir == "h" then
vim.fn.win_move_separator(vim.fn.winnr("h"), -step.h)
elseif dir == "l" then
vim.fn.win_move_separator(vim.fn.winnr("h"), step.h)
elseif dir == "k" then
vim.fn.win_move_statusline(vim.fn.winnr("k"), -step.v)
elseif dir == "j" then
vim.fn.win_move_statusline(vim.fn.winnr("k"), step.v)
end
end
-- stylua: ignore start
vim.keymap.set("n", "<C-w>rh", function() resize("h") end, { desc = "Resize left" })
vim.keymap.set("n", "<C-w>rj", function() resize("j") end, { desc = "Resize down" })
vim.keymap.set("n", "<C-w>rk", function() resize("k") end, { desc = "Resize up" })
vim.keymap.set("n", "<C-w>rl", function() resize("l") end, { desc = "Resize right" })
-- stylua: ignore end
MiniClue.gen_clues.resize = function()
return {
{ mode = "n", keys = "<C-w>rq" },
{ mode = "n", keys = "<C-w>rH", postkeys = "<C-w>r" },
{ mode = "n", keys = "<C-w>rJ", postkeys = "<C-w>r" },
{ mode = "n", keys = "<C-w>rK", postkeys = "<C-w>r" },
{ mode = "n", keys = "<C-w>rL", postkeys = "<C-w>r" },
{ mode = "n", keys = "<C-w>rh", postkeys = "<C-w>r" },
{ mode = "n", keys = "<C-w>rj", postkeys = "<C-w>r" },
{ mode = "n", keys = "<C-w>rk", postkeys = "<C-w>r" },
{ mode = "n", keys = "<C-w>rl", postkeys = "<C-w>r" },
}
end
MiniClue.setup({
triggers = {
{ mode = "n", keys = "<C-w>r" },
{ mode = "n", keys = "<Leader>" },
{ mode = "x", keys = "<Leader>" },
{ mode = "n", keys = "[" },
{ mode = "n", keys = "]" },
{ mode = "i", keys = "<C-x>" },
{ mode = "n", keys = "g" },
{ mode = "x", keys = "g" },
{ mode = "n", keys = "'" },
{ mode = "n", keys = "`" },
{ mode = "x", keys = "'" },
{ mode = "x", keys = "`" },
{ mode = "n", keys = '"' },
{ mode = "x", keys = '"' },
{ mode = "i", keys = "<C-r>" },
{ mode = "c", keys = "<C-r>" },
{ mode = "n", keys = "<C-w>" },
{ mode = "n", keys = "z" },
{ mode = "x", keys = "z" },
},
clues = {
MiniClue.gen_clues.resize(),
MiniClue.gen_clues.square_brackets(),
MiniClue.gen_clues.builtin_completion(),
MiniClue.gen_clues.g(),
MiniClue.gen_clues.marks(),
MiniClue.gen_clues.registers(),
MiniClue.gen_clues.windows(),
MiniClue.gen_clues.z(),
},
})
local MiniDiff = require("mini.diff")
MiniDiff.setup({
mappings = {
textobject = "ih",
-- apply = "gh",
-- reset = "gH",
goto_prev = "[h",
goto_next = "]h",
},
})
local hunk_action = function(mode)
return function()
return MiniDiff.operator(mode) .. MiniDiff.config.mappings.textobject
end
end
vim.keymap.set("n", "gh", hunk_action("apply"), { expr = true, remap = true, desc = "Apply hunk" })
vim.keymap.set("n", "gH", hunk_action("reset"), { expr = true, remap = true, desc = "Reset hunk" })
local MiniExtra = require("mini.extra")
MiniExtra.setup()
-- stylua: ignore
vim.keymap.set("n", "<Leader>sc", function() MiniExtra.pickers.colorschemes() end, { desc = "Search colorschemes" })
local MiniFiles = require("mini.files")
MiniFiles.setup({
windows = {
width_preview = 100,
},
})
local set_bookmark = function(id, path, opts)
MiniFiles.set_bookmark(id, function()
path = vim.is_callable(path) and path() or path
if type(path) ~= "string" then
return path
end
path = vim.fs.abspath(path)
local stat = vim.uv.fs_stat(path)
if not stat then
return path
end
if stat.type == "directory" then
return path
else
vim.schedule(function()
if vim.bo.ft == "minifiles" then
local buf = 0
local win = 0
for line = 1, vim.api.nvim_buf_line_count(buf) do
local entry = MiniFiles.get_fs_entry(buf, line)
if entry.path == path then
vim.api.nvim_win_set_cursor(win, { line, 0 })
end
end
end
end)
return vim.fs.dirname(path)
end
end, opts)
end
-- stylua: ignore
vim.keymap.set("n", "<Leader>F", function() MiniFiles.open() end, { desc = "Open files" })
vim.api.nvim_create_augroup("mini_files", { clear = true })
local files_main = nil
local files_open = MiniFiles.open
MiniFiles.open = function(...)
if vim.bo.ft ~= "minifiles" then
files_main = vim.api.nvim_get_current_buf()
end
return files_open(...)
end
vim.api.nvim_create_autocmd("User", {
pattern = "MiniFilesExplorerOpen",
group = "mini_files",
callback = function()
if files_main then
set_bookmark("%", vim.api.nvim_buf_get_name(files_main), { desc = "Entry file" })
end
set_bookmark("@", vim.fn.getcwd, { desc = "Cwd" })
set_bookmark("n", vim.fn.stdpath("config") .. "/init.lua", { desc = "Config" })
set_bookmark("p", vim.fn.stdpath("data") .. "/site/pack/core/opt", { desc = "Plugins" })
end,
})
vim.api.nvim_create_autocmd("User", {
pattern = "MiniFilesBufferCreate",
group = "mini_files",
callback = function(e)
local buf = e.data.buf_id
vim.keymap.set("n", "<M-p>", function()
local preview = MiniFiles.config.windows.preview
local preview_next = not preview
MiniFiles.config.windows.preview = preview_next
MiniFiles.refresh({ windows = { preview = preview_next } })
if preview then
local branch = MiniFiles.get_explorer_state().branch
table.remove(branch)
MiniFiles.set_branch(branch)
end
end, { buffer = buf, desc = "Toggle preview" })
local minipick = require("mini.pick")
vim.keymap.set("n", "<Leader>sg", function()
local entry = MiniFiles.get_fs_entry()
if not entry then
return
end
local parent = vim.fn.fnamemodify(entry.path, ":h")
if entry.fs_type == "directory" then
minipick.builtin.grep({ pattern = "." }, { source = { cwd = parent } })
else
local name = vim.fn.fnamemodify(entry.path, ":t")
minipick.builtin.grep({ pattern = ".", globs = { name } }, { source = { cwd = parent } })
end
end, { buffer = buf, desc = "Search folder" })
vim.keymap.set("n", "<Leader>sf", function()
local entry = MiniFiles.get_fs_entry()
if not entry then
return
end
local parent = vim.fn.fnamemodify(entry.path, ":h")
minipick.builtin.files(nil, { source = { cwd = parent } })
end, { buffer = buf, desc = "Search folder" })
end,
})
vim.api.nvim_create_autocmd("User", {
pattern = "MiniFilesWindowUpdate",
group = "mini_files",
callback = function(e)
local win = e.data.win_id
vim.wo[win].number = true
vim.wo[win].relativenumber = true
end,
})
local MiniGit = require("mini.git")
MiniGit.setup()
vim.cmd.cnoreabbrev("G", "Git")
vim.api.nvim_create_autocmd("User", {
pattern = "MiniGitCommandSplit",
desc = "Enhance `Git blame`: colorize buffer and set width for vertical split",
group = vim.api.nvim_create_augroup("mini_gitblame", { clear = true }),
callback = function(e)
if e.data.git_subcommand ~= "blame" then
return
end
local win_src = e.data.win_source
local buf = e.buf
local win = e.data.win_stdout
vim.bo[buf].modifiable = false
vim.wo[win].wrap = false
vim.wo[win].cursorline = true
vim.fn.winrestview({ topline = vim.fn.line("w0", win_src) })
vim.api.nvim_win_set_cursor(0, { vim.fn.line(".", win_src), 0 })
vim.wo[win].scrollbind, vim.wo[win_src].scrollbind = true, true
vim.wo[win].cursorbind, vim.wo[win_src].cursorbind = true, true
if string.match(e.data.cmd_input.mods, "vertical") then
local lines = vim.api.nvim_buf_get_lines(0, 1, -1, false)
local width = vim.iter(lines):fold(-1, function(acc, ln)
local stat = string.match(ln, "^[%w%p]+ %b()")
return math.max(acc, vim.fn.strwidth(stat))
end)
width = width + vim.fn.getwininfo(win)[1].textoff
vim.api.nvim_win_set_width(win, width)
end
local leftmost = [[^.\{-}\zs]]
-- stylua: ignore start
--[[ ^hash ]] vim.fn.matchadd("Tag", [[^^\w\+]])
--[[ hash ]] vim.fn.matchadd("Identifier", [[^\w\+]])
--[[ author ]] vim.fn.matchadd("String", leftmost .. [[(\zs.\{-} \ze\d\{4}-]])
--[[ date ]] vim.fn.matchadd("Comment", leftmost .. [[[0-9-]\{10} [0-9:]\{8} [+-]\d\+]])
end,
})
local MiniHipatterns = require("mini.hipatterns")
vim.api.nvim_create_autocmd({ "VimEnter", "ColorScheme" }, {
desc = "Add additional highlights for `mini.hipatterns`",
group = vim.api.nvim_create_augroup("todo_highlight", { clear = true }),
callback = function()
local get = function(name)
return vim.api.nvim_get_hl(0, { name = name, link = false })
end
local make = function(name, fg, bg)
vim.api.nvim_set_hl(0, name, { bold = true, fg = fg, bg = bg })
end
make("UserHipatternsPerf", "black", get("Identifier").fg)
end,
})
local hi_todo = function(words, hl_name)
local pattern = vim
.iter(words)
:map(function(word)
return { "()%f[%w]" .. word .. "%f[%W]()", "() " .. word .. "[: ]()" }
end)
:flatten()
:totable()
return {
pattern = pattern,
group = function(b, _, d)
local parser = vim.treesitter.get_parser(b, nil, { error = false })
if not parser then
return
end
local node = parser:named_node_for_range({
d.line - 1,
d.from_col - 1,
d.line - 1,
d.to_col - 1,
})
if node and node:type() == "comment_content" then
return hl_name
end
end,
}
end
local tw_store = {
hl = {},
-- stylua: ignore
cl = {
slate={[50]="f8fafc",[100]="f1f5f9",[200]="e2e8f0",[300]="cbd5e1",[400]="94a3b8",
[500]="64748b",[600]="475569",[700]="334155",[800]="1e293b",[900]="0f172a",[950]="020617"},
gray={[50]="f9fafb",[100]="f3f4f6",[200]="e5e7eb",[300]="d1d5db",[400]="9ca3af",
[500]="6b7280",[600]="4b5563",[700]="374151",[800]="1f2937",[900]="111827",[950]="030712"},
zinc={[50]="fafafa",[100]="f4f4f5",[200]="e4e4e7",[300]="d4d4d8",[400]="a1a1aa",
[500]="71717a",[600]="52525b",[700]="3f3f46",[800]="27272a",[900]="18181b",[950]="09090B"},
neutral={[50]="fafafa",[100]="f5f5f5",[200]="e5e5e5",[300]="d4d4d4",[400]="a3a3a3",
[500]="737373",[600]="525252",[700]="404040",[800]="262626",[900]="171717",[950]="0a0a0a"},
stone={[50]="fafaf9",[100]="f5f5f4",[200]="e7e5e4",[300]="d6d3d1",[400]="a8a29e",
[500]="78716c",[600]="57534e",[700]="44403c",[800]="292524",[900]="1c1917",[950]="0a0a0a"},
red={[50]="fef2f2",[100]="fee2e2",[200]="fecaca",[300]="fca5a5",[400]="f87171",
[500]="ef4444",[600]="dc2626",[700]="b91c1c",[800]="991b1b",[900]="7f1d1d",[950]="450a0a"},
orange={[50]="fff7ed",[100]="ffedd5",[200]="fed7aa",[300]="fdba74",[400]="fb923c",
[500]="f97316",[600]="ea580c",[700]="c2410c",[800]="9a3412",[900]="7c2d12",[950]="431407"},
amber={[50]="fffbeb",[100]="fef3c7",[200]="fde68a",[300]="fcd34d",[400]="fbbf24",
[500]="f59e0b",[600]="d97706",[700]="b45309",[800]="92400e",[900]="78350f",[950]="451a03"},
yellow={[50]="fefce8",[100]="fef9c3",[200]="fef08a",[300]="fde047",[400]="facc15",
[500]="eab308",[600]="ca8a04",[700]="a16207",[800]="854d0e",[900]="713f12",[950]="422006"},
lime={[50]="f7fee7",[100]="ecfccb",[200]="d9f99d",[300]="bef264",[400]="a3e635",
[500]="84cc16",[600]="65a30d",[700]="4d7c0f",[800]="3f6212",[900]="365314",[950]="1a2e05"},
green={[50]="f0fdf4",[100]="dcfce7",[200]="bbf7d0",[300]="86efac",[400]="4ade80",
[500]="22c55e",[600]="16a34a",[700]="15803d",[800]="166534",[900]="14532d",[950]="052e16"},
emerald={[50]="ecfdf5",[100]="d1fae5",[200]="a7f3d0",[300]="6ee7b7",[400]="34d399",
[500]="10b981",[600]="059669",[700]="047857",[800]="065f46",[900]="064e3b",[950]="022c22"},
teal={[50]="f0fdfa",[100]="ccfbf1",[200]="99f6e4",[300]="5eead4",[400]="2dd4bf",
[500]="14b8a6",[600]="0d9488",[700]="0f766e",[800]="115e59",[900]="134e4a",[950]="042f2e"},
cyan={[50]="ecfeff",[100]="cffafe",[200]="a5f3fc",[300]="67e8f9",[400]="22d3ee",
[500]="06b6d4",[600]="0891b2",[700]="0e7490",[800]="155e75",[900]="164e63",[950]="083344"},
sky={[50]="f0f9ff",[100]="e0f2fe",[200]="bae6fd",[300]="7dd3fc",[400]="38bdf8",
[500]="0ea5e9",[600]="0284c7",[700]="0369a1",[800]="075985",[900]="0c4a6e",[950]="082f49"},
blue={[50]="eff6ff",[100]="dbeafe",[200]="bfdbfe",[300]="93c5fd",[400]="60a5fa",
[500]="3b82f6",[600]="2563eb",[700]="1d4ed8",[800]="1e40af",[900]="1e3a8a",[950]="172554"},
indigo={[50]="eef2ff",[100]="e0e7ff",[200]="c7d2fe",[300]="a5b4fc",[400]="818cf8",
[500]="6366f1",[600]="4f46e5",[700]="4338ca",[800]="3730a3",[900]="312e81",[950]="1e1b4b"},
violet={[50]="f5f3ff",[100]="ede9fe",[200]="ddd6fe",[300]="c4b5fd",[400]="a78bfa",
[500]="8b5cf6",[600]="7c3aed",[700]="6d28d9",[800]="5b21b6",[900]="4c1d95",[950]="2e1065"},
purple={[50]="faf5ff",[100]="f3e8ff",[200]="e9d5ff",[300]="d8b4fe",[400]="c084fc",
[500]="a855f7",[600]="9333ea",[700]="7e22ce",[800]="6b21a8",[900]="581c87",[950]="3b0764"},
fuchsia={[50]="fdf4ff",[100]="fae8ff",[200]="f5d0fe",[300]="f0abfc",[400]="e879f9",
[500]="d946ef",[600]="c026d3",[700]="a21caf",[800]="86198f",[900]="701a75",[950]="4a044e"},
pink={[50]="fdf2f8",[100]="fce7f3",[200]="fbcfe8",[300]="f9a8d4",[400]="f472b6",
[500]="ec4899",[600]="db2777",[700]="be185d",[800]="9d174d",[900]="831843",[950]="500724"},
rose={[50]="fff1f2",[100]="ffe4e6",[200]="fecdd3",[300]="fda4af",[400]="fb7185",
[500]="f43f5e",[600]="e11d48",[700]="be123c",[800]="9f1239",[900]="881337",[950]="4c0519"},
},
}
vim.api.nvim_create_autocmd("ColorScheme", {
desc = "Reset tailwind hl-store on colorscheme change",
group = vim.api.nvim_create_augroup("reset_tailwind_hl", { clear = true }),
callback = function()
tw_store.hl = {}
end,
})
MiniHipatterns.setup({
highlighters = {
fix = hi_todo({ "FIX", "FIXME" }, "MiniHipatternsFixme"),
note = hi_todo({ "NOTE" }, "MiniHipatternsNote"),
todo = hi_todo({ "TODO", "FEAT" }, "MiniHipatternsTodo"),
hack = hi_todo({ "HACK" }, "MiniHipatternsHack"),
perf = hi_todo({ "PERF" }, "UserHipatternsPerf"),
hex_color = MiniHipatterns.gen_highlighter.hex_color(),
hex_color_short = {
pattern = "()#%x%x%x()%f[^%x%w]",
group = function(_, _, data)
local match = data.full_match
local r, g, b = match:sub(2, 2), match:sub(3, 3), match:sub(4, 4)
local hex_color = "#" .. r .. r .. g .. g .. b .. b
return MiniHipatterns.compute_hex_color_group(hex_color, "bg")
end,
},
hsl_color = {
-- NOTE: Partial support for CSS hsl()
pattern = "hsl%(%d+[, ] ?%d+%%?[, ] ?%d+%%?%)",
group = function(_, m, _)
-- https://www.w3.org/TR/css-color-3/#hsl-color
local function hsl_to_rgb(h, s, l)
h, s, l = h % 360, s / 100, l / 100
if h < 0 then
h = h + 360
end
local function f(n)
local k = (n + h / 30) % 12
local a = s * math.min(l, 1 - l)
return l - a * math.max(-1, math.min(k - 3, 9 - k, 1))
end
return f(0) * 255, f(8) * 255, f(4) * 255
end
local h, s, l = m:match("(%d+)[, ] ?(%d+)%%?[, ] ?(%d+)%%?")
local r, g, b = hsl_to_rgb(h, s, l)
local hex = string.format("#%02x%02x%02x", r, g, b)
return MiniHipatterns.compute_hex_color_group(hex)
end,
},
tailwind = {
pattern = function()
local ft = {
"css",
"html",
"javascript",
"javascriptreact",
"svelte",
"typescript",
"typescriptreact",
"vue",
}
if not vim.tbl_contains(ft, vim.bo.filetype) then
return
end
return "%f[%w:-]()[%w:-]+%-[a-z%-]+%-%d+()%f[^%w:-]"
-- compact
-- return "%f[%w:-][%w:-]+%-()[a-z%-]+%-%d+()%f[^%w:-]"
end,
group = function(_, _, d)
local match = d.full_match
local color, shade = match:match("[%w-]+%-([a-z%-]+)%-(%d+)")
shade = tonumber(shade)
local bg = vim.tbl_get(tw_store.cl, color, shade)
if bg then
local hl = "MiniHipatternsTailwind" .. color .. shade
if not tw_store.hl[hl] then
tw_store.hl[hl] = true
local bg_shade = shade == 500 and 950 or shade < 500 and 900 or 100
local fg = vim.tbl_get(tw_store.cl, color, bg_shade)
vim.api.nvim_set_hl(0, hl, { bg = "#" .. bg, fg = "#" .. fg })
end
return hl
end
end,
},
},
})
local MiniIndentscope = require("mini.indentscope")
vim.g.miniindentscope_disable = true
MiniIndentscope.setup({
mappings = {
object_scope = "ii",
object_scope_with_border = "ai",
goto_top = "[i",
goto_bottom = "]i",
},
options = {
indent_at_cursor = false,
},
})
vim.keymap.set("n", "grs", function()
return "<Cmd>sil norm " .. (vim.v.count > 1 and vim.v.count - 1 .. "[i" or "") .. "viiyvaipgv<<Enter>"
end, { expr = true, desc = "Replace scope" })
local MiniJump2d = require("mini.jump2d")
MiniJump2d.setup({ mappings = { start_jumping = "" } })
vim.keymap.set("n", "<S-Enter>", function()
MiniJump2d.start(MiniJump2d.builtin_opts.query)
end, { desc = "Jump2d" })
-- local MiniKeymap = require("mini.keymap")
-- MiniKeymap.map_combo("i", ">", function()
-- local row, col = unpack(vim.api.nvim_win_get_cursor(0))
-- local line = vim.api.nvim_get_current_line()
-- if line:sub(col + 1, col + 1) == "<" then
-- return
-- end
-- local tag = line:sub(1, col):match("<([%l%d:%-]+)[^<>]*>$")
-- if not tag then
-- return
-- end
-- local close = ("</%s>"):format(tag)
-- row = row - 1
-- vim.api.nvim_buf_set_text(0, row, col, row, col, { close })
-- end)
local MiniMisc = require("mini.misc")
MiniMisc.setup_restore_cursor({ center = vim.g.session_center_cursor })
local MiniSessions = require("mini.sessions")
function _G.find_root(buf)
return vim.lsp.buf.list_workspace_folders()[1]
or vim.fs.root(buf or 0, {
".git",
"Makefile",
"package.json",
})
end
MiniSessions.get_current = function()
local name = string.gsub(find_root(0) or "", "/", "%%")
return name
end
MiniSessions.setup({
directory = vim.fn.stdpath("state") .. "/sessions",
autowrite = true,
hooks = {
pre = {
write = function()
vim.fn.mkdir(MiniSessions.config.directory, "p")
end,
},
post = {
read = function()
if vim.g.session_center_cursor then
vim.cmd('normal! zz"')
end
end,
},
},
})
vim.cmd.cnoreabbrev("Lo", "Load")
vim.api.nvim_create_user_command("Load", function()
MiniSessions.read(MiniSessions.get_current())
end, {})
vim.cmd.cnoreabbrev("La", "Last")
vim.api.nvim_create_user_command("Last", function()
MiniSessions.read(MiniSessions.get_latest())
end, {})
if vim.fn.argc() == 0 then
vim.api.nvim_create_autocmd("VimEnter", {
desc = "Read session on `vim` with no args",
group = vim.api.nvim_create_augroup("read_session", { clear = true }),
nested = true,
callback = function()
local name = MiniSessions.get_current()
if name == "" then
return
end
MiniSessions.read(name)
end,
})
end
local MiniMove = require("mini.move")
MiniMove.setup({
mappings = {
left = "<C-h>",
down = "<C-j>",
up = "<C-k>",
right = "<C-l>",
line_left = "",
line_down = "",
line_up = "",
line_right = "",
},
})
local MiniPairs = require("mini.pairs")
MiniPairs.setup({
mappings = {
["("] = { neigh_pattern = "[^\\][%s>)%]},:]" },
["["] = { neigh_pattern = "[^\\][%s>)%]},:]" },
["{"] = { neigh_pattern = "[^\\][%s>)%]},:]" },
['"'] = { neigh_pattern = "[%s<(%[{][%s>)%]},:]" },
["'"] = { neigh_pattern = "[%s<(%[{][%s>)%]},:]" },
["`"] = { neigh_pattern = "[%s<(%[{][%s>)%]},:]" },
["<"] = { action = "open", pair = "<>", neigh_pattern = "[\r%w\"'`].", register = { cr = false } },
[">"] = { action = "close", pair = "<>", register = { cr = false } },
},
})
require("mini.keymap").map_combo("i", "<", function()
local line = vim.api.nvim_get_current_line()
local col = vim.fn.col(".")
-- stylua: ignore
if line:sub(col - 2, col) == "<<>" then return "<Del>" end
end)
require("mini.keymap").map_combo("i", "=", function()
local line = vim.api.nvim_get_current_line()
local col = vim.fn.col(".")
-- stylua: ignore
if line:sub(col - 2, col) == "<=>" then return "<Del>" end
end)
local MiniPick = require("mini.pick")
local minipick_remap = function(lhs, rhs)
-- stylua: ignore
return { char = lhs, func = function() vim.api.nvim_input(rhs) end }
end
MiniPick.setup({
mappings = {
move_down = "<C-n>",
move_up = "<C-p>",
move_down_2 = minipick_remap("<C-j>", "<C-n>"),
move_up_2 = minipick_remap("<C-k>", "<C-p>"),
reveal_file = {
char = "<S-Enter>",
func = function()
local is_file = function(item)
local ok, stat = pcall(vim.uv.fs_stat, item)
return ok and stat ~= nil
end
local matches = MiniPick.get_picker_matches()
local current = matches.current
if not is_file(current) then
return
end
vim.schedule(function()
local minifiles = require("mini.files")
minifiles.open(current, false)
minifiles.reveal_cwd()
end)
return true
end,
},
},
})
vim.keymap.set("n", "<Leader>sf", function()
MiniPick.builtin.cli({
command = { "fd", "-t=f", "-H", "-I", "-E=.git", "-E=node_modules" },
}, {
source = {
name = "Files (fd)",
show = function(buf, items, query)
MiniPick.default_show(buf, items, query, { show_icons = true })
end,
},
})
end, { desc = "Seach files" })
-- stylua: ignore start
vim.keymap.set("n", "<Leader>sb", function() MiniPick.builtin.buffers() end, { desc = "Seach buffers" })
vim.keymap.set("n", "<Leader>sg", function() MiniPick.builtin.grep_live() end, { desc = "Seach grep" })
vim.keymap.set("n", "<Leader>sh", function() MiniPick.builtin.help() end, { desc = "Seach help" })
vim.keymap.set("n", "<Leader>sr", function() MiniPick.builtin.resume() end, { desc = "Seach resume" })
-- stylua: ignore end
local MiniSplitjoin = require("mini.splitjoin")
local gen_hook = MiniSplitjoin.gen_hook
MiniSplitjoin.setup({
mappings = { toggle = "gs" },
split = {
hooks_post = {
gen_hook.add_trailing_separator({ brackets = { "%b{}" } }),
},
},
join = {
hooks_post = {
gen_hook.pad_brackets({ brackets = { "%b{}" } }),
},
},
})
-- -- Treesitter
vim.treesitter.language.register("tsx", "typescriptreact")
local ts_install = vim.g.ts_install or {}
local ts_filetypes = vim
.iter(ts_install)
:map(function(lang)
return vim.treesitter.language.get_filetypes(lang)
end)
:flatten()
:totable()
require("nvim-treesitter").install(ts_install)
vim.api.nvim_create_autocmd("FileType", {
desc = "Setup treesitter for a buffer",
pattern = ts_filetypes,
group = vim.api.nvim_create_augroup("ts_setup", { clear = true }),
callback = function(e)
vim.treesitter.start(e.buf)
vim.wo.foldmethod = "expr"
vim.wo.foldexpr = "v:lua.vim.treesitter.foldexpr()"
vim.bo.indentexpr = "v:lua.require'nvim-treesitter'.indentexpr()"
end,
})
-- -- Mason
local mason_install = vim.g.mason_install or {}
require("mason").setup()
local mason_available = require("mason-registry").get_installed_package_names()
local mason_rest = {}
for _, inst in ipairs(mason_install) do
if not vim.list_contains(mason_available, inst) then
table.insert(mason_rest, inst)
end
end
if #mason_rest > 0 then
vim.cmd("MasonInstall " .. table.concat(mason_rest, " "))
end
-- -- LSP
local lsp_enable = vim.g.lsp_enable or {}
vim.lsp.enable(lsp_enable)
vim.diagnostic.config({ virtual_text = true })
vim.keymap.set("n", "gK", function()
local enable = not vim.diagnostic.config().virtual_text
vim.diagnostic.config({ virtual_text = enable, underline = enable })
end, { desc = "Toggle diagnostic" })
vim.api.nvim_create_autocmd("LspAttach", {
desc = "Enable inlay hints",
group = vim.api.nvim_create_augroup("inlay_hints", { clear = true }),
callback = function(e)
local client = assert(vim.lsp.get_client_by_id(e.data.client_id))
if client:supports_method(vim.lsp.protocol.Methods.textDocument_inlayHint) then
vim.lsp.inlay_hint.enable(true, { bufnr = e.buf })
end
end,
})
vim.schedule(function()
local au = vim.api.nvim_create_augroup("lsp_progress", { clear = true })
local ns = vim.api.nvim_create_namespace("lsp_progress")
local timer = assert(vim.uv.new_timer())
local buf = -1
local win = -1
-- Utils
local text_overflow = function(line, max_width)
if #line <= max_width then
return line
end
local ell = "..."
local cut = max_width - vim.fn.strwidth(ell)
if cut <= 0 then
return ell .. line
end
return line:sub(1, cut) .. ell
end
--
local lsp_notify = function(lines, hl, keep_ms)
hl = hl or "Comment"
keep_ms = keep_ms or nil
if vim.tbl_isempty(lines) then
return
end
local vpad, hpad = 0, 0
local min_width, min_height = 1, 1
local max_width, max_height = vim.o.columns / 3, vim.o.lines - 5
--
local text_width = vim.iter(lines):fold(1, function(max, val)
return math.max(max, #val)
end)
local width = math.max(min_width, math.min(text_width, max_width))
local height = math.max(min_height, math.min(#lines, max_height))
local win_config = { ---@type vim.api.keyset.win_config
relative = "editor",
anchor = "SE",
row = vim.o.lines - 2,
col = vim.o.columns,
width = width + hpad * 2,
height = height + vpad * 2,
zindex = 100,
style = "minimal",
focusable = false,
border = "single",
}
-- Create/update window
if not vim.api.nvim_buf_is_valid(buf) then
buf = vim.api.nvim_create_buf(false, true)
end
if not vim.api.nvim_win_is_valid(win) then
win = vim.api.nvim_open_win(buf, false, win_config)
else
vim.api.nvim_win_set_config(win, win_config)
vim.api.nvim_win_set_buf(win, buf)
end
vim.bo[buf].ft = "lsp_progress"
vim.wo[win].winhighlight = "NormalFloat:FloatBorder,Search:None,CurSearch:None"
--
local buf_lines = lines
-- Cut lines
local cut_edge = vim.api.nvim_win_get_width(win) - hpad * 2
for i, line in ipairs(buf_lines) do
buf_lines[i] = text_overflow(line, cut_edge)
end
-- Pad lines
local padded = {}
local hp = string.rep(" ", hpad)
local vline = string.rep(" ", width + hpad * 2)
local vp = vim.fn["repeat"]({ vline }, vpad)
vim.list_extend(padded, vp)
for _, line in ipairs(lines) do
table.insert(padded, hp .. line .. hp)
end
vim.list_extend(padded, vp)
buf_lines = padded
-- Set lines
vim.api.nvim_buf_set_lines(buf, 0, -1, false, buf_lines)
vim.hl.range(buf, ns, hl, { 0, 0 }, { #buf_lines, -1 })
-- Shedule closing
if keep_ms and keep_ms > 1 then
timer:start(keep_ms, 0, function()
timer:stop()
vim.schedule(function()
if vim.api.nvim_win_is_valid(win) then
vim.api.nvim_win_close(win, true)
end
end)
end)
end
end
vim.api.nvim_create_autocmd("LspProgress", {
desc = "Show LSP progress status",
group = au,
callback = function()
local msg = string.gsub(vim.lsp.status(), "^%s*%d+%%: ", "")
local msg_lines = vim.split(msg, ", ")
lsp_notify(msg_lines, "LspProgress", 1500)
end,
})
end)
-- -- Debug
local dap = require("dap")
local dap_view = require("dap-view")
dap_view.setup()
require("nvim-dap-virtual-text").setup()
-- stylua: ignore start
vim.keymap.set("n", "<Leader>b", function() dap.toggle_breakpoint() end, { desc = "Breakpoint" })
vim.keymap.set("n", "<Leader>B", function() dap.set_breakpoint(vim.fn.input('Breakpoint condition: ')) end, { desc = "Breakpoint condition" })
vim.keymap.set("n", "<Leader>dc", function() dap.continue() end, { desc = "Run/continue" })
vim.keymap.set("n", "<Leader>dp", function() dap.pause() end, { desc = "Pause" })
vim.keymap.set("n", "<Leader>di", function() dap.step_into() end, { desc = "Step into" })
vim.keymap.set("n", "<Leader>do", function() dap.step_over() end, { desc = "Step over" })
vim.keymap.set("n", "<Leader>dO", function() dap.step_out() end, { desc = "Step out" })
vim.keymap.set("n", "<Leader>db", function() dap.step_back() end, { desc = "Debug step back" })
vim.keymap.set("n", "<Leader>df", function() dap.restart_frame() end, { desc = "Debug step back" })
vim.keymap.set("n", "<Leader>dl", function() dap.run_last() end, { desc = "Run Last" })
vim.keymap.set("n", "<Leader>dq", function() dap.terminate() end, { desc = "Terminate" })
vim.keymap.set("n", "<Leader>de", function() dap.eval(nil, { enter = true }) end, { desc = "Eval" })
vim.keymap.set("n", "<Leader>dw", function() dap_view.toggle() end, { desc = "Widgets" })
-- stylua: ignore end
-- vim.keymap.set("n", "<Leader>dq", "<nop>", { desc = "Quit" })
-- MiniClue.gen_clues.debug = function()
-- return {
-- { mode = "n", keys = "<Leader>dq" },
-- { mode = "n", keys = "<Leader>dc", postkeys = "<Leader>d" },
-- }
-- end
-- vim.list_extend(MiniClue.config.triggers, { mode = "n", keys = "<Leader>d" })
-- vim.list_extend(MiniClue.config.clues, MiniClue.gen_clues.debug())
-- stylua: ignore start
dap.listeners.before.attach.dapui_config = function() dap.view.open() end
dap.listeners.before.launch.dapui_config = function() dap.view.open() end
dap.listeners.before.event_terminated.dapui_config = function() dap_view.close() end
dap.listeners.before.event_exited.dapui_config = function() dap_view.close() end
-- stylua: ignore end
-- -- -- Go
-- https://codeberg.org/mfussenegger/nvim-dap/wiki/Debug-Adapter-installation#go-using-delve-directly
dap.adapters.delve = function(callback, config)
if config.mode == "remote" and config.request == "attach" then
callback({
type = "server",
host = config.host or "127.0.0.1",
port = config.port or "38697",
})
else
callback({
type = "server",
port = "${port}",
executable = {
command = "dlv",
args = { "dap", "-l", "127.0.0.1:${port}", "--log", "--log-output=dap" },
detached = vim.fn.has("win32") == 0,
},
})
end
end
dap.configurations.go = {
{
type = "delve",
name = "Debug",
request = "launch",
program = "${file}",
},
{
type = "delve",
name = "Debug test",
request = "launch",
mode = "test",
program = "${file}",
},
{
type = "delve",
name = "Debug test (go.mod)",
request = "launch",
mode = "test",
program = "./${relativeFileDirname}",
},
}
-- Custom
-- -- Format
---@class FormatOpts
---@field cmd string[]
---@field stdin? [integer,integer]
---@field range? [integer,integer]
---@field transform? fun(out: string): string[]
---@field diff? "any"|"none"|"overlap"|"contain"
---@field diff_algorithm? "myers"|"minimal"|"patience"|"histogram"
---@field timeout? integer
---@param buf? integer
---@param opts? FormatOpts
local function format_buf(buf, opts)
buf = buf or 0
opts = vim.tbl_extend("keep", opts or {}, {
cmd = nil,
stdin = {}, -- [line1, line2)
range = {}, -- [line1, line2)
transform = function(out)
return vim.split(out, "\n")
end,
diff = "overlap",
diff_algorithm = "histogram",
timeout = 2500,
})
local cmd = opts.cmd
if not vim.islist(cmd) then
vim.notify("Invalid 'cmd': expected a list of strings", vim.log.levels.ERROR)
return
end
local stdin1 = opts.stdin[1] or 1
local stdin2 = opts.stdin[2] or vim.api.nvim_buf_line_count(buf) + 1
local range1 = opts.range[1] or stdin1
local range2 = opts.range[2] or stdin2
local mode = vim.fn.mode()
if vim.tbl_isempty(opts.range) and mode:match("[vV]") then
local v1 = vim.api.nvim_win_get_cursor(0)[1]
local v2 = vim.fn.getpos("v")[2]
range1 = math.min(v1, v2)
range2 = math.max(v1, v2) + 1
end
local lines = vim.api.nvim_buf_get_lines(buf, stdin1 - 1, stdin2 - 1, true)
local file = vim.api.nvim_buf_get_name(buf)
---@param out vim.SystemCompleted
local on_exit = vim.schedule_wrap(function(out)
if out.code == 0 then
local fmt = assert(out.stdout, "No stdout")
local fmt_lines = opts.transform(fmt)
if opts.diff == "none" then
vim.api.nvim_buf_set_lines(buf, stdin1 - 1, stdin2 - 1, true, fmt_lines)
return
end
local lines_str = table.concat(lines, "\n") .. "\n"
local diff_opts = { result_type = "indices", algorithm = opts.diff_algorithm }
local diff = vim.text.diff(lines_str, fmt, diff_opts)
if not diff then
return
end
for i = #diff, 1, -1 do
local d = diff[i]
local a = { d[1], d[1] + d[2] }
local b = { d[3], d[3] + d[4] }
local a_buf = { a[1] + stdin1 - 1, a[2] + stdin1 - 1 }
local set_hunk = function()
local repl = b[1] == b[2] and {} or vim.list_slice(fmt_lines, b[1], b[2] - 1)
local offs = a[1] == a[2] and 0 or -1
vim.api.nvim_buf_set_lines(buf, a_buf[1] + offs, a_buf[2] + offs, false, repl)
end
if opts.diff == "any" then
set_hunk()
end
if opts.diff == "contain" then
if range1 <= a_buf[1] and range2 >= a_buf[2] then
set_hunk()
end
end
if opts.diff == "overlap" then
if range1 <= a_buf[2] and a_buf[1] <= range2 then
set_hunk()
end
end
end
else
vim.notify(string.format("-%s- %s", cmd[1], out.stderr), vim.log.levels.ERROR)
end
end)
local sysopts = { ---@type vim.SystemOpts
stdin = lines,
text = true,
cwd = vim.fs.dirname(file),
timeout = opts.timeout,
}
return vim.system(cmd, sysopts, on_exit)
end
local format = function(range)
range = range or {}
local formatconf = vim.g.formatconf or {}
local conf = formatconf[vim.bo.ft]
if not vim.is_callable(conf) then
return false
end
local line1 = range[1] or 1
local line2 = range[2] or vim.api.nvim_buf_line_count(0) + 1
local mode = vim.fn.mode()
if vim.tbl_isempty(range) and mode:match("[vV]") then
local v1 = vim.api.nvim_win_get_cursor(0)[1]
local v2 = vim.fn.getpos("v")[2]
line1 = math.min(v1, v2)
line2 = math.max(v1, v2) + 1
end
---@diagnostic disable-next-line: redundant-parameter
local fmt_opts = conf(line1, line2)
fmt_opts = vim.islist(fmt_opts) and fmt_opts or { fmt_opts }
for _, opts in ipairs(fmt_opts) do
opts = vim.tbl_extend("keep", opts, { range = { line1, line2 } })
format_buf(0, opts):wait()
end
return true
end
_G.Formatexpr = function(opts)
local line1, line2 = vim.v.lnum, vim.v.lnum + vim.v.count
if format({ line1, line2 }) then
else
return vim.lsp.formatexpr(opts)
end
end
vim.o.formatexpr = "v:lua.Formatexpr()"
-- stylua: ignore
vim.keymap.set("n", "gqag", function() format() end)
-- stylua: ignore
vim.keymap.set("n", "gqga", function() format() end)
-- -- Terminal
vim.api.nvim_create_autocmd("TermOpen", {
desc = "Set options for the terminal window",
group = vim.api.nvim_create_augroup("term_open", { clear = true }),
callback = function()
vim.wo.number = false
vim.wo.relativenumber = false
end,
})
vim.keymap.set("t", "<Esc><Esc>", "<C-\\><C-n>", { desc = "Exit terminal mode" })
vim.cmd.cnoreabbrev("lz", "Lazygit")
vim.cmd.cnoreabbrev("Lz", "Lazygit")
vim.api.nvim_create_user_command("Lazygit", function()
vim.cmd.tabnew()
vim.cmd.terminal("lazygit")
local win = vim.api.nvim_get_current_win()
vim.api.nvim_create_autocmd("WinClosed", {
pattern = tostring(win),
once = true,
callback = function(e)
vim.cmd.bwipeout({ args = { e.buf }, bang = true })
end,
})
pcall(vim.cmd.file, "term:lazygit")
vim.cmd.startinsert()
end, {})
vim.schedule(function()
_G.Terminal = {
store = {},
openinsert = true,
}
function Terminal.close(id, unload)
local term = Terminal.store[id]
if not term then
return nil
end
local count = nil
if vim.api.nvim_win_is_valid(term.win) then
local buf = vim.api.nvim_win_get_buf(term.win)
count = vim.b[buf].term_count
_G.Terminal.openinsert = vim.fn.mode() == "t"
vim.api.nvim_win_close(term.win, unload)
term.win = -1
end
if unload then
for _, buf in ipairs(term.buflist) do
vim.api.nvim_buf_delete(buf, { force = true })
end
Terminal.store[id] = nil
end
return count
end
function Terminal.open(id, count, win_config)
count = count or 1
win_config = win_config or {}
Terminal.store[id] = Terminal.store[id] or {
win = -1,
buflist = {},
}
local term = Terminal.store[id]
local mods = { mods = { split = "botright" } }
local new = function(buf, win_conf)
buf = buf or -1
win_conf = win_conf or {}
local is_buf = vim.api.nvim_buf_is_valid(buf)
if is_buf then
vim.cmd.split(mods)
else
vim.cmd.terminal(mods)
buf = vim.api.nvim_get_current_buf()
end
local win = vim.api.nvim_get_current_win()
term.win = win
vim.api.nvim_win_set_config(win, win_conf)
if is_buf then
vim.wo[win].winfixbuf = false
vim.api.nvim_win_set_buf(win, buf)
end
vim.wo[win].winfixbuf = true
term.buflist[count] = buf
vim.b[buf].term_count = count
if _G.Terminal.openinsert then
vim.api.nvim_win_call(term.win, vim.cmd.startinsert)
end
end
if vim.api.nvim_win_is_valid(term.win) then
local buf = term.buflist[count] or -1
if vim.api.nvim_buf_is_valid(buf) then
vim.api.nvim_win_set_config(0, win_config)
vim.wo[term.win].winfixbuf = false
vim.api.nvim_win_set_buf(term.win, buf)
vim.wo[term.win].winfixbuf = true
else
local win_state = vim.api.nvim_win_get_config(term.win)
vim.api.nvim_win_close(term.win, false)
new(nil, win_state)
end
else
local buf = term.buflist[count] or -1
new(buf, win_config)
end
return term.win
end
local last_count = 1 ---@type integer?
local win = -1
local win_config = { height = 15 }
local open_term = function(count)
win = Terminal.open("default", count, win_config)
vim.wo[win].winbar = "Terminal " .. count
end
vim.keymap.set({ "v", "n", "t" }, "<M-`>", function()
if vim.api.nvim_win_is_valid(win) then
win_config = vim.api.nvim_win_get_config(win)
if vim.v.count == 0 then
last_count = Terminal.close("default", false)
else
open_term(vim.v.count1)
end
else
open_term(vim.v.count == 0 and last_count or vim.v.count1)
end
end, { desc = "Terminal" })
end)
-- -- Marks
local mark_ns = vim.api.nvim_create_namespace("mark_virtual")
local marks_group = vim.api.nvim_create_augroup("mark_virtual", { clear = true })
vim.g.virt_marks = true
local get_marks = function(buf, filter)
buf = buf or 0
buf = buf == 0 and vim.api.nvim_get_current_buf() or buf
local file = vim.api.nvim_buf_get_name(buf)
filter = filter or function(m)
return m.mark:match("'%a")
end
-- stylua: ignore
local buffer_marks = vim.iter(vim.fn.getmarklist(buf))
:map(function(m) m.type = "buffer"; return m end)
:totable()
-- stylua: ignore
local global_marks = vim.iter(vim.fn.getmarklist())
:filter(function(m) return vim.fn.fnamemodify(m.file, ":p") == file end)
:map(function(m) m.type = "global"; return m end)
:totable()
return vim.iter({ buffer_marks, global_marks }):flatten(1):filter(filter):totable()
end
local clear_buf_marks = function(buf)
vim.api.nvim_buf_clear_namespace(buf, mark_ns, 0, -1)
end
local draw_buf_marks = function(buf)
clear_buf_marks(buf)
local buf_marks = get_marks(buf)
local lnum_marks = {}
for _, m in ipairs(buf_marks) do
local _, lnum = unpack(m.pos)
lnum = lnum - 1
lnum_marks[lnum] = lnum_marks[lnum] or {}
table.insert(lnum_marks[lnum], m)
end
local get_indent = function(lnum)
local line = table.remove(vim.api.nvim_buf_get_lines(buf, lnum, lnum + 1, false))
line = line or ""
return string.match(line, "^%s+") or ""
end
local line_count = vim.api.nvim_buf_line_count(buf)
for lnum, marks in pairs(lnum_marks) do
if lnum < line_count then
local indent = get_indent(lnum)
local virt_lines = {}
for _, m in ipairs(marks) do
table.insert(virt_lines, { { string.format("%s %s", indent, m.mark), "Comment" } })
end
vim.api.nvim_buf_set_extmark(buf, mark_ns, lnum, 0, {
virt_lines = virt_lines,
virt_lines_above = true,
strict = false,
})
end
end
return buf_marks
end
local apply_buf_marks = function(buf, enabled)
vim.g.virt_marks = true
if enabled ~= nil then
vim.b[buf].virt_marks = enabled
end
if vim.b[buf].virt_marks then
draw_buf_marks(buf)
else
clear_buf_marks(buf)
end
end
--
local toggle_marks = function()
local next_val = not vim.b.virt_marks
for _, buf in ipairs(vim.api.nvim_list_bufs()) do
apply_buf_marks(buf, next_val)
end
end
local toggle_buf_marks = function(buf)
buf = buf or 0
apply_buf_marks(buf, not vim.b[buf].virt_marks)
end
-- stylua: ignore start
vim.keymap.set("n", "<Leader>m", function() toggle_buf_marks() end, { desc = "Toggle buf marks" })
vim.keymap.set("n", "<Leader>M", function() toggle_marks() end, { desc = "Toggle marks" })
-- stylua: ignore end
vim.api.nvim_create_autocmd({ "BufEnter", "CursorHold" }, {
desc = "Show named vim marks as virtual lines",
group = marks_group,
callback = function(e)
if not vim.g.virt_marks then
return
end
if vim.b[e.buf].virt_marks == nil then
vim.b[e.buf].virt_marks = vim.g.virt_marks
end
apply_buf_marks(e.buf)
end,
})
-- -- Checkout (mini.git, mini.bracketed)
local conflict_ns = vim.api.nvim_create_namespace("git_conflict")
local conflict_au = vim.api.nvim_create_augroup("git_conflict", {})
-- get_buf_conflicts(buf) -> { { {1,5}, {3,5}, {5,7} }, ... }
-- ours base? theirs
-- 1: <<<<<<< HEAD
-- 2: local a = "main"
-- 3: ||||||| parent of xxxxxxx (xxx)
-- 4: local a = "base"
-- 5: =======
-- 6: local a = "feature"
-- 7: >>>>>>> xxxxxxx (xxx)
--
local function find_conflicts(buf)
buf = buf or 0
local lines = vim.api.nvim_buf_get_lines(buf, 0, -1, true)
local ours, base, theirs = {}, {}, {}
local conflicts = {}
local on_end_mark = function()
local full = function(val)
return val[1] and val[2]
end
if full(ours) and full(theirs) then
base = full(base) and base or nil
table.insert(conflicts, { ours, base, theirs })
ours, base, theirs = {}, {}, {}
end
end
-- stylua: ignore
for ln, line in ipairs(lines) do
if vim.startswith(line, "<<<<<<<") then ours[1] = ln end
if vim.startswith(line, "|||||||") then base[1] = ln end
if vim.startswith(line, "=======") then ours[2], base[2], theirs[1] = ln, ln, ln end
if vim.startswith(line, ">>>>>>>") then theirs[2] = ln; on_end_mark() end
end
return conflicts
end
local conflict_state = {}
local function toggle_conflicts(buf)
buf = buf or 0
if not vim.api.nvim_buf_is_valid(buf) then
vim.notify(string.format("Invalid buffer: %d", buf), vim.log.levels.ERROR)
return
end
conflict_state[buf] = not conflict_state[buf]
if not conflict_state[buf] then
vim.api.nvim_clear_autocmds({ group = conflict_au, buffer = buf })
vim.api.nvim_buf_clear_namespace(buf, conflict_ns, 0, -1)
vim.b[buf].minigit_conflicts = nil
else
local update = function() ---@diagnostic disable-line: redefined-local
local conflicts = find_conflicts(buf)
vim.b[buf].minigit_conflicts = conflicts
vim.api.nvim_buf_clear_namespace(buf, conflict_ns, 0, -1)
local hi = function(from, to, hl)
vim.api.nvim_buf_set_extmark(buf, conflict_ns, from - 1, 0, {
end_row = to,
hl_group = hl,
hl_eol = true,
})
end
for _, conflict in ipairs(conflicts) do
local ours, base, theirs = unpack(conflict)
hi(ours[1], ours[2] - 1, "DiffText")
hi(theirs[1] + 1, theirs[2], "DiffAdd")
if base then
hi(base[1], base[2] - 1, "DiffDelete")
end
end
end
update()
vim.api.nvim_clear_autocmds({ group = conflict_au, buffer = buf })
vim.api.nvim_create_autocmd("ModeChanged", { pattern = "i:*", group = conflict_au, callback = update })
vim.api.nvim_create_autocmd("TextChanged", { group = conflict_au, buffer = buf, callback = update })
end
end
local conflict_acts = {}
do
local get_conflict = function()
local lnum = vim.api.nvim_win_get_cursor(0)[1]
for _, conflict in ipairs(vim.b.minigit_conflicts or {}) do
local ours, _, theirs = unpack(conflict)
if lnum >= ours[1] and lnum <= theirs[2] then
return conflict
end
end
end
local replace_conflict = function(conflict, lines)
local ours, _, theirs = unpack(conflict)
vim.api.nvim_buf_set_lines(0, ours[1] - 1, theirs[2], true, lines)
vim.api.nvim_win_set_cursor(0, { ours[1], 0 })
end
local get_lines = function(from, to)
return vim.api.nvim_buf_get_lines(0, from - 1, to - 1, true)
end
local search = function(line, pattern, ...)
line = type(line) == "number" and line or vim.fn.line(line)
local saved_pos = vim.fn.getpos(".")
vim.fn.cursor(line, 0)
if vim.fn.search(pattern, ...) == 0 or vim.fn.line(".") == saved_pos[2] then
vim.fn.cursor(saved_pos[2], saved_pos[3])
end
end
--
conflict_acts.ours = function()
local conflict = get_conflict()
if conflict then
local ours, base, _ = unpack(conflict)
local repl = get_lines(ours[1] + 1, base[1] or ours[2])
replace_conflict(conflict, repl)
end
end
conflict_acts.theirs = function()
local conflict = get_conflict()
if conflict then
local _, _, theirs = unpack(conflict)
local repl = get_lines(theirs[1] + 1, theirs[2])
replace_conflict(conflict, repl)
end
end
conflict_acts.both = function()
local conflict = get_conflict()
if conflict then
local ours, base, theirs = unpack(conflict)
local repl = {}
vim.list_extend(repl, get_lines(ours[1] + 1, base[1] or ours[2]))
vim.list_extend(repl, get_lines(theirs[1] + 1, theirs[2]))
replace_conflict(conflict, repl)
end
end
conflict_acts.none = function()
local conflict = get_conflict()
if conflict then
replace_conflict(conflict, {})
end
end
conflict_acts.forward = function()
for _ = 1, vim.v.count1 do
search(".", "^<<<<<<< ")
end
end
conflict_acts.backward = function()
for _ = 1, vim.v.count1 do
search(".", "^<<<<<<< ", "b")
end
end
conflict_acts.last = function()
search("$", "^<<<<<<< ", "bW")
end
conflict_acts.first = function()
search(1, "^<<<<<<< ", "cW")
end
end
local function minigit_is_merge(buf)
buf = buf or 0
local git_summary = vim.b[buf].minigit_summary or {}
local in_progress = git_summary.in_progress
return in_progress and (in_progress:find("merge") or in_progress:find("rebase"))
end
vim.api.nvim_create_autocmd("User", {
pattern = "MiniGitUpdated",
group = conflict_au,
callback = function(e)
local buf = e.buf
if minigit_is_merge(buf) then
if not vim.b[buf].minigit_conflicts then
toggle_conflicts(buf)
vim.keymap.set("n", "co", conflict_acts.ours, { buffer = buf, desc = "Checkout ours" })
vim.keymap.set("n", "ct", conflict_acts.theirs, { buffer = buf, desc = "Checkout theirs" })
vim.keymap.set("n", "cb", conflict_acts.both, { buffer = buf, desc = "Checkout both" })
vim.keymap.set("n", "c0", conflict_acts.none, { buffer = buf, desc = "Checkout none" })
vim.keymap.set("n", "]x", conflict_acts.forward, { buffer = buf, desc = "Conflict forward" })
vim.keymap.set("n", "[x", conflict_acts.backward, { buffer = buf, desc = "Conflict backward" })
vim.keymap.set("n", "]X", conflict_acts.last, { buffer = buf, desc = "Conflict last" })
vim.keymap.set("n", "[X", conflict_acts.first, { buffer = buf, desc = "Conflict first" })
end
else
if vim.b[buf].minigit_conflicts then
toggle_conflicts(buf)
vim.keymap.del("n", "co", { buffer = buf })
vim.keymap.del("n", "ct", { buffer = buf })
vim.keymap.del("n", "cb", { buffer = buf })
vim.keymap.del("n", "c0", { buffer = buf })
vim.keymap.del("n", "]x", { buffer = buf })
vim.keymap.del("n", "[x", { buffer = buf })
vim.keymap.del("n", "]X", { buffer = buf })
vim.keymap.del("n", "[X", { buffer = buf })
end
end
end,
}) |
Beta Was this translation helpful? Give feedback.


















Uh oh!
There was an error while loading. Please reload this page.
-
Seeing how other people use
mini.nvimis a very helpful feedback for me. It helps me reason about which modules are used the most and whatconfigvalues are used. This might influence my future decisions in design and default values. And also might other people new ideas.Feel free to share a link to specific part of dotfiles (might be a good idea to pin to specific commit), code or screenshot (if too big, please hide under spoiler).
Thanks!
Beta Was this translation helpful? Give feedback.
All reactions