1

Refresh generated neovim config

This commit is contained in:
2024-08-15 13:01:03 +02:00
parent 64b51cf53a
commit f5af8e2b28
1836 changed files with 38979 additions and 31094 deletions

View File

@ -66,10 +66,6 @@ end
-- }}} -- }}}
vim.loader.enable() vim.loader.enable()
vim.cmd([[
]])
require("lazy").setup({ require("lazy").setup({
dev = { dev = {
path = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins", path = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins",
@ -648,6 +644,7 @@ require("lazy").setup({
{ ["name"] = "cmake" }, { ["name"] = "cmake" },
{ ["name"] = "lua_ls" }, { ["name"] = "lua_ls" },
{ ["name"] = "nil_ls" }, { ["name"] = "nil_ls" },
{ ["name"] = "ltex" },
{ {
["extraOptions"] = { ["extraOptions"] = {
["nixd"] = { ["nixd"] = {
@ -1397,17 +1394,23 @@ do
}, },
{ action = "<cmd>Navbuddy<cr>", key = "<leader>tn", mode = "n", options = { desc = "Toggle NavBuddy" } }, { action = "<cmd>Navbuddy<cr>", key = "<leader>tn", mode = "n", options = { desc = "Toggle NavBuddy" } },
{ {
action = "<cmd>TroubleToggle workspace_diagnostics focus=false<cr>", action = "<cmd>Trouble diagnostics toggle focus=false win.position=bottom<cr>",
key = "<leader>td", key = "<leader>td",
mode = "n", mode = "n",
options = { desc = "Toggle Trouble diagnostics" }, options = { desc = "Toggle Trouble diagnostics" },
}, },
{ {
action = "<cmd>TroubleToggle todo focus=false<cr>", action = "<cmd>Trouble todo toggle focus=false win.position=right<cr>",
key = "<leader>tT", key = "<leader>tT",
mode = "n", mode = "n",
options = { desc = "Toggle Trouble TODOs" }, options = { desc = "Toggle Trouble TODOs" },
}, },
{
action = "<cmd>Trouble symbols toggle focus=false win.position=right<cr>",
key = "<leader>ts",
mode = "n",
options = { desc = "Toggle Trouble symbols" },
},
{ {
action = "<cmd>ToggleAutoformat<cr>", action = "<cmd>ToggleAutoformat<cr>",
key = "<leader>tf", key = "<leader>tf",
@ -1427,6 +1430,12 @@ do
options = { desc = "Toggle inline diagnostics" }, options = { desc = "Toggle inline diagnostics" },
}, },
{ action = "<cmd>:set wrap!<cr>", key = "<leader>tw", mode = "n", options = { desc = "Toggle word-wrap" } }, { action = "<cmd>:set wrap!<cr>", key = "<leader>tw", mode = "n", options = { desc = "Toggle word-wrap" } },
{
action = "<cmd>VimtexTocToggle<cr>",
key = "<leader>tv",
mode = "n",
options = { desc = "Toggle Vimtex ToC" },
},
{ action = "+git", key = "<leader>g", mode = "n" }, { action = "+git", key = "<leader>g", mode = "n" },
{ action = "<cmd>LazyGit<cr>", key = "<leader>gg", mode = "n", options = { desc = "Show LazyGit" } }, { action = "<cmd>LazyGit<cr>", key = "<leader>gg", mode = "n", options = { desc = "Show LazyGit" } },
{ action = "<cmd>GitMessenger<cr>", key = "<leader>gm", mode = "n", options = { desc = "Show GitMessenger" } }, { action = "<cmd>GitMessenger<cr>", key = "<leader>gm", mode = "n", options = { desc = "Show GitMessenger" } },
@ -1541,8 +1550,6 @@ do
end end
-- }}} -- }}}
vim.filetype.add({ extension = { v = "vlang" } })
-- Make Lazy window border rounded -- Make Lazy window border rounded
require("lazy.core.config").options.ui.border = "rounded" require("lazy.core.config").options.ui.border = "rounded"

View File

@ -66,13 +66,9 @@ end
-- }}} -- }}}
vim.loader.enable() vim.loader.enable()
vim.cmd([[
]])
require("lazy").setup({ require("lazy").setup({
dev = { dev = {
path = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins", path = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins",
patterns = { "." }, patterns = { "." },
fallback = false, fallback = false,
}, },
@ -87,7 +83,7 @@ require("lazy").setup({
colorscheme catppuccin colorscheme catppuccin
]]) ]])
end, end,
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/catppuccin-nvim", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/catppuccin-nvim",
lazy = false, lazy = false,
name = "catppuccin", name = "catppuccin",
opts = { background = { dark = "mocha", light = "latte" }, flavour = "mocha" }, opts = { background = { dark = "mocha", light = "latte" }, flavour = "mocha" },
@ -98,7 +94,7 @@ require("lazy").setup({
config = function(_, opts) config = function(_, opts)
require("nvim-web-devicons").setup(opts) require("nvim-web-devicons").setup(opts)
end, end,
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/nvim-web-devicons", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/nvim-web-devicons",
lazy = true, lazy = true,
name = "nvim-web-devicons", name = "nvim-web-devicons",
}, },
@ -107,7 +103,7 @@ require("lazy").setup({
config = function(_, opts) config = function(_, opts)
require("nvim-autopairs").setup(opts) require("nvim-autopairs").setup(opts)
end, end,
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/nvim-autopairs", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/nvim-autopairs",
event = { "InsertEnter" }, event = { "InsertEnter" },
lazy = true, lazy = true,
name = "nvim-autopairs", name = "nvim-autopairs",
@ -116,7 +112,7 @@ require("lazy").setup({
{ {
"vim-bbye", "vim-bbye",
cmd = { "Bdelete", "Bwipeout" }, cmd = { "Bdelete", "Bwipeout" },
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/vim-bbye", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/vim-bbye",
lazy = true, lazy = true,
name = "vim-bbye", name = "vim-bbye",
}, },
@ -125,7 +121,7 @@ require("lazy").setup({
config = function(_, opts) config = function(_, opts)
require("better_escape").setup(opts) require("better_escape").setup(opts)
end, end,
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/better-escape.nvim", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/better-escape.nvim",
event = { "InsertEnter" }, event = { "InsertEnter" },
lazy = true, lazy = true,
name = "better_escape", name = "better_escape",
@ -136,7 +132,7 @@ require("lazy").setup({
config = function(_, opts) config = function(_, opts)
require("clangd_extensions").setup(opts) require("clangd_extensions").setup(opts)
end, end,
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/clangd_extensions.nvim", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/clangd_extensions.nvim",
lazy = true, lazy = true,
name = "clangd_extensions", name = "clangd_extensions",
opts = { inlay_hints = { inline = false } }, opts = { inlay_hints = { inline = false } },
@ -149,50 +145,50 @@ require("lazy").setup({
dependencies = { dependencies = {
{ {
"cmp-async-path", "cmp-async-path",
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/cmp-async-path", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/cmp-async-path",
lazy = true, lazy = true,
name = "cmp-async-path", name = "cmp-async-path",
}, },
{ {
"cmp-buffer", "cmp-buffer",
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/cmp-buffer", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/cmp-buffer",
enabled = false, enabled = false,
lazy = true, lazy = true,
name = "cmp-buffer", name = "cmp-buffer",
}, },
{ {
"cmp-cmdline", "cmp-cmdline",
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/cmp-cmdline", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/cmp-cmdline",
enabled = false, enabled = false,
lazy = true, lazy = true,
name = "cmp-cmdline", name = "cmp-cmdline",
}, },
{ {
"cmp-emoji", "cmp-emoji",
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/cmp-emoji", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/cmp-emoji",
lazy = true, lazy = true,
name = "cmp-emoji", name = "cmp-emoji",
}, },
{ {
"cmp-nvim-lsp", "cmp-nvim-lsp",
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/cmp-nvim-lsp", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/cmp-nvim-lsp",
lazy = true, lazy = true,
name = "cmp-nvim-lsp", name = "cmp-nvim-lsp",
}, },
{ {
"cmp-nvim-lsp-signature-help", "cmp-nvim-lsp-signature-help",
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/cmp-nvim-lsp-signature-help", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/cmp-nvim-lsp-signature-help",
lazy = true, lazy = true,
name = "cmp-nvim-lsp-signature-help", name = "cmp-nvim-lsp-signature-help",
}, },
{ {
"cmp_luasnip", "cmp_luasnip",
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/cmp_luasnip", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/cmp_luasnip",
lazy = true, lazy = true,
name = "cmp_luasnip", name = "cmp_luasnip",
}, },
}, },
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/nvim-cmp", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/nvim-cmp",
event = { "InsertEnter" }, event = { "InsertEnter" },
lazy = true, lazy = true,
name = "cmp", name = "cmp",
@ -273,7 +269,7 @@ require("lazy").setup({
config = function(_, opts) config = function(_, opts)
require("ts_context_commentstring").setup(opts) require("ts_context_commentstring").setup(opts)
end, end,
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/nvim-ts-context-commentstring", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/nvim-ts-context-commentstring",
init = function() init = function()
-- Skip compatibility checks -- Skip compatibility checks
vim.g.skip_ts_context_commentstring_module = true vim.g.skip_ts_context_commentstring_module = true
@ -282,7 +278,7 @@ require("lazy").setup({
name = "ts_context_commentstring", name = "ts_context_commentstring",
}, },
}, },
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/comment.nvim", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/comment.nvim",
lazy = false, lazy = false,
name = "Comment", name = "Comment",
opts = { opts = {
@ -299,7 +295,7 @@ require("lazy").setup({
config = function(_, opts) config = function(_, opts)
require("conform").setup(opts) require("conform").setup(opts)
end, end,
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/conform.nvim", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/conform.nvim",
event = { "BufReadPost", "BufNewFile" }, event = { "BufReadPost", "BufNewFile" },
lazy = true, lazy = true,
name = "conform", name = "conform",
@ -339,7 +335,7 @@ require("lazy").setup({
config = function(_, opts) config = function(_, opts)
require("nvim-web-devicons").setup(opts) require("nvim-web-devicons").setup(opts)
end, end,
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/nvim-web-devicons", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/nvim-web-devicons",
lazy = true, lazy = true,
name = "nvim-web-devicons", name = "nvim-web-devicons",
}, },
@ -366,30 +362,30 @@ require("lazy").setup({
dependencies = { dependencies = {
{ {
"plenary", "plenary",
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/plenary.nvim", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/plenary.nvim",
lazy = true, lazy = true,
name = "plenary", name = "plenary",
}, },
{ {
"telescope-fzf-native", "telescope-fzf-native",
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/telescope-fzf-native.nvim", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/telescope-fzf-native.nvim",
lazy = true, lazy = true,
name = "telescope-fzf-native", name = "telescope-fzf-native",
}, },
{ {
"telescope-undo", "telescope-undo",
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/telescope-undo.nvim", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/telescope-undo.nvim",
lazy = true, lazy = true,
name = "telescope-undo", name = "telescope-undo",
}, },
{ {
"telescope-ui-select", "telescope-ui-select",
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/telescope-ui-select.nvim", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/telescope-ui-select.nvim",
lazy = true, lazy = true,
name = "telescope-ui-select", name = "telescope-ui-select",
}, },
}, },
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/telescope.nvim", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/telescope.nvim",
lazy = true, lazy = true,
name = "telescope", name = "telescope",
opts = { opts = {
@ -405,7 +401,7 @@ require("lazy").setup({
}, },
}, },
}, },
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/persisted.nvim", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/persisted.nvim",
lazy = true, lazy = true,
name = "persisted", name = "persisted",
opts = { opts = {
@ -418,7 +414,7 @@ require("lazy").setup({
}, },
}, },
}, },
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/dashboard-nvim", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/dashboard-nvim",
lazy = false, lazy = false,
name = "dashboard", name = "dashboard",
opts = { opts = {
@ -448,13 +444,13 @@ require("lazy").setup({
{ {
"diffview", "diffview",
cmd = { "DiffviewOpen" }, cmd = { "DiffviewOpen" },
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/diffview.nvim", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/diffview.nvim",
lazy = true, lazy = true,
name = "diffview", name = "diffview",
}, },
{ {
"direnv", "direnv",
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/direnv.vim", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/direnv.vim",
lazy = false, lazy = false,
name = "direnv", name = "direnv",
}, },
@ -463,7 +459,7 @@ require("lazy").setup({
config = function(_, opts) config = function(_, opts)
require("flash").setup(opts) require("flash").setup(opts)
end, end,
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/flash.nvim", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/flash.nvim",
keys = { "s", "S", "f", "F", "t", "T" }, keys = { "s", "S", "f", "F", "t", "T" },
lazy = true, lazy = true,
name = "flash", name = "flash",
@ -471,7 +467,7 @@ require("lazy").setup({
{ {
"gitmessenger", "gitmessenger",
cmd = { "GitMessenger" }, cmd = { "GitMessenger" },
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/git-messenger.vim", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/git-messenger.vim",
init = function() init = function()
for k, v in pairs({ for k, v in pairs({
["git_messenger_floating_win_opts"] = { ["border"] = "rounded" }, ["git_messenger_floating_win_opts"] = { ["border"] = "rounded" },
@ -488,7 +484,7 @@ require("lazy").setup({
config = function(_, opts) config = function(_, opts)
require("gitsigns").setup(opts) require("gitsigns").setup(opts)
end, end,
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/gitsigns.nvim", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/gitsigns.nvim",
event = { "BufReadPost", "BufNewFile" }, event = { "BufReadPost", "BufNewFile" },
lazy = true, lazy = true,
name = "gitsigns", name = "gitsigns",
@ -496,7 +492,7 @@ require("lazy").setup({
}, },
{ {
"haskell-tools", "haskell-tools",
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/haskell-tools.nvim", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/haskell-tools.nvim",
lazy = false, lazy = false,
name = "haskell-tools", name = "haskell-tools",
}, },
@ -505,7 +501,7 @@ require("lazy").setup({
config = function(_, opts) config = function(_, opts)
require("illuminate").configure(opts) require("illuminate").configure(opts)
end, end,
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/vim-illuminate", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/vim-illuminate",
event = { "BufreadPost", "BufNewFile" }, event = { "BufreadPost", "BufNewFile" },
lazy = true, lazy = true,
name = "illuminate", name = "illuminate",
@ -525,14 +521,14 @@ require("lazy").setup({
}, },
{ {
"intellitab", "intellitab",
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/intellitab.nvim", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/intellitab.nvim",
event = { "InsertEnter" }, event = { "InsertEnter" },
lazy = true, lazy = true,
name = "intellitab", name = "intellitab",
}, },
{ {
"jdtls", "jdtls",
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/nvim-jdtls", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/nvim-jdtls",
lazy = false, lazy = false,
name = "jdtls", name = "jdtls",
}, },
@ -541,7 +537,7 @@ require("lazy").setup({
config = function(_, opts) config = function(_, opts)
require("nvim-lastplace").setup(opts) require("nvim-lastplace").setup(opts)
end, end,
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/nvim-lastplace", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/nvim-lastplace",
lazy = false, lazy = false,
name = "nvim-lastplace", name = "nvim-lastplace",
}, },
@ -551,12 +547,12 @@ require("lazy").setup({
dependencies = { dependencies = {
{ {
"plenary", "plenary",
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/plenary.nvim", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/plenary.nvim",
lazy = true, lazy = true,
name = "plenary", name = "plenary",
}, },
}, },
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/lazygit.nvim", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/lazygit.nvim",
lazy = true, lazy = true,
name = "lazygit", name = "lazygit",
}, },
@ -569,7 +565,7 @@ require("lazy").setup({
lint[k] = v lint[k] = v
end end
end, end,
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/nvim-lint", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/nvim-lint",
event = { "BufReadPost", "BufNewFile" }, event = { "BufReadPost", "BufNewFile" },
lazy = true, lazy = true,
name = "lint", name = "lint",
@ -648,6 +644,7 @@ require("lazy").setup({
{ ["name"] = "cmake" }, { ["name"] = "cmake" },
{ ["name"] = "lua_ls" }, { ["name"] = "lua_ls" },
{ ["name"] = "nil_ls" }, { ["name"] = "nil_ls" },
{ ["name"] = "ltex" },
{ {
["extraOptions"] = { ["extraOptions"] = {
["nixd"] = { ["nixd"] = {
@ -682,12 +679,12 @@ require("lazy").setup({
config = function(_, opts) config = function(_, opts)
require("lazydev").setup(opts) require("lazydev").setup(opts)
end, end,
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/vimplugin-nvim-lazydev", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/vimplugin-nvim-lazydev",
ft = { "lua" }, ft = { "lua" },
name = "lazydev", name = "lazydev",
}, },
}, },
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/nvim-lspconfig", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/nvim-lspconfig",
event = { "BufReadPost", "BufNewFile" }, event = { "BufReadPost", "BufNewFile" },
lazy = true, lazy = true,
name = "lspconfig", name = "lspconfig",
@ -705,7 +702,7 @@ require("lazy").setup({
unhide = false, unhide = false,
}) })
end, end,
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/lualine.nvim", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/lualine.nvim",
event = { "BufReadPost", "BufNewFile" }, event = { "BufReadPost", "BufNewFile" },
lazy = true, lazy = true,
name = "lualine", name = "lualine",
@ -733,7 +730,7 @@ require("lazy").setup({
config = function(_, opts) config = function(_, opts)
require("luasnip").config.set_config(opts) require("luasnip").config.set_config(opts)
end, end,
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/luasnip", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/luasnip",
lazy = false, lazy = false,
name = "luasnip", name = "luasnip",
}, },
@ -745,7 +742,7 @@ require("lazy").setup({
vim.keymap.del("x", "<space>nr") vim.keymap.del("x", "<space>nr")
vim.keymap.del("n", "<space>nr") vim.keymap.del("n", "<space>nr")
end, end,
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/NrrwRgn", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/NrrwRgn",
lazy = true, lazy = true,
name = "narrow-region", name = "narrow-region",
}, },
@ -782,13 +779,13 @@ require("lazy").setup({
-- } -- }
-- }) -- })
end, end,
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/nvim-navic", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/nvim-navic",
lazy = true, lazy = true,
name = "navic", name = "navic",
opts = { click = true, depth_limit = 5, highlight = true, lsp = { auto_attach = true } }, opts = { click = true, depth_limit = 5, highlight = true, lsp = { auto_attach = true } },
}, },
}, },
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/nvim-navbuddy", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/nvim-navbuddy",
lazy = true, lazy = true,
name = "navbuddy", name = "navbuddy",
opts = { lsp = { auto_attach = true }, window = { border = "rounded" } }, opts = { lsp = { auto_attach = true }, window = { border = "rounded" } },
@ -802,7 +799,7 @@ require("lazy").setup({
dependencies = { dependencies = {
{ {
"plenary", "plenary",
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/plenary.nvim", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/plenary.nvim",
lazy = true, lazy = true,
name = "plenary", name = "plenary",
}, },
@ -811,18 +808,18 @@ require("lazy").setup({
config = function(_, opts) config = function(_, opts)
require("nvim-web-devicons").setup(opts) require("nvim-web-devicons").setup(opts)
end, end,
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/nvim-web-devicons", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/nvim-web-devicons",
lazy = true, lazy = true,
name = "nvim-web-devicons", name = "nvim-web-devicons",
}, },
{ {
"nui", "nui",
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/nui.nvim", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/nui.nvim",
lazy = true, lazy = true,
name = "nui", name = "nui",
}, },
}, },
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/neo-tree.nvim", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/neo-tree.nvim",
lazy = true, lazy = true,
name = "neo-tree", name = "neo-tree",
opts = { opts = {
@ -877,18 +874,18 @@ require("lazy").setup({
notify.setup(opts) notify.setup(opts)
vim.notify = notify -- Vim uses notify by default vim.notify = notify -- Vim uses notify by default
end, end,
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/nvim-notify", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/nvim-notify",
lazy = true, lazy = true,
name = "notify", name = "notify",
}, },
{ {
"nui", "nui",
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/nui.nvim", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/nui.nvim",
lazy = true, lazy = true,
name = "nui", name = "nui",
}, },
}, },
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/noice.nvim", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/noice.nvim",
lazy = false, lazy = false,
name = "noice", name = "noice",
opts = { opts = {
@ -924,13 +921,13 @@ require("lazy").setup({
}, },
{ {
"rainbow-delimiters", "rainbow-delimiters",
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/rainbow-delimiters.nvim", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/rainbow-delimiters.nvim",
lazy = false, lazy = false,
name = "rainbow-delimiters", name = "rainbow-delimiters",
}, },
{ {
"rustaceanvim", "rustaceanvim",
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/rustaceanvim", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/rustaceanvim",
init = function() init = function()
vim.g.rustaceanvim = { vim.g.rustaceanvim = {
tools = { tools = {
@ -976,7 +973,7 @@ require("lazy").setup({
}, },
{ {
"sandwich", "sandwich",
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/vim-sandwich", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/vim-sandwich",
init = function() init = function()
-- Disable default keymaps -- Disable default keymaps
vim.g.sandwich_no_default_key_mappings = 1 vim.g.sandwich_no_default_key_mappings = 1
@ -988,7 +985,7 @@ require("lazy").setup({
}, },
{ {
"sleuth", "sleuth",
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/vim-sleuth", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/vim-sleuth",
lazy = false, lazy = false,
name = "sleuth", name = "sleuth",
}, },
@ -1006,30 +1003,30 @@ require("lazy").setup({
dependencies = { dependencies = {
{ {
"plenary", "plenary",
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/plenary.nvim", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/plenary.nvim",
lazy = true, lazy = true,
name = "plenary", name = "plenary",
}, },
{ {
"telescope-fzf-native", "telescope-fzf-native",
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/telescope-fzf-native.nvim", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/telescope-fzf-native.nvim",
lazy = true, lazy = true,
name = "telescope-fzf-native", name = "telescope-fzf-native",
}, },
{ {
"telescope-undo", "telescope-undo",
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/telescope-undo.nvim", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/telescope-undo.nvim",
lazy = true, lazy = true,
name = "telescope-undo", name = "telescope-undo",
}, },
{ {
"telescope-ui-select", "telescope-ui-select",
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/telescope-ui-select.nvim", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/telescope-ui-select.nvim",
lazy = true, lazy = true,
name = "telescope-ui-select", name = "telescope-ui-select",
}, },
}, },
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/telescope.nvim", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/telescope.nvim",
lazy = true, lazy = true,
name = "telescope", name = "telescope",
opts = { opts = {
@ -1050,12 +1047,12 @@ require("lazy").setup({
dependencies = { dependencies = {
{ {
"plenary", "plenary",
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/plenary.nvim", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/plenary.nvim",
lazy = true, lazy = true,
name = "plenary", name = "plenary",
}, },
}, },
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/todo-comments.nvim", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/todo-comments.nvim",
event = { "BufReadPost", "BufNewFile" }, event = { "BufReadPost", "BufNewFile" },
lazy = true, lazy = true,
name = "todo-comments", name = "todo-comments",
@ -1078,7 +1075,7 @@ require("lazy").setup({
config = function(_, opts) config = function(_, opts)
require("toggleterm").setup(opts) require("toggleterm").setup(opts)
end, end,
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/toggleterm.nvim", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/toggleterm.nvim",
keys = { "<C-/>" }, keys = { "<C-/>" },
lazy = true, lazy = true,
name = "toggleterm", name = "toggleterm",
@ -1105,14 +1102,14 @@ require("lazy").setup({
config = function(_, opts) config = function(_, opts)
require("nvim-treesitter.configs").setup(opts) require("nvim-treesitter.configs").setup(opts)
end, end,
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/nvim-treesitter", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/nvim-treesitter",
event = { "BufReadPost", "BufNewFile" }, event = { "BufReadPost", "BufNewFile" },
init = function() init = function()
-- Fix treesitter grammars/parsers on nix -- Fix treesitter grammars/parsers on nix
vim.opt.runtimepath:append( vim.opt.runtimepath:append(
"/nix/store/mijdgvgykavkdkyfvhcrd5vh808ijmk0-vimplugin-nvim-treesitter-2024-06-19" "/nix/store/0a8da834qdlvvfrah5i2a2rz2mnqc1d2-vimplugin-nvim-treesitter-2024-08-04"
) )
vim.opt.runtimepath:append("/nix/store/0h2cb1dzf10jm1m643k43xkk6lpl4vk6-treesitter-parsers") vim.opt.runtimepath:append("/nix/store/z5838nllsi3a8z9z73wgv9g0ikx91nlq-treesitter-parsers")
end, end,
lazy = true, lazy = true,
name = "treesitter", name = "treesitter",
@ -1129,7 +1126,7 @@ require("lazy").setup({
}, },
}, },
indent = { enable = true }, indent = { enable = true },
parser_install_dir = "/nix/store/0h2cb1dzf10jm1m643k43xkk6lpl4vk6-treesitter-parsers", parser_install_dir = "/nix/store/z5838nllsi3a8z9z73wgv9g0ikx91nlq-treesitter-parsers",
}, },
}, },
{ {
@ -1137,7 +1134,7 @@ require("lazy").setup({
config = function(_, opts) config = function(_, opts)
require("trim").setup(opts) require("trim").setup(opts)
end, end,
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/trim.nvim", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/trim.nvim",
lazy = false, lazy = false,
name = "trim", name = "trim",
}, },
@ -1147,7 +1144,7 @@ require("lazy").setup({
config = function(_, opts) config = function(_, opts)
require("trouble").setup(opts) require("trouble").setup(opts)
end, end,
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/trouble.nvim", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/trouble.nvim",
lazy = true, lazy = true,
name = "trouble", name = "trouble",
}, },
@ -1159,18 +1156,18 @@ require("lazy").setup({
dependencies = { dependencies = {
{ {
"promise", "promise",
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/promise-async", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/promise-async",
lazy = true, lazy = true,
name = "promise", name = "promise",
}, },
}, },
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/nvim-ufo", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/nvim-ufo",
lazy = false, lazy = false,
name = "ufo", name = "ufo",
}, },
{ {
"vimtex", "vimtex",
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/vimtex", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/vimtex",
init = function() init = function()
vim.g.vimtex_view_method = "zathura" vim.g.vimtex_view_method = "zathura"
end, end,
@ -1181,7 +1178,7 @@ require("lazy").setup({
config = function(_, opts) config = function(_, opts)
require("which-key").setup(opts) require("which-key").setup(opts)
end, end,
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/which-key.nvim", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/which-key.nvim",
lazy = false, lazy = false,
name = "which-key", name = "which-key",
priority = 500, priority = 500,
@ -1192,7 +1189,7 @@ require("lazy").setup({
config = function(_, opts) config = function(_, opts)
require("winshift").setup(opts) require("winshift").setup(opts)
end, end,
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/winshift.nvim", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/winshift.nvim",
lazy = true, lazy = true,
name = "winshift", name = "winshift",
opts = { opts = {
@ -1206,7 +1203,7 @@ require("lazy").setup({
config = function(_, opts) config = function(_, opts)
require("yanky").setup(opts) require("yanky").setup(opts)
end, end,
dir = "/nix/store/qxjygssw1r6xbpsrk1fyk9f0qfp5nnsh-lazy-plugins/yanky.nvim", dir = "/nix/store/p9vf3cclb3px64da4qsk7lfs3140sjbp-lazy-plugins/yanky.nvim",
lazy = true, lazy = true,
name = "yanky", name = "yanky",
}, },
@ -1397,17 +1394,23 @@ do
}, },
{ action = "<cmd>Navbuddy<cr>", key = "<leader>tn", mode = "n", options = { desc = "Toggle NavBuddy" } }, { action = "<cmd>Navbuddy<cr>", key = "<leader>tn", mode = "n", options = { desc = "Toggle NavBuddy" } },
{ {
action = "<cmd>TroubleToggle workspace_diagnostics focus=false<cr>", action = "<cmd>Trouble diagnostics toggle focus=false win.position=bottom<cr>",
key = "<leader>td", key = "<leader>td",
mode = "n", mode = "n",
options = { desc = "Toggle Trouble diagnostics" }, options = { desc = "Toggle Trouble diagnostics" },
}, },
{ {
action = "<cmd>TroubleToggle todo focus=false<cr>", action = "<cmd>Trouble todo toggle focus=false win.position=right<cr>",
key = "<leader>tT", key = "<leader>tT",
mode = "n", mode = "n",
options = { desc = "Toggle Trouble TODOs" }, options = { desc = "Toggle Trouble TODOs" },
}, },
{
action = "<cmd>Trouble symbols toggle focus=false win.position=right<cr>",
key = "<leader>ts",
mode = "n",
options = { desc = "Toggle Trouble symbols" },
},
{ {
action = "<cmd>ToggleAutoformat<cr>", action = "<cmd>ToggleAutoformat<cr>",
key = "<leader>tf", key = "<leader>tf",
@ -1427,6 +1430,12 @@ do
options = { desc = "Toggle inline diagnostics" }, options = { desc = "Toggle inline diagnostics" },
}, },
{ action = "<cmd>:set wrap!<cr>", key = "<leader>tw", mode = "n", options = { desc = "Toggle word-wrap" } }, { action = "<cmd>:set wrap!<cr>", key = "<leader>tw", mode = "n", options = { desc = "Toggle word-wrap" } },
{
action = "<cmd>VimtexTocToggle<cr>",
key = "<leader>tv",
mode = "n",
options = { desc = "Toggle Vimtex ToC" },
},
{ action = "+git", key = "<leader>g", mode = "n" }, { action = "+git", key = "<leader>g", mode = "n" },
{ action = "<cmd>LazyGit<cr>", key = "<leader>gg", mode = "n", options = { desc = "Show LazyGit" } }, { action = "<cmd>LazyGit<cr>", key = "<leader>gg", mode = "n", options = { desc = "Show LazyGit" } },
{ action = "<cmd>GitMessenger<cr>", key = "<leader>gm", mode = "n", options = { desc = "Show GitMessenger" } }, { action = "<cmd>GitMessenger<cr>", key = "<leader>gm", mode = "n", options = { desc = "Show GitMessenger" } },
@ -1541,8 +1550,6 @@ do
end end
-- }}} -- }}}
vim.filetype.add({ extension = { v = "vlang" } })
-- Make Lazy window border rounded -- Make Lazy window border rounded
require("lazy.core.config").options.ui.border = "rounded" require("lazy.core.config").options.ui.border = "rounded"

View File

@ -1,4 +1,4 @@
#!/nix/store/agkxax48k35wdmkhmmija2i2sxg8i7ny-bash-5.2p26/bin/sh #!/nix/store/4bj2kxdm1462fzcc2i2s4dn33g2angcc-bash-5.2p32/bin/sh
for i in */; do for i in */; do
cd "$i" cd "$i"

View File

@ -1,4 +1,4 @@
#!/nix/store/agkxax48k35wdmkhmmija2i2sxg8i7ny-bash-5.2p26/bin/bash #!/nix/store/4bj2kxdm1462fzcc2i2s4dn33g2angcc-bash-5.2p32/bin/bash
#set -x #set -x
dir="$(realpath ../..)" dir="$(realpath ../..)"

View File

@ -1,4 +1,4 @@
#!/nix/store/agkxax48k35wdmkhmmija2i2sxg8i7ny-bash-5.2p26/bin/bash #!/nix/store/4bj2kxdm1462fzcc2i2s4dn33g2angcc-bash-5.2p32/bin/bash
#set -x #set -x
Test="Test2" Test="Test2"

View File

@ -1,4 +1,4 @@
#!/nix/store/agkxax48k35wdmkhmmija2i2sxg8i7ny-bash-5.2p26/bin/bash #!/nix/store/4bj2kxdm1462fzcc2i2s4dn33g2angcc-bash-5.2p32/bin/bash
#set -x #set -x
Test="Test3" Test="Test3"

View File

@ -1,4 +1,4 @@
#!/nix/store/agkxax48k35wdmkhmmija2i2sxg8i7ny-bash-5.2p26/bin/bash #!/nix/store/4bj2kxdm1462fzcc2i2s4dn33g2angcc-bash-5.2p32/bin/bash
#set -x #set -x
Test="Test4" Test="Test4"

View File

@ -1,4 +1,4 @@
#!/nix/store/agkxax48k35wdmkhmmija2i2sxg8i7ny-bash-5.2p26/bin/bash #!/nix/store/4bj2kxdm1462fzcc2i2s4dn33g2angcc-bash-5.2p32/bin/bash
#set -x #set -x
Test=`basename $PWD` Test=`basename $PWD`

View File

@ -1,4 +1,4 @@
#!/nix/store/agkxax48k35wdmkhmmija2i2sxg8i7ny-bash-5.2p26/bin/bash #!/nix/store/4bj2kxdm1462fzcc2i2s4dn33g2angcc-bash-5.2p32/bin/bash
#set -x #set -x
Test=`basename $PWD` Test=`basename $PWD`

View File

@ -1,4 +1,4 @@
#!/nix/store/agkxax48k35wdmkhmmija2i2sxg8i7ny-bash-5.2p26/bin/bash #!/nix/store/4bj2kxdm1462fzcc2i2s4dn33g2angcc-bash-5.2p32/bin/bash
#set -x #set -x
Test=`basename $PWD` Test=`basename $PWD`

View File

@ -1,175 +1,182 @@
local M = {} local M = {}
local uv = vim.uv or vim.loop
local t = function(str)
return vim.api.nvim_replace_termcodes(str, true, true, true)
end
local api = vim.api M.waiting = false
local settings = { local settings = {
timeout = vim.o.timeoutlen, timeout = vim.o.timeoutlen,
mapping = { "jk", "jj" }, default_mappings = true,
clear_empty_lines = false, mappings = {
---@type string|function i = {
keys = "<Esc>", -- first_key[s]
j = {
-- second_key[s]
k = "<Esc>",
j = "<Esc>",
},
},
c = {
j = {
k = "<Esc>",
j = "<Esc>",
},
},
t = {
j = {
k = "<C-\\><C-n>",
},
},
v = {
j = {
k = "<Esc>",
},
},
s = {
j = {
k = "<Esc>",
},
},
},
} }
local first_chars = {} local function unmap_keys()
local second_chars = {} for mode, keys in pairs(settings.mappings) do
for key, subkeys in pairs(keys) do
---@class State pcall(vim.keymap.del, mode, key)
---@field char string for subkey, _ in pairs(subkeys) do
---@field modified boolean pcall(vim.keymap.del, mode, subkey)
local timer
local waiting = false
---@type State[]
local input_states = {}
---@param tbl table table to search through
---@param element any element to search in tbl
---@return table indices
--- Search for indices in tbl where element occurs
local function get_indices(tbl, element)
local indices = {}
for idx, value in ipairs(tbl) do
if element == value then
table.insert(indices, idx)
end
end
return indices
end
---@param keys string keys to feed
--- Replace keys with termcodes and feed them
local function feed(keys, mode)
api.nvim_feedkeys(
api.nvim_replace_termcodes(keys, true, true, true),
mode or "n",
false
)
end
local function start_timer()
waiting = true
if timer then
timer:stop()
end
timer = vim.defer_fn(function()
waiting = false
end, settings.timeout)
end
local function get_keys()
-- if keys is string use it, else use it as a function
return type(settings.keys) == "string" and settings.keys or settings.keys()
end
local function check_timeout()
if waiting then
local current_line = api.nvim_get_current_line()
if settings.clear_empty_lines and current_line:match("^%s+j$") then
vim.schedule(function()
api.nvim_set_current_line("")
feed(get_keys(), "in")
end)
else
feed("<BS><BS>" .. get_keys(), "in") -- delete the characters from the mapping
end
waiting = false -- more timely
return true
end
return false
end
function M.check_charaters()
local char = vim.v.char
table.insert(input_states, { char = char, modified = vim.bo.modified })
local matched = false
if #input_states >= 2 then
---@type State
local prev_state = input_states[#input_states - 1]
local indices = get_indices(second_chars, char)
-- if char == second_chars[idx] and prev_char == first_chars[idx] as well
-- then matched = true
for _, idx in ipairs(indices) do
if first_chars[idx] == prev_state.char then
matched = check_timeout()
break
end end
end end
end
end
if matched then -- WIP: move this into recorder.lua ?
input_states = {} -- When a first_key is pressed, `recorded_key` is set to it
vim.schedule(function() -- (e.g. if jk is a mapping, when 'j' is pressed, `recorded_key` is set to 'j')
vim.bo.modified = prev_state.modified local recorded_key = nil
end) local bufmodified = nil
local timeout_timer = uv.new_timer()
local has_recorded = false -- See `vim.on_key` below
local function record_key(key)
if timeout_timer:is_active() then
timeout_timer:stop()
end
bufmodified = vim.bo.modified
recorded_key = key
has_recorded = true
M.waiting = true
timeout_timer:start(settings.timeout, 0, function()
M.waiting = false
recorded_key = nil
end)
end
vim.on_key(function(_, typed)
if typed == "" then
return
end
if has_recorded == false then
-- If the user presses a key that doesn't get recorded, remove the previously recorded key.
recorded_key = nil
return
end
has_recorded = false
end)
-- List of keys that undo the effect of pressing first_key
local undo_key = {
i = "<bs>",
c = "<bs>",
t = "<bs>",
}
local function map_keys()
for mode, first_keys in pairs(settings.mappings) do
local map_opts = { expr = true }
for first_key, _ in pairs(first_keys) do
vim.keymap.set(mode, first_key, function()
record_key(first_key)
return first_key
end, map_opts)
end
for _, second_keys in pairs(first_keys) do
for second_key, mapping in pairs(second_keys) do
if not mapping then
goto continue
end
vim.keymap.set(mode, second_key, function()
-- If a first_key wasn't recorded, record second_key because it might be a first_key for another sequence.
-- TODO: Explicitly, check if it's a starting key. I don't think that's necessary right now.
if recorded_key == nil then
record_key(second_key)
return second_key
end
-- If a key was recorded, but it isn't the first_key for second_key, record second_key(second_key might be a first_key for another sequence)
-- Or if the recorded_key was just a second_key
if
not (
first_keys[recorded_key]
and first_keys[recorded_key][second_key]
)
then
record_key(second_key)
return second_key
end
local keys = ""
keys = keys
.. t(
(undo_key[mode] or "")
.. (
("<cmd>setlocal %smodified<cr>"):format(
bufmodified and "" or "no"
)
)
)
if type(mapping) == "string" then
keys = keys .. t(mapping)
elseif type(mapping) == "function" then
keys = keys .. t(mapping() or "")
end
vim.api.nvim_feedkeys(keys, "in", false)
end, map_opts)
::continue::
end
end end
end end
-- if can't find a match, and the typed char is first in a mapping, start the timeout
if not matched and vim.tbl_contains(first_chars, char) then
start_timer()
end
end
local function char_at(str, pos)
return vim.fn.nr2char(vim.fn.strgetchar(str, pos))
end
local function validate_settings()
assert(type(settings.mapping) == "table", "Mapping must be a table.")
for _, mapping in ipairs(settings.mapping) do
-- replace all multibyte chars to `A` char
local length = #vim.fn.substitute(mapping, ".", "A", "g")
assert(length == 2, "Mapping must be 2 keys.")
end
if settings.timeout then
assert(type(settings.timeout) == "number", "Timeout must be a number.")
assert(
settings.timeout >= 100,
"Timeout must be greater than or equal to 100."
)
end
assert(
vim.tbl_contains({ "string", "function" }, type(settings.keys)),
"Keys must be a function or string."
)
end end
function M.setup(update) function M.setup(update)
if update and update.default_mappings == false then
settings.mappings = {}
end
settings = vim.tbl_deep_extend("force", settings, update or {}) settings = vim.tbl_deep_extend("force", settings, update or {})
-- if mapping is a string (single mapping) make it a table if settings.keys or settings.clear_empty_lines then
if type(settings.mapping) == "string" then vim.notify(
settings.mapping = { settings.mapping } "[better-escape.nvim]: Rewrite! Check: https://github.com/max397574/better-escape.nvim",
vim.log.levels.WARN,
{}
)
end end
local ok, msg = pcall(validate_settings) if settings.mapping then
if ok then vim.notify(
-- create tables with the first and seconds chars of the mappings "[better-escape.nvim]: Rewrite! Check: https://github.com/max397574/better-escape.nvim",
for _, shortcut in ipairs(settings.mapping) do vim.log.levels.WARN,
vim.cmd("silent! iunmap " .. shortcut) {}
table.insert(first_chars, char_at(shortcut, 0)) )
table.insert(second_chars, char_at(shortcut, 1)) if type(settings.mapping) == "string" then
settings.mapping = { settings.mapping }
end
for _, mapping in ipairs(settings.mappings) do
settings.mappings.i[mapping:sub(1, 2)] = {}
settings.mappings.i[mapping:sub(1, 1)][mapping:sub(2, 2)] =
settings.keys
end end
vim.cmd([[
augroup better_escape
autocmd!
autocmd InsertCharPre * lua require"better_escape".check_charaters()
augroup END
]])
else
vim.notify("Error(better-escape.nvim): " .. msg, vim.log.levels.ERROR)
end end
unmap_keys()
map_keys()
end end
return setmetatable(M, { return M
__index = function(_, k)
if k == "waiting" then
return waiting
end
end,
})

View File

@ -1,21 +1,24 @@
# 🚪better-escape.nvim # better-escape.nvim
This plugin is the lua version of [better_escape.vim](https://github.com/jdhao/better-escape.vim), ![better-escape](https://github.com/max397574/better-escape.nvim/assets/81827001/8863a620-b075-4417-92d0-7eb2d2646186)
with some additional features and optimizations
A lot of people have mappings like `jk` or `jj` to escape insert mode. A lot of people have mappings like `jk` or `jj` to escape insert mode. The
The problem with this mappings is that whenever you type a `j`, neovim wait about 100-500ms (depending on your timeoutlen) to see, if you type a `j` or a `k` because these are mapped. problem with this mappings is that whenever you type a `j`, neovim wait about
Only after that time the `j` will be inserted. 100-500ms (depending on your timeoutlen) to see, if you type a `j` or a `k`
Then you always get a delay when typing a `j`. because these are mapped. Only after that time the `j` will be inserted. Then
you always get a delay when typing a `j`.
This looks like this (see below for a gif): An example where this has a big impact is e.g. telescope. Because the characters
which are mapped aren't really inserted at first the whole filtering isn't
instant.
![Screen Shot 2021-10-08 at 16 21 23](https://user-images.githubusercontent.com/81827001/136576543-c8b4e802-84a8-4087-a7a4-f7d069931885.png) ![better-escape-tele](https://github.com/max397574/better-escape.nvim/assets/81827001/390f115d-87cd-43d8-aadf-fffb12bd84c9)
## ✨Features ## ✨Features
- Escape without getting delay when typing in insert mode - Write mappings in many modes without having a delay when typing
- Customizable mapping and timeout - Customizable timeout
- Map key sequences and lua functions
- Use multiple mappings - Use multiple mappings
- Really small and fast - Really small and fast
@ -24,8 +27,8 @@ This looks like this (see below for a gif):
Use your favourite package manager and call the setup function. Use your favourite package manager and call the setup function.
```lua ```lua
-- lua with packer.nvim -- lua with lazy.nvim
use { {
"max397574/better-escape.nvim", "max397574/better-escape.nvim",
config = function() config = function()
require("better_escape").setup() require("better_escape").setup()
@ -33,31 +36,107 @@ use {
} }
``` ```
## ❗Rewrite
There was a big rewrite which allows much more flexibility now. You can now
define mappings in most modes and also use functions.
The biggest change was that the `mapping` config option was removed. Check the
default configuration below to see the new structure.
This also deprecated the `clear_empty_lines` setting. You can replicate this
behavior by setting a mapping to a function like this:
```lua
-- `k` would be the second key of a mapping
k = function()
vim.api.nvim_input("<esc>")
local current_line = vim.api.nvim_get_current_line()
if current_line:match("^%s+j$") then
vim.schedule(function()
vim.api.nvim_set_current_line("")
end)
end
end
```
## ⚙Customization ## ⚙Customization
Call the setup function with your options as arguments. Call the setup function with your options as arguments.
After the rewrite you can also use any function. So you could for example map
`<space><tab>` to jump with luasnip like this:
```lua
i = {
[" "] = {
["<tab>"] = function()
-- Defer execution to avoid side-effects
vim.defer_fn(function()
-- set undo point
vim.o.ul = vim.o.ul
require("luasnip").expand_or_jump()
end, 1)
end
}
}
```
### Disable mappings
To disable keys set them to `false` in the configuration.
You can also disable all default mappings by setting the `default_mappings` option to false.
<details>
<summary>Default Config</summary>
```lua ```lua
-- lua, default settings -- lua, default settings
require("better_escape").setup { require("better_escape").setup {
mapping = {"jk", "jj"}, -- a table with mappings to use timeout = vim.o.timeoutlen,
timeout = vim.o.timeoutlen, -- the time in which the keys must be hit in ms. Use option timeoutlen by default default_mappings = true,
clear_empty_lines = false, -- clear line after escaping if there is only whitespace mappings = {
keys = "<Esc>", -- keys used for escaping, if it is a function will use the result everytime i = {
-- example(recommended) j = {
-- keys = function() -- These can all also be functions
-- return vim.api.nvim_win_get_cursor(0)[2] > 1 and '<esc>l' or '<esc>' k = "<Esc>",
-- end, j = "<Esc>",
},
},
c = {
j = {
k = "<Esc>",
j = "<Esc>",
},
},
t = {
j = {
k = "<Esc>",
j = "<Esc>",
},
},
v = {
j = {
k = "<Esc>",
},
},
s = {
j = {
k = "<Esc>",
},
},
},
} }
``` ```
</details>
## API ## API
`require("better_escape").waiting` is a boolean indicating that it's waiting for `require("better_escape").waiting` is a boolean indicating that it's waiting for
a mapped sequence to complete. a mapped sequence to complete.
<details> <details>
<summary>statusline example</summary> <summary>Statusline example</summary>
```lua ```lua
function escape_status() function escape_status()
@ -68,28 +147,15 @@ end
</details> </details>
## 👀Demo
![mapping](https://user-images.githubusercontent.com/81827001/135870002-07c1dc41-f3e7-4ece-af6f-50e9b0711a66.gif)
![plugin](https://user-images.githubusercontent.com/81827001/135870101-febf3507-9327-4b80-aa9a-ba08bff6b8d4.gif)
## 🎓How it works
With the mappings there are two tables created.
One contains all first characters and one all second characters.
Whenever you type a character the plugin checks if it's in any of the two tables
If it is in the first one, the plugin starts a timer.
If it is in the second, the plugin checks whether the character you typed before is in the table with the first characters.
If this is the case the plugin gets all the indices where the characters are in the tables, then is searches for matches.
If there is a match, that means that there is a mapping which has the typed character as second and the previous typed character as first character.
The plugin then checks if the time passed since the first character was types is smaller than `timoutlen`.
If this is the case the two characters get deleted and `keys` get feed or executed.
Like this it is possible that the characters really get inserted and therefore you have no delay after typing one of the characters of your mapping.
With the `timeoutlen` it's still possible to type the characters of your mappings.
## ❤️ Support ## ❤️ Support
If you like the projects I do and they can help you in your life you can support my work with [github sponsors](https://github.com/sponsors/max397574).
Every support motivates me to continue working on my open source projects. If you like the projects I do and they can help you in your life you can support
my work with [github sponsors](https://github.com/sponsors/max397574). Every
support motivates me to continue working on my open source projects.
## Similar plugins
The old version of this plugin was a lua version of
[better_escape.vim](https://github.com/jdhao/better-escape.vim), with some
additional features and optimizations. This changed with the rewrite though. Now
it has much more features.

View File

@ -1,5 +1,32 @@
# Changelog # Changelog
## [1.8.0](https://github.com/catppuccin/nvim/compare/v1.7.0...v1.8.0) (2024-07-25)
### Features
* add `grug-far.nvim` integration ([#735](https://github.com/catppuccin/nvim/issues/735)) ([07f1ee8](https://github.com/catppuccin/nvim/commit/07f1ee861394c163d1f1d3e1926eb309e0c81027))
* **bufferline:** add `indicator_visible` and `modified_visible` ([#716](https://github.com/catppuccin/nvim/issues/716)) ([cc8e290](https://github.com/catppuccin/nvim/commit/cc8e290d4c0d572171243087f8541e49be2c8764))
* **csv:** built-in rainbow highlighting ([#720](https://github.com/catppuccin/nvim/issues/720)) ([67565cd](https://github.com/catppuccin/nvim/commit/67565cd353fa543fa30cb738570c2e4c87da3e9c))
* **diffview:** add diffview integrations ([#700](https://github.com/catppuccin/nvim/issues/700)) ([182f256](https://github.com/catppuccin/nvim/commit/182f25640f85a3da2f1f22b088848d896a50fcce))
* **feline:** add lazy.nvim updates module, replace deprecated API ([#725](https://github.com/catppuccin/nvim/issues/725)) ([47bd419](https://github.com/catppuccin/nvim/commit/47bd419c0cb776cb0a67ebb525891eca44020b59))
* **feline:** allow to hide lazy.nvim updates ([#731](https://github.com/catppuccin/nvim/issues/731)) ([7946d1a](https://github.com/catppuccin/nvim/commit/7946d1a195c66fed38b3e34f9fa8e0c5a2da0700))
* **integration:** add colorful-winsep.nvim ([#701](https://github.com/catppuccin/nvim/issues/701)) ([30481d6](https://github.com/catppuccin/nvim/commit/30481d659b6524e6bcae0756201d737e5bc1f209))
* **mini:** add new highlight groups ([#721](https://github.com/catppuccin/nvim/issues/721)) ([6827a67](https://github.com/catppuccin/nvim/commit/6827a6763888f73df686f32c0e5ffb5b6b754d7b))
* **nvim-surround:** add integration ([#733](https://github.com/catppuccin/nvim/issues/733)) ([3f16c6d](https://github.com/catppuccin/nvim/commit/3f16c6d1f25bcb641f7b59f7108b9f4533974c41))
* support new "Ok" diagnostics ([5215ea5](https://github.com/catppuccin/nvim/commit/5215ea59df6d0a7e27da9a5cd1165e06d1b04cbe))
* **treesitter-content:** highlight line number ([#709](https://github.com/catppuccin/nvim/issues/709)) ([4edca6b](https://github.com/catppuccin/nvim/commit/4edca6bed2ccc2715317725985c692ef0a992a50))
### Bug Fixes
* **dapui:** border match bg color ([#727](https://github.com/catppuccin/nvim/issues/727)) ([4ea0173](https://github.com/catppuccin/nvim/commit/4ea01738dc7b872f0081e7093e46d418d8d4c5a1))
* **defaults:** Enable mini integration by default ([894efb5](https://github.com/catppuccin/nvim/commit/894efb557728e532aa98b98029d16907a214ec05))
* **leap:** highlight group for LeapLabel ([2d3419c](https://github.com/catppuccin/nvim/commit/2d3419c2aead379b7d1854d32458f20ffaa58562))
* **neogit:** link WinSeparator ([#713](https://github.com/catppuccin/nvim/issues/713)) ([afccb3d](https://github.com/catppuccin/nvim/commit/afccb3d2377a3d6f0f65405899c9c23b1fd7cc28))
* small typo in feline.lua file ([#719](https://github.com/catppuccin/nvim/issues/719)) ([c0bea77](https://github.com/catppuccin/nvim/commit/c0bea773a09e49e123136b099bce9ddc1bf395d2))
* **treesitter:** highlight paths in `.gitignore` as text ([#736](https://github.com/catppuccin/nvim/issues/736)) ([4374588](https://github.com/catppuccin/nvim/commit/4374588df4e99d403a359cda2ddececcf645d8a9))
## [1.7.0](https://github.com/catppuccin/nvim/compare/v1.6.0...v1.7.0) (2024-04-13) ## [1.7.0](https://github.com/catppuccin/nvim/compare/v1.6.0...v1.7.0) (2024-04-13)

View File

@ -581,7 +581,10 @@ ctp_feline.setup({
extras = clrs.overlay1, extras = clrs.overlay1,
curr_file = clrs.maroon, curr_file = clrs.maroon,
curr_dir = clrs.flamingo, curr_dir = clrs.flamingo,
show_modified = true -- show if the file has been modified show_modified = false -- show if the file has been modified
show_lazy_updates = false -- show the count of updatable plugins from lazy.nvim
-- need to set checker.enabled = true in lazy.nvim first
-- the icon is set in ui.icons.plugin in lazy.nvim
}, },
mode_colors = { mode_colors = {
["n"] = { "NORMAL", clrs.lavender }, ["n"] = { "NORMAL", clrs.lavender },
@ -704,6 +707,17 @@ gitsigns = true
``` ```
<!-- gitsigns.nvim --> <!-- gitsigns.nvim -->
<!-- grug-far.nvim -->
</tr>
<tr>
<td> <a href="https://github.com/MagicDuck/grug-far.nvim">grug-far.nvim</a> </td>
<td>
```lua
grug_far = false
```
<!-- grug-far.nvim -->
<!-- harpoon --> <!-- harpoon -->
</tr> </tr>
<tr> <tr>
@ -1121,6 +1135,20 @@ semantic_tokens = true
</tr> </tr>
<!-- nvim-semantic-tokens --> <!-- nvim-semantic-tokens -->
<!-- nvim-surround -->
</tr>
<tr>
<td> <a href="https://github.com/kylechui/nvim-surround">nvim-surround</a> </td>
<td>
```lua
nvim_surround = false
```
</td>
</tr>
<!-- nvim-surround -->
<!-- nvim-tree.lua --> <!-- nvim-tree.lua -->
</tr> </tr>
<tr> <tr>
@ -1298,6 +1326,20 @@ To use another flavour just replace `mocha` with the one you want to use.
</tr> </tr>
<!-- reactive.nvim --> <!-- reactive.nvim -->
<!-- markdown.nvim -->
</tr>
<tr>
<td> <a href="https://github.com/MeanderingProgrammer/markdown.nvim">render-markdown (markdown.nvim)</a> </td>
<td>
```lua
render_markdown = true
```
</td>
</tr>
<!-- markdown.nvim -->
<!-- symbols-outline.nvim --> <!-- symbols-outline.nvim -->
</tr> </tr>
<tr> <tr>

View File

@ -455,7 +455,10 @@ Here are the defaults:
extras = clrs.overlay1, extras = clrs.overlay1,
curr_file = clrs.maroon, curr_file = clrs.maroon,
curr_dir = clrs.flamingo, curr_dir = clrs.flamingo,
show_modified = true -- show if the file has been modified show_modified = false -- show if the file has been modified
show_lazy_updates = false -- show the count of updatable plugins from lazy.nvim
-- need to set checker.enabled = true in lazy.nvim first
-- the icon is set in ui.icons.plugin in lazy.nvim
}, },
mode_colors = { mode_colors = {
["n"] = { "NORMAL", clrs.lavender }, ["n"] = { "NORMAL", clrs.lavender },
@ -539,6 +542,10 @@ gitsigns.nvim>lua
gitsigns = true gitsigns = true
< <
grug-far.nvim>lua
grug_far = false
<
harpoon>lua harpoon>lua
harpoon = false harpoon = false
< <
@ -721,6 +728,10 @@ nvim-semantic-tokens>lua
semantic_tokens = true semantic_tokens = true
< <
nvim-surround>lua
nvim_surround = false
<
nvim-tree.lua>lua nvim-tree.lua>lua
nvimtree = true nvimtree = true
< <
@ -779,6 +790,10 @@ Here is how you can use them.
To use another flavour just replace `mocha` with the one you want to use. To use another flavour just replace `mocha` with the one you want to use.
render-markdown (markdown.nvim)>lua
render_markdown = true
<
symbols-outline.nvim symbols-outline.nvim
[!NOTE] This plugin has been archived by the author, consider using [!NOTE] This plugin has been archived by the author, consider using
outline.nvim <https://github.com/hedyhli/outline.nvim> outline.nvim <https://github.com/hedyhli/outline.nvim>

View File

@ -12,7 +12,7 @@ function M.get()
DapUIStoppedThread = { fg = C.sky }, DapUIStoppedThread = { fg = C.sky },
DapUISource = { fg = C.lavender }, DapUISource = { fg = C.lavender },
DapUILineNumber = { fg = C.sky }, DapUILineNumber = { fg = C.sky },
DapUIFloatBorder = { fg = C.sky }, DapUIFloatBorder = { link = "FloatBorder" },
DapUIWatchesEmpty = { fg = C.maroon }, DapUIWatchesEmpty = { fg = C.maroon },
DapUIWatchesValue = { fg = C.green }, DapUIWatchesValue = { fg = C.green },

View File

@ -32,6 +32,7 @@ local sett = {
curr_file = C.maroon, curr_file = C.maroon,
curr_dir = C.flamingo, curr_dir = C.flamingo,
show_modified = false, show_modified = false,
show_lazy_updates = false,
} }
if require("catppuccin").flavour == "latte" then if require("catppuccin").flavour == "latte" then
@ -287,7 +288,7 @@ function M.get()
-- macro -- macro
components.active[1][12] = { components.active[1][12] = {
provider = "macro", provider = "macro",
enabled = function() return vim.api.nvim_get_option "cmdheight" == 0 end, enabled = function() return vim.api.nvim_get_option_value("cmdheight", { scope = "global" }) == 0 end,
hl = { hl = {
fg = sett.extras, fg = sett.extras,
bg = sett.bkg, bg = sett.bkg,
@ -298,7 +299,24 @@ function M.get()
-- search count -- search count
components.active[1][13] = { components.active[1][13] = {
provider = "search_count", provider = "search_count",
enabled = function() return vim.api.nvim_get_option "cmdheight" == 0 end, enabled = function() return vim.api.nvim_get_option_value("cmdheight", { scope = "global" }) == 0 end,
hl = {
fg = sett.extras,
bg = sett.bkg,
},
left_sep = invi_sep,
}
-- lazy.nvim updates
components.active[1][14] = {
provider = function() return require("lazy.status").updates() end,
enabled = function()
if sett.show_lazy_updates and pcall(require, "lazy") then
return require("lazy.status").has_updates()
else
return false
end
end,
hl = { hl = {
fg = sett.extras, fg = sett.extras,
bg = sett.bkg, bg = sett.bkg,
@ -412,7 +430,7 @@ function M.get()
components.active[3][2] = { components.active[3][2] = {
provider = function() provider = function()
local active_clients = vim.lsp.get_active_clients { bufnr = 0 } local active_clients = vim.lsp.get_clients { bufnr = 0 }
-- show an indicator that we have running lsps -- show an indicator that we have running lsps
if view.lsp.name == false and next(active_clients) ~= nil then return assets.lsp.server .. " " .. "Lsp" end if view.lsp.name == false and next(active_clients) ~= nil then return assets.lsp.server .. " " .. "Lsp" end

View File

@ -6,17 +6,12 @@ function M.get()
fg = O.transparent_background and C.pink or U.vary_color({ latte = "#222222" }, U.brighten(C.green, 0.3)), fg = O.transparent_background and C.pink or U.vary_color({ latte = "#222222" }, U.brighten(C.green, 0.3)),
style = { "underline", "nocombine", O.transparent_background and "bold" or nil }, style = { "underline", "nocombine", O.transparent_background and "bold" or nil },
}, },
LeapLabelPrimary = { LeapLabel = {
fg = O.transparent_background and C.green or U.vary_color({ latte = "#222222" }, C.base), fg = O.transparent_background and C.green or U.vary_color({ latte = "#222222" }, C.base),
bg = O.transparent_background and C.none bg = O.transparent_background and C.none
or U.vary_color({ latte = U.brighten(C.red, 0.4) }, U.brighten(C.green, 0.3)), or U.vary_color({ latte = U.brighten(C.red, 0.4) }, U.brighten(C.green, 0.3)),
style = { "nocombine", O.transparent_background and "bold" or nil }, style = { "nocombine", O.transparent_background and "bold" or nil },
}, },
LeapLabelSecondary = {
fg = O.transparent_background and C.blue or U.vary_color({ latte = "#222222" }, C.base),
bg = O.transparent_background and C.none or U.vary_color({ latte = U.brighten(C.sky, 0.3) }, C.sky),
style = { "nocombine", O.transparent_background and "bold" or nil },
},
LeapBackdrop = { fg = O.transparent_background and C.overlay0 or C.none }, LeapBackdrop = { fg = O.transparent_background and C.overlay0 or C.none },
} }
end end

View File

@ -8,17 +8,99 @@ function M.get()
local indentscope_color = O.integrations.mini.indentscope_color local indentscope_color = O.integrations.mini.indentscope_color
return { return {
MiniAnimateCursor = { style = { "reverse", "nocombine" } },
MiniAnimateNormalFloat = { link = "NormalFloat" },
MiniClueBorder = { link = "FloatBorder" },
MiniClueDescGroup = { link = "DiagnosticFloatingWarn" },
MiniClueDescSingle = { link = "NormalFloat" },
MiniClueNextKey = { link = "DiagnosticFloatingHint" },
MiniClueNextKeyWithPostkeys = { link = "DiagnosticFloatingError" },
MiniClueSeparator = { link = "DiagnosticFloatingInfo" },
MiniClueTitle = { link = "FloatTitle" },
MiniCompletionActiveParameter = { style = { "underline" } }, MiniCompletionActiveParameter = { style = { "underline" } },
MiniCursorword = { style = { "underline" } }, MiniCursorword = { style = { "underline" } },
MiniCursorwordCurrent = { style = { "underline" } }, MiniCursorwordCurrent = { style = { "underline" } },
MiniDepsChangeAdded = { link = "diffAdded" },
MiniDepsChangeRemoved = { link = "diffRemoved" },
MiniDepsHint = { link = "DiagnosticHint" },
MiniDepsInfo = { link = "DiagnosticInfo" },
MiniDepsMsgBreaking = { link = "DiagnosticWarn" },
MiniDepsPlaceholder = { link = "Comment" },
MiniDepsTitle = { link = "Title" },
MiniDepsTitleError = { bg = C.red, fg = C.base },
MiniDepsTitleSame = { link = "DiffText" },
MiniDepsTitleUpdate = { bg = C.green, fg = C.base },
MiniDiffSignAdd = { fg = C.green },
MiniDiffSignChange = { fg = C.yellow },
MiniDiffSignDelete = { fg = C.red },
MiniDiffOverAdd = { link = "DiffAdd" },
MiniDiffOverChange = { link = "DiffText" },
MiniDiffOverContext = { link = "DiffChange" },
MiniDiffOverDelete = { link = "DiffDelete" },
MiniFilesBorder = { link = "FloatBorder" },
MiniFilesBorderModified = { link = "DiagnosticFloatingWarn" },
MiniFilesCursorLine = { link = "CursorLine" },
MiniFilesDirectory = { link = "Directory" },
MiniFilesFile = { fg = C.text },
MiniFilesNormal = { link = "NormalFloat" },
MiniFilesTitle = { link = "FloatTitle" },
MiniFilesTitleFocused = { fg = C.subtext0, style = { "bold" } },
MiniHipatternsFixme = { fg = C.base, bg = C.red, style = { "bold" } },
MiniHipatternsHack = { fg = C.base, bg = C.yellow, style = { "bold" } },
MiniHipatternsNote = { fg = C.base, bg = C.sky, style = { "bold" } },
MiniHipatternsTodo = { fg = C.base, bg = C.teal, style = { "bold" } },
MiniIconsAzure = { fg = C.sapphire },
MiniIconsBlue = { fg = C.blue },
MiniIconsCyan = { fg = C.teal },
MiniIconsGreen = { fg = C.green },
MiniIconsGrey = { fg = C.text },
MiniIconsOrange = { fg = C.peach },
MiniIconsPurple = { fg = C.mauve },
MiniIconsRed = { fg = C.red },
MiniIconsYellow = { fg = C.yellow },
MiniIndentscopeSymbol = { fg = C[indentscope_color] or C.text }, MiniIndentscopeSymbol = { fg = C[indentscope_color] or C.text },
MiniIndentscopePrefix = { style = { "nocombine" } }, -- Make it invisible MiniIndentscopePrefix = { style = { "nocombine" } }, -- Make it invisible
MiniJump = { fg = C.overlay2, bg = C.pink }, MiniJump = { fg = C.overlay2, bg = C.pink },
MiniJump2dDim = { fg = C.overlay0 },
MiniJump2dSpot = { bg = C.base, fg = C.peach, style = { "bold", "underline" } }, MiniJump2dSpot = { bg = C.base, fg = C.peach, style = { "bold", "underline" } },
MiniJump2dSpotAhead = { bg = C.dim, fg = C.teal },
MiniJump2dSpotUnique = { bg = C.base, fg = C.sky, style = { "bold" } },
MiniMapNormal = { link = "NormalFloat" },
MiniMapSymbolCount = { link = "Special" },
MiniMapSymbolLine = { link = "Title" },
MiniMapSymbolView = { link = "Delimiter" },
MiniNotifyBorder = { link = "FloatBorder" },
MiniNotifyNormal = { link = "NormalFloat" },
MiniNotifyTitle = { link = "FloatTitle" },
MiniOperatorsExchangeFrom = { link = "IncSearch" },
MiniPickBorder = { link = "FloatBorder" },
MiniPickBorderBusy = { link = "DiagnosticFloatingWarn" },
MiniPickBorderText = { fg = C.mauve },
MiniPickIconDirectory = { link = "Directory" },
MiniPickIconFile = { link = "MiniPickNormal" },
MiniPickHeader = { link = "DiagnosticFloatingHint" },
MiniPickMatchCurrent = { link = "CursorLine" },
MiniPickMatchMarked = { link = "Visual" },
MiniPickMatchRanges = { link = "DiagnosticFloatingHint" },
MiniPickNormal = { link = "NormalFloat" },
MiniPickPreviewLine = { link = "CursorLine" },
MiniPickPreviewRegion = { link = "IncSearch" },
MiniPickPrompt = { link = "DiagnosticFloatingInfo" },
MiniStarterCurrent = {}, MiniStarterCurrent = {},
MiniStarterFooter = { fg = C.yellow, style = { "italic" } }, MiniStarterFooter = { fg = C.yellow, style = { "italic" } },

View File

@ -195,6 +195,9 @@ If you want to stay on nvim 0.7, either disable the integration or pin catppucci
-- gitcommit -- gitcommit
["@comment.warning.gitcommit"] = { fg = C.yellow }, ["@comment.warning.gitcommit"] = { fg = C.yellow },
-- gitignore
["@string.special.path.gitignore"] = { fg = C.text },
-- Misc -- Misc
gitcommitSummary = { fg = C.rosewater, style = O.styles.miscs or { "italic" } }, gitcommitSummary = { fg = C.rosewater, style = O.styles.miscs or { "italic" } },
zshKSHFunction = { link = "Function" }, zshKSHFunction = { link = "Function" },

View File

@ -96,6 +96,17 @@ function M.get()
rainbow4 = { fg = C.green }, rainbow4 = { fg = C.green },
rainbow5 = { fg = C.sapphire }, rainbow5 = { fg = C.sapphire },
rainbow6 = { fg = C.lavender }, rainbow6 = { fg = C.lavender },
-- csv
csvCol0 = { fg = C.red },
csvCol1 = { fg = C.peach },
csvCol2 = { fg = C.yellow },
csvCol3 = { fg = C.green },
csvCol4 = { fg = C.sky },
csvCol5 = { fg = C.blue },
csvCol6 = { fg = C.lavender },
csvCol7 = { fg = C.mauve },
csvCol8 = { fg = C.pink },
} }
end end

View File

@ -52,6 +52,7 @@ local M = {
nvimtree = true, nvimtree = true,
ufo = true, ufo = true,
rainbow_delimiters = true, rainbow_delimiters = true,
render_markdown = true,
semantic_tokens = not is_vim, semantic_tokens = not is_vim,
telescope = { enabled = true }, telescope = { enabled = true },
treesitter = not is_vim, treesitter = not is_vim,
@ -103,6 +104,10 @@ local M = {
enabled = false, enabled = false,
color = "red", color = "red",
}, },
mini = {
enabled = true,
indentscope_color = "text",
},
}, },
color_overrides = {}, color_overrides = {},
highlight_overrides = {}, highlight_overrides = {},

View File

@ -151,6 +151,7 @@
---@field flash boolean? ---@field flash boolean?
---@field gitgutter boolean? ---@field gitgutter boolean?
---@field gitsigns boolean? ---@field gitsigns boolean?
---@field grug_far boolean?
---@field harpoon boolean? ---@field harpoon boolean?
---@field headlines boolean? ---@field headlines boolean?
---@field hop boolean? ---@field hop boolean?
@ -185,11 +186,13 @@
---@field neotree boolean? ---@field neotree boolean?
---@field noice boolean? ---@field noice boolean?
---@field notify boolean? ---@field notify boolean?
---@field nvim_surround boolean?
---@field nvimtree boolean? ---@field nvimtree boolean?
---@field octo boolean? ---@field octo boolean?
---@field overseer boolean? ---@field overseer boolean?
---@field pounce boolean? ---@field pounce boolean?
---@field rainbow_delimiters boolean? ---@field rainbow_delimiters boolean?
---@field render_markdown boolean?
---@field sandwich boolean? ---@field sandwich boolean?
---@field semantic_tokens boolean? ---@field semantic_tokens boolean?
---@field symbols_outline boolean? ---@field symbols_outline boolean?

View File

@ -1,3 +1,3 @@
#!/nix/store/agkxax48k35wdmkhmmija2i2sxg8i7ny-bash-5.2p26/bin/bash #!/nix/store/4bj2kxdm1462fzcc2i2s4dn33g2angcc-bash-5.2p32/bin/bash
set -e set -e
make fastlint make fastlint

View File

@ -1,4 +1,4 @@
#!/nix/store/agkxax48k35wdmkhmmija2i2sxg8i7ny-bash-5.2p26/bin/bash #!/nix/store/4bj2kxdm1462fzcc2i2s4dn33g2angcc-bash-5.2p32/bin/bash
set -e set -e
IFS=' ' IFS=' '
while read local_ref _local_sha _remote_ref _remote_sha; do while read local_ref _local_sha _remote_ref _remote_sha; do

View File

@ -50,7 +50,6 @@ jobs:
strategy: strategy:
matrix: matrix:
include: include:
- nvim_tag: v0.8.3
- nvim_tag: v0.9.4 - nvim_tag: v0.9.4
- nvim_tag: v0.10.0 - nvim_tag: v0.10.0

View File

@ -1,5 +1,78 @@
# Changelog # Changelog
## [7.0.0](https://github.com/stevearc/conform.nvim/compare/v6.1.0...v7.0.0) (2024-07-23)
### ⚠ BREAKING CHANGES
* drop support for nvim 0.8
### cleanup
* drop support for nvim 0.8 ([54ea60d](https://github.com/stevearc/conform.nvim/commit/54ea60d1591486e7e56183addf1f45b03244386d))
### Features
* add sleek, a SQL formatter ([#496](https://github.com/stevearc/conform.nvim/issues/496)) ([8925292](https://github.com/stevearc/conform.nvim/commit/8925292a1e18430a0176671552394d819642b9d9))
* allow configuring conform.format() args on a per-filetype basis ([3a0e9b4](https://github.com/stevearc/conform.nvim/commit/3a0e9b44076514ffba6c81ca28685107928b55f7))
* allow customizing format() defaults ([d7de350](https://github.com/stevearc/conform.nvim/commit/d7de350233e8f686b9affac9c1e106a6602f5fe8))
* deprecate will_fallback_lsp in favor of list_formatters_to_run ([1b590cd](https://github.com/stevearc/conform.nvim/commit/1b590cda290bbabdb116397cb241d20530281b87))
* format parameter to only run the first available formatter ([0b3d259](https://github.com/stevearc/conform.nvim/commit/0b3d25969e2da2f5de90cc02ccd6446aa68dd895))
* notify when no formatters available for a buffer ([8c226d9](https://github.com/stevearc/conform.nvim/commit/8c226d917918ffe92e0f30f4e13acfc088a5faa7))
### Bug Fixes
* crash in nvim-notify ([c16c749](https://github.com/stevearc/conform.nvim/commit/c16c749612fb34a9c1dcc6e4a0f40e24e37d5cfb))
* ensure only expected options get passed through ([834d42c](https://github.com/stevearc/conform.nvim/commit/834d42c17687541750447046b94193d47386665d))
* warn user when they are attempting unsupported behavior ([8b0e62b](https://github.com/stevearc/conform.nvim/commit/8b0e62b731429ecd89cdb6c6b8f004f8468bcf71))
## [6.1.0](https://github.com/stevearc/conform.nvim/compare/v6.0.0...v6.1.0) (2024-07-19)
### Features
* add Swiftlint formatter ([#484](https://github.com/stevearc/conform.nvim/issues/484)) ([bf94a7c](https://github.com/stevearc/conform.nvim/commit/bf94a7cee31df9525239bc7d5ca4910009dfa4ee))
* add undojoin as a format option ([#488](https://github.com/stevearc/conform.nvim/issues/488)) ([1d1362b](https://github.com/stevearc/conform.nvim/commit/1d1362b0261d06a0b91872e916c172320bbb988a))
* **shfmt:** add automatic indentation detection ([#481](https://github.com/stevearc/conform.nvim/issues/481)) ([cd75be8](https://github.com/stevearc/conform.nvim/commit/cd75be867f2331b22905f47d28c0c270a69466aa))
* support doctoc ([#489](https://github.com/stevearc/conform.nvim/issues/489)) ([4f476ba](https://github.com/stevearc/conform.nvim/commit/4f476ba2247bfa5fe46ad52d934536d271d75431))
### Bug Fixes
* **biome-check:** use --write instead of deprecated --apply ([#482](https://github.com/stevearc/conform.nvim/issues/482)) ([0cdd6a7](https://github.com/stevearc/conform.nvim/commit/0cdd6a7c66a57560c91c816a567bd1d247be53c3))
* display stdout as error message if stderr is empty ([#486](https://github.com/stevearc/conform.nvim/issues/486)) ([310e2e9](https://github.com/stevearc/conform.nvim/commit/310e2e95a4f832163f3f7a9fedebb1a4afc0db69))
* **npm-groovy-lint:** ignore exit code 1 ([#477](https://github.com/stevearc/conform.nvim/issues/477)) ([c26dadf](https://github.com/stevearc/conform.nvim/commit/c26dadf8a47a547768d1048a0d698ecec33494ce))
* **shfmt:** don't pass indentation if .editorconfig is present ([#492](https://github.com/stevearc/conform.nvim/issues/492)) ([acc7d93](https://github.com/stevearc/conform.nvim/commit/acc7d93f4a080fec587a99fcb36cffa29adc4bad))
## [6.0.0](https://github.com/stevearc/conform.nvim/compare/v5.9.0...v6.0.0) (2024-06-25)
### ⚠ BREAKING CHANGES
* expand options for LSP formatting ([#456](https://github.com/stevearc/conform.nvim/issues/456))
### Features
* add support for caramel fmt ([#469](https://github.com/stevearc/conform.nvim/issues/469)) ([c35f52b](https://github.com/stevearc/conform.nvim/commit/c35f52b04e4436d5525102b2d61150679c967100))
* **djlint:** use tabstop to set indentation ([#467](https://github.com/stevearc/conform.nvim/issues/467)) ([ac6e142](https://github.com/stevearc/conform.nvim/commit/ac6e142a10c8817762f55a35ed6cb9632671ec79)), closes [#457](https://github.com/stevearc/conform.nvim/issues/457)
* expand options for LSP formatting ([#456](https://github.com/stevearc/conform.nvim/issues/456)) ([9228b2f](https://github.com/stevearc/conform.nvim/commit/9228b2ff4efd58b6e081defec643bf887ebadff6))
* support brighterscript-formatter ([#468](https://github.com/stevearc/conform.nvim/issues/468)) ([89af7f0](https://github.com/stevearc/conform.nvim/commit/89af7f00b6e52647c7b0e04eb8cc9bc9cab91e3e))
* support crlfmt ([#470](https://github.com/stevearc/conform.nvim/issues/470)) ([7394d49](https://github.com/stevearc/conform.nvim/commit/7394d4989cd08ddb72e526c43afae7dd3111d553))
* support dcm fix and dcm format ([#471](https://github.com/stevearc/conform.nvim/issues/471)) ([b67f273](https://github.com/stevearc/conform.nvim/commit/b67f2732a2d0276454c7623204741d908de5358a))
* support docformatter ([#472](https://github.com/stevearc/conform.nvim/issues/472)) ([b5ae342](https://github.com/stevearc/conform.nvim/commit/b5ae342ab28919a8083b589a587b030ad859592e))
* support gluon fmt ([#473](https://github.com/stevearc/conform.nvim/issues/473)) ([d1f9bd4](https://github.com/stevearc/conform.nvim/commit/d1f9bd4823628d26a10b98acc9b3b6dbc7b1c053))
* support grain format ([#474](https://github.com/stevearc/conform.nvim/issues/474)) ([d2afc5d](https://github.com/stevearc/conform.nvim/commit/d2afc5de7a24dcde7af13209b91d8e3b87a89661))
* support imba fmt ([#475](https://github.com/stevearc/conform.nvim/issues/475)) ([6856aed](https://github.com/stevearc/conform.nvim/commit/6856aed6d7abf94735739d44a459aef977c2ab44))
* support nickel format ([#476](https://github.com/stevearc/conform.nvim/issues/476)) ([241c892](https://github.com/stevearc/conform.nvim/commit/241c892b265f7a5906584b34c5be36b48c09a4b8))
### Bug Fixes
* deprecate typstfmt formatter ([#458](https://github.com/stevearc/conform.nvim/issues/458)) ([6e5d476](https://github.com/stevearc/conform.nvim/commit/6e5d476e97dbd251cc2233d42fd238c810404701))
* LSP fallback behavior when formatters not availble ([bde3bee](https://github.com/stevearc/conform.nvim/commit/bde3bee1773c96212b6c49f009e05174f932c23a))
## [5.9.0](https://github.com/stevearc/conform.nvim/compare/v5.8.0...v5.9.0) (2024-06-10) ## [5.9.0](https://github.com/stevearc/conform.nvim/compare/v5.8.0...v5.9.0) (2024-06-10)

View File

@ -18,16 +18,16 @@ Lightweight yet powerful formatter plugin for Neovim
- [setup(opts)](#setupopts) - [setup(opts)](#setupopts)
- [format(opts, callback)](#formatopts-callback) - [format(opts, callback)](#formatopts-callback)
- [list_formatters(bufnr)](#list_formattersbufnr) - [list_formatters(bufnr)](#list_formattersbufnr)
- [list_formatters_to_run(bufnr)](#list_formatters_to_runbufnr)
- [list_all_formatters()](#list_all_formatters) - [list_all_formatters()](#list_all_formatters)
- [get_formatter_info(formatter, bufnr)](#get_formatter_infoformatter-bufnr) - [get_formatter_info(formatter, bufnr)](#get_formatter_infoformatter-bufnr)
- [will_fallback_lsp(options)](#will_fallback_lspoptions)
- [Acknowledgements](#acknowledgements) - [Acknowledgements](#acknowledgements)
<!-- /TOC --> <!-- /TOC -->
## Requirements ## Requirements
- Neovim 0.8+ - Neovim 0.9+ (for older versions, use a [nvim-0.x branch](https://github.com/stevearc/conform.nvim/branches))
## Features ## Features
@ -129,8 +129,10 @@ require("conform").setup({
lua = { "stylua" }, lua = { "stylua" },
-- Conform will run multiple formatters sequentially -- Conform will run multiple formatters sequentially
python = { "isort", "black" }, python = { "isort", "black" },
-- Use a sub-list to run only the first available formatter -- You can customize some of the format options for the filetype (:help conform.format)
javascript = { { "prettierd", "prettier" } }, rust = { "rustfmt", lsp_format = "fallback" },
-- Conform will run the first available formatter
javascript = { "prettierd", "prettier", stop_after_first = true },
}, },
}) })
``` ```
@ -196,24 +198,31 @@ You can view this list in vim with `:help conform-formatters`
- [blade-formatter](https://github.com/shufo/blade-formatter) - An opinionated blade template formatter for Laravel that respects readability. - [blade-formatter](https://github.com/shufo/blade-formatter) - An opinionated blade template formatter for Laravel that respects readability.
- [blue](https://github.com/grantjenks/blue) - The slightly less uncompromising Python code formatter. - [blue](https://github.com/grantjenks/blue) - The slightly less uncompromising Python code formatter.
- [bpfmt](https://source.android.com/docs/setup/reference/androidbp) - Android Blueprint file formatter. - [bpfmt](https://source.android.com/docs/setup/reference/androidbp) - Android Blueprint file formatter.
- [bsfmt](https://github.com/rokucommunity/brighterscript-formatter) - A code formatter for BrighterScript (and BrightScript).
- [buf](https://buf.build/docs/reference/cli/buf/format) - A new way of working with Protocol Buffers. - [buf](https://buf.build/docs/reference/cli/buf/format) - A new way of working with Protocol Buffers.
- [buildifier](https://github.com/bazelbuild/buildtools/tree/master/buildifier) - buildifier is a tool for formatting bazel BUILD and .bzl files with a standard convention. - [buildifier](https://github.com/bazelbuild/buildtools/tree/master/buildifier) - buildifier is a tool for formatting bazel BUILD and .bzl files with a standard convention.
- [cabal_fmt](https://hackage.haskell.org/package/cabal-fmt) - Format cabal files with cabal-fmt - [cabal_fmt](https://hackage.haskell.org/package/cabal-fmt) - Format cabal files with cabal-fmt
- [caramel_fmt](https://caramel.run/manual/reference/cli/fmt.html) - Format Caramel code.
- [cbfmt](https://github.com/lukas-reineke/cbfmt) - A tool to format codeblocks inside markdown and org documents. - [cbfmt](https://github.com/lukas-reineke/cbfmt) - A tool to format codeblocks inside markdown and org documents.
- [clang-format](https://www.kernel.org/doc/html/latest/process/clang-format.html) - Tool to format C/C++/… code according to a set of rules and heuristics. - [clang-format](https://www.kernel.org/doc/html/latest/process/clang-format.html) - Tool to format C/C++/… code according to a set of rules and heuristics.
- [cljstyle](https://github.com/greglook/cljstyle) - Formatter for Clojure code. - [cljstyle](https://github.com/greglook/cljstyle) - Formatter for Clojure code.
- [cmake_format](https://github.com/cheshirekow/cmake_format) - Parse cmake listfiles and format them nicely. - [cmake_format](https://github.com/cheshirekow/cmake_format) - Parse cmake listfiles and format them nicely.
- [codespell](https://github.com/codespell-project/codespell) - Check code for common misspellings. - [codespell](https://github.com/codespell-project/codespell) - Check code for common misspellings.
- [crlfmt](https://github.com/cockroachdb/crlfmt) - Formatter for CockroachDB's additions to the Go style guide.
- [crystal](https://crystal-lang.org/) - Format Crystal code. - [crystal](https://crystal-lang.org/) - Format Crystal code.
- [csharpier](https://github.com/belav/csharpier) - The opinionated C# code formatter. - [csharpier](https://github.com/belav/csharpier) - The opinionated C# code formatter.
- [cue_fmt](https://cuelang.org) - Format CUE files using `cue fmt` command. - [cue_fmt](https://cuelang.org) - Format CUE files using `cue fmt` command.
- [d2](https://github.com/terrastruct/d2) - D2 is a modern diagram scripting language that turns text to diagrams. - [d2](https://github.com/terrastruct/d2) - D2 is a modern diagram scripting language that turns text to diagrams.
- [darker](https://github.com/akaihola/darker) - Run black only on changed lines. - [darker](https://github.com/akaihola/darker) - Run black only on changed lines.
- [dart_format](https://dart.dev/tools/dart-format) - Replace the whitespace in your program with formatting that follows Dart guidelines. - [dart_format](https://dart.dev/tools/dart-format) - Replace the whitespace in your program with formatting that follows Dart guidelines.
- [dcm_fix](https://dcm.dev/docs/cli/formatting/fix/) - Fixes issues produced by dcm analyze, dcm check-unused-code or dcm check-dependencies commands.
- [dcm_format](https://dcm.dev/docs/cli/formatting/format/) - Formats .dart files.
- [deno_fmt](https://deno.land/manual/tools/formatter) - Use [Deno](https://deno.land/) to format TypeScript, JavaScript/JSON and markdown. - [deno_fmt](https://deno.land/manual/tools/formatter) - Use [Deno](https://deno.land/) to format TypeScript, JavaScript/JSON and markdown.
- [dfmt](https://github.com/dlang-community/dfmt) - Formatter for D source code. - [dfmt](https://github.com/dlang-community/dfmt) - Formatter for D source code.
- [djlint](https://github.com/Riverside-Healthcare/djLint) - ✨ HTML Template Linter and Formatter. Django - Jinja - Nunjucks - Handlebars - GoLang. - [djlint](https://github.com/Riverside-Healthcare/djLint) - ✨ HTML Template Linter and Formatter. Django - Jinja - Nunjucks - Handlebars - GoLang.
- [docformatter](https://pypi.org/project/docformatter/) - docformatter automatically formats docstrings to follow a subset of the PEP 257 conventions.
- [docstrfmt](https://github.com/LilSpazJoekp/docstrfmt) - reStructuredText formatter. - [docstrfmt](https://github.com/LilSpazJoekp/docstrfmt) - reStructuredText formatter.
- [doctoc](https://github.com/thlorenz/doctoc) - Generates table of contents for markdown files inside local git repository.
- [dprint](https://github.com/dprint/dprint) - Pluggable and configurable code formatting platform written in Rust. - [dprint](https://github.com/dprint/dprint) - Pluggable and configurable code formatting platform written in Rust.
- [easy-coding-standard](https://github.com/easy-coding-standard/easy-coding-standard) - ecs - Use Coding Standard with 0-knowledge of PHP-CS-Fixer and PHP_CodeSniffer. - [easy-coding-standard](https://github.com/easy-coding-standard/easy-coding-standard) - ecs - Use Coding Standard with 0-knowledge of PHP-CS-Fixer and PHP_CodeSniffer.
- [efmt](https://github.com/sile/efmt) - Erlang code formatter. - [efmt](https://github.com/sile/efmt) - Erlang code formatter.
@ -234,6 +243,7 @@ You can view this list in vim with `:help conform-formatters`
- [gdformat](https://github.com/Scony/godot-gdscript-toolkit) - A formatter for Godot's gdscript. - [gdformat](https://github.com/Scony/godot-gdscript-toolkit) - A formatter for Godot's gdscript.
- [gersemi](https://github.com/BlankSpruce/gersemi) - A formatter to make your CMake code the real treasure. - [gersemi](https://github.com/BlankSpruce/gersemi) - A formatter to make your CMake code the real treasure.
- [gleam](https://github.com/gleam-lang/gleam) - ⭐️ A friendly language for building type-safe, scalable systems! - [gleam](https://github.com/gleam-lang/gleam) - ⭐️ A friendly language for building type-safe, scalable systems!
- [gluon_fmt](https://github.com/gluon-lang/gluon) - Code formatting for the gluon programming language.
- [gn](https://gn.googlesource.com/gn/) - gn build system. - [gn](https://gn.googlesource.com/gn/) - gn build system.
- [gofmt](https://pkg.go.dev/cmd/gofmt) - Formats go programs. - [gofmt](https://pkg.go.dev/cmd/gofmt) - Formats go programs.
- [gofumpt](https://github.com/mvdan/gofumpt) - Enforce a stricter format than gofmt, while being backwards compatible. That is, gofumpt is happy with a subset of the formats that gofmt is happy with. - [gofumpt](https://github.com/mvdan/gofumpt) - Enforce a stricter format than gofmt, while being backwards compatible. That is, gofumpt is happy with a subset of the formats that gofmt is happy with.
@ -241,9 +251,11 @@ You can view this list in vim with `:help conform-formatters`
- [goimports-reviser](https://github.com/incu6us/goimports-reviser) - Right imports sorting & code formatting tool (goimports alternative). - [goimports-reviser](https://github.com/incu6us/goimports-reviser) - Right imports sorting & code formatting tool (goimports alternative).
- [golines](https://github.com/segmentio/golines) - A golang formatter that fixes long lines. - [golines](https://github.com/segmentio/golines) - A golang formatter that fixes long lines.
- [google-java-format](https://github.com/google/google-java-format) - Reformats Java source code according to Google Java Style. - [google-java-format](https://github.com/google/google-java-format) - Reformats Java source code according to Google Java Style.
- [grain_format](https://grain-lang.org/docs/tooling/grain_cli#grain-format) - Code formatter for the grain programming language.
- [hcl](https://github.com/hashicorp/hcl) - A formatter for HCL files. - [hcl](https://github.com/hashicorp/hcl) - A formatter for HCL files.
- [hindent](https://github.com/mihaimaruseac/hindent) - Haskell pretty printer. - [hindent](https://github.com/mihaimaruseac/hindent) - Haskell pretty printer.
- [htmlbeautifier](https://github.com/threedaymonk/htmlbeautifier) - A normaliser/beautifier for HTML that also understands embedded Ruby. Ideal for tidying up Rails templates. - [htmlbeautifier](https://github.com/threedaymonk/htmlbeautifier) - A normaliser/beautifier for HTML that also understands embedded Ruby. Ideal for tidying up Rails templates.
- [imba_fmt](https://imba.io/) - Code formatter for the Imba programming language.
- [indent](https://www.gnu.org/software/indent/) - GNU Indent. - [indent](https://www.gnu.org/software/indent/) - GNU Indent.
- [injected](doc/advanced_topics.md#injected-language-formatting-code-blocks) - Format treesitter injected languages. - [injected](doc/advanced_topics.md#injected-language-formatting-code-blocks) - Format treesitter injected languages.
- [inko](https://inko-lang.org/) - A language for building concurrent software with confidence - [inko](https://inko-lang.org/) - A language for building concurrent software with confidence
@ -267,6 +279,7 @@ You can view this list in vim with `:help conform-formatters`
- [mdsf](https://github.com/hougesen/mdsf) - Format markdown code blocks using your favorite code formatters. - [mdsf](https://github.com/hougesen/mdsf) - Format markdown code blocks using your favorite code formatters.
- [mdslw](https://github.com/razziel89/mdslw) - Prepare your markdown for easy diff'ing by adding line breaks after every sentence. - [mdslw](https://github.com/razziel89/mdslw) - Prepare your markdown for easy diff'ing by adding line breaks after every sentence.
- [mix](https://hexdocs.pm/mix/main/Mix.Tasks.Format.html) - Format Elixir files using the mix format command. - [mix](https://hexdocs.pm/mix/main/Mix.Tasks.Format.html) - Format Elixir files using the mix format command.
- [nickel](https://nickel-lang.org/) - Code formatter for the Nickel programming language.
- [nimpretty](https://github.com/nim-lang/nim) - nimpretty is a Nim source code beautifier that follows the official style guide. - [nimpretty](https://github.com/nim-lang/nim) - nimpretty is a Nim source code beautifier that follows the official style guide.
- [nixfmt](https://github.com/serokell/nixfmt) - nixfmt is a formatter for Nix code, intended to apply a uniform style. - [nixfmt](https://github.com/serokell/nixfmt) - nixfmt is a formatter for Nix code, intended to apply a uniform style.
- [nixpkgs_fmt](https://github.com/nix-community/nixpkgs-fmt) - nixpkgs-fmt is a Nix code formatter for nixpkgs. - [nixpkgs_fmt](https://github.com/nix-community/nixpkgs-fmt) - nixpkgs-fmt is a Nix code formatter for nixpkgs.
@ -306,6 +319,7 @@ You can view this list in vim with `:help conform-formatters`
- [shellcheck](https://github.com/koalaman/shellcheck) - A static analysis tool for shell scripts. - [shellcheck](https://github.com/koalaman/shellcheck) - A static analysis tool for shell scripts.
- [shellharden](https://github.com/anordal/shellharden) - The corrective bash syntax highlighter. - [shellharden](https://github.com/anordal/shellharden) - The corrective bash syntax highlighter.
- [shfmt](https://github.com/mvdan/sh) - A shell parser, formatter, and interpreter with `bash` support. - [shfmt](https://github.com/mvdan/sh) - A shell parser, formatter, and interpreter with `bash` support.
- [sleek](https://github.com/nrempel/sleek) - Sleek is a CLI tool for formatting SQL.
- [smlfmt](https://github.com/shwestrick/smlfmt) - A custom parser and code formatter for Standard ML. - [smlfmt](https://github.com/shwestrick/smlfmt) - A custom parser and code formatter for Standard ML.
- [snakefmt](https://github.com/snakemake/snakefmt) - a formatting tool for Snakemake files following the design of Black. - [snakefmt](https://github.com/snakemake/snakefmt) - a formatting tool for Snakemake files following the design of Black.
- [sql_formatter](https://github.com/sql-formatter-org/sql-formatter) - A whitespace formatter for different query languages. - [sql_formatter](https://github.com/sql-formatter-org/sql-formatter) - A whitespace formatter for different query languages.
@ -320,14 +334,15 @@ You can view this list in vim with `:help conform-formatters`
- [stylua](https://github.com/JohnnyMorganz/StyLua) - An opinionated code formatter for Lua. - [stylua](https://github.com/JohnnyMorganz/StyLua) - An opinionated code formatter for Lua.
- [swift_format](https://github.com/apple/swift-format) - Swift formatter from apple. Requires building from source with `swift build`. - [swift_format](https://github.com/apple/swift-format) - Swift formatter from apple. Requires building from source with `swift build`.
- [swiftformat](https://github.com/nicklockwood/SwiftFormat) - SwiftFormat is a code library and command-line tool for reformatting `swift` code on macOS or Linux. - [swiftformat](https://github.com/nicklockwood/SwiftFormat) - SwiftFormat is a code library and command-line tool for reformatting `swift` code on macOS or Linux.
- [swiftlint](https://github.com/realm/SwiftLint) - A tool to enforce Swift style and conventions.
- [taplo](https://github.com/tamasfe/taplo) - A TOML toolkit written in Rust. - [taplo](https://github.com/tamasfe/taplo) - A TOML toolkit written in Rust.
- [templ](https://templ.guide/commands-and-tools/cli/#formatting-templ-files) - Formats templ template files. - [templ](https://templ.guide/commands-and-tools/cli/#formatting-templ-files) - Formats templ template files.
- [terraform_fmt](https://www.terraform.io/docs/cli/commands/fmt.html) - The terraform-fmt command rewrites `terraform` configuration files to a canonical format and style. - [terraform_fmt](https://www.terraform.io/docs/cli/commands/fmt.html) - The terraform-fmt command rewrites `terraform` configuration files to a canonical format and style.
- [terragrunt_hclfmt](https://terragrunt.gruntwork.io/docs/reference/cli-options/#hclfmt) - Format hcl files into a canonical format. - [terragrunt_hclfmt](https://terragrunt.gruntwork.io/docs/reference/cli-options/#hclfmt) - Format hcl files into a canonical format.
- [tlint](https://github.com/tighten/tlint) - Tighten linter for Laravel conventions with support for auto-formatting. - [tlint](https://github.com/tighten/tlint) - Tighten linter for Laravel conventions with support for auto-formatting.
- [tofu_fmt](https://opentofu.org/docs/cli/commands/fmt/) - The tofu-fmt command rewrites OpenTofu configuration files to a canonical format and style. - [tofu_fmt](https://opentofu.org/docs/cli/commands/fmt/) - The tofu-fmt command rewrites OpenTofu configuration files to a canonical format and style.
- [trim_newlines](https://www.gnu.org/software/gawk/manual/gawk.html) - Trim new lines with awk. - [trim_newlines](https://github.com/stevearc/conform.nvim/blob/master/lua/conform/formatters/trim_whitespace.lua) - Trim empty lines at the end of the file.
- [trim_whitespace](https://www.gnu.org/software/gawk/manual/gawk.html) - Trim whitespaces with awk. - [trim_whitespace](https://github.com/stevearc/conform.nvim/blob/master/lua/conform/formatters/trim_whitespace.lua) - Trim trailing whitespace.
- [twig-cs-fixer](https://github.com/VincentLanglet/Twig-CS-Fixer) - Automatically fix Twig Coding Standards issues - [twig-cs-fixer](https://github.com/VincentLanglet/Twig-CS-Fixer) - Automatically fix Twig Coding Standards issues
- [typos](https://github.com/crate-ci/typos) - Source code spell checker - [typos](https://github.com/crate-ci/typos) - Source code spell checker
- [typstyle](https://github.com/Enter-tainer/typstyle) - Beautiful and reliable typst code formatter. - [typstyle](https://github.com/Enter-tainer/typstyle) - Beautiful and reliable typst code formatter.
@ -419,6 +434,8 @@ require("conform").formatters.shfmt = {
- [Command to toggle format-on-save](doc/recipes.md#command-to-toggle-format-on-save) - [Command to toggle format-on-save](doc/recipes.md#command-to-toggle-format-on-save)
- [Automatically run slow formatters async](doc/recipes.md#automatically-run-slow-formatters-async) - [Automatically run slow formatters async](doc/recipes.md#automatically-run-slow-formatters-async)
- [Lazy loading with lazy.nvim](doc/recipes.md#lazy-loading-with-lazynvim) - [Lazy loading with lazy.nvim](doc/recipes.md#lazy-loading-with-lazynvim)
- [Leave visual mode after range format](doc/recipes.md#leave-visual-mode-after-range-format)
- [Run the first available formatter followed by more formatters](doc/recipes.md#run-the-first-available-formatter-followed-by-more-formatters)
<!-- /RECIPES --> <!-- /RECIPES -->
@ -445,8 +462,8 @@ require("conform").setup({
lua = { "stylua" }, lua = { "stylua" },
-- Conform will run multiple formatters sequentially -- Conform will run multiple formatters sequentially
go = { "goimports", "gofmt" }, go = { "goimports", "gofmt" },
-- Use a sub-list to run only the first available formatter -- You can also customize some of the format options for the filetype
javascript = { { "prettierd", "prettier" } }, rust = { "rustfmt", lsp_format = "fallback" },
-- You can use a function here to determine the formatters dynamically -- You can use a function here to determine the formatters dynamically
python = function(bufnr) python = function(bufnr)
if require("conform").get_formatter_info("ruff_format", bufnr).available then if require("conform").get_formatter_info("ruff_format", bufnr).available then
@ -461,6 +478,11 @@ require("conform").setup({
-- have other formatters configured. -- have other formatters configured.
["_"] = { "trim_whitespace" }, ["_"] = { "trim_whitespace" },
}, },
-- Set this to change the default values when calling conform.format()
-- This will also affect the default values for format_on_save/format_after_save
default_format_opts = {
lsp_format = "fallback",
},
-- If this is set, Conform will run the formatter on save. -- If this is set, Conform will run the formatter on save.
-- It will pass the table to conform.format(). -- It will pass the table to conform.format().
-- This can also be a function that returns the table. -- This can also be a function that returns the table.
@ -479,6 +501,8 @@ require("conform").setup({
log_level = vim.log.levels.ERROR, log_level = vim.log.levels.ERROR,
-- Conform will notify you when a formatter errors -- Conform will notify you when a formatter errors
notify_on_error = true, notify_on_error = true,
-- Conform will notify you when no formatters are available for the buffer
notify_no_formatters = true,
-- Custom formatters and overrides for built-in formatters -- Custom formatters and overrides for built-in formatters
formatters = { formatters = {
my_formatter = { my_formatter = {
@ -515,7 +539,6 @@ require("conform").setup({
-- Set to false to disable merging the config with the base definition -- Set to false to disable merging the config with the base definition
inherit = true, inherit = true,
-- When inherit = true, add these additional arguments to the beginning of the command. -- When inherit = true, add these additional arguments to the beginning of the command.
-- When inherit = true, add these additional arguments to the command.
-- This can also be a function, like args -- This can also be a function, like args
prepend_args = { "--use-tabs" }, prepend_args = { "--use-tabs" },
-- When inherit = true, add these additional arguments to the end of the command. -- When inherit = true, add these additional arguments to the end of the command.
@ -564,9 +587,11 @@ require("conform").formatters.my_formatter = {
| opts | `nil\|conform.setupOpts` | | | | opts | `nil\|conform.setupOpts` | | |
| | formatters_by_ft | `nil\|table<string, conform.FiletypeFormatter>` | Map of filetype to formatters | | | formatters_by_ft | `nil\|table<string, conform.FiletypeFormatter>` | Map of filetype to formatters |
| | format_on_save | `nil\|conform.FormatOpts\|fun(bufnr: integer): nil\|conform.FormatOpts` | If this is set, Conform will run the formatter on save. It will pass the table to conform.format(). This can also be a function that returns the table. | | | format_on_save | `nil\|conform.FormatOpts\|fun(bufnr: integer): nil\|conform.FormatOpts` | If this is set, Conform will run the formatter on save. It will pass the table to conform.format(). This can also be a function that returns the table. |
| | default_format_opts | `nil\|conform.DefaultFormatOpts` | The default options to use when calling conform.format() |
| | format_after_save | `nil\|conform.FormatOpts\|fun(bufnr: integer): nil\|conform.FormatOpts` | If this is set, Conform will run the formatter asynchronously after save. It will pass the table to conform.format(). This can also be a function that returns the table. | | | format_after_save | `nil\|conform.FormatOpts\|fun(bufnr: integer): nil\|conform.FormatOpts` | If this is set, Conform will run the formatter asynchronously after save. It will pass the table to conform.format(). This can also be a function that returns the table. |
| | log_level | `nil\|integer` | Set the log level (e.g. `vim.log.levels.DEBUG`). Use `:ConformInfo` to see the location of the log file. | | | log_level | `nil\|integer` | Set the log level (e.g. `vim.log.levels.DEBUG`). Use `:ConformInfo` to see the location of the log file. |
| | notify_on_error | `nil\|boolean` | Conform will notify you when a formatter errors (default true). | | | notify_on_error | `nil\|boolean` | Conform will notify you when a formatter errors (default true). |
| | notify_no_formatters | `nil\|boolean` | Conform will notify you when no formatters are available for the buffer (default true). |
| | formatters | `nil\|table<string, conform.FormatterConfigOverride\|fun(bufnr: integer): nil\|conform.FormatterConfigOverride>` | Custom formatters and overrides for built-in formatters. | | | formatters | `nil\|table<string, conform.FormatterConfigOverride\|fun(bufnr: integer): nil\|conform.FormatterConfigOverride>` | Custom formatters and overrides for built-in formatters. |
### format(opts, callback) ### format(opts, callback)
@ -574,21 +599,28 @@ require("conform").formatters.my_formatter = {
`format(opts, callback): boolean` \ `format(opts, callback): boolean` \
Format a buffer Format a buffer
| Param | Type | Desc | | | Param | Type | Desc | |
| -------- | ---------------------------------------------------- | ----------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | -------- | ---------------------------------------------------- | ------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| opts | `nil\|conform.FormatOpts` | | | | opts | `nil\|conform.FormatOpts` | | |
| | timeout_ms | `nil\|integer` | Time in milliseconds to block for formatting. Defaults to 1000. No effect if async = true. | | | timeout_ms | `nil\|integer` | Time in milliseconds to block for formatting. Defaults to 1000. No effect if async = true. |
| | bufnr | `nil\|integer` | Format this buffer (default 0) | | | bufnr | `nil\|integer` | Format this buffer (default 0) |
| | async | `nil\|boolean` | If true the method won't block. Defaults to false. If the buffer is modified before the formatter completes, the formatting will be discarded. | | | async | `nil\|boolean` | If true the method won't block. Defaults to false. If the buffer is modified before the formatter completes, the formatting will be discarded. |
| | dry_run | `nil\|boolean` | If true don't apply formatting changes to the buffer | | | dry_run | `nil\|boolean` | If true don't apply formatting changes to the buffer |
| | formatters | `nil\|string[]` | List of formatters to run. Defaults to all formatters for the buffer filetype. | | | undojoin | `nil\|boolean` | Use undojoin to merge formatting changes with previous edit (default false) |
| | lsp_format | `nil\|"never"\|"fallback"\|"prefer"\|"first"\|"last"` | "fallback" LSP formatting when no other formatters are available, "prefer" only LSP formatting when available, "first" LSP formatting then other formatters, "last" other formatters then LSP. | | | formatters | `nil\|string[]` | List of formatters to run. Defaults to all formatters for the buffer filetype. |
| | quiet | `nil\|boolean` | Don't show any notifications for warnings or failures. Defaults to false. | | | lsp_format | `nil\|conform.LspFormatOpts` | Configure if and when LSP should be used for formatting. Defaults to "never". |
| | range | `nil\|table` | Range to format. Table must contain `start` and `end` keys with {row, col} tuples using (1,0) indexing. Defaults to current selection in visual mode | | | | > `"never"` | never use the LSP for formatting (default) |
| | id | `nil\|integer` | Passed to vim.lsp.buf.format when using LSP formatting | | | | > `"fallback"` | LSP formatting is used when no other formatters are available |
| | name | `nil\|string` | Passed to vim.lsp.buf.format when using LSP formatting | | | | > `"prefer"` | use only LSP formatting when available |
| | filter | `nil\|fun(client: table): boolean` | Passed to vim.lsp.buf.format when using LSP formatting | | | | > `"first"` | LSP formatting is used when available and then other formatters |
| callback | `nil\|fun(err: nil\|string, did_edit: nil\|boolean)` | Called once formatting has completed | | | | | > `"last"` | other formatters are used then LSP formatting when available |
| | stop_after_first | `nil\|boolean` | Only run the first available formatter in the list. Defaults to false. |
| | quiet | `nil\|boolean` | Don't show any notifications for warnings or failures. Defaults to false. |
| | range | `nil\|conform.Range` | Range to format. Table must contain `start` and `end` keys with {row, col} tuples using (1,0) indexing. Defaults to current selection in visual mode |
| | id | `nil\|integer` | Passed to vim.lsp.buf.format when using LSP formatting |
| | name | `nil\|string` | Passed to vim.lsp.buf.format when using LSP formatting |
| | filter | `nil\|fun(client: table): boolean` | Passed to vim.lsp.buf.format when using LSP formatting |
| callback | `nil\|fun(err: nil\|string, did_edit: nil\|boolean)` | Called once formatting has completed | |
Returns: Returns:
@ -605,6 +637,27 @@ Retrieve the available formatters for a buffer
| ----- | -------------- | ---- | | ----- | -------------- | ---- |
| bufnr | `nil\|integer` | | | bufnr | `nil\|integer` | |
### list_formatters_to_run(bufnr)
`list_formatters_to_run(bufnr): conform.FormatterInfo[], boolean` \
Get the exact formatters that will be run for a buffer.
| Param | Type | Desc |
| ----- | -------------- | ---- |
| bufnr | `nil\|integer` | |
Returns:
| Type | Desc |
| ----------------------- | -------------------------- |
| conform.FormatterInfo[] | |
| boolean | lsp Will use LSP formatter |
**Note:**
<pre>
This accounts for stop_after_first, lsp fallback logic, etc.
</pre>
### list_all_formatters() ### list_all_formatters()
`list_all_formatters(): conform.FormatterInfo[]` \ `list_all_formatters(): conform.FormatterInfo[]` \
@ -620,15 +673,6 @@ Get information about a formatter (including availability)
| --------- | -------------- | ------------------------- | | --------- | -------------- | ------------------------- |
| formatter | `string` | The name of the formatter | | formatter | `string` | The name of the formatter |
| bufnr | `nil\|integer` | | | bufnr | `nil\|integer` | |
### will_fallback_lsp(options)
`will_fallback_lsp(options): boolean` \
Check if the buffer will use LSP formatting when lsp_format = "fallback"
| Param | Type | Desc |
| ------- | ------------ | ------------------------------------ |
| options | `nil\|table` | Options passed to vim.lsp.buf.format |
<!-- /API --> <!-- /API -->
## Acknowledgements ## Acknowledgements

View File

@ -17,8 +17,8 @@ OPTIONS *conform-option
lua = { "stylua" }, lua = { "stylua" },
-- Conform will run multiple formatters sequentially -- Conform will run multiple formatters sequentially
go = { "goimports", "gofmt" }, go = { "goimports", "gofmt" },
-- Use a sub-list to run only the first available formatter -- You can also customize some of the format options for the filetype
javascript = { { "prettierd", "prettier" } }, rust = { "rustfmt", lsp_format = "fallback" },
-- You can use a function here to determine the formatters dynamically -- You can use a function here to determine the formatters dynamically
python = function(bufnr) python = function(bufnr)
if require("conform").get_formatter_info("ruff_format", bufnr).available then if require("conform").get_formatter_info("ruff_format", bufnr).available then
@ -33,6 +33,11 @@ OPTIONS *conform-option
-- have other formatters configured. -- have other formatters configured.
["_"] = { "trim_whitespace" }, ["_"] = { "trim_whitespace" },
}, },
-- Set this to change the default values when calling conform.format()
-- This will also affect the default values for format_on_save/format_after_save
default_format_opts = {
lsp_format = "fallback",
},
-- If this is set, Conform will run the formatter on save. -- If this is set, Conform will run the formatter on save.
-- It will pass the table to conform.format(). -- It will pass the table to conform.format().
-- This can also be a function that returns the table. -- This can also be a function that returns the table.
@ -51,6 +56,8 @@ OPTIONS *conform-option
log_level = vim.log.levels.ERROR, log_level = vim.log.levels.ERROR,
-- Conform will notify you when a formatter errors -- Conform will notify you when a formatter errors
notify_on_error = true, notify_on_error = true,
-- Conform will notify you when no formatters are available for the buffer
notify_no_formatters = true,
-- Custom formatters and overrides for built-in formatters -- Custom formatters and overrides for built-in formatters
formatters = { formatters = {
my_formatter = { my_formatter = {
@ -87,7 +94,6 @@ OPTIONS *conform-option
-- Set to false to disable merging the config with the base definition -- Set to false to disable merging the config with the base definition
inherit = true, inherit = true,
-- When inherit = true, add these additional arguments to the beginning of the command. -- When inherit = true, add these additional arguments to the beginning of the command.
-- When inherit = true, add these additional arguments to the command.
-- This can also be a function, like args -- This can also be a function, like args
prepend_args = { "--use-tabs" }, prepend_args = { "--use-tabs" },
-- When inherit = true, add these additional arguments to the end of the command. -- When inherit = true, add these additional arguments to the end of the command.
@ -119,12 +125,32 @@ setup({opts}) *conform.setu
{opts} `nil|conform.setupOpts` {opts} `nil|conform.setupOpts`
{formatters_by_ft} `nil|table<string, conform.FiletypeFormatter>` Map {formatters_by_ft} `nil|table<string, conform.FiletypeFormatter>` Map
of filetype to formatters of filetype to formatters
{format_on_save} `nil|conform.FormatOpts|fun(bufnr: integer): nil|conform.FormatOpts` I {format_on_save} `nil|conform.FormatOpts|fun(bufnr: integer): nil|conform.FormatOpts`
f this is set, Conform will run the formatter on If this is set, Conform will run the formatter on
save. It will pass the table to conform.format(). save. It will pass the table to conform.format().
This can also be a function that returns the table. This can also be a function that returns the table.
{format_after_save} `nil|conform.FormatOpts|fun(bufnr: integer): nil|conform.FormatOpts` I {default_format_opts} `nil|conform.DefaultFormatOpts` The default
f this is set, Conform will run the formatter options to use when calling conform.format()
{timeout_ms} `nil|integer` Time in milliseconds to block for
formatting. Defaults to 1000. No effect if
async = true.
{lsp_format} `nil|conform.LspFormatOpts` Configure if and
when LSP should be used for formatting.
Defaults to "never".
`"never"` never use the LSP for formatting (default)
`"fallback"` LSP formatting is used when no other formatters
are available
`"prefer"` use only LSP formatting when available
`"first"` LSP formatting is used when available and then
other formatters
`"last"` other formatters are used then LSP formatting
when available
{quiet} `nil|boolean` Don't show any notifications for
warnings or failures. Defaults to false.
{stop_after_first} `nil|boolean` Only run the first available
formatter in the list. Defaults to false.
{format_after_save} `nil|conform.FormatOpts|fun(bufnr: integer): nil|conform.FormatOpts`
If this is set, Conform will run the formatter
asynchronously after save. It will pass the table asynchronously after save. It will pass the table
to conform.format(). This can also be a function to conform.format(). This can also be a function
that returns the table. that returns the table.
@ -133,8 +159,11 @@ setup({opts}) *conform.setu
the location of the log file. the location of the log file.
{notify_on_error} `nil|boolean` Conform will notify you when a {notify_on_error} `nil|boolean` Conform will notify you when a
formatter errors (default true). formatter errors (default true).
{formatters} `nil|table<string, conform.FormatterConfigOverride|fun(bufnr: integer): nil|conform.FormatterConfigOverride>` C {notify_no_formatters} `nil|boolean` Conform will notify you when no
ustom formatters and overrides for built-in formatters are available for the buffer (default
true).
{formatters} `nil|table<string, conform.FormatterConfigOverride|fun(bufnr: integer): nil|conform.FormatterConfigOverride>`
Custom formatters and overrides for built-in
formatters. formatters.
format({opts}, {callback}): boolean *conform.format* format({opts}, {callback}): boolean *conform.format*
@ -142,32 +171,47 @@ format({opts}, {callback}): boolean *conform.forma
Parameters: Parameters:
{opts} `nil|conform.FormatOpts` {opts} `nil|conform.FormatOpts`
{timeout_ms} `nil|integer` Time in milliseconds to block for {timeout_ms} `nil|integer` Time in milliseconds to block for
formatting. Defaults to 1000. No effect if async = true. formatting. Defaults to 1000. No effect if async =
{bufnr} `nil|integer` Format this buffer (default 0) true.
{async} `nil|boolean` If true the method won't block. Defaults to {bufnr} `nil|integer` Format this buffer (default 0)
false. If the buffer is modified before the formatter {async} `nil|boolean` If true the method won't block.
completes, the formatting will be discarded. Defaults to false. If the buffer is modified before
{dry_run} `nil|boolean` If true don't apply formatting changes to the formatter completes, the formatting will be
the buffer discarded.
{formatters} `nil|string[]` List of formatters to run. Defaults to all {dry_run} `nil|boolean` If true don't apply formatting
formatters for the buffer filetype. changes to the buffer
{lsp_format} `nil|"never"|"fallback"|"prefer"|"first"|"last"` "fallbac {undojoin} `nil|boolean` Use undojoin to merge formatting
k" LSP formatting when no other formatters are available, changes with previous edit (default false)
"prefer" only LSP formatting when available, "first" LSP {formatters} `nil|string[]` List of formatters to run. Defaults
formatting then other formatters, "last" other formatters to all formatters for the buffer filetype.
then LSP. {lsp_format} `nil|conform.LspFormatOpts` Configure if and when
{quiet} `nil|boolean` Don't show any notifications for warnings LSP should be used for formatting. Defaults to
or failures. Defaults to false. "never".
{range} `nil|table` Range to format. Table must contain `start` `"never"` never use the LSP for formatting (default)
and `end` keys with {row, col} tuples using (1,0) `"fallback"` LSP formatting is used when no other formatters are
indexing. Defaults to current selection in visual mode available
{id} `nil|integer` Passed to |vim.lsp.buf.format| when using `"prefer"` use only LSP formatting when available
LSP formatting `"first"` LSP formatting is used when available and then other
{name} `nil|string` Passed to |vim.lsp.buf.format| when using formatters
LSP formatting `"last"` other formatters are used then LSP formatting when
{filter} `nil|fun(client: table): boolean` Passed to available
|vim.lsp.buf.format| when using LSP formatting {stop_after_first} `nil|boolean` Only run the first available
formatter in the list. Defaults to false.
{quiet} `nil|boolean` Don't show any notifications for
warnings or failures. Defaults to false.
{range} `nil|conform.Range` Range to format. Table must
contain `start` and `end` keys with {row, col}
tuples using (1,0) indexing. Defaults to current
selection in visual mode
{start} `integer[]`
{end} `integer[]`
{id} `nil|integer` Passed to |vim.lsp.buf.format| when
using LSP formatting
{name} `nil|string` Passed to |vim.lsp.buf.format| when
using LSP formatting
{filter} `nil|fun(client: table): boolean` Passed to |vim.ls
p.buf.format| when using LSP formatting
{callback} `nil|fun(err: nil|string, did_edit: nil|boolean)` Called once {callback} `nil|fun(err: nil|string, did_edit: nil|boolean)` Called once
formatting has completed formatting has completed
Returns: Returns:
@ -179,6 +223,18 @@ list_formatters({bufnr}): conform.FormatterInfo[] *conform.list_formatter
Parameters: Parameters:
{bufnr} `nil|integer` {bufnr} `nil|integer`
list_formatters_to_run({bufnr}): conform.FormatterInfo[], boolean *conform.list_formatters_to_run*
Get the exact formatters that will be run for a buffer.
Parameters:
{bufnr} `nil|integer`
Returns:
`conform.FormatterInfo[]`
`boolean` lsp Will use LSP formatter
Note:
This accounts for stop_after_first, lsp fallback logic, etc.
list_all_formatters(): conform.FormatterInfo[] *conform.list_all_formatters* list_all_formatters(): conform.FormatterInfo[] *conform.list_all_formatters*
List information about all filetype-configured formatters List information about all filetype-configured formatters
@ -190,12 +246,6 @@ get_formatter_info({formatter}, {bufnr}): conform.FormatterInfo *conform.get_for
{formatter} `string` The name of the formatter {formatter} `string` The name of the formatter
{bufnr} `nil|integer` {bufnr} `nil|integer`
will_fallback_lsp({options}): boolean *conform.will_fallback_lsp*
Check if the buffer will use LSP formatting when lsp_format = "fallback"
Parameters:
{options} `nil|table` Options passed to |vim.lsp.buf.format|
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
FORMATTERS *conform-formatters* FORMATTERS *conform-formatters*
@ -229,16 +279,19 @@ FORMATTERS *conform-formatter
respects readability. respects readability.
`blue` - The slightly less uncompromising Python code formatter. `blue` - The slightly less uncompromising Python code formatter.
`bpfmt` - Android Blueprint file formatter. `bpfmt` - Android Blueprint file formatter.
`bsfmt` - A code formatter for BrighterScript (and BrightScript).
`buf` - A new way of working with Protocol Buffers. `buf` - A new way of working with Protocol Buffers.
`buildifier` - buildifier is a tool for formatting bazel BUILD and .bzl files `buildifier` - buildifier is a tool for formatting bazel BUILD and .bzl files
with a standard convention. with a standard convention.
`cabal_fmt` - Format cabal files with cabal-fmt `cabal_fmt` - Format cabal files with cabal-fmt
`caramel_fmt` - Format Caramel code.
`cbfmt` - A tool to format codeblocks inside markdown and org documents. `cbfmt` - A tool to format codeblocks inside markdown and org documents.
`clang-format` - Tool to format C/C++/… code according to a set of rules and `clang-format` - Tool to format C/C++/… code according to a set of rules and
heuristics. heuristics.
`cljstyle` - Formatter for Clojure code. `cljstyle` - Formatter for Clojure code.
`cmake_format` - Parse cmake listfiles and format them nicely. `cmake_format` - Parse cmake listfiles and format them nicely.
`codespell` - Check code for common misspellings. `codespell` - Check code for common misspellings.
`crlfmt` - Formatter for CockroachDB's additions to the Go style guide.
`crystal` - Format Crystal code. `crystal` - Format Crystal code.
`csharpier` - The opinionated C# code formatter. `csharpier` - The opinionated C# code formatter.
`cue_fmt` - Format CUE files using `cue fmt` command. `cue_fmt` - Format CUE files using `cue fmt` command.
@ -246,12 +299,19 @@ FORMATTERS *conform-formatter
`darker` - Run black only on changed lines. `darker` - Run black only on changed lines.
`dart_format` - Replace the whitespace in your program with formatting that `dart_format` - Replace the whitespace in your program with formatting that
follows Dart guidelines. follows Dart guidelines.
`dcm_fix` - Fixes issues produced by dcm analyze, dcm check-unused-code or dcm
check-dependencies commands.
`dcm_format` - Formats .dart files.
`deno_fmt` - Use [Deno](https://deno.land/) to format TypeScript, `deno_fmt` - Use [Deno](https://deno.land/) to format TypeScript,
JavaScript/JSON and markdown. JavaScript/JSON and markdown.
`dfmt` - Formatter for D source code. `dfmt` - Formatter for D source code.
`djlint` - ✨ HTML Template Linter and Formatter. Django - Jinja - Nunjucks - `djlint` - ✨ HTML Template Linter and Formatter. Django - Jinja - Nunjucks -
Handlebars - GoLang. Handlebars - GoLang.
`docformatter` - docformatter automatically formats docstrings to follow a
subset of the PEP 257 conventions.
`docstrfmt` - reStructuredText formatter. `docstrfmt` - reStructuredText formatter.
`doctoc` - Generates table of contents for markdown files inside local git
repository.
`dprint` - Pluggable and configurable code formatting platform written in Rust. `dprint` - Pluggable and configurable code formatting platform written in Rust.
`easy-coding-standard` - ecs - Use Coding Standard with 0-knowledge of PHP-CS- `easy-coding-standard` - ecs - Use Coding Standard with 0-knowledge of PHP-CS-
Fixer and PHP_CodeSniffer. Fixer and PHP_CodeSniffer.
@ -278,6 +338,7 @@ FORMATTERS *conform-formatter
`gdformat` - A formatter for Godot's gdscript. `gdformat` - A formatter for Godot's gdscript.
`gersemi` - A formatter to make your CMake code the real treasure. `gersemi` - A formatter to make your CMake code the real treasure.
`gleam` - ⭐️ A friendly language for building type-safe, scalable systems! `gleam` - ⭐️ A friendly language for building type-safe, scalable systems!
`gluon_fmt` - Code formatting for the gluon programming language.
`gn` - gn build system. `gn` - gn build system.
`gofmt` - Formats go programs. `gofmt` - Formats go programs.
`gofumpt` - Enforce a stricter format than gofmt, while being backwards `gofumpt` - Enforce a stricter format than gofmt, while being backwards
@ -290,10 +351,12 @@ FORMATTERS *conform-formatter
`golines` - A golang formatter that fixes long lines. `golines` - A golang formatter that fixes long lines.
`google-java-format` - Reformats Java source code according to Google Java `google-java-format` - Reformats Java source code according to Google Java
Style. Style.
`grain_format` - Code formatter for the grain programming language.
`hcl` - A formatter for HCL files. `hcl` - A formatter for HCL files.
`hindent` - Haskell pretty printer. `hindent` - Haskell pretty printer.
`htmlbeautifier` - A normaliser/beautifier for HTML that also understands `htmlbeautifier` - A normaliser/beautifier for HTML that also understands
embedded Ruby. Ideal for tidying up Rails templates. embedded Ruby. Ideal for tidying up Rails templates.
`imba_fmt` - Code formatter for the Imba programming language.
`indent` - GNU Indent. `indent` - GNU Indent.
`injected` - Format treesitter injected languages. `injected` - Format treesitter injected languages.
`inko` - A language for building concurrent software with confidence `inko` - A language for building concurrent software with confidence
@ -325,6 +388,7 @@ FORMATTERS *conform-formatter
`mdslw` - Prepare your markdown for easy diff'ing by adding line breaks after `mdslw` - Prepare your markdown for easy diff'ing by adding line breaks after
every sentence. every sentence.
`mix` - Format Elixir files using the mix format command. `mix` - Format Elixir files using the mix format command.
`nickel` - Code formatter for the Nickel programming language.
`nimpretty` - nimpretty is a Nim source code beautifier that follows the `nimpretty` - nimpretty is a Nim source code beautifier that follows the
official style guide. official style guide.
`nixfmt` - nixfmt is a formatter for Nix code, intended to apply a uniform `nixfmt` - nixfmt is a formatter for Nix code, intended to apply a uniform
@ -377,6 +441,7 @@ FORMATTERS *conform-formatter
`shellcheck` - A static analysis tool for shell scripts. `shellcheck` - A static analysis tool for shell scripts.
`shellharden` - The corrective bash syntax highlighter. `shellharden` - The corrective bash syntax highlighter.
`shfmt` - A shell parser, formatter, and interpreter with `bash` support. `shfmt` - A shell parser, formatter, and interpreter with `bash` support.
`sleek` - Sleek is a CLI tool for formatting SQL.
`smlfmt` - A custom parser and code formatter for Standard ML. `smlfmt` - A custom parser and code formatter for Standard ML.
`snakefmt` - a formatting tool for Snakemake files following the design of `snakefmt` - a formatting tool for Snakemake files following the design of
Black. Black.
@ -398,6 +463,7 @@ FORMATTERS *conform-formatter
`swift build`. `swift build`.
`swiftformat` - SwiftFormat is a code library and command-line tool for `swiftformat` - SwiftFormat is a code library and command-line tool for
reformatting `swift` code on macOS or Linux. reformatting `swift` code on macOS or Linux.
`swiftlint` - A tool to enforce Swift style and conventions.
`taplo` - A TOML toolkit written in Rust. `taplo` - A TOML toolkit written in Rust.
`templ` - Formats templ template files. `templ` - Formats templ template files.
`terraform_fmt` - The terraform-fmt command rewrites `terraform` configuration `terraform_fmt` - The terraform-fmt command rewrites `terraform` configuration
@ -407,8 +473,8 @@ FORMATTERS *conform-formatter
formatting. formatting.
`tofu_fmt` - The tofu-fmt command rewrites OpenTofu configuration files to a `tofu_fmt` - The tofu-fmt command rewrites OpenTofu configuration files to a
canonical format and style. canonical format and style.
`trim_newlines` - Trim new lines with awk. `trim_newlines` - Trim empty lines at the end of the file.
`trim_whitespace` - Trim whitespaces with awk. `trim_whitespace` - Trim trailing whitespace.
`twig-cs-fixer` - Automatically fix Twig Coding Standards issues `twig-cs-fixer` - Automatically fix Twig Coding Standards issues
`typos` - Source code spell checker `typos` - Source code spell checker
`typstyle` - Beautiful and reliable typst code formatter. `typstyle` - Beautiful and reliable typst code formatter.

View File

@ -7,6 +7,8 @@
- [Command to toggle format-on-save](#command-to-toggle-format-on-save) - [Command to toggle format-on-save](#command-to-toggle-format-on-save)
- [Automatically run slow formatters async](#automatically-run-slow-formatters-async) - [Automatically run slow formatters async](#automatically-run-slow-formatters-async)
- [Lazy loading with lazy.nvim](#lazy-loading-with-lazynvim) - [Lazy loading with lazy.nvim](#lazy-loading-with-lazynvim)
- [Leave visual mode after range format](#leave-visual-mode-after-range-format)
- [Run the first available formatter followed by more formatters](#run-the-first-available-formatter-followed-by-more-formatters)
<!-- /TOC --> <!-- /TOC -->
@ -149,22 +151,28 @@ return {
-- Customize or remove this keymap to your liking -- Customize or remove this keymap to your liking
"<leader>f", "<leader>f",
function() function()
require("conform").format({ async = true, lsp_format = "fallback" }) require("conform").format({ async = true })
end, end,
mode = "", mode = "",
desc = "Format buffer", desc = "Format buffer",
}, },
}, },
-- Everything in opts will be passed to setup() -- This will provide type hinting with LuaLS
---@module "conform"
---@type conform.setupOpts
opts = { opts = {
-- Define your formatters -- Define your formatters
formatters_by_ft = { formatters_by_ft = {
lua = { "stylua" }, lua = { "stylua" },
python = { "isort", "black" }, python = { "isort", "black" },
javascript = { { "prettierd", "prettier" } }, javascript = { "prettierd", "prettier", stop_after_first = true },
},
-- Set default options
default_format_opts = {
lsp_format = "fallback",
}, },
-- Set up format-on-save -- Set up format-on-save
format_on_save = { timeout_ms = 500, lsp_format = "fallback" }, format_on_save = { timeout_ms = 500 },
-- Customize formatters -- Customize formatters
formatters = { formatters = {
shfmt = { shfmt = {
@ -178,3 +186,51 @@ return {
end, end,
} }
``` ```
## Leave visual mode after range format
If you call `conform.format` when in visual mode, conform will perform a range format on the selected region. If you want it to leave visual mode afterwards (similar to the default `gw` or `gq` behavior), use this mapping:
```lua
vim.keymap.set("", "<leader>f", function()
require("conform").format({ async = true }, function(err)
if not err then
local mode = vim.api.nvim_get_mode().mode
if vim.startswith(string.lower(mode), "v") then
vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes("<Esc>", true, false, true), "n", true)
end
end
end)
end, { desc = "Format code" })
```
## Run the first available formatter followed by more formatters
With the refactor in [#491](https://github.com/stevearc/conform.nvim/pull/491) it is now easy to
just run the first available formatter in a list, but more difficult to do that _and then_ run
another formatter. For example, "format first with either `prettierd` or `prettier`, _then_ use the
`injected` formatter". Here is how you can easily do that:
```lua
---@param bufnr integer
---@param ... string
---@return string
local function first(bufnr, ...)
local conform = require("conform")
for i = 1, select("#", ...) do
local formatter = select(i, ...)
if conform.get_formatter_info(formatter, bufnr).available then
return formatter
end
end
return select(1, ...)
end
require("conform").setup({
formatters_by_ft = {
markdown = function(bufnr)
return { first(bufnr, "prettierd", "prettier"), "injected" }
end,
},
})
```

View File

@ -8,7 +8,7 @@ conform.format conform.txt /*conform.format*
conform.get_formatter_info conform.txt /*conform.get_formatter_info* conform.get_formatter_info conform.txt /*conform.get_formatter_info*
conform.list_all_formatters conform.txt /*conform.list_all_formatters* conform.list_all_formatters conform.txt /*conform.list_all_formatters*
conform.list_formatters conform.txt /*conform.list_formatters* conform.list_formatters conform.txt /*conform.list_formatters*
conform.list_formatters_to_run conform.txt /*conform.list_formatters_to_run*
conform.nvim conform.txt /*conform.nvim* conform.nvim conform.txt /*conform.nvim*
conform.setup conform.txt /*conform.setup* conform.setup conform.txt /*conform.setup*
conform.txt conform.txt /*conform.txt* conform.txt conform.txt /*conform.txt*
conform.will_fallback_lsp conform.txt /*conform.will_fallback_lsp*

View File

@ -7,7 +7,7 @@ return {
}, },
command = util.from_node_modules("biome"), command = util.from_node_modules("biome"),
stdin = true, stdin = true,
args = { "check", "--apply", "--stdin-file-path", "$FILENAME" }, args = { "check", "--write", "--stdin-file-path", "$FILENAME" },
cwd = util.root_file({ cwd = util.root_file({
"biome.json", "biome.json",
"biome.jsonc", "biome.jsonc",

View File

@ -6,10 +6,9 @@ return {
description = "✨ HTML Template Linter and Formatter. Django - Jinja - Nunjucks - Handlebars - GoLang.", description = "✨ HTML Template Linter and Formatter. Django - Jinja - Nunjucks - Handlebars - GoLang.",
}, },
command = "djlint", command = "djlint",
args = { args = function(_, ctx)
"--reformat", return { "--reformat", "--indent", ctx.shiftwidth, "-" }
"-", end,
},
cwd = util.root_file({ cwd = util.root_file({
".djlintrc", ".djlintrc",
}), }),

View File

@ -136,12 +136,6 @@ return {
-- (defaults to the value from formatters_by_ft) -- (defaults to the value from formatters_by_ft)
lang_to_formatters = {}, lang_to_formatters = {},
}, },
condition = function(self, ctx)
local ok, parser = pcall(vim.treesitter.get_parser, ctx.buf)
-- Require Neovim 0.9 because the treesitter API has changed significantly
---@diagnostic disable-next-line: invisible
return ok and parser._injection_query and vim.fn.has("nvim-0.9") == 1
end,
format = function(self, ctx, lines, callback) format = function(self, ctx, lines, callback)
local conform = require("conform") local conform = require("conform")
local errors = require("conform.errors") local errors = require("conform.errors")
@ -284,13 +278,21 @@ return {
---@type string[] ---@type string[]
local formatter_names local formatter_names
if type(ft_formatters) == "function" then if type(ft_formatters) == "function" then
formatter_names = ft_formatters(ctx.buf) ft_formatters = ft_formatters(ctx.buf)
else
local formatters = require("conform").resolve_formatters(ft_formatters, ctx.buf, false)
formatter_names = vim.tbl_map(function(f)
return f.name
end, formatters)
end end
local stop_after_first = ft_formatters.stop_after_first
if stop_after_first == nil then
stop_after_first = conform.default_format_opts.stop_after_first
end
if stop_after_first == nil then
stop_after_first = false
end
local formatters =
conform.resolve_formatters(ft_formatters, ctx.buf, false, stop_after_first)
formatter_names = vim.tbl_map(function(f)
return f.name
end, formatters)
local idx = num_format local idx = num_format
log.debug("Injected format %s:%d:%d: %s", lang, start_lnum, end_lnum, formatter_names) log.debug("Injected format %s:%d:%d: %s", lang, start_lnum, end_lnum, formatter_names)
log.trace("Injected format lines %s", input_lines) log.trace("Injected format lines %s", input_lines)

View File

@ -6,10 +6,10 @@ return {
}, },
command = "markdown-toc", command = "markdown-toc",
stdin = false, stdin = false,
args = function(self, ctx) args = function(_, ctx)
-- use the indentation set in the current buffer, effectively allowing us to -- use the indentation set in the current buffer, effectively allowing us to
-- use values from .editorconfig -- use values from .editorconfig
local indent = vim.bo[ctx.buf].expandtab and (" "):rep(vim.bo[ctx.buf].tabstop) or "\t" local indent = vim.bo[ctx.buf].expandtab and (" "):rep(ctx.shiftwidth) or "\t"
return { "--indent=" .. indent, "-i", "$FILENAME" } return { "--indent=" .. indent, "-i", "$FILENAME" }
end, end,
} }

View File

@ -5,5 +5,15 @@ return {
description = "A shell parser, formatter, and interpreter with `bash` support.", description = "A shell parser, formatter, and interpreter with `bash` support.",
}, },
command = "shfmt", command = "shfmt",
args = { "-filename", "$FILENAME" }, args = function(_, ctx)
local args = { "-filename", "$FILENAME" }
local has_editorconfig = vim.fs.find(".editorconfig", { path = ctx.dirname, upward = true })[1]
~= nil
-- If there is an editorconfig, don't pass any args because shfmt will apply settings from there
-- when no command line args are passed.
if not has_editorconfig and vim.bo[ctx.buf].expandtab then
vim.list_extend(args, { "-i", ctx.shiftwidth })
end
return args
end,
} }

View File

@ -1,9 +1,14 @@
---@type conform.FileFormatterConfig ---@type conform.FileLuaFormatterConfig
return { return {
meta = { meta = {
url = "https://www.gnu.org/software/gawk/manual/gawk.html", url = "https://github.com/stevearc/conform.nvim/blob/master/lua/conform/formatters/trim_whitespace.lua",
description = "Trim new lines with awk.", description = "Trim empty lines at the end of the file.",
}, },
command = "awk", format = function(self, ctx, lines, callback)
args = { 'NF{print s $0; s=""; next} {s=s ORS}' }, local out_lines = vim.deepcopy(lines)
while #out_lines > 0 and out_lines[#out_lines] == "" do
table.remove(out_lines)
end
callback(nil, out_lines)
end,
} }

View File

@ -1,9 +1,15 @@
---@type conform.FileFormatterConfig ---@type conform.FileLuaFormatterConfig
return { return {
meta = { meta = {
url = "https://www.gnu.org/software/gawk/manual/gawk.html", url = "https://github.com/stevearc/conform.nvim/blob/master/lua/conform/formatters/trim_whitespace.lua",
description = "Trim whitespaces with awk.", description = "Trim trailing whitespace.",
}, },
command = "awk", format = function(self, ctx, lines, callback)
args = { '{ sub(/[ \t]+$/, ""); print }' }, local out_lines = {}
for _, line in ipairs(lines) do
local trimmed = line:gsub("%s+$", "")
table.insert(out_lines, trimmed)
end
callback(nil, out_lines)
end,
} }

View File

@ -6,7 +6,6 @@ local health_start = vim.health.start or vim.health.report_start
local health_warn = vim.health.warn or vim.health.report_warn local health_warn = vim.health.warn or vim.health.report_warn
local health_info = vim.health.info or vim.health.report_info local health_info = vim.health.info or vim.health.report_info
local health_ok = vim.health.ok or vim.health.report_ok local health_ok = vim.health.ok or vim.health.report_ok
local islist = vim.islist or vim.tbl_islist
---@param name string ---@param name string
---@return string[] ---@return string[]
@ -16,14 +15,6 @@ local function get_formatter_filetypes(name)
for filetype, formatters in pairs(conform.formatters_by_ft) do for filetype, formatters in pairs(conform.formatters_by_ft) do
if type(formatters) == "function" then if type(formatters) == "function" then
formatters = formatters(0) formatters = formatters(0)
-- support the old structure where formatters could be a subkey
elseif not islist(formatters) then
vim.notify_once(
"Using deprecated structure for formatters_by_ft. See :help conform-options for details.",
vim.log.levels.ERROR
)
---@diagnostic disable-next-line: undefined-field
formatters = formatters.formatters
end end
for _, ft_name in ipairs(formatters) do for _, ft_name in ipairs(formatters) do
@ -61,7 +52,7 @@ M.check = function()
end end
end end
---@param formatters conform.FormatterUnit[] ---@param formatters conform.FiletypeFormatterInternal
---@return string[] ---@return string[]
local function flatten_formatters(formatters) local function flatten_formatters(formatters)
local flat = {} local flat = {}

View File

@ -1,5 +1,3 @@
---@diagnostic disable-next-line: deprecated
local islist = vim.islist or vim.tbl_islist
local M = {} local M = {}
---@type table<string, conform.FiletypeFormatter> ---@type table<string, conform.FiletypeFormatter>
@ -9,20 +7,72 @@ M.formatters_by_ft = {}
M.formatters = {} M.formatters = {}
M.notify_on_error = true M.notify_on_error = true
M.notify_no_formatters = true
---@type conform.DefaultFormatOpts
M.default_format_opts = {}
-- Defer notifications because nvim-notify can throw errors if called immediately
-- in some contexts (e.g. inside statusline function)
local notify = vim.schedule_wrap(function(...)
vim.notify(...)
end)
local notify_once = vim.schedule_wrap(function(...)
vim.notify_once(...)
end)
local allowed_default_opts = { "timeout_ms", "lsp_format", "quiet", "stop_after_first" }
local function merge_default_opts(a, b)
for _, key in ipairs(allowed_default_opts) do
if a[key] == nil then
a[key] = b[key]
end
end
return a
end
---@param conf? conform.FiletypeFormatter
local function check_for_default_opts(conf)
if not conf or type(conf) ~= "table" then
return
end
for k in pairs(conf) do
if type(k) == "string" then
notify(
string.format(
'conform.setup: the "_" and "*" keys in formatters_by_ft do not support configuring format options, such as "%s"',
k
),
vim.log.levels.WARN
)
break
end
end
end
---@param opts? conform.setupOpts ---@param opts? conform.setupOpts
M.setup = function(opts) M.setup = function(opts)
if vim.fn.has("nvim-0.9") == 0 then
notify("conform.nvim requires Neovim 0.9+", vim.log.levels.ERROR)
return
end
opts = opts or {} opts = opts or {}
M.formatters = vim.tbl_extend("force", M.formatters, opts.formatters or {}) M.formatters = vim.tbl_extend("force", M.formatters, opts.formatters or {})
M.formatters_by_ft = vim.tbl_extend("force", M.formatters_by_ft, opts.formatters_by_ft or {}) M.formatters_by_ft = vim.tbl_extend("force", M.formatters_by_ft, opts.formatters_by_ft or {})
check_for_default_opts(M.formatters_by_ft["_"])
check_for_default_opts(M.formatters_by_ft["*"])
M.default_format_opts =
vim.tbl_extend("force", M.default_format_opts, opts.default_format_opts or {})
if opts.log_level then if opts.log_level then
require("conform.log").level = opts.log_level require("conform.log").level = opts.log_level
end end
local notify_on_error = opts.notify_on_error if opts.notify_on_error ~= nil then
if notify_on_error ~= nil then M.notify_on_error = opts.notify_on_error
M.notify_on_error = notify_on_error end
if opts.notify_no_formatters ~= nil then
M.notify_no_formatters = opts.notify_no_formatters
end end
local aug = vim.api.nvim_create_augroup("Conform", { clear = true }) local aug = vim.api.nvim_create_augroup("Conform", { clear = true })
@ -44,7 +94,7 @@ M.setup = function(opts)
end end
if format_args then if format_args then
if format_args.async then if format_args.async then
vim.notify_once( notify_once(
"Conform format_on_save cannot use async=true. Use format_after_save instead.", "Conform format_on_save cannot use async=true. Use format_after_save instead.",
vim.log.levels.ERROR vim.log.levels.ERROR
) )
@ -97,7 +147,7 @@ M.setup = function(opts)
exit_timeout = format_args.timeout_ms or exit_timeout exit_timeout = format_args.timeout_ms or exit_timeout
num_running_format_jobs = num_running_format_jobs + 1 num_running_format_jobs = num_running_format_jobs + 1
if format_args.async == false then if format_args.async == false then
vim.notify_once( notify_once(
"Conform format_after_save cannot use async=false. Use format_on_save instead.", "Conform format_after_save cannot use async=false. Use format_on_save instead.",
vim.log.levels.ERROR vim.log.levels.ERROR
) )
@ -174,7 +224,7 @@ end
---Get the configured formatter filetype for a buffer ---Get the configured formatter filetype for a buffer
---@param bufnr? integer ---@param bufnr? integer
---@return nil|string filetype or nil if no formatter is configured ---@return nil|string filetype or nil if no formatter is configured. Can be "_".
local function get_matching_filetype(bufnr) local function get_matching_filetype(bufnr)
if not bufnr or bufnr == 0 then if not bufnr or bufnr == 0 then
bufnr = vim.api.nvim_get_current_buf() bufnr = vim.api.nvim_get_current_buf()
@ -193,7 +243,7 @@ end
---@private ---@private
---@param bufnr? integer ---@param bufnr? integer
---@return conform.FormatterUnit[] ---@return string[]
M.list_formatters_for_buffer = function(bufnr) M.list_formatters_for_buffer = function(bufnr)
if not bufnr or bufnr == 0 then if not bufnr or bufnr == 0 then
bufnr = vim.api.nvim_get_current_buf() bufnr = vim.api.nvim_get_current_buf()
@ -204,6 +254,10 @@ M.list_formatters_for_buffer = function(bufnr)
local function dedupe_formatters(names, collect) local function dedupe_formatters(names, collect)
for _, name in ipairs(names) do for _, name in ipairs(names) do
if type(name) == "table" then if type(name) == "table" then
notify_once(
"deprecated[conform]: The nested {} syntax to run the first formatter has been replaced by the stop_after_first option (see :help conform.format).\nSupport for the old syntax will be dropped on 2025-01-01.",
vim.log.levels.WARN
)
local alternation = {} local alternation = {}
dedupe_formatters(name, alternation) dedupe_formatters(name, alternation)
if not vim.tbl_isempty(alternation) then if not vim.tbl_isempty(alternation) then
@ -228,16 +282,6 @@ M.list_formatters_for_buffer = function(bufnr)
if type(ft_formatters) == "function" then if type(ft_formatters) == "function" then
dedupe_formatters(ft_formatters(bufnr), formatters) dedupe_formatters(ft_formatters(bufnr), formatters)
else else
-- support the old structure where formatters could be a subkey
if not islist(ft_formatters) then
vim.notify_once(
"Using deprecated structure for formatters_by_ft. See :help conform-options for details.",
vim.log.levels.ERROR
)
---@diagnostic disable-next-line: undefined-field
ft_formatters = ft_formatters.formatters
end
dedupe_formatters(ft_formatters, formatters) dedupe_formatters(ft_formatters, formatters)
end end
end end
@ -246,6 +290,25 @@ M.list_formatters_for_buffer = function(bufnr)
return formatters return formatters
end end
---@param bufnr? integer
---@return nil|conform.DefaultFormatOpts
local function get_opts_from_filetype(bufnr)
if not bufnr or bufnr == 0 then
bufnr = vim.api.nvim_get_current_buf()
end
local matching_filetype = get_matching_filetype(bufnr)
if not matching_filetype then
return nil
end
local ft_formatters = M.formatters_by_ft[matching_filetype]
assert(ft_formatters ~= nil, "get_matching_filetype ensures formatters_by_ft has key")
if type(ft_formatters) == "function" then
ft_formatters = ft_formatters(bufnr)
end
return merge_default_opts({}, ft_formatters)
end
---@param bufnr integer ---@param bufnr integer
---@param mode "v"|"V" ---@param mode "v"|"V"
---@return table {start={row,col}, end={row,col}} using (1, 0) indexing ---@return table {start={row,col}, end={row,col}} using (1, 0) indexing
@ -278,17 +341,18 @@ local function range_from_selection(bufnr, mode)
end end
---@private ---@private
---@param names conform.FormatterUnit[] ---@param names conform.FiletypeFormatterInternal
---@param bufnr integer ---@param bufnr integer
---@param warn_on_missing boolean ---@param warn_on_missing boolean
---@param stop_after_first boolean
---@return conform.FormatterInfo[] ---@return conform.FormatterInfo[]
M.resolve_formatters = function(names, bufnr, warn_on_missing) M.resolve_formatters = function(names, bufnr, warn_on_missing, stop_after_first)
local all_info = {} local all_info = {}
local function add_info(info, warn) local function add_info(info, warn)
if info.available then if info.available then
table.insert(all_info, info) table.insert(all_info, info)
elseif warn then elseif warn then
vim.notify( notify(
string.format("Formatter '%s' unavailable: %s", info.name, info.available_msg), string.format("Formatter '%s' unavailable: %s", info.name, info.available_msg),
vim.log.levels.WARN vim.log.levels.WARN
) )
@ -301,6 +365,10 @@ M.resolve_formatters = function(names, bufnr, warn_on_missing)
local info = M.get_formatter_info(name, bufnr) local info = M.get_formatter_info(name, bufnr)
add_info(info, warn_on_missing) add_info(info, warn_on_missing)
else else
notify_once(
"deprecated[conform]: The nested {} syntax to run the first formatter has been replaced by the stop_after_first option (see :help conform.format).\nSupport for the old syntax will be dropped on 2025-01-01.",
vim.log.levels.WARN
)
-- If this is an alternation, take the first one that's available -- If this is an alternation, take the first one that's available
for i, v in ipairs(name) do for i, v in ipairs(name) do
local info = M.get_formatter_info(v, bufnr) local info = M.get_formatter_info(v, bufnr)
@ -309,6 +377,10 @@ M.resolve_formatters = function(names, bufnr, warn_on_missing)
end end
end end
end end
if stop_after_first and #all_info > 0 then
break
end
end end
return all_info return all_info
end end
@ -328,33 +400,34 @@ local function has_lsp_formatter(opts)
return not vim.tbl_isempty(lsp_format.get_format_clients(opts)) return not vim.tbl_isempty(lsp_format.get_format_clients(opts))
end end
---@class conform.FormatOpts local has_notified_ft_no_formatters = {}
---@field timeout_ms nil|integer Time in milliseconds to block for formatting. Defaults to 1000. No effect if async = true.
---@field bufnr nil|integer Format this buffer (default 0)
---@field async nil|boolean If true the method won't block. Defaults to false. If the buffer is modified before the formatter completes, the formatting will be discarded.
---@field dry_run nil|boolean If true don't apply formatting changes to the buffer
---@field formatters nil|string[] List of formatters to run. Defaults to all formatters for the buffer filetype.
---@field lsp_format? "never"|"fallback"|"prefer"|"first"|"last" "fallback" LSP formatting when no other formatters are available, "prefer" only LSP formatting when available, "first" LSP formatting then other formatters, "last" other formatters then LSP.
---@field quiet nil|boolean Don't show any notifications for warnings or failures. Defaults to false.
---@field range nil|table Range to format. Table must contain `start` and `end` keys with {row, col} tuples using (1,0) indexing. Defaults to current selection in visual mode
---@field id nil|integer Passed to |vim.lsp.buf.format| when using LSP formatting
---@field name nil|string Passed to |vim.lsp.buf.format| when using LSP formatting
---@field filter nil|fun(client: table): boolean Passed to |vim.lsp.buf.format| when using LSP formatting
---Format a buffer ---Format a buffer
---@param opts? conform.FormatOpts ---@param opts? conform.FormatOpts
---@param callback? fun(err: nil|string, did_edit: nil|boolean) Called once formatting has completed ---@param callback? fun(err: nil|string, did_edit: nil|boolean) Called once formatting has completed
---@return boolean True if any formatters were attempted ---@return boolean True if any formatters were attempted
M.format = function(opts, callback) M.format = function(opts, callback)
---@type {timeout_ms: integer, bufnr: integer, async: boolean, dry_run: boolean, lsp_format: "never"|"first"|"last"|"prefer"|"fallback", quiet: boolean, formatters?: string[], range?: conform.Range} opts = opts or {}
opts = vim.tbl_extend("keep", opts or {}, { local has_explicit_formatters = opts.formatters ~= nil
-- If formatters were not passed in directly, fetch any options from formatters_by_ft
if not has_explicit_formatters then
merge_default_opts(opts, get_opts_from_filetype(opts.bufnr) or {})
end
merge_default_opts(opts, M.default_format_opts)
---@type {timeout_ms: integer, bufnr: integer, async: boolean, dry_run: boolean, lsp_format: "never"|"first"|"last"|"prefer"|"fallback", quiet: boolean, stop_after_first: boolean, formatters?: string[], range?: conform.Range, undojoin: boolean}
opts = vim.tbl_extend("keep", opts, {
timeout_ms = 1000, timeout_ms = 1000,
bufnr = 0, bufnr = 0,
async = false, async = false,
dry_run = false, dry_run = false,
lsp_format = "never", lsp_format = "never",
quiet = false, quiet = false,
undojoin = false,
stop_after_first = false,
}) })
if opts.bufnr == 0 then
opts.bufnr = vim.api.nvim_get_current_buf()
end
-- For backwards compatibility -- For backwards compatibility
---@diagnostic disable-next-line: undefined-field ---@diagnostic disable-next-line: undefined-field
@ -365,9 +438,6 @@ M.format = function(opts, callback)
opts.lsp_format = "last" opts.lsp_format = "last"
end end
if opts.bufnr == 0 then
opts.bufnr = vim.api.nvim_get_current_buf()
end
local mode = vim.api.nvim_get_mode().mode local mode = vim.api.nvim_get_mode().mode
if not opts.range and mode == "v" or mode == "V" then if not opts.range and mode == "v" or mode == "V" then
opts.range = range_from_selection(opts.bufnr, mode) opts.range = range_from_selection(opts.bufnr, mode)
@ -378,18 +448,23 @@ M.format = function(opts, callback)
local lsp_format = require("conform.lsp_format") local lsp_format = require("conform.lsp_format")
local runner = require("conform.runner") local runner = require("conform.runner")
local explicit_formatters = opts.formatters ~= nil
local formatter_names = opts.formatters or M.list_formatters_for_buffer(opts.bufnr) local formatter_names = opts.formatters or M.list_formatters_for_buffer(opts.bufnr)
local formatters = local formatters = M.resolve_formatters(
M.resolve_formatters(formatter_names, opts.bufnr, not opts.quiet and explicit_formatters) formatter_names,
opts.bufnr,
not opts.quiet and has_explicit_formatters,
opts.stop_after_first
)
local has_lsp = has_lsp_formatter(opts) local has_lsp = has_lsp_formatter(opts)
---Handle errors and maybe run LSP formatting after cli formatters complete
---@param err? conform.Error ---@param err? conform.Error
---@param did_edit? boolean ---@param did_edit? boolean
local function handle_result(err, did_edit) local function handle_result(err, did_edit)
if err then if err then
local level = errors.level_for_code(err.code) local level = errors.level_for_code(err.code)
log.log(level, err.message) log.log(level, err.message)
---@type boolean?
local should_notify = not opts.quiet and level >= vim.log.levels.WARN local should_notify = not opts.quiet and level >= vim.log.levels.WARN
-- Execution errors have special handling. Maybe should reconsider this. -- Execution errors have special handling. Maybe should reconsider this.
local notify_msg = err.message local notify_msg = err.message
@ -398,7 +473,7 @@ M.format = function(opts, callback)
notify_msg = "Formatter failed. See :ConformInfo for details" notify_msg = "Formatter failed. See :ConformInfo for details"
end end
if should_notify then if should_notify then
vim.notify(notify_msg, level) notify(notify_msg, level)
end end
end end
local err_message = err and err.message local err_message = err and err.message
@ -418,12 +493,15 @@ M.format = function(opts, callback)
callback(nil, did_edit) callback(nil, did_edit)
end end
end end
---Run the resolved formatters on the buffer
local function run_cli_formatters(cb) local function run_cli_formatters(cb)
local resolved_names = vim.tbl_map(function(f) local resolved_names = vim.tbl_map(function(f)
return f.name return f.name
end, formatters) end, formatters)
log.debug("Running formatters on %s: %s", vim.api.nvim_buf_get_name(opts.bufnr), resolved_names) log.debug("Running formatters on %s: %s", vim.api.nvim_buf_get_name(opts.bufnr), resolved_names)
local run_opts = { exclusive = true, dry_run = opts.dry_run } ---@type conform.RunOpts
local run_opts = { exclusive = true, dry_run = opts.dry_run, undojoin = opts.undojoin }
if opts.async then if opts.async then
runner.format_async(opts.bufnr, formatters, opts.range, run_opts, cb) runner.format_async(opts.bufnr, formatters, opts.range, run_opts, cb)
else else
@ -461,19 +539,25 @@ M.format = function(opts, callback)
run_cli_formatters(handle_result) run_cli_formatters(handle_result)
return true return true
else else
local level = explicit_formatters and "warn" or "debug" local level = has_explicit_formatters and "warn" or "debug"
log[level]("No formatters found for %s", vim.api.nvim_buf_get_name(opts.bufnr)) log[level]("Formatters unavailable for %s", vim.api.nvim_buf_get_name(opts.bufnr))
callback("No formatters found for buffer")
local ft = vim.bo[opts.bufnr].filetype
if
not vim.tbl_isempty(formatter_names)
and not has_notified_ft_no_formatters[ft]
and not opts.quiet
and M.notify_no_formatters
then
notify(string.format("Formatters unavailable for %s file", ft), vim.log.levels.WARN)
has_notified_ft_no_formatters[ft] = true
end
callback("No formatters available for buffer")
return false return false
end end
end end
---@class conform.FormatLinesOpts
---@field timeout_ms nil|integer Time in milliseconds to block for formatting. Defaults to 1000. No effect if async = true.
---@field bufnr nil|integer use this as the working buffer (default 0)
---@field async nil|boolean If true the method won't block. Defaults to false. If the buffer is modified before the formatter completes, the formatting will be discarded.
---@field quiet nil|boolean Don't show any notifications for warnings or failures. Defaults to false.
---Process lines with formatters ---Process lines with formatters
---@private ---@private
---@param formatter_names string[] ---@param formatter_names string[]
@ -483,18 +567,20 @@ end
---@return nil|conform.Error error Only present if async = false ---@return nil|conform.Error error Only present if async = false
---@return nil|string[] new_lines Only present if async = false ---@return nil|string[] new_lines Only present if async = false
M.format_lines = function(formatter_names, lines, opts, callback) M.format_lines = function(formatter_names, lines, opts, callback)
---@type {timeout_ms: integer, bufnr: integer, async: boolean, quiet: boolean} ---@type {timeout_ms: integer, bufnr: integer, async: boolean, quiet: boolean, stop_after_first: boolean}
opts = vim.tbl_extend("keep", opts or {}, { opts = vim.tbl_extend("keep", opts or {}, {
timeout_ms = 1000, timeout_ms = 1000,
bufnr = 0, bufnr = 0,
async = false, async = false,
quiet = false, quiet = false,
stop_after_first = false,
}) })
callback = callback or function(_err, _lines) end callback = callback or function(_err, _lines) end
local errors = require("conform.errors") local errors = require("conform.errors")
local log = require("conform.log") local log = require("conform.log")
local runner = require("conform.runner") local runner = require("conform.runner")
local formatters = M.resolve_formatters(formatter_names, opts.bufnr, not opts.quiet) local formatters =
M.resolve_formatters(formatter_names, opts.bufnr, not opts.quiet, opts.stop_after_first)
if vim.tbl_isempty(formatters) then if vim.tbl_isempty(formatters) then
callback(nil, lines) callback(nil, lines)
return return
@ -510,7 +596,8 @@ M.format_lines = function(formatter_names, lines, opts, callback)
callback(err, new_lines) callback(err, new_lines)
end end
local run_opts = { exclusive = false, dry_run = false } ---@type conform.RunOpts
local run_opts = { exclusive = false, dry_run = false, undojoin = false }
if opts.async then if opts.async then
runner.format_lines_async(opts.bufnr, formatters, nil, lines, run_opts, handle_err) runner.format_lines_async(opts.bufnr, formatters, nil, lines, run_opts, handle_err)
else else
@ -529,7 +616,44 @@ M.list_formatters = function(bufnr)
bufnr = vim.api.nvim_get_current_buf() bufnr = vim.api.nvim_get_current_buf()
end end
local formatters = M.list_formatters_for_buffer(bufnr) local formatters = M.list_formatters_for_buffer(bufnr)
return M.resolve_formatters(formatters, bufnr, false) return M.resolve_formatters(formatters, bufnr, false, false)
end
---Get the exact formatters that will be run for a buffer.
---@param bufnr? integer
---@return conform.FormatterInfo[]
---@return boolean lsp Will use LSP formatter
---@note
--- This accounts for stop_after_first, lsp fallback logic, etc.
M.list_formatters_to_run = function(bufnr)
if not bufnr or bufnr == 0 then
bufnr = vim.api.nvim_get_current_buf()
end
---@type {bufnr: integer, lsp_format: conform.LspFormatOpts, stop_after_first: boolean}
local opts = vim.tbl_extend(
"keep",
get_opts_from_filetype(bufnr) or {},
M.default_format_opts,
{ stop_after_first = false, lsp_format = "never", bufnr = bufnr }
)
local formatter_names = M.list_formatters_for_buffer(bufnr)
local formatters = M.resolve_formatters(formatter_names, bufnr, false, opts.stop_after_first)
local has_lsp = has_lsp_formatter(opts)
local any_formatters = has_filetype_formatters(opts.bufnr) and not vim.tbl_isempty(formatters)
if
has_lsp
and (opts.lsp_format == "prefer" or (opts.lsp_format ~= "never" and not any_formatters))
then
return {}, true
elseif has_lsp and opts.lsp_format == "first" then
return formatters, true
elseif not vim.tbl_isempty(formatters) then
return formatters, opts.lsp_format == "last" and has_lsp
else
return {}, false
end
end end
---List information about all filetype-configured formatters ---List information about all filetype-configured formatters
@ -540,18 +664,13 @@ M.list_all_formatters = function()
if type(ft_formatters) == "function" then if type(ft_formatters) == "function" then
ft_formatters = ft_formatters(0) ft_formatters = ft_formatters(0)
end end
-- support the old structure where formatters could be a subkey
if not islist(ft_formatters) then
vim.notify_once(
"Using deprecated structure for formatters_by_ft. See :help conform-options for details.",
vim.log.levels.ERROR
)
---@diagnostic disable-next-line: undefined-field
ft_formatters = ft_formatters.formatters
end
for _, formatter in ipairs(ft_formatters) do for _, formatter in ipairs(ft_formatters) do
if type(formatter) == "table" then if type(formatter) == "table" then
notify_once(
"deprecated[conform]: The nested {} syntax to run the first formatter has been replaced by the stop_after_first option (see :help conform.format).\nSupport for the old syntax will be dropped on 2025-01-01.",
vim.log.levels.WARN
)
for _, v in ipairs(formatter) do for _, v in ipairs(formatter) do
formatters[v] = true formatters[v] = true
end end
@ -590,7 +709,7 @@ M.get_formatter_config = function(formatter, bufnr)
if override and override.command and override.format then if override and override.command and override.format then
local msg = local msg =
string.format("Formatter '%s' cannot define both 'command' and 'format' function", formatter) string.format("Formatter '%s' cannot define both 'command' and 'format' function", formatter)
vim.notify_once(msg, vim.log.levels.ERROR) notify_once(msg, vim.log.levels.ERROR)
return nil return nil
end end
@ -612,7 +731,7 @@ M.get_formatter_config = function(formatter, bufnr)
"Formatter '%s' missing built-in definition\nSet `command` to get rid of this error.", "Formatter '%s' missing built-in definition\nSet `command` to get rid of this error.",
formatter formatter
) )
vim.notify_once(msg, vim.log.levels.ERROR) notify_once(msg, vim.log.levels.ERROR)
return nil return nil
end end
else else
@ -696,9 +815,14 @@ M.get_formatter_info = function(formatter, bufnr)
end end
---Check if the buffer will use LSP formatting when lsp_format = "fallback" ---Check if the buffer will use LSP formatting when lsp_format = "fallback"
---@deprecated
---@param options? table Options passed to |vim.lsp.buf.format| ---@param options? table Options passed to |vim.lsp.buf.format|
---@return boolean ---@return boolean
M.will_fallback_lsp = function(options) M.will_fallback_lsp = function(options)
notify_once(
"deprecated[conform]: will_fallback_lsp is deprecated. Use list_formatters_to_run instead.\nThis method will be removed on 2025-01-01.",
vim.log.levels.WARN
)
options = vim.tbl_deep_extend("keep", options or {}, { options = vim.tbl_deep_extend("keep", options or {}, {
bufnr = vim.api.nvim_get_current_buf(), bufnr = vim.api.nvim_get_current_buf(),
}) })

View File

@ -4,7 +4,7 @@ local util = require("vim.lsp.util")
local M = {} local M = {}
local function apply_text_edits(text_edits, bufnr, offset_encoding, dry_run) local function apply_text_edits(text_edits, bufnr, offset_encoding, dry_run, undojoin)
if if
#text_edits == 1 #text_edits == 1
and text_edits[1].range.start.line == 0 and text_edits[1].range.start.line == 0
@ -25,11 +25,15 @@ local function apply_text_edits(text_edits, bufnr, offset_encoding, dry_run)
new_lines, new_lines,
nil, nil,
false, false,
dry_run dry_run,
undojoin
) )
elseif dry_run then elseif dry_run then
return #text_edits > 0 return #text_edits > 0
else else
if undojoin then
vim.cmd.undojoin()
end
vim.lsp.util.apply_text_edits(text_edits, bufnr, offset_encoding) vim.lsp.util.apply_text_edits(text_edits, bufnr, offset_encoding)
return #text_edits > 0 return #text_edits > 0
end end
@ -124,8 +128,13 @@ function M.format(options, callback)
) )
) )
else else
local this_did_edit = local this_did_edit = apply_text_edits(
apply_text_edits(result, ctx.bufnr, client.offset_encoding, options.dry_run) result,
ctx.bufnr,
client.offset_encoding,
options.dry_run,
options.undojoin
)
changedtick = vim.b[bufnr].changedtick changedtick = vim.b[bufnr].changedtick
if options.dry_run and this_did_edit then if options.dry_run and this_did_edit then
@ -145,8 +154,13 @@ function M.format(options, callback)
local params = set_range(client, util.make_formatting_params(options.formatting_options)) local params = set_range(client, util.make_formatting_params(options.formatting_options))
local result, err = client.request_sync(method, params, timeout_ms, bufnr) local result, err = client.request_sync(method, params, timeout_ms, bufnr)
if result and result.result then if result and result.result then
local this_did_edit = local this_did_edit = apply_text_edits(
apply_text_edits(result.result, bufnr, client.offset_encoding, options.dry_run) result.result,
bufnr,
client.offset_encoding,
options.dry_run,
options.undojoin
)
did_edit = did_edit or this_did_edit did_edit = did_edit or this_did_edit
if options.dry_run and did_edit then if options.dry_run and did_edit then

View File

@ -9,6 +9,7 @@ local M = {}
---@class (exact) conform.RunOpts ---@class (exact) conform.RunOpts
---@field exclusive boolean If true, ensure only a single formatter is running per buffer ---@field exclusive boolean If true, ensure only a single formatter is running per buffer
---@field dry_run boolean If true, do not apply changes and stop after the first formatter attempts to do so ---@field dry_run boolean If true, do not apply changes and stop after the first formatter attempts to do so
---@field undojoin boolean Use undojoin to merge formatting changes with previous edit
---@param formatter_name string ---@param formatter_name string
---@param ctx conform.Context ---@param ctx conform.Context
@ -168,8 +169,18 @@ end
---@param new_lines string[] ---@param new_lines string[]
---@param range? conform.Range ---@param range? conform.Range
---@param only_apply_range boolean ---@param only_apply_range boolean
---@param dry_run boolean
---@param undojoin boolean
---@return boolean any_changes ---@return boolean any_changes
M.apply_format = function(bufnr, original_lines, new_lines, range, only_apply_range, dry_run) M.apply_format = function(
bufnr,
original_lines,
new_lines,
range,
only_apply_range,
dry_run,
undojoin
)
if bufnr == 0 then if bufnr == 0 then
bufnr = vim.api.nvim_get_current_buf() bufnr = vim.api.nvim_get_current_buf()
end end
@ -251,6 +262,9 @@ M.apply_format = function(bufnr, original_lines, new_lines, range, only_apply_ra
if not dry_run then if not dry_run then
log.trace("Applying text edits: %s", text_edits) log.trace("Applying text edits: %s", text_edits)
if undojoin then
vim.cmd.undojoin()
end
vim.lsp.util.apply_text_edits(text_edits, bufnr, "utf-8") vim.lsp.util.apply_text_edits(text_edits, bufnr, "utf-8")
log.trace("Done formatting %s", bufname) log.trace("Done formatting %s", bufname)
end end
@ -258,6 +272,12 @@ M.apply_format = function(bufnr, original_lines, new_lines, range, only_apply_ra
return not vim.tbl_isempty(text_edits) return not vim.tbl_isempty(text_edits)
end end
---@param output? string[]
---@return boolean
local function is_empty_output(output)
return not output or vim.tbl_isempty(output) or (#output == 1 and output[1] == "")
end
---Map of formatter name to if the last run of that formatter produced an error ---Map of formatter name to if the last run of that formatter produced an error
---@type table<string, boolean> ---@type table<string, boolean>
local last_run_errored = {} local last_run_errored = {}
@ -388,10 +408,12 @@ local function run_formatter(bufnr, formatter, config, ctx, input_lines, opts, c
log.debug("%s stdout: %s", formatter.name, stdout) log.debug("%s stdout: %s", formatter.name, stdout)
log.debug("%s stderr: %s", formatter.name, stderr) log.debug("%s stderr: %s", formatter.name, stderr)
local err_str local err_str
if stderr and not vim.tbl_isempty(stderr) then if not is_empty_output(stderr) then
err_str = table.concat(stderr, "\n") err_str = table.concat(stderr, "\n")
elseif stdout and not vim.tbl_isempty(stdout) then elseif not is_empty_output(stdout) then
err_str = table.concat(stdout, "\n") err_str = table.concat(stdout, "\n")
else
err_str = "unknown error"
end end
if if
vim.api.nvim_buf_is_valid(bufnr) vim.api.nvim_buf_is_valid(bufnr)
@ -450,6 +472,11 @@ M.build_context = function(bufnr, config, range)
end end
local filename = vim.api.nvim_buf_get_name(bufnr) local filename = vim.api.nvim_buf_get_name(bufnr)
local shiftwidth = vim.bo[bufnr].shiftwidth
if shiftwidth == 0 then
shiftwidth = vim.bo[bufnr].tabstop
end
-- Hack around checkhealth. For buffers that are not files, we need to fabricate a filename -- Hack around checkhealth. For buffers that are not files, we need to fabricate a filename
if vim.bo[bufnr].buftype ~= "" then if vim.bo[bufnr].buftype ~= "" then
filename = "" filename = ""
@ -482,6 +509,7 @@ M.build_context = function(bufnr, config, range)
filename = filename, filename = filename,
dirname = dirname, dirname = dirname,
range = range, range = range,
shiftwidth = shiftwidth,
} }
end end
@ -529,7 +557,8 @@ M.format_async = function(bufnr, formatters, range, opts, callback)
output_lines, output_lines,
range, range,
not all_support_range_formatting, not all_support_range_formatting,
opts.dry_run opts.dry_run,
opts.undojoin
) )
end end
callback(err, did_edit) callback(err, did_edit)
@ -603,7 +632,8 @@ M.format_sync = function(bufnr, formatters, timeout_ms, range, opts)
final_result, final_result,
range, range,
not all_support_range_formatting, not all_support_range_formatting,
opts.dry_run opts.dry_run,
opts.undojoin
) )
return err, did_edit return err, did_edit
end end

View File

@ -49,6 +49,7 @@
---@field filename string ---@field filename string
---@field dirname string ---@field dirname string
---@field range? conform.Range ---@field range? conform.Range
---@field shiftwidth integer
---@class (exact) conform.RangeContext : conform.Context ---@class (exact) conform.RangeContext : conform.Context
---@field range conform.Range ---@field range conform.Range
@ -57,13 +58,53 @@
---@field start integer[] ---@field start integer[]
---@field end integer[] ---@field end integer[]
---@alias conform.FormatterUnit string|string[] ---@alias conform.FiletypeFormatter conform.FiletypeFormatterInternal|fun(bufnr: integer): conform.FiletypeFormatterInternal
---@alias conform.FiletypeFormatter conform.FormatterUnit[]|fun(bufnr: integer): string[]
---This list of formatters to run for a filetype, an any associated format options.
---@class conform.FiletypeFormatterInternal : conform.DefaultFormatOpts
---@field [integer] string
---@alias conform.LspFormatOpts
---| '"never"' # never use the LSP for formatting (default)
---| '"fallback"' # LSP formatting is used when no other formatters are available
---| '"prefer"' # use only LSP formatting when available
---| '"first"' # LSP formatting is used when available and then other formatters
---| '"last"' # other formatters are used then LSP formatting when available
---@class (exact) conform.FormatOpts
---@field timeout_ms? integer Time in milliseconds to block for formatting. Defaults to 1000. No effect if async = true.
---@field bufnr? integer Format this buffer (default 0)
---@field async? boolean If true the method won't block. Defaults to false. If the buffer is modified before the formatter completes, the formatting will be discarded.
---@field dry_run? boolean If true don't apply formatting changes to the buffer
---@field undojoin? boolean Use undojoin to merge formatting changes with previous edit (default false)
---@field formatters? string[] List of formatters to run. Defaults to all formatters for the buffer filetype.
---@field lsp_format? conform.LspFormatOpts Configure if and when LSP should be used for formatting. Defaults to "never".
---@field stop_after_first? boolean Only run the first available formatter in the list. Defaults to false.
---@field quiet? boolean Don't show any notifications for warnings or failures. Defaults to false.
---@field range? conform.Range Range to format. Table must contain `start` and `end` keys with {row, col} tuples using (1,0) indexing. Defaults to current selection in visual mode
---@field id? integer Passed to |vim.lsp.buf.format| when using LSP formatting
---@field name? string Passed to |vim.lsp.buf.format| when using LSP formatting
---@field filter? fun(client: table): boolean Passed to |vim.lsp.buf.format| when using LSP formatting
---@class (exact) conform.DefaultFormatOpts
---@field timeout_ms? integer Time in milliseconds to block for formatting. Defaults to 1000. No effect if async = true.
---@field lsp_format? conform.LspFormatOpts Configure if and when LSP should be used for formatting. Defaults to "never".
---@field quiet? boolean Don't show any notifications for warnings or failures. Defaults to false.
---@field stop_after_first? boolean Only run the first available formatter in the list. Defaults to false.
---@class conform.FormatLinesOpts
---@field timeout_ms? integer Time in milliseconds to block for formatting. Defaults to 1000. No effect if async = true.
---@field bufnr? integer use this as the working buffer (default 0)
---@field async? boolean If true the method won't block. Defaults to false. If the buffer is modified before the formatter completes, the formatting will be discarded.
---@field quiet? boolean Don't show any notifications for warnings or failures. Defaults to false.
---@field stop_after_first? boolean Only run the first available formatter in the list. Defaults to false.
---@class (exact) conform.setupOpts ---@class (exact) conform.setupOpts
---@field formatters_by_ft? table<string, conform.FiletypeFormatter> Map of filetype to formatters ---@field formatters_by_ft? table<string, conform.FiletypeFormatter> Map of filetype to formatters
---@field format_on_save? conform.FormatOpts|fun(bufnr: integer): nil|conform.FormatOpts If this is set, Conform will run the formatter on save. It will pass the table to conform.format(). This can also be a function that returns the table. ---@field format_on_save? conform.FormatOpts|fun(bufnr: integer): nil|conform.FormatOpts If this is set, Conform will run the formatter on save. It will pass the table to conform.format(). This can also be a function that returns the table.
---@field default_format_opts? conform.DefaultFormatOpts The default options to use when calling conform.format()
---@field format_after_save? conform.FormatOpts|fun(bufnr: integer): nil|conform.FormatOpts If this is set, Conform will run the formatter asynchronously after save. It will pass the table to conform.format(). This can also be a function that returns the table. ---@field format_after_save? conform.FormatOpts|fun(bufnr: integer): nil|conform.FormatOpts If this is set, Conform will run the formatter asynchronously after save. It will pass the table to conform.format(). This can also be a function that returns the table.
---@field log_level? integer Set the log level (e.g. `vim.log.levels.DEBUG`). Use `:ConformInfo` to see the location of the log file. ---@field log_level? integer Set the log level (e.g. `vim.log.levels.DEBUG`). Use `:ConformInfo` to see the location of the log file.
---@field notify_on_error? boolean Conform will notify you when a formatter errors (default true). ---@field notify_on_error? boolean Conform will notify you when a formatter errors (default true).
---@field notify_no_formatters? boolean Conform will notify you when no formatters are available for the buffer (default true).
---@field formatters? table<string, conform.FormatterConfigOverride|fun(bufnr: integer): nil|conform.FormatterConfigOverride> Custom formatters and overrides for built-in formatters. ---@field formatters? table<string, conform.FormatterConfigOverride|fun(bufnr: integer): nil|conform.FormatterConfigOverride> Custom formatters and overrides for built-in formatters.

View File

@ -1,4 +1,4 @@
#!/nix/store/agkxax48k35wdmkhmmija2i2sxg8i7ny-bash-5.2p26/bin/bash #!/nix/store/4bj2kxdm1462fzcc2i2s4dn33g2angcc-bash-5.2p32/bin/bash
set -e set -e
mkdir -p ".testenv/config/nvim" mkdir -p ".testenv/config/nvim"

View File

@ -4,8 +4,8 @@ require("conform").setup({
lua = { "stylua" }, lua = { "stylua" },
-- Conform will run multiple formatters sequentially -- Conform will run multiple formatters sequentially
go = { "goimports", "gofmt" }, go = { "goimports", "gofmt" },
-- Use a sub-list to run only the first available formatter -- You can also customize some of the format options for the filetype
javascript = { { "prettierd", "prettier" } }, rust = { "rustfmt", lsp_format = "fallback" },
-- You can use a function here to determine the formatters dynamically -- You can use a function here to determine the formatters dynamically
python = function(bufnr) python = function(bufnr)
if require("conform").get_formatter_info("ruff_format", bufnr).available then if require("conform").get_formatter_info("ruff_format", bufnr).available then
@ -20,6 +20,11 @@ require("conform").setup({
-- have other formatters configured. -- have other formatters configured.
["_"] = { "trim_whitespace" }, ["_"] = { "trim_whitespace" },
}, },
-- Set this to change the default values when calling conform.format()
-- This will also affect the default values for format_on_save/format_after_save
default_format_opts = {
lsp_format = "fallback",
},
-- If this is set, Conform will run the formatter on save. -- If this is set, Conform will run the formatter on save.
-- It will pass the table to conform.format(). -- It will pass the table to conform.format().
-- This can also be a function that returns the table. -- This can also be a function that returns the table.
@ -38,6 +43,8 @@ require("conform").setup({
log_level = vim.log.levels.ERROR, log_level = vim.log.levels.ERROR,
-- Conform will notify you when a formatter errors -- Conform will notify you when a formatter errors
notify_on_error = true, notify_on_error = true,
-- Conform will notify you when no formatters are available for the buffer
notify_no_formatters = true,
-- Custom formatters and overrides for built-in formatters -- Custom formatters and overrides for built-in formatters
formatters = { formatters = {
my_formatter = { my_formatter = {
@ -74,7 +81,6 @@ require("conform").setup({
-- Set to false to disable merging the config with the base definition -- Set to false to disable merging the config with the base definition
inherit = true, inherit = true,
-- When inherit = true, add these additional arguments to the beginning of the command. -- When inherit = true, add these additional arguments to the beginning of the command.
-- When inherit = true, add these additional arguments to the command.
-- This can also be a function, like args -- This can also be a function, like args
prepend_args = { "--use-tabs" }, prepend_args = { "--use-tabs" },
-- When inherit = true, add these additional arguments to the end of the command. -- When inherit = true, add these additional arguments to the end of the command.

View File

@ -1,4 +1,4 @@
#!/nix/store/agkxax48k35wdmkhmmija2i2sxg8i7ny-bash-5.2p26/bin/bash #!/nix/store/4bj2kxdm1462fzcc2i2s4dn33g2angcc-bash-5.2p32/bin/bash
set -e set -e

View File

@ -25,7 +25,7 @@ describe("fuzzer", function()
vim.api.nvim_set_current_buf(bufnr) vim.api.nvim_set_current_buf(bufnr)
vim.api.nvim_buf_set_lines(bufnr, 0, -1, true, buf_content) vim.api.nvim_buf_set_lines(bufnr, 0, -1, true, buf_content)
vim.bo[bufnr].modified = false vim.bo[bufnr].modified = false
runner.apply_format(0, buf_content, expected, nil, false) runner.apply_format(0, buf_content, expected, nil, false, false, false)
assert.are.same(expected, vim.api.nvim_buf_get_lines(0, 0, -1, false)) assert.are.same(expected, vim.api.nvim_buf_get_lines(0, 0, -1, false))
end end

View File

@ -4,11 +4,6 @@ local injected = require("conform.formatters.injected")
local runner = require("conform.runner") local runner = require("conform.runner")
local test_util = require("tests.test_util") local test_util = require("tests.test_util")
-- injected formatter only supported on neovim 0.9+
if vim.fn.has("nvim-0.9") == 0 then
return
end
---@param dir string ---@param dir string
---@return string[] ---@return string[]
local function list_test_files(dir) local function list_test_files(dir)

View File

@ -59,11 +59,36 @@ describe("runner", function()
local config = assert(conform.get_formatter_config("test")) local config = assert(conform.get_formatter_config("test"))
local ctx = runner.build_context(0, config) local ctx = runner.build_context(0, config)
local filename = vim.api.nvim_buf_get_name(bufnr) local filename = vim.api.nvim_buf_get_name(bufnr)
assert.are.same({ assert.equal(bufnr, ctx.buf)
buf = bufnr, assert.equal(filename, ctx.filename)
filename = filename, assert.equal(vim.fs.dirname(filename), ctx.dirname)
dirname = vim.fs.dirname(filename), end)
}, ctx)
it("sets the shiftwidth to shiftwidth", function()
vim.cmd.edit({ args = { "README.md" } })
local bufnr = vim.api.nvim_get_current_buf()
vim.bo[bufnr].shiftwidth = 7
conform.formatters.test = {
meta = { url = "", description = "" },
command = "echo",
}
local config = assert(conform.get_formatter_config("test"))
local ctx = runner.build_context(0, config)
assert.equal(7, ctx.shiftwidth)
end)
it("sets the shiftwidth to tabstop as fallback", function()
vim.cmd.edit({ args = { "README.md" } })
local bufnr = vim.api.nvim_get_current_buf()
vim.bo[bufnr].shiftwidth = 0
vim.bo[bufnr].tabstop = 3
conform.formatters.test = {
meta = { url = "", description = "" },
command = "echo",
}
local config = assert(conform.get_formatter_config("test"))
local ctx = runner.build_context(0, config)
assert.equal(3, ctx.shiftwidth)
end) end)
it("sets temp file when stdin = false", function() it("sets temp file when stdin = false", function()

View File

@ -52,6 +52,7 @@ use {
theme = 'hyper' -- theme is doom and hyper default is hyper theme = 'hyper' -- theme is doom and hyper default is hyper
disable_move -- default is false disable move keymap for hyper disable_move -- default is false disable move keymap for hyper
shortcut_type -- shorcut type 'letter' or 'number' shortcut_type -- shorcut type 'letter' or 'number'
shuffle_letter -- default is true, shortcut 'letter' will be randomize, set to false to have ordered letter.
change_to_vcs_root -- default is false,for open file in hyper mru. it will change to the root of vcs change_to_vcs_root -- default is false,for open file in hyper mru. it will change to the root of vcs
config = {}, -- config used for theme config = {}, -- config used for theme
hide = { hide = {

View File

@ -1,4 +1,4 @@
*dashboard.txt* For Nvim 0.8.0 Last change: 2024 June 12 *dashboard.txt* For Nvim 0.8.0 Last change: 2024 July 14
============================================================================== ==============================================================================
Table of Contents *dashboard-table-of-contents* Table of Contents *dashboard-table-of-contents*
@ -68,6 +68,7 @@ OPTIONS *dashboard-configuration-options*
theme = 'hyper' -- theme is doom and hyper default is hyper theme = 'hyper' -- theme is doom and hyper default is hyper
disable_move -- default is false disable move keymap for hyper disable_move -- default is false disable move keymap for hyper
shortcut_type -- shorcut type 'letter' or 'number' shortcut_type -- shorcut type 'letter' or 'number'
shuffle_letter -- default is true, shortcut 'letter' will be randomize, set to false to have ordered letter.
change_to_vcs_root -- default is false,for open file in hyper mru. it will change to the root of vcs change_to_vcs_root -- default is false,for open file in hyper mru. it will change to the root of vcs
config = {}, -- config used for theme config = {}, -- config used for theme
hide = { hide = {

View File

@ -36,6 +36,7 @@ local function default_options()
theme = 'hyper', theme = 'hyper',
disable_move = false, disable_move = false,
shortcut_type = 'letter', shortcut_type = 'letter',
shuffle_letter = false,
buffer_name = 'Dashboard', buffer_name = 'Dashboard',
change_to_vcs_root = false, change_to_vcs_root = false,
config = { config = {
@ -76,7 +77,6 @@ local function buf_local()
['filetype'] = 'dashboard', ['filetype'] = 'dashboard',
['wrap'] = false, ['wrap'] = false,
['signcolumn'] = 'no', ['signcolumn'] = 'no',
['winbar'] = '',
} }
for opt, val in pairs(opts) do for opt, val in pairs(opts) do
vim.opt_local[opt] = val vim.opt_local[opt] = val
@ -94,6 +94,7 @@ function db:save_user_options()
self.user_cursor_line = vim.opt.cursorline:get() self.user_cursor_line = vim.opt.cursorline:get()
self.user_laststatus_value = vim.opt.laststatus:get() self.user_laststatus_value = vim.opt.laststatus:get()
self.user_tabline_value = vim.opt.showtabline:get() self.user_tabline_value = vim.opt.showtabline:get()
self.user_winbar_value = vim.opt.winbar:get()
end end
function db:set_ui_options(opts) function db:set_ui_options(opts)
@ -103,6 +104,9 @@ function db:set_ui_options(opts)
if opts.hide.tabline then if opts.hide.tabline then
vim.opt.showtabline = 0 vim.opt.showtabline = 0
end end
if opts.hide.winbar then
vim.opt.winbar = ''
end
end end
function db:restore_user_options(opts) function db:restore_user_options(opts)
@ -117,6 +121,10 @@ function db:restore_user_options(opts)
if opts.hide.tabline and self.user_tabline_value then if opts.hide.tabline and self.user_tabline_value then
vim.opt.showtabline = tonumber(self.user_tabline_value) vim.opt.showtabline = tonumber(self.user_tabline_value)
end end
if opts.hide.winbar and self.user_winbar_value then
vim.opt.winbar = self.user_winbar_value
end
end end
function db:cache_opts() function db:cache_opts()
@ -190,6 +198,7 @@ function db:load_theme(opts)
winid = self.winid, winid = self.winid,
confirm_key = opts.confirm_key or nil, confirm_key = opts.confirm_key or nil,
shortcut_type = opts.shortcut_type, shortcut_type = opts.shortcut_type,
shuffle_letter = opts.shuffle_letter,
change_to_vcs_root = opts.change_to_vcs_root, change_to_vcs_root = opts.change_to_vcs_root,
}) })

View File

@ -135,11 +135,12 @@ local function generate_center(config)
-- FIX: #422: In Lua the length of a string is the number of bytes not -- FIX: #422: In Lua the length of a string is the number of bytes not
-- the number of characters. -- the number of characters.
local curline_str = api.nvim_buf_get_lines(config.bufnr, curline - 1, curline, false)[1] local curline_str = api.nvim_buf_get_lines(config.bufnr, curline - 1, curline, false)[1]
local offset = col_width - api.nvim_strwidth(curline_str:sub(1, col + 1)) local strwidth = api.nvim_strwidth(curline_str:sub(1, col + 1))
if offset < 0 then local col_with_offset = col + col_width - strwidth
offset = 0 if col_with_offset < 0 then
col_with_offset = 0
end end
api.nvim_win_set_cursor(config.winid, { curline, col + offset }) api.nvim_win_set_cursor(config.winid, { curline, col_with_offset })
end, end,
}) })
end, 0) end, 0)

View File

@ -175,11 +175,12 @@ local function mru_list(config)
if config.mru.cwd_only then if config.mru.cwd_only then
local cwd = uv.cwd() local cwd = uv.cwd()
local sep = utils.is_win and '\\' or '/' -- get separator from the first file
local cwd_with_sep = cwd .. sep local sep = mlist[1]:match('[\\/]')
local cwd_with_sep = cwd:gsub('[\\/]', sep) .. sep
mlist = vim.tbl_filter(function(file) mlist = vim.tbl_filter(function(file)
local file_dir = vim.fn.fnamemodify(file, ':p:h') .. sep local file_dir = vim.fn.fnamemodify(file, ':p:h')
if file_dir and cwd then if file_dir and cwd_with_sep then
return file_dir:sub(1, #cwd_with_sep) == cwd_with_sep return file_dir:sub(1, #cwd_with_sep) == cwd_with_sep
end end
end, mlist) end, mlist)
@ -188,7 +189,7 @@ local function mru_list(config)
for _, file in pairs(vim.list_slice(mlist, 1, config.mru.limit)) do for _, file in pairs(vim.list_slice(mlist, 1, config.mru.limit)) do
local filename = vim.fn.fnamemodify(file, ':t') local filename = vim.fn.fnamemodify(file, ':t')
local icon, group = utils.get_icon(filename) local icon, group = utils.get_icon(filename)
icon = icon or '' icon = icon or ''
if config.mru.cwd_only then if config.mru.cwd_only then
file = vim.fn.fnamemodify(file, ':.') file = vim.fn.fnamemodify(file, ':.')
elseif not utils.is_win then elseif not utils.is_win then
@ -215,6 +216,7 @@ end
local function letter_hotkey(config) local function letter_hotkey(config)
-- Reserve j, k keys to move up and down. -- Reserve j, k keys to move up and down.
local list = { 106, 107 } local list = { 106, 107 }
local shuffle = config.shuffle_letter
for _, item in pairs(config.shortcut or {}) do for _, item in pairs(config.shortcut or {}) do
if item.key then if item.key then
@ -233,7 +235,9 @@ local function letter_hotkey(config)
end end
end end
shuffle_table(unused_keys) if shuffle then
shuffle_table(unused_keys)
end
local unused_uppercase_keys = {} local unused_uppercase_keys = {}
-- A - Z -- A - Z
@ -243,7 +247,9 @@ local function letter_hotkey(config)
end end
end end
shuffle_table(unused_uppercase_keys) if shuffle then
shuffle_table(unused_uppercase_keys)
end
-- Push shuffled uppercase keys after the lowercase ones -- Push shuffled uppercase keys after the lowercase ones
for _, key in pairs(unused_uppercase_keys) do for _, key in pairs(unused_uppercase_keys) do
@ -404,14 +410,16 @@ local function gen_center(plist, config)
for i, data in pairs(mgroups) do for i, data in pairs(mgroups) do
local len, group = unpack(data) local len, group = unpack(data)
api.nvim_buf_add_highlight( if group then
config.bufnr, api.nvim_buf_add_highlight(
0, config.bufnr,
group, 0,
first_line + i + plist_len, group,
start_col, first_line + i + plist_len,
start_col + len start_col,
) start_col + len
)
end
api.nvim_buf_add_highlight( api.nvim_buf_add_highlight(
config.bufnr, config.bufnr,
0, 0,

View File

@ -64,7 +64,6 @@ end
function utils.get_icon(filename) function utils.get_icon(filename)
local ok, devicons = pcall(require, 'nvim-web-devicons') local ok, devicons = pcall(require, 'nvim-web-devicons')
if not ok then if not ok then
vim.notify('[dashboard.nvim] not found nvim-web-devicons')
return nil return nil
end end
return devicons.get_icon(filename, nil, { default = true }) return devicons.get_icon(filename, nil, { default = true })

View File

@ -6,7 +6,10 @@ body:
- type: markdown - type: markdown
attributes: attributes:
value: | value: |
**Before** reporting an issue, make sure to read the [documentation](https://github.com/folke/flash.nvim) and search [existing issues](https://github.com/folke/flash.nvim/issues). Usage questions such as ***"How do I...?"*** belong in [Discussions](https://github.com/folke/flash.nvim/discussions) and will be closed. **Before** reporting an issue, make sure to read the [documentation](https://github.com/folke/flash.nvim)
and search [existing issues](https://github.com/folke/flash.nvim/issues).
Usage questions such as ***"How do I...?"*** belong in [Discussions](https://github.com/folke/flash.nvim/discussions) and will be closed.
- type: checkboxes - type: checkboxes
attributes: attributes:
label: Did you check docs and existing issues? label: Did you check docs and existing issues?
@ -14,6 +17,8 @@ body:
options: options:
- label: I have read all the flash.nvim docs - label: I have read all the flash.nvim docs
required: true required: true
- label: I have updated the plugin to the latest version before submitting this issue
required: true
- label: I have searched the existing issues of flash.nvim - label: I have searched the existing issues of flash.nvim
required: true required: true
- label: I have searched the existing issues of plugins related to this issue - label: I have searched the existing issues of plugins related to this issue
@ -57,33 +62,15 @@ body:
label: Repro label: Repro
description: Minimal `init.lua` to reproduce this issue. Save as `repro.lua` and run with `nvim -u repro.lua` description: Minimal `init.lua` to reproduce this issue. Save as `repro.lua` and run with `nvim -u repro.lua`
value: | value: |
-- DO NOT change the paths and don't remove the colorscheme vim.env.LAZY_STDPATH = ".repro"
local root = vim.fn.fnamemodify("./.repro", ":p") load(vim.fn.system("curl -s https://raw.githubusercontent.com/folke/lazy.nvim/main/bootstrap.lua"))()
-- set stdpaths to use .repro require("lazy.minit").repro({
for _, name in ipairs({ "config", "data", "state", "cache" }) do spec = {
vim.env[("XDG_%s_HOME"):format(name:upper())] = root .. "/" .. name { "folke/flash.nvim", opts = {} },
end -- add any other plugins here
},
-- bootstrap lazy
local lazypath = root .. "/plugins/lazy.nvim"
if not vim.loop.fs_stat(lazypath) then
vim.fn.system({ "git", "clone", "--filter=blob:none", "https://github.com/folke/lazy.nvim.git", lazypath, })
end
vim.opt.runtimepath:prepend(lazypath)
-- install plugins
local plugins = {
"folke/tokyonight.nvim",
{ "folke/flash.nvim", opts = {} },
-- add any other plugins here
}
require("lazy").setup(plugins, {
root = root .. "/plugins",
}) })
render: lua
vim.cmd.colorscheme("tokyonight")
-- add anything else here
render: Lua
validations: validations:
required: false required: false

View File

@ -1,72 +1,14 @@
name: CI name: CI
on: on:
push: push:
branches: [main, master]
pull_request: pull_request:
jobs: jobs:
tests: ci:
strategy: uses: folke/github/.github/workflows/ci.yml@main
matrix: secrets: inherit
# os: [ubuntu-latest, windows-latest] with:
os: [ubuntu-latest] plugin: flash.nvim
runs-on: ${{ matrix.os }} repo: folke/flash.nvim
steps:
- uses: actions/checkout@v3
- name: Install Neovim
shell: bash
run: |
mkdir -p /tmp/nvim
wget -q https://github.com/neovim/neovim/releases/download/nightly/nvim.appimage -O /tmp/nvim/nvim.appimage
cd /tmp/nvim
chmod a+x ./nvim.appimage
./nvim.appimage --appimage-extract
echo "/tmp/nvim/squashfs-root/usr/bin/" >> $GITHUB_PATH
- name: Run Tests
run: |
nvim --version
[ ! -d tests ] && exit 0
nvim --headless -u tests/init.lua -c "PlenaryBustedDirectory tests/ {minimal_init = 'tests/init.lua', sequential = true}"
docs:
runs-on: ubuntu-latest
needs: tests
if: ${{ github.ref == 'refs/heads/main' }}
steps:
- uses: actions/checkout@v3
- name: panvimdoc
uses: kdheepak/panvimdoc@main
with:
vimdoc: flash.nvim
version: "Neovim >= 0.8.0"
demojify: true
treesitter: true
- name: Push changes
uses: stefanzweifel/git-auto-commit-action@v4
with:
commit_message: "chore(build): auto-generate vimdoc"
commit_user_name: "github-actions[bot]"
commit_user_email: "github-actions[bot]@users.noreply.github.com"
commit_author: "github-actions[bot] <github-actions[bot]@users.noreply.github.com>"
release:
name: release
if: ${{ github.ref == 'refs/heads/main' }}
needs:
- docs
- tests
runs-on: ubuntu-latest
steps:
- uses: google-github-actions/release-please-action@v3
id: release
with:
release-type: simple
package-name: flash.nvim
- uses: actions/checkout@v3
- name: tag stable versions
if: ${{ steps.release.outputs.release_created }}
run: |
git config user.name github-actions[bot]
git config user.email github-actions[bot]@users.noreply.github.com
git remote add gh-token "https://${{ secrets.GITHUB_TOKEN }}@github.com/google-github-actions/release-please-action.git"
git tag -d stable || true
git push origin :stable || true
git tag -a stable -m "Last Stable Release"
git push origin stable

View File

@ -1,8 +1,9 @@
tt.*
.tests
doc/tags
debug
.repro
foo.*
*.log *.log
data /.repro
/.tests
/build
/debug
/doc/tags
foo.*
node_modules
tt.*

View File

@ -1,5 +1,37 @@
# Changelog # Changelog
## [2.1.0](https://github.com/folke/flash.nvim/compare/v2.0.0...v2.1.0) (2024-07-07)
### Features
* **prompt:** add `flash.prompt()` to get the prompt text ([#347](https://github.com/folke/flash.nvim/issues/347)) ([f226e02](https://github.com/folke/flash.nvim/commit/f226e02306e6968604aaffe4d3d5c106ce460a4f))
* **treesitter:** opt-out selection of the smallest node with flash.treesitter() by specifying autojump = false ([#276](https://github.com/folke/flash.nvim/issues/276)) ([daa06cd](https://github.com/folke/flash.nvim/commit/daa06cda13bea0f04a1a120d5f8e7ec32752be19))
### Bug Fixes
* **state:** abort to use Util.exit() ([#324](https://github.com/folke/flash.nvim/issues/324)) ([e7ab1e4](https://github.com/folke/flash.nvim/commit/e7ab1e4003aec864a8fc87f19a4032a2a453479e))
* **treesitter:** process all trees. Closes [#275](https://github.com/folke/flash.nvim/issues/275) ([51f3ee1](https://github.com/folke/flash.nvim/commit/51f3ee13d2c031bb04b78fb324b8ad33e33fdc1f))
## [2.0.0](https://github.com/folke/flash.nvim/compare/v1.18.3...v2.0.0) (2024-07-05)
### ⚠ BREAKING CHANGES
* **search:** flash is now no longer enabled by default during search. Enable it in your config, or use toggle.
### Features
* **char:** add auto-jump/auto-motion option when using labels, closes [#183](https://github.com/folke/flash.nvim/issues/183) ([#281](https://github.com/folke/flash.nvim/issues/281)) ([b14120a](https://github.com/folke/flash.nvim/commit/b14120a4b55c34a83baf40650b8612b411c81ef4))
* **search:** flash is now no longer enabled by default during search. Enable it in your config, or use toggle. ([2411de6](https://github.com/folke/flash.nvim/commit/2411de6fd773ab5b902cf04f2dccfe3baadff229))
### Bug Fixes
* Don't exit in regular search mode when there is no result ([#277](https://github.com/folke/flash.nvim/issues/277)) ([518c047](https://github.com/folke/flash.nvim/commit/518c047031e3dee0b22fad2b23d75deb7ecd826e))
* use real cursors on Neovim &gt;= 0.10. See [#345](https://github.com/folke/flash.nvim/issues/345) ([7ba2298](https://github.com/folke/flash.nvim/commit/7ba2298eb196826442ce68cc6ec0cae2d7d4dbe1))
## [1.18.3](https://github.com/folke/flash.nvim/compare/v1.18.2...v1.18.3) (2024-05-03) ## [1.18.3](https://github.com/folke/flash.nvim/compare/v1.18.2...v1.18.3) (2024-05-03)

View File

@ -292,13 +292,18 @@ Install the plugin with your preferred package manager:
end, end,
search = { wrap = false }, search = { wrap = false },
highlight = { backdrop = true }, highlight = { backdrop = true },
jump = { register = false }, jump = {
register = false,
-- when using jump labels, set to 'true' to automatically jump
-- or execute a motion when there is only one match
autojump = false,
},
}, },
-- options used for treesitter selections -- options used for treesitter selections
-- `require("flash").treesitter()` -- `require("flash").treesitter()`
treesitter = { treesitter = {
labels = "abcdefghijklmnopqrstuvwxyz", labels = "abcdefghijklmnopqrstuvwxyz",
jump = { pos = "range" }, jump = { pos = "range", autojump = true },
search = { incremental = false }, search = { incremental = false },
label = { before = true, after = true, style = "inline" }, label = { before = true, after = true, style = "inline" },
highlight = { highlight = {
@ -319,6 +324,7 @@ Install the plugin with your preferred package manager:
}, },
-- options for the floating window that shows the prompt, -- options for the floating window that shows the prompt,
-- for regular jumps -- for regular jumps
-- `require("flash").prompt()` is always available to get the prompt text
prompt = { prompt = {
enabled = true, enabled = true,
prefix = { { "⚡", "FlashPromptIcon" } }, prefix = { { "⚡", "FlashPromptIcon" } },
@ -405,7 +411,8 @@ Install the plugin with your preferred package manager:
- **jump**: `require("flash").jump(opts?)` opens **flash** with the given options - **jump**: `require("flash").jump(opts?)` opens **flash** with the given options
- type any number of characters before typing a jump label - type any number of characters before typing a jump label
- **VS Code**: some functionality is changed/disabled when running **flash** in **VS Code**: - **VS Code**: some functionality is changed/disabled when running **flash** in **VS Code**:
- `prompt` is disabled - `prompt` is disabled. You can use `require("flash").prompt()` to get the
prompt text and integrate it into the statusline.
- `highlights` are set to different defaults that will actually work in VS Code - `highlights` are set to different defaults that will actually work in VS Code
## 📡 API ## 📡 API

View File

@ -1,4 +1,4 @@
*flash.nvim.txt* For Neovim >= 0.8.0 Last change: 2024 June 04 *flash.nvim.txt* For Neovim Last change: 2024 July 22
============================================================================== ==============================================================================
Table of Contents *flash.nvim-table-of-contents* Table of Contents *flash.nvim-table-of-contents*
@ -281,13 +281,18 @@ Default Settings ~
end, end,
search = { wrap = false }, search = { wrap = false },
highlight = { backdrop = true }, highlight = { backdrop = true },
jump = { register = false }, jump = {
register = false,
-- when using jump labels, set to 'true' to automatically jump
-- or execute a motion when there is only one match
autojump = false,
},
}, },
-- options used for treesitter selections -- options used for treesitter selections
-- `require("flash").treesitter()` -- `require("flash").treesitter()`
treesitter = { treesitter = {
labels = "abcdefghijklmnopqrstuvwxyz", labels = "abcdefghijklmnopqrstuvwxyz",
jump = { pos = "range" }, jump = { pos = "range", autojump = true },
search = { incremental = false }, search = { incremental = false },
label = { before = true, after = true, style = "inline" }, label = { before = true, after = true, style = "inline" },
highlight = { highlight = {
@ -308,6 +313,7 @@ Default Settings ~
}, },
-- options for the floating window that shows the prompt, -- options for the floating window that shows the prompt,
-- for regular jumps -- for regular jumps
-- `require("flash").prompt()` is always available to get the prompt text
prompt = { prompt = {
enabled = true, enabled = true,
prefix = { { "⚡", "FlashPromptIcon" } }, prefix = { { "⚡", "FlashPromptIcon" } },
@ -390,7 +396,8 @@ USAGE *flash.nvim-flash.nvim-usage*
- type any number of characters before typing a jump label - type any number of characters before typing a jump label
- **VS Code**some functionality is changed/disabled when running **flash** in - **VS Code**some functionality is changed/disabled when running **flash** in
**VS Code** **VS Code**
- `prompt`is disabled - `prompt`is disabled. You can use `require("flash").prompt()` to get the
prompt text and integrate it into the statusline.
- `highlights` are set to different defaults that will actually work in VS Code - `highlights` are set to different defaults that will actually work in VS Code

View File

@ -33,4 +33,9 @@ function M.toggle(enabled)
return Search.toggle(enabled) return Search.toggle(enabled)
end end
---@return string
function M.prompt()
return require("flash.prompt").prompt or ""
end
return M return M

View File

@ -216,7 +216,7 @@ local defaults = {
-- `require("flash").treesitter()` -- `require("flash").treesitter()`
treesitter = { treesitter = {
labels = "abcdefghijklmnopqrstuvwxyz", labels = "abcdefghijklmnopqrstuvwxyz",
jump = { pos = "range" }, jump = { pos = "range", autojump = true },
search = { incremental = false }, search = { incremental = false },
label = { before = true, after = true, style = "inline" }, label = { before = true, after = true, style = "inline" },
highlight = { highlight = {
@ -237,6 +237,7 @@ local defaults = {
}, },
-- options for the floating window that shows the prompt, -- options for the floating window that shows the prompt,
-- for regular jumps -- for regular jumps
-- `require("flash").prompt()` is always available to get the prompt text
prompt = { prompt = {
enabled = true, enabled = true,
prefix = { { "", "FlashPromptIcon" } }, prefix = { { "", "FlashPromptIcon" } },
@ -313,10 +314,7 @@ function M.get(...)
o.label = vim.tbl_deep_extend("force", o.label or {}, o.highlight.label) o.label = vim.tbl_deep_extend("force", o.label or {}, o.highlight.label)
---@diagnostic disable-next-line: no-unknown ---@diagnostic disable-next-line: no-unknown
o.highlight.label = nil o.highlight.label = nil
vim.notify_once( vim.notify_once("flash: `opts.highlight.label` is deprecated, use `opts.label` instead", vim.log.levels.WARN)
"flash: `opts.highlight.label` is deprecated, use `opts.label` instead",
vim.log.levels.WARN
)
end end
for _, field in ipairs({ "autohide", "jump_labels" }) do for _, field in ipairs({ "autohide", "jump_labels" }) do
if type(o[field]) == "function" then if type(o[field]) == "function" then

View File

@ -124,12 +124,7 @@ function M.update(state)
-- dont show the label if the cursor is on the same position -- dont show the label if the cursor is on the same position
-- in the same window -- in the same window
-- and the label is not a range -- and the label is not a range
if if cursor[1] == row + 1 and cursor[2] == col and match.win == state.win and state.opts.jump.pos ~= "range" then
cursor[1] == row + 1
and cursor[2] == col
and match.win == state.win
and state.opts.jump.pos ~= "range"
then
return return
end end
if match.fold then if match.fold then

View File

@ -80,10 +80,7 @@ function M.remote_op(match, state, register)
vim.cmd("normal! v") vim.cmd("normal! v")
vim.api.nvim_win_set_cursor(match.win, match.end_pos) vim.api.nvim_win_set_cursor(match.win, match.end_pos)
else else
vim.api.nvim_win_set_cursor( vim.api.nvim_win_set_cursor(match.win, state.opts.jump.pos == "start" and match.pos or match.end_pos)
match.win,
state.opts.jump.pos == "start" and match.pos or match.end_pos
)
end end
-- otherwise, use the remote window's cursor position -- otherwise, use the remote window's cursor position
@ -196,9 +193,7 @@ function M._jump(match, state, opts)
offset = 1 offset = 1
end end
pos = Pos( pos = Pos(require("flash.util").offset_pos(vim.api.nvim_win_get_buf(match.win), pos, { 0, offset or 0 }))
require("flash.util").offset_pos(vim.api.nvim_win_get_buf(match.win), pos, { 0, offset or 0 })
)
pos[2] = math.max(0, pos[2]) pos[2] = math.max(0, pos[2])
vim.api.nvim_win_set_cursor(match.win, pos) vim.api.nvim_win_set_cursor(match.win, pos)

View File

@ -50,10 +50,7 @@ function M:reset()
skip[l] = true skip[l] = true
end end
end end
if if not self.state.opts.search.max_length or #self.state.pattern() < self.state.opts.search.max_length then
not self.state.opts.search.max_length
or #self.state.pattern() < self.state.opts.search.max_length
then
for _, win in pairs(self.state.wins) do for _, win in pairs(self.state.wins) do
self.labels = self:skip(win, self.labels) self.labels = self:skip(win, self.labels)
end end

View File

@ -46,8 +46,7 @@ function M.new()
}, M.motions[M.motion]) }, M.motions[M.motion])
-- never show the current match label -- never show the current match label
opts.highlight.groups.current = M.motion:lower() == "f" and opts.highlight.groups.label opts.highlight.groups.current = M.motion:lower() == "f" and opts.highlight.groups.label or opts.highlight.groups.match
or opts.highlight.groups.match
-- exclude the motion labels so we can use them for next/prev -- exclude the motion labels so we can use them for next/prev
opts.labels = opts.labels:gsub(M.motion:lower(), "") opts.labels = opts.labels:gsub(M.motion:lower(), "")
@ -241,7 +240,7 @@ function M.jump(key)
M.state:update({ force = true }) M.state:update({ force = true })
if M.jump_labels then if M.jump_labels then
if (Config.get("char").jump.autojump and #M.state.results == 1) then if Config.get("char").jump.autojump and #M.state.results == 1 then
M.state:hide() M.state:hide()
return M.state return M.state
end end

View File

@ -9,7 +9,7 @@ local M = {}
---@field node TSNode ---@field node TSNode
---@field depth? number ---@field depth? number
---@param win window ---@param win number
---@param pos? Pos ---@param pos? Pos
function M.get_nodes(win, pos) function M.get_nodes(win, pos)
local buf = vim.api.nvim_win_get_buf(win) local buf = vim.api.nvim_win_get_buf(win)
@ -18,7 +18,7 @@ function M.get_nodes(win, pos)
local nodes = {} ---@type TSNode[] local nodes = {} ---@type TSNode[]
local ok, tree = pcall(vim.treesitter.get_parser, buf) local ok, parser = pcall(vim.treesitter.get_parser, buf)
if not ok then if not ok then
vim.notify( vim.notify(
"No treesitter parser for this buffer with filetype=" .. vim.bo[buf].filetype, "No treesitter parser for this buffer with filetype=" .. vim.bo[buf].filetype,
@ -27,20 +27,25 @@ function M.get_nodes(win, pos)
) )
vim.api.nvim_input("<esc>") vim.api.nvim_input("<esc>")
end end
if not (ok and tree) then if not (ok and parser) then
return {} return {}
end end
do do
-- get all ranges of the current node and its parents parser:for_each_tree(function(tstree, tree)
local node = tree:named_node_for_range({ pos[1] - 1, pos[2], pos[1] - 1, pos[2] }, { if not tstree then
ignore_injections = false, return
}) end
-- get all ranges of the current node and its parents
local node = tree:named_node_for_range({ pos[1] - 1, pos[2], pos[1] - 1, pos[2] }, {
ignore_injections = true,
})
while node do while node do
nodes[#nodes + 1] = node nodes[#nodes + 1] = node
node = node:parent() ---@type TSNode node = node:parent() ---@type TSNode
end end
end)
end end
-- convert ranges to matches -- convert ranges to matches
@ -63,14 +68,12 @@ function M.get_nodes(win, pos)
-- then move it to the last character of the last line. -- then move it to the last character of the last line.
if match.end_pos[1] > line_count then if match.end_pos[1] > line_count then
match.end_pos[1] = line_count match.end_pos[1] = line_count
match.end_pos[2] = match.end_pos[2] = #vim.api.nvim_buf_get_lines(buf, match.end_pos[1] - 1, match.end_pos[1], false)[1]
#vim.api.nvim_buf_get_lines(buf, match.end_pos[1] - 1, match.end_pos[1], false)[1]
elseif match.end_pos[2] == -1 then elseif match.end_pos[2] == -1 then
-- If the end points to the start of the next line, move it to the -- If the end points to the start of the next line, move it to the
-- end of the previous line. -- end of the previous line.
-- Otherwise operations include the first character of the next line -- Otherwise operations include the first character of the next line
local line = local line = vim.api.nvim_buf_get_lines(buf, match.end_pos[1] - 2, match.end_pos[1] - 1, false)[1]
vim.api.nvim_buf_get_lines(buf, match.end_pos[1] - 2, match.end_pos[1] - 1, false)[1]
match.end_pos[1] = match.end_pos[1] - 1 match.end_pos[1] = match.end_pos[1] - 1
match.end_pos[2] = #line match.end_pos[2] = #line
end end
@ -121,11 +124,13 @@ function M.jump(opts)
current = m current = m
end end
end end
current = state:jump(current) if state.opts.jump.autojump then
current = state:jump(current)
end
state:loop({ state:loop({
abort = function() abort = function()
vim.cmd([[normal! v]]) Util.exit()
end, end,
actions = { actions = {
[";"] = function() [";"] = function()
@ -174,7 +179,11 @@ function M.search(opts)
end) end)
local state = Repeat.get_state("treesitter-search", opts) local state = Repeat.get_state("treesitter-search", opts)
state:loop() state:loop({
abort = function()
Util.exit()
end,
})
return state return state
end end

View File

@ -1,8 +1,9 @@
local Config = require("flash.config") local Config = require("flash.config")
---@class Flash.Prompt ---@class Flash.Prompt
---@field win window ---@field win number
---@field buf buffer ---@field buf number
---@field prompt string
local M = {} local M = {}
local ns = vim.api.nvim_create_namespace("flash_prompt") local ns = vim.api.nvim_create_namespace("flash_prompt")
@ -47,6 +48,8 @@ function M.show()
end end
function M.hide() function M.hide()
M.prompt = ""
if M.win and vim.api.nvim_win_is_valid(M.win) then if M.win and vim.api.nvim_win_is_valid(M.win) then
vim.api.nvim_win_close(M.win, true) vim.api.nvim_win_close(M.win, true)
M.win = nil M.win = nil
@ -58,8 +61,8 @@ function M.hide()
end end
---@param pattern string ---@param pattern string
function M.set(pattern) ---@param show boolean
M.show() function M.set(pattern, show)
local text = vim.deepcopy(Config.prompt.prefix) local text = vim.deepcopy(Config.prompt.prefix)
text[#text + 1] = { pattern } text[#text + 1] = { pattern }
@ -67,6 +70,15 @@ function M.set(pattern)
for _, item in ipairs(text) do for _, item in ipairs(text) do
str = str .. item[1] str = str .. item[1]
end end
M.prompt = str
if not show then
return
end
M.show()
vim.api.nvim_buf_set_lines(M.buf, 0, -1, false, { str }) vim.api.nvim_buf_set_lines(M.buf, 0, -1, false, { str })
vim.api.nvim_buf_clear_namespace(M.buf, ns, 0, -1) vim.api.nvim_buf_clear_namespace(M.buf, ns, 0, -1)
local col = 0 local col = 0

View File

@ -56,11 +56,7 @@ function M.setup()
local ok, err = pcall(state.update, state) local ok, err = pcall(state.update, state)
if not ok then if not ok then
vim.schedule(function() vim.schedule(function()
vim.notify( vim.notify("Flash error during redraw:\n" .. err, vim.log.levels.ERROR, { title = "flash.nvim" })
"Flash error during redraw:\n" .. err,
vim.log.levels.ERROR,
{ title = "flash.nvim" }
)
end) end)
end end
end end
@ -217,9 +213,7 @@ function M:check_jump(pattern)
return return
end end
local chars = vim.fn.strchars(pattern) local chars = vim.fn.strchars(pattern)
if if pattern:find(self.pattern(), 1, true) == 1 and chars == vim.fn.strchars(self.pattern()) + 1 then
pattern:find(self.pattern(), 1, true) == 1 and chars == vim.fn.strchars(self.pattern()) + 1
then
local label = vim.fn.strcharpart(pattern, chars - 1, 1) local label = vim.fn.strcharpart(pattern, chars - 1, 1)
if self:jump(label) then if self:jump(label) then
return true return true
@ -349,8 +343,8 @@ end
---@param opts? Flash.Step.Options ---@param opts? Flash.Step.Options
function M:step(opts) function M:step(opts)
opts = opts or {} opts = opts or {}
if self.opts.prompt.enabled and not M.is_search() then if not M.is_search() then
Prompt.set(self.pattern()) Prompt.set(self.pattern(), self.opts.prompt.enabled)
end end
local actions = opts.actions or self.opts.actions or {} local actions = opts.actions or self.opts.actions or {}
local c = self:get_char() local c = self:get_char()
@ -394,7 +388,7 @@ function M:step(opts)
end end
-- exit if no results and not in regular search mode -- exit if no results and not in regular search mode
if #self.results == 0 and not self.pattern:empty() and self.pattern.mode ~= 'search' then if #self.results == 0 and not self.pattern:empty() and self.pattern.mode ~= "search" then
if self.opts.search.incremental then if self.opts.search.incremental then
vim.api.nvim_input(c) vim.api.nvim_input(c)
end end

View File

@ -1 +1,4 @@
std="vim" std="vim"
[lints]
mixed_table="allow"

View File

@ -1,5 +1,6 @@
indent_type = "Spaces" indent_type = "Spaces"
indent_width = 2 indent_width = 2
column_width = 100 column_width = 120
[sort_requires] [sort_requires]
enabled = true enabled = true

View File

@ -1,36 +0,0 @@
local M = {}
function M.root(root)
local f = debug.getinfo(1, "S").source:sub(2)
return vim.fn.fnamemodify(f, ":p:h:h") .. "/" .. (root or "")
end
---@param plugin string
function M.load(plugin)
local name = plugin:match(".*/(.*)")
local package_root = M.root(".tests/site/pack/deps/start/")
if not vim.loop.fs_stat(package_root .. name) then
print("Installing " .. plugin)
vim.fn.mkdir(package_root, "p")
vim.fn.system({
"git",
"clone",
"--depth=1",
"https://github.com/" .. plugin .. ".git",
package_root .. "/" .. name,
})
end
end
function M.setup()
vim.cmd([[set runtimepath=$VIMRUNTIME]])
vim.opt.runtimepath:append(M.root())
vim.opt.packpath = { M.root(".tests/site") }
M.load("nvim-lua/plenary.nvim")
vim.env.XDG_CONFIG_HOME = M.root(".tests/config")
vim.env.XDG_DATA_HOME = M.root(".tests/data")
vim.env.XDG_STATE_HOME = M.root(".tests/state")
vim.env.XDG_CACHE_HOME = M.root(".tests/cache")
end
M.setup()

View File

@ -1,3 +0,0 @@
#!/nix/store/agkxax48k35wdmkhmmija2i2sxg8i7ny-bash-5.2p26/bin/sh
nvim --headless -u tests/init.lua -c "PlenaryBustedDirectory tests {minimal_init = 'tests//init.lua', sequential = true}"

View File

@ -8,42 +8,14 @@ any = true
[jit] [jit]
any = true any = true
[[describe.args]] [assert]
type = "string"
[[describe.args]]
type = "function"
[[it.args]]
type = "string"
[[it.args]]
type = "function"
[[before_each.args]]
type = "function"
[[after_each.args]]
type = "function"
[assert.is_not]
any = true any = true
[[assert.equals.args]] [describe]
type = "any" any = true
[[assert.equals.args]]
type = "any"
[[assert.equals.args]]
type = "any"
required = false
[[assert.same.args]] [it]
type = "any" any = true
[[assert.same.args]]
type = "any"
[[assert.truthy.args]] [before_each.args]
type = "any" any = true
[[assert.spy.args]]
type = "any"
[[assert.stub.args]]
type = "any"

View File

@ -42,6 +42,15 @@ of the default settings:
changedelete = { text = '~' }, changedelete = { text = '~' },
untracked = { text = '┆' }, untracked = { text = '┆' },
}, },
signs_staged = {
add = { text = '┃' },
change = { text = '┃' },
delete = { text = '_' },
topdelete = { text = '‾' },
changedelete = { text = '~' },
untracked = { text = '┆' },
},
signs_staged_enable = true,
signcolumn = true, -- Toggle with `:Gitsigns toggle_signs` signcolumn = true, -- Toggle with `:Gitsigns toggle_signs`
numhl = false, -- Toggle with `:Gitsigns toggle_numhl` numhl = false, -- Toggle with `:Gitsigns toggle_numhl`
linehl = false, -- Toggle with `:Gitsigns toggle_linehl` linehl = false, -- Toggle with `:Gitsigns toggle_linehl`
@ -287,9 +296,13 @@ blame({callback?}) *gitsigns.blame()*
Run git-blame on the current file and open the results Run git-blame on the current file and open the results
in a scroll-bound vertical split. in a scroll-bound vertical split.
<CR> is mapped to open a menu with the actions: Mappings:
- [Show commit] in a vertical split. <CR> is mapped to open a menu with the other mappings
- [Reblame at commit] Note: <Alt> must be held to activate the mappings whilst the menu is
open.
s [Show commit] in a vertical split.
S [Show commit] in a new tab.
r [Reblame at commit]
Attributes: ~ Attributes: ~
{async} {async}
@ -308,8 +321,6 @@ blame_line({opts}, {callback?}) *gitsigns.blame_line()*
Display full commit message with hunk. Display full commit message with hunk.
• {ignore_whitespace}: (boolean) • {ignore_whitespace}: (boolean)
Ignore whitespace when running blame. Ignore whitespace when running blame.
• {rev}: (string)
Revision to blame against.
• {extra_opts}: (string[]) • {extra_opts}: (string[])
Extra options passed to `git-blame`. Extra options passed to `git-blame`.
@ -561,6 +572,7 @@ signs *gitsigns-config-signs*
• `GitSignsAdd` (for normal text signs) • `GitSignsAdd` (for normal text signs)
• `GitSignsAddNr` (for signs when `config.numhl == true`) • `GitSignsAddNr` (for signs when `config.numhl == true`)
• `GitSignsAddLn `(for signs when `config.linehl == true`) • `GitSignsAddLn `(for signs when `config.linehl == true`)
• `GitSignsAddCul `(for signs when `config.culhl == true`)
See |gitsigns-highlight-groups|. See |gitsigns-highlight-groups|.
@ -675,6 +687,16 @@ linehl *gitsigns-config-linehl*
the highlight group does not exist, then it is automatically defined the highlight group does not exist, then it is automatically defined
and linked to the corresponding highlight group in `signs.*.hl`. and linked to the corresponding highlight group in `signs.*.hl`.
culhl *gitsigns-config-culhl*
Type: `boolean`, Default: `false`
Enable/disable highlights for the sign column when the cursor is on
the same line.
When enabled the highlights defined in `signs.*.culhl` are used. If
the highlight group does not exist, then it is automatically defined
and linked to the corresponding highlight group in `signs.*.hl`.
show_deleted *gitsigns-config-show_deleted* show_deleted *gitsigns-config-show_deleted*
Type: `boolean`, Default: `false` Type: `boolean`, Default: `false`
@ -1030,6 +1052,36 @@ GitSignsUntrackedLn
Used for buffer line (when `config.linehl == true`) of 'untracked' signs. Used for buffer line (when `config.linehl == true`) of 'untracked' signs.
Fallbacks: `GitSignsAddLn` Fallbacks: `GitSignsAddLn`
*hl-GitSignsAddCul*
GitSignsAddCul
Used for the text of 'add' signs when the cursor is on the same line as the sign.
Fallbacks: `GitSignsAdd`
*hl-GitSignsChangeCul*
GitSignsChangeCul
Used for the text of 'change' signs when the cursor is on the same line as the sign.
Fallbacks: `GitSignsChange`
*hl-GitSignsDeleteCul*
GitSignsDeleteCul
Used for the text of 'delete' signs when the cursor is on the same line as the sign.
Fallbacks: `GitSignsDelete`
*hl-GitSignsChangedeleteCul*
GitSignsChangedeleteCul
Used for the text of 'changedelete' signs when the cursor is on the same line as the sign.
Fallbacks: `GitSignsChangeCul`
*hl-GitSignsTopdeleteCul*
GitSignsTopdeleteCul
Used for the text of 'topdelete' signs when the cursor is on the same line as the sign.
Fallbacks: `GitSignsDeleteCul`
*hl-GitSignsUntrackedCul*
GitSignsUntrackedCul
Used for the text of 'untracked' signs when the cursor is on the same line as the sign.
Fallbacks: `GitSignsAddCul`
*hl-GitSignsAddPreview* *hl-GitSignsAddPreview*
GitSignsAddPreview GitSignsAddPreview
Used for added lines in previews. Used for added lines in previews.
@ -1202,4 +1254,3 @@ GitSignsChanged After any event in which Gitsigns can potentially change
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
vim:tw=78:ts=8:ft=help:norl: vim:tw=78:ts=8:ft=help:norl:

View File

@ -14,6 +14,7 @@ gitsigns-config-attach_to_untracked gitsigns.txt /*gitsigns-config-attach_to_unt
gitsigns-config-auto_attach gitsigns.txt /*gitsigns-config-auto_attach* gitsigns-config-auto_attach gitsigns.txt /*gitsigns-config-auto_attach*
gitsigns-config-base gitsigns.txt /*gitsigns-config-base* gitsigns-config-base gitsigns.txt /*gitsigns-config-base*
gitsigns-config-count_chars gitsigns.txt /*gitsigns-config-count_chars* gitsigns-config-count_chars gitsigns.txt /*gitsigns-config-count_chars*
gitsigns-config-culhl gitsigns.txt /*gitsigns-config-culhl*
gitsigns-config-current_line_blame gitsigns.txt /*gitsigns-config-current_line_blame* gitsigns-config-current_line_blame gitsigns.txt /*gitsigns-config-current_line_blame*
gitsigns-config-current_line_blame_formatter gitsigns.txt /*gitsigns-config-current_line_blame_formatter* gitsigns-config-current_line_blame_formatter gitsigns.txt /*gitsigns-config-current_line_blame_formatter*
gitsigns-config-current_line_blame_formatter_nc gitsigns.txt /*gitsigns-config-current_line_blame_formatter_nc* gitsigns-config-current_line_blame_formatter_nc gitsigns.txt /*gitsigns-config-current_line_blame_formatter_nc*
@ -82,21 +83,25 @@ gitsigns.toggle_word_diff() gitsigns.txt /*gitsigns.toggle_word_diff()*
gitsigns.txt gitsigns.txt /*gitsigns.txt* gitsigns.txt gitsigns.txt /*gitsigns.txt*
gitsigns.undo_stage_hunk() gitsigns.txt /*gitsigns.undo_stage_hunk()* gitsigns.undo_stage_hunk() gitsigns.txt /*gitsigns.undo_stage_hunk()*
hl-GitSignsAdd gitsigns.txt /*hl-GitSignsAdd* hl-GitSignsAdd gitsigns.txt /*hl-GitSignsAdd*
hl-GitSignsAddCul gitsigns.txt /*hl-GitSignsAddCul*
hl-GitSignsAddInline gitsigns.txt /*hl-GitSignsAddInline* hl-GitSignsAddInline gitsigns.txt /*hl-GitSignsAddInline*
hl-GitSignsAddLn gitsigns.txt /*hl-GitSignsAddLn* hl-GitSignsAddLn gitsigns.txt /*hl-GitSignsAddLn*
hl-GitSignsAddLnInline gitsigns.txt /*hl-GitSignsAddLnInline* hl-GitSignsAddLnInline gitsigns.txt /*hl-GitSignsAddLnInline*
hl-GitSignsAddNr gitsigns.txt /*hl-GitSignsAddNr* hl-GitSignsAddNr gitsigns.txt /*hl-GitSignsAddNr*
hl-GitSignsAddPreview gitsigns.txt /*hl-GitSignsAddPreview* hl-GitSignsAddPreview gitsigns.txt /*hl-GitSignsAddPreview*
hl-GitSignsChange gitsigns.txt /*hl-GitSignsChange* hl-GitSignsChange gitsigns.txt /*hl-GitSignsChange*
hl-GitSignsChangeCul gitsigns.txt /*hl-GitSignsChangeCul*
hl-GitSignsChangeInline gitsigns.txt /*hl-GitSignsChangeInline* hl-GitSignsChangeInline gitsigns.txt /*hl-GitSignsChangeInline*
hl-GitSignsChangeLn gitsigns.txt /*hl-GitSignsChangeLn* hl-GitSignsChangeLn gitsigns.txt /*hl-GitSignsChangeLn*
hl-GitSignsChangeLnInline gitsigns.txt /*hl-GitSignsChangeLnInline* hl-GitSignsChangeLnInline gitsigns.txt /*hl-GitSignsChangeLnInline*
hl-GitSignsChangeNr gitsigns.txt /*hl-GitSignsChangeNr* hl-GitSignsChangeNr gitsigns.txt /*hl-GitSignsChangeNr*
hl-GitSignsChangedelete gitsigns.txt /*hl-GitSignsChangedelete* hl-GitSignsChangedelete gitsigns.txt /*hl-GitSignsChangedelete*
hl-GitSignsChangedeleteCul gitsigns.txt /*hl-GitSignsChangedeleteCul*
hl-GitSignsChangedeleteLn gitsigns.txt /*hl-GitSignsChangedeleteLn* hl-GitSignsChangedeleteLn gitsigns.txt /*hl-GitSignsChangedeleteLn*
hl-GitSignsChangedeleteNr gitsigns.txt /*hl-GitSignsChangedeleteNr* hl-GitSignsChangedeleteNr gitsigns.txt /*hl-GitSignsChangedeleteNr*
hl-GitSignsCurrentLineBlame gitsigns.txt /*hl-GitSignsCurrentLineBlame* hl-GitSignsCurrentLineBlame gitsigns.txt /*hl-GitSignsCurrentLineBlame*
hl-GitSignsDelete gitsigns.txt /*hl-GitSignsDelete* hl-GitSignsDelete gitsigns.txt /*hl-GitSignsDelete*
hl-GitSignsDeleteCul gitsigns.txt /*hl-GitSignsDeleteCul*
hl-GitSignsDeleteInline gitsigns.txt /*hl-GitSignsDeleteInline* hl-GitSignsDeleteInline gitsigns.txt /*hl-GitSignsDeleteInline*
hl-GitSignsDeleteLnInline gitsigns.txt /*hl-GitSignsDeleteLnInline* hl-GitSignsDeleteLnInline gitsigns.txt /*hl-GitSignsDeleteLnInline*
hl-GitSignsDeleteNr gitsigns.txt /*hl-GitSignsDeleteNr* hl-GitSignsDeleteNr gitsigns.txt /*hl-GitSignsDeleteNr*
@ -104,8 +109,10 @@ hl-GitSignsDeletePreview gitsigns.txt /*hl-GitSignsDeletePreview*
hl-GitSignsDeleteVirtLn gitsigns.txt /*hl-GitSignsDeleteVirtLn* hl-GitSignsDeleteVirtLn gitsigns.txt /*hl-GitSignsDeleteVirtLn*
hl-GitSignsDeleteVirtLnInLine gitsigns.txt /*hl-GitSignsDeleteVirtLnInLine* hl-GitSignsDeleteVirtLnInLine gitsigns.txt /*hl-GitSignsDeleteVirtLnInLine*
hl-GitSignsTopdelete gitsigns.txt /*hl-GitSignsTopdelete* hl-GitSignsTopdelete gitsigns.txt /*hl-GitSignsTopdelete*
hl-GitSignsTopdeleteCul gitsigns.txt /*hl-GitSignsTopdeleteCul*
hl-GitSignsTopdeleteNr gitsigns.txt /*hl-GitSignsTopdeleteNr* hl-GitSignsTopdeleteNr gitsigns.txt /*hl-GitSignsTopdeleteNr*
hl-GitSignsUntracked gitsigns.txt /*hl-GitSignsUntracked* hl-GitSignsUntracked gitsigns.txt /*hl-GitSignsUntracked*
hl-GitSignsUntrackedCul gitsigns.txt /*hl-GitSignsUntrackedCul*
hl-GitSignsUntrackedLn gitsigns.txt /*hl-GitSignsUntrackedLn* hl-GitSignsUntrackedLn gitsigns.txt /*hl-GitSignsUntrackedLn*
hl-GitSignsUntrackedNr gitsigns.txt /*hl-GitSignsUntrackedNr* hl-GitSignsUntrackedNr gitsigns.txt /*hl-GitSignsUntrackedNr*
hl-GitSignsVirtLnum gitsigns.txt /*hl-GitSignsVirtLnum* hl-GitSignsVirtLnum gitsigns.txt /*hl-GitSignsVirtLnum*

View File

@ -1,8 +1,8 @@
local async = require('gitsigns.async') local async = require('gitsigns.async')
local log = require('gitsigns.debug.log') local log = require('gitsigns.debug.log')
local Config = require('gitsigns.config')
local gs_config = require('gitsigns.config') local config = Config.config
local config = gs_config.config
local api = vim.api local api = vim.api
local uv = vim.uv or vim.loop local uv = vim.uv or vim.loop
@ -12,8 +12,8 @@ local M = {}
local cwd_watcher ---@type uv.uv_fs_event_t? local cwd_watcher ---@type uv.uv_fs_event_t?
--- @async --- @async
--- @return string gitdir --- @return string? gitdir
--- @return string head --- @return string? head
local function get_gitdir_and_head() local function get_gitdir_and_head()
local cwd = assert(uv.cwd()) local cwd = assert(uv.cwd())
@ -29,9 +29,11 @@ local function get_gitdir_and_head()
end end
end end
local info = require('gitsigns.git').get_repo_info(cwd) local info = require('gitsigns.git').Repo.get_info(cwd)
return info.gitdir, info.abbrev_head if info then
return info.gitdir, info.abbrev_head
end
end end
local update_cwd_head = async.create(function() local update_cwd_head = async.create(function()
@ -89,7 +91,7 @@ local update_cwd_head = async.create(function()
100, 100,
async.create(function() async.create(function()
local git = require('gitsigns.git') local git = require('gitsigns.git')
local new_head = git.get_repo_info(cwd).abbrev_head local new_head = git.Repo.get_info(cwd).abbrev_head
async.scheduler() async.scheduler()
vim.g.gitsigns_head = new_head vim.g.gitsigns_head = new_head
end) end)
@ -204,7 +206,7 @@ end
--- @param cfg table|nil Configuration for Gitsigns. --- @param cfg table|nil Configuration for Gitsigns.
--- See |gitsigns-usage| for more details. --- See |gitsigns-usage| for more details.
function M.setup(cfg) function M.setup(cfg)
gs_config.build(cfg) Config.build(cfg)
if vim.fn.executable('git') == 0 then if vim.fn.executable('git') == 0 then
print('gitsigns: git not in path. Aborting setup') print('gitsigns: git not in path. Aborting setup')

View File

@ -1,16 +1,14 @@
local async = require('gitsigns.async') local async = require('gitsigns.async')
local config = require('gitsigns.config').config local git = require('gitsigns.git')
local mk_repeatable = require('gitsigns.repeat').mk_repeatable local Hunks = require('gitsigns.hunks')
local manager = require('gitsigns.manager')
local popup = require('gitsigns.popup') local popup = require('gitsigns.popup')
local util = require('gitsigns.util') local util = require('gitsigns.util')
local manager = require('gitsigns.manager')
local git = require('gitsigns.git')
local run_diff = require('gitsigns.diff') local run_diff = require('gitsigns.diff')
local gs_cache = require('gitsigns.cache') local config = require('gitsigns.config').config
local cache = gs_cache.cache local mk_repeatable = require('gitsigns.repeat').mk_repeatable
local cache = require('gitsigns.cache').cache
local Hunks = require('gitsigns.hunks')
local api = vim.api local api = vim.api
local current_buf = api.nvim_get_current_buf local current_buf = api.nvim_get_current_buf
@ -416,7 +414,6 @@ end)
--- {async} --- {async}
M.stage_buffer = async.create(function() M.stage_buffer = async.create(function()
local bufnr = current_buf() local bufnr = current_buf()
local bcache = cache[bufnr] local bcache = cache[bufnr]
if not bcache then if not bcache then
return return
@ -977,8 +974,6 @@ end
--- Display full commit message with hunk. --- Display full commit message with hunk.
--- • {ignore_whitespace}: (boolean) --- • {ignore_whitespace}: (boolean)
--- Ignore whitespace when running blame. --- Ignore whitespace when running blame.
--- • {rev}: (string)
--- Revision to blame against.
--- • {extra_opts}: (string[]) --- • {extra_opts}: (string[])
--- Extra options passed to `git-blame`. --- Extra options passed to `git-blame`.
M.blame_line = async.create(1, function(opts) M.blame_line = async.create(1, function(opts)
@ -1014,16 +1009,14 @@ M.blame_line = async.create(1, function(opts)
return return
end end
assert(result) result = util.convert_blame_info(assert(result))
result = util.convert_blame_info(result)
local is_committed = result.sha and tonumber('0x' .. result.sha) ~= 0 local is_committed = result.sha and tonumber('0x' .. result.sha) ~= 0
local blame_linespec = create_blame_fmt(is_committed, opts.full) local blame_linespec = create_blame_fmt(is_committed, opts.full)
if is_committed and opts.full then if is_committed and opts.full then
local body = bcache.git_obj:command( local body = bcache.git_obj.repo:command(
{ 'show', '-s', '--format=%B', result.sha }, { 'show', '-s', '--format=%B', result.sha },
{ text = true } { text = true }
) )
@ -1055,9 +1048,13 @@ end
--- Run git-blame on the current file and open the results --- Run git-blame on the current file and open the results
--- in a scroll-bound vertical split. --- in a scroll-bound vertical split.
--- ---
--- <CR> is mapped to open a menu with the actions: --- Mappings:
--- - [Show commit] in a vertical split. --- <CR> is mapped to open a menu with the other mappings
--- - [Reblame at commit] --- Note: <Alt> must be held to activate the mappings whilst the menu is
--- open.
--- s [Show commit] in a vertical split.
--- S [Show commit] in a new tab.
--- r [Reblame at commit]
--- ---
--- Attributes: ~ --- Attributes: ~
--- {async} --- {async}
@ -1243,6 +1240,10 @@ M.show = function(revision, callback)
diffthis.show(bufnr, revision, callback) diffthis.show(bufnr, revision, callback)
end end
C.show = function(args, _)
M.show(args[1])
end
CP.show = complete_heads CP.show = complete_heads
--- @param buf_or_filename string|integer --- @param buf_or_filename string|integer
@ -1287,17 +1288,24 @@ local function buildqflist(target)
end end
end end
local repo = git.Repo.new(assert(vim.loop.cwd())) local repo = git.Repo.get(assert(vim.loop.cwd()))
if not repos[repo.gitdir] then if repo and not repos[repo.gitdir] then
repos[repo.gitdir] = repo repos[repo.gitdir] = repo
end end
for _, r in pairs(repos) do for _, r in pairs(repos) do
for _, f in ipairs(r:files_changed()) do for _, f in ipairs(r:files_changed(config.base)) do
local f_abs = r.toplevel .. '/' .. f local f_abs = r.toplevel .. '/' .. f
local stat = vim.loop.fs_stat(f_abs) local stat = vim.loop.fs_stat(f_abs)
if stat and stat.type == 'file' then if stat and stat.type == 'file' then
local a = r:get_show_text(':0:' .. f) ---@type string
local obj
if config.base and config.base ~= ':0' then
obj = config.base .. ':' .. f
else
obj = ':0:' .. f
end
local a = r:get_show_text(obj)
async.scheduler() async.scheduler()
local hunks = run_diff(a, util.file_lines(f_abs)) local hunks = run_diff(a, util.file_lines(f_abs))
hunks_to_qflist(f_abs, hunks, qflist) hunks_to_qflist(f_abs, hunks, qflist)

View File

@ -181,6 +181,7 @@ function M.create(argc_or_func, func)
return function(...) return function(...)
local callback = argc and select(argc + 1, ...) or nil local callback = argc and select(argc + 1, ...) or nil
assert(not callback or type(callback) == 'function')
return run(func, callback, unpack({ ... }, 1, argc)) return run(func, callback, unpack({ ... }, 1, argc))
end end
end end

View File

@ -1,20 +1,15 @@
local Status = require('gitsigns.status')
local async = require('gitsigns.async') local async = require('gitsigns.async')
local git = require('gitsigns.git') local git = require('gitsigns.git')
local Cache = require('gitsigns.cache')
local manager = require('gitsigns.manager')
local log = require('gitsigns.debug.log') local log = require('gitsigns.debug.log')
local dprintf = log.dprintf local manager = require('gitsigns.manager')
local dprint = log.dprint
local gs_cache = require('gitsigns.cache')
local cache = gs_cache.cache
local Status = require('gitsigns.status')
local config = require('gitsigns.config').config
local util = require('gitsigns.util') local util = require('gitsigns.util')
local cache = Cache.cache
local config = require('gitsigns.config').config
local dprint = log.dprint
local dprintf = log.dprintf
local throttle_by_id = require('gitsigns.debounce').throttle_by_id local throttle_by_id = require('gitsigns.debounce').throttle_by_id
local api = vim.api local api = vim.api
@ -46,13 +41,25 @@ end
--- @return string buffer --- @return string buffer
--- @return string? commit --- @return string? commit
local function parse_gitsigns_uri(name) local function parse_gitsigns_uri(name)
-- TODO(lewis6991): Support submodules local _proto, head, tail = unpack(vim.split(name, '//'))
--- @type any, any, string?, string?, string
local _, _, root_path, commit, rel_path = name:find([[^gitsigns://(.*)/%.git/(.*):(.*)]]) --- @type any, any, string?, string?
local _, _, root_path, sub_path = head:find([[(.*)/%.git(.*)]])
--- @type any, any, string?, string?
local _, _, commit, rel_path = tail:find([[(.*):(.*)]])
commit = util.norm_base(commit) commit = util.norm_base(commit)
if root_path then if root_path then
name = root_path .. '/' .. rel_path if sub_path then
sub_path = sub_path:gsub('^/modules/', '')
name = string.format('%s/%s/%s', root_path, sub_path, rel_path)
else
name = string.format('%s/%s', root_path, rel_path)
end
end end
return name, commit return name, commit
end end
@ -71,7 +78,7 @@ local function get_buf_path(bufnr)
dprintf("Fugitive buffer for file '%s' from path '%s'", path, file) dprintf("Fugitive buffer for file '%s' from path '%s'", path, file)
if path then if path then
local realpath = uv.fs_realpath(path) local realpath = uv.fs_realpath(path)
if realpath then if realpath and vim.fn.isdirectory(realpath) == 0 then
return realpath, commit, true return realpath, commit, true
end end
end end
@ -323,7 +330,7 @@ local attach_throttled = throttle_by_id(function(cbuf, ctx, aucmd)
return return
end end
cache[cbuf] = gs_cache.new({ cache[cbuf] = Cache.new({
bufnr = cbuf, bufnr = cbuf,
file = file, file = file,
git_obj = git_obj, git_obj = git_obj,
@ -357,6 +364,10 @@ local attach_throttled = throttle_by_id(function(cbuf, ctx, aucmd)
-- Initial update -- Initial update
manager.update(cbuf) manager.update(cbuf)
if config.current_line_blame then
require('gitsigns.current_line_blame').update(cbuf)
end
end) end)
--- Detach Gitsigns from all buffers it is attached to. --- Detach Gitsigns from all buffers it is attached to.
@ -391,7 +402,7 @@ function M.detach(bufnr, _keep_signs)
-- Clear status variables -- Clear status variables
Status:clear(bufnr) Status:clear(bufnr)
gs_cache.destroy(bufnr) Cache.destroy(bufnr)
end end
--- Attach Gitsigns to the buffer. --- Attach Gitsigns to the buffer.

View File

@ -22,9 +22,12 @@ local M = {
--- @field blame? table<integer,Gitsigns.BlameInfo?> --- @field blame? table<integer,Gitsigns.BlameInfo?>
local CacheEntry = M.CacheEntry local CacheEntry = M.CacheEntry
function CacheEntry:get_rev_bufname(rev) function CacheEntry:get_rev_bufname(rev, nofile)
rev = rev or self.git_obj.revision or ':0' rev = rev or self.git_obj.revision or ':0'
return string.format('gitsigns://%s/%s:%s', self.git_obj.repo.gitdir, rev, self.git_obj.relpath) if nofile then
return string.format('gitsigns://%s//%s', self.git_obj.repo.gitdir, rev)
end
return string.format('gitsigns://%s//%s:%s', self.git_obj.repo.gitdir, rev, self.git_obj.relpath)
end end
--- Invalidate any state dependent on the buffer content. --- Invalidate any state dependent on the buffer content.
@ -53,6 +56,7 @@ local sleep = async.wrap(2, function(duration, cb)
vim.defer_fn(cb, duration) vim.defer_fn(cb, duration)
end) end)
--- @async
--- @private --- @private
function CacheEntry:wait_for_hunks() function CacheEntry:wait_for_hunks()
local loop_protect = 0 local loop_protect = 0
@ -65,71 +69,61 @@ end
-- If a file contains has up to this amount of lines, then -- If a file contains has up to this amount of lines, then
-- always blame the whole file, otherwise only blame one line -- always blame the whole file, otherwise only blame one line
-- at a time. -- at a time.
local BLAME_THRESHOLD_LEN = 1000000 local BLAME_THRESHOLD_LEN = 10000
--- @async --- @async
--- @private
--- @param lnum? integer --- @param lnum? integer
--- @param opts Gitsigns.BlameOpts --- @param opts? Gitsigns.BlameOpts
--- @return table<integer,Gitsigns.BlameInfo?>? --- @return table<integer,Gitsigns.BlameInfo?>
--- @return boolean? full
function CacheEntry:run_blame(lnum, opts) function CacheEntry:run_blame(lnum, opts)
local bufnr = self.bufnr local bufnr = self.bufnr
local blame_cache --- @type table<integer,Gitsigns.BlameInfo?>? local blame --- @type table<integer,Gitsigns.BlameInfo?>?
local lnum0 --- @type integer?
repeat repeat
local buftext = util.buf_lines(bufnr, true) local buftext = util.buf_lines(bufnr, true)
local tick = vim.b[bufnr].changedtick local tick = vim.b[bufnr].changedtick
local lnum0 = #buftext > BLAME_THRESHOLD_LEN and lnum or nil lnum0 = #buftext > BLAME_THRESHOLD_LEN and lnum or nil
-- TODO(lewis6991): Cancel blame on changedtick -- TODO(lewis6991): Cancel blame on changedtick
blame_cache = self.git_obj:run_blame(buftext, lnum0, opts) blame = self.git_obj:run_blame(buftext, lnum0, self.git_obj.revision, opts)
async.scheduler() async.scheduler()
if not vim.api.nvim_buf_is_valid(bufnr) then if not vim.api.nvim_buf_is_valid(bufnr) then
return return {}
end end
until vim.b[bufnr].changedtick == tick until vim.b[bufnr].changedtick == tick
return blame_cache return blame, lnum0 == nil
end end
--- @param file string --- If lnum is nil then run blame for the entire buffer.
--- @param lnum integer --- @async
--- @return Gitsigns.BlameInfo --- @param lnum? integer
local function get_blame_nc(file, lnum) --- @param opts? Gitsigns.BlameOpts
local Git = require('gitsigns.git')
return {
orig_lnum = 0,
final_lnum = lnum,
commit = Git.not_committed(file),
filename = file,
}
end
--- @param lnum integer
--- @param opts Gitsigns.BlameOpts
--- @return Gitsigns.BlameInfo? --- @return Gitsigns.BlameInfo?
function CacheEntry:get_blame(lnum, opts) function CacheEntry:get_blame(lnum, opts)
if opts.rev then local blame = self.blame
local buftext = util.buf_lines(self.bufnr)
return self.git_obj:run_blame(buftext, lnum, opts)[lnum]
end
local blame_cache = self.blame if not blame or (lnum and not blame[lnum]) then
if not blame_cache or not blame_cache[lnum] then
self:wait_for_hunks() self:wait_for_hunks()
blame = blame or {}
local Hunks = require('gitsigns.hunks') local Hunks = require('gitsigns.hunks')
if Hunks.find_hunk(lnum, self.hunks) then if lnum and Hunks.find_hunk(lnum, self.hunks) then
--- Bypass running blame (which can be expensive) if we know lnum is in a hunk --- Bypass running blame (which can be expensive) if we know lnum is in a hunk
blame_cache = blame_cache or {} local Blame = require('gitsigns.git.blame')
blame_cache[lnum] = get_blame_nc(self.git_obj.relpath, lnum) blame[lnum] = Blame.get_blame_nc(self.git_obj.relpath, lnum)
else else
-- Refresh cache -- Refresh/update cache
blame_cache = self:run_blame(lnum, opts) local b, full = self:run_blame(lnum, opts)
if lnum and not full then
blame[lnum] = b[lnum]
else
blame = b
end
end end
self.blame = blame_cache self.blame = blame
end end
if blame_cache then return blame[lnum]
return blame_cache[lnum]
end
end end
function CacheEntry:destroy() function CacheEntry:destroy()
@ -137,9 +131,10 @@ function CacheEntry:destroy()
if w and not w:is_closing() then if w and not w:is_closing() then
w:close() w:close()
end end
self.git_obj.repo:unref()
end end
---@type table<integer,Gitsigns.CacheEntry> ---@type table<integer,Gitsigns.CacheEntry?>
M.cache = {} M.cache = {}
--- @param bufnr integer --- @param bufnr integer

View File

@ -1,20 +1,16 @@
local async = require('gitsigns.async')
local log = require('gitsigns.debug.log')
local dprintf = log.dprintf
local message = require('gitsigns.message')
local parse_args = require('gitsigns.cli.argparse').parse_args
local actions = require('gitsigns.actions') local actions = require('gitsigns.actions')
local argparse = require('gitsigns.cli.argparse')
local async = require('gitsigns.async')
local attach = require('gitsigns.attach') local attach = require('gitsigns.attach')
local gs_debug = require('gitsigns.debug') local Debug = require('gitsigns.debug')
local log = require('gitsigns.debug.log')
local message = require('gitsigns.message')
--- @type table<table<string,function>,boolean> --- @type table<table<string,function>,boolean>
local sources = { local sources = {
[actions] = true, [actions] = true,
[attach] = false, [attach] = false,
[gs_debug] = false, [Debug] = false,
} }
-- try to parse each argument as a lua boolean, nil or number, if fails then -- try to parse each argument as a lua boolean, nil or number, if fails then
@ -64,7 +60,7 @@ end
M.run = async.create(1, function(params) M.run = async.create(1, function(params)
local __FUNC__ = 'cli.run' local __FUNC__ = 'cli.run'
local pos_args_raw, named_args_raw = parse_args(params.args) local pos_args_raw, named_args_raw = argparse.parse_args(params.args)
local func = pos_args_raw[1] local func = pos_args_raw[1]
@ -79,7 +75,7 @@ M.run = async.create(1, function(params)
local named_args = vim.tbl_map(parse_to_lua, named_args_raw) local named_args = vim.tbl_map(parse_to_lua, named_args_raw)
local args = vim.tbl_extend('error', pos_args, named_args) local args = vim.tbl_extend('error', pos_args, named_args)
dprintf( log.dprintf(
"Running action '%s' with arguments %s", "Running action '%s' with arguments %s",
func, func,
vim.inspect(args, { newline = ' ', indent = '' }) vim.inspect(args, { newline = ' ', indent = '' })

View File

@ -25,6 +25,7 @@
--- @field text string --- @field text string
--- @field numhl string --- @field numhl string
--- @field linehl string --- @field linehl string
--- @field culhl string
--- @alias Gitsigns.SignType --- @alias Gitsigns.SignType
--- | 'add' --- | 'add'
@ -34,7 +35,7 @@
--- | 'changedelete' --- | 'changedelete'
--- | 'untracked' --- | 'untracked'
--- @alias Gitsigns.CurrentLineBlameFmtFun fun(user: string, info: table<string,any>): {[1]:string,[2]:string}[] --- @alias Gitsigns.CurrentLineBlameFmtFun fun(user: string, info: table<string,any>): [string,string][]
--- @class (exact) Gitsigns.CurrentLineBlameOpts : Gitsigns.BlameOpts --- @class (exact) Gitsigns.CurrentLineBlameOpts : Gitsigns.BlameOpts
--- @field virt_text? boolean --- @field virt_text? boolean
@ -44,7 +45,6 @@
--- @class (exact) Gitsigns.BlameOpts --- @class (exact) Gitsigns.BlameOpts
--- @field ignore_whitespace? boolean --- @field ignore_whitespace? boolean
--- @field rev? string
--- @field extra_opts? string[] --- @field extra_opts? string[]
--- @class (exact) Gitsigns.LineBlameOpts : Gitsigns.BlameOpts --- @class (exact) Gitsigns.LineBlameOpts : Gitsigns.BlameOpts
@ -61,6 +61,7 @@
--- @field signcolumn boolean --- @field signcolumn boolean
--- @field numhl boolean --- @field numhl boolean
--- @field linehl boolean --- @field linehl boolean
--- @field culhl boolean
--- @field show_deleted boolean --- @field show_deleted boolean
--- @field sign_priority integer --- @field sign_priority integer
--- @field _on_attach_pre fun(bufnr: integer, callback: fun(_: table)) --- @field _on_attach_pre fun(bufnr: integer, callback: fun(_: table))
@ -184,10 +185,13 @@ local function validate_signs(x)
if x[kind] and x[kind][ty] and vim.endswith(ty, 'hl') then if x[kind] and x[kind][ty] and vim.endswith(ty, 'hl') then
warnings = warnings or {} warnings = warnings or {}
local w = string.format( local w = string.format(
"'signs.%s.%s' is now deprecated, please define highlight '%s'", "'signs.%s.%s' is now deprecated, please define highlight '%s' e.g:\n"
.. " vim.api.nvim_set_hl(0, '%s', { link = '%s' })",
kind, kind,
ty, ty,
v v,
v,
x[kind][ty]
) )
warnings[w] = true warnings[w] = true
end end
@ -210,36 +214,47 @@ M.schema = {
type = validate_signs, type = validate_signs,
deep_extend = true, deep_extend = true,
default = { default = {
add = { hl = 'GitSignsAdd', text = '', numhl = 'GitSignsAddNr', linehl = 'GitSignsAddLn' }, add = {
hl = 'GitSignsAdd',
text = '',
numhl = 'GitSignsAddNr',
linehl = 'GitSignsAddLn',
culhl = 'GitSignsAddCul',
},
change = { change = {
hl = 'GitSignsChange', hl = 'GitSignsChange',
text = '', text = '',
numhl = 'GitSignsChangeNr', numhl = 'GitSignsChangeNr',
linehl = 'GitSignsChangeLn', linehl = 'GitSignsChangeLn',
culhl = 'GitSignsChangeCul',
}, },
delete = { delete = {
hl = 'GitSignsDelete', hl = 'GitSignsDelete',
text = '', text = '',
numhl = 'GitSignsDeleteNr', numhl = 'GitSignsDeleteNr',
linehl = 'GitSignsDeleteLn', linehl = 'GitSignsDeleteLn',
culhl = 'GitSignsDeleteCul',
}, },
topdelete = { topdelete = {
hl = 'GitSignsTopdelete', hl = 'GitSignsTopdelete',
text = '', text = '',
numhl = 'GitSignsTopdeleteNr', numhl = 'GitSignsTopdeleteNr',
linehl = 'GitSignsTopdeleteLn', linehl = 'GitSignsTopdeleteLn',
culhl = 'GitSignsTopdeleteCul',
}, },
changedelete = { changedelete = {
hl = 'GitSignsChangedelete', hl = 'GitSignsChangedelete',
text = '~', text = '~',
numhl = 'GitSignsChangedeleteNr', numhl = 'GitSignsChangedeleteNr',
linehl = 'GitSignsChangedeleteLn', linehl = 'GitSignsChangedeleteLn',
culhl = 'GitSignsChangedeleteCul',
}, },
untracked = { untracked = {
hl = 'GitSignsUntracked', hl = 'GitSignsUntracked',
text = '', text = '',
numhl = 'GitSignsUntrackedNr', numhl = 'GitSignsUntrackedNr',
linehl = 'GitSignsUntrackedLn', linehl = 'GitSignsUntrackedLn',
culhl = 'GitSignsUntrackedCul',
}, },
}, },
default_help = [[{ default_help = [[{
@ -261,6 +276,7 @@ M.schema = {
• `GitSignsAdd` (for normal text signs) • `GitSignsAdd` (for normal text signs)
• `GitSignsAddNr` (for signs when `config.numhl == true`) • `GitSignsAddNr` (for signs when `config.numhl == true`)
• `GitSignsAddLn `(for signs when `config.linehl == true`) • `GitSignsAddLn `(for signs when `config.linehl == true`)
• `GitSignsAddCul `(for signs when `config.culhl == true`)
See |gitsigns-highlight-groups|. See |gitsigns-highlight-groups|.
]], ]],
@ -275,30 +291,35 @@ M.schema = {
text = '', text = '',
numhl = 'GitSignsStagedAddNr', numhl = 'GitSignsStagedAddNr',
linehl = 'GitSignsStagedAddLn', linehl = 'GitSignsStagedAddLn',
culhl = 'GitSignsStagedAddCul',
}, },
change = { change = {
hl = 'GitSignsStagedChange', hl = 'GitSignsStagedChange',
text = '', text = '',
numhl = 'GitSignsStagedChangeNr', numhl = 'GitSignsStagedChangeNr',
linehl = 'GitSignsStagedChangeLn', linehl = 'GitSignsStagedChangeLn',
culhl = 'GitSignsStagedChangeCul',
}, },
delete = { delete = {
hl = 'GitSignsStagedDelete', hl = 'GitSignsStagedDelete',
text = '', text = '',
numhl = 'GitSignsStagedDeleteNr', numhl = 'GitSignsStagedDeleteNr',
linehl = 'GitSignsStagedDeleteLn', linehl = 'GitSignsStagedDeleteLn',
culhl = 'GitSignsStagedDeleteCul',
}, },
topdelete = { topdelete = {
hl = 'GitSignsStagedTopdelete', hl = 'GitSignsStagedTopdelete',
text = '', text = '',
numhl = 'GitSignsStagedTopdeleteNr', numhl = 'GitSignsStagedTopdeleteNr',
linehl = 'GitSignsStagedTopdeleteLn', linehl = 'GitSignsStagedTopdeleteLn',
culhl = 'GitSignsStagedTopdeleteCul',
}, },
changedelete = { changedelete = {
hl = 'GitSignsStagedChangedelete', hl = 'GitSignsStagedChangedelete',
text = '~', text = '~',
numhl = 'GitSignsStagedChangedeleteNr', numhl = 'GitSignsStagedChangedeleteNr',
linehl = 'GitSignsStagedChangedeleteLn', linehl = 'GitSignsStagedChangedeleteLn',
culhl = 'GitSignsStagedChangedeleteCul',
}, },
}, },
default_help = [[{ default_help = [[{
@ -456,6 +477,19 @@ M.schema = {
]], ]],
}, },
culhl = {
type = 'boolean',
default = false,
description = [[
Enable/disable highlights for the sign column when the cursor is on
the same line.
When enabled the highlights defined in `signs.*.culhl` are used. If
the highlight group does not exist, then it is automatically defined
and linked to the corresponding highlight group in `signs.*.hl`.
]],
},
show_deleted = { show_deleted = {
type = 'boolean', type = 'boolean',
default = false, default = false,

View File

@ -1,11 +1,13 @@
local async = require('gitsigns.async') local async = require('gitsigns.async')
local cache = require('gitsigns.cache').cache local debounce = require('gitsigns.debounce')
local config = require('gitsigns.config').config
local util = require('gitsigns.util') local util = require('gitsigns.util')
local api = vim.api local cache = require('gitsigns.cache').cache
local config = require('gitsigns.config').config
local schema = require('gitsigns.config').schema
local error_once = require('gitsigns.message').error_once
local debounce = require('gitsigns.debounce') local api = vim.api
local namespace = api.nvim_create_namespace('gitsigns_blame') local namespace = api.nvim_create_namespace('gitsigns_blame')
@ -72,19 +74,31 @@ end
---@param bufnr integer ---@param bufnr integer
---@param blame_info Gitsigns.BlameInfoPublic ---@param blame_info Gitsigns.BlameInfoPublic
---@return {[1]: string, [2]:string}[] ---@return [string, string][]
local function get_blame_virt_text(bufnr, blame_info) local function get_blame_virt_text(bufnr, blame_info)
local git_obj = assert(cache[bufnr]).git_obj local git_obj = assert(cache[bufnr]).git_obj
local use_nc = blame_info.author == 'Not Committed Yet'
local clb_formatter = blame_info.author == 'Not Committed Yet' local clb_formatter = use_nc and config.current_line_blame_formatter_nc
and config.current_line_blame_formatter_nc
or config.current_line_blame_formatter or config.current_line_blame_formatter
if type(clb_formatter) == 'string' then if type(clb_formatter) == 'function' then
clb_formatter = default_formatter(clb_formatter) local ok, res = pcall(clb_formatter, git_obj.repo.username, blame_info)
if ok then
return res
end
local nc_sfx = use_nc and '_nc' or ''
error_once(
'Failed running config.current_line_blame_formatter%s, using default:\n %s',
nc_sfx,
res
)
--- @type string
clb_formatter = schema.current_line_blame_formatter.default
end end
return clb_formatter(git_obj.repo.username, blame_info) return default_formatter(clb_formatter)(git_obj.repo.username, blame_info)
end end
--- @param bufnr integer --- @param bufnr integer
@ -192,50 +206,53 @@ end
local update = async.create(1, debounce.throttle_by_id(update0)) local update = async.create(1, debounce.throttle_by_id(update0))
--- @type fun(bufnr: integer) --- @type fun(bufnr: integer)
local update_debounced M.update = nil
function M.setup() function M.setup()
local group = api.nvim_create_augroup('gitsigns_blame', {}) for k in pairs(cache) do
local opts = config.current_line_blame_opts
update_debounced = debounce.debounce_trailing(opts.delay, update)
for k, _ in pairs(cache) do
reset(k) reset(k)
end end
if config.current_line_blame then local group = api.nvim_create_augroup('gitsigns_blame', {})
local events = { 'FocusGained', 'BufEnter', 'CursorMoved', 'CursorMovedI' }
if vim.fn.exists('#WinResized') == 1 then
-- For nvim 0.9+
events[#events + 1] = 'WinResized'
end
api.nvim_create_autocmd(events, { if not config.current_line_blame then
group = group, return
callback = function(args)
reset(args.buf)
update_debounced(args.buf)
end,
})
api.nvim_create_autocmd({ 'InsertEnter', 'FocusLost', 'BufLeave' }, {
group = group,
callback = function(args)
reset(args.buf)
end,
})
api.nvim_create_autocmd('OptionSet', {
group = group,
pattern = { 'fileformat', 'bomb', 'eol' },
callback = function(args)
reset(args.buf)
end,
})
update_debounced(api.nvim_get_current_buf())
end end
local opts = config.current_line_blame_opts
M.update = debounce.debounce_trailing(opts.delay, update)
-- show current buffer line blame immediately
M.update(api.nvim_get_current_buf())
local events = { 'FocusGained', 'BufEnter', 'CursorMoved', 'CursorMovedI' }
if vim.fn.exists('#WinResized') == 1 then
-- For nvim 0.9+
events[#events + 1] = 'WinResized'
end
api.nvim_create_autocmd(events, {
group = group,
callback = function(args)
reset(args.buf)
M.update(args.buf)
end,
})
api.nvim_create_autocmd({ 'InsertEnter', 'FocusLost', 'BufLeave' }, {
group = group,
callback = function(args)
reset(args.buf)
end,
})
api.nvim_create_autocmd('OptionSet', {
group = group,
pattern = { 'fileformat', 'bomb', 'eol' },
callback = function(args)
reset(args.buf)
end,
})
end end
return M return M

View File

@ -1,4 +1,4 @@
local uv = vim.loop local uv = vim.uv or vim.loop
local M = {} local M = {}

View File

@ -1,10 +1,10 @@
local Hunks = require('gitsigns.hunks')
local util = require('gitsigns.util')
local scheduler = require('gitsigns.async').scheduler
local config = require('gitsigns.config').config local config = require('gitsigns.config').config
local git_diff = require('gitsigns.git').diff local git_diff = require('gitsigns.git').diff
local gs_hunks = require('gitsigns.hunks')
local util = require('gitsigns.util')
local scheduler = require('gitsigns.async').scheduler
local M = {} local M = {}
-- Async function -- Async function
@ -61,7 +61,7 @@ function M.run_diff(text_cmp, text_buf)
for _, line in ipairs(out) do for _, line in ipairs(out) do
if vim.startswith(line, '@@') then if vim.startswith(line, '@@') then
results[#results + 1] = gs_hunks.parse_diff_line(line) results[#results + 1] = Hunks.parse_diff_line(line)
elseif #results > 0 then elseif #results > 0 then
local r = results[#results] local r = results[#results]
if line:sub(1, 1) == '-' then if line:sub(1, 1) == '-' then

View File

@ -1,6 +1,7 @@
local async = require('gitsigns.async')
local create_hunk = require('gitsigns.hunks').create_hunk local create_hunk = require('gitsigns.hunks').create_hunk
local config = require('gitsigns.config').config local config = require('gitsigns.config').config
local async = require('gitsigns.async')
local M = {} local M = {}

View File

@ -1,15 +1,15 @@
local api = vim.api
local async = require('gitsigns.async') local async = require('gitsigns.async')
local cache = require('gitsigns.cache').cache
local util = require('gitsigns.util')
local manager = require('gitsigns.manager') local manager = require('gitsigns.manager')
local message = require('gitsigns.message') local message = require('gitsigns.message')
local util = require('gitsigns.util')
local Status = require('gitsigns.status') local Status = require('gitsigns.status')
local dprint = require('gitsigns.debug.log').dprint local cache = require('gitsigns.cache').cache
local log = require('gitsigns.debug.log')
local throttle_by_id = require('gitsigns.debounce').throttle_by_id local throttle_by_id = require('gitsigns.debounce').throttle_by_id
local api = vim.api
local M = {} local M = {}
--- @async --- @async
@ -17,7 +17,7 @@ local M = {}
--- @param dbufnr integer --- @param dbufnr integer
--- @param base string? --- @param base string?
local function bufread(bufnr, dbufnr, base) local function bufread(bufnr, dbufnr, base)
local bcache = cache[bufnr] local bcache = assert(cache[bufnr])
base = util.norm_base(base) base = util.norm_base(base)
local text --- @type string[] local text --- @type string[]
if base == bcache.git_obj.revision then if base == bcache.git_obj.revision then
@ -52,8 +52,9 @@ end
--- @param bufnr integer --- @param bufnr integer
--- @param dbufnr integer --- @param dbufnr integer
--- @param base string? --- @param base string?
local bufwrite = async.create(3, function(bufnr, dbufnr, base) --- @param _callback? fun()
local bcache = cache[bufnr] local bufwrite = async.create(3, function(bufnr, dbufnr, base, _callback)
local bcache = assert(cache[bufnr])
local buftext = util.buf_lines(dbufnr) local buftext = util.buf_lines(dbufnr)
base = util.norm_base(base) base = util.norm_base(base)
bcache.git_obj:stage_lines(buftext) bcache.git_obj:stage_lines(buftext)
@ -151,14 +152,17 @@ end
--- @param base string? --- @param base string?
--- @param opts Gitsigns.DiffthisOpts --- @param opts Gitsigns.DiffthisOpts
M.diffthis = async.create(2, function(base, opts) --- @param _callback? fun()
M.diffthis = async.create(2, function(base, opts, _callback)
if vim.wo.diff then if vim.wo.diff then
log.dprint('diff is disabled')
return return
end end
local bufnr = api.nvim_get_current_buf() local bufnr = api.nvim_get_current_buf()
local bcache = cache[bufnr] local bcache = cache[bufnr]
if not bcache then if not bcache then
log.dprintf('buffer %d is not attached', bufnr)
return return
end end
@ -176,16 +180,24 @@ end)
--- @param bufnr integer --- @param bufnr integer
--- @param base string --- @param base string
M.show = async.create(2, function(bufnr, base) --- @param _callback? fun()
M.show = async.create(2, function(bufnr, base, _callback)
__FUNC__ = 'show' __FUNC__ = 'show'
local bufname = create_show_buf(bufnr, base) local bufname = create_show_buf(bufnr, base)
if not bufname then if not bufname then
dprint('No bufname for revision ' .. base) log.dprint('No bufname for revision ' .. base)
return return
end end
dprint('bufname ' .. bufname) log.dprint('bufname ' .. bufname)
vim.cmd.edit(bufname) vim.cmd.edit(bufname)
-- Wait for the buffer to attach in case the user passes a callback that
-- requires the buffer to be attached.
local sbufnr = api.nvim_get_current_buf()
vim.wait(2000, function()
return cache[sbufnr] ~= nil
end)
end) end)
--- @param bufnr integer --- @param bufnr integer
@ -205,16 +217,15 @@ end
-- This function needs to be throttled as there is a call to vim.ui.input -- This function needs to be throttled as there is a call to vim.ui.input
--- @param bufnr integer --- @param bufnr integer
M.update = throttle_by_id(async.create(1, function(bufnr) --- @param _callback? fun()
M.update = throttle_by_id(async.create(1, function(bufnr, _callback)
if not vim.wo.diff then if not vim.wo.diff then
return return
end end
local bcache = cache[bufnr]
-- Note this will be the bufname for the currently set base -- Note this will be the bufname for the currently set base
-- which are the only ones we want to update -- which are the only ones we want to update
local bufname = bcache:get_rev_bufname() local bufname = assert(cache[bufnr]):get_rev_bufname()
for _, w in ipairs(api.nvim_list_wins()) do for _, w in ipairs(api.nvim_list_wins()) do
if api.nvim_win_is_valid(w) then if api.nvim_win_is_valid(w) then

View File

@ -1,25 +1,12 @@
local async = require('gitsigns.async')
local scheduler = require('gitsigns.async').scheduler
local log = require('gitsigns.debug.log') local log = require('gitsigns.debug.log')
local util = require('gitsigns.util') local util = require('gitsigns.util')
local system = require('gitsigns.system').system local Repo = require('gitsigns.git.repo')
local gs_config = require('gitsigns.config')
local config = gs_config.config
local uv = vim.uv or vim.loop
local dprint = log.dprint
local dprintf = log.dprintf
local error_once = require('gitsigns.message').error_once
local check_version = require('gitsigns.git.version').check local check_version = require('gitsigns.git.version').check
local M = {} local M = {}
--- @type fun(cmd: string[], opts?: vim.SystemOpts): vim.SystemCompleted M.Repo = Repo
local asystem = async.wrap(3, system)
--- @param file string --- @param file string
--- @return boolean --- @return boolean
@ -48,78 +35,7 @@ local Obj = {}
M.Obj = Obj M.Obj = Obj
--- @class Gitsigns.RepoInfo local git_command = require('gitsigns.git.cmd')
--- @field gitdir string
--- @field toplevel string
--- @field detached boolean
--- @field abbrev_head string
--- @class Gitsigns.Repo : Gitsigns.RepoInfo
--- @field username string
local Repo = {}
M.Repo = Repo
--- @class Gitsigns.Git.JobSpec : vim.SystemOpts
--- @field command? string
--- @field ignore_error? boolean
--- @async
--- @param args string[]
--- @param spec? Gitsigns.Git.JobSpec
--- @return string[] stdout, string? stderr
local function git_command(args, spec)
spec = spec or {}
local cmd = {
spec.command or 'git',
'--no-pager',
'--no-optional-locks',
'--literal-pathspecs',
'-c',
'gc.auto=0', -- Disable auto-packing which emits messages to stderr
unpack(args),
}
if spec.text == nil then
spec.text = true
end
-- Fix #895. Only needed for Nvim 0.9 and older
spec.clear_env = true
--- @type vim.SystemCompleted
local obj = asystem(cmd, spec)
local stdout = obj.stdout
local stderr = obj.stderr
if not spec.ignore_error and obj.code > 0 then
local cmd_str = table.concat(cmd, ' ')
log.eprintf("Received exit code %d when running command\n'%s':\n%s", obj.code, cmd_str, stderr)
end
local stdout_lines = vim.split(stdout or '', '\n')
if spec.text then
-- If stdout ends with a newline, then remove the final empty string after
-- the split
if stdout_lines[#stdout_lines] == '' then
stdout_lines[#stdout_lines] = nil
end
end
if log.verbose then
log.vprintf('%d lines:', #stdout_lines)
for i = 1, math.min(10, #stdout_lines) do
log.vprintf('\t%s', stdout_lines[i])
end
end
if stderr == '' then
stderr = nil
end
return stdout_lines, stderr
end
--- @async --- @async
--- @param file_cmp string --- @param file_cmp string
@ -145,224 +61,9 @@ function M.diff(file_cmp, file_buf, indent_heuristic, diff_algo)
}) })
end end
--- @async
--- @param gitdir string
--- @param head_str string
--- @param cwd string
--- @param cmd? string
--- @return string
local function process_abbrev_head(gitdir, head_str, cwd, cmd)
if not gitdir then
return head_str
end
if head_str == 'HEAD' then
local short_sha = git_command({ 'rev-parse', '--short', 'HEAD' }, {
command = cmd,
ignore_error = true,
cwd = cwd,
})[1] or ''
if log.debug_mode and short_sha ~= '' then
short_sha = 'HEAD'
end
if
util.path_exists(gitdir .. '/rebase-merge')
or util.path_exists(gitdir .. '/rebase-apply')
then
return short_sha .. '(rebasing)'
end
return short_sha
end
return head_str
end
local has_cygpath = jit and jit.os == 'Windows' and vim.fn.executable('cygpath') == 1
local cygpath_convert ---@type fun(path: string): string
if has_cygpath then
cygpath_convert = function(path)
--- @type vim.SystemCompleted
local obj = asystem({ 'cygpath', '-aw', path })
return obj.stdout
end
end
--- @param path string
--- @return string
local function normalize_path(path)
if path and has_cygpath and not uv.fs_stat(path) then
-- If on windows and path isn't recognizable as a file, try passing it
-- through cygpath
path = cygpath_convert(path)
end
return path
end
--- @async
--- @param cwd string
--- @param cmd? string
--- @param gitdir? string
--- @param toplevel? string
--- @return Gitsigns.RepoInfo
function M.get_repo_info(cwd, cmd, gitdir, toplevel)
-- Does git rev-parse have --absolute-git-dir, added in 2.13:
-- https://public-inbox.org/git/20170203024829.8071-16-szeder.dev@gmail.com/
local has_abs_gd = check_version({ 2, 13 })
local git_dir_opt = has_abs_gd and '--absolute-git-dir' or '--git-dir'
-- Wait for internal scheduler to settle before running command (#215)
scheduler()
local args = {}
if gitdir then
vim.list_extend(args, { '--git-dir', gitdir })
end
if toplevel then
vim.list_extend(args, { '--work-tree', toplevel })
end
vim.list_extend(args, {
'rev-parse',
'--show-toplevel',
git_dir_opt,
'--abbrev-ref',
'HEAD',
})
local results = git_command(args, {
command = cmd,
ignore_error = true,
cwd = toplevel or cwd,
})
local toplevel_r = normalize_path(results[1])
local gitdir_r = normalize_path(results[2])
if gitdir_r and not has_abs_gd then
gitdir_r = assert(uv.fs_realpath(gitdir_r))
end
return {
toplevel = toplevel_r,
gitdir = gitdir_r,
abbrev_head = process_abbrev_head(gitdir_r, results[3], cwd, cmd),
detached = toplevel_r and gitdir_r ~= toplevel_r .. '/.git',
}
end
--------------------------------------------------------------------------------
-- Git repo object methods
--------------------------------------------------------------------------------
--- Run git command the with the objects gitdir and toplevel
--- @async
--- @param args string[]
--- @param spec? Gitsigns.Git.JobSpec
--- @return string[] stdout, string? stderr
function Repo:command(args, spec)
spec = spec or {}
spec.cwd = self.toplevel
local args1 = {
'--git-dir',
self.gitdir,
}
if self.detached then
vim.list_extend(args1, { '--work-tree', self.toplevel })
end
vim.list_extend(args1, args)
return git_command(args1, spec)
end
--- @return string[]
function Repo:files_changed()
--- @type string[]
local results = self:command({ 'status', '--porcelain', '--ignore-submodules' })
local ret = {} --- @type string[]
for _, line in ipairs(results) do
if line:sub(1, 2):match('^.M') then
ret[#ret + 1] = line:sub(4, -1)
end
end
return ret
end
--- @param encoding string
--- @return boolean
local function iconv_supported(encoding)
-- TODO(lewis6991): needs https://github.com/neovim/neovim/pull/21924
if vim.startswith(encoding, 'utf-16') then
return false
elseif vim.startswith(encoding, 'utf-32') then
return false
end
return true
end
--- Get version of file in the index, return array lines
--- @param object string
--- @param encoding? string
--- @return string[] stdout, string? stderr
function Repo:get_show_text(object, encoding)
local stdout, stderr = self:command({ 'show', object }, { text = false, ignore_error = true })
if encoding and encoding ~= 'utf-8' and iconv_supported(encoding) then
for i, l in ipairs(stdout) do
--- @diagnostic disable-next-line:param-type-mismatch
stdout[i] = vim.iconv(l, encoding, 'utf-8')
end
end
return stdout, stderr
end
--- @async
function Repo:update_abbrev_head()
self.abbrev_head = M.get_repo_info(self.toplevel).abbrev_head
end
--- @async
--- @param dir string
--- @param gitdir? string
--- @param toplevel? string
--- @return Gitsigns.Repo
function Repo.new(dir, gitdir, toplevel)
local self = setmetatable({}, { __index = Repo })
self.username = git_command({ 'config', 'user.name' }, { ignore_error = true })[1]
local info = M.get_repo_info(dir, nil, gitdir, toplevel)
for k, v in
pairs(info --[[@as table<string,any>]])
do
---@diagnostic disable-next-line:no-unknown
self[k] = v
end
return self
end
--------------------------------------------------------------------------------
-- Git object methods
--------------------------------------------------------------------------------
--- Run git command the with the objects gitdir and toplevel
--- @param args string[]
--- @param spec? Gitsigns.Git.JobSpec
--- @return string[] stdout, string? stderr
function Obj:command(args, spec)
return self.repo:command(args, spec)
end
--- @param revision? string --- @param revision? string
function Obj:update_revision(revision) function Obj:update_revision(revision)
revision = util.norm_base(revision) self.revision = util.norm_base(revision)
self.revision = revision
self:update() self:update()
end end
@ -434,7 +135,7 @@ function Obj:file_info_index(file, silent)
cmd[#cmd + 1] = file or self.file cmd[#cmd + 1] = file or self.file
local results, stderr = self:command(cmd, { ignore_error = true }) local results, stderr = self.repo:command(cmd, { ignore_error = true })
if stderr and not silent then if stderr and not silent then
-- ignore_error for the cases when we run: -- ignore_error for the cases when we run:
@ -481,7 +182,7 @@ end
--- @param silent? boolean --- @param silent? boolean
--- @return Gitsigns.FileInfo --- @return Gitsigns.FileInfo
function Obj:file_info_tree(file, silent) function Obj:file_info_tree(file, silent)
local results, stderr = self:command({ local results, stderr = self.repo:command({
'-c', '-c',
'core.quotepath=off', 'core.quotepath=off',
'ls-tree', 'ls-tree',
@ -516,14 +217,14 @@ end
--- @return string[] stdout, string? stderr --- @return string[] stdout, string? stderr
function Obj:get_show_text(revision) function Obj:get_show_text(revision)
if revision and not self.relpath then if revision and not self.relpath then
dprint('no relpath') log.dprint('no relpath')
return {} return {}
end end
local object = revision and (revision .. ':' .. self.relpath) or self.object_name local object = revision and (revision .. ':' .. self.relpath) or self.object_name
if not object then if not object then
dprint('no revision or object_name') log.dprint('no revision or object_name')
return { '' } return { '' }
end end
@ -551,215 +252,17 @@ local function autocmd_changed(file)
end end
function Obj:unstage_file() function Obj:unstage_file()
self:command({ 'reset', self.file }) self.repo:command({ 'reset', self.file })
autocmd_changed(self.file) autocmd_changed(self.file)
end end
--- @class Gitsigns.CommitInfo
--- @field author string
--- @field author_mail string
--- @field author_time integer
--- @field author_tz string
--- @field committer string
--- @field committer_mail string
--- @field committer_time integer
--- @field committer_tz string
--- @field summary string
--- @field sha string
--- @field abbrev_sha string
--- @field boundary? true
--- @class Gitsigns.BlameInfoPublic: Gitsigns.BlameInfo, Gitsigns.CommitInfo
--- @field body? string[]
--- @field hunk_no? integer
--- @field num_hunks? integer
--- @field hunk? string[]
--- @field hunk_head? string
--- @class Gitsigns.BlameInfo
--- @field orig_lnum integer
--- @field final_lnum integer
--- @field commit Gitsigns.CommitInfo
--- @field filename string
--- @field previous_filename? string
--- @field previous_sha? string
local NOT_COMMITTED = {
author = 'Not Committed Yet',
author_mail = '<not.committed.yet>',
committer = 'Not Committed Yet',
committer_mail = '<not.committed.yet>',
}
--- @param file string
--- @return Gitsigns.CommitInfo
function M.not_committed(file)
local time = os.time()
return {
sha = string.rep('0', 40),
abbrev_sha = string.rep('0', 8),
author = 'Not Committed Yet',
author_mail = '<not.committed.yet>',
author_tz = '+0000',
author_time = time,
committer = 'Not Committed Yet',
committer_time = time,
committer_mail = '<not.committed.yet>',
committer_tz = '+0000',
summary = 'Version of ' .. file,
}
end
---@param x any
---@return integer
local function asinteger(x)
return assert(tonumber(x))
end
--- @param lines string[] --- @param lines string[]
--- @param lnum? integer --- @param lnum? integer
--- @param revision? string
--- @param opts? Gitsigns.BlameOpts --- @param opts? Gitsigns.BlameOpts
--- @return table<integer,Gitsigns.BlameInfo?>? --- @return table<integer,Gitsigns.BlameInfo?>
function Obj:run_blame(lines, lnum, opts) function Obj:run_blame(lines, lnum, revision, opts)
local ret = {} --- @type table<integer,Gitsigns.BlameInfo> return require('gitsigns.git.blame').run_blame(self, lines, lnum, revision, opts)
if not self.object_name or self.repo.abbrev_head == '' then
-- As we support attaching to untracked files we need to return something if
-- the file isn't isn't tracked in git.
-- If abbrev_head is empty, then assume the repo has no commits
local commit = M.not_committed(self.file)
for i in ipairs(lines) do
ret[i] = {
orig_lnum = 0,
final_lnum = i,
commit = commit,
filename = self.file,
}
end
return ret
end
local args = { 'blame', '--contents', '-', '--incremental' }
opts = opts or {}
if opts.ignore_whitespace then
args[#args + 1] = '-w'
end
if lnum then
vim.list_extend(args, { '-L', lnum .. ',+1' })
end
if opts.extra_opts then
vim.list_extend(args, opts.extra_opts)
end
local ignore_file = self.repo.toplevel .. '/.git-blame-ignore-revs'
if uv.fs_stat(ignore_file) then
vim.list_extend(args, { '--ignore-revs-file', ignore_file })
end
args[#args + 1] = opts.rev
args[#args + 1] = '--'
args[#args + 1] = self.file
local results, stderr = self:command(args, { stdin = lines, ignore_error = true })
if stderr then
error_once('Error running git-blame: ' .. stderr)
return
end
if #results == 0 then
return
end
local commits = {} --- @type table<string,Gitsigns.CommitInfo>
local i = 1
while i <= #results do
--- @param pat? string
--- @return string
local function get(pat)
local l = assert(results[i])
i = i + 1
if pat then
return l:match(pat)
end
return l
end
local function peek(pat)
local l = results[i]
if l and pat then
return l:match(pat)
end
return l
end
local sha, orig_lnum_str, final_lnum_str, size_str = get('(%x+) (%d+) (%d+) (%d+)')
local orig_lnum = asinteger(orig_lnum_str)
local final_lnum = asinteger(final_lnum_str)
local size = asinteger(size_str)
if peek():match('^author ') then
--- @type table<string,string|true>
local commit = {
sha = sha,
abbrev_sha = sha:sub(1, 8),
}
-- filename terminates the entry
while peek() and not (peek():match('^filename ') or peek():match('^previous ')) do
local l = get()
local key, value = l:match('^([^%s]+) (.*)')
if key then
if vim.endswith(key, '_time') then
value = tonumber(value)
end
key = key:gsub('%-', '_') --- @type string
commit[key] = value
else
commit[l] = true
if l ~= 'boundary' then
dprintf("Unknown tag: '%s'", l)
end
end
end
-- New in git 2.41:
-- The output given by "git blame" that attributes a line to contents
-- taken from the file specified by the "--contents" option shows it
-- differently from a line attributed to the working tree file.
if
commit.author_mail == '<external.file>'
or commit.author_mail == 'External file (--contents)'
then
commit = vim.tbl_extend('force', commit, NOT_COMMITTED)
end
commits[sha] = commit
end
local previous_sha, previous_filename = peek():match('^previous (%x+) (.*)')
if previous_sha then
get()
end
local filename = assert(get():match('^filename (.*)'))
for j = 0, size - 1 do
ret[final_lnum + j] = {
final_lnum = final_lnum + j,
orig_lnum = orig_lnum + j,
commit = commits[sha],
filename = filename,
previous_filename = previous_filename,
previous_sha = previous_sha,
}
end
end
return ret
end end
--- @param obj Gitsigns.GitObj --- @param obj Gitsigns.GitObj
@ -770,12 +273,12 @@ local function ensure_file_in_index(obj)
if not obj.object_name then if not obj.object_name then
-- If there is no object_name then it is not yet in the index so add it -- If there is no object_name then it is not yet in the index so add it
obj:command({ 'add', '--intent-to-add', obj.file }) obj.repo:command({ 'add', '--intent-to-add', obj.file })
else else
-- Update the index with the common ancestor (stage 1) which is what bcache -- Update the index with the common ancestor (stage 1) which is what bcache
-- stores -- stores
local info = string.format('%s,%s,%s', obj.mode_bits, obj.object_name, obj.relpath) local info = string.format('%s,%s,%s', obj.mode_bits, obj.object_name, obj.relpath)
obj:command({ 'update-index', '--add', '--cacheinfo', info }) obj.repo:command({ 'update-index', '--add', '--cacheinfo', info })
end end
obj:update() obj:update()
@ -784,17 +287,15 @@ end
--- Stage 'lines' as the entire contents of the file --- Stage 'lines' as the entire contents of the file
--- @param lines string[] --- @param lines string[]
function Obj:stage_lines(lines) function Obj:stage_lines(lines)
local stdout = self:command({ local new_object = self.repo:command({
'hash-object', 'hash-object',
'-w', '-w',
'--path', '--path',
self.relpath, self.relpath,
'--stdin', '--stdin',
}, { stdin = lines }) }, { stdin = lines })[1]
local new_object = stdout[1] self.repo:command({
self:command({
'update-index', 'update-index',
'--cacheinfo', '--cacheinfo',
string.format('%s,%s,%s', self.mode_bits, new_object, self.relpath), string.format('%s,%s,%s', self.mode_bits, new_object, self.relpath),
@ -808,9 +309,7 @@ end
function Obj:stage_hunks(hunks, invert) function Obj:stage_hunks(hunks, invert)
ensure_file_in_index(self) ensure_file_in_index(self)
local gs_hunks = require('gitsigns.hunks') local patch = require('gitsigns.hunks').create_patch(self.relpath, hunks, self.mode_bits, invert)
local patch = gs_hunks.create_patch(self.relpath, hunks, self.mode_bits, invert)
if not self.i_crlf and self.w_crlf then if not self.i_crlf and self.w_crlf then
-- Remove cr -- Remove cr
@ -819,7 +318,7 @@ function Obj:stage_hunks(hunks, invert)
end end
end end
self:command({ self.repo:command({
'apply', 'apply',
'--whitespace=nowarn', '--whitespace=nowarn',
'--cached', '--cached',
@ -834,7 +333,7 @@ end
--- @return string? --- @return string?
function Obj:has_moved() function Obj:has_moved()
local out = self:command({ 'diff', '--name-status', '-C', '--cached' }) local out = self.repo:command({ 'diff', '--name-status', '-C', '--cached' })
local orig_relpath = self.orig_relpath or self.relpath local orig_relpath = self.orig_relpath or self.relpath
for _, l in ipairs(out) do for _, l in ipairs(out) do
local parts = vim.split(l, '%s+') local parts = vim.split(l, '%s+')
@ -858,24 +357,25 @@ end
--- @return Gitsigns.GitObj? --- @return Gitsigns.GitObj?
function Obj.new(file, revision, encoding, gitdir, toplevel) function Obj.new(file, revision, encoding, gitdir, toplevel)
if in_git_dir(file) then if in_git_dir(file) then
dprint('In git dir') log.dprint('In git dir')
return nil return nil
end end
local self = setmetatable({}, { __index = Obj })
if not vim.startswith(file, '/') and toplevel then if not vim.startswith(file, '/') and toplevel then
file = toplevel .. util.path_sep .. file file = toplevel .. util.path_sep .. file
end end
local repo = Repo.get(util.dirname(file), gitdir, toplevel)
if not repo then
log.dprint('Not in git repo')
return
end
local self = setmetatable({}, { __index = Obj })
self.repo = repo
self.file = file self.file = file
self.revision = util.norm_base(revision) self.revision = util.norm_base(revision)
self.encoding = encoding self.encoding = encoding
self.repo = Repo.new(util.dirname(file), gitdir, toplevel)
if not self.repo.gitdir then
dprint('Not in git repo')
return nil
end
-- When passing gitdir and toplevel, suppress stderr when resolving the file -- When passing gitdir and toplevel, suppress stderr when resolving the file
local silent = gitdir ~= nil and toplevel ~= nil local silent = gitdir ~= nil and toplevel ~= nil

View File

@ -135,6 +135,48 @@ M.hls = {
}, },
}, },
{
GitSignsAddCul = {
'GitSignsAdd',
desc = "Used for the text of 'add' signs when the cursor is on the same line as the sign.",
},
},
{
GitSignsChangeCul = {
'GitSignsChange',
desc = "Used for the text of 'change' signs when the cursor is on the same line as the sign.",
},
},
{
GitSignsDeleteCul = {
'GitSignsDelete',
desc = "Used for the text of 'delete' signs when the cursor is on the same line as the sign.",
},
},
{
GitSignsChangedeleteCul = {
'GitSignsChangeCul',
desc = "Used for the text of 'changedelete' signs when the cursor is on the same line as the sign.",
},
},
{
GitSignsTopdeleteCul = {
'GitSignsDeleteCul',
desc = "Used for the text of 'topdelete' signs when the cursor is on the same line as the sign.",
},
},
{
GitSignsUntrackedCul = {
'GitSignsAddCul',
desc = "Used for the text of 'untracked' signs when the cursor is on the same line as the sign.",
},
},
-- Don't set GitSignsDeleteLn by default -- Don't set GitSignsDeleteLn by default
-- {GitSignsDeleteLn = {}}, -- {GitSignsDeleteLn = {}},
@ -153,6 +195,11 @@ M.hls = {
{ GitSignsStagedDeleteLn = { 'GitSignsDeleteLn', fg_factor = 0.5, hidden = true } }, { GitSignsStagedDeleteLn = { 'GitSignsDeleteLn', fg_factor = 0.5, hidden = true } },
{ GitSignsStagedChangedeleteLn = { 'GitSignsChangedeleteLn', fg_factor = 0.5, hidden = true } }, { GitSignsStagedChangedeleteLn = { 'GitSignsChangedeleteLn', fg_factor = 0.5, hidden = true } },
{ GitSignsStagedTopdeleteLn = { 'GitSignsTopdeleteLn', fg_factor = 0.5, hidden = true } }, { GitSignsStagedTopdeleteLn = { 'GitSignsTopdeleteLn', fg_factor = 0.5, hidden = true } },
{ GitSignsStagedAddCul = { 'GitSignsAddCul', fg_factor = 0.5, hidden = true } },
{ GitSignsStagedChangeCul = { 'GitSignsChangeCul', fg_factor = 0.5, hidden = true } },
{ GitSignsStagedDeleteCul = { 'GitSignsDeleteCul', fg_factor = 0.5, hidden = true } },
{ GitSignsStagedChangedeleteCul = { 'GitSignsChangedeleteCul', fg_factor = 0.5, hidden = true } },
{ GitSignsStagedTopdeleteCul = { 'GitSignsTopdeleteCul', fg_factor = 0.5, hidden = true } },
{ {
GitSignsAddPreview = { GitSignsAddPreview = {

View File

@ -1,22 +1,15 @@
local async = require('gitsigns.async') local async = require('gitsigns.async')
local log = require('gitsigns.debug.log')
local gs_cache = require('gitsigns.cache') local util = require('gitsigns.util')
local cache = gs_cache.cache local run_diff = require('gitsigns.diff')
local Hunks = require('gitsigns.hunks')
local Signs = require('gitsigns.signs') local Signs = require('gitsigns.signs')
local Status = require('gitsigns.status') local Status = require('gitsigns.status')
local debounce_trailing = require('gitsigns.debounce').debounce_trailing local debounce_trailing = require('gitsigns.debounce').debounce_trailing
local throttle_by_id = require('gitsigns.debounce').throttle_by_id local throttle_by_id = require('gitsigns.debounce').throttle_by_id
local log = require('gitsigns.debug.log') local cache = require('gitsigns.cache').cache
local dprint = log.dprint
local util = require('gitsigns.util')
local run_diff = require('gitsigns.diff')
local gs_hunks = require('gitsigns.hunks')
local config = require('gitsigns.config').config local config = require('gitsigns.config').config
local api = vim.api local api = vim.api
@ -31,7 +24,7 @@ local M = {}
--- @param hunks Gitsigns.Hunk.Hunk[] --- @param hunks Gitsigns.Hunk.Hunk[]
--- @param top integer --- @param top integer
--- @param bot integer --- @param bot integer
--- @param clear boolean --- @param clear? boolean
--- @param untracked boolean --- @param untracked boolean
local function apply_win_signs0(bufnr, signs, hunks, top, bot, clear, untracked) local function apply_win_signs0(bufnr, signs, hunks, top, bot, clear, untracked)
if clear then if clear then
@ -47,14 +40,11 @@ local function apply_win_signs0(bufnr, signs, hunks, top, bot, clear, untracked)
-- least one sign. Only do this on the first call after an update when we all -- least one sign. Only do this on the first call after an update when we all
-- the signs have been cleared. -- the signs have been cleared.
if clear and i == 1 then if clear and i == 1 then
signs:add( signs:add(bufnr, Hunks.calc_signs(hunk, next, hunk.added.start, hunk.added.start, untracked))
bufnr,
gs_hunks.calc_signs(hunk, next, hunk.added.start, hunk.added.start, untracked)
)
end end
if top <= hunk.vend and bot >= hunk.added.start then if top <= hunk.vend and bot >= hunk.added.start then
signs:add(bufnr, gs_hunks.calc_signs(hunk, next, top, bot, untracked)) signs:add(bufnr, Hunks.calc_signs(hunk, next, top, bot, untracked))
end end
if hunk.added.start > bot then if hunk.added.start > bot then
break break
@ -65,13 +55,9 @@ end
--- @param bufnr integer --- @param bufnr integer
--- @param top integer --- @param top integer
--- @param bot integer --- @param bot integer
--- @param clear boolean --- @param clear? boolean
local function apply_win_signs(bufnr, top, bot, clear) local function apply_win_signs(bufnr, top, bot, clear)
local bcache = cache[bufnr] local bcache = assert(cache[bufnr])
if not bcache then
return
end
local untracked = bcache.git_obj.object_name == nil local untracked = bcache.git_obj.object_name == nil
apply_win_signs0(bufnr, signs_normal, bcache.hunks, top, bot, clear, untracked) apply_win_signs0(bufnr, signs_normal, bcache.hunks, top, bot, clear, untracked)
if signs_staged then if signs_staged then
@ -88,15 +74,13 @@ local function on_lines_blame(blame, first, last_orig, last_new)
return return
end end
if last_new ~= last_orig then if last_new < last_orig then
if last_new < last_orig then util.list_remove(blame, last_new + 1, last_orig)
util.list_remove(blame, last_new, last_orig) elseif last_new > last_orig then
else util.list_insert(blame, last_orig + 1, last_new)
util.list_insert(blame, last_orig, last_new)
end
end end
for i = math.min(first + 1, last_new), math.max(first + 1, last_new) do for i = first + 1, last_new do
blame[i] = nil blame[i] = nil
end end
end end
@ -109,7 +93,7 @@ end
function M.on_lines(buf, first, last_orig, last_new) function M.on_lines(buf, first, last_orig, last_new)
local bcache = cache[buf] local bcache = cache[buf]
if not bcache then if not bcache then
dprint('Cache for buffer was nil. Detaching') log.dprint('Cache for buffer was nil. Detaching')
return true return true
end end
@ -161,7 +145,7 @@ local function apply_word_diff(bufnr, row)
local lnum = row + 1 local lnum = row + 1
local hunk = gs_hunks.find_hunk(lnum, bcache.hunks) local hunk = Hunks.find_hunk(lnum, bcache.hunks)
if not hunk then if not hunk then
-- No hunk at line -- No hunk at line
return return
@ -320,7 +304,7 @@ function M.show_deleted_in_float(bufnr, nsd, hunk, staged)
virt_lines_leftcol = true, virt_lines_leftcol = true,
}) })
local bcache = cache[bufnr] local bcache = assert(cache[bufnr])
local pbufnr = api.nvim_create_buf(false, true) local pbufnr = api.nvim_create_buf(false, true)
local text = staged and bcache.compare_text_head or bcache.compare_text local text = staged and bcache.compare_text_head or bcache.compare_text
api.nvim_buf_set_lines(pbufnr, 0, -1, false, assert(text)) api.nvim_buf_set_lines(pbufnr, 0, -1, false, assert(text))
@ -422,7 +406,7 @@ end
--- @param bufnr integer --- @param bufnr integer
local function update_show_deleted(bufnr) local function update_show_deleted(bufnr)
local bcache = cache[bufnr] local bcache = assert(cache[bufnr])
clear_deleted(bufnr) clear_deleted(bufnr)
if config.show_deleted then if config.show_deleted then
@ -440,15 +424,15 @@ end
function M.schedule(bufnr, check_compare_text) function M.schedule(bufnr, check_compare_text)
async.scheduler() async.scheduler()
if not api.nvim_buf_is_valid(bufnr) then if not api.nvim_buf_is_valid(bufnr) then
dprint('Buffer not valid, aborting') log.dprint('Buffer not valid, aborting')
return false return false
end end
if not cache[bufnr] then if not cache[bufnr] then
dprint('Has detached, aborting') log.dprint('Has detached, aborting')
return false return false
end end
if check_compare_text and not cache[bufnr].compare_text then if check_compare_text and not cache[bufnr].compare_text then
dprint('compare_text was invalid, aborting') log.dprint('compare_text was invalid, aborting')
return false return false
end end
return true return true
@ -463,7 +447,7 @@ M.update = throttle_by_id(function(bufnr)
if not M.schedule(bufnr) then if not M.schedule(bufnr) then
return return
end end
local bcache = cache[bufnr] local bcache = assert(cache[bufnr])
local old_hunks, old_hunks_staged = bcache.hunks, bcache.hunks_staged local old_hunks, old_hunks_staged = bcache.hunks, bcache.hunks_staged
bcache.hunks, bcache.hunks_staged = nil, nil bcache.hunks, bcache.hunks_staged = nil, nil
@ -500,15 +484,15 @@ M.update = throttle_by_id(function(bufnr)
if not M.schedule(bufnr) then if not M.schedule(bufnr) then
return return
end end
bcache.hunks_staged = gs_hunks.filter_common(hunks_head, bcache.hunks) bcache.hunks_staged = Hunks.filter_common(hunks_head, bcache.hunks)
end end
-- Note the decoration provider may have invalidated bcache.hunks at this -- Note the decoration provider may have invalidated bcache.hunks at this
-- point -- point
if if
bcache.force_next_update bcache.force_next_update
or gs_hunks.compare_heads(bcache.hunks, old_hunks) or Hunks.compare_heads(bcache.hunks, old_hunks)
or gs_hunks.compare_heads(bcache.hunks_staged, old_hunks_staged) or Hunks.compare_heads(bcache.hunks_staged, old_hunks_staged)
then then
-- Apply signs to the window. Other signs will be added by the decoration -- Apply signs to the window. Other signs will be added by the decoration
-- provider as they are drawn. -- provider as they are drawn.
@ -517,7 +501,7 @@ M.update = throttle_by_id(function(bufnr)
update_show_deleted(bufnr) update_show_deleted(bufnr)
bcache.force_next_update = false bcache.force_next_update = false
local summary = gs_hunks.get_summary(bcache.hunks) local summary = Hunks.get_summary(bcache.hunks)
summary.head = git_obj.repo.abbrev_head summary.head = git_obj.repo.abbrev_head
Status:update(bufnr, summary) Status:update(bufnr, summary)
end end
@ -558,7 +542,7 @@ local function on_win(_cb, _winid, bufnr, topline, botline_guess)
end end
local botline = math.min(botline_guess, api.nvim_buf_line_count(bufnr)) local botline = math.min(botline_guess, api.nvim_buf_line_count(bufnr))
apply_win_signs(bufnr, topline + 1, botline + 1, false) apply_win_signs(bufnr, topline + 1, botline + 1)
if not (config.word_diff and config.diff_opts.internal) then if not (config.word_diff and config.diff_opts.internal) then
return false return false

View File

@ -1,7 +1,7 @@
local M = {}
local api = vim.api local api = vim.api
local M = {}
--- @param bufnr integer --- @param bufnr integer
--- @param lines string[] --- @param lines string[]
--- @return integer --- @return integer

View File

@ -65,6 +65,7 @@ function M:add(bufnr, signs)
sign_hl_group = hls.hl, sign_hl_group = hls.hl,
number_hl_group = config.numhl and hls.numhl or nil, number_hl_group = config.numhl and hls.numhl or nil,
line_hl_group = config.linehl and hls.linehl or nil, line_hl_group = config.linehl and hls.linehl or nil,
cursorline_hl_group = config.culhl and hls.culhl or nil,
}) })
if not ok and config.debug_mode then if not ok and config.debug_mode then

View File

@ -327,7 +327,7 @@ end
---@param first integer ---@param first integer
---@param last integer ---@param last integer
function M.list_remove(t, first, last) function M.list_remove(t, first, last)
local n = #t local n = table.maxn(t)
for i = 0, n - first do for i = 0, n - first do
t[first + i] = t[last + 1 + i] t[first + i] = t[last + 1 + i]
t[last + 1 + i] = nil t[last + 1 + i] = nil
@ -347,7 +347,7 @@ end
---@param last integer ---@param last integer
---@param v any ---@param v any
function M.list_insert(t, first, last, v) function M.list_insert(t, first, last, v)
local n = #t local n = table.maxn(t)
-- Shift table forward -- Shift table forward
for i = n - first, 0, -1 do for i = n - first, 0, -1 do

View File

@ -1,10 +1,10 @@
local api = vim.api local api = vim.api
local uv = vim.loop local uv = vim.loop
local Status = require('gitsigns.status')
local async = require('gitsigns.async') local async = require('gitsigns.async')
local log = require('gitsigns.debug.log') local log = require('gitsigns.debug.log')
local util = require('gitsigns.util') local util = require('gitsigns.util')
local Status = require('gitsigns.status')
local cache = require('gitsigns.cache').cache local cache = require('gitsigns.cache').cache
local config = require('gitsigns.config').config local config = require('gitsigns.config').config
@ -18,7 +18,7 @@ local dprintf = log.dprintf
--- @param bufnr integer --- @param bufnr integer
--- @param old_relpath string --- @param old_relpath string
local function handle_moved(bufnr, old_relpath) local function handle_moved(bufnr, old_relpath)
local bcache = cache[bufnr] local bcache = assert(cache[bufnr])
local git_obj = bcache.git_obj local git_obj = bcache.git_obj
local new_name = git_obj:has_moved() local new_name = git_obj:has_moved()
@ -73,6 +73,7 @@ local function watcher_handler0(bufnr)
-- Avoid cache hit for detached buffer -- Avoid cache hit for detached buffer
-- ref: https://github.com/lewis6991/gitsigns.nvim/issues/956 -- ref: https://github.com/lewis6991/gitsigns.nvim/issues/956
if not manager.schedule(bufnr) then if not manager.schedule(bufnr) then
dprint('buffer invalid (1)')
return return
end end
@ -81,6 +82,7 @@ local function watcher_handler0(bufnr)
git_obj.repo:update_abbrev_head() git_obj.repo:update_abbrev_head()
if not manager.schedule(bufnr) then if not manager.schedule(bufnr) then
dprint('buffer invalid (2)')
return return
end end
@ -91,6 +93,7 @@ local function watcher_handler0(bufnr)
git_obj:update() git_obj:update()
if not manager.schedule(bufnr) then if not manager.schedule(bufnr) then
dprint('buffer invalid (3)')
return return
end end
@ -99,6 +102,7 @@ local function watcher_handler0(bufnr)
-- moved. Check if it was moved and switch to it. -- moved. Check if it was moved and switch to it.
handle_moved(bufnr, old_relpath) handle_moved(bufnr, old_relpath)
if not manager.schedule(bufnr) then if not manager.schedule(bufnr) then
dprint('buffer invalid (4)')
return return
end end
end end
@ -108,9 +112,12 @@ local function watcher_handler0(bufnr)
require('gitsigns.manager').update(bufnr) require('gitsigns.manager').update(bufnr)
end end
--- Debounce and throttle the handler. --- Debounce to:
--- We also throttle in case the debounce delay is not enough and to prevent --- - wait for all changes to the gitdir to complete.
--- too many handlers from being launched (and interleaved). --- Throttle to:
--- - ensure handler is only triggered once per git operation.
--- - prevent updates to the same buffer from interleaving as the handler is
--- async.
local watcher_handler = local watcher_handler =
debounce_trailing(200, async.create(1, throttle_by_id(watcher_handler0, true)), 1) debounce_trailing(200, async.create(1, throttle_by_id(watcher_handler0, true)), 1)
@ -123,11 +130,6 @@ end
local M = {} local M = {}
local WATCH_IGNORE = {
ORIG_HEAD = true,
FETCH_HEAD = true,
}
--- @param bufnr integer --- @param bufnr integer
--- @param gitdir string --- @param gitdir string
--- @return uv.uv_fs_event_t --- @return uv.uv_fs_event_t
@ -141,17 +143,15 @@ function M.watch_gitdir(bufnr, gitdir)
return return
end end
local info = string.format("Git dir update: '%s' %s", filename, inspect(events))
-- The luv docs say filename is passed as a string but it has been observed -- The luv docs say filename is passed as a string but it has been observed
-- to sometimes be nil. -- to sometimes be nil.
-- https://github.com/lewis6991/gitsigns.nvim/issues/848 -- https://github.com/lewis6991/gitsigns.nvim/issues/848
if filename == nil or WATCH_IGNORE[filename] or vim.endswith(filename, '.lock') then if not filename then
dprintf('%s (ignoring)', info) log.eprint('No filename')
return return
end end
dprint(info) dprintf("Git dir update: '%s' %s", filename, inspect(events))
watcher_handler(bufnr) watcher_handler(bufnr)
end) end)

View File

@ -1 +1 @@
/nix/store/3czmrawji85vf8979kll2yx2f1kjkric-lua-5.1.5 /nix/store/rn8bzg423wwkayzbsbmhmvcgjmbzrq5z-lua-5.1.5

View File

@ -1,50 +1,53 @@
rock_manifest = { rock_manifest = {
doc = { doc = {
["gitsigns.txt"] = "e537e0db7825ce01a1c568a124432989" ["gitsigns.txt"] = "ed2c2a9eac117833753afc9dd55adcf4"
}, },
["gitsigns.nvim-scm-1.rockspec"] = "a9b165d604ce401cfeea760a9366418d", ["gitsigns.nvim-scm-1.rockspec"] = "a9b165d604ce401cfeea760a9366418d",
lua = { lua = {
gitsigns = { gitsigns = {
["actions.lua"] = "accecf1db114ace88739c40835cb5a77", ["actions.lua"] = "ac0661d45e50424f5f59924528b1c031",
["async.lua"] = "15f310cd469f5bfa46bb1e49e5a1d61c", ["async.lua"] = "ab34c767e5b6c917335d19f2acc6fd36",
["attach.lua"] = "6f81186d03fbde2ddc631c46fea09315", ["attach.lua"] = "44664690d66389b4487d934ebcad98e6",
["blame.lua"] = "e8388c8b29982475bfccec28ea4f72be", ["blame.lua"] = "05feea95e221a2409a8d44334c47529f",
["cache.lua"] = "a084b897b3af2f3603a018f4c00c20fa", ["cache.lua"] = "523c72aa06168f06b3ecd34fd04cbe9d",
cli = { cli = {
["argparse.lua"] = "fb6c9ffda01b2090f3c252ecaf00f68a" ["argparse.lua"] = "fb6c9ffda01b2090f3c252ecaf00f68a"
}, },
["cli.lua"] = "f00c3494d6be1b07c352c51132150586", ["cli.lua"] = "00273191aa1ca467c5edbd9531f8fd9d",
["config.lua"] = "ef58f99d7782297a32e3867634906738", ["config.lua"] = "8743742b5a5b0a0713f0352ff4e88db0",
["current_line_blame.lua"] = "b1e920875977e12bb4f9f6be08a92db8", ["current_line_blame.lua"] = "48e477d836e39ab98e58c2b027dd9db8",
["debounce.lua"] = "e0c1145a3dc341f46b36b43d814c1202", ["debounce.lua"] = "5a28036b5ac45c1f93f9883b855e564f",
debug = { debug = {
["log.lua"] = "f7e994b68e9cbcf91adfeb5bc379d7b1" ["log.lua"] = "f7e994b68e9cbcf91adfeb5bc379d7b1"
}, },
["debug.lua"] = "6a819b17a531b74ee11622145097afae", ["debug.lua"] = "6a819b17a531b74ee11622145097afae",
["diff.lua"] = "0c462ae71c77899e81da151dcfdf77eb", ["diff.lua"] = "0c462ae71c77899e81da151dcfdf77eb",
["diff_ext.lua"] = "04005195067132403fc336422e05c7d3", ["diff_ext.lua"] = "31454455cd645f1518d8363446e8d0f6",
["diff_int.lua"] = "df447e56f11906998e81d5b94499e013", ["diff_int.lua"] = "8e73883f55811dcb68ad481d389aa687",
["diffthis.lua"] = "b91c6a177c0a80c5e611b8c09f6eb46e", ["diffthis.lua"] = "aaac58016e9982bb14e942f9e4e24c52",
git = { git = {
["blame.lua"] = "e779f4344bcc41cdb92c1a1be5eb2815",
["cmd.lua"] = "449c03c67b7ae516babc41d6da0dc66e",
["repo.lua"] = "1efe3178f64b77e0fc22cad55d9586a0",
["version.lua"] = "068a582ed4565978eb1f6eb089a6fa6c" ["version.lua"] = "068a582ed4565978eb1f6eb089a6fa6c"
}, },
["git.lua"] = "8a216cac54214508e798c7f4b920dd36", ["git.lua"] = "0d3e8859ff8cf7ebd3beb739b64a8c49",
["highlight.lua"] = "f1966ef758f9a0a86102a699ec7a1eca", ["highlight.lua"] = "f0bf039b629818fbfae8a6fad161f9a2",
["hunks.lua"] = "ee058ee8b056b055cd8404460ca6921f", ["hunks.lua"] = "ee058ee8b056b055cd8404460ca6921f",
["manager.lua"] = "527083250ad693ee4faa5e4dde47f275", ["manager.lua"] = "f6e7e2430f2f28a4dbcfd2479f2c8480",
["message.lua"] = "523ee4df9da4a7fa9b5ab2100eb27ac4", ["message.lua"] = "523ee4df9da4a7fa9b5ab2100eb27ac4",
["popup.lua"] = "cbc11678e30094bff8ed54f0357e26f9", ["popup.lua"] = "2fcf3052f95d81cb5c0bb04ca4e06aae",
["repeat.lua"] = "798544de97c774bc8e10eecfd6479585", ["repeat.lua"] = "798544de97c774bc8e10eecfd6479585",
["signs.lua"] = "9224bcde01ebd0c320bcd678822fc799", ["signs.lua"] = "a22dd6943d762dffcdbb8d2db4d885bb",
["status.lua"] = "a229a7213a3fbecfcf2d98aaf587fcab", ["status.lua"] = "a229a7213a3fbecfcf2d98aaf587fcab",
system = { system = {
["compat.lua"] = "05d2b6d08602fba46be9b540288091e7" ["compat.lua"] = "05d2b6d08602fba46be9b540288091e7"
}, },
["system.lua"] = "d73fac4f6e734cc8ce9f13d6be027503", ["system.lua"] = "d73fac4f6e734cc8ce9f13d6be027503",
["test.lua"] = "082f7c7a556bf27352a378d047b8e79b", ["test.lua"] = "082f7c7a556bf27352a378d047b8e79b",
["util.lua"] = "b24bac967bc60ba1434bf5cd7cf3fc98", ["util.lua"] = "d30ad092850bd48a1446ce069320f5a7",
["watcher.lua"] = "034303cfa063c77bb6628f1a55d559c4" ["watcher.lua"] = "978875698d84bc1f715c55fefa72bcc1"
}, },
["gitsigns.lua"] = "784d1b15d5970f0177fd19d163ea9dfb" ["gitsigns.lua"] = "bf3f49482d8340f4be41060d7f461fd1"
} }
} }

View File

@ -37,208 +37,268 @@ HaskellTools *HaskellTools*
plugin configuration *haskell-tools.config* plugin configuration *haskell-tools.config*
To configure haskell-tools.nvim, set the variable `vim.g.haskell_tools`, To configure haskell-tools.nvim, set the variable `vim.g.haskell_tools`,
which is a `HTOpts` table, in your neovim configuration. which is a `haskell-tools.Opts` table, in your neovim configuration.
Example: Example:
> >
---@type HTOpts ---@type haskell-tools.Opts
vim.g.haskell_tools = { vim.g.haskell_tools = {
---@type ToolsOpts ---@type haskell-tools.tools.Opts
tools = { tools = {
-- ... -- ...
}, },
---@type HaskellLspClientOpts ---@type haskell-tools.lsp.ClientOpts
hls = { hls = {
on_attach = function(client, bufnr) on_attach = function(client, bufnr)
-- Set keybindings, etc. here. -- Set keybindings, etc. here.
end, end,
-- ... -- ...
}, },
---@type HTDapOpts ---@type haskell-tools.dap.Opts
dap = { dap = {
-- ... -- ...
}, },
} }
< <
Note: `vim.g.haskell_tools` can also be a function that returns a 'HTOpts' table. Note: `vim.g.haskell_tools` can also be a function that returns a 'haskell-tools.Opts' table.
HTOpts *HTOpts* haskell-tools.Opts *haskell-tools.Opts*
Fields: ~ Fields: ~
{tools?} (ToolsOpts) haskell-tools module options. {tools?} (haskell-tools.tools.Opts)
{hls?} (HaskellLspClientOpts) haskell-language-server client options. haskell-tools module options.
{dap?} (HTDapOpts) debug adapter config for nvim-dap. {hls?} (haskell-tools.lsp.ClientOpts)
haskell-language-server client options.
{dap?} (haskell-tools.dap.Opts)
debug adapter config for nvim-dap.
ToolsOpts *ToolsOpts* haskell-tools.tools.Opts *haskell-tools.tools.Opts*
Fields: ~ Fields: ~
{codeLens?} (CodeLensOpts) LSP codeLens options. {codeLens?} (haskell-tools.codeLens.Opts)
{hoogle?} (HoogleOpts) Hoogle type signature search options. LSP codeLens options.
{hover?} (HoverOpts) LSP hover options. {hoogle?} (haskell-tools.hoogle.Opts)
{definition?} (DefinitionOpts) LSP go-to-definition options. Hoogle type signature search options.
{repl?} (ReplOpts) GHCi repl options. {hover?} (haskell-tools.hover.Opts)
{tags?} (FastTagsOpts) fast-tags module options. LSP hover options.
{log?} (HTLogOpts) haskell-tools logger options. {definition?} (haskell-tools.definition.Opts) LSP go-to-definition options.
{repl?} (haskell-tools.repl.Opts)
GHCi repl options.
{tags?} (haskell-tools.fast-tags.Opts)
fast-tags module options.
{log?} (haskell-tools.log.Opts)
haskell-tools logger options.
CodeLensOpts *CodeLensOpts* haskell-tools.codeLens.Opts *haskell-tools.codeLens.Opts*
Fields: ~ Fields: ~
{autoRefresh?} (fun():boolean|boolean) (default: `true`) Whether to auto-refresh code-lenses. {autoRefresh?} (fun():boolean|boolean)
(default: `true`) Whether to auto-refresh code-lenses.
HoogleOpts *HoogleOpts* haskell-tools.hoogle.Opts *haskell-tools.hoogle.Opts*
Fields: ~ Fields: ~
{mode?} (HoogleMode) Use a telescope with a local hoogle installation or a web backend, or use the browser for hoogle signature search? {mode?} (haskell-tools.hoogle.Mode)
Use a telescope with a local hoogle installation or a web backend,
or use the browser for hoogle signature search?
HoogleMode *HoogleMode* haskell-tools.hoogle.Mode *haskell-tools.hoogle.Mode*
Type: ~ Type: ~
"auto"|"telescope-local"|"telescope-web"|"browser" "auto"|"telescope-local"|"telescope-web"|"browser"
HoverOpts *HoverOpts* haskell-tools.hover.Opts *haskell-tools.hover.Opts*
Fields: ~ Fields: ~
{enable?} (fun():boolean|boolean) (default: `true`) Whether to enable haskell-tools hover. {enable?} (fun():boolean|boolean)
{border?} (string[][]) The hover window's border. Set to `nil` to disable. (default: `true`) Whether to enable haskell-tools hover.
{stylize_markdown?} (boolean) (default: `false`) The builtin LSP client's default behaviour is to stylize markdown. Setting this option to false sets the file type to markdown and enables treesitter syntax highligting for Haskell snippets if nvim-treesitter is installed. {border?} (string[][])
{auto_focus?} (boolean) (default: `false`) Whether to automatically switch to the hover window. The hover window's border. Set to `nil` to disable.
{stylize_markdown?} (boolean)
(default: `false`) The builtin LSP client's default behaviour is to stylize markdown.
Setting this option to false sets the file type to markdown
and enables treesitter syntax highligting for Haskell snippets if nvim-treesitter is installed.
{auto_focus?} (boolean)
(default: `false`) Whether to automatically switch to the hover window.
DefinitionOpts *DefinitionOpts* haskell-tools.definition.Opts *haskell-tools.definition.Opts*
Fields: ~ Fields: ~
{hoogle_signature_fallback?} (fun():boolean|boolean) (default: `false`) Configure `vim.lsp.definition` to fall back to hoogle search (does not affect `vim.lsp.tagfunc`). {hoogle_signature_fallback?} (fun():boolean|boolean)
(default: `false`) Configure |vim.lsp.definition| to fall back to hoogle search
(does not affect |vim.lsp.tagfunc|).
ReplOpts *ReplOpts* haskell-tools.repl.Opts *haskell-tools.repl.Opts*
Fields: ~ Fields: ~
{handler?} (fun():ReplHandler|ReplHandler) `'builtin'`: Use the simple builtin repl. `'toggleterm'`: Use akinsho/toggleterm.nvim. {handler?} (fun():haskell-tools.repl.Handler|haskell-tools.repl.Handler)
{prefer?} (fun():repl_backend|repl_backend) Prefer cabal or stack when both stack and cabal project files are present? `'builtin'`: Use the simple builtin repl.
{builtin?} (BuiltinReplOpts) Configuration for the builtin repl. `'toggleterm'`: Use akinsho/toggleterm.nvim.
{auto_focus?} (boolean) Whether to auto-focus the repl on toggle or send. If unset, the handler decides. {prefer?} (fun():haskell-tools.repl.Backend|haskell-tools.repl.Backend)
Prefer cabal or stack when both stack and cabal project files are present?
{builtin?} (haskell-tools.repl.builtin.Opts)
Configuration for the builtin repl.
{auto_focus?} (boolean)
Whether to auto-focus the repl on toggle or send. If unset, the handler decides.
ReplHandler *ReplHandler* haskell-tools.repl.Handler *haskell-tools.repl.Handler*
Type: ~ Type: ~
"builtin"|"toggleterm" "builtin"|"toggleterm"
repl_backend *repl_backend* haskell-tools.repl.Backend *haskell-tools.repl.Backend*
Type: ~ Type: ~
"cabal"|"stack" "cabal"|"stack"
BuiltinReplOpts *BuiltinReplOpts* haskell-tools.repl.builtin.Opts *haskell-tools.repl.builtin.Opts*
Fields: ~ Fields: ~
{create_repl_window?} (fun(view:ReplView):fun(mk_repl_cmd:mk_repl_cmd_fun)) {create_repl_window?} (fun(view:haskell-tools.repl.View):fun(mk_repl_cmd:mk_ht_repl_cmd_fun))
How to create the repl window.
Should return a function that calls one of the |haskell-tools.repl.View|'s functions.
ReplView *ReplView* haskell-tools.repl.View *haskell-tools.repl.View*
Fields: ~ Fields: ~
{create_repl_split?} (fun(opts:ReplViewOpts):mk_repl_cmd_fun) Create the REPL in a horizontally split window. {create_repl_split?} (fun(opts:haskell-tools.repl.view.Opts):mk_ht_repl_cmd_fun)
{create_repl_vsplit?} (fun(opts:ReplViewOpts):mk_repl_cmd_fun) Create the REPL in a vertically split window. Create the REPL in a horizontally split window.
{create_repl_tabnew?} (fun(opts:ReplViewOpts):mk_repl_cmd_fun) Create the REPL in a new tab. {create_repl_vsplit?} (fun(opts:haskell-tools.repl.view.Opts):mk_ht_repl_cmd_fun)
{create_repl_cur_win?} (fun(opts:ReplViewOpts):mk_repl_cmd_fun) Create the REPL in the current window. Create the REPL in a vertically split window.
{create_repl_tabnew?} (fun(opts:haskell-tools.repl.view.Opts):mk_ht_repl_cmd_fun)
Create the REPL in a new tab.
{create_repl_cur_win?} (fun(opts:haskell-tools.repl.view.Opts):mk_ht_repl_cmd_fun)
Create the REPL in the current window.
ReplViewOpts *ReplViewOpts* haskell-tools.repl.view.Opts *haskell-tools.repl.view.Opts*
Fields: ~ Fields: ~
{delete_buffer_on_exit?} (boolean) Whether to delete the buffer when the Repl quits. {delete_buffer_on_exit?} (boolean)
{size?} (fun():number|number) The size of the window or a function that determines it. Whether to delete the buffer when the Repl quits.
{size?} (fun():number|number)
The size of the window or a function that determines it.
mk_repl_cmd_fun *mk_repl_cmd_fun* mk_ht_repl_cmd_fun *mk_ht_repl_cmd_fun*
Type: ~ Type: ~
fun():string[]|nil fun():string[]|nil
FastTagsOpts *FastTagsOpts* haskell-tools.fast-tags.Opts *haskell-tools.fast-tags.Opts*
Fields: ~ Fields: ~
{enable?} (boolean|fun():boolean) {enable?} (boolean|fun():boolean)
Enabled by default if the `fast-tags` executable is found.
{package_events?} (string[])
The |autocmd| events to trigger package tag generation.
HTLogOpts *HTLogOpts* haskell-tools.log.Opts *haskell-tools.log.Opts*
Fields: ~ Fields: ~
{level?} (number|string) The log level. {level?} (number|string)
The log level.
See: ~ See: ~
|vim.log.levels| |vim.log.levels|
HaskellLspClientOpts *HaskellLspClientOpts* haskell-tools.lsp.ClientOpts *haskell-tools.lsp.ClientOpts*
Fields: ~ Fields: ~
{auto_attach?} (fun():boolean|boolean) Whether to automatically attach the LSP client. Defaults to `true` if the haskell-language-server executable is found. {auto_attach?} (fun():boolean|boolean)
{debug?} (boolean) Whether to enable haskell-language-server debug logging. Whether to automatically attach the LSP client.
{on_attach?} (fun(client:number,bufnr:number,ht:HaskellTools)) Callback that is invoked when the client attaches to a buffer. Defaults to `true` if the haskell-language-server executable is found.
{cmd?} (fun():string[]|string[]) The command to start haskell-language-server with. {debug?} (boolean)
{capabilities?} (lsp.ClientCapabilities) LSP client capabilities. Whether to enable haskell-language-server debug logging.
{settings?} (fun(project_root:string|nil):table|table) The haskell-language-server settings or a function that creates them. To view the default settings, run `haskell-language-server generate-default-config`. {on_attach?} (fun(client:number,bufnr:number,ht:HaskellTools))
{default_settings?} (table) The default haskell-language-server settings that will be used if no settings are specified or detected. Callback that is invoked when the client attaches to a buffer.
{logfile?} (string) The path to the haskell-language-server log file. {cmd?} (fun():string[]|string[])
The command to start haskell-language-server with.
{capabilities?} (lsp.ClientCapabilities)
LSP client capabilities.
{settings?} (fun(project_root:string|nil):table|table)
The haskell-language-server settings or a function that creates them.
To view the default settings, run `haskell-language-server generate-default-config`.
{default_settings?} (table)
The default haskell-language-server settings that will be used if no settings are specified or detected.
{logfile?} (string)
The path to the haskell-language-server log file.
To print all options that are available for your haskell-language-server version, run `haskell-language-server-wrapper generate-default-config` To print all options that are available for your haskell-language-server version, run `haskell-language-server-wrapper generate-default-config`
See: https://haskell-language-server.readthedocs.io/en/latest/configuration.html. See: https://haskell-language-server.readthedocs.io/en/latest/configuration.html.
HTDapOpts *HTDapOpts* haskell-tools.dap.Opts *haskell-tools.dap.Opts*
Fields: ~ Fields: ~
{cmd?} (string[]) The command to start the debug adapter server with. {cmd?} (string[])
{logFile?} (string) Log file path for detected configurations. The command to start the debug adapter server with.
{logLevel?} (HaskellDebugAdapterLogLevel) The log level for detected configurations. {logFile?} (string)
{auto_discover?} (boolean|AddDapConfigOpts) Set to `false` to disable auto-discovery of launch configurations. `true` uses the default configurations options`. Log file path for detected configurations.
{logLevel?} (haskell-tools.debugAdapter.LogLevel)
The log level for detected configurations.
{auto_discover?} (boolean|haskell-tools.dap.AddConfigOpts) Set to `false` to disable auto-discovery of launch configurations. `true` uses the default configurations options`.
HaskellDebugAdapterLogLevel *HaskellDebugAdapterLogLevel* haskell-tools.debugAdapter.LogLevel *haskell-tools.debugAdapter.LogLevel*
Type: ~ Type: ~
"Debug"|"Info"|"Warning"|"Error" "Debug"|"Info"|"Warning"|"Error"
haskell-tools.dap.AddConfigOpts *haskell-tools.dap.AddConfigOpts*
Fields: ~
{autodetect} (boolean)
Whether to automatically detect launch configurations for the project.
{settings_file_pattern} (string)
File name or pattern to search for.
Defaults to 'launch.json'.
============================================================================== ==============================================================================
haskell-language-server LSP client tools *haskell-tools.lsp* haskell-language-server LSP client tools *haskell-tools.lsp*
The following commands are available: The following commands are available:
* `:HlsStart` - Start the LSP client. * `:Hls start` - Start the LSP client.
* `:HlsStop` - Stop the LSP client. * `:Hls stop` - Stop the LSP client.
* `:HlsRestart` - Restart the LSP client. * `:Hls restart` - Restart the LSP client.
* `:HlsEvalAll` - Evaluate all code snippets in comments. * `:Hls evalAll` - Evaluate all code snippets in comments.
LoadHlsSettingsOpts *LoadHlsSettingsOpts* haskell-tools.load_hls_settings.Opts *haskell-tools.load_hls_settings.Opts*
Fields: ~ Fields: ~
{settings_file_pattern} (string|nil) File name or pattern to search for. Defaults to 'hls.json' {settings_file_pattern} (string|nil) File name or pattern to search for. Defaults to 'hls.json'
HlsTools *HlsTools* haskell-tools.Hls *haskell-tools.Hls*
*HlsTools.load_hls_settings* *Hls.load_hls_settings*
HlsTools.load_hls_settings({project_root}, {opts}) Hls.load_hls_settings({project_root}, {opts})
Search the project root for a haskell-language-server settings JSON file and load it to a Lua table. Search the project root for a haskell-language-server settings JSON file and load it to a Lua table.
Falls back to the `hls.default_settings` if no file is found or file cannot be read or decoded. Falls back to the `hls.default_settings` if no file is found or file cannot be read or decoded.
Parameters: ~ Parameters: ~
{project_root} (string|nil) The project root {project_root} (string|nil) The project root
{opts} (LoadHlsSettingsOpts|nil) {opts} (haskell-tools.load_hls_settings.Opts|nil)
Returns: ~ Returns: ~
(table) hls_settings (table) hls_settings
@ -247,7 +307,7 @@ HlsTools.load_hls_settings({project_root}, {opts})
|https://haskell-language-server.readthedocs.io/en/latest/configuration.html| |https://haskell-language-server.readthedocs.io/en/latest/configuration.html|
HlsTools.start({bufnr}) *HlsTools.start* Hls.start({bufnr}) *Hls.start*
Start or attach the LSP client. Start or attach the LSP client.
Fails silently if the buffer's filetype is not one of the filetypes specified in the config. Fails silently if the buffer's filetype is not one of the filetypes specified in the config.
@ -258,7 +318,7 @@ HlsTools.start({bufnr}) *HlsTools.start*
(number|nil) The LSP client ID (number|nil) The LSP client ID
HlsTools.stop({bufnr}) *HlsTools.stop* Hls.stop({bufnr}) *Hls.stop*
Stop the LSP client. Stop the LSP client.
Parameters: ~ Parameters: ~
@ -268,7 +328,7 @@ HlsTools.stop({bufnr}) *HlsTools.stop*
(table[]) A list of clients that will be stopped (table[]) A list of clients that will be stopped
HlsTools.restart({bufnr}) *HlsTools.restart* Hls.restart({bufnr}) *Hls.restart*
Restart the LSP client. Restart the LSP client.
Fails silently if the buffer's filetype is not one of the filetypes specified in the config. Fails silently if the buffer's filetype is not one of the filetypes specified in the config.
@ -279,7 +339,7 @@ HlsTools.restart({bufnr}) *HlsTools.restart*
(number|nil) The LSP client ID after restart (number|nil) The LSP client ID after restart
HlsTools.buf_eval_all({bufnr}) *HlsTools.buf_eval_all* Hls.buf_eval_all({bufnr}) *Hls.buf_eval_all*
Evaluate all code snippets in comments. Evaluate all code snippets in comments.
Parameters: ~ Parameters: ~
@ -292,22 +352,19 @@ HlsTools.buf_eval_all({bufnr}) *HlsTools.buf_eval_all*
============================================================================== ==============================================================================
haskell-tools nvim-dap setup *haskell-tools.dap* haskell-tools nvim-dap setup *haskell-tools.dap*
HsDapLaunchConfiguration *HsDapLaunchConfiguration* haskell-tools.dap.LaunchConfiguration *haskell-tools.dap.LaunchConfiguration*
HsDapTools *HsDapTools* haskell-tools.Dap *haskell-tools.Dap*
AddDapConfigOpts *AddDapConfigOpts* *Dap.discover_configurations*
Dap.discover_configurations({bufnr}, {opts})
*HsDapTools.discover_configurations*
HsDapTools.discover_configurations({bufnr}, {opts})
Discover nvim-dap launch configurations for haskell-debug-adapter. Discover nvim-dap launch configurations for haskell-debug-adapter.
Parameters: ~ Parameters: ~
{bufnr} (number|nil) The buffer number {bufnr} (number|nil) The buffer number
{opts} (AddDapConfigOpts|nil) {opts} (haskell-tools.dap.AddConfigOpts|nil)
Returns: ~ Returns: ~
(nil) (nil)
@ -316,10 +373,10 @@ HsDapTools.discover_configurations({bufnr}, {opts})
============================================================================== ==============================================================================
haskell-tools Hoogle search *haskell-tools.hoogle* haskell-tools Hoogle search *haskell-tools.hoogle*
HoogleTools *HoogleTools* haskell-tools.Hoogle *haskell-tools.Hoogle*
HoogleTools.hoogle_signature({options}) *HoogleTools.hoogle_signature* Hoogle.hoogle_signature({options}) *Hoogle.hoogle_signature*
Parameters: ~ Parameters: ~
{options} (table<string,any>|nil) Includes the `search_term` and options to pass to the telescope picker (if available) {options} (table<string,any>|nil) Includes the `search_term` and options to pass to the telescope picker (if available)
@ -333,64 +390,68 @@ haskell-tools GHCi REPL module *haskell-tools.repl*
The following commands are available: The following commands are available:
* `:HtReplToggle` - Toggle a GHCi repl. * `:Haskell repl toggle {file?}` - Toggle a GHCi repl.
* `:HtReplQuit` - Quit the current repl. * `:Haskell repl quit` - Quit the current repl.
* `:HtReplLoad` - Load a Haskell file into the repl. * `:Haskell repl load {file?}` - Load a Haskell file into the repl.
* `:HtReplReload` - Reload the current repl. * `:Haskell repl reload` - Reload the current repl.
* `:Haskell repl paste_type {register?}` - Query the repl for the type of |registers| {register}
* `:Haskell repl cword_type` - Query the repl for the type of |cword|
* `:Haskell repl paste_info {register?}` - Query the repl for the info on |registers| {register}
* `:Haskell repl cword_info` - Query the repl for info on |cword|
HsReplTools *HsReplTools* haskell-tools.Repl *haskell-tools.Repl*
HsReplTools.buf_mk_repl_cmd() *HsReplTools.buf_mk_repl_cmd* Repl.buf_mk_repl_cmd() *Repl.buf_mk_repl_cmd*
Create the command to create a repl for the current buffer. Create the command to create a repl for the current buffer.
Returns: ~ Returns: ~
(table|nil) command (table|nil) command
HsReplTools.operator() *HsReplTools.operator* Repl.operator() *Repl.operator*
See: ~ See: ~
|operatorfunc| |operatorfunc|
HsReplTools.paste({reg}) *HsReplTools.paste* Repl.paste({reg}) *Repl.paste*
Paste from register `reg` to the REPL Paste from register `reg` to the REPL
Parameters: ~ Parameters: ~
{reg} (string|nil) register (defaults to '"') {reg} (string|nil) register (defaults to '"')
HsReplTools.paste_type({reg}) *HsReplTools.paste_type* Repl.paste_type({reg}) *Repl.paste_type*
Query the REPL for the type of register `reg` Query the REPL for the type of register `reg`
Parameters: ~ Parameters: ~
{reg} (string|nil) register (defaults to '"') {reg} (string|nil) register (defaults to '"')
HsReplTools.cword_type() *HsReplTools.cword_type* Repl.cword_type() *Repl.cword_type*
Query the REPL for the type of word under the cursor Query the REPL for the type of word under the cursor
HsReplTools.paste_info({reg}) *HsReplTools.paste_info* Repl.paste_info({reg}) *Repl.paste_info*
Query the REPL for info on register `reg` Query the REPL for info on register `reg`
Parameters: ~ Parameters: ~
{reg} (string|nil) register (defaults to '"') {reg} (string|nil) register (defaults to '"')
HsReplTools.cword_info() *HsReplTools.cword_info* Repl.cword_info() *Repl.cword_info*
Query the REPL for the type of word under the cursor Query the REPL for the type of word under the cursor
HsReplTools.load_file({filepath}) *HsReplTools.load_file* Repl.load_file({filepath}) *Repl.load_file*
Load a file into the REPL Load a file into the REPL
Parameters: ~ Parameters: ~
{filepath} (string) The absolute file path {filepath} (string) The absolute file path
HsReplTools.reload() *HsReplTools.reload* Repl.reload() *Repl.reload*
Reload the repl Reload the repl
@ -399,14 +460,14 @@ haskell-tools Project module *haskell-tools.project*
The following commands are available: The following commands are available:
* `:HsProjectFile` - Open the project file for the current buffer (cabal.project or stack.yaml). * `:Haskell projectFile` - Open the project file for the current buffer (cabal.project or stack.yaml).
* `:HsPackageYaml` - Open the package.yaml file for the current buffer. * `:Haskell packageYaml` - Open the package.yaml file for the current buffer.
* `:HsPackageCabal` - Open the *.cabal file for the current buffer. * `:Haskell packageCabal` - Open the *.cabal file for the current buffer.
HsProjectTools *HsProjectTools* haskell-tools.Project *haskell-tools.Project*
HsProjectTools.root_dir({project_file}) *HsProjectTools.root_dir* Project.root_dir({project_file}) *Project.root_dir*
Get the project's root directory Get the project's root directory
Parameters: ~ Parameters: ~
@ -416,21 +477,21 @@ HsProjectTools.root_dir({project_file}) *HsProjectTools.root_dir*
(string|nil) (string|nil)
HsProjectTools.open_package_yaml() *HsProjectTools.open_package_yaml* Project.open_package_yaml() *Project.open_package_yaml*
Open the package.yaml of the package containing the current buffer. Open the package.yaml of the package containing the current buffer.
Returns: ~ Returns: ~
(nil) (nil)
HsProjectTools.open_package_cabal() *HsProjectTools.open_package_cabal* Project.open_package_cabal() *Project.open_package_cabal*
Open the *.cabal file of the package containing the current buffer. Open the *.cabal file of the package containing the current buffer.
Returns: ~ Returns: ~
(nil) (nil)
HsProjectTools.open_project_file() *HsProjectTools.open_project_file* Project.open_project_file() *Project.open_project_file*
Open the current buffer's project file (cabal.project or stack.yaml). Open the current buffer's project file (cabal.project or stack.yaml).
Returns: ~ Returns: ~
@ -440,27 +501,27 @@ HsProjectTools.open_project_file() *HsProjectTools.open_project_file*
============================================================================== ==============================================================================
haskell-tools fast-tags module *haskell-tools.tags* haskell-tools fast-tags module *haskell-tools.tags*
GenerateProjectTagsOpts *GenerateProjectTagsOpts* *haskell-tools.tags.generate_project_tags.Opts*
haskell-tools.tags.generate_project_tags.Opts
Fields: ~ Fields: ~
{refresh} (boolean) Whether to refresh the tags if they have already been generated {refresh} (boolean) Whether to refresh the tags if they have already been generated
FastTagsTools *FastTagsTools* haskell-tools.FastTags *haskell-tools.FastTags*
for the project (default: true) for the project (default: true)
*FastTagsTools.generate_project_tags* *FastTags.generate_project_tags*
FastTagsTools.generate_project_tags({path}, {opts}) FastTags.generate_project_tags({path}, {opts})
Generates tags for the current project Generates tags for the current project
Parameters: ~ Parameters: ~
{path} (string|nil) File path {path} (string|nil) File path
{opts} (GenerateProjectTagsOpts|nil) Options {opts} (haskell-tools.tags.generate_project_tags.Opts|nil) Options
*FastTagsTools.generate_package_tags* FastTags.generate_package_tags({path}) *FastTags.generate_package_tags*
FastTagsTools.generate_package_tags({path})
Generate tags for the package containing `path` Generate tags for the package containing `path`
Parameters: ~ Parameters: ~
@ -472,42 +533,42 @@ haskell-tools Logging *haskell-tools.log*
The following commands are available: The following commands are available:
* `:HtLog` - Open the haskell-tools.nvim log file. * `:Haskell log setLevel` - Set the haskell-tools.nvim and LSP client log level.
* `:HlsLog` - Open the haskell-language-server log file. * `:Haskell log openLog` - Open the haskell-tools.nvim log file.
* `:HtSetLogLevel` - Set the haskell-tools.nvim and LSP client log level. * `:Haskell log openHlsLog` - Open the haskell-language-server log file.
HaskellToolsLog *HaskellToolsLog* haskell-tools.Log *haskell-tools.Log*
HaskellToolsLog.get_hls_logfile() *HaskellToolsLog.get_hls_logfile* Log.get_hls_logfile() *Log.get_hls_logfile*
Get the haskell-language-server log file Get the haskell-language-server log file
Returns: ~ Returns: ~
(string) filepath (string) filepath
HaskellToolsLog.get_logfile() *HaskellToolsLog.get_logfile* Log.get_logfile() *Log.get_logfile*
Get the haskell-tools.nvim log file path. Get the haskell-tools.nvim log file path.
Returns: ~ Returns: ~
(string) filepath (string) filepath
HaskellToolsLog.nvim_open_hls_logfile() *HaskellToolsLog.nvim_open_hls_logfile* Log.nvim_open_hls_logfile() *Log.nvim_open_hls_logfile*
Open the haskell-language-server log file Open the haskell-language-server log file
Returns: ~ Returns: ~
(nil) (nil)
HaskellToolsLog.nvim_open_logfile() *HaskellToolsLog.nvim_open_logfile* Log.nvim_open_logfile() *Log.nvim_open_logfile*
Open the haskell-tools.nvim log file. Open the haskell-tools.nvim log file.
Returns: ~ Returns: ~
(nil) (nil)
HaskellToolsLog.set_level() *HaskellToolsLog.set_level* Log.set_level() *Log.set_level*
Returns: ~ Returns: ~
(nil) (nil)

View File

@ -1,69 +1,69 @@
AddDapConfigOpts haskell-tools.txt /*AddDapConfigOpts* Dap.discover_configurations haskell-tools.txt /*Dap.discover_configurations*
BuiltinReplOpts haskell-tools.txt /*BuiltinReplOpts* FastTags.generate_package_tags haskell-tools.txt /*FastTags.generate_package_tags*
CodeLensOpts haskell-tools.txt /*CodeLensOpts* FastTags.generate_project_tags haskell-tools.txt /*FastTags.generate_project_tags*
DefinitionOpts haskell-tools.txt /*DefinitionOpts*
FastTagsOpts haskell-tools.txt /*FastTagsOpts*
FastTagsTools haskell-tools.txt /*FastTagsTools*
FastTagsTools.generate_package_tags haskell-tools.txt /*FastTagsTools.generate_package_tags*
FastTagsTools.generate_project_tags haskell-tools.txt /*FastTagsTools.generate_project_tags*
GenerateProjectTagsOpts haskell-tools.txt /*GenerateProjectTagsOpts*
HTDapOpts haskell-tools.txt /*HTDapOpts*
HTLogOpts haskell-tools.txt /*HTLogOpts*
HTOpts haskell-tools.txt /*HTOpts*
HaskellDebugAdapterLogLevel haskell-tools.txt /*HaskellDebugAdapterLogLevel*
HaskellLspClientOpts haskell-tools.txt /*HaskellLspClientOpts*
HaskellTools haskell-tools.txt /*HaskellTools* HaskellTools haskell-tools.txt /*HaskellTools*
HaskellToolsLog haskell-tools.txt /*HaskellToolsLog* Hls.buf_eval_all haskell-tools.txt /*Hls.buf_eval_all*
HaskellToolsLog.get_hls_logfile haskell-tools.txt /*HaskellToolsLog.get_hls_logfile* Hls.load_hls_settings haskell-tools.txt /*Hls.load_hls_settings*
HaskellToolsLog.get_logfile haskell-tools.txt /*HaskellToolsLog.get_logfile* Hls.restart haskell-tools.txt /*Hls.restart*
HaskellToolsLog.nvim_open_hls_logfile haskell-tools.txt /*HaskellToolsLog.nvim_open_hls_logfile* Hls.start haskell-tools.txt /*Hls.start*
HaskellToolsLog.nvim_open_logfile haskell-tools.txt /*HaskellToolsLog.nvim_open_logfile* Hls.stop haskell-tools.txt /*Hls.stop*
HaskellToolsLog.set_level haskell-tools.txt /*HaskellToolsLog.set_level* Hoogle.hoogle_signature haskell-tools.txt /*Hoogle.hoogle_signature*
HlsTools haskell-tools.txt /*HlsTools* Log.get_hls_logfile haskell-tools.txt /*Log.get_hls_logfile*
HlsTools.buf_eval_all haskell-tools.txt /*HlsTools.buf_eval_all* Log.get_logfile haskell-tools.txt /*Log.get_logfile*
HlsTools.load_hls_settings haskell-tools.txt /*HlsTools.load_hls_settings* Log.nvim_open_hls_logfile haskell-tools.txt /*Log.nvim_open_hls_logfile*
HlsTools.restart haskell-tools.txt /*HlsTools.restart* Log.nvim_open_logfile haskell-tools.txt /*Log.nvim_open_logfile*
HlsTools.start haskell-tools.txt /*HlsTools.start* Log.set_level haskell-tools.txt /*Log.set_level*
HlsTools.stop haskell-tools.txt /*HlsTools.stop* Project.open_package_cabal haskell-tools.txt /*Project.open_package_cabal*
HoogleMode haskell-tools.txt /*HoogleMode* Project.open_package_yaml haskell-tools.txt /*Project.open_package_yaml*
HoogleOpts haskell-tools.txt /*HoogleOpts* Project.open_project_file haskell-tools.txt /*Project.open_project_file*
HoogleTools haskell-tools.txt /*HoogleTools* Project.root_dir haskell-tools.txt /*Project.root_dir*
HoogleTools.hoogle_signature haskell-tools.txt /*HoogleTools.hoogle_signature* Repl.buf_mk_repl_cmd haskell-tools.txt /*Repl.buf_mk_repl_cmd*
HoverOpts haskell-tools.txt /*HoverOpts* Repl.cword_info haskell-tools.txt /*Repl.cword_info*
HsDapLaunchConfiguration haskell-tools.txt /*HsDapLaunchConfiguration* Repl.cword_type haskell-tools.txt /*Repl.cword_type*
HsDapTools haskell-tools.txt /*HsDapTools* Repl.load_file haskell-tools.txt /*Repl.load_file*
HsDapTools.discover_configurations haskell-tools.txt /*HsDapTools.discover_configurations* Repl.operator haskell-tools.txt /*Repl.operator*
HsProjectTools haskell-tools.txt /*HsProjectTools* Repl.paste haskell-tools.txt /*Repl.paste*
HsProjectTools.open_package_cabal haskell-tools.txt /*HsProjectTools.open_package_cabal* Repl.paste_info haskell-tools.txt /*Repl.paste_info*
HsProjectTools.open_package_yaml haskell-tools.txt /*HsProjectTools.open_package_yaml* Repl.paste_type haskell-tools.txt /*Repl.paste_type*
HsProjectTools.open_project_file haskell-tools.txt /*HsProjectTools.open_project_file* Repl.reload haskell-tools.txt /*Repl.reload*
HsProjectTools.root_dir haskell-tools.txt /*HsProjectTools.root_dir*
HsReplTools haskell-tools.txt /*HsReplTools*
HsReplTools.buf_mk_repl_cmd haskell-tools.txt /*HsReplTools.buf_mk_repl_cmd*
HsReplTools.cword_info haskell-tools.txt /*HsReplTools.cword_info*
HsReplTools.cword_type haskell-tools.txt /*HsReplTools.cword_type*
HsReplTools.load_file haskell-tools.txt /*HsReplTools.load_file*
HsReplTools.operator haskell-tools.txt /*HsReplTools.operator*
HsReplTools.paste haskell-tools.txt /*HsReplTools.paste*
HsReplTools.paste_info haskell-tools.txt /*HsReplTools.paste_info*
HsReplTools.paste_type haskell-tools.txt /*HsReplTools.paste_type*
HsReplTools.reload haskell-tools.txt /*HsReplTools.reload*
LoadHlsSettingsOpts haskell-tools.txt /*LoadHlsSettingsOpts*
ReplHandler haskell-tools.txt /*ReplHandler*
ReplOpts haskell-tools.txt /*ReplOpts*
ReplView haskell-tools.txt /*ReplView*
ReplViewOpts haskell-tools.txt /*ReplViewOpts*
ToolsOpts haskell-tools.txt /*ToolsOpts*
haskell-tools haskell-tools.txt /*haskell-tools* haskell-tools haskell-tools.txt /*haskell-tools*
haskell-tools.Dap haskell-tools.txt /*haskell-tools.Dap*
haskell-tools.FastTags haskell-tools.txt /*haskell-tools.FastTags*
haskell-tools.Hls haskell-tools.txt /*haskell-tools.Hls*
haskell-tools.Hoogle haskell-tools.txt /*haskell-tools.Hoogle*
haskell-tools.Log haskell-tools.txt /*haskell-tools.Log*
haskell-tools.Opts haskell-tools.txt /*haskell-tools.Opts*
haskell-tools.Project haskell-tools.txt /*haskell-tools.Project*
haskell-tools.Repl haskell-tools.txt /*haskell-tools.Repl*
haskell-tools.codeLens.Opts haskell-tools.txt /*haskell-tools.codeLens.Opts*
haskell-tools.config haskell-tools.txt /*haskell-tools.config* haskell-tools.config haskell-tools.txt /*haskell-tools.config*
haskell-tools.contents haskell-tools.txt /*haskell-tools.contents* haskell-tools.contents haskell-tools.txt /*haskell-tools.contents*
haskell-tools.dap haskell-tools.txt /*haskell-tools.dap* haskell-tools.dap haskell-tools.txt /*haskell-tools.dap*
haskell-tools.dap.AddConfigOpts haskell-tools.txt /*haskell-tools.dap.AddConfigOpts*
haskell-tools.dap.LaunchConfiguration haskell-tools.txt /*haskell-tools.dap.LaunchConfiguration*
haskell-tools.dap.Opts haskell-tools.txt /*haskell-tools.dap.Opts*
haskell-tools.debugAdapter.LogLevel haskell-tools.txt /*haskell-tools.debugAdapter.LogLevel*
haskell-tools.definition.Opts haskell-tools.txt /*haskell-tools.definition.Opts*
haskell-tools.fast-tags.Opts haskell-tools.txt /*haskell-tools.fast-tags.Opts*
haskell-tools.hoogle haskell-tools.txt /*haskell-tools.hoogle* haskell-tools.hoogle haskell-tools.txt /*haskell-tools.hoogle*
haskell-tools.hoogle.Mode haskell-tools.txt /*haskell-tools.hoogle.Mode*
haskell-tools.hoogle.Opts haskell-tools.txt /*haskell-tools.hoogle.Opts*
haskell-tools.hover.Opts haskell-tools.txt /*haskell-tools.hover.Opts*
haskell-tools.load_hls_settings.Opts haskell-tools.txt /*haskell-tools.load_hls_settings.Opts*
haskell-tools.log haskell-tools.txt /*haskell-tools.log* haskell-tools.log haskell-tools.txt /*haskell-tools.log*
haskell-tools.log.Opts haskell-tools.txt /*haskell-tools.log.Opts*
haskell-tools.lsp haskell-tools.txt /*haskell-tools.lsp* haskell-tools.lsp haskell-tools.txt /*haskell-tools.lsp*
haskell-tools.lsp.ClientOpts haskell-tools.txt /*haskell-tools.lsp.ClientOpts*
haskell-tools.project haskell-tools.txt /*haskell-tools.project* haskell-tools.project haskell-tools.txt /*haskell-tools.project*
haskell-tools.repl haskell-tools.txt /*haskell-tools.repl* haskell-tools.repl haskell-tools.txt /*haskell-tools.repl*
haskell-tools.repl.Backend haskell-tools.txt /*haskell-tools.repl.Backend*
haskell-tools.repl.Handler haskell-tools.txt /*haskell-tools.repl.Handler*
haskell-tools.repl.Opts haskell-tools.txt /*haskell-tools.repl.Opts*
haskell-tools.repl.View haskell-tools.txt /*haskell-tools.repl.View*
haskell-tools.repl.builtin.Opts haskell-tools.txt /*haskell-tools.repl.builtin.Opts*
haskell-tools.repl.view.Opts haskell-tools.txt /*haskell-tools.repl.view.Opts*
haskell-tools.tags haskell-tools.txt /*haskell-tools.tags* haskell-tools.tags haskell-tools.txt /*haskell-tools.tags*
haskell-tools.tags.generate_project_tags.Opts haskell-tools.txt /*haskell-tools.tags.generate_project_tags.Opts*
haskell-tools.tools.Opts haskell-tools.txt /*haskell-tools.tools.Opts*
intro haskell-tools.txt /*intro* intro haskell-tools.txt /*intro*
mk_repl_cmd_fun haskell-tools.txt /*mk_repl_cmd_fun* mk_ht_repl_cmd_fun haskell-tools.txt /*mk_ht_repl_cmd_fun*
repl_backend haskell-tools.txt /*repl_backend*

Some files were not shown because too many files have changed in this diff Show More