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.cmd([[
]])
require("lazy").setup({
dev = {
path = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins",
@ -648,6 +644,7 @@ require("lazy").setup({
{ ["name"] = "cmake" },
{ ["name"] = "lua_ls" },
{ ["name"] = "nil_ls" },
{ ["name"] = "ltex" },
{
["extraOptions"] = {
["nixd"] = {
@ -1397,17 +1394,23 @@ do
},
{ 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",
mode = "n",
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",
mode = "n",
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>",
key = "<leader>tf",
@ -1427,6 +1430,12 @@ do
options = { desc = "Toggle inline diagnostics" },
},
{ 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 = "<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" } },
@ -1541,8 +1550,6 @@ do
end
-- }}}
vim.filetype.add({ extension = { v = "vlang" } })
-- Make Lazy window border rounded
require("lazy.core.config").options.ui.border = "rounded"

View File

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

View File

@ -1,175 +1,182 @@
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 = {
timeout = vim.o.timeoutlen,
mapping = { "jk", "jj" },
clear_empty_lines = false,
---@type string|function
keys = "<Esc>",
default_mappings = true,
mappings = {
i = {
-- 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 second_chars = {}
---@class State
---@field char string
---@field modified boolean
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)
local function unmap_keys()
for mode, keys in pairs(settings.mappings) do
for key, subkeys in pairs(keys) do
pcall(vim.keymap.del, mode, key)
for subkey, _ in pairs(subkeys) do
pcall(vim.keymap.del, mode, subkey)
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")
-- WIP: move this into recorder.lua ?
-- When a first_key is pressed, `recorded_key` is set to it
-- (e.g. if jk is a mapping, when 'j' is pressed, `recorded_key` is set to 'j')
local recorded_key = nil
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)
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
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)
if matched then
input_states = {}
vim.schedule(function()
vim.bo.modified = prev_state.modified
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
-- 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()
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
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."
-- 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
assert(
vim.tbl_contains({ "string", "function" }, type(settings.keys)),
"Keys must be a function or string."
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
function M.setup(update)
if update and update.default_mappings == false then
settings.mappings = {}
end
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
vim.notify(
"[better-escape.nvim]: Rewrite! Check: https://github.com/max397574/better-escape.nvim",
vim.log.levels.WARN,
{}
)
end
if settings.mapping then
vim.notify(
"[better-escape.nvim]: Rewrite! Check: https://github.com/max397574/better-escape.nvim",
vim.log.levels.WARN,
{}
)
if type(settings.mapping) == "string" then
settings.mapping = { settings.mapping }
end
local ok, msg = pcall(validate_settings)
if ok then
-- create tables with the first and seconds chars of the mappings
for _, shortcut in ipairs(settings.mapping) do
vim.cmd("silent! iunmap " .. shortcut)
table.insert(first_chars, char_at(shortcut, 0))
table.insert(second_chars, char_at(shortcut, 1))
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
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
unmap_keys()
map_keys()
end
return setmetatable(M, {
__index = function(_, k)
if k == "waiting" then
return waiting
end
end,
})
return M

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),
with some additional features and optimizations
![better-escape](https://github.com/max397574/better-escape.nvim/assets/81827001/8863a620-b075-4417-92d0-7eb2d2646186)
A lot of people have mappings like `jk` or `jj` to escape insert mode.
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.
Only after that time the `j` will be inserted.
Then you always get a delay when typing a `j`.
A lot of people have mappings like `jk` or `jj` to escape insert mode. 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. 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
- Escape without getting delay when typing in insert mode
- Customizable mapping and timeout
- Write mappings in many modes without having a delay when typing
- Customizable timeout
- Map key sequences and lua functions
- Use multiple mappings
- 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.
```lua
-- lua with packer.nvim
use {
-- lua with lazy.nvim
{
"max397574/better-escape.nvim",
config = function()
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
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, default settings
require("better_escape").setup {
mapping = {"jk", "jj"}, -- a table with mappings to use
timeout = vim.o.timeoutlen, -- the time in which the keys must be hit in ms. Use option timeoutlen by default
clear_empty_lines = false, -- clear line after escaping if there is only whitespace
keys = "<Esc>", -- keys used for escaping, if it is a function will use the result everytime
-- example(recommended)
-- keys = function()
-- return vim.api.nvim_win_get_cursor(0)[2] > 1 and '<esc>l' or '<esc>'
-- end,
timeout = vim.o.timeoutlen,
default_mappings = true,
mappings = {
i = {
j = {
-- These can all also be functions
k = "<Esc>",
j = "<Esc>",
},
},
c = {
j = {
k = "<Esc>",
j = "<Esc>",
},
},
t = {
j = {
k = "<Esc>",
j = "<Esc>",
},
},
v = {
j = {
k = "<Esc>",
},
},
s = {
j = {
k = "<Esc>",
},
},
},
}
```
</details>
## API
`require("better_escape").waiting` is a boolean indicating that it's waiting for
a mapped sequence to complete.
<details>
<summary>statusline example</summary>
<summary>Statusline example</summary>
```lua
function escape_status()
@ -68,28 +147,15 @@ end
</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
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
## [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)

View File

@ -581,7 +581,10 @@ ctp_feline.setup({
extras = clrs.overlay1,
curr_file = clrs.maroon,
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 = {
["n"] = { "NORMAL", clrs.lavender },
@ -704,6 +707,17 @@ gitsigns = true
```
<!-- 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 -->
</tr>
<tr>
@ -1121,6 +1135,20 @@ semantic_tokens = true
</tr>
<!-- 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 -->
</tr>
<tr>
@ -1298,6 +1326,20 @@ To use another flavour just replace `mocha` with the one you want to use.
</tr>
<!-- 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 -->
</tr>
<tr>

View File

@ -455,7 +455,10 @@ Here are the defaults:
extras = clrs.overlay1,
curr_file = clrs.maroon,
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 = {
["n"] = { "NORMAL", clrs.lavender },
@ -539,6 +542,10 @@ gitsigns.nvim>lua
gitsigns = true
<
grug-far.nvim>lua
grug_far = false
<
harpoon>lua
harpoon = false
<
@ -721,6 +728,10 @@ nvim-semantic-tokens>lua
semantic_tokens = true
<
nvim-surround>lua
nvim_surround = false
<
nvim-tree.lua>lua
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.
render-markdown (markdown.nvim)>lua
render_markdown = true
<
symbols-outline.nvim
[!NOTE] This plugin has been archived by the author, consider using
outline.nvim <https://github.com/hedyhli/outline.nvim>

View File

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

View File

@ -32,6 +32,7 @@ local sett = {
curr_file = C.maroon,
curr_dir = C.flamingo,
show_modified = false,
show_lazy_updates = false,
}
if require("catppuccin").flavour == "latte" then
@ -287,7 +288,7 @@ function M.get()
-- macro
components.active[1][12] = {
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 = {
fg = sett.extras,
bg = sett.bkg,
@ -298,7 +299,24 @@ function M.get()
-- search count
components.active[1][13] = {
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 = {
fg = sett.extras,
bg = sett.bkg,
@ -412,7 +430,7 @@ function M.get()
components.active[3][2] = {
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
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)),
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),
bg = O.transparent_background and C.none
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 },
},
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 },
}
end

View File

@ -8,17 +8,99 @@ function M.get()
local indentscope_color = O.integrations.mini.indentscope_color
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" } },
MiniCursorword = { 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 },
MiniIndentscopePrefix = { style = { "nocombine" } }, -- Make it invisible
MiniJump = { fg = C.overlay2, bg = C.pink },
MiniJump2dDim = { fg = C.overlay0 },
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 = {},
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
["@comment.warning.gitcommit"] = { fg = C.yellow },
-- gitignore
["@string.special.path.gitignore"] = { fg = C.text },
-- Misc
gitcommitSummary = { fg = C.rosewater, style = O.styles.miscs or { "italic" } },
zshKSHFunction = { link = "Function" },

View File

@ -96,6 +96,17 @@ function M.get()
rainbow4 = { fg = C.green },
rainbow5 = { fg = C.sapphire },
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

View File

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

View File

@ -151,6 +151,7 @@
---@field flash boolean?
---@field gitgutter boolean?
---@field gitsigns boolean?
---@field grug_far boolean?
---@field harpoon boolean?
---@field headlines boolean?
---@field hop boolean?
@ -185,11 +186,13 @@
---@field neotree boolean?
---@field noice boolean?
---@field notify boolean?
---@field nvim_surround boolean?
---@field nvimtree boolean?
---@field octo boolean?
---@field overseer boolean?
---@field pounce boolean?
---@field rainbow_delimiters boolean?
---@field render_markdown boolean?
---@field sandwich boolean?
---@field semantic_tokens 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
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
IFS=' '
while read local_ref _local_sha _remote_ref _remote_sha; do

View File

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

View File

@ -1,5 +1,78 @@
# 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)

View File

@ -18,16 +18,16 @@ Lightweight yet powerful formatter plugin for Neovim
- [setup(opts)](#setupopts)
- [format(opts, callback)](#formatopts-callback)
- [list_formatters(bufnr)](#list_formattersbufnr)
- [list_formatters_to_run(bufnr)](#list_formatters_to_runbufnr)
- [list_all_formatters()](#list_all_formatters)
- [get_formatter_info(formatter, bufnr)](#get_formatter_infoformatter-bufnr)
- [will_fallback_lsp(options)](#will_fallback_lspoptions)
- [Acknowledgements](#acknowledgements)
<!-- /TOC -->
## Requirements
- Neovim 0.8+
- Neovim 0.9+ (for older versions, use a [nvim-0.x branch](https://github.com/stevearc/conform.nvim/branches))
## Features
@ -129,8 +129,10 @@ require("conform").setup({
lua = { "stylua" },
-- Conform will run multiple formatters sequentially
python = { "isort", "black" },
-- Use a sub-list to run only the first available formatter
javascript = { { "prettierd", "prettier" } },
-- You can customize some of the format options for the filetype (:help conform.format)
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.
- [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.
- [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.
- [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
- [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.
- [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.
- [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.
- [crlfmt](https://github.com/cockroachdb/crlfmt) - Formatter for CockroachDB's additions to the Go style guide.
- [crystal](https://crystal-lang.org/) - Format Crystal code.
- [csharpier](https://github.com/belav/csharpier) - The opinionated C# code formatter.
- [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.
- [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.
- [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.
- [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.
- [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.
- [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.
- [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.
@ -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.
- [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!
- [gluon_fmt](https://github.com/gluon-lang/gluon) - Code formatting for the gluon programming language.
- [gn](https://gn.googlesource.com/gn/) - gn build system.
- [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.
@ -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).
- [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.
- [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.
- [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.
- [imba_fmt](https://imba.io/) - Code formatter for the Imba programming language.
- [indent](https://www.gnu.org/software/indent/) - GNU Indent.
- [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
@ -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.
- [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.
- [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.
- [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.
@ -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.
- [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.
- [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.
- [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.
@ -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.
- [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.
- [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.
- [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.
- [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.
- [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_whitespace](https://www.gnu.org/software/gawk/manual/gawk.html) - Trim whitespaces 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://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
- [typos](https://github.com/crate-ci/typos) - Source code spell checker
- [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)
- [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)
- [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 -->
@ -445,8 +462,8 @@ require("conform").setup({
lua = { "stylua" },
-- Conform will run multiple formatters sequentially
go = { "goimports", "gofmt" },
-- Use a sub-list to run only the first available formatter
javascript = { { "prettierd", "prettier" } },
-- You can also customize some of the format options for the filetype
rust = { "rustfmt", lsp_format = "fallback" },
-- You can use a function here to determine the formatters dynamically
python = function(bufnr)
if require("conform").get_formatter_info("ruff_format", bufnr).available then
@ -461,6 +478,11 @@ require("conform").setup({
-- have other formatters configured.
["_"] = { "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.
-- It will pass the table to conform.format().
-- This can also be a function that returns the table.
@ -479,6 +501,8 @@ require("conform").setup({
log_level = vim.log.levels.ERROR,
-- Conform will notify you when a formatter errors
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
formatters = {
my_formatter = {
@ -515,7 +539,6 @@ require("conform").setup({
-- Set to false to disable merging the config with the base definition
inherit = true,
-- 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
prepend_args = { "--use-tabs" },
-- 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` | | |
| | 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. |
| | 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. |
| | 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_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. |
### format(opts, callback)
@ -575,16 +600,23 @@ require("conform").formatters.my_formatter = {
Format a buffer
| Param | Type | Desc | |
| -------- | ---------------------------------------------------- | ----------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| -------- | ---------------------------------------------------- | ------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| opts | `nil\|conform.FormatOpts` | | |
| | 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) |
| | 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 |
| | undojoin | `nil\|boolean` | Use undojoin to merge formatting changes with previous edit (default false) |
| | formatters | `nil\|string[]` | List of formatters to run. Defaults to all formatters for the buffer filetype. |
| | 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. |
| | 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 |
| | 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\|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 |
| | 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 |
@ -605,6 +637,27 @@ Retrieve the available formatters for a buffer
| ----- | -------------- | ---- |
| 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(): conform.FormatterInfo[]` \
@ -620,15 +673,6 @@ Get information about a formatter (including availability)
| --------- | -------------- | ------------------------- |
| formatter | `string` | The name of the formatter |
| 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 -->
## Acknowledgements

View File

@ -17,8 +17,8 @@ OPTIONS *conform-option
lua = { "stylua" },
-- Conform will run multiple formatters sequentially
go = { "goimports", "gofmt" },
-- Use a sub-list to run only the first available formatter
javascript = { { "prettierd", "prettier" } },
-- You can also customize some of the format options for the filetype
rust = { "rustfmt", lsp_format = "fallback" },
-- You can use a function here to determine the formatters dynamically
python = function(bufnr)
if require("conform").get_formatter_info("ruff_format", bufnr).available then
@ -33,6 +33,11 @@ OPTIONS *conform-option
-- have other formatters configured.
["_"] = { "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.
-- It will pass the table to conform.format().
-- This can also be a function that returns the table.
@ -51,6 +56,8 @@ OPTIONS *conform-option
log_level = vim.log.levels.ERROR,
-- Conform will notify you when a formatter errors
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
formatters = {
my_formatter = {
@ -87,7 +94,6 @@ OPTIONS *conform-option
-- Set to false to disable merging the config with the base definition
inherit = true,
-- 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
prepend_args = { "--use-tabs" },
-- 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`
{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` I
f this is set, Conform will run the formatter on
{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_after_save} `nil|conform.FormatOpts|fun(bufnr: integer): nil|conform.FormatOpts` I
f this is set, Conform will run the formatter
{default_format_opts} `nil|conform.DefaultFormatOpts` The default
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
to conform.format(). This can also be a function
that returns the table.
@ -133,8 +159,11 @@ setup({opts}) *conform.setu
the location of the log file.
{notify_on_error} `nil|boolean` Conform will notify you when a
formatter errors (default true).
{formatters} `nil|table<string, conform.FormatterConfigOverride|fun(bufnr: integer): nil|conform.FormatterConfigOverride>` C
ustom formatters and overrides for built-in
{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.
format({opts}, {callback}): boolean *conform.format*
@ -143,31 +172,46 @@ format({opts}, {callback}): boolean *conform.forma
Parameters:
{opts} `nil|conform.FormatOpts`
{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 =
true.
{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.
{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.
{lsp_format} `nil|"never"|"fallback"|"prefer"|"first"|"last"` "fallbac
k" 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.
{quiet} `nil|boolean` Don't show any notifications for warnings
or failures. Defaults to false.
{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
{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
{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
{undojoin} `nil|boolean` Use undojoin to merge formatting
changes with previous edit (default false)
{formatters} `nil|string[]` List of formatters to run. Defaults
to all formatters for the buffer filetype.
{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
{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
formatting has completed
Returns:
@ -179,6 +223,18 @@ list_formatters({bufnr}): conform.FormatterInfo[] *conform.list_formatter
Parameters:
{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 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
{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*
@ -229,16 +279,19 @@ FORMATTERS *conform-formatter
respects readability.
`blue` - The slightly less uncompromising Python code formatter.
`bpfmt` - Android Blueprint file formatter.
`bsfmt` - A code formatter for BrighterScript (and BrightScript).
`buf` - A new way of working with Protocol Buffers.
`buildifier` - buildifier is a tool for formatting bazel BUILD and .bzl files
with a standard convention.
`cabal_fmt` - Format cabal files with cabal-fmt
`caramel_fmt` - Format Caramel code.
`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
heuristics.
`cljstyle` - Formatter for Clojure code.
`cmake_format` - Parse cmake listfiles and format them nicely.
`codespell` - Check code for common misspellings.
`crlfmt` - Formatter for CockroachDB's additions to the Go style guide.
`crystal` - Format Crystal code.
`csharpier` - The opinionated C# code formatter.
`cue_fmt` - Format CUE files using `cue fmt` command.
@ -246,12 +299,19 @@ FORMATTERS *conform-formatter
`darker` - Run black only on changed lines.
`dart_format` - Replace the whitespace in your program with formatting that
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,
JavaScript/JSON and markdown.
`dfmt` - Formatter for D source code.
`djlint` - ✨ HTML Template Linter and Formatter. Django - Jinja - Nunjucks -
Handlebars - GoLang.
`docformatter` - docformatter automatically formats docstrings to follow a
subset of the PEP 257 conventions.
`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.
`easy-coding-standard` - ecs - Use Coding Standard with 0-knowledge of PHP-CS-
Fixer and PHP_CodeSniffer.
@ -278,6 +338,7 @@ FORMATTERS *conform-formatter
`gdformat` - A formatter for Godot's gdscript.
`gersemi` - A formatter to make your CMake code the real treasure.
`gleam` - ⭐️ A friendly language for building type-safe, scalable systems!
`gluon_fmt` - Code formatting for the gluon programming language.
`gn` - gn build system.
`gofmt` - Formats go programs.
`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.
`google-java-format` - Reformats Java source code according to Google Java
Style.
`grain_format` - Code formatter for the grain programming language.
`hcl` - A formatter for HCL files.
`hindent` - Haskell pretty printer.
`htmlbeautifier` - A normaliser/beautifier for HTML that also understands
embedded Ruby. Ideal for tidying up Rails templates.
`imba_fmt` - Code formatter for the Imba programming language.
`indent` - GNU Indent.
`injected` - Format treesitter injected languages.
`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
every sentence.
`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
official style guide.
`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.
`shellharden` - The corrective bash syntax highlighter.
`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.
`snakefmt` - a formatting tool for Snakemake files following the design of
Black.
@ -398,6 +463,7 @@ FORMATTERS *conform-formatter
`swift build`.
`swiftformat` - SwiftFormat is a code library and command-line tool for
reformatting `swift` code on macOS or Linux.
`swiftlint` - A tool to enforce Swift style and conventions.
`taplo` - A TOML toolkit written in Rust.
`templ` - Formats templ template files.
`terraform_fmt` - The terraform-fmt command rewrites `terraform` configuration
@ -407,8 +473,8 @@ FORMATTERS *conform-formatter
formatting.
`tofu_fmt` - The tofu-fmt command rewrites OpenTofu configuration files to a
canonical format and style.
`trim_newlines` - Trim new lines with awk.
`trim_whitespace` - Trim whitespaces with awk.
`trim_newlines` - Trim empty lines at the end of the file.
`trim_whitespace` - Trim trailing whitespace.
`twig-cs-fixer` - Automatically fix Twig Coding Standards issues
`typos` - Source code spell checker
`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)
- [Automatically run slow formatters async](#automatically-run-slow-formatters-async)
- [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 -->
@ -149,22 +151,28 @@ return {
-- Customize or remove this keymap to your liking
"<leader>f",
function()
require("conform").format({ async = true, lsp_format = "fallback" })
require("conform").format({ async = true })
end,
mode = "",
desc = "Format buffer",
},
},
-- Everything in opts will be passed to setup()
-- This will provide type hinting with LuaLS
---@module "conform"
---@type conform.setupOpts
opts = {
-- Define your formatters
formatters_by_ft = {
lua = { "stylua" },
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
format_on_save = { timeout_ms = 500, lsp_format = "fallback" },
format_on_save = { timeout_ms = 500 },
-- Customize formatters
formatters = {
shfmt = {
@ -178,3 +186,51 @@ return {
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.list_all_formatters conform.txt /*conform.list_all_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.setup conform.txt /*conform.setup*
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"),
stdin = true,
args = { "check", "--apply", "--stdin-file-path", "$FILENAME" },
args = { "check", "--write", "--stdin-file-path", "$FILENAME" },
cwd = util.root_file({
"biome.json",
"biome.jsonc",

View File

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

View File

@ -136,12 +136,6 @@ return {
-- (defaults to the value from formatters_by_ft)
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)
local conform = require("conform")
local errors = require("conform.errors")
@ -284,13 +278,21 @@ return {
---@type string[]
local formatter_names
if type(ft_formatters) == "function" then
formatter_names = ft_formatters(ctx.buf)
else
local formatters = require("conform").resolve_formatters(ft_formatters, ctx.buf, false)
ft_formatters = ft_formatters(ctx.buf)
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)
end
local idx = num_format
log.debug("Injected format %s:%d:%d: %s", lang, start_lnum, end_lnum, formatter_names)
log.trace("Injected format lines %s", input_lines)

View File

@ -6,10 +6,10 @@ return {
},
command = "markdown-toc",
stdin = false,
args = function(self, ctx)
args = function(_, ctx)
-- use the indentation set in the current buffer, effectively allowing us to
-- 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" }
end,
}

View File

@ -5,5 +5,15 @@ return {
description = "A shell parser, formatter, and interpreter with `bash` support.",
},
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 {
meta = {
url = "https://www.gnu.org/software/gawk/manual/gawk.html",
description = "Trim new lines with awk.",
url = "https://github.com/stevearc/conform.nvim/blob/master/lua/conform/formatters/trim_whitespace.lua",
description = "Trim empty lines at the end of the file.",
},
command = "awk",
args = { 'NF{print s $0; s=""; next} {s=s ORS}' },
format = function(self, ctx, lines, callback)
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 {
meta = {
url = "https://www.gnu.org/software/gawk/manual/gawk.html",
description = "Trim whitespaces with awk.",
url = "https://github.com/stevearc/conform.nvim/blob/master/lua/conform/formatters/trim_whitespace.lua",
description = "Trim trailing whitespace.",
},
command = "awk",
args = { '{ sub(/[ \t]+$/, ""); print }' },
format = function(self, ctx, lines, callback)
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_info = vim.health.info or vim.health.report_info
local health_ok = vim.health.ok or vim.health.report_ok
local islist = vim.islist or vim.tbl_islist
---@param name string
---@return string[]
@ -16,14 +15,6 @@ local function get_formatter_filetypes(name)
for filetype, formatters in pairs(conform.formatters_by_ft) do
if type(formatters) == "function" then
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
for _, ft_name in ipairs(formatters) do
@ -61,7 +52,7 @@ M.check = function()
end
end
---@param formatters conform.FormatterUnit[]
---@param formatters conform.FiletypeFormatterInternal
---@return string[]
local function flatten_formatters(formatters)
local flat = {}

View File

@ -1,5 +1,3 @@
---@diagnostic disable-next-line: deprecated
local islist = vim.islist or vim.tbl_islist
local M = {}
---@type table<string, conform.FiletypeFormatter>
@ -9,20 +7,72 @@ M.formatters_by_ft = {}
M.formatters = {}
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
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 {}
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 {})
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
require("conform.log").level = opts.log_level
end
local notify_on_error = opts.notify_on_error
if notify_on_error ~= nil then
M.notify_on_error = notify_on_error
if opts.notify_on_error ~= nil then
M.notify_on_error = opts.notify_on_error
end
if opts.notify_no_formatters ~= nil then
M.notify_no_formatters = opts.notify_no_formatters
end
local aug = vim.api.nvim_create_augroup("Conform", { clear = true })
@ -44,7 +94,7 @@ M.setup = function(opts)
end
if format_args then
if format_args.async then
vim.notify_once(
notify_once(
"Conform format_on_save cannot use async=true. Use format_after_save instead.",
vim.log.levels.ERROR
)
@ -97,7 +147,7 @@ M.setup = function(opts)
exit_timeout = format_args.timeout_ms or exit_timeout
num_running_format_jobs = num_running_format_jobs + 1
if format_args.async == false then
vim.notify_once(
notify_once(
"Conform format_after_save cannot use async=false. Use format_on_save instead.",
vim.log.levels.ERROR
)
@ -174,7 +224,7 @@ end
---Get the configured formatter filetype for a buffer
---@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)
if not bufnr or bufnr == 0 then
bufnr = vim.api.nvim_get_current_buf()
@ -193,7 +243,7 @@ end
---@private
---@param bufnr? integer
---@return conform.FormatterUnit[]
---@return string[]
M.list_formatters_for_buffer = function(bufnr)
if not bufnr or bufnr == 0 then
bufnr = vim.api.nvim_get_current_buf()
@ -204,6 +254,10 @@ M.list_formatters_for_buffer = function(bufnr)
local function dedupe_formatters(names, collect)
for _, name in ipairs(names) do
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 = {}
dedupe_formatters(name, alternation)
if not vim.tbl_isempty(alternation) then
@ -228,16 +282,6 @@ M.list_formatters_for_buffer = function(bufnr)
if type(ft_formatters) == "function" then
dedupe_formatters(ft_formatters(bufnr), formatters)
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)
end
end
@ -246,6 +290,25 @@ M.list_formatters_for_buffer = function(bufnr)
return formatters
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 mode "v"|"V"
---@return table {start={row,col}, end={row,col}} using (1, 0) indexing
@ -278,17 +341,18 @@ local function range_from_selection(bufnr, mode)
end
---@private
---@param names conform.FormatterUnit[]
---@param names conform.FiletypeFormatterInternal
---@param bufnr integer
---@param warn_on_missing boolean
---@param stop_after_first boolean
---@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 function add_info(info, warn)
if info.available then
table.insert(all_info, info)
elseif warn then
vim.notify(
notify(
string.format("Formatter '%s' unavailable: %s", info.name, info.available_msg),
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)
add_info(info, warn_on_missing)
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
for i, v in ipairs(name) do
local info = M.get_formatter_info(v, bufnr)
@ -309,6 +377,10 @@ M.resolve_formatters = function(names, bufnr, warn_on_missing)
end
end
end
if stop_after_first and #all_info > 0 then
break
end
end
return all_info
end
@ -328,33 +400,34 @@ local function has_lsp_formatter(opts)
return not vim.tbl_isempty(lsp_format.get_format_clients(opts))
end
---@class conform.FormatOpts
---@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
local has_notified_ft_no_formatters = {}
---Format a buffer
---@param opts? conform.FormatOpts
---@param callback? fun(err: nil|string, did_edit: nil|boolean) Called once formatting has completed
---@return boolean True if any formatters were attempted
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 = vim.tbl_extend("keep", opts or {}, {
opts = 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,
bufnr = 0,
async = false,
dry_run = false,
lsp_format = "never",
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
---@diagnostic disable-next-line: undefined-field
@ -365,9 +438,6 @@ M.format = function(opts, callback)
opts.lsp_format = "last"
end
if opts.bufnr == 0 then
opts.bufnr = vim.api.nvim_get_current_buf()
end
local mode = vim.api.nvim_get_mode().mode
if not opts.range and mode == "v" or mode == "V" then
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 runner = require("conform.runner")
local explicit_formatters = opts.formatters ~= nil
local formatter_names = opts.formatters or M.list_formatters_for_buffer(opts.bufnr)
local formatters =
M.resolve_formatters(formatter_names, opts.bufnr, not opts.quiet and explicit_formatters)
local formatters = M.resolve_formatters(
formatter_names,
opts.bufnr,
not opts.quiet and has_explicit_formatters,
opts.stop_after_first
)
local has_lsp = has_lsp_formatter(opts)
---Handle errors and maybe run LSP formatting after cli formatters complete
---@param err? conform.Error
---@param did_edit? boolean
local function handle_result(err, did_edit)
if err then
local level = errors.level_for_code(err.code)
log.log(level, err.message)
---@type boolean?
local should_notify = not opts.quiet and level >= vim.log.levels.WARN
-- Execution errors have special handling. Maybe should reconsider this.
local notify_msg = err.message
@ -398,7 +473,7 @@ M.format = function(opts, callback)
notify_msg = "Formatter failed. See :ConformInfo for details"
end
if should_notify then
vim.notify(notify_msg, level)
notify(notify_msg, level)
end
end
local err_message = err and err.message
@ -418,12 +493,15 @@ M.format = function(opts, callback)
callback(nil, did_edit)
end
end
---Run the resolved formatters on the buffer
local function run_cli_formatters(cb)
local resolved_names = vim.tbl_map(function(f)
return f.name
end, formatters)
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
runner.format_async(opts.bufnr, formatters, opts.range, run_opts, cb)
else
@ -461,19 +539,25 @@ M.format = function(opts, callback)
run_cli_formatters(handle_result)
return true
else
local level = explicit_formatters and "warn" or "debug"
log[level]("No formatters found for %s", vim.api.nvim_buf_get_name(opts.bufnr))
callback("No formatters found for buffer")
local level = has_explicit_formatters and "warn" or "debug"
log[level]("Formatters unavailable for %s", vim.api.nvim_buf_get_name(opts.bufnr))
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
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
---@private
---@param formatter_names string[]
@ -483,18 +567,20 @@ end
---@return nil|conform.Error error Only present if async = false
---@return nil|string[] new_lines Only present if async = false
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 {}, {
timeout_ms = 1000,
bufnr = 0,
async = false,
quiet = false,
stop_after_first = false,
})
callback = callback or function(_err, _lines) end
local errors = require("conform.errors")
local log = require("conform.log")
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
callback(nil, lines)
return
@ -510,7 +596,8 @@ M.format_lines = function(formatter_names, lines, opts, callback)
callback(err, new_lines)
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
runner.format_lines_async(opts.bufnr, formatters, nil, lines, run_opts, handle_err)
else
@ -529,7 +616,44 @@ M.list_formatters = function(bufnr)
bufnr = vim.api.nvim_get_current_buf()
end
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
---List information about all filetype-configured formatters
@ -540,18 +664,13 @@ M.list_all_formatters = function()
if type(ft_formatters) == "function" then
ft_formatters = ft_formatters(0)
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
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
formatters[v] = true
end
@ -590,7 +709,7 @@ M.get_formatter_config = function(formatter, bufnr)
if override and override.command and override.format then
local msg =
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
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
)
vim.notify_once(msg, vim.log.levels.ERROR)
notify_once(msg, vim.log.levels.ERROR)
return nil
end
else
@ -696,9 +815,14 @@ M.get_formatter_info = function(formatter, bufnr)
end
---Check if the buffer will use LSP formatting when lsp_format = "fallback"
---@deprecated
---@param options? table Options passed to |vim.lsp.buf.format|
---@return boolean
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 {}, {
bufnr = vim.api.nvim_get_current_buf(),
})

View File

@ -4,7 +4,7 @@ local util = require("vim.lsp.util")
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
#text_edits == 1
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,
nil,
false,
dry_run
dry_run,
undojoin
)
elseif dry_run then
return #text_edits > 0
else
if undojoin then
vim.cmd.undojoin()
end
vim.lsp.util.apply_text_edits(text_edits, bufnr, offset_encoding)
return #text_edits > 0
end
@ -124,8 +128,13 @@ function M.format(options, callback)
)
)
else
local this_did_edit =
apply_text_edits(result, ctx.bufnr, client.offset_encoding, options.dry_run)
local this_did_edit = apply_text_edits(
result,
ctx.bufnr,
client.offset_encoding,
options.dry_run,
options.undojoin
)
changedtick = vim.b[bufnr].changedtick
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 result, err = client.request_sync(method, params, timeout_ms, bufnr)
if result and result.result then
local this_did_edit =
apply_text_edits(result.result, bufnr, client.offset_encoding, options.dry_run)
local this_did_edit = apply_text_edits(
result.result,
bufnr,
client.offset_encoding,
options.dry_run,
options.undojoin
)
did_edit = did_edit or this_did_edit
if options.dry_run and did_edit then

View File

@ -9,6 +9,7 @@ local M = {}
---@class (exact) conform.RunOpts
---@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 undojoin boolean Use undojoin to merge formatting changes with previous edit
---@param formatter_name string
---@param ctx conform.Context
@ -168,8 +169,18 @@ end
---@param new_lines string[]
---@param range? conform.Range
---@param only_apply_range boolean
---@param dry_run boolean
---@param undojoin boolean
---@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
bufnr = vim.api.nvim_get_current_buf()
end
@ -251,6 +262,9 @@ M.apply_format = function(bufnr, original_lines, new_lines, range, only_apply_ra
if not dry_run then
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")
log.trace("Done formatting %s", bufname)
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)
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
---@type table<string, boolean>
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 stderr: %s", formatter.name, stderr)
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")
elseif stdout and not vim.tbl_isempty(stdout) then
elseif not is_empty_output(stdout) then
err_str = table.concat(stdout, "\n")
else
err_str = "unknown error"
end
if
vim.api.nvim_buf_is_valid(bufnr)
@ -450,6 +472,11 @@ M.build_context = function(bufnr, config, range)
end
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
if vim.bo[bufnr].buftype ~= "" then
filename = ""
@ -482,6 +509,7 @@ M.build_context = function(bufnr, config, range)
filename = filename,
dirname = dirname,
range = range,
shiftwidth = shiftwidth,
}
end
@ -529,7 +557,8 @@ M.format_async = function(bufnr, formatters, range, opts, callback)
output_lines,
range,
not all_support_range_formatting,
opts.dry_run
opts.dry_run,
opts.undojoin
)
end
callback(err, did_edit)
@ -603,7 +632,8 @@ M.format_sync = function(bufnr, formatters, timeout_ms, range, opts)
final_result,
range,
not all_support_range_formatting,
opts.dry_run
opts.dry_run,
opts.undojoin
)
return err, did_edit
end

View File

@ -49,6 +49,7 @@
---@field filename string
---@field dirname string
---@field range? conform.Range
---@field shiftwidth integer
---@class (exact) conform.RangeContext : conform.Context
---@field range conform.Range
@ -57,13 +58,53 @@
---@field start integer[]
---@field end integer[]
---@alias conform.FormatterUnit string|string[]
---@alias conform.FiletypeFormatter conform.FormatterUnit[]|fun(bufnr: integer): string[]
---@alias conform.FiletypeFormatter conform.FiletypeFormatterInternal|fun(bufnr: integer): conform.FiletypeFormatterInternal
---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
---@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 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 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_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.

View File

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

View File

@ -4,8 +4,8 @@ require("conform").setup({
lua = { "stylua" },
-- Conform will run multiple formatters sequentially
go = { "goimports", "gofmt" },
-- Use a sub-list to run only the first available formatter
javascript = { { "prettierd", "prettier" } },
-- You can also customize some of the format options for the filetype
rust = { "rustfmt", lsp_format = "fallback" },
-- You can use a function here to determine the formatters dynamically
python = function(bufnr)
if require("conform").get_formatter_info("ruff_format", bufnr).available then
@ -20,6 +20,11 @@ require("conform").setup({
-- have other formatters configured.
["_"] = { "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.
-- It will pass the table to conform.format().
-- This can also be a function that returns the table.
@ -38,6 +43,8 @@ require("conform").setup({
log_level = vim.log.levels.ERROR,
-- Conform will notify you when a formatter errors
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
formatters = {
my_formatter = {
@ -74,7 +81,6 @@ require("conform").setup({
-- Set to false to disable merging the config with the base definition
inherit = true,
-- 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
prepend_args = { "--use-tabs" },
-- 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

View File

@ -25,7 +25,7 @@ describe("fuzzer", function()
vim.api.nvim_set_current_buf(bufnr)
vim.api.nvim_buf_set_lines(bufnr, 0, -1, true, buf_content)
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))
end

View File

@ -4,11 +4,6 @@ local injected = require("conform.formatters.injected")
local runner = require("conform.runner")
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
---@return string[]
local function list_test_files(dir)

View File

@ -59,11 +59,36 @@ describe("runner", function()
local config = assert(conform.get_formatter_config("test"))
local ctx = runner.build_context(0, config)
local filename = vim.api.nvim_buf_get_name(bufnr)
assert.are.same({
buf = bufnr,
filename = filename,
dirname = vim.fs.dirname(filename),
}, ctx)
assert.equal(bufnr, ctx.buf)
assert.equal(filename, ctx.filename)
assert.equal(vim.fs.dirname(filename), ctx.dirname)
end)
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)
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
disable_move -- default is false disable move keymap for hyper
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
config = {}, -- config used for theme
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*
@ -68,6 +68,7 @@ OPTIONS *dashboard-configuration-options*
theme = 'hyper' -- theme is doom and hyper default is hyper
disable_move -- default is false disable move keymap for hyper
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
config = {}, -- config used for theme
hide = {

View File

@ -36,6 +36,7 @@ local function default_options()
theme = 'hyper',
disable_move = false,
shortcut_type = 'letter',
shuffle_letter = false,
buffer_name = 'Dashboard',
change_to_vcs_root = false,
config = {
@ -76,7 +77,6 @@ local function buf_local()
['filetype'] = 'dashboard',
['wrap'] = false,
['signcolumn'] = 'no',
['winbar'] = '',
}
for opt, val in pairs(opts) do
vim.opt_local[opt] = val
@ -94,6 +94,7 @@ function db:save_user_options()
self.user_cursor_line = vim.opt.cursorline:get()
self.user_laststatus_value = vim.opt.laststatus:get()
self.user_tabline_value = vim.opt.showtabline:get()
self.user_winbar_value = vim.opt.winbar:get()
end
function db:set_ui_options(opts)
@ -103,6 +104,9 @@ function db:set_ui_options(opts)
if opts.hide.tabline then
vim.opt.showtabline = 0
end
if opts.hide.winbar then
vim.opt.winbar = ''
end
end
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
vim.opt.showtabline = tonumber(self.user_tabline_value)
end
if opts.hide.winbar and self.user_winbar_value then
vim.opt.winbar = self.user_winbar_value
end
end
function db:cache_opts()
@ -190,6 +198,7 @@ function db:load_theme(opts)
winid = self.winid,
confirm_key = opts.confirm_key or nil,
shortcut_type = opts.shortcut_type,
shuffle_letter = opts.shuffle_letter,
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
-- the number of characters.
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))
if offset < 0 then
offset = 0
local strwidth = api.nvim_strwidth(curline_str:sub(1, col + 1))
local col_with_offset = col + col_width - strwidth
if col_with_offset < 0 then
col_with_offset = 0
end
api.nvim_win_set_cursor(config.winid, { curline, col + offset })
api.nvim_win_set_cursor(config.winid, { curline, col_with_offset })
end,
})
end, 0)

View File

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

View File

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

View File

@ -6,7 +6,10 @@ body:
- type: markdown
attributes:
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
attributes:
label: Did you check docs and existing issues?
@ -14,6 +17,8 @@ body:
options:
- label: I have read all the flash.nvim docs
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
required: true
- label: I have searched the existing issues of plugins related to this issue
@ -57,33 +62,15 @@ body:
label: Repro
description: Minimal `init.lua` to reproduce this issue. Save as `repro.lua` and run with `nvim -u repro.lua`
value: |
-- DO NOT change the paths and don't remove the colorscheme
local root = vim.fn.fnamemodify("./.repro", ":p")
vim.env.LAZY_STDPATH = ".repro"
load(vim.fn.system("curl -s https://raw.githubusercontent.com/folke/lazy.nvim/main/bootstrap.lua"))()
-- set stdpaths to use .repro
for _, name in ipairs({ "config", "data", "state", "cache" }) do
vim.env[("XDG_%s_HOME"):format(name:upper())] = root .. "/" .. name
end
-- 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",
require("lazy.minit").repro({
spec = {
{ "folke/flash.nvim", opts = {} },
-- add any other plugins here
}
require("lazy").setup(plugins, {
root = root .. "/plugins",
},
})
vim.cmd.colorscheme("tokyonight")
-- add anything else here
render: Lua
render: lua
validations:
required: false

View File

@ -1,72 +1,14 @@
name: CI
on:
push:
branches: [main, master]
pull_request:
jobs:
tests:
strategy:
matrix:
# os: [ubuntu-latest, windows-latest]
os: [ubuntu-latest]
runs-on: ${{ matrix.os }}
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
ci:
uses: folke/github/.github/workflows/ci.yml@main
secrets: inherit
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
plugin: flash.nvim
repo: folke/flash.nvim

View File

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

View File

@ -1,5 +1,37 @@
# 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)

View File

@ -292,13 +292,18 @@ Install the plugin with your preferred package manager:
end,
search = { wrap = false },
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
-- `require("flash").treesitter()`
treesitter = {
labels = "abcdefghijklmnopqrstuvwxyz",
jump = { pos = "range" },
jump = { pos = "range", autojump = true },
search = { incremental = false },
label = { before = true, after = true, style = "inline" },
highlight = {
@ -319,6 +324,7 @@ Install the plugin with your preferred package manager:
},
-- options for the floating window that shows the prompt,
-- for regular jumps
-- `require("flash").prompt()` is always available to get the prompt text
prompt = {
enabled = true,
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
- type any number of characters before typing a jump label
- **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
## 📡 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*
@ -281,13 +281,18 @@ Default Settings ~
end,
search = { wrap = false },
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
-- `require("flash").treesitter()`
treesitter = {
labels = "abcdefghijklmnopqrstuvwxyz",
jump = { pos = "range" },
jump = { pos = "range", autojump = true },
search = { incremental = false },
label = { before = true, after = true, style = "inline" },
highlight = {
@ -308,6 +313,7 @@ Default Settings ~
},
-- options for the floating window that shows the prompt,
-- for regular jumps
-- `require("flash").prompt()` is always available to get the prompt text
prompt = {
enabled = true,
prefix = { { "⚡", "FlashPromptIcon" } },
@ -390,7 +396,8 @@ USAGE *flash.nvim-flash.nvim-usage*
- type any number of characters before typing a jump label
- **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

View File

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

View File

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

View File

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

View File

@ -50,10 +50,7 @@ function M:reset()
skip[l] = true
end
end
if
not self.state.opts.search.max_length
or #self.state.pattern() < self.state.opts.search.max_length
then
if 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
self.labels = self:skip(win, self.labels)
end

View File

@ -46,8 +46,7 @@ function M.new()
}, M.motions[M.motion])
-- never show the current match label
opts.highlight.groups.current = M.motion:lower() == "f" and opts.highlight.groups.label
or opts.highlight.groups.match
opts.highlight.groups.current = M.motion:lower() == "f" and opts.highlight.groups.label or opts.highlight.groups.match
-- exclude the motion labels so we can use them for next/prev
opts.labels = opts.labels:gsub(M.motion:lower(), "")
@ -241,7 +240,7 @@ function M.jump(key)
M.state:update({ force = true })
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()
return M.state
end

View File

@ -9,7 +9,7 @@ local M = {}
---@field node TSNode
---@field depth? number
---@param win window
---@param win number
---@param pos? Pos
function M.get_nodes(win, pos)
local buf = vim.api.nvim_win_get_buf(win)
@ -18,7 +18,7 @@ function M.get_nodes(win, pos)
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
vim.notify(
"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>")
end
if not (ok and tree) then
if not (ok and parser) then
return {}
end
do
parser:for_each_tree(function(tstree, tree)
if not tstree then
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 = false,
ignore_injections = true,
})
while node do
nodes[#nodes + 1] = node
node = node:parent() ---@type TSNode
end
end)
end
-- 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.
if match.end_pos[1] > line_count then
match.end_pos[1] = line_count
match.end_pos[2] =
#vim.api.nvim_buf_get_lines(buf, match.end_pos[1] - 1, match.end_pos[1], false)[1]
match.end_pos[2] = #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
-- If the end points to the start of the next line, move it to the
-- end of the previous line.
-- Otherwise operations include the first character of the next line
local line =
vim.api.nvim_buf_get_lines(buf, match.end_pos[1] - 2, match.end_pos[1] - 1, false)[1]
local line = 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[2] = #line
end
@ -121,11 +124,13 @@ function M.jump(opts)
current = m
end
end
if state.opts.jump.autojump then
current = state:jump(current)
end
state:loop({
abort = function()
vim.cmd([[normal! v]])
Util.exit()
end,
actions = {
[";"] = function()
@ -174,7 +179,11 @@ function M.search(opts)
end)
local state = Repeat.get_state("treesitter-search", opts)
state:loop()
state:loop({
abort = function()
Util.exit()
end,
})
return state
end

View File

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

View File

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

View File

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

View File

@ -1,5 +1,6 @@
indent_type = "Spaces"
indent_width = 2
column_width = 100
column_width = 120
[sort_requires]
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]
any = true
[[describe.args]]
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]
[assert]
any = true
[[assert.equals.args]]
type = "any"
[[assert.equals.args]]
type = "any"
[[assert.equals.args]]
type = "any"
required = false
[describe]
any = true
[[assert.same.args]]
type = "any"
[[assert.same.args]]
type = "any"
[it]
any = true
[[assert.truthy.args]]
type = "any"
[[assert.spy.args]]
type = "any"
[[assert.stub.args]]
type = "any"
[before_each.args]
any = true

View File

@ -42,6 +42,15 @@ of the default settings:
changedelete = { 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`
numhl = false, -- Toggle with `:Gitsigns toggle_numhl`
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
in a scroll-bound vertical split.
<CR> is mapped to open a menu with the actions:
- [Show commit] in a vertical split.
- [Reblame at commit]
Mappings:
<CR> is mapped to open a menu with the other mappings
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: ~
{async}
@ -308,8 +321,6 @@ blame_line({opts}, {callback?}) *gitsigns.blame_line()*
Display full commit message with hunk.
• {ignore_whitespace}: (boolean)
Ignore whitespace when running blame.
• {rev}: (string)
Revision to blame against.
• {extra_opts}: (string[])
Extra options passed to `git-blame`.
@ -561,6 +572,7 @@ signs *gitsigns-config-signs*
• `GitSignsAdd` (for normal text signs)
• `GitSignsAddNr` (for signs when `config.numhl == true`)
• `GitSignsAddLn `(for signs when `config.linehl == true`)
• `GitSignsAddCul `(for signs when `config.culhl == true`)
See |gitsigns-highlight-groups|.
@ -675,6 +687,16 @@ linehl *gitsigns-config-linehl*
the highlight group does not exist, then it is automatically defined
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*
Type: `boolean`, Default: `false`
@ -1030,6 +1052,36 @@ GitSignsUntrackedLn
Used for buffer line (when `config.linehl == true`) of 'untracked' signs.
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*
GitSignsAddPreview
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:

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-base gitsigns.txt /*gitsigns-config-base*
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_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*
@ -82,21 +83,25 @@ gitsigns.toggle_word_diff() gitsigns.txt /*gitsigns.toggle_word_diff()*
gitsigns.txt gitsigns.txt /*gitsigns.txt*
gitsigns.undo_stage_hunk() gitsigns.txt /*gitsigns.undo_stage_hunk()*
hl-GitSignsAdd gitsigns.txt /*hl-GitSignsAdd*
hl-GitSignsAddCul gitsigns.txt /*hl-GitSignsAddCul*
hl-GitSignsAddInline gitsigns.txt /*hl-GitSignsAddInline*
hl-GitSignsAddLn gitsigns.txt /*hl-GitSignsAddLn*
hl-GitSignsAddLnInline gitsigns.txt /*hl-GitSignsAddLnInline*
hl-GitSignsAddNr gitsigns.txt /*hl-GitSignsAddNr*
hl-GitSignsAddPreview gitsigns.txt /*hl-GitSignsAddPreview*
hl-GitSignsChange gitsigns.txt /*hl-GitSignsChange*
hl-GitSignsChangeCul gitsigns.txt /*hl-GitSignsChangeCul*
hl-GitSignsChangeInline gitsigns.txt /*hl-GitSignsChangeInline*
hl-GitSignsChangeLn gitsigns.txt /*hl-GitSignsChangeLn*
hl-GitSignsChangeLnInline gitsigns.txt /*hl-GitSignsChangeLnInline*
hl-GitSignsChangeNr gitsigns.txt /*hl-GitSignsChangeNr*
hl-GitSignsChangedelete gitsigns.txt /*hl-GitSignsChangedelete*
hl-GitSignsChangedeleteCul gitsigns.txt /*hl-GitSignsChangedeleteCul*
hl-GitSignsChangedeleteLn gitsigns.txt /*hl-GitSignsChangedeleteLn*
hl-GitSignsChangedeleteNr gitsigns.txt /*hl-GitSignsChangedeleteNr*
hl-GitSignsCurrentLineBlame gitsigns.txt /*hl-GitSignsCurrentLineBlame*
hl-GitSignsDelete gitsigns.txt /*hl-GitSignsDelete*
hl-GitSignsDeleteCul gitsigns.txt /*hl-GitSignsDeleteCul*
hl-GitSignsDeleteInline gitsigns.txt /*hl-GitSignsDeleteInline*
hl-GitSignsDeleteLnInline gitsigns.txt /*hl-GitSignsDeleteLnInline*
hl-GitSignsDeleteNr gitsigns.txt /*hl-GitSignsDeleteNr*
@ -104,8 +109,10 @@ hl-GitSignsDeletePreview gitsigns.txt /*hl-GitSignsDeletePreview*
hl-GitSignsDeleteVirtLn gitsigns.txt /*hl-GitSignsDeleteVirtLn*
hl-GitSignsDeleteVirtLnInLine gitsigns.txt /*hl-GitSignsDeleteVirtLnInLine*
hl-GitSignsTopdelete gitsigns.txt /*hl-GitSignsTopdelete*
hl-GitSignsTopdeleteCul gitsigns.txt /*hl-GitSignsTopdeleteCul*
hl-GitSignsTopdeleteNr gitsigns.txt /*hl-GitSignsTopdeleteNr*
hl-GitSignsUntracked gitsigns.txt /*hl-GitSignsUntracked*
hl-GitSignsUntrackedCul gitsigns.txt /*hl-GitSignsUntrackedCul*
hl-GitSignsUntrackedLn gitsigns.txt /*hl-GitSignsUntrackedLn*
hl-GitSignsUntrackedNr gitsigns.txt /*hl-GitSignsUntrackedNr*
hl-GitSignsVirtLnum gitsigns.txt /*hl-GitSignsVirtLnum*

View File

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

View File

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

View File

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

View File

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

View File

@ -22,9 +22,12 @@ local M = {
--- @field blame? table<integer,Gitsigns.BlameInfo?>
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'
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
--- 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)
end)
--- @async
--- @private
function CacheEntry:wait_for_hunks()
local loop_protect = 0
@ -65,71 +69,61 @@ end
-- If a file contains has up to this amount of lines, then
-- always blame the whole file, otherwise only blame one line
-- at a time.
local BLAME_THRESHOLD_LEN = 1000000
local BLAME_THRESHOLD_LEN = 10000
--- @async
--- @private
--- @param lnum? integer
--- @param opts Gitsigns.BlameOpts
--- @return table<integer,Gitsigns.BlameInfo?>?
--- @param opts? Gitsigns.BlameOpts
--- @return table<integer,Gitsigns.BlameInfo?>
--- @return boolean? full
function CacheEntry:run_blame(lnum, opts)
local bufnr = self.bufnr
local blame_cache --- @type table<integer,Gitsigns.BlameInfo?>?
local blame --- @type table<integer,Gitsigns.BlameInfo?>?
local lnum0 --- @type integer?
repeat
local buftext = util.buf_lines(bufnr, true)
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
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()
if not vim.api.nvim_buf_is_valid(bufnr) then
return
return {}
end
until vim.b[bufnr].changedtick == tick
return blame_cache
return blame, lnum0 == nil
end
--- @param file string
--- @param lnum integer
--- @return Gitsigns.BlameInfo
local function get_blame_nc(file, lnum)
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
--- If lnum is nil then run blame for the entire buffer.
--- @async
--- @param lnum? integer
--- @param opts? Gitsigns.BlameOpts
--- @return Gitsigns.BlameInfo?
function CacheEntry:get_blame(lnum, opts)
if opts.rev then
local buftext = util.buf_lines(self.bufnr)
return self.git_obj:run_blame(buftext, lnum, opts)[lnum]
end
local blame = self.blame
local blame_cache = self.blame
if not blame_cache or not blame_cache[lnum] then
if not blame or (lnum and not blame[lnum]) then
self:wait_for_hunks()
blame = blame or {}
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
blame_cache = blame_cache or {}
blame_cache[lnum] = get_blame_nc(self.git_obj.relpath, lnum)
local Blame = require('gitsigns.git.blame')
blame[lnum] = Blame.get_blame_nc(self.git_obj.relpath, lnum)
else
-- Refresh cache
blame_cache = self:run_blame(lnum, opts)
-- Refresh/update cache
local b, full = self:run_blame(lnum, opts)
if lnum and not full then
blame[lnum] = b[lnum]
else
blame = b
end
self.blame = blame_cache
end
self.blame = blame
end
if blame_cache then
return blame_cache[lnum]
end
return blame[lnum]
end
function CacheEntry:destroy()
@ -137,9 +131,10 @@ function CacheEntry:destroy()
if w and not w:is_closing() then
w:close()
end
self.git_obj.repo:unref()
end
---@type table<integer,Gitsigns.CacheEntry>
---@type table<integer,Gitsigns.CacheEntry?>
M.cache = {}
--- @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 argparse = require('gitsigns.cli.argparse')
local async = require('gitsigns.async')
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>
local sources = {
[actions] = true,
[attach] = false,
[gs_debug] = false,
[Debug] = false,
}
-- 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)
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]
@ -79,7 +75,7 @@ M.run = async.create(1, function(params)
local named_args = vim.tbl_map(parse_to_lua, named_args_raw)
local args = vim.tbl_extend('error', pos_args, named_args)
dprintf(
log.dprintf(
"Running action '%s' with arguments %s",
func,
vim.inspect(args, { newline = ' ', indent = '' })

View File

@ -25,6 +25,7 @@
--- @field text string
--- @field numhl string
--- @field linehl string
--- @field culhl string
--- @alias Gitsigns.SignType
--- | 'add'
@ -34,7 +35,7 @@
--- | 'changedelete'
--- | '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
--- @field virt_text? boolean
@ -44,7 +45,6 @@
--- @class (exact) Gitsigns.BlameOpts
--- @field ignore_whitespace? boolean
--- @field rev? string
--- @field extra_opts? string[]
--- @class (exact) Gitsigns.LineBlameOpts : Gitsigns.BlameOpts
@ -61,6 +61,7 @@
--- @field signcolumn boolean
--- @field numhl boolean
--- @field linehl boolean
--- @field culhl boolean
--- @field show_deleted boolean
--- @field sign_priority integer
--- @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
warnings = warnings or {}
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,
ty,
v
v,
v,
x[kind][ty]
)
warnings[w] = true
end
@ -210,36 +214,47 @@ M.schema = {
type = validate_signs,
deep_extend = true,
default = {
add = { hl = 'GitSignsAdd', text = '', numhl = 'GitSignsAddNr', linehl = 'GitSignsAddLn' },
add = {
hl = 'GitSignsAdd',
text = '',
numhl = 'GitSignsAddNr',
linehl = 'GitSignsAddLn',
culhl = 'GitSignsAddCul',
},
change = {
hl = 'GitSignsChange',
text = '',
numhl = 'GitSignsChangeNr',
linehl = 'GitSignsChangeLn',
culhl = 'GitSignsChangeCul',
},
delete = {
hl = 'GitSignsDelete',
text = '',
numhl = 'GitSignsDeleteNr',
linehl = 'GitSignsDeleteLn',
culhl = 'GitSignsDeleteCul',
},
topdelete = {
hl = 'GitSignsTopdelete',
text = '',
numhl = 'GitSignsTopdeleteNr',
linehl = 'GitSignsTopdeleteLn',
culhl = 'GitSignsTopdeleteCul',
},
changedelete = {
hl = 'GitSignsChangedelete',
text = '~',
numhl = 'GitSignsChangedeleteNr',
linehl = 'GitSignsChangedeleteLn',
culhl = 'GitSignsChangedeleteCul',
},
untracked = {
hl = 'GitSignsUntracked',
text = '',
numhl = 'GitSignsUntrackedNr',
linehl = 'GitSignsUntrackedLn',
culhl = 'GitSignsUntrackedCul',
},
},
default_help = [[{
@ -261,6 +276,7 @@ M.schema = {
• `GitSignsAdd` (for normal text signs)
• `GitSignsAddNr` (for signs when `config.numhl == true`)
• `GitSignsAddLn `(for signs when `config.linehl == true`)
• `GitSignsAddCul `(for signs when `config.culhl == true`)
See |gitsigns-highlight-groups|.
]],
@ -275,30 +291,35 @@ M.schema = {
text = '',
numhl = 'GitSignsStagedAddNr',
linehl = 'GitSignsStagedAddLn',
culhl = 'GitSignsStagedAddCul',
},
change = {
hl = 'GitSignsStagedChange',
text = '',
numhl = 'GitSignsStagedChangeNr',
linehl = 'GitSignsStagedChangeLn',
culhl = 'GitSignsStagedChangeCul',
},
delete = {
hl = 'GitSignsStagedDelete',
text = '',
numhl = 'GitSignsStagedDeleteNr',
linehl = 'GitSignsStagedDeleteLn',
culhl = 'GitSignsStagedDeleteCul',
},
topdelete = {
hl = 'GitSignsStagedTopdelete',
text = '',
numhl = 'GitSignsStagedTopdeleteNr',
linehl = 'GitSignsStagedTopdeleteLn',
culhl = 'GitSignsStagedTopdeleteCul',
},
changedelete = {
hl = 'GitSignsStagedChangedelete',
text = '~',
numhl = 'GitSignsStagedChangedeleteNr',
linehl = 'GitSignsStagedChangedeleteLn',
culhl = 'GitSignsStagedChangedeleteCul',
},
},
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 = {
type = 'boolean',
default = false,

View File

@ -1,11 +1,13 @@
local async = require('gitsigns.async')
local cache = require('gitsigns.cache').cache
local config = require('gitsigns.config').config
local debounce = require('gitsigns.debounce')
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')
@ -72,19 +74,31 @@ end
---@param bufnr integer
---@param blame_info Gitsigns.BlameInfoPublic
---@return {[1]: string, [2]:string}[]
---@return [string, string][]
local function get_blame_virt_text(bufnr, blame_info)
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'
and config.current_line_blame_formatter_nc
local clb_formatter = use_nc and config.current_line_blame_formatter_nc
or config.current_line_blame_formatter
if type(clb_formatter) == 'string' then
clb_formatter = default_formatter(clb_formatter)
if type(clb_formatter) == 'function' then
local ok, res = pcall(clb_formatter, git_obj.repo.username, blame_info)
if ok then
return res
end
return clb_formatter(git_obj.repo.username, blame_info)
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
return default_formatter(clb_formatter)(git_obj.repo.username, blame_info)
end
--- @param bufnr integer
@ -192,19 +206,25 @@ end
local update = async.create(1, debounce.throttle_by_id(update0))
--- @type fun(bufnr: integer)
local update_debounced
M.update = nil
function M.setup()
local group = api.nvim_create_augroup('gitsigns_blame', {})
local opts = config.current_line_blame_opts
update_debounced = debounce.debounce_trailing(opts.delay, update)
for k, _ in pairs(cache) do
for k in pairs(cache) do
reset(k)
end
if config.current_line_blame then
local group = api.nvim_create_augroup('gitsigns_blame', {})
if not config.current_line_blame then
return
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+
@ -215,7 +235,7 @@ function M.setup()
group = group,
callback = function(args)
reset(args.buf)
update_debounced(args.buf)
M.update(args.buf)
end,
})
@ -233,9 +253,6 @@ function M.setup()
reset(args.buf)
end,
})
update_debounced(api.nvim_get_current_buf())
end
end
return M

View File

@ -1,4 +1,4 @@
local uv = vim.loop
local uv = vim.uv or vim.loop
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 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 = {}
-- Async function
@ -61,7 +61,7 @@ function M.run_diff(text_cmp, text_buf)
for _, line in ipairs(out) do
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
local r = results[#results]
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 config = require('gitsigns.config').config
local async = require('gitsigns.async')
local M = {}

View File

@ -1,15 +1,15 @@
local api = vim.api
local async = require('gitsigns.async')
local cache = require('gitsigns.cache').cache
local util = require('gitsigns.util')
local manager = require('gitsigns.manager')
local message = require('gitsigns.message')
local util = require('gitsigns.util')
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 api = vim.api
local M = {}
--- @async
@ -17,7 +17,7 @@ local M = {}
--- @param dbufnr integer
--- @param base string?
local function bufread(bufnr, dbufnr, base)
local bcache = cache[bufnr]
local bcache = assert(cache[bufnr])
base = util.norm_base(base)
local text --- @type string[]
if base == bcache.git_obj.revision then
@ -52,8 +52,9 @@ end
--- @param bufnr integer
--- @param dbufnr integer
--- @param base string?
local bufwrite = async.create(3, function(bufnr, dbufnr, base)
local bcache = cache[bufnr]
--- @param _callback? fun()
local bufwrite = async.create(3, function(bufnr, dbufnr, base, _callback)
local bcache = assert(cache[bufnr])
local buftext = util.buf_lines(dbufnr)
base = util.norm_base(base)
bcache.git_obj:stage_lines(buftext)
@ -151,14 +152,17 @@ end
--- @param base string?
--- @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
log.dprint('diff is disabled')
return
end
local bufnr = api.nvim_get_current_buf()
local bcache = cache[bufnr]
if not bcache then
log.dprintf('buffer %d is not attached', bufnr)
return
end
@ -176,16 +180,24 @@ end)
--- @param bufnr integer
--- @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'
local bufname = create_show_buf(bufnr, base)
if not bufname then
dprint('No bufname for revision ' .. base)
log.dprint('No bufname for revision ' .. base)
return
end
dprint('bufname ' .. bufname)
log.dprint('bufname ' .. 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)
--- @param bufnr integer
@ -205,16 +217,15 @@ end
-- This function needs to be throttled as there is a call to vim.ui.input
--- @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
return
end
local bcache = cache[bufnr]
-- Note this will be the bufname for the currently set base
-- 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
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 util = require('gitsigns.util')
local system = require('gitsigns.system').system
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 Repo = require('gitsigns.git.repo')
local check_version = require('gitsigns.git.version').check
local M = {}
--- @type fun(cmd: string[], opts?: vim.SystemOpts): vim.SystemCompleted
local asystem = async.wrap(3, system)
M.Repo = Repo
--- @param file string
--- @return boolean
@ -48,78 +35,7 @@ local Obj = {}
M.Obj = Obj
--- @class Gitsigns.RepoInfo
--- @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
local git_command = require('gitsigns.git.cmd')
--- @async
--- @param file_cmp string
@ -145,224 +61,9 @@ function M.diff(file_cmp, file_buf, indent_heuristic, diff_algo)
})
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
function Obj:update_revision(revision)
revision = util.norm_base(revision)
self.revision = revision
self.revision = util.norm_base(revision)
self:update()
end
@ -434,7 +135,7 @@ function Obj:file_info_index(file, silent)
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
-- ignore_error for the cases when we run:
@ -481,7 +182,7 @@ end
--- @param silent? boolean
--- @return Gitsigns.FileInfo
function Obj:file_info_tree(file, silent)
local results, stderr = self:command({
local results, stderr = self.repo:command({
'-c',
'core.quotepath=off',
'ls-tree',
@ -516,14 +217,14 @@ end
--- @return string[] stdout, string? stderr
function Obj:get_show_text(revision)
if revision and not self.relpath then
dprint('no relpath')
log.dprint('no relpath')
return {}
end
local object = revision and (revision .. ':' .. self.relpath) or self.object_name
if not object then
dprint('no revision or object_name')
log.dprint('no revision or object_name')
return { '' }
end
@ -551,215 +252,17 @@ local function autocmd_changed(file)
end
function Obj:unstage_file()
self:command({ 'reset', self.file })
self.repo:command({ 'reset', self.file })
autocmd_changed(self.file)
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 lnum? integer
--- @param revision? string
--- @param opts? Gitsigns.BlameOpts
--- @return table<integer,Gitsigns.BlameInfo?>?
function Obj:run_blame(lines, lnum, opts)
local ret = {} --- @type table<integer,Gitsigns.BlameInfo>
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
--- @return table<integer,Gitsigns.BlameInfo?>
function Obj:run_blame(lines, lnum, revision, opts)
return require('gitsigns.git.blame').run_blame(self, lines, lnum, revision, opts)
end
--- @param obj Gitsigns.GitObj
@ -770,12 +273,12 @@ local function ensure_file_in_index(obj)
if not obj.object_name then
-- 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
-- Update the index with the common ancestor (stage 1) which is what bcache
-- stores
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
obj:update()
@ -784,17 +287,15 @@ end
--- Stage 'lines' as the entire contents of the file
--- @param lines string[]
function Obj:stage_lines(lines)
local stdout = self:command({
local new_object = self.repo:command({
'hash-object',
'-w',
'--path',
self.relpath,
'--stdin',
}, { stdin = lines })
}, { stdin = lines })[1]
local new_object = stdout[1]
self:command({
self.repo:command({
'update-index',
'--cacheinfo',
string.format('%s,%s,%s', self.mode_bits, new_object, self.relpath),
@ -808,9 +309,7 @@ end
function Obj:stage_hunks(hunks, invert)
ensure_file_in_index(self)
local gs_hunks = require('gitsigns.hunks')
local patch = gs_hunks.create_patch(self.relpath, hunks, self.mode_bits, invert)
local patch = require('gitsigns.hunks').create_patch(self.relpath, hunks, self.mode_bits, invert)
if not self.i_crlf and self.w_crlf then
-- Remove cr
@ -819,7 +318,7 @@ function Obj:stage_hunks(hunks, invert)
end
end
self:command({
self.repo:command({
'apply',
'--whitespace=nowarn',
'--cached',
@ -834,7 +333,7 @@ end
--- @return string?
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
for _, l in ipairs(out) do
local parts = vim.split(l, '%s+')
@ -858,24 +357,25 @@ end
--- @return Gitsigns.GitObj?
function Obj.new(file, revision, encoding, gitdir, toplevel)
if in_git_dir(file) then
dprint('In git dir')
log.dprint('In git dir')
return nil
end
local self = setmetatable({}, { __index = Obj })
if not vim.startswith(file, '/') and toplevel then
file = toplevel .. util.path_sep .. file
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.revision = util.norm_base(revision)
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
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
-- {GitSignsDeleteLn = {}},
@ -153,6 +195,11 @@ M.hls = {
{ GitSignsStagedDeleteLn = { 'GitSignsDeleteLn', fg_factor = 0.5, hidden = true } },
{ GitSignsStagedChangedeleteLn = { 'GitSignsChangedeleteLn', 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 = {

View File

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

View File

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

View File

@ -65,6 +65,7 @@ function M:add(bufnr, signs)
sign_hl_group = hls.hl,
number_hl_group = config.numhl and hls.numhl 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

View File

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

View File

@ -1,10 +1,10 @@
local api = vim.api
local uv = vim.loop
local Status = require('gitsigns.status')
local async = require('gitsigns.async')
local log = require('gitsigns.debug.log')
local util = require('gitsigns.util')
local Status = require('gitsigns.status')
local cache = require('gitsigns.cache').cache
local config = require('gitsigns.config').config
@ -18,7 +18,7 @@ local dprintf = log.dprintf
--- @param bufnr integer
--- @param old_relpath string
local function handle_moved(bufnr, old_relpath)
local bcache = cache[bufnr]
local bcache = assert(cache[bufnr])
local git_obj = bcache.git_obj
local new_name = git_obj:has_moved()
@ -73,6 +73,7 @@ local function watcher_handler0(bufnr)
-- Avoid cache hit for detached buffer
-- ref: https://github.com/lewis6991/gitsigns.nvim/issues/956
if not manager.schedule(bufnr) then
dprint('buffer invalid (1)')
return
end
@ -81,6 +82,7 @@ local function watcher_handler0(bufnr)
git_obj.repo:update_abbrev_head()
if not manager.schedule(bufnr) then
dprint('buffer invalid (2)')
return
end
@ -91,6 +93,7 @@ local function watcher_handler0(bufnr)
git_obj:update()
if not manager.schedule(bufnr) then
dprint('buffer invalid (3)')
return
end
@ -99,6 +102,7 @@ local function watcher_handler0(bufnr)
-- moved. Check if it was moved and switch to it.
handle_moved(bufnr, old_relpath)
if not manager.schedule(bufnr) then
dprint('buffer invalid (4)')
return
end
end
@ -108,9 +112,12 @@ local function watcher_handler0(bufnr)
require('gitsigns.manager').update(bufnr)
end
--- Debounce and throttle the handler.
--- We also throttle in case the debounce delay is not enough and to prevent
--- too many handlers from being launched (and interleaved).
--- Debounce to:
--- - wait for all changes to the gitdir to complete.
--- 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 =
debounce_trailing(200, async.create(1, throttle_by_id(watcher_handler0, true)), 1)
@ -123,11 +130,6 @@ end
local M = {}
local WATCH_IGNORE = {
ORIG_HEAD = true,
FETCH_HEAD = true,
}
--- @param bufnr integer
--- @param gitdir string
--- @return uv.uv_fs_event_t
@ -141,17 +143,15 @@ function M.watch_gitdir(bufnr, gitdir)
return
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
-- to sometimes be nil.
-- https://github.com/lewis6991/gitsigns.nvim/issues/848
if filename == nil or WATCH_IGNORE[filename] or vim.endswith(filename, '.lock') then
dprintf('%s (ignoring)', info)
if not filename then
log.eprint('No filename')
return
end
dprint(info)
dprintf("Git dir update: '%s' %s", filename, inspect(events))
watcher_handler(bufnr)
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 = {
doc = {
["gitsigns.txt"] = "e537e0db7825ce01a1c568a124432989"
["gitsigns.txt"] = "ed2c2a9eac117833753afc9dd55adcf4"
},
["gitsigns.nvim-scm-1.rockspec"] = "a9b165d604ce401cfeea760a9366418d",
lua = {
gitsigns = {
["actions.lua"] = "accecf1db114ace88739c40835cb5a77",
["async.lua"] = "15f310cd469f5bfa46bb1e49e5a1d61c",
["attach.lua"] = "6f81186d03fbde2ddc631c46fea09315",
["blame.lua"] = "e8388c8b29982475bfccec28ea4f72be",
["cache.lua"] = "a084b897b3af2f3603a018f4c00c20fa",
["actions.lua"] = "ac0661d45e50424f5f59924528b1c031",
["async.lua"] = "ab34c767e5b6c917335d19f2acc6fd36",
["attach.lua"] = "44664690d66389b4487d934ebcad98e6",
["blame.lua"] = "05feea95e221a2409a8d44334c47529f",
["cache.lua"] = "523c72aa06168f06b3ecd34fd04cbe9d",
cli = {
["argparse.lua"] = "fb6c9ffda01b2090f3c252ecaf00f68a"
},
["cli.lua"] = "f00c3494d6be1b07c352c51132150586",
["config.lua"] = "ef58f99d7782297a32e3867634906738",
["current_line_blame.lua"] = "b1e920875977e12bb4f9f6be08a92db8",
["debounce.lua"] = "e0c1145a3dc341f46b36b43d814c1202",
["cli.lua"] = "00273191aa1ca467c5edbd9531f8fd9d",
["config.lua"] = "8743742b5a5b0a0713f0352ff4e88db0",
["current_line_blame.lua"] = "48e477d836e39ab98e58c2b027dd9db8",
["debounce.lua"] = "5a28036b5ac45c1f93f9883b855e564f",
debug = {
["log.lua"] = "f7e994b68e9cbcf91adfeb5bc379d7b1"
},
["debug.lua"] = "6a819b17a531b74ee11622145097afae",
["diff.lua"] = "0c462ae71c77899e81da151dcfdf77eb",
["diff_ext.lua"] = "04005195067132403fc336422e05c7d3",
["diff_int.lua"] = "df447e56f11906998e81d5b94499e013",
["diffthis.lua"] = "b91c6a177c0a80c5e611b8c09f6eb46e",
["diff_ext.lua"] = "31454455cd645f1518d8363446e8d0f6",
["diff_int.lua"] = "8e73883f55811dcb68ad481d389aa687",
["diffthis.lua"] = "aaac58016e9982bb14e942f9e4e24c52",
git = {
["blame.lua"] = "e779f4344bcc41cdb92c1a1be5eb2815",
["cmd.lua"] = "449c03c67b7ae516babc41d6da0dc66e",
["repo.lua"] = "1efe3178f64b77e0fc22cad55d9586a0",
["version.lua"] = "068a582ed4565978eb1f6eb089a6fa6c"
},
["git.lua"] = "8a216cac54214508e798c7f4b920dd36",
["highlight.lua"] = "f1966ef758f9a0a86102a699ec7a1eca",
["git.lua"] = "0d3e8859ff8cf7ebd3beb739b64a8c49",
["highlight.lua"] = "f0bf039b629818fbfae8a6fad161f9a2",
["hunks.lua"] = "ee058ee8b056b055cd8404460ca6921f",
["manager.lua"] = "527083250ad693ee4faa5e4dde47f275",
["manager.lua"] = "f6e7e2430f2f28a4dbcfd2479f2c8480",
["message.lua"] = "523ee4df9da4a7fa9b5ab2100eb27ac4",
["popup.lua"] = "cbc11678e30094bff8ed54f0357e26f9",
["popup.lua"] = "2fcf3052f95d81cb5c0bb04ca4e06aae",
["repeat.lua"] = "798544de97c774bc8e10eecfd6479585",
["signs.lua"] = "9224bcde01ebd0c320bcd678822fc799",
["signs.lua"] = "a22dd6943d762dffcdbb8d2db4d885bb",
["status.lua"] = "a229a7213a3fbecfcf2d98aaf587fcab",
system = {
["compat.lua"] = "05d2b6d08602fba46be9b540288091e7"
},
["system.lua"] = "d73fac4f6e734cc8ce9f13d6be027503",
["test.lua"] = "082f7c7a556bf27352a378d047b8e79b",
["util.lua"] = "b24bac967bc60ba1434bf5cd7cf3fc98",
["watcher.lua"] = "034303cfa063c77bb6628f1a55d559c4"
["util.lua"] = "d30ad092850bd48a1446ce069320f5a7",
["watcher.lua"] = "978875698d84bc1f715c55fefa72bcc1"
},
["gitsigns.lua"] = "784d1b15d5970f0177fd19d163ea9dfb"
["gitsigns.lua"] = "bf3f49482d8340f4be41060d7f461fd1"
}
}

View File

@ -37,208 +37,268 @@ HaskellTools *HaskellTools*
plugin configuration *haskell-tools.config*
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:
>
---@type HTOpts
---@type haskell-tools.Opts
vim.g.haskell_tools = {
---@type ToolsOpts
---@type haskell-tools.tools.Opts
tools = {
-- ...
},
---@type HaskellLspClientOpts
---@type haskell-tools.lsp.ClientOpts
hls = {
on_attach = function(client, bufnr)
-- Set keybindings, etc. here.
end,
-- ...
},
---@type HTDapOpts
---@type haskell-tools.dap.Opts
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: ~
{tools?} (ToolsOpts) haskell-tools module options.
{hls?} (HaskellLspClientOpts) haskell-language-server client options.
{dap?} (HTDapOpts) debug adapter config for nvim-dap.
{tools?} (haskell-tools.tools.Opts)
haskell-tools module options.
{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: ~
{codeLens?} (CodeLensOpts) LSP codeLens options.
{hoogle?} (HoogleOpts) Hoogle type signature search options.
{hover?} (HoverOpts) LSP hover options.
{definition?} (DefinitionOpts) LSP go-to-definition options.
{repl?} (ReplOpts) GHCi repl options.
{tags?} (FastTagsOpts) fast-tags module options.
{log?} (HTLogOpts) haskell-tools logger options.
{codeLens?} (haskell-tools.codeLens.Opts)
LSP codeLens options.
{hoogle?} (haskell-tools.hoogle.Opts)
Hoogle type signature search options.
{hover?} (haskell-tools.hover.Opts)
LSP hover 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: ~
{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: ~
{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: ~
"auto"|"telescope-local"|"telescope-web"|"browser"
HoverOpts *HoverOpts*
haskell-tools.hover.Opts *haskell-tools.hover.Opts*
Fields: ~
{enable?} (fun():boolean|boolean) (default: `true`) Whether to enable haskell-tools hover.
{border?} (string[][]) 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.
{enable?} (fun():boolean|boolean)
(default: `true`) Whether to enable haskell-tools hover.
{border?} (string[][])
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: ~
{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: ~
{handler?} (fun():ReplHandler|ReplHandler) `'builtin'`: Use the simple builtin repl. `'toggleterm'`: Use akinsho/toggleterm.nvim.
{prefer?} (fun():repl_backend|repl_backend) Prefer cabal or stack when both stack and cabal project files are present?
{builtin?} (BuiltinReplOpts) Configuration for the builtin repl.
{auto_focus?} (boolean) Whether to auto-focus the repl on toggle or send. If unset, the handler decides.
{handler?} (fun():haskell-tools.repl.Handler|haskell-tools.repl.Handler)
`'builtin'`: Use the simple builtin repl.
`'toggleterm'`: Use akinsho/toggleterm.nvim.
{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: ~
"builtin"|"toggleterm"
repl_backend *repl_backend*
haskell-tools.repl.Backend *haskell-tools.repl.Backend*
Type: ~
"cabal"|"stack"
BuiltinReplOpts *BuiltinReplOpts*
haskell-tools.repl.builtin.Opts *haskell-tools.repl.builtin.Opts*
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: ~
{create_repl_split?} (fun(opts:ReplViewOpts):mk_repl_cmd_fun) Create the REPL in a horizontally split window.
{create_repl_vsplit?} (fun(opts:ReplViewOpts):mk_repl_cmd_fun) Create the REPL in a vertically split window.
{create_repl_tabnew?} (fun(opts:ReplViewOpts):mk_repl_cmd_fun) Create the REPL in a new tab.
{create_repl_cur_win?} (fun(opts:ReplViewOpts):mk_repl_cmd_fun) Create the REPL in the current window.
{create_repl_split?} (fun(opts:haskell-tools.repl.view.Opts):mk_ht_repl_cmd_fun)
Create the REPL in a horizontally split window.
{create_repl_vsplit?} (fun(opts:haskell-tools.repl.view.Opts):mk_ht_repl_cmd_fun)
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: ~
{delete_buffer_on_exit?} (boolean) Whether to delete the buffer when the Repl quits.
{size?} (fun():number|number) The size of the window or a function that determines it.
{delete_buffer_on_exit?} (boolean)
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: ~
fun():string[]|nil
FastTagsOpts *FastTagsOpts*
haskell-tools.fast-tags.Opts *haskell-tools.fast-tags.Opts*
Fields: ~
{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: ~
{level?} (number|string) The log level.
{level?} (number|string)
The log level.
See: ~
|vim.log.levels|
HaskellLspClientOpts *HaskellLspClientOpts*
haskell-tools.lsp.ClientOpts *haskell-tools.lsp.ClientOpts*
Fields: ~
{auto_attach?} (fun():boolean|boolean) Whether to automatically attach the LSP client. Defaults to `true` if the haskell-language-server executable is found.
{debug?} (boolean) Whether to enable haskell-language-server debug logging.
{on_attach?} (fun(client:number,bufnr:number,ht:HaskellTools)) Callback that is invoked when the client attaches to a buffer.
{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.
{auto_attach?} (fun():boolean|boolean)
Whether to automatically attach the LSP client.
Defaults to `true` if the haskell-language-server executable is found.
{debug?} (boolean)
Whether to enable haskell-language-server debug logging.
{on_attach?} (fun(client:number,bufnr:number,ht:HaskellTools))
Callback that is invoked when the client attaches to a buffer.
{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`
See: https://haskell-language-server.readthedocs.io/en/latest/configuration.html.
HTDapOpts *HTDapOpts*
haskell-tools.dap.Opts *haskell-tools.dap.Opts*
Fields: ~
{cmd?} (string[]) The command to start the debug adapter server with.
{logFile?} (string) Log file path for detected configurations.
{logLevel?} (HaskellDebugAdapterLogLevel) The log level for detected configurations.
{auto_discover?} (boolean|AddDapConfigOpts) Set to `false` to disable auto-discovery of launch configurations. `true` uses the default configurations options`.
{cmd?} (string[])
The command to start the debug adapter server with.
{logFile?} (string)
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: ~
"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*
The following commands are available:
* `:HlsStart` - Start the LSP client.
* `:HlsStop` - Stop the LSP client.
* `:HlsRestart` - Restart the LSP client.
* `:HlsEvalAll` - Evaluate all code snippets in comments.
* `:Hls start` - Start the LSP client.
* `:Hls stop` - Stop the LSP client.
* `:Hls restart` - Restart the LSP client.
* `:Hls evalAll` - Evaluate all code snippets in comments.
LoadHlsSettingsOpts *LoadHlsSettingsOpts*
haskell-tools.load_hls_settings.Opts *haskell-tools.load_hls_settings.Opts*
Fields: ~
{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*
HlsTools.load_hls_settings({project_root}, {opts})
*Hls.load_hls_settings*
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.
Falls back to the `hls.default_settings` if no file is found or file cannot be read or decoded.
Parameters: ~
{project_root} (string|nil) The project root
{opts} (LoadHlsSettingsOpts|nil)
{opts} (haskell-tools.load_hls_settings.Opts|nil)
Returns: ~
(table) hls_settings
@ -247,7 +307,7 @@ HlsTools.load_hls_settings({project_root}, {opts})
|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.
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
HlsTools.stop({bufnr}) *HlsTools.stop*
Hls.stop({bufnr}) *Hls.stop*
Stop the LSP client.
Parameters: ~
@ -268,7 +328,7 @@ HlsTools.stop({bufnr}) *HlsTools.stop*
(table[]) A list of clients that will be stopped
HlsTools.restart({bufnr}) *HlsTools.restart*
Hls.restart({bufnr}) *Hls.restart*
Restart the LSP client.
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
HlsTools.buf_eval_all({bufnr}) *HlsTools.buf_eval_all*
Hls.buf_eval_all({bufnr}) *Hls.buf_eval_all*
Evaluate all code snippets in comments.
Parameters: ~
@ -292,22 +352,19 @@ HlsTools.buf_eval_all({bufnr}) *HlsTools.buf_eval_all*
==============================================================================
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*
*HsDapTools.discover_configurations*
HsDapTools.discover_configurations({bufnr}, {opts})
*Dap.discover_configurations*
Dap.discover_configurations({bufnr}, {opts})
Discover nvim-dap launch configurations for haskell-debug-adapter.
Parameters: ~
{bufnr} (number|nil) The buffer number
{opts} (AddDapConfigOpts|nil)
{opts} (haskell-tools.dap.AddConfigOpts|nil)
Returns: ~
(nil)
@ -316,10 +373,10 @@ HsDapTools.discover_configurations({bufnr}, {opts})
==============================================================================
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: ~
{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:
* `:HtReplToggle` - Toggle a GHCi repl.
* `:HtReplQuit` - Quit the current repl.
* `:HtReplLoad` - Load a Haskell file into the repl.
* `:HtReplReload` - Reload the current repl.
* `:Haskell repl toggle {file?}` - Toggle a GHCi repl.
* `:Haskell repl quit` - Quit the current repl.
* `:Haskell repl load {file?}` - Load a Haskell file into the 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.
Returns: ~
(table|nil) command
HsReplTools.operator() *HsReplTools.operator*
Repl.operator() *Repl.operator*
See: ~
|operatorfunc|
HsReplTools.paste({reg}) *HsReplTools.paste*
Repl.paste({reg}) *Repl.paste*
Paste from register `reg` to the REPL
Parameters: ~
{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`
Parameters: ~
{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
HsReplTools.paste_info({reg}) *HsReplTools.paste_info*
Repl.paste_info({reg}) *Repl.paste_info*
Query the REPL for info on register `reg`
Parameters: ~
{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
HsReplTools.load_file({filepath}) *HsReplTools.load_file*
Repl.load_file({filepath}) *Repl.load_file*
Load a file into the REPL
Parameters: ~
{filepath} (string) The absolute file path
HsReplTools.reload() *HsReplTools.reload*
Repl.reload() *Repl.reload*
Reload the repl
@ -399,14 +460,14 @@ haskell-tools Project module *haskell-tools.project*
The following commands are available:
* `:HsProjectFile` - Open the project file for the current buffer (cabal.project or stack.yaml).
* `:HsPackageYaml` - Open the package.yaml file for the current buffer.
* `:HsPackageCabal` - Open the *.cabal file for the current buffer.
* `:Haskell projectFile` - Open the project file for the current buffer (cabal.project or stack.yaml).
* `:Haskell packageYaml` - Open the package.yaml 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
Parameters: ~
@ -416,21 +477,21 @@ HsProjectTools.root_dir({project_file}) *HsProjectTools.root_dir*
(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.
Returns: ~
(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.
Returns: ~
(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).
Returns: ~
@ -440,27 +501,27 @@ HsProjectTools.open_project_file() *HsProjectTools.open_project_file*
==============================================================================
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: ~
{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)
*FastTagsTools.generate_project_tags*
FastTagsTools.generate_project_tags({path}, {opts})
*FastTags.generate_project_tags*
FastTags.generate_project_tags({path}, {opts})
Generates tags for the current project
Parameters: ~
{path} (string|nil) File path
{opts} (GenerateProjectTagsOpts|nil) Options
{opts} (haskell-tools.tags.generate_project_tags.Opts|nil) Options
*FastTagsTools.generate_package_tags*
FastTagsTools.generate_package_tags({path})
FastTags.generate_package_tags({path}) *FastTags.generate_package_tags*
Generate tags for the package containing `path`
Parameters: ~
@ -472,42 +533,42 @@ haskell-tools Logging *haskell-tools.log*
The following commands are available:
* `:HtLog` - Open the haskell-tools.nvim log file.
* `:HlsLog` - Open the haskell-language-server log file.
* `:HtSetLogLevel` - Set the haskell-tools.nvim and LSP client log level.
* `:Haskell log setLevel` - Set the haskell-tools.nvim and LSP client log level.
* `:Haskell log openLog` - Open the haskell-tools.nvim log file.
* `: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
Returns: ~
(string) filepath
HaskellToolsLog.get_logfile() *HaskellToolsLog.get_logfile*
Log.get_logfile() *Log.get_logfile*
Get the haskell-tools.nvim log file path.
Returns: ~
(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
Returns: ~
(nil)
HaskellToolsLog.nvim_open_logfile() *HaskellToolsLog.nvim_open_logfile*
Log.nvim_open_logfile() *Log.nvim_open_logfile*
Open the haskell-tools.nvim log file.
Returns: ~
(nil)
HaskellToolsLog.set_level() *HaskellToolsLog.set_level*
Log.set_level() *Log.set_level*
Returns: ~
(nil)

View File

@ -1,69 +1,69 @@
AddDapConfigOpts haskell-tools.txt /*AddDapConfigOpts*
BuiltinReplOpts haskell-tools.txt /*BuiltinReplOpts*
CodeLensOpts haskell-tools.txt /*CodeLensOpts*
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*
Dap.discover_configurations haskell-tools.txt /*Dap.discover_configurations*
FastTags.generate_package_tags haskell-tools.txt /*FastTags.generate_package_tags*
FastTags.generate_project_tags haskell-tools.txt /*FastTags.generate_project_tags*
HaskellTools haskell-tools.txt /*HaskellTools*
HaskellToolsLog haskell-tools.txt /*HaskellToolsLog*
HaskellToolsLog.get_hls_logfile haskell-tools.txt /*HaskellToolsLog.get_hls_logfile*
HaskellToolsLog.get_logfile haskell-tools.txt /*HaskellToolsLog.get_logfile*
HaskellToolsLog.nvim_open_hls_logfile haskell-tools.txt /*HaskellToolsLog.nvim_open_hls_logfile*
HaskellToolsLog.nvim_open_logfile haskell-tools.txt /*HaskellToolsLog.nvim_open_logfile*
HaskellToolsLog.set_level haskell-tools.txt /*HaskellToolsLog.set_level*
HlsTools haskell-tools.txt /*HlsTools*
HlsTools.buf_eval_all haskell-tools.txt /*HlsTools.buf_eval_all*
HlsTools.load_hls_settings haskell-tools.txt /*HlsTools.load_hls_settings*
HlsTools.restart haskell-tools.txt /*HlsTools.restart*
HlsTools.start haskell-tools.txt /*HlsTools.start*
HlsTools.stop haskell-tools.txt /*HlsTools.stop*
HoogleMode haskell-tools.txt /*HoogleMode*
HoogleOpts haskell-tools.txt /*HoogleOpts*
HoogleTools haskell-tools.txt /*HoogleTools*
HoogleTools.hoogle_signature haskell-tools.txt /*HoogleTools.hoogle_signature*
HoverOpts haskell-tools.txt /*HoverOpts*
HsDapLaunchConfiguration haskell-tools.txt /*HsDapLaunchConfiguration*
HsDapTools haskell-tools.txt /*HsDapTools*
HsDapTools.discover_configurations haskell-tools.txt /*HsDapTools.discover_configurations*
HsProjectTools haskell-tools.txt /*HsProjectTools*
HsProjectTools.open_package_cabal haskell-tools.txt /*HsProjectTools.open_package_cabal*
HsProjectTools.open_package_yaml haskell-tools.txt /*HsProjectTools.open_package_yaml*
HsProjectTools.open_project_file haskell-tools.txt /*HsProjectTools.open_project_file*
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*
Hls.buf_eval_all haskell-tools.txt /*Hls.buf_eval_all*
Hls.load_hls_settings haskell-tools.txt /*Hls.load_hls_settings*
Hls.restart haskell-tools.txt /*Hls.restart*
Hls.start haskell-tools.txt /*Hls.start*
Hls.stop haskell-tools.txt /*Hls.stop*
Hoogle.hoogle_signature haskell-tools.txt /*Hoogle.hoogle_signature*
Log.get_hls_logfile haskell-tools.txt /*Log.get_hls_logfile*
Log.get_logfile haskell-tools.txt /*Log.get_logfile*
Log.nvim_open_hls_logfile haskell-tools.txt /*Log.nvim_open_hls_logfile*
Log.nvim_open_logfile haskell-tools.txt /*Log.nvim_open_logfile*
Log.set_level haskell-tools.txt /*Log.set_level*
Project.open_package_cabal haskell-tools.txt /*Project.open_package_cabal*
Project.open_package_yaml haskell-tools.txt /*Project.open_package_yaml*
Project.open_project_file haskell-tools.txt /*Project.open_project_file*
Project.root_dir haskell-tools.txt /*Project.root_dir*
Repl.buf_mk_repl_cmd haskell-tools.txt /*Repl.buf_mk_repl_cmd*
Repl.cword_info haskell-tools.txt /*Repl.cword_info*
Repl.cword_type haskell-tools.txt /*Repl.cword_type*
Repl.load_file haskell-tools.txt /*Repl.load_file*
Repl.operator haskell-tools.txt /*Repl.operator*
Repl.paste haskell-tools.txt /*Repl.paste*
Repl.paste_info haskell-tools.txt /*Repl.paste_info*
Repl.paste_type haskell-tools.txt /*Repl.paste_type*
Repl.reload haskell-tools.txt /*Repl.reload*
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.contents haskell-tools.txt /*haskell-tools.contents*
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.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.Opts haskell-tools.txt /*haskell-tools.log.Opts*
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.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.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*
mk_repl_cmd_fun haskell-tools.txt /*mk_repl_cmd_fun*
repl_backend haskell-tools.txt /*repl_backend*
mk_ht_repl_cmd_fun haskell-tools.txt /*mk_ht_repl_cmd_fun*

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