Refresh generated nvim config
This commit is contained in:
@ -94,7 +94,7 @@ require("lazy").setup({
|
||||
require("nvim-web-devicons").setup(opts)
|
||||
end,
|
||||
["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/nvim-web-devicons",
|
||||
["lazy"] = false,
|
||||
["lazy"] = true,
|
||||
["name"] = "web-devicons",
|
||||
},
|
||||
{
|
||||
@ -122,16 +122,6 @@ require("lazy").setup({
|
||||
["name"] = "better-escape",
|
||||
["opts"] = { ["mapping"] = { "jk" }, ["timeout"] = 200 },
|
||||
},
|
||||
{
|
||||
"chadtree",
|
||||
["config"] = function(_, opts)
|
||||
vim.api.nvim_set_var("chadtree_settings", opts)
|
||||
end,
|
||||
["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/chadtree",
|
||||
["lazy"] = false,
|
||||
["name"] = "chadtree",
|
||||
["opts"] = { ["theme"] = { ["text_colour_set"] = "nord" }, ["xdg"] = true },
|
||||
},
|
||||
{
|
||||
"clangd-extensions",
|
||||
["config"] = function(_, opts)
|
||||
@ -150,45 +140,45 @@ require("lazy").setup({
|
||||
{
|
||||
"cmp-async-path",
|
||||
["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/cmp-async-path",
|
||||
["lazy"] = false,
|
||||
["lazy"] = true,
|
||||
["name"] = "cmp-async-path",
|
||||
},
|
||||
{
|
||||
"cmp-buffer",
|
||||
["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/cmp-buffer",
|
||||
["enabled"] = false,
|
||||
["lazy"] = false,
|
||||
["lazy"] = true,
|
||||
["name"] = "cmp-buffer",
|
||||
},
|
||||
{
|
||||
"cmp-cmdline",
|
||||
["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/cmp-cmdline",
|
||||
["enabled"] = false,
|
||||
["lazy"] = false,
|
||||
["lazy"] = true,
|
||||
["name"] = "cmp-cmdline",
|
||||
},
|
||||
{
|
||||
"cmp-emoji",
|
||||
["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/cmp-emoji",
|
||||
["lazy"] = false,
|
||||
["lazy"] = true,
|
||||
["name"] = "cmp-emoji",
|
||||
},
|
||||
{
|
||||
"cmp-nvim-lsp",
|
||||
["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/cmp-nvim-lsp",
|
||||
["lazy"] = false,
|
||||
["lazy"] = true,
|
||||
["name"] = "cmp-nvim-lsp",
|
||||
},
|
||||
{
|
||||
"cmp-nvim-lsp-signature-help",
|
||||
["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/cmp-nvim-lsp-signature-help",
|
||||
["lazy"] = false,
|
||||
["lazy"] = true,
|
||||
["name"] = "cmp-nvim-lsp-signature-help",
|
||||
},
|
||||
{
|
||||
"cmp-luasnip",
|
||||
["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/cmp_luasnip",
|
||||
["lazy"] = false,
|
||||
["lazy"] = true,
|
||||
["name"] = "cmp-luasnip",
|
||||
},
|
||||
},
|
||||
@ -229,16 +219,22 @@ require("lazy").setup({
|
||||
},
|
||||
|
||||
mapping = cmp.mapping.preset.insert({
|
||||
["<Down>"] = cmp.mapping.select_next_item({ behavior = cmp.SelectBehavior.Select }),
|
||||
["<Up>"] = cmp.mapping.select_prev_item({ behavior = cmp.SelectBehavior.Select }),
|
||||
["<C-e>"] = cmp.mapping.abort(),
|
||||
["<Esc>"] = cmp.mapping.abort(),
|
||||
["<C-Up>"] = cmp.mapping.scroll_docs(-4),
|
||||
["<C-Down>"] = cmp.mapping.scroll_docs(4),
|
||||
["<C-Space>"] = cmp.mapping.complete({}),
|
||||
|
||||
["<C-Up>"] = cmp.mapping.scroll_docs(-4),
|
||||
["<C-e>"] = cmp.mapping.abort(),
|
||||
["<CR>"] = cmp.mapping.confirm({ select = true }),
|
||||
|
||||
["<Down>"] = cmp.mapping.select_next_item({ behavior = cmp.SelectBehavior.Select }),
|
||||
["<Esc>"] = cmp.mapping.abort(),
|
||||
["<S-Tab>"] = cmp.mapping(function(fallback)
|
||||
if cmp.visible() then
|
||||
cmp.select_prev_item()
|
||||
elseif luasnip.jumpable(-1) then
|
||||
luasnip.jump(-1)
|
||||
else
|
||||
fallback()
|
||||
end
|
||||
end, { "i", "s" }),
|
||||
["<Tab>"] = cmp.mapping(function(fallback)
|
||||
if cmp.visible() then
|
||||
cmp.select_next_item()
|
||||
@ -250,16 +246,7 @@ require("lazy").setup({
|
||||
fallback()
|
||||
end
|
||||
end, { "i", "s" }),
|
||||
|
||||
["<S-Tab>"] = cmp.mapping(function(fallback)
|
||||
if cmp.visible() then
|
||||
cmp.select_prev_item()
|
||||
elseif luasnip.jumpable(-1) then
|
||||
luasnip.jump(-1)
|
||||
else
|
||||
fallback()
|
||||
end
|
||||
end, { "i", "s" }),
|
||||
["<Up>"] = cmp.mapping.select_prev_item({ behavior = cmp.SelectBehavior.Select }),
|
||||
}),
|
||||
}
|
||||
end,
|
||||
@ -282,12 +269,13 @@ require("lazy").setup({
|
||||
{
|
||||
"ts-context-commentstring",
|
||||
["config"] = function(_, opts)
|
||||
vim.g.skip_ts_context_commentstring_module = true -- Skip compatibility checks
|
||||
-- Skip compatibility checks
|
||||
vim.g.skip_ts_context_commentstring_module = true
|
||||
|
||||
require("ts_context_commentstring").setup(opts)
|
||||
end,
|
||||
["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/nvim-ts-context-commentstring",
|
||||
["lazy"] = false,
|
||||
["lazy"] = true,
|
||||
["name"] = "ts-context-commentstring",
|
||||
},
|
||||
},
|
||||
@ -335,7 +323,7 @@ require("lazy").setup({
|
||||
require("flash").setup(opts)
|
||||
end,
|
||||
["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/flash.nvim",
|
||||
["lazy"] = false,
|
||||
["lazy"] = true,
|
||||
["name"] = "flash",
|
||||
},
|
||||
{
|
||||
@ -501,7 +489,15 @@ require("lazy").setup({
|
||||
{
|
||||
"lualine",
|
||||
["config"] = function(_, opts)
|
||||
require("lualine").setup(opts)
|
||||
local lualine = require("lualine")
|
||||
|
||||
lualine.setup(opts)
|
||||
|
||||
-- Disable tabline/winbar sections
|
||||
lualine.hide({
|
||||
place = { "tabline", "winbar" },
|
||||
unhide = false,
|
||||
})
|
||||
end,
|
||||
["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/lualine.nvim",
|
||||
["lazy"] = false,
|
||||
@ -518,12 +514,11 @@ require("lazy").setup({
|
||||
["sections"] = {
|
||||
["lualine_a"] = { "mode" },
|
||||
["lualine_b"] = { "branch", "diff", "diagnostics" },
|
||||
["lualine_c"] = { { ["extraConfig"] = { ["path"] = 1 }, ["name"] = "filename" } },
|
||||
["lualine_c"] = { { "filename", path = 1 } },
|
||||
["lualine_x"] = { "filetype", "encoding", "fileformat" },
|
||||
["lualine_y"] = { "progress", "searchcount", "selectioncount" },
|
||||
["lualine_z"] = { "location" },
|
||||
},
|
||||
["tabline"] = { ["lualine_a"] = { "buffers" }, ["lualine_z"] = { "tabs" } },
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -556,16 +551,73 @@ require("lazy").setup({
|
||||
["name"] = "navic",
|
||||
["opts"] = { ["click"] = true, ["highlight"] = true, ["lsp"] = { ["auto_attach"] = true } },
|
||||
},
|
||||
{
|
||||
"neo-tree",
|
||||
["cmd"] = "Neotree",
|
||||
["config"] = function(_, opts)
|
||||
require("neo-tree").setup(opts)
|
||||
end,
|
||||
["dependencies"] = {
|
||||
{
|
||||
"plenary",
|
||||
["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/plenary.nvim",
|
||||
["lazy"] = true,
|
||||
["name"] = "plenary",
|
||||
},
|
||||
{
|
||||
"web-devicons",
|
||||
["config"] = function(_, opts)
|
||||
require("nvim-web-devicons").setup(opts)
|
||||
end,
|
||||
["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/nvim-web-devicons",
|
||||
["lazy"] = true,
|
||||
["name"] = "web-devicons",
|
||||
},
|
||||
{
|
||||
"nui",
|
||||
["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/nui.nvim",
|
||||
["lazy"] = true,
|
||||
["name"] = "nui",
|
||||
},
|
||||
},
|
||||
["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/neo-tree.nvim",
|
||||
["lazy"] = true,
|
||||
["name"] = "neo-tree",
|
||||
["opts"] = {
|
||||
["buffers"] = { ["follow_current_file"] = { ["enabled"] = true, ["leave_dirs_open"] = false } },
|
||||
["filesystem"] = { ["follow_current_file"] = { ["enabled"] = true, ["leave_dirs_open"] = false } },
|
||||
["use_default_mappings"] = false,
|
||||
["window"] = {
|
||||
["mappings"] = {
|
||||
["/"] = "fuzzy_finder",
|
||||
["<CR>"] = "toggle_node",
|
||||
["<Esc>"] = "cancel",
|
||||
["<S-CR>"] = "open",
|
||||
["?"] = "show_help",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"noice",
|
||||
["config"] = function(_, opts)
|
||||
require("noice").setup(opts)
|
||||
end,
|
||||
["dependencies"] = {
|
||||
{
|
||||
"notify",
|
||||
["config"] = function(_, opts)
|
||||
vim.notify = require("notify")
|
||||
require("notify").setup(opts)
|
||||
end,
|
||||
["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/nvim-notify",
|
||||
["lazy"] = true,
|
||||
["name"] = "notify",
|
||||
},
|
||||
{
|
||||
"nui",
|
||||
["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/nui.nvim",
|
||||
["lazy"] = false,
|
||||
["lazy"] = true,
|
||||
["name"] = "nui",
|
||||
},
|
||||
},
|
||||
@ -605,16 +657,6 @@ require("lazy").setup({
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"notify",
|
||||
["config"] = function(_, opts)
|
||||
vim.notify = require("notify")
|
||||
require("notify").setup(opts)
|
||||
end,
|
||||
["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/nvim-notify",
|
||||
["lazy"] = false,
|
||||
["name"] = "notify",
|
||||
},
|
||||
{
|
||||
"rainbow-delimiters",
|
||||
["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/rainbow-delimiters.nvim",
|
||||
@ -641,6 +683,7 @@ require("lazy").setup({
|
||||
},
|
||||
{
|
||||
"telescope",
|
||||
["cmd"] = "Telescope",
|
||||
["config"] = function(_, opts)
|
||||
local telescope = require("telescope")
|
||||
telescope.setup(opts)
|
||||
@ -653,30 +696,30 @@ require("lazy").setup({
|
||||
{
|
||||
"plenary",
|
||||
["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/plenary.nvim",
|
||||
["lazy"] = false,
|
||||
["lazy"] = true,
|
||||
["name"] = "plenary",
|
||||
},
|
||||
{
|
||||
"telescope-fzf-native",
|
||||
["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/telescope-fzf-native.nvim",
|
||||
["lazy"] = true,
|
||||
["name"] = "telescope-fzf-native",
|
||||
},
|
||||
{
|
||||
"telescope-undo",
|
||||
["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/telescope-undo.nvim",
|
||||
["lazy"] = false,
|
||||
["lazy"] = true,
|
||||
["name"] = "telescope-undo",
|
||||
},
|
||||
{
|
||||
"telescope-ui-select",
|
||||
["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/telescope-ui-select.nvim",
|
||||
["lazy"] = false,
|
||||
["lazy"] = true,
|
||||
["name"] = "telescope-ui-select",
|
||||
},
|
||||
{
|
||||
"telescope-fzf-native",
|
||||
["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/telescope-fzf-native.nvim",
|
||||
["lazy"] = false,
|
||||
["name"] = "telescope-fzf-native",
|
||||
},
|
||||
},
|
||||
["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/telescope.nvim",
|
||||
["lazy"] = false,
|
||||
["lazy"] = true,
|
||||
["name"] = "telescope",
|
||||
["opts"] = {
|
||||
["defaults"] = {
|
||||
@ -692,11 +735,14 @@ require("lazy").setup({
|
||||
},
|
||||
{
|
||||
"todo-comments",
|
||||
["config"] = function(_, opts)
|
||||
require("todo-comments").setup(opts)
|
||||
end,
|
||||
["dependencies"] = {
|
||||
{
|
||||
"plenary",
|
||||
["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/plenary.nvim",
|
||||
["lazy"] = false,
|
||||
["lazy"] = true,
|
||||
["name"] = "plenary",
|
||||
},
|
||||
},
|
||||
@ -784,7 +830,7 @@ require("lazy").setup({
|
||||
{
|
||||
"promise",
|
||||
["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/promise-async",
|
||||
["lazy"] = false,
|
||||
["lazy"] = true,
|
||||
["name"] = "promise",
|
||||
},
|
||||
},
|
||||
@ -804,11 +850,12 @@ require("lazy").setup({
|
||||
},
|
||||
{
|
||||
"yanky",
|
||||
["cmd"] = { "YankyClearHistory", "YankyRingHistory" },
|
||||
["config"] = function(_, opts)
|
||||
require("yanky").setup(opts)
|
||||
end,
|
||||
["dir"] = "/home/lab/smchurla/Downloads/flake-nixinator/config/neovim/store/lazy-plugins/yanky.nvim",
|
||||
["lazy"] = false,
|
||||
["lazy"] = true,
|
||||
["name"] = "yanky",
|
||||
},
|
||||
},
|
||||
@ -817,25 +864,25 @@ require("lazy").setup({
|
||||
-- Set up keybinds {{{
|
||||
do
|
||||
local __nixvim_binds = {
|
||||
{ ["action"] = "<cmd>w<CR>", ["key"] = "<C-s>", ["mode"] = "n", ["options"] = {
|
||||
{ ["action"] = "<CMD>w<CR>", ["key"] = "<C-s>", ["mode"] = "n", ["options"] = {
|
||||
["desc"] = "Save current buffer",
|
||||
} },
|
||||
{ ["action"] = "<cmd>wa<CR>", ["key"] = "<C-S-s>", ["mode"] = "n", ["options"] = {
|
||||
{ ["action"] = "<CMD>wa<CR>", ["key"] = "<C-S-s>", ["mode"] = "n", ["options"] = {
|
||||
["desc"] = "Save all buffers",
|
||||
} },
|
||||
{ ["action"] = "<gv", ["key"] = "<", ["mode"] = "v", ["options"] = { ["desc"] = "Outdent" } },
|
||||
{ ["action"] = ">gv", ["key"] = ">", ["mode"] = "v", ["options"] = { ["desc"] = "Indent" } },
|
||||
{ ["action"] = "v<<Esc>", ["key"] = "<", ["mode"] = "n", ["options"] = { ["desc"] = "Outdent" } },
|
||||
{ ["action"] = "v><Esc>", ["key"] = ">", ["mode"] = "n", ["options"] = { ["desc"] = "Indent" } },
|
||||
{ ["action"] = "<C-d>zz", ["key"] = "<C-d>", ["mode"] = "n", ["options"] = { ["desc"] = "Jump down" } },
|
||||
{ ["action"] = "<C-u>zz", ["key"] = "<C-u>", ["mode"] = "n", ["options"] = { ["desc"] = "Jump up" } },
|
||||
{ ["action"] = "nzzzv", ["key"] = "n", ["mode"] = "n", ["options"] = { ["desc"] = "Next match" } },
|
||||
{ ["action"] = "Nzzzv", ["key"] = "N", ["mode"] = "n", ["options"] = { ["desc"] = "Previous match" } },
|
||||
{ ["action"] = "<C-d>zz", ["key"] = "<C-d>", ["mode"] = "n", ["options"] = { ["desc"] = "Jump down (centered)" } },
|
||||
{ ["action"] = "<C-u>zz", ["key"] = "<C-u>", ["mode"] = "n", ["options"] = { ["desc"] = "Jump up (centered)" } },
|
||||
{ ["action"] = "nzzzv", ["key"] = "n", ["mode"] = "n", ["options"] = { ["desc"] = "Next match (centered)" } },
|
||||
{ ["action"] = "Nzzzv", ["key"] = "N", ["mode"] = "n", ["options"] = { ["desc"] = "Previous match (centered)" } },
|
||||
{
|
||||
["action"] = "<cmd>lua require('intellitab').indent()<CR>",
|
||||
["action"] = "<CMD>lua require('intellitab').indent()<CR>",
|
||||
["key"] = "<Tab>",
|
||||
["mode"] = "i",
|
||||
["options"] = { ["desc"] = "Indent" },
|
||||
["options"] = { ["desc"] = "Indent (IntelliTab)" },
|
||||
},
|
||||
{ ["action"] = "<C-w>", ["key"] = "<C-BS>", ["mode"] = "i", ["options"] = { ["desc"] = "Delete previous word" } },
|
||||
{ ["action"] = "<C-w>", ["key"] = "<M-BS>", ["mode"] = "i", ["options"] = { ["desc"] = "Delete previous word" } },
|
||||
@ -850,137 +897,143 @@ do
|
||||
} },
|
||||
{ ["action"] = '"+y', ["key"] = "<C-S-c>", ["mode"] = "v", ["options"] = { ["desc"] = "Copy to clipboard" } },
|
||||
{
|
||||
["action"] = "<cmd>nohlsearch<CR>",
|
||||
["action"] = "<CMD>nohlsearch<CR>",
|
||||
["key"] = "<C-h>",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Clear search highlights" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>lua vim.lsp.buf.hover()<CR>",
|
||||
["action"] = "<CMD>lua vim.lsp.buf.hover()<CR>",
|
||||
["key"] = "K",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Show LSP hover" },
|
||||
},
|
||||
{ ["action"] = "<cmd>quitall<CR>", ["key"] = "<leader>qq", ["mode"] = "n", ["options"] = { ["desc"] = "Quit" } },
|
||||
{
|
||||
["action"] = "<cmd>quitall!<CR>",
|
||||
["key"] = "<leader>q!",
|
||||
["action"] = "<CMD>Telescope current_buffer_fuzzy_find<CR>",
|
||||
["key"] = "/",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Forceful quit" },
|
||||
["options"] = { ["desc"] = "Find in current buffer" },
|
||||
},
|
||||
{ ["action"] = "<cmd>Lazy<CR>", ["key"] = "<leader>L", ["mode"] = "n", ["options"] = { ["desc"] = "Show Lazy" } },
|
||||
{ ["action"] = "<CMD>Lazy<CR>", ["key"] = "<leader>L", ["mode"] = "n", ["options"] = { ["desc"] = "Show Lazy" } },
|
||||
{
|
||||
["action"] = "<cmd>Telescope buffers<CR>",
|
||||
["action"] = "<CMD>Telescope buffers<CR>",
|
||||
["key"] = "<leader><Space>",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Show open buffers" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>wa<CR>",
|
||||
["action"] = "<CMD>w<CR>",
|
||||
["key"] = "<leader>s",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Save current buffer" },
|
||||
},
|
||||
{
|
||||
["action"] = "<CMD>wa<CR>",
|
||||
["key"] = "<leader>S",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Save all buffers" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>Telescope find_files<CR>",
|
||||
["action"] = "<CMD>Telescope find_files<CR>",
|
||||
["key"] = "<leader>f",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Find file" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>Telescope vim_options<CR>",
|
||||
["action"] = "<CMD>Telescope vim_options<CR>",
|
||||
["key"] = "<leader>o",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Show Vim options" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>Telescope undo<CR>",
|
||||
["action"] = "<CMD>Telescope undo<CR>",
|
||||
["key"] = "<leader>u",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Show undo history" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>Telescope current_buffer_fuzzy_find<CR>",
|
||||
["action"] = "<CMD>Telescope live_grep<CR>",
|
||||
["key"] = "<leader>/",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Find in current buffer" },
|
||||
["options"] = { ["desc"] = "Find in working directory" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>Telescope notify<CR>",
|
||||
["action"] = "<CMD>Telescope notify<CR>",
|
||||
["key"] = "<leader>n",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Show notify history" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>Telescope live_grep<CR>",
|
||||
["key"] = "<leader>s",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Find in working directory" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>Telescope resume<CR>",
|
||||
["action"] = "<CMD>Telescope resume<CR>",
|
||||
["key"] = "<leader>r",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Show last telescope picker" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>Telescope keymaps<CR>",
|
||||
["action"] = "<CMD>Telescope keymaps<CR>",
|
||||
["key"] = "<leader>?",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Show keymaps" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>Telescope commands<CR>",
|
||||
["action"] = "<CMD>Telescope commands<CR>",
|
||||
["key"] = "<leader>:",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Execute command" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>Telescope marks<CR>",
|
||||
["action"] = "<CMD>Telescope marks<CR>",
|
||||
["key"] = "<leader>M",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Show marks" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>Telescope jumplist<CR>",
|
||||
["action"] = "<CMD>Telescope jumplist<CR>",
|
||||
["key"] = "<leader>J",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Show jumplist" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>Telescope man_pages<CR>",
|
||||
["action"] = "<CMD>Telescope man_pages<CR>",
|
||||
["key"] = "<leader>m",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Show manpages" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>Telescope help_tags<CR>",
|
||||
["action"] = "<CMD>Telescope help_tags<CR>",
|
||||
["key"] = "<leader>h",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Show help tags" },
|
||||
},
|
||||
{ ["action"] = "+quit", ["key"] = "<leader>q", ["mode"] = "n" },
|
||||
{ ["action"] = "<CMD>quitall<CR>", ["key"] = "<leader>qq", ["mode"] = "n", ["options"] = { ["desc"] = "Quit" } },
|
||||
{
|
||||
["action"] = "<CMD>quitall!<CR>",
|
||||
["key"] = "<leader>q!",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Quit forcefully" },
|
||||
},
|
||||
{ ["action"] = "+buffers", ["key"] = "<leader>b", ["mode"] = "n" },
|
||||
{
|
||||
["action"] = "<cmd>Telescope buffers<CR>",
|
||||
["action"] = "<CMD>Telescope buffers<CR>",
|
||||
["key"] = "<leader>bb",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Show open buffers" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>bnext<CR>",
|
||||
["action"] = "<CMD>bnext<CR>",
|
||||
["key"] = "<leader>bn",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Goto next buffer" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>bprevious<CR>",
|
||||
["action"] = "<CMD>bprevious<CR>",
|
||||
["key"] = "<leader>bp",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Goto previous buffer" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>Bdelete<CR>",
|
||||
["action"] = "<CMD>Bdelete<CR>",
|
||||
["key"] = "<leader>bd",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Close current buffer" },
|
||||
@ -998,6 +1051,7 @@ do
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Split window vertically" },
|
||||
},
|
||||
{ ["action"] = "<C-w>=", ["key"] = "<leader>w=", ["mode"] = "n", ["options"] = { ["desc"] = "Balance windows" } },
|
||||
{
|
||||
["action"] = "<C-w>c",
|
||||
["key"] = "<leader>wd",
|
||||
@ -1017,124 +1071,124 @@ do
|
||||
} },
|
||||
{ ["action"] = "+toggle", ["key"] = "<leader>t", ["mode"] = "n" },
|
||||
{
|
||||
["action"] = "<cmd>CHADopen --nofocus<CR>",
|
||||
["action"] = "<CMD>Neotree action=show toggle=true<CR>",
|
||||
["key"] = "<leader>tt",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Toggle CHADtree" },
|
||||
["options"] = { ["desc"] = "Toggle NeoTree" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>Navbuddy<CR>",
|
||||
["action"] = "<CMD>Navbuddy<CR>",
|
||||
["key"] = "<leader>tn",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Toggle NavBuddy" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>TroubleToggle focus=false<CR>",
|
||||
["action"] = "<CMD>TroubleToggle focus=false<CR>",
|
||||
["key"] = "<leader>td",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Toggle Trouble" },
|
||||
},
|
||||
{ ["action"] = "+git", ["key"] = "<leader>g", ["mode"] = "n" },
|
||||
{
|
||||
["action"] = "<cmd>LazyGit<CR>",
|
||||
["action"] = "<CMD>LazyGit<CR>",
|
||||
["key"] = "<leader>gg",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Show LazyGit" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>GitMessenger<CR>",
|
||||
["action"] = "<CMD>GitMessenger<CR>",
|
||||
["key"] = "<leader>gm",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Show GitMessenger" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>Telescope git_status<CR>",
|
||||
["action"] = "<CMD>Telescope git_status<CR>",
|
||||
["key"] = "<leader>gs",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Show Git status" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>Telescope git_commits<CR>",
|
||||
["action"] = "<CMD>Telescope git_commits<CR>",
|
||||
["key"] = "<leader>gc",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Show Git log" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>Telescope git_branches<CR>",
|
||||
["action"] = "<CMD>Telescope git_branches<CR>",
|
||||
["key"] = "<leader>gb",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Show Git branches" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>Telescope git_bcommits<CR>",
|
||||
["action"] = "<CMD>Telescope git_bcommits<CR>",
|
||||
["key"] = "<leader>gf",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Show Git log for current file" },
|
||||
},
|
||||
{ ["action"] = "+lsp", ["key"] = "<leader>l", ["mode"] = "n" },
|
||||
{
|
||||
["action"] = "<cmd>Telescope lsp_references<CR>",
|
||||
["action"] = "<CMD>Telescope lsp_references<CR>",
|
||||
["key"] = "<leader>lr",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Goto references" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>Telescope lsp_definitions<CR>",
|
||||
["action"] = "<CMD>Telescope lsp_definitions<CR>",
|
||||
["key"] = "<leader>ld",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Goto definition" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>Telescope lsp_implementations<CR>",
|
||||
["action"] = "<CMD>Telescope lsp_implementations<CR>",
|
||||
["key"] = "<leader>li",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Goto implementation" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>Telescope lsp_type_definitions<CR>",
|
||||
["action"] = "<CMD>Telescope lsp_type_definitions<CR>",
|
||||
["key"] = "<leader>lt",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Goto type definition" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>Telescope lsp_incoming_calls<CR>",
|
||||
["action"] = "<CMD>Telescope lsp_incoming_calls<CR>",
|
||||
["key"] = "<leader>lI",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Show incoming calls" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>Telescope lsp_outgoing_calls<CR>",
|
||||
["action"] = "<CMD>Telescope lsp_outgoing_calls<CR>",
|
||||
["key"] = "<leader>lO",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Show outgoing calls" },
|
||||
},
|
||||
{ ["action"] = "+code", ["key"] = "<leader>c", ["mode"] = "n" },
|
||||
{
|
||||
["action"] = "<cmd>lua require('conform').format()<CR>",
|
||||
["action"] = "<CMD>lua require('conform').format()<CR>",
|
||||
["key"] = "<leader>cf",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Format current buffer" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>Telescope diagnostics<CR>",
|
||||
["action"] = "<CMD>Telescope diagnostics<CR>",
|
||||
["key"] = "<leader>cd",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Show diagnostics" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>lua vim.lsp.buf.rename()<CR>",
|
||||
["action"] = "<CMD>lua vim.lsp.buf.rename()<CR>",
|
||||
["key"] = "<leader>cr",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Rename LSP symbol" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>lua vim.lsp.buf.code_action()<CR>",
|
||||
["action"] = "<CMD>lua vim.lsp.buf.code_action()<CR>",
|
||||
["key"] = "<leader>ca",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Show LSP code actions" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>lua vim.diagnostic.open_float()<CR>",
|
||||
["action"] = "<CMD>lua vim.diagnostic.open_float()<CR>",
|
||||
["key"] = "<leader>cD",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Show LSP line diagnostics" },
|
||||
|
||||
@ -67,7 +67,7 @@ vim.cmd([[
|
||||
]])
|
||||
require("lazy").setup({
|
||||
dev = {
|
||||
path = "/nix/store/8m92rbw7hfvgr0i4jvcmlpn1lb1chjq2-lazy-plugins",
|
||||
path = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins",
|
||||
patterns = { "." },
|
||||
fallback = false,
|
||||
},
|
||||
@ -82,7 +82,7 @@ require("lazy").setup({
|
||||
colorscheme catppuccin
|
||||
]])
|
||||
end,
|
||||
["dir"] = "/nix/store/8m92rbw7hfvgr0i4jvcmlpn1lb1chjq2-lazy-plugins/catppuccin-nvim",
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/catppuccin-nvim",
|
||||
["lazy"] = false,
|
||||
["name"] = "catppuccin",
|
||||
["opts"] = { ["background"] = { ["dark"] = "mocha", ["light"] = "latte" }, ["flavour"] = "mocha" },
|
||||
@ -93,8 +93,8 @@ require("lazy").setup({
|
||||
["config"] = function(_, opts)
|
||||
require("nvim-web-devicons").setup(opts)
|
||||
end,
|
||||
["dir"] = "/nix/store/8m92rbw7hfvgr0i4jvcmlpn1lb1chjq2-lazy-plugins/nvim-web-devicons",
|
||||
["lazy"] = false,
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/nvim-web-devicons",
|
||||
["lazy"] = true,
|
||||
["name"] = "web-devicons",
|
||||
},
|
||||
{
|
||||
@ -102,13 +102,13 @@ require("lazy").setup({
|
||||
["config"] = function(_, opts)
|
||||
require("nvim-autopairs").setup(opts)
|
||||
end,
|
||||
["dir"] = "/nix/store/8m92rbw7hfvgr0i4jvcmlpn1lb1chjq2-lazy-plugins/nvim-autopairs",
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/nvim-autopairs",
|
||||
["lazy"] = false,
|
||||
["name"] = "autopairs",
|
||||
},
|
||||
{
|
||||
"bbye",
|
||||
["dir"] = "/nix/store/8m92rbw7hfvgr0i4jvcmlpn1lb1chjq2-lazy-plugins/vim-bbye",
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/vim-bbye",
|
||||
["lazy"] = false,
|
||||
["name"] = "bbye",
|
||||
},
|
||||
@ -117,27 +117,17 @@ require("lazy").setup({
|
||||
["config"] = function(_, opts)
|
||||
require("better_escape").setup(opts)
|
||||
end,
|
||||
["dir"] = "/nix/store/8m92rbw7hfvgr0i4jvcmlpn1lb1chjq2-lazy-plugins/better-escape.nvim",
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/better-escape.nvim",
|
||||
["lazy"] = false,
|
||||
["name"] = "better-escape",
|
||||
["opts"] = { ["mapping"] = { "jk" }, ["timeout"] = 200 },
|
||||
},
|
||||
{
|
||||
"chadtree",
|
||||
["config"] = function(_, opts)
|
||||
vim.api.nvim_set_var("chadtree_settings", opts)
|
||||
end,
|
||||
["dir"] = "/nix/store/8m92rbw7hfvgr0i4jvcmlpn1lb1chjq2-lazy-plugins/chadtree",
|
||||
["lazy"] = false,
|
||||
["name"] = "chadtree",
|
||||
["opts"] = { ["theme"] = { ["text_colour_set"] = "nord" }, ["xdg"] = true },
|
||||
},
|
||||
{
|
||||
"clangd-extensions",
|
||||
["config"] = function(_, opts)
|
||||
require("clangd_extensions").setup(opts)
|
||||
end,
|
||||
["dir"] = "/nix/store/8m92rbw7hfvgr0i4jvcmlpn1lb1chjq2-lazy-plugins/clangd_extensions.nvim",
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/clangd_extensions.nvim",
|
||||
["lazy"] = false,
|
||||
["name"] = "clangd-extensions",
|
||||
},
|
||||
@ -149,50 +139,50 @@ require("lazy").setup({
|
||||
["dependencies"] = {
|
||||
{
|
||||
"cmp-async-path",
|
||||
["dir"] = "/nix/store/8m92rbw7hfvgr0i4jvcmlpn1lb1chjq2-lazy-plugins/cmp-async-path",
|
||||
["lazy"] = false,
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/cmp-async-path",
|
||||
["lazy"] = true,
|
||||
["name"] = "cmp-async-path",
|
||||
},
|
||||
{
|
||||
"cmp-buffer",
|
||||
["dir"] = "/nix/store/8m92rbw7hfvgr0i4jvcmlpn1lb1chjq2-lazy-plugins/cmp-buffer",
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/cmp-buffer",
|
||||
["enabled"] = false,
|
||||
["lazy"] = false,
|
||||
["lazy"] = true,
|
||||
["name"] = "cmp-buffer",
|
||||
},
|
||||
{
|
||||
"cmp-cmdline",
|
||||
["dir"] = "/nix/store/8m92rbw7hfvgr0i4jvcmlpn1lb1chjq2-lazy-plugins/cmp-cmdline",
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/cmp-cmdline",
|
||||
["enabled"] = false,
|
||||
["lazy"] = false,
|
||||
["lazy"] = true,
|
||||
["name"] = "cmp-cmdline",
|
||||
},
|
||||
{
|
||||
"cmp-emoji",
|
||||
["dir"] = "/nix/store/8m92rbw7hfvgr0i4jvcmlpn1lb1chjq2-lazy-plugins/cmp-emoji",
|
||||
["lazy"] = false,
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/cmp-emoji",
|
||||
["lazy"] = true,
|
||||
["name"] = "cmp-emoji",
|
||||
},
|
||||
{
|
||||
"cmp-nvim-lsp",
|
||||
["dir"] = "/nix/store/8m92rbw7hfvgr0i4jvcmlpn1lb1chjq2-lazy-plugins/cmp-nvim-lsp",
|
||||
["lazy"] = false,
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/cmp-nvim-lsp",
|
||||
["lazy"] = true,
|
||||
["name"] = "cmp-nvim-lsp",
|
||||
},
|
||||
{
|
||||
"cmp-nvim-lsp-signature-help",
|
||||
["dir"] = "/nix/store/8m92rbw7hfvgr0i4jvcmlpn1lb1chjq2-lazy-plugins/cmp-nvim-lsp-signature-help",
|
||||
["lazy"] = false,
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/cmp-nvim-lsp-signature-help",
|
||||
["lazy"] = true,
|
||||
["name"] = "cmp-nvim-lsp-signature-help",
|
||||
},
|
||||
{
|
||||
"cmp-luasnip",
|
||||
["dir"] = "/nix/store/8m92rbw7hfvgr0i4jvcmlpn1lb1chjq2-lazy-plugins/cmp_luasnip",
|
||||
["lazy"] = false,
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/cmp_luasnip",
|
||||
["lazy"] = true,
|
||||
["name"] = "cmp-luasnip",
|
||||
},
|
||||
},
|
||||
["dir"] = "/nix/store/8m92rbw7hfvgr0i4jvcmlpn1lb1chjq2-lazy-plugins/nvim-cmp",
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/nvim-cmp",
|
||||
["lazy"] = false,
|
||||
["name"] = "cmp",
|
||||
["opts"] = function()
|
||||
@ -229,16 +219,22 @@ require("lazy").setup({
|
||||
},
|
||||
|
||||
mapping = cmp.mapping.preset.insert({
|
||||
["<Down>"] = cmp.mapping.select_next_item({ behavior = cmp.SelectBehavior.Select }),
|
||||
["<Up>"] = cmp.mapping.select_prev_item({ behavior = cmp.SelectBehavior.Select }),
|
||||
["<C-e>"] = cmp.mapping.abort(),
|
||||
["<Esc>"] = cmp.mapping.abort(),
|
||||
["<C-Up>"] = cmp.mapping.scroll_docs(-4),
|
||||
["<C-Down>"] = cmp.mapping.scroll_docs(4),
|
||||
["<C-Space>"] = cmp.mapping.complete({}),
|
||||
|
||||
["<C-Up>"] = cmp.mapping.scroll_docs(-4),
|
||||
["<C-e>"] = cmp.mapping.abort(),
|
||||
["<CR>"] = cmp.mapping.confirm({ select = true }),
|
||||
|
||||
["<Down>"] = cmp.mapping.select_next_item({ behavior = cmp.SelectBehavior.Select }),
|
||||
["<Esc>"] = cmp.mapping.abort(),
|
||||
["<S-Tab>"] = cmp.mapping(function(fallback)
|
||||
if cmp.visible() then
|
||||
cmp.select_prev_item()
|
||||
elseif luasnip.jumpable(-1) then
|
||||
luasnip.jump(-1)
|
||||
else
|
||||
fallback()
|
||||
end
|
||||
end, { "i", "s" }),
|
||||
["<Tab>"] = cmp.mapping(function(fallback)
|
||||
if cmp.visible() then
|
||||
cmp.select_next_item()
|
||||
@ -250,16 +246,7 @@ require("lazy").setup({
|
||||
fallback()
|
||||
end
|
||||
end, { "i", "s" }),
|
||||
|
||||
["<S-Tab>"] = cmp.mapping(function(fallback)
|
||||
if cmp.visible() then
|
||||
cmp.select_prev_item()
|
||||
elseif luasnip.jumpable(-1) then
|
||||
luasnip.jump(-1)
|
||||
else
|
||||
fallback()
|
||||
end
|
||||
end, { "i", "s" }),
|
||||
["<Up>"] = cmp.mapping.select_prev_item({ behavior = cmp.SelectBehavior.Select }),
|
||||
}),
|
||||
}
|
||||
end,
|
||||
@ -269,7 +256,7 @@ require("lazy").setup({
|
||||
["config"] = function(_, opts)
|
||||
require("colorizer").setup(opts)
|
||||
end,
|
||||
["dir"] = "/nix/store/8m92rbw7hfvgr0i4jvcmlpn1lb1chjq2-lazy-plugins/nvim-colorizer.lua",
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/nvim-colorizer.lua",
|
||||
["lazy"] = false,
|
||||
["name"] = "colorizer",
|
||||
},
|
||||
@ -282,16 +269,17 @@ require("lazy").setup({
|
||||
{
|
||||
"ts-context-commentstring",
|
||||
["config"] = function(_, opts)
|
||||
vim.g.skip_ts_context_commentstring_module = true -- Skip compatibility checks
|
||||
-- Skip compatibility checks
|
||||
vim.g.skip_ts_context_commentstring_module = true
|
||||
|
||||
require("ts_context_commentstring").setup(opts)
|
||||
end,
|
||||
["dir"] = "/nix/store/8m92rbw7hfvgr0i4jvcmlpn1lb1chjq2-lazy-plugins/nvim-ts-context-commentstring",
|
||||
["lazy"] = false,
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/nvim-ts-context-commentstring",
|
||||
["lazy"] = true,
|
||||
["name"] = "ts-context-commentstring",
|
||||
},
|
||||
},
|
||||
["dir"] = "/nix/store/8m92rbw7hfvgr0i4jvcmlpn1lb1chjq2-lazy-plugins/comment.nvim",
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/comment.nvim",
|
||||
["lazy"] = false,
|
||||
["name"] = "comment",
|
||||
["opts"] = {
|
||||
@ -308,7 +296,7 @@ require("lazy").setup({
|
||||
["config"] = function(_, opts)
|
||||
require("conform").setup(opts)
|
||||
end,
|
||||
["dir"] = "/nix/store/8m92rbw7hfvgr0i4jvcmlpn1lb1chjq2-lazy-plugins/conform.nvim",
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/conform.nvim",
|
||||
["lazy"] = false,
|
||||
["name"] = "conform",
|
||||
["opts"] = {
|
||||
@ -334,8 +322,8 @@ require("lazy").setup({
|
||||
["config"] = function(_, opts)
|
||||
require("flash").setup(opts)
|
||||
end,
|
||||
["dir"] = "/nix/store/8m92rbw7hfvgr0i4jvcmlpn1lb1chjq2-lazy-plugins/flash.nvim",
|
||||
["lazy"] = false,
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/flash.nvim",
|
||||
["lazy"] = true,
|
||||
["name"] = "flash",
|
||||
},
|
||||
{
|
||||
@ -345,7 +333,7 @@ require("lazy").setup({
|
||||
vim.g[k] = v
|
||||
end
|
||||
end,
|
||||
["dir"] = "/nix/store/8m92rbw7hfvgr0i4jvcmlpn1lb1chjq2-lazy-plugins/git-messenger.vim",
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/git-messenger.vim",
|
||||
["lazy"] = false,
|
||||
["name"] = "gitmessenger",
|
||||
["opts"] = {
|
||||
@ -358,14 +346,14 @@ require("lazy").setup({
|
||||
["config"] = function(_, opts)
|
||||
require("gitsigns").setup(opts)
|
||||
end,
|
||||
["dir"] = "/nix/store/8m92rbw7hfvgr0i4jvcmlpn1lb1chjq2-lazy-plugins/gitsigns.nvim",
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/gitsigns.nvim",
|
||||
["lazy"] = false,
|
||||
["name"] = "gitsigns",
|
||||
["opts"] = { ["current_line_blame"] = false },
|
||||
},
|
||||
{
|
||||
"haskell-tools",
|
||||
["dir"] = "/nix/store/8m92rbw7hfvgr0i4jvcmlpn1lb1chjq2-lazy-plugins/haskell-tools.nvim",
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/haskell-tools.nvim",
|
||||
["lazy"] = false,
|
||||
["name"] = "haskell-tools",
|
||||
},
|
||||
@ -374,7 +362,7 @@ require("lazy").setup({
|
||||
["config"] = function(_, opts)
|
||||
require("illuminate").configure(opts)
|
||||
end,
|
||||
["dir"] = "/nix/store/8m92rbw7hfvgr0i4jvcmlpn1lb1chjq2-lazy-plugins/vim-illuminate",
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/vim-illuminate",
|
||||
["lazy"] = false,
|
||||
["name"] = "illuminate",
|
||||
["opts"] = {
|
||||
@ -393,7 +381,7 @@ require("lazy").setup({
|
||||
},
|
||||
{
|
||||
"intellitab",
|
||||
["dir"] = "/nix/store/8m92rbw7hfvgr0i4jvcmlpn1lb1chjq2-lazy-plugins/intellitab.nvim",
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/intellitab.nvim",
|
||||
["lazy"] = false,
|
||||
["name"] = "intellitab",
|
||||
},
|
||||
@ -402,13 +390,13 @@ require("lazy").setup({
|
||||
["config"] = function(_, opts)
|
||||
require("nvim-lastplace").setup(opts)
|
||||
end,
|
||||
["dir"] = "/nix/store/8m92rbw7hfvgr0i4jvcmlpn1lb1chjq2-lazy-plugins/nvim-lastplace",
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/nvim-lastplace",
|
||||
["lazy"] = false,
|
||||
["name"] = "lastplace",
|
||||
},
|
||||
{
|
||||
"lazygit",
|
||||
["dir"] = "/nix/store/8m92rbw7hfvgr0i4jvcmlpn1lb1chjq2-lazy-plugins/lazygit.nvim",
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/lazygit.nvim",
|
||||
["lazy"] = false,
|
||||
["name"] = "lazygit",
|
||||
},
|
||||
@ -421,7 +409,7 @@ require("lazy").setup({
|
||||
lint[k] = v
|
||||
end
|
||||
end,
|
||||
["dir"] = "/nix/store/8m92rbw7hfvgr0i4jvcmlpn1lb1chjq2-lazy-plugins/nvim-lint",
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/nvim-lint",
|
||||
["lazy"] = false,
|
||||
["name"] = "lint",
|
||||
["opts"] = {
|
||||
@ -489,21 +477,29 @@ require("lazy").setup({
|
||||
["config"] = function(_, opts)
|
||||
require("neodev").setup(opts)
|
||||
end,
|
||||
["dir"] = "/nix/store/8m92rbw7hfvgr0i4jvcmlpn1lb1chjq2-lazy-plugins/neodev.nvim",
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/neodev.nvim",
|
||||
["lazy"] = false,
|
||||
["name"] = "neodev",
|
||||
},
|
||||
},
|
||||
["dir"] = "/nix/store/8m92rbw7hfvgr0i4jvcmlpn1lb1chjq2-lazy-plugins/nvim-lspconfig",
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/nvim-lspconfig",
|
||||
["lazy"] = false,
|
||||
["name"] = "lspconfig",
|
||||
},
|
||||
{
|
||||
"lualine",
|
||||
["config"] = function(_, opts)
|
||||
require("lualine").setup(opts)
|
||||
local lualine = require("lualine")
|
||||
|
||||
lualine.setup(opts)
|
||||
|
||||
-- Disable tabline/winbar sections
|
||||
lualine.hide({
|
||||
place = { "tabline", "winbar" },
|
||||
unhide = false,
|
||||
})
|
||||
end,
|
||||
["dir"] = "/nix/store/8m92rbw7hfvgr0i4jvcmlpn1lb1chjq2-lazy-plugins/lualine.nvim",
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/lualine.nvim",
|
||||
["lazy"] = false,
|
||||
["name"] = "lualine",
|
||||
["opts"] = {
|
||||
@ -518,12 +514,11 @@ require("lazy").setup({
|
||||
["sections"] = {
|
||||
["lualine_a"] = { "mode" },
|
||||
["lualine_b"] = { "branch", "diff", "diagnostics" },
|
||||
["lualine_c"] = { { ["extraConfig"] = { ["path"] = 1 }, ["name"] = "filename" } },
|
||||
["lualine_c"] = { { "filename", path = 1 } },
|
||||
["lualine_x"] = { "filetype", "encoding", "fileformat" },
|
||||
["lualine_y"] = { "progress", "searchcount", "selectioncount" },
|
||||
["lualine_z"] = { "location" },
|
||||
},
|
||||
["tabline"] = { ["lualine_a"] = { "buffers" }, ["lualine_z"] = { "tabs" } },
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -531,7 +526,7 @@ require("lazy").setup({
|
||||
["config"] = function(_, opts)
|
||||
require("luasnip").config.set_config(opts)
|
||||
end,
|
||||
["dir"] = "/nix/store/8m92rbw7hfvgr0i4jvcmlpn1lb1chjq2-lazy-plugins/luasnip",
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/luasnip",
|
||||
["lazy"] = false,
|
||||
["name"] = "luasnip",
|
||||
},
|
||||
@ -541,7 +536,7 @@ require("lazy").setup({
|
||||
local actions = require("nvim-navbuddy.actions") -- ?
|
||||
require("nvim-navbuddy").setup(opts)
|
||||
end,
|
||||
["dir"] = "/nix/store/8m92rbw7hfvgr0i4jvcmlpn1lb1chjq2-lazy-plugins/nvim-navbuddy",
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/nvim-navbuddy",
|
||||
["lazy"] = false,
|
||||
["name"] = "navbuddy",
|
||||
["opts"] = { ["lsp"] = { ["auto_attach"] = true }, ["window"] = { ["border"] = "rounded" } },
|
||||
@ -551,25 +546,82 @@ require("lazy").setup({
|
||||
["config"] = function(_, opts)
|
||||
require("nvim-navic").setup(opts)
|
||||
end,
|
||||
["dir"] = "/nix/store/8m92rbw7hfvgr0i4jvcmlpn1lb1chjq2-lazy-plugins/nvim-navic",
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/nvim-navic",
|
||||
["lazy"] = false,
|
||||
["name"] = "navic",
|
||||
["opts"] = { ["click"] = true, ["highlight"] = true, ["lsp"] = { ["auto_attach"] = true } },
|
||||
},
|
||||
{
|
||||
"neo-tree",
|
||||
["cmd"] = "Neotree",
|
||||
["config"] = function(_, opts)
|
||||
require("neo-tree").setup(opts)
|
||||
end,
|
||||
["dependencies"] = {
|
||||
{
|
||||
"plenary",
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/plenary.nvim",
|
||||
["lazy"] = true,
|
||||
["name"] = "plenary",
|
||||
},
|
||||
{
|
||||
"web-devicons",
|
||||
["config"] = function(_, opts)
|
||||
require("nvim-web-devicons").setup(opts)
|
||||
end,
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/nvim-web-devicons",
|
||||
["lazy"] = true,
|
||||
["name"] = "web-devicons",
|
||||
},
|
||||
{
|
||||
"nui",
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/nui.nvim",
|
||||
["lazy"] = true,
|
||||
["name"] = "nui",
|
||||
},
|
||||
},
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/neo-tree.nvim",
|
||||
["lazy"] = true,
|
||||
["name"] = "neo-tree",
|
||||
["opts"] = {
|
||||
["buffers"] = { ["follow_current_file"] = { ["enabled"] = true, ["leave_dirs_open"] = false } },
|
||||
["filesystem"] = { ["follow_current_file"] = { ["enabled"] = true, ["leave_dirs_open"] = false } },
|
||||
["use_default_mappings"] = false,
|
||||
["window"] = {
|
||||
["mappings"] = {
|
||||
["/"] = "fuzzy_finder",
|
||||
["<CR>"] = "toggle_node",
|
||||
["<Esc>"] = "cancel",
|
||||
["<S-CR>"] = "open",
|
||||
["?"] = "show_help",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"noice",
|
||||
["config"] = function(_, opts)
|
||||
require("noice").setup(opts)
|
||||
end,
|
||||
["dependencies"] = {
|
||||
{
|
||||
"notify",
|
||||
["config"] = function(_, opts)
|
||||
vim.notify = require("notify")
|
||||
require("notify").setup(opts)
|
||||
end,
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/nvim-notify",
|
||||
["lazy"] = true,
|
||||
["name"] = "notify",
|
||||
},
|
||||
{
|
||||
"nui",
|
||||
["dir"] = "/nix/store/8m92rbw7hfvgr0i4jvcmlpn1lb1chjq2-lazy-plugins/nui.nvim",
|
||||
["lazy"] = false,
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/nui.nvim",
|
||||
["lazy"] = true,
|
||||
["name"] = "nui",
|
||||
},
|
||||
},
|
||||
["dir"] = "/nix/store/8m92rbw7hfvgr0i4jvcmlpn1lb1chjq2-lazy-plugins/noice.nvim",
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/noice.nvim",
|
||||
["lazy"] = false,
|
||||
["name"] = "noice",
|
||||
["opts"] = {
|
||||
@ -605,42 +657,33 @@ require("lazy").setup({
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"notify",
|
||||
["config"] = function(_, opts)
|
||||
vim.notify = require("notify")
|
||||
require("notify").setup(opts)
|
||||
end,
|
||||
["dir"] = "/nix/store/8m92rbw7hfvgr0i4jvcmlpn1lb1chjq2-lazy-plugins/nvim-notify",
|
||||
["lazy"] = false,
|
||||
["name"] = "notify",
|
||||
},
|
||||
{
|
||||
"rainbow-delimiters",
|
||||
["dir"] = "/nix/store/8m92rbw7hfvgr0i4jvcmlpn1lb1chjq2-lazy-plugins/rainbow-delimiters.nvim",
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/rainbow-delimiters.nvim",
|
||||
["lazy"] = false,
|
||||
["name"] = "rainbow-delimiters",
|
||||
},
|
||||
{
|
||||
"rustaceanvim",
|
||||
["dir"] = "/nix/store/8m92rbw7hfvgr0i4jvcmlpn1lb1chjq2-lazy-plugins/rustaceanvim",
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/rustaceanvim",
|
||||
["lazy"] = false,
|
||||
["name"] = "rustaceanvim",
|
||||
},
|
||||
{
|
||||
"sandwich",
|
||||
["dir"] = "/nix/store/8m92rbw7hfvgr0i4jvcmlpn1lb1chjq2-lazy-plugins/vim-sandwich",
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/vim-sandwich",
|
||||
["lazy"] = false,
|
||||
["name"] = "sandwich",
|
||||
},
|
||||
{
|
||||
"sleuth",
|
||||
["dir"] = "/nix/store/8m92rbw7hfvgr0i4jvcmlpn1lb1chjq2-lazy-plugins/vim-sleuth",
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/vim-sleuth",
|
||||
["lazy"] = false,
|
||||
["name"] = "sleuth",
|
||||
},
|
||||
{
|
||||
"telescope",
|
||||
["cmd"] = "Telescope",
|
||||
["config"] = function(_, opts)
|
||||
local telescope = require("telescope")
|
||||
telescope.setup(opts)
|
||||
@ -652,31 +695,31 @@ require("lazy").setup({
|
||||
["dependencies"] = {
|
||||
{
|
||||
"plenary",
|
||||
["dir"] = "/nix/store/8m92rbw7hfvgr0i4jvcmlpn1lb1chjq2-lazy-plugins/plenary.nvim",
|
||||
["lazy"] = false,
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/plenary.nvim",
|
||||
["lazy"] = true,
|
||||
["name"] = "plenary",
|
||||
},
|
||||
{
|
||||
"telescope-fzf-native",
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/telescope-fzf-native.nvim",
|
||||
["lazy"] = true,
|
||||
["name"] = "telescope-fzf-native",
|
||||
},
|
||||
{
|
||||
"telescope-undo",
|
||||
["dir"] = "/nix/store/8m92rbw7hfvgr0i4jvcmlpn1lb1chjq2-lazy-plugins/telescope-undo.nvim",
|
||||
["lazy"] = false,
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/telescope-undo.nvim",
|
||||
["lazy"] = true,
|
||||
["name"] = "telescope-undo",
|
||||
},
|
||||
{
|
||||
"telescope-ui-select",
|
||||
["dir"] = "/nix/store/8m92rbw7hfvgr0i4jvcmlpn1lb1chjq2-lazy-plugins/telescope-ui-select.nvim",
|
||||
["lazy"] = false,
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/telescope-ui-select.nvim",
|
||||
["lazy"] = true,
|
||||
["name"] = "telescope-ui-select",
|
||||
},
|
||||
{
|
||||
"telescope-fzf-native",
|
||||
["dir"] = "/nix/store/8m92rbw7hfvgr0i4jvcmlpn1lb1chjq2-lazy-plugins/telescope-fzf-native.nvim",
|
||||
["lazy"] = false,
|
||||
["name"] = "telescope-fzf-native",
|
||||
},
|
||||
},
|
||||
["dir"] = "/nix/store/8m92rbw7hfvgr0i4jvcmlpn1lb1chjq2-lazy-plugins/telescope.nvim",
|
||||
["lazy"] = false,
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/telescope.nvim",
|
||||
["lazy"] = true,
|
||||
["name"] = "telescope",
|
||||
["opts"] = {
|
||||
["defaults"] = {
|
||||
@ -692,15 +735,18 @@ require("lazy").setup({
|
||||
},
|
||||
{
|
||||
"todo-comments",
|
||||
["config"] = function(_, opts)
|
||||
require("todo-comments").setup(opts)
|
||||
end,
|
||||
["dependencies"] = {
|
||||
{
|
||||
"plenary",
|
||||
["dir"] = "/nix/store/8m92rbw7hfvgr0i4jvcmlpn1lb1chjq2-lazy-plugins/plenary.nvim",
|
||||
["lazy"] = false,
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/plenary.nvim",
|
||||
["lazy"] = true,
|
||||
["name"] = "plenary",
|
||||
},
|
||||
},
|
||||
["dir"] = "/nix/store/8m92rbw7hfvgr0i4jvcmlpn1lb1chjq2-lazy-plugins/todo-comments.nvim",
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/todo-comments.nvim",
|
||||
["lazy"] = false,
|
||||
["name"] = "todo-comments",
|
||||
},
|
||||
@ -709,7 +755,7 @@ require("lazy").setup({
|
||||
["config"] = function(_, opts)
|
||||
require("toggleterm").setup(opts)
|
||||
end,
|
||||
["dir"] = "/nix/store/8m92rbw7hfvgr0i4jvcmlpn1lb1chjq2-lazy-plugins/toggleterm.nvim",
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/toggleterm.nvim",
|
||||
["lazy"] = false,
|
||||
["name"] = "toggleterm",
|
||||
["opts"] = {
|
||||
@ -732,13 +778,13 @@ require("lazy").setup({
|
||||
["config"] = function(_, opts)
|
||||
-- Fix treesitter grammars/parsers on nix
|
||||
vim.opt.runtimepath:append(
|
||||
"/nix/store/a05m2wf9i4lx3010pagz1p5s4vl1dva2-vimplugin-nvim-treesitter-2024-05-25"
|
||||
"/nix/store/dks5shbpaksflcsig4dspi8vs9a06yqw-vimplugin-nvim-treesitter-2024-05-28"
|
||||
)
|
||||
vim.opt.runtimepath:append("/nix/store/7lrj56kr2nj7591m4kjiq03hq9kwabm9-treesitter-parsers")
|
||||
vim.opt.runtimepath:append("/nix/store/774ydms06ccrb8zybw2y045ajgs9l7jk-treesitter-parsers")
|
||||
|
||||
require("nvim-treesitter.configs").setup(opts)
|
||||
end,
|
||||
["dir"] = "/nix/store/8m92rbw7hfvgr0i4jvcmlpn1lb1chjq2-lazy-plugins/nvim-treesitter",
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/nvim-treesitter",
|
||||
["lazy"] = false,
|
||||
["name"] = "treesitter",
|
||||
["opts"] = {
|
||||
@ -754,7 +800,7 @@ require("lazy").setup({
|
||||
},
|
||||
},
|
||||
["indent"] = { ["enable"] = true },
|
||||
["parser_install_dir"] = "/nix/store/7lrj56kr2nj7591m4kjiq03hq9kwabm9-treesitter-parsers",
|
||||
["parser_install_dir"] = "/nix/store/774ydms06ccrb8zybw2y045ajgs9l7jk-treesitter-parsers",
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -762,7 +808,7 @@ require("lazy").setup({
|
||||
["config"] = function(_, opts)
|
||||
require("trim").setup(opts)
|
||||
end,
|
||||
["dir"] = "/nix/store/8m92rbw7hfvgr0i4jvcmlpn1lb1chjq2-lazy-plugins/trim.nvim",
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/trim.nvim",
|
||||
["lazy"] = false,
|
||||
["name"] = "trim",
|
||||
},
|
||||
@ -771,7 +817,7 @@ require("lazy").setup({
|
||||
["config"] = function(_, opts)
|
||||
require("trouble").setup(opts)
|
||||
end,
|
||||
["dir"] = "/nix/store/8m92rbw7hfvgr0i4jvcmlpn1lb1chjq2-lazy-plugins/trouble.nvim",
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/trouble.nvim",
|
||||
["lazy"] = false,
|
||||
["name"] = "trouble",
|
||||
},
|
||||
@ -783,12 +829,12 @@ require("lazy").setup({
|
||||
["dependencies"] = {
|
||||
{
|
||||
"promise",
|
||||
["dir"] = "/nix/store/8m92rbw7hfvgr0i4jvcmlpn1lb1chjq2-lazy-plugins/promise-async",
|
||||
["lazy"] = false,
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/promise-async",
|
||||
["lazy"] = true,
|
||||
["name"] = "promise",
|
||||
},
|
||||
},
|
||||
["dir"] = "/nix/store/8m92rbw7hfvgr0i4jvcmlpn1lb1chjq2-lazy-plugins/nvim-ufo",
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/nvim-ufo",
|
||||
["lazy"] = false,
|
||||
["name"] = "ufo",
|
||||
},
|
||||
@ -797,18 +843,19 @@ require("lazy").setup({
|
||||
["config"] = function(_, opts)
|
||||
require("which-key").setup(opts)
|
||||
end,
|
||||
["dir"] = "/nix/store/8m92rbw7hfvgr0i4jvcmlpn1lb1chjq2-lazy-plugins/which-key.nvim",
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/which-key.nvim",
|
||||
["lazy"] = false,
|
||||
["name"] = "which-key",
|
||||
["priority"] = 500,
|
||||
},
|
||||
{
|
||||
"yanky",
|
||||
["cmd"] = { "YankyClearHistory", "YankyRingHistory" },
|
||||
["config"] = function(_, opts)
|
||||
require("yanky").setup(opts)
|
||||
end,
|
||||
["dir"] = "/nix/store/8m92rbw7hfvgr0i4jvcmlpn1lb1chjq2-lazy-plugins/yanky.nvim",
|
||||
["lazy"] = false,
|
||||
["dir"] = "/nix/store/8bx1xnvd173gghqaak7qyfr9ay7vxdw3-lazy-plugins/yanky.nvim",
|
||||
["lazy"] = true,
|
||||
["name"] = "yanky",
|
||||
},
|
||||
},
|
||||
@ -817,25 +864,25 @@ require("lazy").setup({
|
||||
-- Set up keybinds {{{
|
||||
do
|
||||
local __nixvim_binds = {
|
||||
{ ["action"] = "<cmd>w<CR>", ["key"] = "<C-s>", ["mode"] = "n", ["options"] = {
|
||||
{ ["action"] = "<CMD>w<CR>", ["key"] = "<C-s>", ["mode"] = "n", ["options"] = {
|
||||
["desc"] = "Save current buffer",
|
||||
} },
|
||||
{ ["action"] = "<cmd>wa<CR>", ["key"] = "<C-S-s>", ["mode"] = "n", ["options"] = {
|
||||
{ ["action"] = "<CMD>wa<CR>", ["key"] = "<C-S-s>", ["mode"] = "n", ["options"] = {
|
||||
["desc"] = "Save all buffers",
|
||||
} },
|
||||
{ ["action"] = "<gv", ["key"] = "<", ["mode"] = "v", ["options"] = { ["desc"] = "Outdent" } },
|
||||
{ ["action"] = ">gv", ["key"] = ">", ["mode"] = "v", ["options"] = { ["desc"] = "Indent" } },
|
||||
{ ["action"] = "v<<Esc>", ["key"] = "<", ["mode"] = "n", ["options"] = { ["desc"] = "Outdent" } },
|
||||
{ ["action"] = "v><Esc>", ["key"] = ">", ["mode"] = "n", ["options"] = { ["desc"] = "Indent" } },
|
||||
{ ["action"] = "<C-d>zz", ["key"] = "<C-d>", ["mode"] = "n", ["options"] = { ["desc"] = "Jump down" } },
|
||||
{ ["action"] = "<C-u>zz", ["key"] = "<C-u>", ["mode"] = "n", ["options"] = { ["desc"] = "Jump up" } },
|
||||
{ ["action"] = "nzzzv", ["key"] = "n", ["mode"] = "n", ["options"] = { ["desc"] = "Next match" } },
|
||||
{ ["action"] = "Nzzzv", ["key"] = "N", ["mode"] = "n", ["options"] = { ["desc"] = "Previous match" } },
|
||||
{ ["action"] = "<C-d>zz", ["key"] = "<C-d>", ["mode"] = "n", ["options"] = { ["desc"] = "Jump down (centered)" } },
|
||||
{ ["action"] = "<C-u>zz", ["key"] = "<C-u>", ["mode"] = "n", ["options"] = { ["desc"] = "Jump up (centered)" } },
|
||||
{ ["action"] = "nzzzv", ["key"] = "n", ["mode"] = "n", ["options"] = { ["desc"] = "Next match (centered)" } },
|
||||
{ ["action"] = "Nzzzv", ["key"] = "N", ["mode"] = "n", ["options"] = { ["desc"] = "Previous match (centered)" } },
|
||||
{
|
||||
["action"] = "<cmd>lua require('intellitab').indent()<CR>",
|
||||
["action"] = "<CMD>lua require('intellitab').indent()<CR>",
|
||||
["key"] = "<Tab>",
|
||||
["mode"] = "i",
|
||||
["options"] = { ["desc"] = "Indent" },
|
||||
["options"] = { ["desc"] = "Indent (IntelliTab)" },
|
||||
},
|
||||
{ ["action"] = "<C-w>", ["key"] = "<C-BS>", ["mode"] = "i", ["options"] = { ["desc"] = "Delete previous word" } },
|
||||
{ ["action"] = "<C-w>", ["key"] = "<M-BS>", ["mode"] = "i", ["options"] = { ["desc"] = "Delete previous word" } },
|
||||
@ -850,137 +897,143 @@ do
|
||||
} },
|
||||
{ ["action"] = '"+y', ["key"] = "<C-S-c>", ["mode"] = "v", ["options"] = { ["desc"] = "Copy to clipboard" } },
|
||||
{
|
||||
["action"] = "<cmd>nohlsearch<CR>",
|
||||
["action"] = "<CMD>nohlsearch<CR>",
|
||||
["key"] = "<C-h>",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Clear search highlights" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>lua vim.lsp.buf.hover()<CR>",
|
||||
["action"] = "<CMD>lua vim.lsp.buf.hover()<CR>",
|
||||
["key"] = "K",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Show LSP hover" },
|
||||
},
|
||||
{ ["action"] = "<cmd>quitall<CR>", ["key"] = "<leader>qq", ["mode"] = "n", ["options"] = { ["desc"] = "Quit" } },
|
||||
{
|
||||
["action"] = "<cmd>quitall!<CR>",
|
||||
["key"] = "<leader>q!",
|
||||
["action"] = "<CMD>Telescope current_buffer_fuzzy_find<CR>",
|
||||
["key"] = "/",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Forceful quit" },
|
||||
["options"] = { ["desc"] = "Find in current buffer" },
|
||||
},
|
||||
{ ["action"] = "<cmd>Lazy<CR>", ["key"] = "<leader>L", ["mode"] = "n", ["options"] = { ["desc"] = "Show Lazy" } },
|
||||
{ ["action"] = "<CMD>Lazy<CR>", ["key"] = "<leader>L", ["mode"] = "n", ["options"] = { ["desc"] = "Show Lazy" } },
|
||||
{
|
||||
["action"] = "<cmd>Telescope buffers<CR>",
|
||||
["action"] = "<CMD>Telescope buffers<CR>",
|
||||
["key"] = "<leader><Space>",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Show open buffers" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>wa<CR>",
|
||||
["action"] = "<CMD>w<CR>",
|
||||
["key"] = "<leader>s",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Save current buffer" },
|
||||
},
|
||||
{
|
||||
["action"] = "<CMD>wa<CR>",
|
||||
["key"] = "<leader>S",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Save all buffers" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>Telescope find_files<CR>",
|
||||
["action"] = "<CMD>Telescope find_files<CR>",
|
||||
["key"] = "<leader>f",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Find file" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>Telescope vim_options<CR>",
|
||||
["action"] = "<CMD>Telescope vim_options<CR>",
|
||||
["key"] = "<leader>o",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Show Vim options" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>Telescope undo<CR>",
|
||||
["action"] = "<CMD>Telescope undo<CR>",
|
||||
["key"] = "<leader>u",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Show undo history" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>Telescope current_buffer_fuzzy_find<CR>",
|
||||
["action"] = "<CMD>Telescope live_grep<CR>",
|
||||
["key"] = "<leader>/",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Find in current buffer" },
|
||||
["options"] = { ["desc"] = "Find in working directory" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>Telescope notify<CR>",
|
||||
["action"] = "<CMD>Telescope notify<CR>",
|
||||
["key"] = "<leader>n",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Show notify history" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>Telescope live_grep<CR>",
|
||||
["key"] = "<leader>s",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Find in working directory" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>Telescope resume<CR>",
|
||||
["action"] = "<CMD>Telescope resume<CR>",
|
||||
["key"] = "<leader>r",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Show last telescope picker" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>Telescope keymaps<CR>",
|
||||
["action"] = "<CMD>Telescope keymaps<CR>",
|
||||
["key"] = "<leader>?",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Show keymaps" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>Telescope commands<CR>",
|
||||
["action"] = "<CMD>Telescope commands<CR>",
|
||||
["key"] = "<leader>:",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Execute command" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>Telescope marks<CR>",
|
||||
["action"] = "<CMD>Telescope marks<CR>",
|
||||
["key"] = "<leader>M",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Show marks" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>Telescope jumplist<CR>",
|
||||
["action"] = "<CMD>Telescope jumplist<CR>",
|
||||
["key"] = "<leader>J",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Show jumplist" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>Telescope man_pages<CR>",
|
||||
["action"] = "<CMD>Telescope man_pages<CR>",
|
||||
["key"] = "<leader>m",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Show manpages" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>Telescope help_tags<CR>",
|
||||
["action"] = "<CMD>Telescope help_tags<CR>",
|
||||
["key"] = "<leader>h",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Show help tags" },
|
||||
},
|
||||
{ ["action"] = "+quit", ["key"] = "<leader>q", ["mode"] = "n" },
|
||||
{ ["action"] = "<CMD>quitall<CR>", ["key"] = "<leader>qq", ["mode"] = "n", ["options"] = { ["desc"] = "Quit" } },
|
||||
{
|
||||
["action"] = "<CMD>quitall!<CR>",
|
||||
["key"] = "<leader>q!",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Quit forcefully" },
|
||||
},
|
||||
{ ["action"] = "+buffers", ["key"] = "<leader>b", ["mode"] = "n" },
|
||||
{
|
||||
["action"] = "<cmd>Telescope buffers<CR>",
|
||||
["action"] = "<CMD>Telescope buffers<CR>",
|
||||
["key"] = "<leader>bb",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Show open buffers" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>bnext<CR>",
|
||||
["action"] = "<CMD>bnext<CR>",
|
||||
["key"] = "<leader>bn",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Goto next buffer" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>bprevious<CR>",
|
||||
["action"] = "<CMD>bprevious<CR>",
|
||||
["key"] = "<leader>bp",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Goto previous buffer" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>Bdelete<CR>",
|
||||
["action"] = "<CMD>Bdelete<CR>",
|
||||
["key"] = "<leader>bd",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Close current buffer" },
|
||||
@ -998,6 +1051,7 @@ do
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Split window vertically" },
|
||||
},
|
||||
{ ["action"] = "<C-w>=", ["key"] = "<leader>w=", ["mode"] = "n", ["options"] = { ["desc"] = "Balance windows" } },
|
||||
{
|
||||
["action"] = "<C-w>c",
|
||||
["key"] = "<leader>wd",
|
||||
@ -1017,124 +1071,124 @@ do
|
||||
} },
|
||||
{ ["action"] = "+toggle", ["key"] = "<leader>t", ["mode"] = "n" },
|
||||
{
|
||||
["action"] = "<cmd>CHADopen --nofocus<CR>",
|
||||
["action"] = "<CMD>Neotree action=show toggle=true<CR>",
|
||||
["key"] = "<leader>tt",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Toggle CHADtree" },
|
||||
["options"] = { ["desc"] = "Toggle NeoTree" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>Navbuddy<CR>",
|
||||
["action"] = "<CMD>Navbuddy<CR>",
|
||||
["key"] = "<leader>tn",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Toggle NavBuddy" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>TroubleToggle focus=false<CR>",
|
||||
["action"] = "<CMD>TroubleToggle focus=false<CR>",
|
||||
["key"] = "<leader>td",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Toggle Trouble" },
|
||||
},
|
||||
{ ["action"] = "+git", ["key"] = "<leader>g", ["mode"] = "n" },
|
||||
{
|
||||
["action"] = "<cmd>LazyGit<CR>",
|
||||
["action"] = "<CMD>LazyGit<CR>",
|
||||
["key"] = "<leader>gg",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Show LazyGit" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>GitMessenger<CR>",
|
||||
["action"] = "<CMD>GitMessenger<CR>",
|
||||
["key"] = "<leader>gm",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Show GitMessenger" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>Telescope git_status<CR>",
|
||||
["action"] = "<CMD>Telescope git_status<CR>",
|
||||
["key"] = "<leader>gs",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Show Git status" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>Telescope git_commits<CR>",
|
||||
["action"] = "<CMD>Telescope git_commits<CR>",
|
||||
["key"] = "<leader>gc",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Show Git log" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>Telescope git_branches<CR>",
|
||||
["action"] = "<CMD>Telescope git_branches<CR>",
|
||||
["key"] = "<leader>gb",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Show Git branches" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>Telescope git_bcommits<CR>",
|
||||
["action"] = "<CMD>Telescope git_bcommits<CR>",
|
||||
["key"] = "<leader>gf",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Show Git log for current file" },
|
||||
},
|
||||
{ ["action"] = "+lsp", ["key"] = "<leader>l", ["mode"] = "n" },
|
||||
{
|
||||
["action"] = "<cmd>Telescope lsp_references<CR>",
|
||||
["action"] = "<CMD>Telescope lsp_references<CR>",
|
||||
["key"] = "<leader>lr",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Goto references" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>Telescope lsp_definitions<CR>",
|
||||
["action"] = "<CMD>Telescope lsp_definitions<CR>",
|
||||
["key"] = "<leader>ld",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Goto definition" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>Telescope lsp_implementations<CR>",
|
||||
["action"] = "<CMD>Telescope lsp_implementations<CR>",
|
||||
["key"] = "<leader>li",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Goto implementation" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>Telescope lsp_type_definitions<CR>",
|
||||
["action"] = "<CMD>Telescope lsp_type_definitions<CR>",
|
||||
["key"] = "<leader>lt",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Goto type definition" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>Telescope lsp_incoming_calls<CR>",
|
||||
["action"] = "<CMD>Telescope lsp_incoming_calls<CR>",
|
||||
["key"] = "<leader>lI",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Show incoming calls" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>Telescope lsp_outgoing_calls<CR>",
|
||||
["action"] = "<CMD>Telescope lsp_outgoing_calls<CR>",
|
||||
["key"] = "<leader>lO",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Show outgoing calls" },
|
||||
},
|
||||
{ ["action"] = "+code", ["key"] = "<leader>c", ["mode"] = "n" },
|
||||
{
|
||||
["action"] = "<cmd>lua require('conform').format()<CR>",
|
||||
["action"] = "<CMD>lua require('conform').format()<CR>",
|
||||
["key"] = "<leader>cf",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Format current buffer" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>Telescope diagnostics<CR>",
|
||||
["action"] = "<CMD>Telescope diagnostics<CR>",
|
||||
["key"] = "<leader>cd",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Show diagnostics" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>lua vim.lsp.buf.rename()<CR>",
|
||||
["action"] = "<CMD>lua vim.lsp.buf.rename()<CR>",
|
||||
["key"] = "<leader>cr",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Rename LSP symbol" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>lua vim.lsp.buf.code_action()<CR>",
|
||||
["action"] = "<CMD>lua vim.lsp.buf.code_action()<CR>",
|
||||
["key"] = "<leader>ca",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Show LSP code actions" },
|
||||
},
|
||||
{
|
||||
["action"] = "<cmd>lua vim.diagnostic.open_float()<CR>",
|
||||
["action"] = "<CMD>lua vim.diagnostic.open_float()<CR>",
|
||||
["key"] = "<leader>cD",
|
||||
["mode"] = "n",
|
||||
["options"] = { ["desc"] = "Show LSP line diagnostics" },
|
||||
|
||||
@ -439,12 +439,14 @@ native_lsp = {
|
||||
hints = { "italic" },
|
||||
warnings = { "italic" },
|
||||
information = { "italic" },
|
||||
ok = { "italic" },
|
||||
},
|
||||
underlines = {
|
||||
errors = { "underline" },
|
||||
hints = { "underline" },
|
||||
warnings = { "underline" },
|
||||
information = { "underline" },
|
||||
ok = { "underline" },
|
||||
},
|
||||
inlay_hints = {
|
||||
background = true,
|
||||
@ -1038,12 +1040,14 @@ native_lsp = {
|
||||
hints = { "italic" },
|
||||
warnings = { "italic" },
|
||||
information = { "italic" },
|
||||
ok = { "italic" },
|
||||
},
|
||||
underlines = {
|
||||
errors = { "underline" },
|
||||
hints = { "underline" },
|
||||
warnings = { "underline" },
|
||||
information = { "underline" },
|
||||
ok = { "underline" },
|
||||
},
|
||||
inlay_hints = {
|
||||
background = true,
|
||||
|
||||
@ -366,12 +366,14 @@ directly at the thing (e.g. an error)).
|
||||
hints = { "italic" },
|
||||
warnings = { "italic" },
|
||||
information = { "italic" },
|
||||
ok = { "italic" },
|
||||
},
|
||||
underlines = {
|
||||
errors = { "underline" },
|
||||
hints = { "underline" },
|
||||
warnings = { "underline" },
|
||||
information = { "underline" },
|
||||
ok = { "underline" },
|
||||
},
|
||||
inlay_hints = {
|
||||
background = true,
|
||||
@ -674,12 +676,14 @@ nvim-lspconfig>lua
|
||||
hints = { "italic" },
|
||||
warnings = { "italic" },
|
||||
information = { "italic" },
|
||||
ok = { "italic" },
|
||||
},
|
||||
underlines = {
|
||||
errors = { "underline" },
|
||||
hints = { "underline" },
|
||||
warnings = { "underline" },
|
||||
information = { "underline" },
|
||||
ok = { "underline" },
|
||||
},
|
||||
inlay_hints = {
|
||||
background = true,
|
||||
|
||||
15
config/neovim/store/lazy-plugins/catppuccin-nvim/doc/tags
Normal file
15
config/neovim/store/lazy-plugins/catppuccin-nvim/doc/tags
Normal file
@ -0,0 +1,15 @@
|
||||
catppuccin-compile catppuccin.txt /*catppuccin-compile*
|
||||
catppuccin-configuration catppuccin.txt /*catppuccin-configuration*
|
||||
catppuccin-customize-highlights catppuccin.txt /*catppuccin-customize-highlights*
|
||||
catppuccin-customize-highlights-get-catppuccin-colors catppuccin.txt /*catppuccin-customize-highlights-get-catppuccin-colors*
|
||||
catppuccin-customize-highlights-overwriting-colors catppuccin.txt /*catppuccin-customize-highlights-overwriting-colors*
|
||||
catppuccin-faq catppuccin.txt /*catppuccin-faq*
|
||||
catppuccin-faq-wrong-treesitter-highlights catppuccin.txt /*catppuccin-faq-wrong-treesitter-highlights*
|
||||
catppuccin-features catppuccin.txt /*catppuccin-features*
|
||||
catppuccin-installation catppuccin.txt /*catppuccin-installation*
|
||||
catppuccin-integrations catppuccin.txt /*catppuccin-integrations*
|
||||
catppuccin-links catppuccin.txt /*catppuccin-links*
|
||||
catppuccin-table-of-contents catppuccin.txt /*catppuccin-table-of-contents*
|
||||
catppuccin-thanks-to catppuccin.txt /*catppuccin-thanks-to*
|
||||
catppuccin-usage catppuccin.txt /*catppuccin-usage*
|
||||
catppuccin.txt catppuccin.txt /*catppuccin.txt*
|
||||
@ -9,6 +9,7 @@ function M.get()
|
||||
local warning = C.yellow
|
||||
local info = C.sky
|
||||
local hint = C.teal
|
||||
local ok = C.green
|
||||
local darkening_percentage = 0.095
|
||||
|
||||
return {
|
||||
@ -40,27 +41,35 @@ function M.get()
|
||||
fg = hint,
|
||||
style = virtual_text.hints,
|
||||
}, -- Used as the mantle highlight group. Other Diagnostic highlights link to this by default
|
||||
DiagnosticVirtualTextOk = {
|
||||
bg = O.transparent_background and C.none or U.darken(hint, darkening_percentage, C.base),
|
||||
fg = ok,
|
||||
style = virtual_text.ok,
|
||||
}, -- Used as the mantle highlight group. Other Diagnostic highlights link to this by default
|
||||
|
||||
DiagnosticError = { bg = C.none, fg = error, style = virtual_text.errors }, -- Used as the mantle highlight group. Other Diagnostic highlights link to this by default
|
||||
DiagnosticWarn = { bg = C.none, fg = warning, style = virtual_text.warnings }, -- Used as the mantle highlight group. Other Diagnostic highlights link to this by default
|
||||
DiagnosticInfo = { bg = C.none, fg = info, style = virtual_text.information }, -- Used as the mantle highlight group. Other Diagnostic highlights link to this by default
|
||||
DiagnosticHint = { bg = C.none, fg = hint, style = virtual_text.hints }, -- Used as the mantle highlight group. Other Diagnostic highlights link to this by default
|
||||
DiagnosticOk = { bg = C.none, fg = ok, style = virtual_text.ok }, -- Used as the mantle highlight group. Other Diagnostic highlights link to this by default
|
||||
|
||||
-- for nvim nightly
|
||||
DiagnosticUnderlineError = { style = underlines.errors, sp = error }, -- Used to underline "Error" diagnostics
|
||||
DiagnosticUnderlineWarn = { style = underlines.warnings, sp = warning }, -- Used to underline "Warn" diagnostics
|
||||
DiagnosticUnderlineInfo = { style = underlines.information, sp = info }, -- Used to underline "Info" diagnostics
|
||||
DiagnosticUnderlineHint = { style = underlines.hints, sp = hint }, -- Used to underline "Hint" diagnostics
|
||||
DiagnosticUnderlineOk = { style = underlines.ok, sp = ok }, -- Used to underline "Ok" diagnostics
|
||||
|
||||
DiagnosticFloatingError = { fg = error }, -- Used to color "Error" diagnostic messages in diagnostics float
|
||||
DiagnosticFloatingWarn = { fg = warning }, -- Used to color "Warn" diagnostic messages in diagnostics float
|
||||
DiagnosticFloatingInfo = { fg = info }, -- Used to color "Info" diagnostic messages in diagnostics float
|
||||
DiagnosticFloatingHint = { fg = hint }, -- Used to color "Hint" diagnostic messages in diagnostics float
|
||||
DiagnosticFloatingOk = { fg = ok }, -- Used to color "Ok" diagnostic messages in diagnostics float
|
||||
|
||||
DiagnosticSignError = { fg = error }, -- Used for "Error" signs in sign column
|
||||
DiagnosticSignWarn = { fg = warning }, -- Used for "Warn" signs in sign column
|
||||
DiagnosticSignInfo = { fg = info }, -- Used for "Info" signs in sign column
|
||||
DiagnosticSignHint = { fg = hint }, -- Used for "Hint" signs in sign column
|
||||
DiagnosticSignOk = { fg = ok }, -- Used for "Ok" signs in sign column
|
||||
|
||||
LspDiagnosticsDefaultError = { fg = error }, -- Used as the mantle highlight group. Other LspDiagnostic highlights link to this by default (except Underline)
|
||||
LspDiagnosticsDefaultWarning = { fg = warning }, -- Used as the mantle highlight group. Other LspDiagnostic highlights link to this by default (except Underline)
|
||||
|
||||
@ -1,9 +1,12 @@
|
||||
local M = {}
|
||||
|
||||
function M.get()
|
||||
return O.transparent_background and {
|
||||
return O.transparent_background
|
||||
and {
|
||||
TreesitterContextBottom = { sp = C.dim, style = { "underline" } },
|
||||
} or {
|
||||
TreesitterContextLineNumber = { fg = C.rosewater },
|
||||
}
|
||||
or {
|
||||
TreesitterContextBottom = {
|
||||
sp = C.surface0,
|
||||
style = { "underline" },
|
||||
|
||||
@ -78,12 +78,14 @@ local M = {
|
||||
hints = { "italic" },
|
||||
warnings = { "italic" },
|
||||
information = { "italic" },
|
||||
ok = { "italic" },
|
||||
},
|
||||
underlines = {
|
||||
errors = { "underline" },
|
||||
hints = { "underline" },
|
||||
warnings = { "underline" },
|
||||
information = { "underline" },
|
||||
ok = { "underline" },
|
||||
},
|
||||
inlay_hints = {
|
||||
background = true,
|
||||
|
||||
@ -87,14 +87,16 @@
|
||||
---@field miscs CtpHighlightArgs[]?
|
||||
|
||||
---@class CtpNativeLspStyles
|
||||
-- Change the style of LSP errors.
|
||||
-- Change the style of LSP error diagnostics.
|
||||
---@field errors CtpHighlightArgs[]?
|
||||
-- Change the style of LSP hints.
|
||||
-- Change the style of LSP hint diagnostics.
|
||||
---@field hints CtpHighlightArgs[]?
|
||||
-- Change the style of LSP warnings.
|
||||
-- Change the style of LSP warning diagnostics.
|
||||
---@field warnings CtpHighlightArgs[]?
|
||||
-- Change the style of LSP information.
|
||||
-- Change the style of LSP information diagnostics.
|
||||
---@field information CtpHighlightArgs[]?
|
||||
-- Change the style of LSP ok diagnostics.
|
||||
---@field ok CtpHighlightArgs[]?
|
||||
|
||||
---@class CtpNativeLspInlayHints
|
||||
-- Toggle the background of inlay hints.
|
||||
|
||||
@ -1,7 +0,0 @@
|
||||
/.git/
|
||||
/.venv/
|
||||
__pycache__/
|
||||
.mypy_cache/
|
||||
/.vars/
|
||||
/temp/
|
||||
/.vscode/
|
||||
@ -1,25 +0,0 @@
|
||||
---
|
||||
name: Artifacts
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- chad
|
||||
schedule:
|
||||
- cron: "0 0 * * *" # daily
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v3
|
||||
|
||||
- env:
|
||||
CI_TOKEN: ${{ secrets.CI_TOKEN }}
|
||||
run: |-
|
||||
make build
|
||||
@ -1,33 +0,0 @@
|
||||
---
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
schedule:
|
||||
- cron: "0 0 * * *" # daily
|
||||
|
||||
jobs:
|
||||
mypy:
|
||||
strategy:
|
||||
matrix:
|
||||
python_ver:
|
||||
- "3.8"
|
||||
- "3.9"
|
||||
- "3.10"
|
||||
- "3.11"
|
||||
- "3.12"
|
||||
- "3"
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v3
|
||||
with:
|
||||
python-version: ${{ matrix.python_ver }}
|
||||
|
||||
- run: |-
|
||||
make lint
|
||||
@ -1,57 +0,0 @@
|
||||
---
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
schedule:
|
||||
- cron: "0 0 * * *" # daily
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [ 'python' ]
|
||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
|
||||
# Learn more:
|
||||
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v1
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
# queries: ./path/to/local/query, your-org/your-repo/queries@main
|
||||
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v1
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
|
||||
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
|
||||
# and modify them (or add more) to build your code if your project
|
||||
# uses a compiled language
|
||||
|
||||
#- run: |
|
||||
# make bootstrap
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v1
|
||||
@ -1,7 +0,0 @@
|
||||
/.git/
|
||||
/.venv/
|
||||
__pycache__/
|
||||
.mypy_cache/
|
||||
/.vars/
|
||||
/temp/
|
||||
/.vscode/
|
||||
@ -1,6 +0,0 @@
|
||||
---
|
||||
ignored:
|
||||
# Allow Latest Dockerfile
|
||||
- DL3007
|
||||
# Allow Unpinned Apt Packages
|
||||
- DL3008
|
||||
@ -1,13 +0,0 @@
|
||||
FROM ubuntu:focal
|
||||
|
||||
ENV TERM=xterm-256color
|
||||
RUN apt-get update && \
|
||||
DEBIAN_FRONTEND=noninteractive apt-get install --yes --no-install-recommends -- python3-venv neovim git ca-certificates && \
|
||||
rm -rf -- /var/lib/apt/lists/*
|
||||
|
||||
|
||||
COPY ./docker /
|
||||
WORKDIR /root/.config/nvim/pack/modules/start/chadtree
|
||||
COPY . .
|
||||
|
||||
RUN python3 -m chadtree deps --xdg ~/.local/share/nvim
|
||||
@ -1,60 +0,0 @@
|
||||
MAKEFLAGS += --check-symlink-times
|
||||
MAKEFLAGS += --jobs
|
||||
MAKEFLAGS += --no-builtin-rules
|
||||
MAKEFLAGS += --no-builtin-variables
|
||||
MAKEFLAGS += --shuffle
|
||||
MAKEFLAGS += --warn-undefined-variables
|
||||
SHELL := bash
|
||||
.DELETE_ON_ERROR:
|
||||
.ONESHELL:
|
||||
.SHELLFLAGS := --norc --noprofile -Eeuo pipefail -O dotglob -O nullglob -O extglob -O failglob -O globstar -c
|
||||
|
||||
.DEFAULT_GOAL := help
|
||||
|
||||
.PHONY: clean clobber build lint fmt
|
||||
|
||||
clean:
|
||||
rm -v -rf -- .mypy_cache/ .venv/
|
||||
|
||||
clobber: clean
|
||||
rm -v -rf -- .vars/
|
||||
|
||||
.venv/bin/python3:
|
||||
python3 -m venv -- .venv
|
||||
|
||||
define PYDEPS
|
||||
from itertools import chain
|
||||
from os import execl
|
||||
from sys import executable
|
||||
|
||||
from tomli import load
|
||||
|
||||
toml = load(open("pyproject.toml", "rb"))
|
||||
|
||||
project = toml["project"]
|
||||
execl(
|
||||
executable,
|
||||
executable,
|
||||
"-m",
|
||||
"pip",
|
||||
"install",
|
||||
"--upgrade",
|
||||
"--",
|
||||
*project.get("dependencies", ()),
|
||||
*chain.from_iterable(project["optional-dependencies"].values()),
|
||||
)
|
||||
endef
|
||||
|
||||
.venv/bin/mypy: .venv/bin/python3
|
||||
'$<' -m pip install --requirement requirements.txt -- tomli
|
||||
'$<' <<< '$(PYDEPS)'
|
||||
|
||||
lint: .venv/bin/mypy
|
||||
'$<' -- .
|
||||
|
||||
build: .venv/bin/mypy
|
||||
.venv/bin/python3 -- ci/prepare.py
|
||||
|
||||
fmt: .venv/bin/mypy
|
||||
.venv/bin/isort --profile=black --gitignore -- .
|
||||
.venv/bin/black -- .
|
||||
@ -1,157 +0,0 @@
|
||||
# [CHADTree](https://ms-jpq.github.io/chadtree)
|
||||
|
||||
File Manager for Neovim, Better than NERDTree.
|
||||
|
||||
## Features Illustrated
|
||||
|
||||
**See full list of screen captures [here](https://github.com/ms-jpq/chadtree/tree/chad/docs/FEATURES.md)**
|
||||
|
||||
### I like speed
|
||||
|
||||
- **Parallel** Filesystem Scan
|
||||
|
||||
- **[React Like](https://reactjs.org/docs/reconciliation.html)** Reconciling Difference Minimizing Rendering engine
|
||||
|
||||
- **Never** blocks
|
||||
|
||||
_You can read more about my [performance optimization](https://github.com/ms-jpq/chadtree/tree/chad/docs/ARCHITECTURE.md) here._
|
||||
|
||||
### I like power
|
||||
|
||||
- Visual mode selections
|
||||
|
||||
- Create, Copy, Paste, Delete, Rename, gotta do them all
|
||||
|
||||
- Quickfix integration
|
||||
|
||||
- [Bookmarks](https://raw.githubusercontent.com/ms-jpq/chadtree/chad/docs/img/bookmarks.png)
|
||||
|
||||

|
||||
|
||||
### I like 21st century
|
||||
|
||||
- Filtering by glob
|
||||
|
||||
- Follow mode
|
||||
|
||||
- Session support (save open folders to disk, pick up where you left off)
|
||||
|
||||
- Trash support (requires [`trash`](https://formulae.brew.sh/formula/trash) or [`trash-cli`](https://github.com/andreafrancia/trash-cli))
|
||||
|
||||
- `ls -l` statistics
|
||||
|
||||
- Correct! handling of symlinks
|
||||
|
||||

|
||||
|
||||
### I like version control
|
||||
|
||||
- Asynchronous parse git status (untracked, modified, staged)
|
||||
|
||||
- Full support for git submodules
|
||||
|
||||

|
||||
|
||||
### I like colours
|
||||
|
||||
- Full `$LS_COLOR` support! (shows same colours as unix `ls` & `tree` commands)
|
||||
|
||||
- [Github coloured](https://github.com/github/linguist) icons (over 600 colours!)
|
||||
|
||||
- Three different sets of icons out of the box
|
||||
|
||||
- Four built-in themes - nord, solarized, trapdoor, vim-syntax
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
### I like refinement
|
||||
|
||||
- Maintain cursor position on relevant files even when during movements.
|
||||
|
||||
- Maintain selection when copying, moving files
|
||||
|
||||
- Mimetype warning (so you don't accidentally open an image)
|
||||
|
||||
- Validating config parser **(notice, I added an extra `"dog"` param)**
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
### I like documentation
|
||||
|
||||
- Built-in help command in a floating window!
|
||||
|
||||
- Over 1000 lines of meticulous docs covering every option / function!
|
||||
|
||||
**Use `:CHADhelp` to view [documentation](https://github.com/ms-jpq/chadtree/tree/chad/docs)**
|
||||
|
||||
**Use `:CHADhelp --web` to open documentation in your browser!** (If you have one installed)
|
||||
|
||||
## Install
|
||||
|
||||
**Minimum version**: `python`: 3.8.2, `nvim`: `0.4.3`, make sure to have `virtualenv` installed (e.g.: `sudo apt install --yes -- python3-venv`)
|
||||
|
||||
Install the usual way, ie. [VimPlug](https://github.com/junegunn/vim-plug), [Vundle](https://github.com/VundleVim/Vundle.vim), etc
|
||||
|
||||
```vim
|
||||
Plug 'ms-jpq/chadtree', {'branch': 'chad', 'do': 'python3 -m chadtree deps'}
|
||||
```
|
||||
|
||||
You will have to run `:CHADdeps` when installing / updating. This will install CHADTree's dependencies locally inside `chadtree/.vars/runtime`.
|
||||
|
||||
doing `rm -rf chadtree/` will cleanly remove everything CHADTree uses on your computer.
|
||||
|
||||
## Usage
|
||||
|
||||
To toggle CHADTree run command `:CHADopen`. Set it to a hotkey for convenience.
|
||||
|
||||
```vimL
|
||||
nnoremap <leader>v <cmd>CHADopen<cr>
|
||||
```
|
||||
|
||||
To see a list of hot keys:
|
||||
|
||||
Either use `:CHADhelp keybind` or open in browser using [`:CHADhelp keybind --web`](https://github.com/ms-jpq/chadtree/tree/chad/docs/KEYBIND.md)
|
||||
|
||||
### FAQ
|
||||
|
||||
Q: Sometimes Windows will get stuck with CHADTree decorations when I do not want them to be, how do I resolve this?
|
||||
|
||||
A: Run `:CHADrestore`
|
||||
|
||||
### Recommendations
|
||||
|
||||
Add a hotkey to clear quickfix list:
|
||||
|
||||
```vimL
|
||||
nnoremap <leader>l <cmd>call setqflist([])<cr>
|
||||
```
|
||||
|
||||
## If you like this...
|
||||
|
||||
Also check out
|
||||
|
||||
- [`sad`](https://github.com/ms-jpq/sad), its a modern `sed` that does previews with syntax highlighting, and lets you pick and choose which chunks to edit.
|
||||
|
||||
- [`coq.nvim`](https://github.com/ms-jpq/coq_nvim), it's a FAST AS FUCK completion client with shit tons of features.
|
||||
|
||||
- [isomorphic-copy](https://github.com/ms-jpq/isomorphic-copy), it's a cross platform clipboard that is daemonless, and does not require third party support.
|
||||
|
||||
## Special Thanks
|
||||
|
||||
CHADTree does not define it's own colours beyond some minimal defaults, all themes are imported from other open source projects.
|
||||
|
||||
> The base icons are imported from the [vim-devicon](https://github.com/ryanoasis/vim-devicons)
|
||||
|
||||
> All emoji icons are imported from the [vim-emoji-icon-theme](https://github.com/adelarsq/vim-emoji-icon-theme)
|
||||
|
||||
> Some themes are imported from [dircolors-solarized](https://github.com/seebi/dircolors-solarized)
|
||||
|
||||
> Some themes are imported from [nord-dircolors](https://github.com/arcticicestudio/nord-dircolors)
|
||||
|
||||
> Some themes are imported from [LS_COLORS](https://github.com/trapd00r/LS_COLORS)
|
||||
|
||||
> Some themes are imported from [vim-nerdtree-syntax-highlight](https://github.com/tiagofumo/vim-nerdtree-syntax-highlight)
|
||||
@ -1,7 +0,0 @@
|
||||
---
|
||||
title: CHADTree
|
||||
|
||||
showcase: True
|
||||
|
||||
images:
|
||||
- https://raw.githubusercontent.com/ms-jpq/chadtree/chad/docs/img/visual_select.gif
|
||||
@ -1,3 +0,0 @@
|
||||
# DO NOT EDIT
|
||||
|
||||
These are code generated jsons.
|
||||
File diff suppressed because one or more lines are too long
@ -1 +0,0 @@
|
||||
# Used to Generate Artifacts
|
||||
@ -1,6 +0,0 @@
|
||||
---
|
||||
icon_colours: {}
|
||||
text_colours:
|
||||
ext_exact: {}
|
||||
name_exact: {}
|
||||
name_glob: {}
|
||||
@ -1,36 +0,0 @@
|
||||
---
|
||||
ascii: &ascii
|
||||
default_icon: ●
|
||||
ext_exact: {}
|
||||
folder:
|
||||
closed: ▶
|
||||
open: ▼
|
||||
link:
|
||||
broken: -/->
|
||||
normal: ->
|
||||
name_exact: {}
|
||||
name_glob: {}
|
||||
status:
|
||||
active: ">"
|
||||
inactive: " "
|
||||
not_selected: " "
|
||||
selected: "*"
|
||||
|
||||
ascii_hollow:
|
||||
<<: *ascii
|
||||
default_icon: ○
|
||||
folder:
|
||||
closed: ▷
|
||||
open: ▽
|
||||
|
||||
devicons: &devicons
|
||||
link:
|
||||
broken:
|
||||
normal:
|
||||
status:
|
||||
active: ▶
|
||||
inactive: " "
|
||||
not_selected: " "
|
||||
selected: ✸
|
||||
|
||||
emoji: *devicons
|
||||
@ -1,146 +0,0 @@
|
||||
from dataclasses import dataclass
|
||||
from enum import Enum, auto
|
||||
from pathlib import Path
|
||||
from typing import Mapping
|
||||
|
||||
TOP_LEVEL = Path(__file__).resolve(strict=True).parent
|
||||
ASSETS = TOP_LEVEL / "assets"
|
||||
ARTIFACT = TOP_LEVEL / "artifacts" / "artifact.json"
|
||||
|
||||
|
||||
"""
|
||||
Icons
|
||||
"""
|
||||
|
||||
|
||||
Icon = str
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class _FolderIcons:
|
||||
open: Icon
|
||||
closed: Icon
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class _LinkIcons:
|
||||
normal: Icon
|
||||
broken: Icon
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class _StatusIcons:
|
||||
active: Icon
|
||||
inactive: Icon
|
||||
selected: Icon
|
||||
not_selected: Icon
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class IconGlyphs:
|
||||
default_icon: Icon
|
||||
folder: _FolderIcons
|
||||
link: _LinkIcons
|
||||
status: _StatusIcons
|
||||
|
||||
ext_exact: Mapping[str, Icon]
|
||||
name_exact: Mapping[str, Icon]
|
||||
name_glob: Mapping[str, Icon]
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class IconGlyphSet:
|
||||
ascii_hollow: IconGlyphs
|
||||
ascii: IconGlyphs
|
||||
devicons: IconGlyphs
|
||||
emoji: IconGlyphs
|
||||
|
||||
|
||||
class IconGlyphSetEnum(Enum):
|
||||
ascii_hollow = auto()
|
||||
ascii = auto()
|
||||
devicons = auto()
|
||||
emoji = auto()
|
||||
|
||||
|
||||
"""
|
||||
Icon Colours
|
||||
"""
|
||||
|
||||
|
||||
Hex = str
|
||||
IconColours = Mapping[str, Hex]
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class IconColourSet:
|
||||
github: IconColours
|
||||
|
||||
|
||||
class IconColourSetEnum(Enum):
|
||||
github = auto()
|
||||
none = auto()
|
||||
|
||||
|
||||
"""
|
||||
LS Colours
|
||||
"""
|
||||
|
||||
|
||||
LS_COLOR = str
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class LSColourSet:
|
||||
solarized_dark_256: LS_COLOR
|
||||
solarized_dark: LS_COLOR
|
||||
solarized_light: LS_COLOR
|
||||
solarized_universal: LS_COLOR
|
||||
nord: LS_COLOR
|
||||
trapdoor: LS_COLOR
|
||||
|
||||
|
||||
class LSColoursEnum(Enum):
|
||||
env = auto()
|
||||
solarized_dark_256 = auto()
|
||||
solarized_dark = auto()
|
||||
solarized_light = auto()
|
||||
solarized_universal = auto()
|
||||
nord = auto()
|
||||
trapdoor = auto()
|
||||
|
||||
|
||||
"""
|
||||
Text Colours
|
||||
"""
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class TextColours:
|
||||
ext_exact: Mapping[str, Hex]
|
||||
name_exact: Mapping[str, Hex]
|
||||
name_glob: Mapping[str, Hex]
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class TextColourSet:
|
||||
nerdtree_syntax_light: TextColours
|
||||
nerdtree_syntax_dark: TextColours
|
||||
|
||||
|
||||
class TextColourSetEnum(Enum):
|
||||
nerdtree_syntax_light = auto()
|
||||
nerdtree_syntax_dark = auto()
|
||||
|
||||
|
||||
"""
|
||||
Artifact
|
||||
"""
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Artifact:
|
||||
icons: IconGlyphSet
|
||||
ls_colours: LSColourSet
|
||||
icon_colours: IconColourSet
|
||||
text_colours: TextColourSet
|
||||
@ -1,158 +0,0 @@
|
||||
from argparse import ArgumentParser, Namespace
|
||||
from asyncio import run as arun
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
from contextlib import nullcontext, redirect_stderr, redirect_stdout
|
||||
from io import StringIO
|
||||
from pathlib import Path, PurePath
|
||||
from subprocess import DEVNULL, STDOUT, CalledProcessError, run
|
||||
from sys import (
|
||||
executable,
|
||||
exit,
|
||||
getswitchinterval,
|
||||
setswitchinterval,
|
||||
stderr,
|
||||
version_info,
|
||||
)
|
||||
from textwrap import dedent
|
||||
from typing import Any, Union
|
||||
from webbrowser import open as open_w
|
||||
|
||||
from .consts import GIL_SWITCH, IS_WIN, MIGRATION_URI, REQUIREMENTS, RT_DIR, RT_PY
|
||||
|
||||
setswitchinterval(min(getswitchinterval(), GIL_SWITCH))
|
||||
|
||||
try:
|
||||
from typing import Literal
|
||||
|
||||
if version_info < (3, 8, 2):
|
||||
raise ImportError()
|
||||
except ImportError:
|
||||
msg = "For python < 3.8.2 please install using the branch -- legacy"
|
||||
print(msg, file=stderr)
|
||||
open_w(MIGRATION_URI)
|
||||
exit(1)
|
||||
|
||||
|
||||
def _socket(arg: str) -> Any:
|
||||
if arg.startswith("localhost:"):
|
||||
host, _, port = arg.rpartition(":")
|
||||
return host, int(port)
|
||||
else:
|
||||
return PurePath(arg)
|
||||
|
||||
|
||||
def parse_args() -> Namespace:
|
||||
parser = ArgumentParser()
|
||||
|
||||
sub_parsers = parser.add_subparsers(dest="command", required=True)
|
||||
|
||||
with nullcontext(sub_parsers.add_parser("run")) as p:
|
||||
p.add_argument("--ppid", type=int)
|
||||
p.add_argument("--socket", required=True, type=_socket)
|
||||
p.add_argument("--xdg")
|
||||
|
||||
with nullcontext(sub_parsers.add_parser("deps")) as p:
|
||||
p.add_argument("--nvim", action="store_true")
|
||||
p.add_argument("--xdg", nargs="?")
|
||||
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
args = parse_args()
|
||||
command: Union[Literal["deps"], Literal["run"]] = args.command
|
||||
|
||||
_XDG = Path(args.xdg) if args.xdg is not None else None
|
||||
|
||||
_RT_DIR = _XDG / "chadrt" if _XDG else RT_DIR
|
||||
_RT_PY = (
|
||||
(_RT_DIR / "Scripts" / "python.exe" if IS_WIN else _RT_DIR / "bin" / "python3")
|
||||
if _XDG
|
||||
else RT_PY
|
||||
)
|
||||
_LOCK_FILE = _RT_DIR / "requirements.lock"
|
||||
_EXEC_PATH = Path(executable)
|
||||
_EXEC_PATH = _EXEC_PATH.parent.resolve(strict=True) / _EXEC_PATH.name
|
||||
_REQ = REQUIREMENTS.read_text()
|
||||
|
||||
_IN_VENV = True
|
||||
|
||||
|
||||
if command == "deps":
|
||||
assert not _IN_VENV
|
||||
|
||||
io_out = StringIO()
|
||||
try:
|
||||
from venv import EnvBuilder
|
||||
|
||||
print("...", flush=True)
|
||||
with redirect_stdout(io_out), redirect_stderr(io_out):
|
||||
EnvBuilder(
|
||||
system_site_packages=False,
|
||||
with_pip=True,
|
||||
upgrade=True,
|
||||
symlinks=not IS_WIN,
|
||||
clear=True,
|
||||
).create(_RT_DIR)
|
||||
except (ImportError, CalledProcessError):
|
||||
msg = "Please install python3-venv separately. (apt, yum, apk, etc)"
|
||||
print(msg, io_out.getvalue(), file=stderr)
|
||||
exit(1)
|
||||
else:
|
||||
proc = run(
|
||||
(
|
||||
_RT_PY,
|
||||
"-m",
|
||||
"pip",
|
||||
"install",
|
||||
"--upgrade",
|
||||
"--requirement",
|
||||
REQUIREMENTS,
|
||||
),
|
||||
stdin=DEVNULL,
|
||||
stderr=STDOUT,
|
||||
)
|
||||
if proc.returncode:
|
||||
print("Installation failed, check :message", file=stderr)
|
||||
exit(proc.returncode)
|
||||
else:
|
||||
_LOCK_FILE.write_text(_REQ)
|
||||
msg = """
|
||||
---
|
||||
You can now use :CHADopen
|
||||
"""
|
||||
print(dedent(msg), file=stderr)
|
||||
|
||||
elif command == "run":
|
||||
try:
|
||||
lock = _LOCK_FILE.read_text()
|
||||
except Exception:
|
||||
lock = ""
|
||||
try:
|
||||
if not _IN_VENV:
|
||||
raise ImportError()
|
||||
elif False:
|
||||
raise ImportError()
|
||||
else:
|
||||
import pynvim_pp
|
||||
import yaml
|
||||
|
||||
from .client import init
|
||||
except ImportError as e:
|
||||
print(e)
|
||||
msg = """
|
||||
Please update dependencies using :CHADdeps
|
||||
-
|
||||
-
|
||||
Dependencies will be installed privately inside `chadtree/.vars`
|
||||
`rm -rf chadtree/` will cleanly remove everything
|
||||
"""
|
||||
msg = dedent(msg)
|
||||
print(msg, end="", file=stderr)
|
||||
exit(1)
|
||||
else:
|
||||
with ThreadPoolExecutor() as th:
|
||||
arun(init(args.socket, ppid=args.ppid, th=th))
|
||||
|
||||
|
||||
else:
|
||||
assert False
|
||||
@ -1,158 +0,0 @@
|
||||
from argparse import ArgumentParser, Namespace
|
||||
from asyncio import run as arun
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
from contextlib import nullcontext, redirect_stderr, redirect_stdout
|
||||
from io import StringIO
|
||||
from pathlib import Path, PurePath
|
||||
from subprocess import DEVNULL, STDOUT, CalledProcessError, run
|
||||
from sys import (
|
||||
executable,
|
||||
exit,
|
||||
getswitchinterval,
|
||||
setswitchinterval,
|
||||
stderr,
|
||||
version_info,
|
||||
)
|
||||
from textwrap import dedent
|
||||
from typing import Any, Union
|
||||
from webbrowser import open as open_w
|
||||
|
||||
from .consts import GIL_SWITCH, IS_WIN, MIGRATION_URI, REQUIREMENTS, RT_DIR, RT_PY
|
||||
|
||||
setswitchinterval(min(getswitchinterval(), GIL_SWITCH))
|
||||
|
||||
try:
|
||||
from typing import Literal
|
||||
|
||||
if version_info < (3, 8, 2):
|
||||
raise ImportError()
|
||||
except ImportError:
|
||||
msg = "For python < 3.8.2 please install using the branch -- legacy"
|
||||
print(msg, file=stderr)
|
||||
open_w(MIGRATION_URI)
|
||||
exit(1)
|
||||
|
||||
|
||||
def _socket(arg: str) -> Any:
|
||||
if arg.startswith("localhost:"):
|
||||
host, _, port = arg.rpartition(":")
|
||||
return host, int(port)
|
||||
else:
|
||||
return PurePath(arg)
|
||||
|
||||
|
||||
def parse_args() -> Namespace:
|
||||
parser = ArgumentParser()
|
||||
|
||||
sub_parsers = parser.add_subparsers(dest="command", required=True)
|
||||
|
||||
with nullcontext(sub_parsers.add_parser("run")) as p:
|
||||
p.add_argument("--ppid", type=int)
|
||||
p.add_argument("--socket", required=True, type=_socket)
|
||||
p.add_argument("--xdg")
|
||||
|
||||
with nullcontext(sub_parsers.add_parser("deps")) as p:
|
||||
p.add_argument("--nvim", action="store_true")
|
||||
p.add_argument("--xdg", nargs="?")
|
||||
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
args = parse_args()
|
||||
command: Union[Literal["deps"], Literal["run"]] = args.command
|
||||
|
||||
_XDG = Path(args.xdg) if args.xdg is not None else None
|
||||
|
||||
_RT_DIR = _XDG / "chadrt" if _XDG else RT_DIR
|
||||
_RT_PY = (
|
||||
(_RT_DIR / "Scripts" / "python.exe" if IS_WIN else _RT_DIR / "bin" / "python3")
|
||||
if _XDG
|
||||
else RT_PY
|
||||
)
|
||||
_LOCK_FILE = _RT_DIR / "requirements.lock"
|
||||
_EXEC_PATH = Path(executable)
|
||||
_EXEC_PATH = _EXEC_PATH.parent.resolve(strict=True) / _EXEC_PATH.name
|
||||
_REQ = REQUIREMENTS.read_text()
|
||||
|
||||
_IN_VENV = _RT_PY == _EXEC_PATH
|
||||
|
||||
|
||||
if command == "deps":
|
||||
assert not _IN_VENV
|
||||
|
||||
io_out = StringIO()
|
||||
try:
|
||||
from venv import EnvBuilder
|
||||
|
||||
print("...", flush=True)
|
||||
with redirect_stdout(io_out), redirect_stderr(io_out):
|
||||
EnvBuilder(
|
||||
system_site_packages=False,
|
||||
with_pip=True,
|
||||
upgrade=True,
|
||||
symlinks=not IS_WIN,
|
||||
clear=True,
|
||||
).create(_RT_DIR)
|
||||
except (ImportError, CalledProcessError):
|
||||
msg = "Please install python3-venv separately. (apt, yum, apk, etc)"
|
||||
print(msg, io_out.getvalue(), file=stderr)
|
||||
exit(1)
|
||||
else:
|
||||
proc = run(
|
||||
(
|
||||
_RT_PY,
|
||||
"-m",
|
||||
"pip",
|
||||
"install",
|
||||
"--upgrade",
|
||||
"--requirement",
|
||||
REQUIREMENTS,
|
||||
),
|
||||
stdin=DEVNULL,
|
||||
stderr=STDOUT,
|
||||
)
|
||||
if proc.returncode:
|
||||
print("Installation failed, check :message", file=stderr)
|
||||
exit(proc.returncode)
|
||||
else:
|
||||
_LOCK_FILE.write_text(_REQ)
|
||||
msg = """
|
||||
---
|
||||
You can now use :CHADopen
|
||||
"""
|
||||
print(dedent(msg), file=stderr)
|
||||
|
||||
elif command == "run":
|
||||
try:
|
||||
lock = _LOCK_FILE.read_text()
|
||||
except Exception:
|
||||
lock = ""
|
||||
try:
|
||||
if not _IN_VENV:
|
||||
raise ImportError()
|
||||
elif lock != _REQ:
|
||||
raise ImportError()
|
||||
else:
|
||||
import pynvim_pp
|
||||
import yaml
|
||||
|
||||
from .client import init
|
||||
except ImportError as e:
|
||||
print(e)
|
||||
msg = """
|
||||
Please update dependencies using :CHADdeps
|
||||
-
|
||||
-
|
||||
Dependencies will be installed privately inside `chadtree/.vars`
|
||||
`rm -rf chadtree/` will cleanly remove everything
|
||||
"""
|
||||
msg = dedent(msg)
|
||||
print(msg, end="", file=stderr)
|
||||
exit(1)
|
||||
else:
|
||||
with ThreadPoolExecutor() as th:
|
||||
arun(init(args.socket, ppid=args.ppid, th=th))
|
||||
|
||||
|
||||
else:
|
||||
assert False
|
||||
@ -1,54 +0,0 @@
|
||||
from .transitions import (
|
||||
autocmds,
|
||||
click,
|
||||
collapse,
|
||||
copy_name,
|
||||
cut_copy,
|
||||
delete,
|
||||
filter,
|
||||
focus,
|
||||
help,
|
||||
link,
|
||||
marks,
|
||||
new,
|
||||
noop,
|
||||
open_system,
|
||||
quit,
|
||||
refresh,
|
||||
rename,
|
||||
resize,
|
||||
schedule_update,
|
||||
selection,
|
||||
stat,
|
||||
toggle_exec,
|
||||
toggle_open,
|
||||
toggles,
|
||||
)
|
||||
|
||||
assert autocmds
|
||||
assert click
|
||||
assert collapse
|
||||
assert copy_name
|
||||
assert cut_copy
|
||||
assert delete
|
||||
assert filter
|
||||
assert focus
|
||||
assert help
|
||||
assert link
|
||||
assert marks
|
||||
assert new
|
||||
assert noop
|
||||
assert open_system
|
||||
assert quit
|
||||
assert refresh
|
||||
assert refresh
|
||||
assert rename
|
||||
assert resize
|
||||
assert schedule_update
|
||||
assert selection
|
||||
assert stat
|
||||
assert toggle_exec
|
||||
assert toggle_open
|
||||
assert toggles
|
||||
|
||||
____ = None
|
||||
@ -1,217 +0,0 @@
|
||||
from asyncio import (
|
||||
FIRST_COMPLETED,
|
||||
AbstractEventLoop,
|
||||
Event,
|
||||
Lock,
|
||||
Task,
|
||||
create_task,
|
||||
gather,
|
||||
get_running_loop,
|
||||
wait,
|
||||
wrap_future,
|
||||
)
|
||||
from concurrent.futures import Future, ThreadPoolExecutor
|
||||
from contextlib import AbstractAsyncContextManager, suppress
|
||||
from functools import wraps
|
||||
from logging import DEBUG as DEBUG_LVL
|
||||
from logging import INFO
|
||||
from multiprocessing import cpu_count
|
||||
from pathlib import Path
|
||||
from platform import uname
|
||||
from string import Template
|
||||
from sys import executable, exit
|
||||
from textwrap import dedent
|
||||
from time import monotonic
|
||||
from typing import Any, Optional, Sequence, cast
|
||||
|
||||
from pynvim_pp.highlight import highlight
|
||||
from pynvim_pp.logging import log, suppress_and_log
|
||||
from pynvim_pp.nvim import Nvim, conn
|
||||
from pynvim_pp.rpc_types import (
|
||||
Method,
|
||||
MsgType,
|
||||
NvimError,
|
||||
RPCallable,
|
||||
RPClient,
|
||||
ServerAddr,
|
||||
)
|
||||
from pynvim_pp.types import NoneType
|
||||
from std2.asyncio import cancel
|
||||
from std2.cell import RefCell
|
||||
from std2.contextlib import nullacontext
|
||||
from std2.pickle.types import DecodeError
|
||||
from std2.platform import OS, os
|
||||
from std2.sched import aticker
|
||||
from std2.sys import autodie
|
||||
|
||||
from ._registry import ____
|
||||
from .consts import DEBUG, RENDER_RETRIES
|
||||
from .registry import autocmd, dequeue_event, enqueue_event, rpc
|
||||
from .settings.load import initial as initial_settings
|
||||
from .settings.localization import init as init_locale
|
||||
from .state.load import initial as initial_state
|
||||
from .state.types import State
|
||||
from .timeit import timeit
|
||||
from .transitions.autocmds import setup
|
||||
from .transitions.redraw import redraw
|
||||
from .transitions.schedule_update import scheduled_update
|
||||
from .transitions.types import Stage
|
||||
|
||||
assert ____ or True
|
||||
|
||||
_CB = RPCallable[Optional[Stage]]
|
||||
|
||||
|
||||
def _autodie(ppid: int) -> AbstractAsyncContextManager:
|
||||
if os is OS.windows:
|
||||
return nullacontext(None)
|
||||
else:
|
||||
return autodie(ppid)
|
||||
|
||||
|
||||
async def _profile(t1: float) -> None:
|
||||
t2 = monotonic()
|
||||
info = uname()
|
||||
msg = f"""
|
||||
First msg {int((t2 - t1) * 1000)}ms
|
||||
Arch {info.machine}
|
||||
Processor {info.processor}
|
||||
Cores {cpu_count()}
|
||||
System {info.system}
|
||||
Version {info.version}
|
||||
Python {Path(executable).resolve(strict=True)}
|
||||
"""
|
||||
await Nvim.write(dedent(msg))
|
||||
|
||||
|
||||
async def _sched(ref: RefCell[State]) -> None:
|
||||
await enqueue_event(False, method=scheduled_update.method, params=(True,))
|
||||
|
||||
async for _ in aticker(ref.val.settings.polling_rate, immediately=False):
|
||||
if ref.val.vim_focus:
|
||||
await enqueue_event(False, method=scheduled_update.method)
|
||||
|
||||
|
||||
def _trans(handler: _CB) -> _CB:
|
||||
@wraps(handler)
|
||||
async def f(*params: Any) -> None:
|
||||
await enqueue_event(True, method=handler.method, params=params)
|
||||
|
||||
return cast(_CB, f)
|
||||
|
||||
|
||||
async def _default(_: MsgType, method: Method, params: Sequence[Any]) -> None:
|
||||
await enqueue_event(True, method=method, params=params)
|
||||
|
||||
|
||||
async def _go(loop: AbstractEventLoop, client: RPClient) -> None:
|
||||
th = ThreadPoolExecutor()
|
||||
atomic, handlers = rpc.drain()
|
||||
try:
|
||||
settings = await initial_settings(handlers.values())
|
||||
except DecodeError as e:
|
||||
tpl = """
|
||||
Some options may have changed.
|
||||
See help doc on Github under [docs/CONFIGURATION.md]
|
||||
|
||||
|
||||
${e}
|
||||
"""
|
||||
ms = Template(dedent(tpl)).substitute(e=e)
|
||||
await Nvim.write(ms, error=True)
|
||||
exit(1)
|
||||
else:
|
||||
hl = highlight(*settings.view.hl_context.groups)
|
||||
await (atomic + autocmd.drain() + hl).commit(NoneType)
|
||||
state = RefCell(await initial_state(settings, th=th))
|
||||
|
||||
init_locale(settings.lang)
|
||||
with suppress_and_log():
|
||||
await setup(settings)
|
||||
|
||||
for f in handlers.values():
|
||||
ff = _trans(f)
|
||||
client.register(ff)
|
||||
|
||||
staged = RefCell[Optional[Stage]](None)
|
||||
event = Event()
|
||||
lock = Lock()
|
||||
|
||||
async def step(method: Method, params: Sequence[Any]) -> None:
|
||||
if handler := cast(Optional[_CB], handlers.get(method)):
|
||||
with suppress_and_log():
|
||||
async with lock:
|
||||
if stage := await handler(state.val, *params):
|
||||
state.val = stage.state
|
||||
staged.val = stage
|
||||
event.set()
|
||||
else:
|
||||
assert False, (method, params)
|
||||
|
||||
async def c1() -> None:
|
||||
transcient: Optional[Task] = None
|
||||
get: Optional[Task] = None
|
||||
try:
|
||||
while True:
|
||||
with suppress_and_log():
|
||||
get = create_task(dequeue_event())
|
||||
if transcient:
|
||||
await wait((transcient, get), return_when=FIRST_COMPLETED)
|
||||
if not transcient.done():
|
||||
with timeit("transcient"):
|
||||
await cancel(transcient)
|
||||
transcient = None
|
||||
|
||||
sync, method, params = await get
|
||||
task = step(method, params=params)
|
||||
if sync:
|
||||
with timeit(method):
|
||||
await task
|
||||
else:
|
||||
transcient = create_task(task)
|
||||
finally:
|
||||
await cancel(
|
||||
*(get or loop.create_future(), transcient or loop.create_future())
|
||||
)
|
||||
|
||||
async def c2() -> None:
|
||||
t1, has_drawn = monotonic(), False
|
||||
|
||||
while True:
|
||||
await event.wait()
|
||||
with suppress_and_log():
|
||||
try:
|
||||
if stage := staged.val:
|
||||
state = stage.state
|
||||
|
||||
for _ in range(RENDER_RETRIES - 1):
|
||||
with suppress(NvimError):
|
||||
await redraw(state, focus=stage.focus)
|
||||
break
|
||||
else:
|
||||
try:
|
||||
await redraw(state, focus=stage.focus)
|
||||
except NvimError as e:
|
||||
log.warn("%s", e)
|
||||
|
||||
if settings.profiling and not has_drawn:
|
||||
has_drawn = True
|
||||
await _profile(t1=t1)
|
||||
finally:
|
||||
event.clear()
|
||||
|
||||
await gather(c1(), c2(), _sched(state))
|
||||
|
||||
|
||||
async def init(socket: ServerAddr, ppid: int, th: ThreadPoolExecutor) -> None:
|
||||
loop = get_running_loop()
|
||||
loop.set_default_executor(th)
|
||||
log.setLevel(DEBUG_LVL if DEBUG else INFO)
|
||||
|
||||
die: Future = Future()
|
||||
|
||||
async def cont() -> None:
|
||||
async with conn(die, socket=socket, default=_default) as client:
|
||||
await _go(loop, client=client)
|
||||
|
||||
await gather(wrap_future(die), cont())
|
||||
@ -1,65 +0,0 @@
|
||||
from os import environ, name
|
||||
from pathlib import Path
|
||||
|
||||
from chad_types import TOP_LEVEL
|
||||
|
||||
GIL_SWITCH = 1 / 1000
|
||||
IS_WIN = name == "nt"
|
||||
REQUIREMENTS = TOP_LEVEL / "requirements.txt"
|
||||
|
||||
DEBUG = "CHADTREE_DEBUG" in environ
|
||||
|
||||
BATCH_FACTOR = 88
|
||||
RENDER_RETRIES = 3
|
||||
|
||||
FM_FILETYPE = "CHADTree"
|
||||
FM_HL_PREFIX = "chadtree"
|
||||
URI_SCHEME = FM_FILETYPE.casefold()
|
||||
|
||||
DEFAULT_LANG = "en"
|
||||
LANG_ROOT = TOP_LEVEL / "locale"
|
||||
CONFIG_YML = TOP_LEVEL / "config" / "defaults.yml"
|
||||
SETTINGS_VAR = "chadtree_settings"
|
||||
|
||||
"""
|
||||
STORAGE
|
||||
"""
|
||||
|
||||
_VARS = Path.home() / ".cache/chadtree/vars"
|
||||
RT_DIR = _VARS / "runtime"
|
||||
RT_PY = RT_DIR / "Scripts" / "python.exe" if IS_WIN else RT_DIR / "bin" / "python3"
|
||||
SESSION_DIR = _VARS / "sessions"
|
||||
|
||||
|
||||
"""
|
||||
Docs
|
||||
"""
|
||||
|
||||
|
||||
_DOCS_URI_BASE = "https://github.com/ms-jpq/chadtree/blob/chad/docs"
|
||||
_DOCS_DIR = TOP_LEVEL / "docs"
|
||||
|
||||
|
||||
_README_md = "README.md"
|
||||
README_MD = _DOCS_DIR / _README_md
|
||||
README_URI = f"{_DOCS_URI_BASE}"
|
||||
|
||||
_FEATURES_md = "FEATURES.md"
|
||||
FEATURES_MD = _DOCS_DIR / _FEATURES_md
|
||||
FEATURES_URI = f"{_DOCS_URI_BASE}/{_FEATURES_md}"
|
||||
|
||||
_KEYBIND_md = "KEYBIND.md"
|
||||
KEYBIND_MD = _DOCS_DIR / _KEYBIND_md
|
||||
KEYBIND_URI = f"{_DOCS_URI_BASE}/{_KEYBIND_md}"
|
||||
|
||||
_CONFIGURATION_md = "CONFIGURATION.md"
|
||||
CONFIGURATION_MD = _DOCS_DIR / _CONFIGURATION_md
|
||||
CONFIGURATION_URI = f"{_DOCS_URI_BASE}/{_CONFIGURATION_md}"
|
||||
|
||||
_THEME_md = "THEME.md"
|
||||
THEME_MD = _DOCS_DIR / _THEME_md
|
||||
THEME_URI = f"{_DOCS_URI_BASE}/{_THEME_md}"
|
||||
|
||||
_MIGRATION_md = "MIGRATION.md"
|
||||
MIGRATION_MD = _DOCS_DIR / _MIGRATION_md
|
||||
MIGRATION_URI = f"{_DOCS_URI_BASE}/{_MIGRATION_md}"
|
||||
@ -1,230 +0,0 @@
|
||||
from asyncio import sleep
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
from contextlib import suppress
|
||||
from fnmatch import fnmatch
|
||||
from os import DirEntry, scandir, stat, stat_result
|
||||
from os.path import normcase
|
||||
from pathlib import Path, PurePath
|
||||
from stat import (
|
||||
S_IFDOOR,
|
||||
S_ISBLK,
|
||||
S_ISCHR,
|
||||
S_ISDIR,
|
||||
S_ISFIFO,
|
||||
S_ISGID,
|
||||
S_ISLNK,
|
||||
S_ISREG,
|
||||
S_ISSOCK,
|
||||
S_ISUID,
|
||||
S_ISVTX,
|
||||
S_IWOTH,
|
||||
S_IXUSR,
|
||||
)
|
||||
from typing import (
|
||||
AbstractSet,
|
||||
Iterator,
|
||||
Mapping,
|
||||
MutableMapping,
|
||||
Optional,
|
||||
Tuple,
|
||||
Union,
|
||||
cast,
|
||||
)
|
||||
|
||||
from std2.itertools import batched
|
||||
from std2.pathlib import is_relative_to
|
||||
|
||||
from ..consts import BATCH_FACTOR
|
||||
from ..state.executor import AsyncExecutor
|
||||
from ..state.types import Index
|
||||
from ..timeit import timeit
|
||||
from .nt import is_junction
|
||||
from .types import Ignored, Mode, Node
|
||||
|
||||
_FILE_MODES: Mapping[int, Mode] = {
|
||||
S_IXUSR: Mode.executable,
|
||||
S_IFDOOR: Mode.door,
|
||||
S_ISGID: Mode.set_gid,
|
||||
S_ISUID: Mode.set_uid,
|
||||
S_ISVTX: Mode.sticky,
|
||||
S_IWOTH: Mode.other_writable,
|
||||
S_IWOTH | S_ISVTX: Mode.sticky_other_writable,
|
||||
}
|
||||
|
||||
|
||||
def _iter(
|
||||
dirent: Union[PurePath, DirEntry[str]], follow: bool, index: Index, lv: int = 0
|
||||
) -> Iterator[PurePath]:
|
||||
if not lv:
|
||||
yield PurePath(dirent)
|
||||
with suppress(NotADirectoryError, FileNotFoundError, PermissionError):
|
||||
with scandir(dirent) as dirents:
|
||||
for child in dirents:
|
||||
yield (path := PurePath(child))
|
||||
if child.is_dir(follow_symlinks=follow) and path in index:
|
||||
yield from _iter(child, follow=follow, index=index, lv=lv + 1)
|
||||
|
||||
|
||||
def _fs_modes(stat: stat_result) -> Iterator[Mode]:
|
||||
st_mode = stat.st_mode
|
||||
if S_ISDIR(st_mode):
|
||||
yield Mode.folder
|
||||
if S_ISREG(st_mode):
|
||||
yield Mode.file
|
||||
if S_ISFIFO(st_mode):
|
||||
yield Mode.pipe
|
||||
if S_ISSOCK(st_mode):
|
||||
yield Mode.socket
|
||||
if S_ISCHR(st_mode):
|
||||
yield Mode.char_device
|
||||
if S_ISBLK(st_mode):
|
||||
yield Mode.block_device
|
||||
if stat.st_nlink > 1:
|
||||
yield Mode.multi_hardlink
|
||||
for bit, mode in _FILE_MODES.items():
|
||||
if bit and st_mode & bit == bit:
|
||||
yield mode
|
||||
|
||||
|
||||
def _fs_stat(path: PurePath) -> Tuple[AbstractSet[Mode], Optional[PurePath]]:
|
||||
try:
|
||||
info = stat(path, follow_symlinks=False)
|
||||
except (FileNotFoundError, PermissionError):
|
||||
return {Mode.orphan_link}, None
|
||||
else:
|
||||
if S_ISLNK(info.st_mode) or is_junction(info):
|
||||
try:
|
||||
pointed = Path(path).resolve(strict=True)
|
||||
link_info = stat(pointed, follow_symlinks=False)
|
||||
except (FileNotFoundError, NotADirectoryError, RuntimeError):
|
||||
return {Mode.orphan_link}, None
|
||||
else:
|
||||
mode = {*_fs_modes(link_info)}
|
||||
return mode | {Mode.link}, pointed
|
||||
else:
|
||||
mode = {*_fs_modes(info)}
|
||||
return mode, None
|
||||
|
||||
|
||||
def _fs_node(path: PurePath) -> Node:
|
||||
mode, pointed = _fs_stat(path)
|
||||
node = Node(
|
||||
path=path,
|
||||
mode=mode,
|
||||
pointed=pointed,
|
||||
children={},
|
||||
)
|
||||
return node
|
||||
|
||||
|
||||
def _iter_single_nodes(
|
||||
th: ThreadPoolExecutor, root: PurePath, follow: bool, index: Index
|
||||
) -> Iterator[Node]:
|
||||
with timeit("fs->_iter"):
|
||||
dir_stream = batched(_iter(root, index=index, follow=follow), n=BATCH_FACTOR)
|
||||
for seq in th.map(lambda x: tuple(map(_fs_node, x)), dir_stream):
|
||||
yield from seq
|
||||
|
||||
|
||||
async def _new(
|
||||
th: ThreadPoolExecutor, root: PurePath, follow_links: bool, index: Index
|
||||
) -> Node:
|
||||
nodes: MutableMapping[PurePath, Node] = {}
|
||||
|
||||
for idx, node in enumerate(
|
||||
_iter_single_nodes(th, root=root, follow=follow_links, index=index), start=1
|
||||
):
|
||||
if idx % BATCH_FACTOR == 0:
|
||||
await sleep(0)
|
||||
nodes[node.path] = node
|
||||
if parent := nodes.get(node.path.parent):
|
||||
if parent == node:
|
||||
continue
|
||||
cast(MutableMapping[PurePath, Node], parent.children)[node.path] = node
|
||||
|
||||
return nodes[root]
|
||||
|
||||
|
||||
def _cross_over(root: PurePath, invalid: PurePath) -> bool:
|
||||
return is_relative_to(root, invalid) or is_relative_to(invalid, root)
|
||||
|
||||
|
||||
async def _update(
|
||||
th: ThreadPoolExecutor,
|
||||
root: Node,
|
||||
follow_links: bool,
|
||||
index: Index,
|
||||
invalidate_dirs: AbstractSet[PurePath],
|
||||
) -> Node:
|
||||
if any((_cross_over(root.path, invalid=invalid) for invalid in invalidate_dirs)):
|
||||
return await _new(th, root=root.path, follow_links=follow_links, index=index)
|
||||
else:
|
||||
children: MutableMapping[PurePath, Node] = {}
|
||||
for path, node in root.children.items():
|
||||
new_node = await _update(
|
||||
th,
|
||||
root=node,
|
||||
follow_links=follow_links,
|
||||
index=index,
|
||||
invalidate_dirs=invalidate_dirs,
|
||||
)
|
||||
children[path] = new_node
|
||||
return Node(
|
||||
path=root.path,
|
||||
mode=root.mode,
|
||||
pointed=root.pointed,
|
||||
children=children,
|
||||
)
|
||||
|
||||
|
||||
async def new(
|
||||
exec: AsyncExecutor, root: PurePath, follow_links: bool, index: Index
|
||||
) -> Node:
|
||||
with timeit("fs->new"):
|
||||
return await exec.submit(
|
||||
_new(exec.threadpool, root=root, follow_links=follow_links, index=index)
|
||||
)
|
||||
|
||||
|
||||
async def update(
|
||||
exec: AsyncExecutor,
|
||||
root: Node,
|
||||
*,
|
||||
follow_links: bool,
|
||||
index: Index,
|
||||
invalidate_dirs: AbstractSet[PurePath],
|
||||
) -> Node:
|
||||
with timeit("fs->_update"):
|
||||
try:
|
||||
return await exec.submit(
|
||||
_update(
|
||||
exec.threadpool,
|
||||
root=root,
|
||||
follow_links=follow_links,
|
||||
index=index,
|
||||
invalidate_dirs=invalidate_dirs,
|
||||
)
|
||||
)
|
||||
except FileNotFoundError:
|
||||
return await new(
|
||||
exec, follow_links=follow_links, root=root.path, index=index
|
||||
)
|
||||
|
||||
|
||||
def user_ignored(node: Node, ignores: Ignored) -> bool:
|
||||
return (
|
||||
node.path.name in ignores.name_exact
|
||||
or any(fnmatch(node.path.name, pattern) for pattern in ignores.name_glob)
|
||||
or any(fnmatch(normcase(node.path), pattern) for pattern in ignores.path_glob)
|
||||
)
|
||||
|
||||
|
||||
def is_dir(node: Node) -> bool:
|
||||
return Mode.folder in node.mode
|
||||
|
||||
|
||||
def act_like_dir(node: Node, follow_links: bool) -> bool:
|
||||
if node.pointed and not follow_links:
|
||||
return False
|
||||
else:
|
||||
return is_dir(node)
|
||||
@ -1,13 +0,0 @@
|
||||
import sys
|
||||
from os import stat_result
|
||||
from stat import S_ISDIR
|
||||
|
||||
if sys.platform == "win32":
|
||||
|
||||
def is_junction(st: stat_result) -> bool:
|
||||
return bool(S_ISDIR(st.st_mode) and st.st_reparse_tag)
|
||||
|
||||
else:
|
||||
|
||||
def is_junction(st: stat_result) -> bool:
|
||||
return False
|
||||
@ -1,242 +0,0 @@
|
||||
from asyncio import Lock, gather
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime
|
||||
from functools import lru_cache
|
||||
from itertools import chain
|
||||
from os import makedirs, readlink
|
||||
from os import remove as rm
|
||||
from os import stat, symlink
|
||||
from os.path import isdir, isfile, normpath
|
||||
from pathlib import Path, PurePath
|
||||
from shutil import copy2, copytree
|
||||
from shutil import move as mv
|
||||
from shutil import rmtree
|
||||
from shutil import which as _which
|
||||
from stat import S_ISDIR, S_ISLNK, filemode
|
||||
from typing import AbstractSet, Iterable, Mapping, Optional
|
||||
|
||||
from std2.asyncio import to_thread
|
||||
from std2.stat import RW_R__R__, RWXR_XR_X
|
||||
|
||||
from .nt import is_junction
|
||||
|
||||
_FOLDER_MODE = RWXR_XR_X
|
||||
_FILE_MODE = RW_R__R__
|
||||
|
||||
|
||||
def ancestors(*paths: PurePath) -> AbstractSet[PurePath]:
|
||||
return {*chain.from_iterable(path.parents for path in paths)}
|
||||
|
||||
|
||||
def unify_ancestors(paths: AbstractSet[PurePath]) -> AbstractSet[PurePath]:
|
||||
return {p for p in paths if ancestors(p).isdisjoint(paths)}
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class FSstat:
|
||||
permissions: str
|
||||
user: str
|
||||
group: str
|
||||
date_mod: datetime
|
||||
size: int
|
||||
link: Optional[PurePath]
|
||||
|
||||
|
||||
@lru_cache(maxsize=None)
|
||||
def lock() -> Lock:
|
||||
return Lock()
|
||||
|
||||
|
||||
try:
|
||||
from grp import getgrgid
|
||||
from pwd import getpwuid
|
||||
|
||||
def _get_username(uid: int) -> str:
|
||||
try:
|
||||
return getpwuid(uid).pw_name
|
||||
except KeyError:
|
||||
return str(uid)
|
||||
|
||||
def _get_groupname(gid: int) -> str:
|
||||
try:
|
||||
return getgrgid(gid).gr_name
|
||||
except KeyError:
|
||||
return str(gid)
|
||||
|
||||
except ImportError:
|
||||
|
||||
def _get_username(uid: int) -> str:
|
||||
return str(uid)
|
||||
|
||||
def _get_groupname(gid: int) -> str:
|
||||
return str(gid)
|
||||
|
||||
|
||||
@lru_cache(maxsize=None)
|
||||
def which(path: PurePath) -> Optional[PurePath]:
|
||||
if bin := _which(path):
|
||||
return PurePath(bin)
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
async def fs_stat(path: PurePath) -> FSstat:
|
||||
def cont() -> FSstat:
|
||||
stats = stat(path, follow_symlinks=False)
|
||||
permissions = filemode(stats.st_mode)
|
||||
user = _get_username(stats.st_uid)
|
||||
group = _get_groupname(stats.st_gid)
|
||||
date_mod = datetime.fromtimestamp(stats.st_mtime)
|
||||
size = stats.st_size
|
||||
try:
|
||||
link = (
|
||||
readlink(path) if S_ISLNK(stats.st_mode) or is_junction(stats) else None
|
||||
)
|
||||
except OSError:
|
||||
plink = None
|
||||
else:
|
||||
plink = PurePath(link) if link else None
|
||||
fs_stat = FSstat(
|
||||
permissions=permissions,
|
||||
user=user,
|
||||
group=group,
|
||||
date_mod=date_mod,
|
||||
size=size,
|
||||
link=plink,
|
||||
)
|
||||
return fs_stat
|
||||
|
||||
return await to_thread(cont)
|
||||
|
||||
|
||||
async def resolve(path: PurePath, strict: bool) -> Path:
|
||||
def cont() -> Path:
|
||||
return Path(path).resolve(strict=strict)
|
||||
|
||||
return await to_thread(cont)
|
||||
|
||||
|
||||
async def exists(path: PurePath, follow: bool) -> bool:
|
||||
def cont() -> bool:
|
||||
try:
|
||||
stat(path, follow_symlinks=follow)
|
||||
except (OSError, ValueError):
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
return await to_thread(cont)
|
||||
|
||||
|
||||
async def exists_many(
|
||||
paths: Iterable[PurePath], follow: bool
|
||||
) -> Mapping[PurePath, bool]:
|
||||
existence = await gather(*(exists(path, follow=follow) for path in paths))
|
||||
return {path: exi for path, exi in zip(paths, existence)}
|
||||
|
||||
|
||||
async def is_dir(path: PurePath) -> bool:
|
||||
return await to_thread(lambda: isdir(path))
|
||||
|
||||
|
||||
async def is_file(path: PurePath) -> bool:
|
||||
return await to_thread(lambda: isfile(path))
|
||||
|
||||
|
||||
def _mkdir_p(path: PurePath) -> None:
|
||||
makedirs(path, mode=_FOLDER_MODE, exist_ok=True)
|
||||
|
||||
|
||||
async def _mkdir(path: PurePath) -> None:
|
||||
def cont() -> None:
|
||||
_mkdir_p(path)
|
||||
|
||||
await to_thread(cont)
|
||||
|
||||
|
||||
async def mkdir(paths: Iterable[PurePath]) -> None:
|
||||
await gather(*map(_mkdir, paths))
|
||||
|
||||
|
||||
async def _new(path: PurePath) -> None:
|
||||
def cont() -> None:
|
||||
makedirs(path.parent, mode=_FOLDER_MODE, exist_ok=True)
|
||||
Path(path).touch(mode=_FILE_MODE, exist_ok=True)
|
||||
|
||||
await to_thread(cont)
|
||||
|
||||
|
||||
async def new(paths: Iterable[PurePath]) -> None:
|
||||
async with lock():
|
||||
await gather(*map(_new, paths))
|
||||
|
||||
|
||||
async def _rename(src: PurePath, dst: PurePath) -> None:
|
||||
def cont() -> None:
|
||||
makedirs(dst.parent, mode=_FOLDER_MODE, exist_ok=True)
|
||||
mv(normpath(src), normpath(dst))
|
||||
|
||||
await to_thread(cont)
|
||||
|
||||
|
||||
async def rename(operations: Mapping[PurePath, PurePath]) -> None:
|
||||
async with lock():
|
||||
await gather(*(_rename(src, dst) for src, dst in operations.items()))
|
||||
|
||||
|
||||
async def _remove(path: PurePath) -> None:
|
||||
def cont() -> None:
|
||||
stats = stat(path, follow_symlinks=False)
|
||||
if S_ISDIR(stats.st_mode):
|
||||
rmtree(path)
|
||||
else:
|
||||
rm(path)
|
||||
|
||||
await to_thread(cont)
|
||||
|
||||
|
||||
async def remove(paths: Iterable[PurePath]) -> None:
|
||||
async with lock():
|
||||
await gather(*map(_remove, paths))
|
||||
|
||||
|
||||
async def _cut(src: PurePath, dst: PurePath) -> None:
|
||||
def cont() -> None:
|
||||
mv(normpath(src), normpath(dst))
|
||||
|
||||
await to_thread(cont)
|
||||
|
||||
|
||||
async def cut(operations: Mapping[PurePath, PurePath]) -> None:
|
||||
async with lock():
|
||||
await gather(*(_cut(src, dst) for src, dst in operations.items()))
|
||||
|
||||
|
||||
async def _copy(src: PurePath, dst: PurePath) -> None:
|
||||
def cont() -> None:
|
||||
stats = stat(src, follow_symlinks=False)
|
||||
if S_ISDIR(stats.st_mode):
|
||||
copytree(src, dst, symlinks=True, dirs_exist_ok=True)
|
||||
else:
|
||||
copy2(src, dst, follow_symlinks=False)
|
||||
|
||||
await to_thread(cont)
|
||||
|
||||
|
||||
async def copy(operations: Mapping[PurePath, PurePath]) -> None:
|
||||
async with lock():
|
||||
await gather(*(_copy(src, dst) for src, dst in operations.items()))
|
||||
|
||||
|
||||
async def _link(src: PurePath, dst: PurePath) -> None:
|
||||
def cont() -> None:
|
||||
target_is_directory = isdir(src)
|
||||
_mkdir_p(dst.parent)
|
||||
symlink(normpath(src), normpath(dst), target_is_directory=target_is_directory)
|
||||
|
||||
await to_thread(cont)
|
||||
|
||||
|
||||
async def link(operations: Mapping[PurePath, PurePath]) -> None:
|
||||
async with lock():
|
||||
await gather(*(_link(src, dst) for dst, src in operations.items()))
|
||||
@ -1,52 +0,0 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass, field
|
||||
from enum import IntEnum, auto, unique
|
||||
from pathlib import PurePath
|
||||
from typing import AbstractSet, Any, Mapping, Optional, Sequence
|
||||
|
||||
|
||||
# https://github.com/coreutils/coreutils/blob/master/src/ls.c
|
||||
@unique
|
||||
class Mode(IntEnum):
|
||||
orphan_link = auto()
|
||||
link = auto()
|
||||
|
||||
pipe = auto()
|
||||
socket = auto()
|
||||
block_device = auto()
|
||||
char_device = auto()
|
||||
door = auto()
|
||||
|
||||
sticky_other_writable = auto()
|
||||
other_writable = auto()
|
||||
sticky = auto()
|
||||
folder = auto()
|
||||
|
||||
set_uid = auto()
|
||||
set_gid = auto()
|
||||
file_w_capacity = auto()
|
||||
executable = auto()
|
||||
multi_hardlink = auto()
|
||||
file = auto()
|
||||
|
||||
|
||||
@dataclass
|
||||
class _RenderCache:
|
||||
sort_by: Optional[Sequence[Any]] = None
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Node:
|
||||
mode: AbstractSet[Mode]
|
||||
path: PurePath
|
||||
pointed: Optional[PurePath]
|
||||
children: Mapping[PurePath, Node]
|
||||
cache: _RenderCache = field(default_factory=_RenderCache)
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Ignored:
|
||||
name_exact: AbstractSet[str]
|
||||
name_glob: Sequence[str]
|
||||
path_glob: Sequence[str]
|
||||
@ -1,30 +0,0 @@
|
||||
(function(_)
|
||||
if vim.diagnostic then
|
||||
local diagnostics = vim.diagnostic.get(nil, nil)
|
||||
vim.validate({diagnostics = {diagnostics, "table"}})
|
||||
local acc = {}
|
||||
for _, row in pairs(diagnostics) do
|
||||
local buf = row.bufnr
|
||||
local severity = tostring(row.severity)
|
||||
vim.validate(
|
||||
{
|
||||
buf = {buf, "number"},
|
||||
row_severity = {row.severity, "number"}
|
||||
}
|
||||
)
|
||||
if not acc[buf] then
|
||||
acc[buf] = {}
|
||||
end
|
||||
if not acc[buf][severity] then
|
||||
acc[buf][severity] = 0
|
||||
end
|
||||
acc[buf][severity] = acc[buf][severity] + 1
|
||||
end
|
||||
local acc2 = {}
|
||||
for buf, warnings in pairs(acc) do
|
||||
local path = vim.api.nvim_buf_get_name(buf)
|
||||
acc2[path] = warnings
|
||||
end
|
||||
return acc2
|
||||
end
|
||||
end)(...)
|
||||
@ -1,44 +0,0 @@
|
||||
import sys
|
||||
from collections import Counter
|
||||
from pathlib import Path, PurePath
|
||||
from typing import Mapping, MutableMapping, cast
|
||||
|
||||
from pynvim_pp.nvim import Nvim
|
||||
from pynvim_pp.types import NoneType
|
||||
|
||||
from ..fs.ops import ancestors
|
||||
from ..state.types import Diagnostics
|
||||
|
||||
_LUA = (
|
||||
Path(__file__).resolve(strict=True).with_name("diagnostics.lua").read_text("UTF-8")
|
||||
)
|
||||
|
||||
if sys.version_info < (3, 9):
|
||||
_C = Counter
|
||||
else:
|
||||
_C = Counter[int]
|
||||
|
||||
|
||||
async def poll(min_severity: int) -> Diagnostics:
|
||||
diagnostics: Mapping[str, Mapping[str, int]] = cast(
|
||||
Mapping[str, Mapping[str, int]], await Nvim.fn.luaeval(NoneType, _LUA, ())
|
||||
)
|
||||
|
||||
raw = {
|
||||
PurePath(path): Counter(
|
||||
{
|
||||
s: count
|
||||
for severity, count in (counts or {}).items()
|
||||
if (s := int(severity)) <= min_severity
|
||||
}
|
||||
)
|
||||
for path, counts in (diagnostics or {}).items()
|
||||
}
|
||||
|
||||
acc: MutableMapping[PurePath, _C] = {}
|
||||
for path, counts in raw.items():
|
||||
for parent in ancestors(path):
|
||||
c = acc.setdefault(parent, Counter())
|
||||
c += counts
|
||||
|
||||
return {**acc, **raw}
|
||||
@ -1,9 +0,0 @@
|
||||
(function(args)
|
||||
local method, params = unpack(args)
|
||||
if vim.lsp then
|
||||
local clients = (vim.lsp.get_clients or vim.lsp.get_active_clients)()
|
||||
for _, client in pairs(clients) do
|
||||
client.notify(method, params)
|
||||
end
|
||||
end
|
||||
end)(...)
|
||||
@ -1,31 +0,0 @@
|
||||
from pathlib import Path, PurePath
|
||||
from typing import Any, Iterable, Mapping
|
||||
|
||||
from pynvim_pp.nvim import Nvim
|
||||
from pynvim_pp.types import NoneType
|
||||
|
||||
_LUA = Path(__file__).resolve(strict=True).with_name("notify.lua").read_text("UTF-8")
|
||||
|
||||
|
||||
async def _notify(method: str, params: Any) -> None:
|
||||
await Nvim.fn.luaeval(NoneType, _LUA, (method, params))
|
||||
|
||||
|
||||
async def lsp_created(paths: Iterable[PurePath]) -> None:
|
||||
params = {"files": tuple({"uri": path.as_uri()} for path in paths)}
|
||||
await _notify("workspace/didCreateFiles", params=params)
|
||||
|
||||
|
||||
async def lsp_removed(paths: Iterable[PurePath]) -> None:
|
||||
params = {"files": tuple({"uri": path.as_uri()} for path in paths)}
|
||||
await _notify("workspace/didDeleteFiles", params=params)
|
||||
|
||||
|
||||
async def lsp_moved(paths: Mapping[PurePath, PurePath]) -> None:
|
||||
params = {
|
||||
"files": tuple(
|
||||
{"oldUri": old.as_uri(), "newUri": new.as_uri()}
|
||||
for old, new in paths.items()
|
||||
)
|
||||
}
|
||||
await _notify("workspace/didRenameFiles", params=params)
|
||||
@ -1,48 +0,0 @@
|
||||
from asyncio import gather
|
||||
from collections import Counter
|
||||
from itertools import chain
|
||||
from pathlib import PurePath
|
||||
from typing import AbstractSet, Mapping, MutableMapping, MutableSet, Sequence, cast
|
||||
|
||||
from pynvim_pp.atomic import Atomic
|
||||
from pynvim_pp.buffer import Buffer
|
||||
from pynvim_pp.nvim import Marker, Nvim
|
||||
from pynvim_pp.types import NoneType
|
||||
|
||||
from ..fs.ops import ancestors
|
||||
from .types import Markers
|
||||
|
||||
|
||||
async def _bookmarks() -> Mapping[PurePath, AbstractSet[Marker]]:
|
||||
acc: MutableMapping[PurePath, MutableSet[Marker]] = {}
|
||||
bookmarks = await Nvim.list_bookmarks()
|
||||
for marker, (path, _, _) in bookmarks.items():
|
||||
if path:
|
||||
for marked_path in chain((path,), ancestors(path)):
|
||||
marks = acc.setdefault(marked_path, set())
|
||||
marks.add(marker)
|
||||
|
||||
return acc
|
||||
|
||||
|
||||
async def _quickfix() -> Mapping[PurePath, int]:
|
||||
qflist = cast(Sequence[Mapping[str, int]], await Nvim.fn.getqflist(NoneType))
|
||||
|
||||
atomic = Atomic()
|
||||
for q in qflist:
|
||||
bufnr = q["bufnr"]
|
||||
buf = Buffer.from_int(bufnr)
|
||||
atomic.buf_get_name(buf)
|
||||
|
||||
bufnames = cast(Sequence[str], await atomic.commit(NoneType))
|
||||
filenames = tuple(map(PurePath, bufnames))
|
||||
parents = (ancestor for fullname in filenames for ancestor in ancestors(fullname))
|
||||
locations = Counter(chain(filenames, parents))
|
||||
|
||||
return locations
|
||||
|
||||
|
||||
async def markers() -> Markers:
|
||||
qf, bm = await gather(_quickfix(), _bookmarks())
|
||||
markers = Markers(quick_fix=qf, bookmarks=bm)
|
||||
return markers
|
||||
@ -1,11 +0,0 @@
|
||||
from dataclasses import dataclass
|
||||
from pathlib import PurePath
|
||||
from typing import AbstractSet, Mapping
|
||||
|
||||
from pynvim_pp.nvim import Marker
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Markers:
|
||||
quick_fix: Mapping[PurePath, int]
|
||||
bookmarks: Mapping[PurePath, AbstractSet[Marker]]
|
||||
@ -1,34 +0,0 @@
|
||||
from asyncio import Queue
|
||||
from functools import lru_cache
|
||||
from typing import Any, Awaitable, Callable, Sequence, Tuple
|
||||
|
||||
from pynvim_pp.autocmd import AutoCMD
|
||||
from pynvim_pp.handler import RPC
|
||||
from pynvim_pp.rpc_types import Method
|
||||
|
||||
_MSG = Tuple[bool, Method, Sequence[Any]]
|
||||
|
||||
NAMESPACE = "CHAD"
|
||||
|
||||
|
||||
def _name_gen(fn: Callable[..., Awaitable[Any]]) -> str:
|
||||
return fn.__qualname__.lstrip("_").capitalize()
|
||||
|
||||
|
||||
@lru_cache(maxsize=None)
|
||||
def queue() -> Queue:
|
||||
return Queue()
|
||||
|
||||
|
||||
autocmd = AutoCMD()
|
||||
rpc = RPC(NAMESPACE, name_gen=_name_gen)
|
||||
|
||||
|
||||
async def enqueue_event(sync: bool, method: Method, params: Sequence[Any] = ()) -> None:
|
||||
msg = (sync, method, params)
|
||||
await queue().put(msg)
|
||||
|
||||
|
||||
async def dequeue_event() -> _MSG:
|
||||
msg: _MSG = await queue().get()
|
||||
return msg
|
||||
@ -1,178 +0,0 @@
|
||||
from dataclasses import dataclass
|
||||
from enum import Enum, auto
|
||||
from locale import strxfrm
|
||||
from typing import (
|
||||
AbstractSet,
|
||||
Any,
|
||||
Iterable,
|
||||
Mapping,
|
||||
Optional,
|
||||
Sequence,
|
||||
SupportsFloat,
|
||||
Union,
|
||||
cast,
|
||||
)
|
||||
|
||||
from pynvim_pp.atomic import Atomic
|
||||
from pynvim_pp.nvim import Nvim
|
||||
from pynvim_pp.rpc_types import RPCallable
|
||||
from pynvim_pp.types import NoneType
|
||||
from pynvim_pp.window import Window
|
||||
from std2.configparser import hydrate
|
||||
from std2.graphlib import merge
|
||||
from std2.pickle.decoder import new_decoder
|
||||
from std2.pickle.types import DecodeError
|
||||
from yaml import safe_load
|
||||
|
||||
from chad_types import (
|
||||
ARTIFACT,
|
||||
Artifact,
|
||||
IconColourSetEnum,
|
||||
IconGlyphSetEnum,
|
||||
LSColoursEnum,
|
||||
TextColourSetEnum,
|
||||
)
|
||||
|
||||
from ..consts import CONFIG_YML, SETTINGS_VAR
|
||||
from ..fs.types import Ignored
|
||||
from ..registry import NAMESPACE
|
||||
from ..view.load import load_theme
|
||||
from ..view.types import HLGroups, Sortby, ViewOptions
|
||||
from .types import MimetypeOptions, Settings, VersionCtlOpts
|
||||
|
||||
|
||||
class _OpenDirection(Enum):
|
||||
left = auto()
|
||||
right = auto()
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class _UserOptions:
|
||||
close_on_open: bool
|
||||
follow: bool
|
||||
follow_links: bool
|
||||
follow_ignore: bool
|
||||
lang: Optional[str]
|
||||
mimetypes: MimetypeOptions
|
||||
page_increment: int
|
||||
polling_rate: SupportsFloat
|
||||
session: bool
|
||||
show_hidden: bool
|
||||
min_diagnostics_severity: int
|
||||
version_control: VersionCtlOpts
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class _UserTheme:
|
||||
highlights: HLGroups
|
||||
icon_glyph_set: IconGlyphSetEnum
|
||||
icon_colour_set: IconColourSetEnum
|
||||
text_colour_set: Union[LSColoursEnum, TextColourSetEnum]
|
||||
discrete_colour_map: Mapping[str, str]
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class _UserView:
|
||||
open_direction: _OpenDirection
|
||||
width: int
|
||||
sort_by: Sequence[Sortby]
|
||||
time_format: str
|
||||
window_options: Mapping[str, Union[bool, str]]
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class _UserConfig:
|
||||
keymap: Mapping[str, AbstractSet[str]]
|
||||
options: _UserOptions
|
||||
idle_timeout: SupportsFloat
|
||||
ignore: Ignored
|
||||
view: _UserView
|
||||
theme: _UserTheme
|
||||
xdg: bool
|
||||
profiling: bool
|
||||
|
||||
|
||||
async def initial(specs: Iterable[RPCallable]) -> Settings:
|
||||
a_decode = new_decoder[Artifact](Artifact)
|
||||
c_decode = new_decoder[_UserConfig](_UserConfig)
|
||||
|
||||
win = await Window.get_current()
|
||||
artifacts = a_decode(safe_load(ARTIFACT.read_text("UTF-8")))
|
||||
|
||||
user_config = cast(
|
||||
Mapping[str, Any], await Nvim.vars.get(NoneType, SETTINGS_VAR) or {}
|
||||
)
|
||||
config = c_decode(
|
||||
merge(
|
||||
safe_load(CONFIG_YML.read_text("UTF-8")), hydrate(user_config), replace=True
|
||||
)
|
||||
)
|
||||
options, view, theme = config.options, config.view, config.theme
|
||||
|
||||
atomic = Atomic()
|
||||
for opt in view.window_options:
|
||||
atomic.win_get_option(win, opt)
|
||||
win_opts = cast(Sequence[Union[bool, str]], await atomic.commit(NoneType))
|
||||
win_actual_opts = {k: v for k, v in zip(view.window_options, win_opts)}
|
||||
|
||||
icons, hl_context = load_theme(
|
||||
artifact=artifacts,
|
||||
particular_mappings=theme.highlights,
|
||||
discrete_colours=theme.discrete_colour_map,
|
||||
icon_set=theme.icon_glyph_set,
|
||||
icon_colour_set=theme.icon_colour_set,
|
||||
text_colour_set=theme.text_colour_set,
|
||||
)
|
||||
|
||||
use_icons = theme.icon_glyph_set not in {
|
||||
IconGlyphSetEnum.ascii,
|
||||
IconGlyphSetEnum.ascii_hollow,
|
||||
}
|
||||
|
||||
view_opts = ViewOptions(
|
||||
hl_context=hl_context,
|
||||
icons=icons,
|
||||
sort_by=tuple(view.sort_by),
|
||||
use_icons=use_icons,
|
||||
time_fmt=view.time_format,
|
||||
)
|
||||
|
||||
keymap = {f"{NAMESPACE}.{k.capitalize()}": v for k, v in config.keymap.items()}
|
||||
legal_keys = {f"{NAMESPACE}.{spec.method.capitalize()}" for spec in specs}
|
||||
extra_keys = keymap.keys() - legal_keys
|
||||
|
||||
if extra_keys:
|
||||
raise DecodeError(
|
||||
path=(_UserOptions, sorted(legal_keys, key=strxfrm)),
|
||||
actual=None,
|
||||
missing_keys=(),
|
||||
extra_keys=sorted(extra_keys, key=strxfrm),
|
||||
)
|
||||
|
||||
else:
|
||||
settings = Settings(
|
||||
close_on_open=options.close_on_open,
|
||||
follow=options.follow,
|
||||
follow_links=options.follow_links,
|
||||
follow_ignore=options.follow_ignore,
|
||||
ignores=config.ignore,
|
||||
idle_timeout=float(config.idle_timeout),
|
||||
keymap=keymap,
|
||||
lang=options.lang,
|
||||
mime=options.mimetypes,
|
||||
min_diagnostics_severity=options.min_diagnostics_severity,
|
||||
open_left=view.open_direction is _OpenDirection.left,
|
||||
page_increment=options.page_increment,
|
||||
polling_rate=float(options.polling_rate),
|
||||
session=options.session,
|
||||
show_hidden=options.show_hidden,
|
||||
version_ctl=options.version_control,
|
||||
view=view_opts,
|
||||
width=view.width,
|
||||
win_actual_opts=win_actual_opts,
|
||||
win_local_opts=view.window_options,
|
||||
xdg=config.xdg,
|
||||
profiling=config.profiling,
|
||||
)
|
||||
|
||||
return settings
|
||||
@ -1,46 +0,0 @@
|
||||
from locale import getlocale
|
||||
from string import Template
|
||||
from typing import Mapping, MutableMapping, Optional, Union
|
||||
|
||||
from std2.pickle.decoder import new_decoder
|
||||
from yaml import safe_load
|
||||
|
||||
from ..consts import DEFAULT_LANG, LANG_ROOT
|
||||
|
||||
|
||||
def _get_lang(code: Optional[str], fallback: str) -> str:
|
||||
if code:
|
||||
return code.casefold()
|
||||
else:
|
||||
tag, _ = getlocale()
|
||||
tag = (tag or fallback).casefold()
|
||||
primary, _, _ = tag.partition("-")
|
||||
lang, _, _ = primary.partition("_")
|
||||
return lang
|
||||
|
||||
|
||||
class _Lang:
|
||||
def __init__(self, specs: MutableMapping[str, str]) -> None:
|
||||
self._specs = specs
|
||||
|
||||
def __call__(self, key: str, **kwds: Union[int, float, str]) -> str:
|
||||
spec = self._specs[key]
|
||||
return Template(spec).substitute(kwds)
|
||||
|
||||
|
||||
LANG = _Lang({})
|
||||
|
||||
|
||||
def init(code: Optional[str]) -> None:
|
||||
decode = new_decoder[Mapping[str, str]](Mapping[str, str])
|
||||
|
||||
lang = _get_lang(code, fallback=DEFAULT_LANG)
|
||||
lang_path = (LANG_ROOT / lang).with_suffix(".yml")
|
||||
yml_path = (
|
||||
lang_path
|
||||
if lang_path.exists()
|
||||
else (LANG_ROOT / DEFAULT_LANG).with_suffix(".yml")
|
||||
)
|
||||
|
||||
specs = decode(safe_load(yml_path.read_text("UTF-8")))
|
||||
LANG._specs.update(specs)
|
||||
@ -1,42 +0,0 @@
|
||||
from dataclasses import dataclass
|
||||
from typing import AbstractSet, Mapping, Optional, Union
|
||||
|
||||
from ..fs.types import Ignored
|
||||
from ..view.types import ViewOptions
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class VersionCtlOpts:
|
||||
enable: bool
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class MimetypeOptions:
|
||||
warn: AbstractSet[str]
|
||||
allow_exts: AbstractSet[str]
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Settings:
|
||||
close_on_open: bool
|
||||
follow: bool
|
||||
follow_links: bool
|
||||
follow_ignore: bool
|
||||
ignores: Ignored
|
||||
keymap: Mapping[str, AbstractSet[str]]
|
||||
lang: Optional[str]
|
||||
mime: MimetypeOptions
|
||||
open_left: bool
|
||||
page_increment: int
|
||||
polling_rate: float
|
||||
idle_timeout: float
|
||||
profiling: bool
|
||||
session: bool
|
||||
show_hidden: bool
|
||||
version_ctl: VersionCtlOpts
|
||||
view: ViewOptions
|
||||
width: int
|
||||
win_actual_opts: Mapping[str, Union[bool, str]]
|
||||
win_local_opts: Mapping[str, Union[bool, str]]
|
||||
min_diagnostics_severity: int
|
||||
xdg: bool
|
||||
@ -1,25 +0,0 @@
|
||||
from functools import cached_property
|
||||
|
||||
from ..timeit import timeit
|
||||
from ..view.render import render
|
||||
from ..view.types import Derived
|
||||
from .types import State
|
||||
|
||||
|
||||
class DeepState(State):
|
||||
@cached_property
|
||||
def derived(self) -> Derived:
|
||||
with timeit("render"):
|
||||
return render(
|
||||
self.root,
|
||||
settings=self.settings,
|
||||
index=self.index,
|
||||
selection=self.selection,
|
||||
filter_pattern=self.filter_pattern,
|
||||
markers=self.markers,
|
||||
diagnostics=self.diagnostics,
|
||||
vc=self.vc,
|
||||
follow_links=self.follow_links,
|
||||
show_hidden=self.show_hidden,
|
||||
current=self.current,
|
||||
)
|
||||
@ -1,56 +0,0 @@
|
||||
from asyncio import (
|
||||
AbstractEventLoop,
|
||||
get_running_loop,
|
||||
run,
|
||||
run_coroutine_threadsafe,
|
||||
wrap_future,
|
||||
)
|
||||
from concurrent.futures import Future, InvalidStateError, ThreadPoolExecutor
|
||||
from contextlib import suppress
|
||||
from threading import Thread
|
||||
from typing import Any, Awaitable, Callable, Coroutine, TypeVar
|
||||
|
||||
_T = TypeVar("_T")
|
||||
|
||||
|
||||
class AsyncExecutor:
|
||||
def __init__(self, threadpool: ThreadPoolExecutor) -> None:
|
||||
f: Future = Future()
|
||||
self._fut: Future = Future()
|
||||
|
||||
async def cont() -> None:
|
||||
loop = get_running_loop()
|
||||
if threadpool:
|
||||
loop.set_default_executor(threadpool)
|
||||
f.set_result(loop)
|
||||
main: Coroutine = await wrap_future(self._fut)
|
||||
await main
|
||||
|
||||
self._th = Thread(daemon=True, target=lambda: run(cont()))
|
||||
self._th.start()
|
||||
self.threadpool = threadpool
|
||||
self.loop: AbstractEventLoop = f.result()
|
||||
|
||||
def run(self, main: Awaitable[Any]) -> None:
|
||||
self._fut.set_result(main)
|
||||
|
||||
def fsubmit(self, f: Callable[..., Any], *args: Any, **kwargs: Any) -> Future:
|
||||
fut: Future = Future()
|
||||
|
||||
def cont() -> None:
|
||||
if fut.set_running_or_notify_cancel():
|
||||
try:
|
||||
ret = f(*args, **kwargs)
|
||||
except BaseException as e:
|
||||
with suppress(InvalidStateError):
|
||||
fut.set_exception(e)
|
||||
else:
|
||||
with suppress(InvalidStateError):
|
||||
fut.set_result(ret)
|
||||
|
||||
self.loop.call_soon_threadsafe(cont)
|
||||
return fut
|
||||
|
||||
def submit(self, co: Awaitable[_T]) -> Awaitable[_T]:
|
||||
f = run_coroutine_threadsafe(co, loop=self.loop)
|
||||
return wrap_future(f)
|
||||
@ -1,72 +0,0 @@
|
||||
from asyncio import gather
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
from pathlib import Path
|
||||
|
||||
from pynvim_pp.nvim import Nvim
|
||||
|
||||
from ..consts import SESSION_DIR
|
||||
from ..fs.cartographer import new
|
||||
from ..nvim.markers import markers
|
||||
from ..settings.types import Settings
|
||||
from ..version_ctl.types import VCStatus
|
||||
from .cache import DeepState
|
||||
from .executor import AsyncExecutor
|
||||
from .ops import load_session
|
||||
from .types import Selection, Session, State
|
||||
|
||||
|
||||
async def initial(settings: Settings, th: ThreadPoolExecutor) -> State:
|
||||
executor = AsyncExecutor(threadpool=th)
|
||||
cwd, marks = await gather(Nvim.getcwd(), markers())
|
||||
storage = (
|
||||
Path(await Nvim.fn.stdpath(str, "cache")) / "chad_sessions"
|
||||
if settings.xdg
|
||||
else SESSION_DIR
|
||||
)
|
||||
|
||||
session = Session(workdir=cwd, storage=storage)
|
||||
stored = await load_session(session) if settings.session else None
|
||||
index = {cwd} | (stored.index if stored else frozenset())
|
||||
|
||||
show_hidden = (
|
||||
stored.show_hidden
|
||||
if stored and stored.show_hidden is not None
|
||||
else settings.show_hidden
|
||||
)
|
||||
enable_vc = (
|
||||
stored.enable_vc
|
||||
if stored and stored.enable_vc is not None
|
||||
else settings.version_ctl.enable
|
||||
)
|
||||
|
||||
selection: Selection = frozenset()
|
||||
node = await new(
|
||||
executor, follow_links=settings.follow_links, root=cwd, index=index
|
||||
)
|
||||
vc = VCStatus()
|
||||
|
||||
current = None
|
||||
filter_pattern = None
|
||||
|
||||
state = DeepState(
|
||||
executor=executor,
|
||||
settings=settings,
|
||||
session=session,
|
||||
vim_focus=True,
|
||||
index=index,
|
||||
selection=selection,
|
||||
filter_pattern=filter_pattern,
|
||||
show_hidden=show_hidden,
|
||||
follow=settings.follow,
|
||||
follow_links=settings.follow_links,
|
||||
follow_ignore=settings.follow_ignore,
|
||||
enable_vc=enable_vc,
|
||||
width=settings.width,
|
||||
root=node,
|
||||
markers=marks,
|
||||
diagnostics={},
|
||||
vc=vc,
|
||||
current=current,
|
||||
window_order={},
|
||||
)
|
||||
return state
|
||||
@ -1,85 +0,0 @@
|
||||
from pathlib import PurePath
|
||||
from typing import AbstractSet, Mapping, Optional, Union, cast
|
||||
|
||||
from pynvim_pp.rpc_types import ExtData
|
||||
from std2.types import Void, VoidType, or_else
|
||||
|
||||
from ..fs.cartographer import update
|
||||
from ..fs.types import Node
|
||||
from ..nvim.types import Markers
|
||||
from ..version_ctl.types import VCStatus
|
||||
from .cache import DeepState
|
||||
from .types import Diagnostics, FilterPattern, Index, Selection, Session, State
|
||||
|
||||
|
||||
async def forward(
|
||||
state: State,
|
||||
*,
|
||||
root: Union[Node, VoidType] = Void,
|
||||
index: Union[Index, VoidType] = Void,
|
||||
selection: Union[Selection, VoidType] = Void,
|
||||
filter_pattern: Union[Optional[FilterPattern], VoidType] = Void,
|
||||
show_hidden: Union[bool, VoidType] = Void,
|
||||
follow: Union[bool, VoidType] = Void,
|
||||
follow_links: Union[bool, VoidType] = Void,
|
||||
follow_ignore: Union[bool, VoidType] = Void,
|
||||
enable_vc: Union[bool, VoidType] = Void,
|
||||
width: Union[int, VoidType] = Void,
|
||||
markers: Union[Markers, VoidType] = Void,
|
||||
diagnostics: Union[Diagnostics, VoidType] = Void,
|
||||
vc: Union[VCStatus, VoidType] = Void,
|
||||
current: Union[PurePath, VoidType] = Void,
|
||||
invalidate_dirs: Union[AbstractSet[PurePath], VoidType] = Void,
|
||||
window_order: Union[Mapping[ExtData, None], VoidType] = Void,
|
||||
session: Union[Session, VoidType] = Void,
|
||||
vim_focus: Union[bool, VoidType] = Void,
|
||||
trace: bool = True,
|
||||
) -> State:
|
||||
new_index = or_else(index, state.index)
|
||||
new_selection = or_else(selection, state.selection)
|
||||
new_filter_pattern = or_else(filter_pattern, state.filter_pattern)
|
||||
new_current = or_else(current, state.current)
|
||||
new_follow_links = or_else(follow_links, state.follow_links)
|
||||
new_root = cast(
|
||||
Node,
|
||||
root
|
||||
or (
|
||||
await update(
|
||||
state.executor,
|
||||
root=state.root,
|
||||
follow_links=new_follow_links,
|
||||
index=new_index,
|
||||
invalidate_dirs=invalidate_dirs,
|
||||
)
|
||||
if not isinstance(invalidate_dirs, VoidType)
|
||||
else state.root
|
||||
),
|
||||
)
|
||||
new_markers = or_else(markers, state.markers)
|
||||
new_vc = or_else(vc, state.vc)
|
||||
new_hidden = or_else(show_hidden, state.show_hidden)
|
||||
new_vim_focus = or_else(vim_focus, state.vim_focus)
|
||||
|
||||
new_state = DeepState(
|
||||
executor=state.executor,
|
||||
settings=state.settings,
|
||||
session=or_else(session, state.session),
|
||||
vim_focus=new_vim_focus,
|
||||
index=new_index,
|
||||
selection=new_selection,
|
||||
filter_pattern=new_filter_pattern,
|
||||
show_hidden=new_hidden,
|
||||
follow=or_else(follow, state.follow),
|
||||
follow_links=new_follow_links,
|
||||
follow_ignore=or_else(follow_ignore, state.follow_ignore),
|
||||
enable_vc=or_else(enable_vc, state.enable_vc),
|
||||
width=or_else(width, state.width),
|
||||
root=new_root,
|
||||
markers=new_markers,
|
||||
diagnostics=or_else(diagnostics, state.diagnostics),
|
||||
vc=new_vc,
|
||||
current=new_current,
|
||||
window_order=or_else(window_order, state.window_order),
|
||||
)
|
||||
|
||||
return new_state
|
||||
@ -1,69 +0,0 @@
|
||||
from hashlib import sha1
|
||||
from json import dumps, loads
|
||||
from os.path import normcase
|
||||
from pathlib import Path, PurePath
|
||||
from tempfile import NamedTemporaryFile
|
||||
from typing import Any, MutableMapping, Optional
|
||||
|
||||
from pynvim_pp.lib import decode, encode
|
||||
from std2.asyncio import to_thread
|
||||
from std2.pickle.decoder import new_decoder
|
||||
from std2.pickle.encoder import new_encoder
|
||||
|
||||
from .types import Session, State, StoredSession
|
||||
|
||||
_DECODER = new_decoder[StoredSession](StoredSession)
|
||||
_ENCODER = new_encoder[StoredSession](StoredSession)
|
||||
|
||||
|
||||
def _session_path(cwd: PurePath, storage: Path) -> Path:
|
||||
hashed = sha1(normcase(cwd).encode()).hexdigest()
|
||||
part = storage / hashed
|
||||
return part.with_suffix(".json")
|
||||
|
||||
|
||||
async def _load_json(path: Path) -> Optional[Any]:
|
||||
def cont() -> Optional[Any]:
|
||||
try:
|
||||
json = decode(path.read_bytes())
|
||||
except FileNotFoundError:
|
||||
return None
|
||||
else:
|
||||
return loads(json)
|
||||
|
||||
return await to_thread(cont)
|
||||
|
||||
|
||||
async def load_session(session: Session) -> StoredSession:
|
||||
load_path = _session_path(session.workdir, storage=session.storage)
|
||||
try:
|
||||
json = await _load_json(load_path)
|
||||
if isinstance(json, MutableMapping):
|
||||
json.pop("bookmarks", None)
|
||||
sessions = _DECODER(json)
|
||||
except Exception:
|
||||
return StoredSession(index=frozenset(), show_hidden=None, enable_vc=None)
|
||||
else:
|
||||
return sessions
|
||||
|
||||
|
||||
async def dump_session(state: State) -> None:
|
||||
stored = StoredSession(
|
||||
index=state.index,
|
||||
show_hidden=state.show_hidden,
|
||||
enable_vc=state.enable_vc,
|
||||
)
|
||||
|
||||
json = _ENCODER(stored)
|
||||
path = _session_path(state.session.workdir, storage=state.session.storage)
|
||||
parent = path.parent
|
||||
dumped = encode(dumps(json, ensure_ascii=False, check_circular=False, indent=2))
|
||||
|
||||
def cont() -> None:
|
||||
parent.mkdir(parents=True, exist_ok=True)
|
||||
with NamedTemporaryFile(dir=parent, delete=False) as f:
|
||||
f.write(dumped)
|
||||
|
||||
Path(f.name).replace(path)
|
||||
|
||||
await to_thread(cont)
|
||||
@ -1,63 +0,0 @@
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path, PurePath
|
||||
from typing import AbstractSet, Mapping, Optional
|
||||
|
||||
from pynvim_pp.rpc_types import ExtData
|
||||
|
||||
from ..fs.types import Node
|
||||
from ..nvim.types import Markers
|
||||
from ..settings.types import Settings
|
||||
from ..version_ctl.types import VCStatus
|
||||
from ..view.types import Derived
|
||||
from .executor import AsyncExecutor
|
||||
|
||||
Index = AbstractSet[PurePath]
|
||||
Selection = Index
|
||||
Diagnostics = Mapping[PurePath, Mapping[int, int]]
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class FilterPattern:
|
||||
pattern: str
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Session:
|
||||
workdir: PurePath
|
||||
storage: Path
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class State:
|
||||
executor: AsyncExecutor
|
||||
settings: Settings
|
||||
session: Session
|
||||
follow_links: bool
|
||||
follow_ignore: bool
|
||||
vim_focus: bool
|
||||
current: Optional[PurePath]
|
||||
enable_vc: bool
|
||||
filter_pattern: Optional[FilterPattern]
|
||||
follow: bool
|
||||
index: Index
|
||||
markers: Markers
|
||||
root: Node
|
||||
selection: Selection
|
||||
show_hidden: bool
|
||||
vc: VCStatus
|
||||
width: int
|
||||
diagnostics: Diagnostics
|
||||
window_order: Mapping[ExtData, None]
|
||||
|
||||
@property
|
||||
def derived(self) -> Derived:
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class StoredSession:
|
||||
# TODO: sync across sessions
|
||||
# pid: int
|
||||
index: Index
|
||||
show_hidden: Optional[bool]
|
||||
enable_vc: Optional[bool]
|
||||
@ -1,35 +0,0 @@
|
||||
from contextlib import contextmanager
|
||||
from typing import Any, Iterator, MutableMapping, Optional, Tuple
|
||||
|
||||
from pynvim_pp.logging import log
|
||||
from std2.locale import si_prefixed_smol
|
||||
from std2.timeit import timeit as _timeit
|
||||
|
||||
from .consts import DEBUG
|
||||
|
||||
_RECORDS: MutableMapping[str, Tuple[int, float]] = {}
|
||||
|
||||
|
||||
@contextmanager
|
||||
def timeit(
|
||||
name: str, *args: Any, force: bool = False, warn: Optional[float] = None
|
||||
) -> Iterator[None]:
|
||||
if DEBUG or force or warn is not None:
|
||||
with _timeit() as t:
|
||||
yield None
|
||||
delta = t().total_seconds()
|
||||
if DEBUG or force or delta >= (warn or 0):
|
||||
times, cum = _RECORDS.get(name, (0, 0))
|
||||
tt, c = times + 1, cum + delta
|
||||
_RECORDS[name] = tt, c
|
||||
|
||||
label = name.ljust(50)
|
||||
time = f"{si_prefixed_smol(delta, precision=0)}s".ljust(8)
|
||||
ttime = f"{si_prefixed_smol(c / tt, precision=0)}s".ljust(8)
|
||||
msg = f"TIME -- {label} :: {time} @ {ttime} {' '.join(map(str, args))}"
|
||||
if force:
|
||||
log.info("%s", msg)
|
||||
else:
|
||||
log.debug("%s", msg)
|
||||
else:
|
||||
yield None
|
||||
@ -1,199 +0,0 @@
|
||||
from asyncio import Task, create_task, sleep
|
||||
from collections.abc import Sequence
|
||||
from itertools import chain
|
||||
from typing import Optional
|
||||
|
||||
from pynvim_pp.buffer import Buffer
|
||||
from pynvim_pp.nvim import Nvim
|
||||
from pynvim_pp.rpc_types import NvimError
|
||||
from pynvim_pp.window import Window
|
||||
from std2.asyncio import cancel
|
||||
from std2.cell import RefCell
|
||||
|
||||
from ..consts import FM_FILETYPE, URI_SCHEME
|
||||
from ..fs.ops import ancestors, is_file
|
||||
from ..lsp.diagnostics import poll
|
||||
from ..nvim.markers import markers
|
||||
from ..registry import NAMESPACE, autocmd, rpc
|
||||
from ..settings.types import Settings
|
||||
from ..state.next import forward
|
||||
from ..state.ops import dump_session
|
||||
from ..state.types import State
|
||||
from .shared.current import new_current_file, new_root
|
||||
from .shared.wm import (
|
||||
find_current_buffer_path,
|
||||
find_fm_buffers,
|
||||
is_fm_buf_name,
|
||||
is_fm_buffer,
|
||||
restore_non_fm_win,
|
||||
setup_fm_buf,
|
||||
)
|
||||
from .types import Stage
|
||||
|
||||
_CELL = RefCell[Optional[Task]](None)
|
||||
|
||||
|
||||
async def _setup_fm_win(settings: Settings, win: Window) -> None:
|
||||
for key, val in settings.win_local_opts.items():
|
||||
await win.opts.set(key, val=val)
|
||||
|
||||
|
||||
async def setup(settings: Settings) -> None:
|
||||
async for buf in find_fm_buffers():
|
||||
await setup_fm_buf(settings, buf=buf)
|
||||
for win in await Window.list():
|
||||
buf = await win.get_buf()
|
||||
if await is_fm_buffer(buf):
|
||||
await _setup_fm_win(settings, win=win)
|
||||
|
||||
|
||||
@rpc(blocking=False)
|
||||
async def _when_idle(state: State) -> None:
|
||||
if task := _CELL.val:
|
||||
_CELL.val = None
|
||||
await cancel(task)
|
||||
|
||||
async def cont() -> None:
|
||||
await sleep(state.settings.idle_timeout)
|
||||
diagnostics = await poll(state.settings.min_diagnostics_severity)
|
||||
await forward(state, diagnostics=diagnostics)
|
||||
|
||||
_CELL.val = create_task(cont())
|
||||
|
||||
|
||||
_ = autocmd("CursorHold", "CursorHoldI") << f"lua {NAMESPACE}.{_when_idle.method}()"
|
||||
|
||||
|
||||
@rpc(blocking=False)
|
||||
async def save_session(state: State) -> None:
|
||||
"""
|
||||
Save CHADTree state
|
||||
"""
|
||||
|
||||
await dump_session(state)
|
||||
|
||||
|
||||
_ = autocmd("ExitPre") << f"lua {NAMESPACE}.{save_session.method}()"
|
||||
_ = (
|
||||
autocmd("User", modifiers=("CHADSave",))
|
||||
<< f"lua {NAMESPACE}.{save_session.method}()"
|
||||
)
|
||||
|
||||
|
||||
@rpc(blocking=False)
|
||||
async def focus_lost(state: State) -> Stage:
|
||||
"""
|
||||
Save CHADTree state
|
||||
"""
|
||||
|
||||
await dump_session(state)
|
||||
new_state = await forward(state, vim_focus=False)
|
||||
return Stage(new_state)
|
||||
|
||||
|
||||
_ = autocmd("FocusLost") << f"lua {NAMESPACE}.{focus_lost.method}()"
|
||||
|
||||
|
||||
@rpc(blocking=False)
|
||||
async def _focus_gained(state: State) -> Stage:
|
||||
""" """
|
||||
|
||||
new_state = await forward(state, vim_focus=True)
|
||||
return Stage(new_state)
|
||||
|
||||
|
||||
_ = autocmd("FocusGained") << f"lua {NAMESPACE}.{_focus_gained.method}()"
|
||||
|
||||
|
||||
@rpc(blocking=False)
|
||||
async def _record_win_pos(state: State) -> Stage:
|
||||
"""
|
||||
Record last windows
|
||||
"""
|
||||
|
||||
win = await Window.get_current()
|
||||
win_id = win.data
|
||||
|
||||
window_order = {
|
||||
wid: None
|
||||
for wid in chain(
|
||||
(wid for wid in state.window_order if wid != win_id), (win_id,)
|
||||
)
|
||||
}
|
||||
new_state = await forward(state, window_order=window_order)
|
||||
return Stage(new_state)
|
||||
|
||||
|
||||
_ = autocmd("WinEnter") << f"lua {NAMESPACE}.{_record_win_pos.method}()"
|
||||
|
||||
|
||||
@rpc(blocking=False)
|
||||
async def _changedir(state: State) -> Stage:
|
||||
"""
|
||||
Follow cwd update
|
||||
"""
|
||||
|
||||
cwd = await Nvim.getcwd()
|
||||
new_state = await new_root(state, new_cwd=cwd, indices=frozenset())
|
||||
return Stage(new_state)
|
||||
|
||||
|
||||
_ = autocmd("DirChanged") << f"lua {NAMESPACE}.{_changedir.method}()"
|
||||
|
||||
|
||||
@rpc(blocking=False)
|
||||
async def _restore(state: State, args: Sequence[str]) -> None:
|
||||
win = await Window.get_current()
|
||||
await restore_non_fm_win(state.settings.win_actual_opts, win=win)
|
||||
|
||||
|
||||
@rpc(blocking=False)
|
||||
async def _update_follow(state: State) -> Optional[Stage]:
|
||||
"""
|
||||
Follow buffer
|
||||
"""
|
||||
|
||||
win = await Window.get_current()
|
||||
buf = await Buffer.get_current()
|
||||
name = await buf.get_name()
|
||||
is_fm_win = await win.vars.get(bool, URI_SCHEME)
|
||||
is_fm_buf = await buf.filetype() == FM_FILETYPE
|
||||
is_fm_uri = name and is_fm_buf_name(name)
|
||||
|
||||
if is_fm_win and not is_fm_buf:
|
||||
await restore_non_fm_win(state.settings.win_actual_opts, win=win)
|
||||
|
||||
if is_fm_uri or is_fm_buf and not is_fm_win:
|
||||
await _setup_fm_win(state.settings, win=win)
|
||||
|
||||
if is_fm_uri and not is_fm_buf:
|
||||
await setup_fm_buf(state.settings, buf=buf)
|
||||
|
||||
try:
|
||||
if (current := await find_current_buffer_path(name)) and await is_file(current):
|
||||
if state.vc.ignored & {current, *ancestors(current)}:
|
||||
return None
|
||||
else:
|
||||
stage = await new_current_file(state, current=current)
|
||||
return stage
|
||||
else:
|
||||
return None
|
||||
except NvimError:
|
||||
return None
|
||||
|
||||
|
||||
_ = autocmd("BufEnter") << f"lua {NAMESPACE}.{_update_follow.method}()"
|
||||
|
||||
|
||||
@rpc(blocking=False)
|
||||
async def _update_markers(state: State) -> Stage:
|
||||
"""
|
||||
Update markers
|
||||
"""
|
||||
|
||||
mks = await markers()
|
||||
new_state = await forward(state, markers=mks)
|
||||
return Stage(new_state)
|
||||
|
||||
|
||||
_ = autocmd("QuickfixCmdPost") << f"lua {NAMESPACE}.{_update_markers.method}()"
|
||||
@ -1,108 +0,0 @@
|
||||
from typing import Optional
|
||||
|
||||
from pynvim_pp.nvim import Nvim
|
||||
from std2 import anext
|
||||
|
||||
from ..fs.cartographer import is_dir
|
||||
from ..fs.types import Mode
|
||||
from ..registry import rpc
|
||||
from ..settings.localization import LANG
|
||||
from ..state.next import forward
|
||||
from ..state.types import State
|
||||
from .shared.index import indices
|
||||
from .shared.open_file import open_file
|
||||
from .shared.wm import find_fm_windows
|
||||
from .types import ClickType, Stage
|
||||
|
||||
|
||||
async def _click(
|
||||
state: State, is_visual: bool, click_type: ClickType
|
||||
) -> Optional[Stage]:
|
||||
node = await anext(indices(state, is_visual=is_visual), None)
|
||||
|
||||
if not node:
|
||||
return None
|
||||
else:
|
||||
if Mode.orphan_link in node.mode:
|
||||
await Nvim.write(LANG("dead_link", name=node.path.name), error=True)
|
||||
return None
|
||||
else:
|
||||
if is_dir(node):
|
||||
if node.path == state.root.path:
|
||||
return None
|
||||
elif node.pointed and not state.follow_links:
|
||||
return None
|
||||
elif state.filter_pattern:
|
||||
await Nvim.write(LANG("filter_click"))
|
||||
return None
|
||||
else:
|
||||
index = state.index ^ {node.path}
|
||||
invalidate_dirs = {node.path}
|
||||
new_state = await forward(
|
||||
state,
|
||||
index=index,
|
||||
invalidate_dirs=invalidate_dirs,
|
||||
)
|
||||
return Stage(new_state)
|
||||
else:
|
||||
nxt = await open_file(
|
||||
state,
|
||||
path=node.path,
|
||||
click_type=click_type,
|
||||
)
|
||||
|
||||
if state.settings.close_on_open and click_type != ClickType.secondary:
|
||||
async for win, _ in find_fm_windows():
|
||||
await win.close()
|
||||
|
||||
return nxt
|
||||
|
||||
|
||||
@rpc(blocking=False)
|
||||
async def _primary(state: State, is_visual: bool) -> Optional[Stage]:
|
||||
"""
|
||||
Folders -> toggle
|
||||
File -> open
|
||||
"""
|
||||
|
||||
return await _click(state, is_visual=is_visual, click_type=ClickType.primary)
|
||||
|
||||
|
||||
@rpc(blocking=False)
|
||||
async def _secondary(state: State, is_visual: bool) -> Optional[Stage]:
|
||||
"""
|
||||
Folders -> toggle
|
||||
File -> preview
|
||||
"""
|
||||
|
||||
return await _click(state, is_visual=is_visual, click_type=ClickType.secondary)
|
||||
|
||||
|
||||
@rpc(blocking=False)
|
||||
async def _tertiary(state: State, is_visual: bool) -> Optional[Stage]:
|
||||
"""
|
||||
Folders -> toggle
|
||||
File -> open in new tab
|
||||
"""
|
||||
|
||||
return await _click(state, is_visual=is_visual, click_type=ClickType.tertiary)
|
||||
|
||||
|
||||
@rpc(blocking=False)
|
||||
async def _v_split(state: State, is_visual: bool) -> Optional[Stage]:
|
||||
"""
|
||||
Folders -> toggle
|
||||
File -> open in vertical split
|
||||
"""
|
||||
|
||||
return await _click(state, is_visual=is_visual, click_type=ClickType.v_split)
|
||||
|
||||
|
||||
@rpc(blocking=False)
|
||||
async def _h_split(state: State, is_visual: bool) -> Optional[Stage]:
|
||||
"""
|
||||
Folders -> toggle
|
||||
File -> open in horizontal split
|
||||
"""
|
||||
|
||||
return await _click(state, is_visual=is_visual, click_type=ClickType.h_split)
|
||||
@ -1,38 +0,0 @@
|
||||
from typing import Optional
|
||||
|
||||
from std2 import anext
|
||||
|
||||
from ..fs.cartographer import act_like_dir
|
||||
from ..fs.ops import ancestors
|
||||
from ..registry import rpc
|
||||
from ..state.next import forward
|
||||
from ..state.types import State
|
||||
from .shared.index import indices
|
||||
from .types import Stage
|
||||
|
||||
|
||||
@rpc(blocking=False)
|
||||
async def _collapse(state: State, is_visual: bool) -> Optional[Stage]:
|
||||
"""
|
||||
Collapse folder
|
||||
"""
|
||||
|
||||
node = await anext(indices(state, is_visual=is_visual), None)
|
||||
if not node:
|
||||
return None
|
||||
else:
|
||||
if act_like_dir(node, follow_links=state.follow_links):
|
||||
path = node.path if node.path in state.index else node.path.parent
|
||||
else:
|
||||
path = node.path.parent
|
||||
|
||||
paths = {
|
||||
indexed
|
||||
for indexed in state.index
|
||||
if path in (ancestors(indexed) | {indexed})
|
||||
}
|
||||
|
||||
index = (state.index - paths) | {state.root.path}
|
||||
invalidate_dirs = {path}
|
||||
new_state = await forward(state, index=index, invalidate_dirs=invalidate_dirs)
|
||||
return Stage(new_state, focus=path)
|
||||
@ -1,75 +0,0 @@
|
||||
from locale import strxfrm
|
||||
from os import linesep
|
||||
from os.path import normpath, sep
|
||||
from pathlib import PurePath
|
||||
from typing import AsyncIterator, Callable
|
||||
|
||||
from pynvim_pp.nvim import Nvim
|
||||
from pynvim_pp.types import NoneType
|
||||
|
||||
from ..fs.cartographer import is_dir
|
||||
from ..fs.ops import is_dir as iis_dir
|
||||
from ..registry import rpc
|
||||
from ..settings.localization import LANG
|
||||
from ..state.types import State
|
||||
from .shared.index import indices
|
||||
|
||||
|
||||
async def _cn(state: State, is_visual: bool, proc: Callable[[PurePath], str]) -> None:
|
||||
async def gen_paths() -> AsyncIterator[str]:
|
||||
if selection := state.selection:
|
||||
for path in selection:
|
||||
suffix = sep if await iis_dir(path) else ""
|
||||
yield proc(path) + suffix
|
||||
else:
|
||||
nodes = indices(state, is_visual=is_visual)
|
||||
async for node in nodes:
|
||||
suffix = sep if is_dir(node) else ""
|
||||
yield proc(node.path) + suffix
|
||||
|
||||
paths = sorted([path async for path in gen_paths()], key=strxfrm)
|
||||
clip = linesep.join(paths)
|
||||
copied_paths = ", ".join(paths)
|
||||
|
||||
await Nvim.fn.setreg(NoneType, "+", clip)
|
||||
await Nvim.fn.setreg(NoneType, "*", clip)
|
||||
await Nvim.write(LANG("copy_paths", copied_paths=copied_paths))
|
||||
|
||||
|
||||
@rpc(blocking=False)
|
||||
async def _copy_name(state: State, is_visual: bool) -> None:
|
||||
"""
|
||||
Copy dirname / filename
|
||||
"""
|
||||
|
||||
await _cn(
|
||||
state,
|
||||
is_visual=is_visual,
|
||||
proc=lambda p: normpath(p.name),
|
||||
)
|
||||
|
||||
|
||||
@rpc(blocking=False)
|
||||
async def _copy_basename(state: State, is_visual: bool) -> None:
|
||||
"""
|
||||
Copy basename of dirname / filename
|
||||
"""
|
||||
|
||||
await _cn(
|
||||
state,
|
||||
is_visual=is_visual,
|
||||
proc=normpath,
|
||||
)
|
||||
|
||||
|
||||
@rpc(blocking=False)
|
||||
async def _copy_relname(state: State, is_visual: bool) -> None:
|
||||
"""
|
||||
Copy relname of dirname / filename
|
||||
"""
|
||||
|
||||
await _cn(
|
||||
state,
|
||||
is_visual=is_visual,
|
||||
proc=lambda p: normpath(p.relative_to(state.root.path)),
|
||||
)
|
||||
@ -1,171 +0,0 @@
|
||||
from itertools import chain
|
||||
from os import linesep
|
||||
from pathlib import PurePath
|
||||
from typing import AbstractSet, Awaitable, Callable, Mapping, MutableMapping, Optional
|
||||
|
||||
from pynvim_pp.nvim import Nvim
|
||||
from std2 import anext
|
||||
from std2.locale import pathsort_key
|
||||
|
||||
from ..fs.cartographer import act_like_dir
|
||||
from ..fs.ops import ancestors, copy, cut, exists, unify_ancestors
|
||||
from ..fs.types import Node
|
||||
from ..lsp.notify import lsp_created, lsp_moved
|
||||
from ..registry import rpc
|
||||
from ..settings.localization import LANG
|
||||
from ..state.next import forward
|
||||
from ..state.types import State
|
||||
from ..view.ops import display_path
|
||||
from .shared.index import indices
|
||||
from .shared.refresh import refresh
|
||||
from .shared.wm import kill_buffers
|
||||
from .types import Stage
|
||||
|
||||
|
||||
def _find_dest(src: PurePath, node: Node, follow_links: bool) -> PurePath:
|
||||
parent = (
|
||||
node.path if act_like_dir(node, follow_links=follow_links) else node.path.parent
|
||||
)
|
||||
dst = parent / src.name
|
||||
return dst
|
||||
|
||||
|
||||
async def _operation(
|
||||
*,
|
||||
state: State,
|
||||
is_visual: bool,
|
||||
nono: AbstractSet[PurePath],
|
||||
op_name: str,
|
||||
is_move: bool,
|
||||
action: Callable[[Mapping[PurePath, PurePath]], Awaitable[None]],
|
||||
) -> Optional[Stage]:
|
||||
node = await anext(indices(state, is_visual=is_visual), None)
|
||||
selection = state.selection
|
||||
unified = unify_ancestors(selection)
|
||||
|
||||
if not unified or not node:
|
||||
await Nvim.write(LANG("nothing_select"), error=True)
|
||||
return None
|
||||
elif not unified.isdisjoint(nono):
|
||||
await Nvim.write(LANG("operation not permitted on root"), error=True)
|
||||
return None
|
||||
else:
|
||||
pre_operations = {
|
||||
src: _find_dest(src, node=node, follow_links=state.follow_links)
|
||||
for src in unified
|
||||
}
|
||||
pre_existing = {
|
||||
s: d for s, d in pre_operations.items() if await exists(d, follow=False)
|
||||
}
|
||||
|
||||
new_operations: MutableMapping[PurePath, PurePath] = {}
|
||||
while pre_existing:
|
||||
source, dest = pre_existing.popitem()
|
||||
resp = await Nvim.input(question=LANG("path_exists_err"), default=dest.name)
|
||||
new_dest = dest.parent / resp if resp else None
|
||||
|
||||
if not new_dest:
|
||||
pre_existing[source] = dest
|
||||
break
|
||||
elif await exists(new_dest, follow=False):
|
||||
pre_existing[source] = new_dest
|
||||
else:
|
||||
new_operations[source] = new_dest
|
||||
|
||||
if pre_existing:
|
||||
msg = linesep.join(
|
||||
f"{display_path(s, state=state)} -> {display_path(d, state=state)}"
|
||||
for s, d in sorted(
|
||||
pre_existing.items(), key=lambda t: pathsort_key(t[0])
|
||||
)
|
||||
)
|
||||
await Nvim.write(
|
||||
LANG("paths already exist", operation=op_name, paths=msg),
|
||||
error=True,
|
||||
)
|
||||
return None
|
||||
|
||||
else:
|
||||
operations = {**pre_operations, **new_operations}
|
||||
msg = linesep.join(
|
||||
f"{display_path(s, state=state)} -> {display_path(d, state=state)}"
|
||||
for s, d in sorted(operations.items(), key=lambda t: pathsort_key(t[0]))
|
||||
)
|
||||
|
||||
question = LANG("confirm op", operation=op_name, paths=msg)
|
||||
ans = await Nvim.confirm(
|
||||
question=question,
|
||||
answers=LANG("ask_yesno"),
|
||||
answer_key={1: True, 2: False},
|
||||
)
|
||||
|
||||
if not ans:
|
||||
return None
|
||||
else:
|
||||
try:
|
||||
await action(operations)
|
||||
except Exception as e:
|
||||
await Nvim.write(e, error=True)
|
||||
return await refresh(state)
|
||||
else:
|
||||
parents = {
|
||||
p.parent for p in chain(operations.keys(), operations.values())
|
||||
}
|
||||
invalidate_dirs = parents
|
||||
index = state.index | parents
|
||||
new_selection = {*operations.values()}
|
||||
new_state = await forward(
|
||||
state,
|
||||
index=index,
|
||||
selection=new_selection if is_move else selection,
|
||||
invalidate_dirs=invalidate_dirs,
|
||||
)
|
||||
focus = next(
|
||||
iter(sorted(new_selection, key=pathsort_key)),
|
||||
None,
|
||||
)
|
||||
|
||||
if is_move:
|
||||
await kill_buffers(
|
||||
last_used=new_state.window_order,
|
||||
paths=selection,
|
||||
reopen={},
|
||||
)
|
||||
await lsp_moved(operations)
|
||||
else:
|
||||
await lsp_created(new_selection)
|
||||
return Stage(new_state, focus=focus)
|
||||
|
||||
|
||||
@rpc(blocking=False)
|
||||
async def _cut(state: State, is_visual: bool) -> Optional[Stage]:
|
||||
"""
|
||||
Cut selected
|
||||
"""
|
||||
|
||||
cwd, root = await Nvim.getcwd(), state.root.path
|
||||
nono = {cwd, root} | ancestors(cwd, root)
|
||||
return await _operation(
|
||||
state=state,
|
||||
is_visual=is_visual,
|
||||
nono=nono,
|
||||
op_name=LANG("cut"),
|
||||
action=cut,
|
||||
is_move=True,
|
||||
)
|
||||
|
||||
|
||||
@rpc(blocking=False)
|
||||
async def _copy(state: State, is_visual: bool) -> Optional[Stage]:
|
||||
"""
|
||||
Copy selected
|
||||
"""
|
||||
|
||||
return await _operation(
|
||||
state=state,
|
||||
is_visual=is_visual,
|
||||
nono=frozenset(),
|
||||
op_name=LANG("copy"),
|
||||
action=copy,
|
||||
is_move=False,
|
||||
)
|
||||
@ -1,102 +0,0 @@
|
||||
from locale import strxfrm
|
||||
from os import linesep
|
||||
from pathlib import PurePath
|
||||
from subprocess import CalledProcessError
|
||||
from typing import Awaitable, Callable, Iterable, Optional
|
||||
|
||||
from pynvim_pp.nvim import Nvim
|
||||
from std2.asyncio.subprocess import call
|
||||
|
||||
from ..fs.ops import ancestors, remove, unify_ancestors, which
|
||||
from ..lsp.notify import lsp_removed
|
||||
from ..registry import rpc
|
||||
from ..settings.localization import LANG
|
||||
from ..state.next import forward
|
||||
from ..state.types import State
|
||||
from ..view.ops import display_path
|
||||
from .shared.index import indices
|
||||
from .shared.refresh import refresh
|
||||
from .shared.wm import kill_buffers
|
||||
from .types import Stage
|
||||
|
||||
|
||||
async def _remove(
|
||||
state: State,
|
||||
is_visual: bool,
|
||||
yeet: Callable[[Iterable[PurePath]], Awaitable[None]],
|
||||
) -> Optional[Stage]:
|
||||
cwd, root = await Nvim.getcwd(), state.root.path
|
||||
nono = {cwd, root} | ancestors(cwd, root)
|
||||
|
||||
selection = state.selection or {
|
||||
node.path async for node in indices(state, is_visual=is_visual)
|
||||
}
|
||||
unified = unify_ancestors(selection)
|
||||
|
||||
if not unified:
|
||||
return None
|
||||
elif not unified.isdisjoint(nono):
|
||||
await Nvim.write(LANG("operation not permitted on root"), error=True)
|
||||
return None
|
||||
else:
|
||||
display_paths = linesep.join(
|
||||
sorted((display_path(path, state=state) for path in unified), key=strxfrm)
|
||||
)
|
||||
|
||||
question = LANG("ask_trash", display_paths=display_paths)
|
||||
ans = await Nvim.confirm(
|
||||
question=question,
|
||||
answers=LANG("ask_yesno"),
|
||||
answer_key={1: True, 2: False},
|
||||
)
|
||||
|
||||
if not ans:
|
||||
return None
|
||||
else:
|
||||
try:
|
||||
await yeet(unified)
|
||||
except Exception as e:
|
||||
await Nvim.write(e, error=True)
|
||||
return await refresh(state)
|
||||
else:
|
||||
invalidate_dirs = {path.parent for path in unified}
|
||||
new_state = await forward(
|
||||
state, selection=frozenset(), invalidate_dirs=invalidate_dirs
|
||||
)
|
||||
|
||||
await kill_buffers(
|
||||
last_used=new_state.window_order, paths=selection, reopen={}
|
||||
)
|
||||
await lsp_removed(unified)
|
||||
return Stage(new_state)
|
||||
|
||||
|
||||
@rpc(blocking=False)
|
||||
async def _delete(state: State, is_visual: bool) -> Optional[Stage]:
|
||||
"""
|
||||
Delete selected
|
||||
"""
|
||||
|
||||
return await _remove(state, is_visual=is_visual, yeet=remove)
|
||||
|
||||
|
||||
async def _sys_trash(paths: Iterable[PurePath]) -> None:
|
||||
cwd = await Nvim.getcwd()
|
||||
|
||||
if arg0 := which("trash"):
|
||||
try:
|
||||
await call(arg0, "--", *map(str, paths), cwd=cwd)
|
||||
except CalledProcessError as e:
|
||||
await Nvim.write(e, e.stderr, e.stdout, error=True)
|
||||
|
||||
else:
|
||||
await Nvim.write(LANG("sys_trash_err"), error=True)
|
||||
|
||||
|
||||
@rpc(blocking=False)
|
||||
async def _trash(state: State, is_visual: bool) -> Optional[Stage]:
|
||||
"""
|
||||
Delete selected
|
||||
"""
|
||||
|
||||
return await _remove(state, is_visual=is_visual, yeet=_sys_trash)
|
||||
@ -1,48 +0,0 @@
|
||||
from typing import Optional
|
||||
|
||||
from pynvim_pp.nvim import Nvim
|
||||
from std2 import anext
|
||||
|
||||
from ..registry import rpc
|
||||
from ..settings.localization import LANG
|
||||
from ..state.next import forward
|
||||
from ..state.types import FilterPattern, Selection, State
|
||||
from .shared.index import indices
|
||||
from .types import Stage
|
||||
|
||||
|
||||
@rpc(blocking=False)
|
||||
async def _clear_filter(state: State, is_visual: bool) -> Optional[Stage]:
|
||||
"""
|
||||
Clear filter
|
||||
"""
|
||||
|
||||
node = await anext(indices(state, is_visual=is_visual), None)
|
||||
if not node:
|
||||
return None
|
||||
else:
|
||||
focus = node.path
|
||||
new_state = await forward(state, filter_pattern=None)
|
||||
return Stage(new_state, focus=focus)
|
||||
|
||||
|
||||
@rpc(blocking=False)
|
||||
async def _filter(state: State, is_visual: bool) -> Optional[Stage]:
|
||||
"""
|
||||
Update filter
|
||||
"""
|
||||
|
||||
node = await anext(indices(state, is_visual=is_visual), None)
|
||||
if not node:
|
||||
return None
|
||||
else:
|
||||
focus = node.path
|
||||
old_p = state.filter_pattern.pattern if state.filter_pattern else ""
|
||||
pattern = await Nvim.input(question=LANG("new_filter"), default=old_p)
|
||||
|
||||
filter_pattern = FilterPattern(pattern=pattern) if pattern else None
|
||||
selection: Selection = state.selection if filter_pattern else frozenset()
|
||||
new_state = await forward(
|
||||
state, selection=selection, filter_pattern=filter_pattern
|
||||
)
|
||||
return Stage(new_state, focus=focus)
|
||||
@ -1,105 +0,0 @@
|
||||
from os.path import normcase, normpath
|
||||
from pathlib import PurePath
|
||||
from typing import Optional
|
||||
|
||||
from pynvim_pp.nvim import Nvim
|
||||
from std2 import anext
|
||||
|
||||
from ..fs.cartographer import act_like_dir
|
||||
from ..registry import rpc
|
||||
from ..settings.localization import LANG
|
||||
from ..state.types import State
|
||||
from .shared.current import maybe_path_above, new_current_file, new_root
|
||||
from .shared.index import indices
|
||||
from .types import Stage
|
||||
|
||||
|
||||
async def _jump(state: State, path: PurePath) -> Optional[Stage]:
|
||||
if new_state := await maybe_path_above(state, paths={path}):
|
||||
return Stage(new_state, focus=path)
|
||||
elif stage := await new_current_file(state, current=path):
|
||||
return Stage(stage.state, focus=path)
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
@rpc(blocking=False)
|
||||
async def _jump_to_current(state: State, is_visual: bool) -> Optional[Stage]:
|
||||
"""
|
||||
Jump to active file
|
||||
"""
|
||||
|
||||
if not (curr := state.current):
|
||||
return None
|
||||
else:
|
||||
return await _jump(state, path=curr)
|
||||
|
||||
|
||||
@rpc(blocking=False)
|
||||
async def _refocus(state: State, is_visual: bool) -> Stage:
|
||||
"""
|
||||
Follow cwd update
|
||||
"""
|
||||
|
||||
cwd = await Nvim.getcwd()
|
||||
new_state = await new_root(state, new_cwd=cwd, indices=frozenset())
|
||||
focus = new_state.root.path
|
||||
return Stage(new_state, focus=focus)
|
||||
|
||||
|
||||
@rpc(blocking=False)
|
||||
async def _change_dir(state: State, is_visual: bool) -> Optional[Stage]:
|
||||
"""
|
||||
Change root directory
|
||||
"""
|
||||
|
||||
node = await anext(indices(state, is_visual=is_visual), None)
|
||||
if not node:
|
||||
return None
|
||||
else:
|
||||
cwd = (
|
||||
node.path
|
||||
if act_like_dir(node, follow_links=state.follow_links)
|
||||
else node.path.parent
|
||||
)
|
||||
new_state = await new_root(state, new_cwd=cwd, indices=frozenset())
|
||||
escaped = await Nvim.fn.fnameescape(str, normcase(new_state.root.path))
|
||||
await Nvim.exec(f"chdir {escaped}")
|
||||
await Nvim.write(LANG("new cwd", cwd=normpath(new_state.root.path)))
|
||||
return Stage(new_state, focus=new_state.root.path)
|
||||
|
||||
|
||||
@rpc(blocking=False)
|
||||
async def _change_focus(state: State, is_visual: bool) -> Optional[Stage]:
|
||||
"""
|
||||
Refocus root directory
|
||||
"""
|
||||
|
||||
node = await anext(indices(state, is_visual=is_visual), None)
|
||||
if not node:
|
||||
return None
|
||||
else:
|
||||
new_base = (
|
||||
node.path
|
||||
if act_like_dir(node, follow_links=state.follow_links)
|
||||
else node.path.parent
|
||||
)
|
||||
new_state = await new_root(state, new_cwd=new_base, indices=frozenset())
|
||||
focus = node.path
|
||||
return Stage(new_state, focus=focus)
|
||||
|
||||
|
||||
@rpc(blocking=False)
|
||||
async def _change_focus_up(state: State, is_visual: bool) -> Optional[Stage]:
|
||||
"""
|
||||
Refocus root directory up
|
||||
"""
|
||||
|
||||
node = await anext(indices(state, is_visual=is_visual), None)
|
||||
if not node:
|
||||
return None
|
||||
else:
|
||||
new_state = await new_root(
|
||||
state, new_cwd=state.root.path.parent, indices=frozenset()
|
||||
)
|
||||
return Stage(new_state, focus=node.path)
|
||||
@ -1,95 +0,0 @@
|
||||
from enum import Enum, auto
|
||||
from pathlib import Path
|
||||
from typing import Sequence, Tuple
|
||||
from uuid import uuid4
|
||||
from webbrowser import open as open_w
|
||||
|
||||
from pynvim_pp.buffer import Buffer
|
||||
from pynvim_pp.float_win import list_floatwins, open_float_win
|
||||
from pynvim_pp.nvim import Nvim
|
||||
from std2.argparse import ArgparseError, ArgParser
|
||||
from std2.types import never
|
||||
|
||||
from ..consts import (
|
||||
CONFIGURATION_MD,
|
||||
CONFIGURATION_URI,
|
||||
FEATURES_MD,
|
||||
FEATURES_URI,
|
||||
KEYBIND_MD,
|
||||
KEYBIND_URI,
|
||||
MIGRATION_MD,
|
||||
MIGRATION_URI,
|
||||
README_MD,
|
||||
README_URI,
|
||||
THEME_MD,
|
||||
THEME_URI,
|
||||
)
|
||||
from ..registry import rpc
|
||||
from ..state.types import State
|
||||
|
||||
_NS = uuid4()
|
||||
|
||||
|
||||
class _Topics(Enum):
|
||||
index = auto()
|
||||
features = auto()
|
||||
keybind = auto()
|
||||
config = auto()
|
||||
theme = auto()
|
||||
migration = auto()
|
||||
|
||||
|
||||
def _directory(topic: _Topics) -> Tuple[Path, str]:
|
||||
if topic is _Topics.index:
|
||||
return README_MD, README_URI
|
||||
elif topic is _Topics.features:
|
||||
return FEATURES_MD, FEATURES_URI
|
||||
elif topic is _Topics.keybind:
|
||||
return KEYBIND_MD, KEYBIND_URI
|
||||
elif topic is _Topics.config:
|
||||
return CONFIGURATION_MD, CONFIGURATION_URI
|
||||
elif topic is _Topics.theme:
|
||||
return THEME_MD, THEME_URI
|
||||
elif topic is _Topics.migration:
|
||||
return MIGRATION_MD, MIGRATION_URI
|
||||
else:
|
||||
never(topic)
|
||||
|
||||
|
||||
def _parse_args(args: Sequence[str]) -> Tuple[_Topics, bool]:
|
||||
parser = ArgParser()
|
||||
parser.add_argument(
|
||||
"topic",
|
||||
nargs="?",
|
||||
choices=tuple(topic.name for topic in _Topics),
|
||||
default=_Topics.index.name,
|
||||
)
|
||||
parser.add_argument("-w", "--web", action="store_true", default=False)
|
||||
ns = parser.parse_args(args)
|
||||
return _Topics[ns.topic], ns.web
|
||||
|
||||
|
||||
@rpc(blocking=False)
|
||||
async def _help(state: State, args: Sequence[str]) -> None:
|
||||
"""
|
||||
Open help doc
|
||||
"""
|
||||
|
||||
try:
|
||||
topic, use_web = _parse_args(args)
|
||||
except ArgparseError as e:
|
||||
await Nvim.write(e, error=True)
|
||||
else:
|
||||
md, uri = _directory(topic)
|
||||
web_d = open_w(uri) if use_web else False
|
||||
if not web_d:
|
||||
async for win in list_floatwins(_NS):
|
||||
await win.close()
|
||||
lines = md.read_text("UTF-8").splitlines()
|
||||
buf = await Buffer.create(
|
||||
listed=False, scratch=True, wipe=True, nofile=True, noswap=True
|
||||
)
|
||||
await buf.set_lines(lines=lines)
|
||||
await buf.opts.set("modifiable", val=False)
|
||||
await buf.opts.set("syntax", val="markdown")
|
||||
await open_float_win(_NS, margin=0, relsize=0.95, buf=buf, border="rounded")
|
||||
@ -1,79 +0,0 @@
|
||||
from os.path import normpath, relpath
|
||||
from pathlib import PurePath
|
||||
from typing import MutableMapping, Optional
|
||||
|
||||
from pynvim_pp.nvim import Nvim
|
||||
from std2 import anext
|
||||
from std2.locale import pathsort_key
|
||||
|
||||
from ..fs.cartographer import act_like_dir
|
||||
from ..fs.ops import ancestors, exists, link, resolve
|
||||
from ..lsp.notify import lsp_created
|
||||
from ..registry import rpc
|
||||
from ..settings.localization import LANG
|
||||
from ..state.next import forward
|
||||
from ..state.types import State
|
||||
from ..view.ops import display_path
|
||||
from .shared.current import maybe_path_above
|
||||
from .shared.index import indices
|
||||
from .shared.refresh import refresh
|
||||
from .types import Stage
|
||||
|
||||
|
||||
@rpc(blocking=False)
|
||||
async def _link(state: State, is_visual: bool) -> Optional[Stage]:
|
||||
"""
|
||||
Symlink selected
|
||||
"""
|
||||
|
||||
node = await anext(indices(state, is_visual=is_visual), None)
|
||||
if node is None:
|
||||
return None
|
||||
else:
|
||||
parent = (
|
||||
node.path
|
||||
if act_like_dir(node, follow_links=state.follow_links)
|
||||
else node.path.parent
|
||||
)
|
||||
selection = state.selection or {node.path}
|
||||
operations: MutableMapping[PurePath, PurePath] = {}
|
||||
for selected in selection:
|
||||
display = display_path(selected, state=state)
|
||||
if child := await Nvim.input(
|
||||
question=LANG("link", src=display), default=""
|
||||
):
|
||||
try:
|
||||
dst = await resolve(parent / child, strict=False)
|
||||
except Exception as e:
|
||||
await Nvim.write(e, error=True)
|
||||
return None
|
||||
else:
|
||||
if dst in operations or await exists(dst, follow=False):
|
||||
await Nvim.write(
|
||||
LANG("already_exists", name=normpath(dst)), error=True
|
||||
)
|
||||
return None
|
||||
else:
|
||||
src = PurePath(relpath(selected, start=dst.parent))
|
||||
operations[dst] = src
|
||||
else:
|
||||
return None
|
||||
|
||||
try:
|
||||
await link(operations)
|
||||
except Exception as e:
|
||||
await Nvim.write(e, error=True)
|
||||
return await refresh(state)
|
||||
else:
|
||||
paths = operations.keys()
|
||||
new_state = await maybe_path_above(state, paths=paths) or state
|
||||
await lsp_created(paths)
|
||||
focus, *_ = sorted(paths, key=pathsort_key)
|
||||
invalidate_dirs = {path.parent for path in paths}
|
||||
index = state.index | ancestors(*paths)
|
||||
next_state = await forward(
|
||||
new_state,
|
||||
index=index,
|
||||
invalidate_dirs=invalidate_dirs,
|
||||
)
|
||||
return Stage(next_state, focus=focus)
|
||||
@ -1,57 +0,0 @@
|
||||
from locale import strxfrm
|
||||
from pathlib import PurePath
|
||||
from typing import Any, Iterator, MutableMapping, MutableSet, Optional, Tuple
|
||||
|
||||
from pynvim_pp.nvim import Nvim
|
||||
from std2.locale import pathsort_key
|
||||
from std2.pathlib import is_relative_to
|
||||
|
||||
from ..registry import rpc
|
||||
from ..settings.localization import LANG
|
||||
from ..state.types import State
|
||||
from ..view.ops import display_path
|
||||
from .focus import _jump
|
||||
from .types import Stage
|
||||
|
||||
|
||||
def _order(root: PurePath, marks: str, path: PurePath) -> Tuple[bool, str, Any]:
|
||||
return not is_relative_to(path, root), "", pathsort_key(path)
|
||||
|
||||
|
||||
def _display_path(state: State, marks: str, path: PurePath, idx: int) -> str:
|
||||
display = display_path(path, state=state)
|
||||
return f"{idx}. [{marks}] {display}"
|
||||
|
||||
|
||||
@rpc(blocking=False)
|
||||
async def _bookmark_goto(state: State, is_visual: bool) -> Optional[Stage]:
|
||||
"""
|
||||
Goto bookmark
|
||||
"""
|
||||
|
||||
def cont() -> Iterator[Tuple[str, PurePath]]:
|
||||
root = state.root.path
|
||||
markers: MutableMapping[str, PurePath] = {}
|
||||
for path, marks in state.markers.bookmarks.items():
|
||||
for mark in marks:
|
||||
if m := markers.get(mark):
|
||||
markers[mark] = max(m, path)
|
||||
else:
|
||||
markers[mark] = path
|
||||
|
||||
seen: MutableSet[PurePath] = set()
|
||||
for _, path in sorted(markers.items(), key=lambda kv: _order(root, *kv)):
|
||||
if path not in seen:
|
||||
ms = sorted(state.markers.bookmarks.get(path, ()), key=strxfrm)
|
||||
yield "".join(ms), path
|
||||
|
||||
opts = {
|
||||
_display_path(state, marks=marks, path=path, idx=idx): path
|
||||
for idx, (marks, path) in enumerate(cont(), start=1)
|
||||
}
|
||||
|
||||
if mark := await Nvim.input_list(opts):
|
||||
return await _jump(state, path=mark)
|
||||
else:
|
||||
await Nvim.write(LANG("no_bookmarks"), error=True)
|
||||
return None
|
||||
@ -1,68 +0,0 @@
|
||||
from os import sep
|
||||
from os.path import abspath, normpath
|
||||
from pathlib import PurePath
|
||||
from typing import Optional
|
||||
|
||||
from pynvim_pp.nvim import Nvim
|
||||
from std2 import anext
|
||||
|
||||
from ..fs.cartographer import act_like_dir
|
||||
from ..fs.ops import ancestors, exists, mkdir, new
|
||||
from ..lsp.notify import lsp_created
|
||||
from ..registry import rpc
|
||||
from ..settings.localization import LANG
|
||||
from ..state.next import forward
|
||||
from ..state.types import State
|
||||
from .shared.current import maybe_path_above
|
||||
from .shared.index import indices
|
||||
from .shared.refresh import refresh
|
||||
from .types import Stage
|
||||
|
||||
|
||||
@rpc(blocking=False)
|
||||
async def _new(state: State, is_visual: bool) -> Optional[Stage]:
|
||||
"""
|
||||
new file / folder
|
||||
"""
|
||||
|
||||
node = await anext(indices(state, is_visual=is_visual), None)
|
||||
if not node:
|
||||
return None
|
||||
else:
|
||||
parent = (
|
||||
node.path
|
||||
if act_like_dir(node, follow_links=state.follow_links)
|
||||
else node.path.parent
|
||||
)
|
||||
|
||||
child = await Nvim.input(question=LANG("pencil"), default="")
|
||||
|
||||
if not child:
|
||||
return None
|
||||
else:
|
||||
path = PurePath(abspath(parent / child))
|
||||
if await exists(path, follow=False):
|
||||
await Nvim.write(
|
||||
LANG("already_exists", name=normpath(path)), error=True
|
||||
)
|
||||
return None
|
||||
else:
|
||||
try:
|
||||
if child.endswith(sep):
|
||||
await mkdir((path,))
|
||||
else:
|
||||
await new((path,))
|
||||
except Exception as e:
|
||||
await Nvim.write(e, error=True)
|
||||
return await refresh(state=state)
|
||||
else:
|
||||
new_state = await maybe_path_above(state, paths={path}) or state
|
||||
invalidate_dirs = {path.parent}
|
||||
index = state.index | ancestors(path)
|
||||
next_state = await forward(
|
||||
new_state,
|
||||
index=index,
|
||||
invalidate_dirs=invalidate_dirs,
|
||||
)
|
||||
await lsp_created((path,))
|
||||
return Stage(next_state, focus=path)
|
||||
@ -1,11 +0,0 @@
|
||||
from typing import Any
|
||||
|
||||
from ..registry import rpc
|
||||
from ..state.types import State
|
||||
|
||||
|
||||
@rpc(blocking=False)
|
||||
async def _noop(state: State, *_: Any) -> None:
|
||||
"""
|
||||
NOOP
|
||||
"""
|
||||
@ -1,52 +0,0 @@
|
||||
import sys
|
||||
from asyncio import create_task
|
||||
from pathlib import PurePath
|
||||
from subprocess import CalledProcessError
|
||||
|
||||
from pynvim_pp.logging import suppress_and_log
|
||||
from pynvim_pp.nvim import Nvim
|
||||
from std2 import anext
|
||||
from std2.asyncio.subprocess import call
|
||||
from std2.pathlib import AnyPath
|
||||
from std2.platform import OS, os
|
||||
|
||||
from ..fs.ops import which
|
||||
from ..registry import rpc
|
||||
from ..settings.localization import LANG
|
||||
from ..state.types import State
|
||||
from .shared.index import indices
|
||||
|
||||
|
||||
async def _call(cwd: PurePath, arg0: AnyPath, *args: AnyPath) -> None:
|
||||
try:
|
||||
await call(arg0, *args, cwd=cwd)
|
||||
except CalledProcessError as e:
|
||||
await Nvim.write(e, e.stderr, e.stdout, error=True)
|
||||
|
||||
|
||||
async def _open_gui(path: PurePath, cwd: PurePath) -> None:
|
||||
with suppress_and_log():
|
||||
if sys.platform == "win32":
|
||||
from os import startfile
|
||||
|
||||
startfile(path, cwd=cwd)
|
||||
elif os is OS.macos and (arg0 := which("open")):
|
||||
await _call(cwd, arg0, "--", path)
|
||||
elif os is OS.linux and (arg0 := which("xdg-open")):
|
||||
await _call(cwd, arg0, path)
|
||||
else:
|
||||
await Nvim.write(LANG("sys_open_err"))
|
||||
|
||||
|
||||
@rpc(blocking=False)
|
||||
async def _open_sys(state: State, is_visual: bool) -> None:
|
||||
"""
|
||||
Open using finder / dolphin, etc
|
||||
"""
|
||||
|
||||
node = await anext(indices(state, is_visual=is_visual), None)
|
||||
if not node:
|
||||
return None
|
||||
else:
|
||||
cwd = await Nvim.getcwd()
|
||||
create_task(_open_gui(node.path, cwd=cwd))
|
||||
@ -1,20 +0,0 @@
|
||||
from pynvim_pp.nvim import Nvim
|
||||
from pynvim_pp.window import Window
|
||||
|
||||
from ..registry import rpc
|
||||
from ..state.types import State
|
||||
from .shared.wm import find_fm_windows_in_tab
|
||||
|
||||
|
||||
@rpc(blocking=False)
|
||||
async def _quit(state: State, is_visual: bool) -> None:
|
||||
"""
|
||||
Close sidebar
|
||||
"""
|
||||
|
||||
wins = await Window.list()
|
||||
if len(wins) <= 1:
|
||||
await Nvim.exec("quit")
|
||||
else:
|
||||
async for win in find_fm_windows_in_tab(state.window_order):
|
||||
await win.close()
|
||||
@ -1,145 +0,0 @@
|
||||
from pathlib import Path, PurePath
|
||||
from posixpath import sep
|
||||
from typing import Optional, Sequence
|
||||
from uuid import uuid4
|
||||
|
||||
from pynvim_pp.atomic import Atomic
|
||||
from pynvim_pp.buffer import Buffer
|
||||
from pynvim_pp.nvim import Nvim
|
||||
from pynvim_pp.operators import operator_marks
|
||||
from pynvim_pp.rpc_types import NvimError
|
||||
from pynvim_pp.types import NoneType
|
||||
from std2.difflib import trans_inplace
|
||||
from std2.pickle.decoder import new_decoder
|
||||
from std2.pickle.types import DecodeError
|
||||
|
||||
from ..consts import URI_SCHEME
|
||||
from ..state.types import State
|
||||
from ..view.types import Derived
|
||||
from .shared.wm import find_fm_windows
|
||||
|
||||
|
||||
class UnrecoverableError(Exception):
|
||||
...
|
||||
|
||||
|
||||
_NS = uuid4()
|
||||
|
||||
|
||||
_DECODER = new_decoder[Sequence[str]](Sequence[str])
|
||||
_HOME = Path.home()
|
||||
|
||||
|
||||
def _buf_name(root: PurePath) -> str:
|
||||
try:
|
||||
rel = root.relative_to(_HOME)
|
||||
except ValueError:
|
||||
name = root.as_posix()
|
||||
else:
|
||||
name = f"~{sep}{rel.as_posix()}"
|
||||
|
||||
return name
|
||||
|
||||
|
||||
def _update(
|
||||
use_extmarks: bool,
|
||||
buf: Buffer,
|
||||
ns: int,
|
||||
derived: Derived,
|
||||
hashed_lines: Sequence[str],
|
||||
) -> Atomic:
|
||||
atomic = Atomic()
|
||||
for (i1, i2), (j1, j2) in trans_inplace(
|
||||
src=hashed_lines, dest=derived.hashed, unifying=10
|
||||
):
|
||||
atomic.buf_clear_namespace(buf, ns, i1, i2)
|
||||
atomic.buf_set_lines(buf, i1, i2, True, derived.lines[j1:j2])
|
||||
|
||||
for idx, highlights in enumerate(derived.highlights[j1:j2], start=i1):
|
||||
for hl in highlights:
|
||||
atomic.buf_add_highlight(buf, ns, hl.group, idx, hl.begin, hl.end)
|
||||
|
||||
for idx, badges in enumerate(derived.badges[j1:j2], start=i1):
|
||||
vtxt = tuple((bdg.text, bdg.group) for bdg in badges)
|
||||
if use_extmarks:
|
||||
atomic.buf_set_extmark(
|
||||
buf, ns, idx, -1, {"virt_text": vtxt, "hl_mode": "combine"}
|
||||
)
|
||||
else:
|
||||
atomic.buf_set_virtual_text(buf, ns, idx, vtxt, {})
|
||||
|
||||
atomic.buf_set_var(buf, str(_NS), derived.hashed)
|
||||
return atomic
|
||||
|
||||
|
||||
async def redraw(state: State, focus: Optional[PurePath]) -> None:
|
||||
focus_row = state.derived.path_row_lookup.get(focus) if focus else None
|
||||
buf_name = _buf_name(state.root.path)
|
||||
|
||||
ns = await Nvim.create_namespace(_NS)
|
||||
use_extmarks = await Nvim.api.has("nvim-0.6")
|
||||
|
||||
async for win, buf in find_fm_windows():
|
||||
is_fm_win = await win.vars.get(bool, URI_SCHEME)
|
||||
p_count = await buf.line_count()
|
||||
n_count = len(state.derived.lines)
|
||||
row, col = await win.get_cursor()
|
||||
(r1, c1), (r2, c2) = await operator_marks(buf, visual_type=None)
|
||||
buf_var = await buf.vars.get(NoneType, str(_NS))
|
||||
|
||||
try:
|
||||
hashed_lines = _DECODER(buf_var)
|
||||
except DecodeError:
|
||||
hashed_lines = ("",)
|
||||
|
||||
if focus_row is not None:
|
||||
new_row: Optional[int] = focus_row + 1
|
||||
elif row >= n_count:
|
||||
new_row = n_count
|
||||
elif p_count != n_count:
|
||||
new_row = row + 1
|
||||
else:
|
||||
new_row = None
|
||||
|
||||
a1 = Atomic()
|
||||
a1.buf_set_option(buf, "modifiable", True)
|
||||
|
||||
a2 = _update(
|
||||
use_extmarks,
|
||||
buf=buf,
|
||||
ns=ns,
|
||||
derived=state.derived,
|
||||
hashed_lines=hashed_lines,
|
||||
)
|
||||
|
||||
a3 = Atomic()
|
||||
a3.buf_set_option(buf, "modifiable", False)
|
||||
a3.call_function("setpos", ("'<", (buf.number, r1 + 1, c1 + 1, 0)))
|
||||
a3.call_function("setpos", ("'>", (buf.number, r2 + 1, c2, 0)))
|
||||
if new_row is not None:
|
||||
win_height = await win.get_height()
|
||||
win_lo = await Nvim.fn.line(int, "w0", win)
|
||||
win_hi = await Nvim.fn.line(int, "w$", win)
|
||||
lo = max(1, new_row - win_height // 2)
|
||||
hi = min(n_count, new_row + win_height // 2)
|
||||
|
||||
if new_row < win_lo or new_row > win_hi:
|
||||
a3.win_set_cursor(win, (lo, 0))
|
||||
a3.win_set_cursor(win, (hi, 0))
|
||||
a3.win_set_cursor(win, (lo, 0))
|
||||
a3.win_set_cursor(win, (hi, 0))
|
||||
|
||||
a3.win_set_cursor(win, (new_row, col))
|
||||
|
||||
a3.buf_set_name(buf, f"{URI_SCHEME}://{buf_name}")
|
||||
a3.win_set_var(win, URI_SCHEME, True)
|
||||
|
||||
if not is_fm_win:
|
||||
for key, val in state.settings.win_local_opts.items():
|
||||
a3.win_set_option(win, key, val)
|
||||
|
||||
a4 = a1 + a2 + a3
|
||||
try:
|
||||
await a4.commit(NoneType)
|
||||
except NvimError as e:
|
||||
raise UnrecoverableError(e)
|
||||
@ -1,23 +0,0 @@
|
||||
from contextlib import asynccontextmanager
|
||||
from typing import AsyncIterator
|
||||
|
||||
from pynvim_pp.nvim import Nvim
|
||||
|
||||
from ..registry import rpc
|
||||
from ..settings.localization import LANG
|
||||
from ..state.types import State
|
||||
from .shared.refresh import refresh as _refresh
|
||||
from .types import Stage
|
||||
|
||||
|
||||
@asynccontextmanager
|
||||
async def with_manual() -> AsyncIterator[None]:
|
||||
await Nvim.write(LANG("hourglass"))
|
||||
yield None
|
||||
await Nvim.write(LANG("ok_sym"))
|
||||
|
||||
|
||||
@rpc(blocking=False)
|
||||
async def refresh(state: State, is_visual: bool) -> Stage:
|
||||
async with with_manual():
|
||||
return await _refresh(state)
|
||||
@ -1,75 +0,0 @@
|
||||
from os.path import abspath, normpath
|
||||
from pathlib import PurePath
|
||||
from typing import Optional
|
||||
|
||||
from pynvim_pp.hold import hold_win
|
||||
from pynvim_pp.nvim import Nvim
|
||||
from pynvim_pp.window import Window
|
||||
from std2 import anext
|
||||
|
||||
from ..fs.ops import ancestors, exists, rename
|
||||
from ..lsp.notify import lsp_moved
|
||||
from ..registry import rpc
|
||||
from ..settings.localization import LANG
|
||||
from ..state.next import forward
|
||||
from ..state.types import State
|
||||
from .shared.current import maybe_path_above
|
||||
from .shared.index import indices
|
||||
from .shared.refresh import refresh
|
||||
from .shared.wm import kill_buffers
|
||||
from .types import Stage
|
||||
|
||||
|
||||
@rpc(blocking=False)
|
||||
async def _rename(state: State, is_visual: bool) -> Optional[Stage]:
|
||||
"""
|
||||
rename file / folder
|
||||
"""
|
||||
|
||||
node = await anext(indices(state, is_visual=is_visual), None)
|
||||
if not node:
|
||||
return None
|
||||
else:
|
||||
old_path = node.path
|
||||
child = await Nvim.input(question=LANG("pencil"), default=old_path.name)
|
||||
if not child:
|
||||
return None
|
||||
else:
|
||||
new_path = PurePath(abspath(old_path.parent / child))
|
||||
operations = {old_path: new_path}
|
||||
if await exists(new_path, follow=False):
|
||||
await Nvim.write(
|
||||
LANG("already_exists", name=normpath(new_path)), error=True
|
||||
)
|
||||
return None
|
||||
else:
|
||||
killed = await kill_buffers(
|
||||
last_used=state.window_order,
|
||||
paths={old_path},
|
||||
reopen={old_path: new_path},
|
||||
)
|
||||
try:
|
||||
await rename(operations)
|
||||
except Exception as e:
|
||||
await Nvim.write(e, error=True)
|
||||
return await refresh(state=state)
|
||||
else:
|
||||
async with hold_win(win=None):
|
||||
for win, new_path in killed.items():
|
||||
await Window.set_current(win)
|
||||
escaped = await Nvim.fn.fnameescape(str, normpath(new_path))
|
||||
await Nvim.exec(f"edit! {escaped}")
|
||||
|
||||
new_state = await maybe_path_above(state, paths={new_path}) or state
|
||||
parents = ancestors(new_path)
|
||||
invalidate_dirs = {old_path.parent, new_path.parent}
|
||||
index = state.index | parents
|
||||
new_selection = {new_path} if state.selection else frozenset()
|
||||
next_state = await forward(
|
||||
new_state,
|
||||
index=index,
|
||||
invalidate_dirs=invalidate_dirs,
|
||||
selection=new_selection,
|
||||
)
|
||||
await lsp_moved(operations)
|
||||
return Stage(next_state, focus=new_path)
|
||||
@ -1,42 +0,0 @@
|
||||
from operator import add, sub
|
||||
from typing import Callable, Optional
|
||||
|
||||
from pynvim_pp.window import Window
|
||||
|
||||
from ..registry import rpc
|
||||
from ..state.next import forward
|
||||
from ..state.types import State
|
||||
from .shared.wm import is_fm_window, resize_fm_windows
|
||||
from .types import Stage
|
||||
|
||||
|
||||
async def _resize(
|
||||
state: State, direction: Callable[[int, int], int]
|
||||
) -> Optional[Stage]:
|
||||
win = await Window.get_current()
|
||||
if not await is_fm_window(win):
|
||||
return None
|
||||
else:
|
||||
old_width = await win.get_width()
|
||||
new_width = max(direction(old_width, 10), 1)
|
||||
new_state = await forward(state, width=new_width)
|
||||
await resize_fm_windows(new_state.window_order, width=new_state.width)
|
||||
return Stage(new_state)
|
||||
|
||||
|
||||
@rpc(blocking=False)
|
||||
async def _bigger(state: State, is_visual: bool) -> Optional[Stage]:
|
||||
"""
|
||||
Bigger sidebar
|
||||
"""
|
||||
|
||||
return await _resize(state, direction=add)
|
||||
|
||||
|
||||
@rpc(blocking=False)
|
||||
async def _smaller(state: State, is_visual: bool) -> Optional[Stage]:
|
||||
"""
|
||||
Smaller sidebar
|
||||
"""
|
||||
|
||||
return await _resize(state, direction=sub)
|
||||
@ -1,37 +0,0 @@
|
||||
from asyncio import gather
|
||||
from typing import Optional
|
||||
|
||||
from pynvim_pp.nvim import Nvim
|
||||
from pynvim_pp.rpc_types import NvimError
|
||||
from std2.asyncio import pure
|
||||
|
||||
from ..lsp.diagnostics import poll
|
||||
from ..registry import rpc
|
||||
from ..state.next import forward
|
||||
from ..state.ops import dump_session
|
||||
from ..state.types import State
|
||||
from ..version_ctl.git import status
|
||||
from ..version_ctl.types import VCStatus
|
||||
from .shared.refresh import refresh
|
||||
from .types import Stage
|
||||
|
||||
|
||||
@rpc(blocking=False)
|
||||
async def scheduled_update(state: State, init: bool = False) -> Optional[Stage]:
|
||||
cwd = await Nvim.getcwd()
|
||||
store = dump_session(state) if state.vim_focus else pure(None)
|
||||
|
||||
try:
|
||||
stage, diagnostics, vc, _ = await gather(
|
||||
refresh(state=state),
|
||||
poll(state.settings.min_diagnostics_severity),
|
||||
status(cwd, prev=state.vc)
|
||||
if not init and state.enable_vc
|
||||
else pure(VCStatus()),
|
||||
store,
|
||||
)
|
||||
except NvimError:
|
||||
return None
|
||||
else:
|
||||
new_state = await forward(stage.state, diagnostics=diagnostics, vc=vc)
|
||||
return Stage(new_state, focus=stage.focus)
|
||||
@ -1,27 +0,0 @@
|
||||
from ..registry import rpc
|
||||
from ..state.next import forward
|
||||
from ..state.types import State
|
||||
from .shared.index import indices
|
||||
from .types import Stage
|
||||
|
||||
|
||||
@rpc(blocking=False)
|
||||
async def _clear_selection(state: State, is_visual: bool) -> Stage:
|
||||
"""
|
||||
Clear selected
|
||||
"""
|
||||
|
||||
new_state = await forward(state, selection=frozenset())
|
||||
return Stage(new_state)
|
||||
|
||||
|
||||
@rpc(blocking=False)
|
||||
async def _select(state: State, is_visual: bool) -> Stage:
|
||||
"""
|
||||
Folder / File -> select
|
||||
"""
|
||||
|
||||
nodes = indices(state, is_visual=is_visual)
|
||||
selection = state.selection ^ {node.path async for node in nodes}
|
||||
new_state = await forward(state, selection=selection)
|
||||
return Stage(new_state)
|
||||
@ -1,65 +0,0 @@
|
||||
from pathlib import PurePath
|
||||
from typing import AbstractSet, Iterator, Optional
|
||||
|
||||
from std2.locale import pathsort_key
|
||||
from std2.pathlib import is_relative_to, longest_common_path
|
||||
|
||||
from ...fs.cartographer import new
|
||||
from ...fs.ops import ancestors
|
||||
from ...state.next import forward
|
||||
from ...state.types import State
|
||||
from ..types import Stage
|
||||
|
||||
|
||||
async def new_current_file(state: State, current: PurePath) -> Stage:
|
||||
"""
|
||||
New file focused in buf
|
||||
"""
|
||||
|
||||
parents = ancestors(current)
|
||||
if state.root.path in parents:
|
||||
invalidate_dirs = {current.parent}
|
||||
index = state.index | parents
|
||||
new_state = await forward(
|
||||
state,
|
||||
index=index,
|
||||
invalidate_dirs=invalidate_dirs,
|
||||
current=current,
|
||||
)
|
||||
else:
|
||||
new_state = await forward(state, current=current)
|
||||
|
||||
focus = current if state.follow else None
|
||||
return Stage(new_state, focus=focus)
|
||||
|
||||
|
||||
async def new_root(
|
||||
state: State,
|
||||
new_cwd: PurePath,
|
||||
indices: AbstractSet[PurePath],
|
||||
) -> State:
|
||||
index = state.index | ancestors(new_cwd) | {new_cwd} | indices
|
||||
root = await new(
|
||||
state.executor, follow_links=state.follow_links, root=new_cwd, index=index
|
||||
)
|
||||
selection = {path for path in state.selection if root.path in ancestors(path)}
|
||||
return await forward(state, root=root, selection=selection, index=index)
|
||||
|
||||
|
||||
async def maybe_path_above(
|
||||
state: State, paths: AbstractSet[PurePath]
|
||||
) -> Optional[State]:
|
||||
root = state.root.path
|
||||
if all(is_relative_to(path, root) for path in paths):
|
||||
return None
|
||||
else:
|
||||
|
||||
def cont() -> Iterator[PurePath]:
|
||||
for path in paths:
|
||||
lcp = longest_common_path(path, root)
|
||||
yield lcp if lcp else path.parent
|
||||
|
||||
ordered = sorted(cont(), key=pathsort_key)
|
||||
indices = ancestors(*ordered)
|
||||
new_cwd, *_ = ordered
|
||||
return await new_root(state=state, new_cwd=new_cwd, indices=indices)
|
||||
@ -1,35 +0,0 @@
|
||||
from typing import AsyncIterator, Optional
|
||||
|
||||
from pynvim_pp.operators import operator_marks
|
||||
from pynvim_pp.window import Window
|
||||
|
||||
from ...fs.types import Node
|
||||
from ...state.types import State
|
||||
from .wm import is_fm_buffer
|
||||
|
||||
|
||||
def _row_index(state: State, row: int) -> Optional[Node]:
|
||||
if (row >= 0) and (row < len(state.derived.node_row_lookup)):
|
||||
return state.derived.node_row_lookup[row]
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
async def indices(state: State, is_visual: bool) -> AsyncIterator[Node]:
|
||||
win = await Window.get_current()
|
||||
buf = await win.get_buf()
|
||||
|
||||
if not await is_fm_buffer(buf):
|
||||
return
|
||||
else:
|
||||
row, _ = await win.get_cursor()
|
||||
if node := _row_index(state, row):
|
||||
yield node
|
||||
|
||||
if is_visual:
|
||||
(row1, _), (row2, _) = await operator_marks(buf, visual_type=None)
|
||||
|
||||
for r in range(row1, row2 + 1):
|
||||
if r != row:
|
||||
if node := _row_index(state, r):
|
||||
yield node
|
||||
@ -1,117 +0,0 @@
|
||||
from contextlib import suppress
|
||||
from mimetypes import guess_type
|
||||
from os.path import getsize, normpath
|
||||
from pathlib import PurePath
|
||||
from posixpath import sep
|
||||
from typing import AsyncContextManager, Optional, cast
|
||||
|
||||
from pynvim_pp.buffer import Buffer
|
||||
from pynvim_pp.hold import hold_win
|
||||
from pynvim_pp.nvim import Nvim
|
||||
from pynvim_pp.window import Window
|
||||
from std2 import anext
|
||||
from std2.aitertools import achain, to_async
|
||||
from std2.contextlib import nullacontext
|
||||
|
||||
from ...settings.localization import LANG
|
||||
from ...state.next import forward
|
||||
from ...state.types import State
|
||||
from ..types import ClickType, Stage
|
||||
from .wm import (
|
||||
find_buffers_with_file,
|
||||
find_non_fm_windows_in_tab,
|
||||
find_window_with_file_in_tab,
|
||||
new_window,
|
||||
resize_fm_windows,
|
||||
)
|
||||
|
||||
|
||||
async def _show_file(*, state: State, click_type: ClickType) -> None:
|
||||
if click_type is ClickType.tertiary:
|
||||
await Nvim.exec("tabnew")
|
||||
win = await Window.get_current()
|
||||
for key, val in state.settings.win_actual_opts.items():
|
||||
await win.opts.set(key, val=val)
|
||||
|
||||
if path := state.current:
|
||||
mgr = (
|
||||
cast(AsyncContextManager[None], hold_win(win=None))
|
||||
if click_type is ClickType.secondary
|
||||
else nullacontext(None)
|
||||
)
|
||||
async with mgr:
|
||||
non_fm_windows = [
|
||||
win
|
||||
async for win in find_non_fm_windows_in_tab(
|
||||
last_used=state.window_order
|
||||
)
|
||||
]
|
||||
buf = await anext(find_buffers_with_file(file=path), None)
|
||||
win = await anext(
|
||||
achain(
|
||||
find_window_with_file_in_tab(
|
||||
last_used=state.window_order, file=path
|
||||
),
|
||||
to_async(non_fm_windows),
|
||||
),
|
||||
cast(Window, None),
|
||||
) or await new_window(
|
||||
last_used=state.window_order,
|
||||
win_local=state.settings.win_actual_opts,
|
||||
open_left=not state.settings.open_left,
|
||||
width=None
|
||||
if len(non_fm_windows)
|
||||
else await Nvim.opts.get(int, "columns") - state.width - 1,
|
||||
)
|
||||
|
||||
await Window.set_current(win)
|
||||
non_fm_count = len(non_fm_windows)
|
||||
|
||||
if click_type is ClickType.v_split and non_fm_count:
|
||||
await Nvim.exec("vnew")
|
||||
temp_buf = await Buffer.get_current()
|
||||
await temp_buf.opts.set("bufhidden", val="wipe")
|
||||
elif click_type is ClickType.h_split and non_fm_count:
|
||||
await Nvim.exec("new")
|
||||
temp_buf = await Buffer.get_current()
|
||||
await temp_buf.opts.set("bufhidden", val="wipe")
|
||||
|
||||
win = await Window.get_current()
|
||||
|
||||
if buf:
|
||||
await win.set_buf(buf)
|
||||
else:
|
||||
escaped = await Nvim.fn.fnameescape(str, normpath(path))
|
||||
await Nvim.exec(f"edit! {escaped}")
|
||||
|
||||
await resize_fm_windows(last_used=state.window_order, width=state.width)
|
||||
|
||||
|
||||
async def open_file(
|
||||
state: State, path: PurePath, click_type: ClickType
|
||||
) -> Optional[Stage]:
|
||||
mime, _ = guess_type(path.name, strict=False)
|
||||
m_type, _, _ = (mime or "").partition(sep)
|
||||
|
||||
with suppress(OSError):
|
||||
size = getsize(path)
|
||||
|
||||
question = LANG("mime_warn", name=path.name, mime=str(mime))
|
||||
|
||||
go = (
|
||||
await Nvim.confirm(
|
||||
question=question,
|
||||
answers=LANG("ask_yesno"),
|
||||
answer_key={1: True, 2: False},
|
||||
)
|
||||
if m_type in state.settings.mime.warn
|
||||
and path.suffix not in state.settings.mime.allow_exts
|
||||
else True
|
||||
)
|
||||
|
||||
if go:
|
||||
new_state = await forward(state, current=path)
|
||||
await _show_file(state=new_state, click_type=click_type)
|
||||
return Stage(new_state, focus=path)
|
||||
else:
|
||||
return None
|
||||
@ -1,78 +0,0 @@
|
||||
from asyncio import gather
|
||||
from pathlib import PurePath
|
||||
from typing import AbstractSet, Mapping
|
||||
|
||||
from pynvim_pp.rpc_types import ExtData
|
||||
from pynvim_pp.window import Window
|
||||
from std2.types import Void
|
||||
|
||||
from ...fs.ops import ancestors, exists_many
|
||||
from ...nvim.markers import markers
|
||||
from ...state.next import forward
|
||||
from ...state.types import State
|
||||
from ..shared.wm import find_current_buffer_path
|
||||
from ..types import Stage
|
||||
|
||||
|
||||
async def _index(state: State, paths: AbstractSet[PurePath]) -> AbstractSet[PurePath]:
|
||||
index = {
|
||||
path
|
||||
for path, exists in (await exists_many(state.index, follow=True)).items()
|
||||
if exists
|
||||
} | paths
|
||||
|
||||
return index
|
||||
|
||||
|
||||
async def _selection(state: State) -> AbstractSet[PurePath]:
|
||||
selection = {
|
||||
selected
|
||||
for selected, exists in (
|
||||
await exists_many(state.selection, follow=False)
|
||||
).items()
|
||||
if exists
|
||||
}
|
||||
|
||||
return selection
|
||||
|
||||
|
||||
async def _window_order(state: State) -> Mapping[ExtData, None]:
|
||||
window_ids = {w.data for w in await Window.list()}
|
||||
window_order = {
|
||||
win_id: None for win_id in state.window_order if win_id in window_ids
|
||||
}
|
||||
return window_order
|
||||
|
||||
|
||||
async def refresh(state: State) -> Stage:
|
||||
cwd = state.root.path
|
||||
invalidate_dirs = {cwd}
|
||||
|
||||
current, index, selection, window_order, mks = await gather(
|
||||
find_current_buffer_path(),
|
||||
_index(state, paths=invalidate_dirs),
|
||||
_selection(state),
|
||||
_window_order(state),
|
||||
markers(),
|
||||
)
|
||||
current_ancestors = ancestors(current) if current else frozenset()
|
||||
new_current = current if cwd in current_ancestors else None
|
||||
|
||||
parent_paths: AbstractSet[PurePath] = (
|
||||
current_ancestors if state.follow else frozenset()
|
||||
)
|
||||
new_index = index if new_current else index | parent_paths
|
||||
focus = current if state.follow else None
|
||||
|
||||
new_state = await forward(
|
||||
state,
|
||||
index=new_index,
|
||||
selection=selection,
|
||||
markers=mks,
|
||||
invalidate_dirs=invalidate_dirs,
|
||||
current=new_current or Void,
|
||||
window_order=window_order,
|
||||
trace=False,
|
||||
)
|
||||
|
||||
return Stage(new_state, focus=focus)
|
||||
@ -1,254 +0,0 @@
|
||||
from contextlib import suppress
|
||||
from math import inf
|
||||
from pathlib import PurePath
|
||||
from typing import (
|
||||
AbstractSet,
|
||||
AsyncIterator,
|
||||
Mapping,
|
||||
Optional,
|
||||
Sequence,
|
||||
Tuple,
|
||||
Union,
|
||||
cast,
|
||||
)
|
||||
from urllib.parse import urlsplit
|
||||
|
||||
from pynvim_pp.atomic import Atomic
|
||||
from pynvim_pp.buffer import Buffer
|
||||
from pynvim_pp.keymap import Keymap
|
||||
from pynvim_pp.lib import resolve_path
|
||||
from pynvim_pp.nvim import Nvim
|
||||
from pynvim_pp.rpc_types import ExtData
|
||||
from pynvim_pp.tabpage import Tabpage
|
||||
from pynvim_pp.types import NoneType
|
||||
from pynvim_pp.window import Window
|
||||
|
||||
from ...consts import FM_FILETYPE, URI_SCHEME
|
||||
from ...fs.ops import ancestors
|
||||
from ...settings.types import Settings
|
||||
|
||||
|
||||
def is_fm_buf_name(name: str) -> bool:
|
||||
with suppress(ValueError):
|
||||
uri = urlsplit(name)
|
||||
return uri.scheme == URI_SCHEME
|
||||
return False
|
||||
|
||||
|
||||
async def is_fm_buffer(buf: Buffer) -> bool:
|
||||
ft = await buf.filetype()
|
||||
if ft == FM_FILETYPE:
|
||||
return True
|
||||
elif name := await buf.get_name():
|
||||
return is_fm_buf_name(name)
|
||||
|
||||
return False
|
||||
|
||||
|
||||
async def is_fm_window(win: Window) -> bool:
|
||||
buf = await win.get_buf()
|
||||
return await is_fm_buffer(buf)
|
||||
|
||||
|
||||
async def find_windows_in_tab(
|
||||
last_used: Mapping[ExtData, None], no_secondary: bool
|
||||
) -> AsyncIterator[Window]:
|
||||
ordering = {win_id: idx for idx, win_id in enumerate(reversed(last_used.keys()))}
|
||||
tab = await Tabpage.get_current()
|
||||
wins = await tab.list_wins()
|
||||
|
||||
atomic = Atomic()
|
||||
for win in wins:
|
||||
atomic.win_get_position(win)
|
||||
pos = cast(Sequence[Tuple[int, int]], await atomic.commit(NoneType))
|
||||
positions = {win.data: rc for win, rc in zip(wins, pos)}
|
||||
|
||||
def key_by(win: Window) -> Tuple[float, float, float]:
|
||||
"""
|
||||
-> sort by last_used, then row, then col
|
||||
"""
|
||||
|
||||
order = ordering.get(win.data, inf)
|
||||
row, col = positions.get(win.data, (inf, inf))
|
||||
return order, col, row
|
||||
|
||||
ordered = sorted(wins, key=key_by)
|
||||
|
||||
for win in ordered:
|
||||
is_preview = await win.opts.get(bool, "previewwindow")
|
||||
buf = await win.get_buf()
|
||||
ft = await buf.filetype()
|
||||
is_secondary = is_preview or ft == "qf"
|
||||
if not is_secondary or not no_secondary:
|
||||
yield win
|
||||
|
||||
|
||||
async def find_fm_windows() -> AsyncIterator[Tuple[Window, Buffer]]:
|
||||
for win in await Window.list():
|
||||
buf = await win.get_buf()
|
||||
if await is_fm_buffer(buf):
|
||||
yield win, buf
|
||||
|
||||
|
||||
async def find_fm_windows_in_tab(
|
||||
last_used: Mapping[ExtData, None]
|
||||
) -> AsyncIterator[Window]:
|
||||
async for win in find_windows_in_tab(last_used, no_secondary=True):
|
||||
buf = await win.get_buf()
|
||||
if await is_fm_buffer(buf):
|
||||
yield win
|
||||
|
||||
|
||||
async def find_non_fm_windows_in_tab(
|
||||
last_used: Mapping[ExtData, None]
|
||||
) -> AsyncIterator[Window]:
|
||||
async for win in find_windows_in_tab(last_used, no_secondary=True):
|
||||
buf = await win.get_buf()
|
||||
if not await is_fm_buffer(buf):
|
||||
yield win
|
||||
|
||||
|
||||
async def find_window_with_file_in_tab(
|
||||
last_used: Mapping[ExtData, None], file: PurePath
|
||||
) -> AsyncIterator[Window]:
|
||||
async for win in find_windows_in_tab(last_used, no_secondary=True):
|
||||
buf = await win.get_buf()
|
||||
if name := await buf.get_name():
|
||||
if PurePath(name) == file:
|
||||
yield win
|
||||
|
||||
|
||||
async def find_fm_buffers() -> AsyncIterator[Buffer]:
|
||||
for buf in await Buffer.list(listed=True):
|
||||
if await is_fm_buffer(buf):
|
||||
yield buf
|
||||
|
||||
|
||||
async def find_buffers_with_file(file: PurePath) -> AsyncIterator[Buffer]:
|
||||
for buf in await Buffer.list(listed=True):
|
||||
if name := await buf.get_name():
|
||||
if PurePath(name) == file:
|
||||
yield buf
|
||||
|
||||
|
||||
async def find_current_buffer_path(
|
||||
buf_name: Optional[str] = None,
|
||||
) -> Optional[PurePath]:
|
||||
if buf_name is None:
|
||||
buf = await Buffer.get_current()
|
||||
buf_name = await buf.get_name()
|
||||
|
||||
if buf_name and not is_fm_buf_name(buf_name):
|
||||
return await resolve_path(None, path=buf_name)
|
||||
|
||||
return None
|
||||
|
||||
|
||||
async def setup_fm_buf(settings: Settings, buf: Buffer) -> None:
|
||||
await buf.opts.set("modifiable", val=False)
|
||||
await buf.opts.set("filetype", val=FM_FILETYPE)
|
||||
await buf.opts.set("undolevels", val=-1)
|
||||
|
||||
km = Keymap()
|
||||
_ = km.n("{") << f"{settings.page_increment}g<up>"
|
||||
_ = km.n("}") << f"{settings.page_increment}g<down>"
|
||||
for function, mappings in settings.keymap.items():
|
||||
for mapping in mappings:
|
||||
_ = (
|
||||
km.n(mapping, noremap=True, silent=True, nowait=True)
|
||||
<< f"<cmd>lua {function}(false)<cr>"
|
||||
)
|
||||
_ = (
|
||||
km.v(mapping, noremap=True, silent=True, nowait=True)
|
||||
<< rf"<c-\><c-n><cmd>lua {function}(true)<cr>"
|
||||
)
|
||||
|
||||
await km.drain(buf=buf).commit(NoneType)
|
||||
|
||||
|
||||
async def new_fm_buffer(settings: Settings) -> Buffer:
|
||||
buf = await Buffer.create(
|
||||
listed=False, scratch=True, wipe=False, nofile=True, noswap=True
|
||||
)
|
||||
await setup_fm_buf(settings, buf=buf)
|
||||
return buf
|
||||
|
||||
|
||||
async def restore_non_fm_win(
|
||||
win_local: Mapping[str, Union[bool, str]], win: Window
|
||||
) -> None:
|
||||
await win.vars.set(URI_SCHEME, False)
|
||||
for key, val in win_local.items():
|
||||
await win.opts.set(key, val=val)
|
||||
|
||||
|
||||
async def new_window(
|
||||
*,
|
||||
last_used: Mapping[ExtData, None],
|
||||
win_local: Mapping[str, Union[bool, str]],
|
||||
open_left: bool,
|
||||
width: Optional[int],
|
||||
) -> Window:
|
||||
split_r = await Nvim.opts.get(bool, "splitright")
|
||||
|
||||
wins = [win async for win in find_windows_in_tab(last_used, no_secondary=False)]
|
||||
focus_win = wins[0] if open_left else wins[-1]
|
||||
direction = False if open_left else True
|
||||
|
||||
await Nvim.opts.set("splitright", val=direction)
|
||||
await Window.set_current(focus_win)
|
||||
await Nvim.exec(f"{width}vnew" if width else "vnew")
|
||||
await Nvim.opts.set("splitright", val=split_r)
|
||||
|
||||
win = await Window.get_current()
|
||||
buf = await win.get_buf()
|
||||
await restore_non_fm_win(win_local, win=win)
|
||||
await buf.opts.set("bufhidden", val="wipe")
|
||||
return win
|
||||
|
||||
|
||||
async def resize_fm_windows(last_used: Mapping[ExtData, None], width: int) -> None:
|
||||
async for win in find_fm_windows_in_tab(last_used):
|
||||
await win.set_width(width)
|
||||
|
||||
|
||||
async def kill_buffers(
|
||||
last_used: Mapping[ExtData, None],
|
||||
paths: AbstractSet[PurePath],
|
||||
reopen: Mapping[PurePath, PurePath],
|
||||
) -> Mapping[Window, PurePath]:
|
||||
active = (
|
||||
{
|
||||
await win.get_buf(): win
|
||||
async for win in find_non_fm_windows_in_tab(
|
||||
last_used,
|
||||
)
|
||||
}
|
||||
if reopen
|
||||
else {}
|
||||
)
|
||||
|
||||
async def cont() -> AsyncIterator[Tuple[Window, PurePath]]:
|
||||
for buf in await Buffer.list(listed=True):
|
||||
if bufname := await buf.get_name():
|
||||
name = PurePath(bufname)
|
||||
buf_paths = ancestors(name) | {name}
|
||||
|
||||
if not buf_paths.isdisjoint(paths):
|
||||
if (
|
||||
reopen
|
||||
and (win := active.get(buf))
|
||||
and (new_path := reopen.get(name))
|
||||
):
|
||||
tmp = await Buffer.create(
|
||||
listed=False,
|
||||
scratch=True,
|
||||
wipe=True,
|
||||
nofile=True,
|
||||
noswap=True,
|
||||
)
|
||||
await win.set_buf(tmp)
|
||||
yield win, new_path
|
||||
await buf.delete()
|
||||
|
||||
return {win: path async for win, path in cont()}
|
||||
@ -1,35 +0,0 @@
|
||||
from pynvim_pp.nvim import Nvim
|
||||
from std2 import anext
|
||||
from std2.locale import si_prefixed
|
||||
|
||||
from ..fs.ops import fs_stat
|
||||
from ..registry import rpc
|
||||
from ..state.types import State
|
||||
from ..view.ops import display_path
|
||||
from .shared.index import indices
|
||||
|
||||
|
||||
@rpc(blocking=False)
|
||||
async def _stat(state: State, is_visual: bool) -> None:
|
||||
"""
|
||||
Print file stat to cmdline
|
||||
"""
|
||||
|
||||
node = await anext(indices(state, is_visual=is_visual), None)
|
||||
if not node:
|
||||
return None
|
||||
else:
|
||||
try:
|
||||
stat = await fs_stat(node.path)
|
||||
except Exception as e:
|
||||
await Nvim.write(e, error=True)
|
||||
else:
|
||||
permissions = stat.permissions
|
||||
size = si_prefixed(stat.size, precision=2)
|
||||
user = stat.user
|
||||
group = stat.group
|
||||
mtime = stat.date_mod.strftime(state.settings.view.time_fmt)
|
||||
name = display_path(node.path, state=state)
|
||||
full_name = f"{name} -> {stat.link}" if stat.link else name
|
||||
mode_line = f"{permissions} {size}b {user} {group} {mtime} {full_name}"
|
||||
await Nvim.write(mode_line)
|
||||
@ -1,43 +0,0 @@
|
||||
from os import chmod, stat, stat_result
|
||||
from pathlib import PurePath
|
||||
from stat import S_ISDIR, S_IXGRP, S_IXOTH, S_IXUSR
|
||||
from typing import Iterator, Tuple
|
||||
|
||||
from ..fs.cartographer import act_like_dir
|
||||
from ..registry import rpc
|
||||
from ..state.next import forward
|
||||
from ..state.types import State
|
||||
from .shared.index import indices
|
||||
from .types import Stage
|
||||
|
||||
|
||||
@rpc(blocking=False)
|
||||
async def _toggle_exec(state: State, is_visual: bool) -> Stage:
|
||||
"""
|
||||
Toggle chmod +-x
|
||||
"""
|
||||
|
||||
selected = state.selection or {
|
||||
node.path
|
||||
async for node in indices(state, is_visual=is_visual)
|
||||
if not act_like_dir(node, follow_links=state.follow_links)
|
||||
}
|
||||
|
||||
def cont() -> Iterator[Tuple[PurePath, stat_result]]:
|
||||
for path in selected:
|
||||
try:
|
||||
st = stat(path)
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
else:
|
||||
if not S_ISDIR(st.st_mode):
|
||||
yield path, st
|
||||
|
||||
stats = {path: st for path, st in cont()}
|
||||
|
||||
for path, st in stats.items():
|
||||
chmod(path, st.st_mode ^ S_IXUSR ^ S_IXGRP ^ S_IXOTH)
|
||||
|
||||
invalidate_dirs = {path.parent for path in stats.keys()}
|
||||
new_state = await forward(state, invalidate_dirs=invalidate_dirs)
|
||||
return Stage(state=new_state)
|
||||
@ -1,184 +0,0 @@
|
||||
from dataclasses import dataclass
|
||||
from pathlib import PurePath
|
||||
from subprocess import CalledProcessError
|
||||
from typing import Mapping, Optional, Sequence
|
||||
|
||||
from pynvim_pp.nvim import Nvim
|
||||
from pynvim_pp.rpc_types import ExtData
|
||||
from pynvim_pp.window import Window
|
||||
from std2 import anext
|
||||
from std2.argparse import ArgparseError, ArgParser
|
||||
|
||||
from ..fs.ops import exists, new, which
|
||||
from ..registry import rpc
|
||||
from ..settings.localization import LANG
|
||||
from ..settings.types import Settings
|
||||
from ..state.types import State
|
||||
from ..version_ctl.git import root as version_ctl_toplv
|
||||
from .shared.current import maybe_path_above, new_current_file, new_root
|
||||
from .shared.open_file import open_file
|
||||
from .shared.wm import (
|
||||
find_current_buffer_path,
|
||||
find_fm_buffers,
|
||||
find_fm_windows_in_tab,
|
||||
find_windows_in_tab,
|
||||
new_fm_buffer,
|
||||
new_window,
|
||||
resize_fm_windows,
|
||||
)
|
||||
from .types import ClickType, Stage
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class _Args:
|
||||
path: Optional[PurePath]
|
||||
version_ctl: bool
|
||||
toggle: bool
|
||||
focus: bool
|
||||
|
||||
|
||||
def _parse_args(args: Sequence[str]) -> _Args:
|
||||
parser = ArgParser()
|
||||
parser.add_argument("path", nargs="?", type=PurePath)
|
||||
parser.add_argument("--version-ctl", action="store_true")
|
||||
|
||||
focus_group = parser.add_mutually_exclusive_group()
|
||||
focus_group.add_argument(
|
||||
"--always-focus", dest="toggle", action="store_false", default=True
|
||||
)
|
||||
focus_group.add_argument(
|
||||
"--nofocus", dest="focus", action="store_false", default=True
|
||||
)
|
||||
|
||||
ns = parser.parse_args(args=args)
|
||||
opts = _Args(
|
||||
path=ns.path,
|
||||
version_ctl=ns.version_ctl,
|
||||
toggle=False if ns.version_ctl or ns.path else ns.toggle,
|
||||
focus=ns.focus,
|
||||
)
|
||||
return opts
|
||||
|
||||
|
||||
async def _ensure_side_window(
|
||||
*,
|
||||
settings: Settings,
|
||||
window_order: Mapping[ExtData, None],
|
||||
width: int,
|
||||
window: Window,
|
||||
) -> None:
|
||||
open_left = settings.open_left
|
||||
windows = [
|
||||
win
|
||||
async for win in find_windows_in_tab(last_used=window_order, no_secondary=False)
|
||||
]
|
||||
target = windows[0] if open_left else windows[-1]
|
||||
if window.data != target.data:
|
||||
if open_left:
|
||||
await Nvim.exec("wincmd H")
|
||||
else:
|
||||
await Nvim.exec("wincmd L")
|
||||
await resize_fm_windows(last_used=window_order, width=width)
|
||||
|
||||
|
||||
async def _open_fm_window(
|
||||
settings: Settings,
|
||||
window_order: Mapping[ExtData, None],
|
||||
opts: _Args,
|
||||
width: int,
|
||||
) -> None:
|
||||
cwin = await Window.get_current()
|
||||
win = await anext(find_fm_windows_in_tab(last_used=window_order), None)
|
||||
if win:
|
||||
if opts.toggle:
|
||||
wins = await Window.list()
|
||||
if len(wins) > 1:
|
||||
await win.close()
|
||||
else:
|
||||
await Window.set_current(win)
|
||||
else:
|
||||
buf = await anext(find_fm_buffers(), None)
|
||||
if not buf:
|
||||
buf = await new_fm_buffer(settings=settings)
|
||||
|
||||
win = await new_window(
|
||||
last_used=window_order,
|
||||
win_local=settings.win_actual_opts,
|
||||
open_left=settings.open_left,
|
||||
width=width,
|
||||
)
|
||||
|
||||
await win.set_buf(buf)
|
||||
|
||||
await _ensure_side_window(
|
||||
window=win, settings=settings, window_order=window_order, width=width
|
||||
)
|
||||
if not opts.focus:
|
||||
await Window.set_current(cwin)
|
||||
|
||||
|
||||
@rpc(blocking=False)
|
||||
async def _open(state: State, args: Sequence[str]) -> Optional[Stage]:
|
||||
"""
|
||||
Toggle sidebar
|
||||
"""
|
||||
|
||||
try:
|
||||
opts = _parse_args(args)
|
||||
except ArgparseError as e:
|
||||
await Nvim.write(e, error=True)
|
||||
return None
|
||||
else:
|
||||
if opts.version_ctl:
|
||||
if git := which("git"):
|
||||
try:
|
||||
cwd = await version_ctl_toplv(git, cwd=state.root.path)
|
||||
new_state = await new_root(
|
||||
state=state, new_cwd=cwd, indices=frozenset()
|
||||
)
|
||||
except CalledProcessError:
|
||||
await Nvim.write(LANG("cannot find version ctl root"), error=True)
|
||||
return None
|
||||
else:
|
||||
await Nvim.write(LANG("cannot find version ctl root"), error=True)
|
||||
return None
|
||||
else:
|
||||
new_state = state
|
||||
|
||||
if opts.path:
|
||||
path = (
|
||||
opts.path
|
||||
if opts.path.is_absolute()
|
||||
else await Nvim.getcwd() / opts.path
|
||||
)
|
||||
if not await exists(path, follow=True):
|
||||
await new((path,))
|
||||
next_state = await maybe_path_above(new_state, paths={path}) or new_state
|
||||
await _open_fm_window(
|
||||
state.settings,
|
||||
opts=opts,
|
||||
window_order=new_state.window_order,
|
||||
width=next_state.width,
|
||||
)
|
||||
await open_file(
|
||||
state=state,
|
||||
path=path,
|
||||
click_type=ClickType.primary,
|
||||
)
|
||||
return Stage(next_state, focus=path)
|
||||
else:
|
||||
curr = await find_current_buffer_path()
|
||||
stage = (
|
||||
await new_current_file(state=new_state, current=curr) if curr else None
|
||||
)
|
||||
await _open_fm_window(
|
||||
state.settings,
|
||||
opts=opts,
|
||||
window_order=new_state.window_order,
|
||||
width=new_state.width,
|
||||
)
|
||||
return (
|
||||
Stage(stage.state, focus=curr)
|
||||
if stage
|
||||
else Stage(new_state, focus=curr)
|
||||
)
|
||||
@ -1,78 +0,0 @@
|
||||
from typing import Optional, Union
|
||||
|
||||
from pynvim_pp.nvim import Nvim
|
||||
from std2 import anext
|
||||
from std2.types import Void, VoidType
|
||||
|
||||
from ..registry import rpc
|
||||
from ..settings.localization import LANG
|
||||
from ..state.next import forward
|
||||
from ..state.types import Selection, State
|
||||
from ..version_ctl.types import VCStatus
|
||||
from .shared.index import indices
|
||||
from .types import Stage
|
||||
|
||||
|
||||
@rpc(blocking=False)
|
||||
async def _toggle_hidden(state: State, is_visual: bool) -> Optional[Stage]:
|
||||
"""
|
||||
Toggle hidden
|
||||
"""
|
||||
|
||||
node = await anext(indices(state, is_visual=is_visual))
|
||||
if not node:
|
||||
return None
|
||||
else:
|
||||
focus = node.path
|
||||
show_hidden = not state.show_hidden
|
||||
selection: Selection = state.selection if show_hidden else frozenset()
|
||||
new_state = await forward(state, show_hidden=show_hidden, selection=selection)
|
||||
return Stage(new_state, focus=focus)
|
||||
|
||||
|
||||
@rpc(blocking=False)
|
||||
async def _toggle_follow(state: State, is_visual: bool) -> Stage:
|
||||
"""
|
||||
Toggle follow
|
||||
"""
|
||||
|
||||
new_state = await forward(state, follow=not state.follow)
|
||||
await Nvim.write(LANG("follow_mode_indi", follow=str(new_state.follow)))
|
||||
return Stage(new_state)
|
||||
|
||||
|
||||
@rpc(blocking=False)
|
||||
async def _toggle_follow_links(state: State, is_visual: bool) -> Stage:
|
||||
"""
|
||||
Toggle --follow
|
||||
"""
|
||||
|
||||
follow_links = not state.follow_links
|
||||
new_state = await forward(state, follow_links=follow_links)
|
||||
await Nvim.write(LANG("follow_links_indi", follow=str(new_state.follow_links)))
|
||||
return Stage(new_state)
|
||||
|
||||
|
||||
@rpc(blocking=False)
|
||||
async def _toggle_follow_ignore(state: State, is_visual: bool) -> Stage:
|
||||
"""
|
||||
Toggle --follow
|
||||
"""
|
||||
|
||||
follow_links = not state.follow_links
|
||||
new_state = await forward(state, follow_links=follow_links)
|
||||
await Nvim.write(LANG("follow_ignore_indi", follow=str(new_state.follow_links)))
|
||||
return Stage(new_state)
|
||||
|
||||
|
||||
@rpc(blocking=False)
|
||||
async def _toggle_version_control(state: State, is_visual: bool) -> Stage:
|
||||
"""
|
||||
Toggle version control
|
||||
"""
|
||||
|
||||
enable_vc = not state.enable_vc
|
||||
vc: Union[VoidType, VCStatus] = Void if enable_vc else VCStatus()
|
||||
new_state = await forward(state, enable_vc=enable_vc, vc=vc)
|
||||
await Nvim.write(LANG("version_control_indi", enable_vc=str(new_state.enable_vc)))
|
||||
return Stage(new_state)
|
||||
@ -1,20 +0,0 @@
|
||||
from dataclasses import dataclass
|
||||
from enum import Enum, auto
|
||||
from pathlib import PurePath
|
||||
from typing import Optional
|
||||
|
||||
from ..state.types import State
|
||||
|
||||
|
||||
class ClickType(Enum):
|
||||
primary = auto()
|
||||
secondary = auto()
|
||||
tertiary = auto()
|
||||
v_split = auto()
|
||||
h_split = auto()
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Stage:
|
||||
state: State
|
||||
focus: Optional[PurePath] = None
|
||||
@ -1,189 +0,0 @@
|
||||
from asyncio import gather
|
||||
from functools import lru_cache
|
||||
from itertools import chain
|
||||
from locale import strxfrm
|
||||
from os import linesep
|
||||
from os.path import normpath
|
||||
from pathlib import PurePath
|
||||
from string import whitespace
|
||||
from subprocess import CalledProcessError
|
||||
from typing import (
|
||||
Iterable,
|
||||
Iterator,
|
||||
MutableMapping,
|
||||
MutableSequence,
|
||||
MutableSet,
|
||||
Sequence,
|
||||
Tuple,
|
||||
)
|
||||
|
||||
from std2.asyncio import to_thread
|
||||
from std2.pathlib import ROOT
|
||||
from std2.string import removeprefix, removesuffix
|
||||
|
||||
from ..fs.ops import ancestors, which
|
||||
from .nice import nice_call
|
||||
from .types import VCStatus
|
||||
|
||||
_Stats = Iterable[Tuple[str, PurePath]]
|
||||
|
||||
_WHITE_SPACES = {*whitespace}
|
||||
_GIT_LIST_CMD = (
|
||||
"--no-optional-locks",
|
||||
"status",
|
||||
"--ignored",
|
||||
"--renames",
|
||||
"--porcelain",
|
||||
"-z",
|
||||
)
|
||||
|
||||
|
||||
_GIT_SUBMODULE_MARKER = "Entering "
|
||||
_SUBMODULE_MARKER = "S"
|
||||
_IGNORED_MARKER = "I"
|
||||
_UNTRACKED_MARKER = "?"
|
||||
|
||||
|
||||
async def root(git: PurePath, cwd: PurePath) -> PurePath:
|
||||
stdout = await nice_call(
|
||||
(
|
||||
git,
|
||||
"--no-optional-locks",
|
||||
"rev-parse",
|
||||
"--path-format=relative",
|
||||
"--show-toplevel",
|
||||
),
|
||||
cwd=cwd,
|
||||
)
|
||||
return PurePath(normpath(cwd / stdout.rstrip()))
|
||||
|
||||
|
||||
@lru_cache(maxsize=1)
|
||||
def _parse_stats_main(stdout: str) -> Sequence[Tuple[str, PurePath]]:
|
||||
def cont() -> Iterator[Tuple[str, PurePath]]:
|
||||
it = iter(stdout.split("\0"))
|
||||
for line in it:
|
||||
prefix, file = line[:2], line[3:]
|
||||
yield prefix, PurePath(file)
|
||||
|
||||
if "R" in prefix:
|
||||
next(it, None)
|
||||
|
||||
return tuple(cont())
|
||||
|
||||
|
||||
async def _stat_main(git: PurePath, cwd: PurePath) -> str:
|
||||
stdout = await nice_call((git, *_GIT_LIST_CMD), cwd=cwd)
|
||||
return stdout
|
||||
|
||||
|
||||
@lru_cache(maxsize=1)
|
||||
def _parse_sub_modules(stdout: str) -> Sequence[Tuple[str, PurePath]]:
|
||||
def cont() -> Iterator[Tuple[str, PurePath]]:
|
||||
it = iter(stdout)
|
||||
sub_module = ROOT
|
||||
acc: MutableSequence[str] = []
|
||||
|
||||
for char in it:
|
||||
if char == linesep:
|
||||
line = "".join(acc)
|
||||
acc.clear()
|
||||
|
||||
if not line.startswith(_GIT_SUBMODULE_MARKER):
|
||||
raise ValueError(stdout)
|
||||
else:
|
||||
quoted = removeprefix(line, prefix=_GIT_SUBMODULE_MARKER)
|
||||
if not (quoted.startswith("'") and quoted.endswith("'")):
|
||||
raise ValueError(stdout)
|
||||
else:
|
||||
sub_module = PurePath(
|
||||
removesuffix(removeprefix(quoted, prefix="'"), suffix="'")
|
||||
)
|
||||
yield _SUBMODULE_MARKER, sub_module
|
||||
|
||||
elif char == "\0":
|
||||
line = "".join(acc)
|
||||
acc.clear()
|
||||
|
||||
if not sub_module:
|
||||
raise ValueError(stdout)
|
||||
else:
|
||||
prefix, file = line[:2], line[3:]
|
||||
yield prefix, sub_module / file
|
||||
|
||||
if "R" in prefix:
|
||||
next(it, None)
|
||||
else:
|
||||
acc.append(char)
|
||||
|
||||
return tuple(cont())
|
||||
|
||||
|
||||
async def _stat_sub_modules(git: PurePath, cwd: PurePath) -> str:
|
||||
stdout = await nice_call(
|
||||
(
|
||||
git,
|
||||
"--no-optional-locks",
|
||||
"submodule",
|
||||
"foreach",
|
||||
"--recursive",
|
||||
git,
|
||||
*_GIT_LIST_CMD,
|
||||
),
|
||||
cwd=cwd,
|
||||
)
|
||||
return stdout
|
||||
|
||||
|
||||
def _stat_name(stat: str) -> str:
|
||||
markers = {
|
||||
"!!": _IGNORED_MARKER,
|
||||
"??": _UNTRACKED_MARKER,
|
||||
}
|
||||
return markers.get(stat, stat)
|
||||
|
||||
|
||||
def _parse(root: PurePath, stats: _Stats) -> VCStatus:
|
||||
above = ancestors(root)
|
||||
ignored: MutableSet[PurePath] = set()
|
||||
status: MutableMapping[PurePath, str] = {}
|
||||
directories: MutableMapping[PurePath, MutableSet[str]] = {}
|
||||
|
||||
for stat, name in stats:
|
||||
path = root / name
|
||||
status[path] = _stat_name(stat)
|
||||
if "!" in stat:
|
||||
ignored.add(path)
|
||||
else:
|
||||
for ancestor in ancestors(path):
|
||||
parents = directories.setdefault(ancestor, set())
|
||||
if stat != _SUBMODULE_MARKER:
|
||||
for sym in stat:
|
||||
parents.add(sym)
|
||||
|
||||
for directory, syms in directories.items():
|
||||
pre_existing = {*status.get(directory, "")}
|
||||
symbols = pre_existing | syms - _WHITE_SPACES
|
||||
consoildated = sorted(symbols, key=strxfrm)
|
||||
status[directory] = "".join(consoildated)
|
||||
|
||||
trimmed = {path: stat for path, stat in status.items() if path not in above}
|
||||
return VCStatus(ignored=ignored, status=trimmed)
|
||||
|
||||
|
||||
async def status(cwd: PurePath, prev: VCStatus) -> VCStatus:
|
||||
if git := which("git"):
|
||||
bin = PurePath(git)
|
||||
try:
|
||||
raw_root, main, submodules = await gather(
|
||||
root(bin, cwd=cwd),
|
||||
_stat_main(bin, cwd=cwd),
|
||||
_stat_sub_modules(bin, cwd=cwd),
|
||||
)
|
||||
stats = chain((_parse_stats_main(main)), _parse_sub_modules(submodules))
|
||||
except CalledProcessError:
|
||||
return VCStatus()
|
||||
else:
|
||||
return await to_thread(lambda: _parse(raw_root, stats=stats))
|
||||
else:
|
||||
return VCStatus()
|
||||
@ -1,42 +0,0 @@
|
||||
import sys
|
||||
from contextlib import suppress
|
||||
from os import environ
|
||||
from pathlib import PurePath
|
||||
from typing import Optional, Sequence
|
||||
|
||||
from pynvim_pp.lib import decode
|
||||
from std2.asyncio.subprocess import call
|
||||
from std2.pathlib import AnyPath
|
||||
|
||||
if sys.platform == "win32":
|
||||
from subprocess import BELOW_NORMAL_PRIORITY_CLASS
|
||||
|
||||
nice = lambda _: None
|
||||
else:
|
||||
from os import nice
|
||||
|
||||
BELOW_NORMAL_PRIORITY_CLASS = 0
|
||||
|
||||
|
||||
_ENV = {**environ, "LC_ALL": "C"}
|
||||
|
||||
|
||||
def _nice() -> None:
|
||||
with suppress(PermissionError):
|
||||
nice(19)
|
||||
|
||||
|
||||
async def nice_call(
|
||||
argv: Sequence[AnyPath],
|
||||
stdin: Optional[bytes] = None,
|
||||
cwd: Optional[PurePath] = None,
|
||||
) -> str:
|
||||
proc = await call(
|
||||
*argv,
|
||||
cwd=cwd,
|
||||
stdin=stdin,
|
||||
env=_ENV,
|
||||
preexec_fn=_nice,
|
||||
creationflags=BELOW_NORMAL_PRIORITY_CLASS,
|
||||
)
|
||||
return decode(proc.stdout)
|
||||
@ -1,12 +0,0 @@
|
||||
from dataclasses import dataclass, field
|
||||
from pathlib import PurePath
|
||||
from typing import AbstractSet, Mapping, MutableMapping
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class VCStatus:
|
||||
main: str = ""
|
||||
submodules: str = ""
|
||||
ignored: AbstractSet[PurePath] = frozenset()
|
||||
status: Mapping[PurePath, str] = field(default_factory=dict)
|
||||
ignore_cache: MutableMapping[PurePath, bool] = field(default_factory=dict)
|
||||
@ -1,27 +0,0 @@
|
||||
from typing import Iterator, Mapping, Tuple
|
||||
from uuid import uuid4
|
||||
|
||||
from pynvim_pp.highlight import HLgroup
|
||||
|
||||
from ..consts import FM_HL_PREFIX
|
||||
|
||||
LEGAL_CTERM = {
|
||||
"bold",
|
||||
"underline",
|
||||
"undercurl",
|
||||
"strikethrough",
|
||||
"reverse",
|
||||
"italic",
|
||||
"standout",
|
||||
}
|
||||
|
||||
LEGAL_CTERM_COLOURS = range(8)
|
||||
|
||||
|
||||
def gen_hl(name_prefix: str, mapping: Mapping[str, str]) -> Mapping[str, HLgroup]:
|
||||
def cont() -> Iterator[Tuple[str, HLgroup]]:
|
||||
for key, val in mapping.items():
|
||||
name = f"{FM_HL_PREFIX}_{name_prefix}_{uuid4().hex}"
|
||||
yield key, HLgroup(name=name, guifg=val)
|
||||
|
||||
return {k: v for k, v in cont()}
|
||||
@ -1,118 +0,0 @@
|
||||
from itertools import chain
|
||||
from os import environ
|
||||
from typing import Mapping, Tuple, TypeVar, Union
|
||||
|
||||
from pynvim_pp.highlight import HLgroup
|
||||
from std2.types import never
|
||||
|
||||
from chad_types import (
|
||||
Artifact,
|
||||
IconColourSetEnum,
|
||||
IconGlyphs,
|
||||
IconGlyphSetEnum,
|
||||
LSColoursEnum,
|
||||
TextColourSetEnum,
|
||||
)
|
||||
|
||||
from ..consts import FM_HL_PREFIX
|
||||
from .highlight import gen_hl
|
||||
from .ls_colours import parse_lsc
|
||||
from .types import HLcontext, HLGroups
|
||||
|
||||
T = TypeVar("T")
|
||||
|
||||
|
||||
def _trans(mapping: Mapping[T, HLgroup]) -> Mapping[T, str]:
|
||||
return {k: v.name for k, v in mapping.items()}
|
||||
|
||||
|
||||
def load_theme(
|
||||
artifact: Artifact,
|
||||
particular_mappings: HLGroups,
|
||||
discrete_colours: Mapping[str, str],
|
||||
icon_set: IconGlyphSetEnum,
|
||||
icon_colour_set: IconColourSetEnum,
|
||||
text_colour_set: Union[LSColoursEnum, TextColourSetEnum],
|
||||
) -> Tuple[IconGlyphs, HLcontext]:
|
||||
if icon_set is IconGlyphSetEnum.ascii:
|
||||
icons = artifact.icons.ascii
|
||||
elif icon_set is IconGlyphSetEnum.ascii_hollow:
|
||||
icons = artifact.icons.ascii_hollow
|
||||
elif icon_set is IconGlyphSetEnum.devicons:
|
||||
icons = artifact.icons.devicons
|
||||
elif icon_set is IconGlyphSetEnum.emoji:
|
||||
icons = artifact.icons.emoji
|
||||
else:
|
||||
never(icon_set)
|
||||
|
||||
if text_colour_set is LSColoursEnum.env and "LS_COLORS" not in environ:
|
||||
text_colour_set = LSColoursEnum.solarized_dark_256
|
||||
|
||||
if isinstance(text_colour_set, LSColoursEnum):
|
||||
if text_colour_set is LSColoursEnum.env:
|
||||
_lsc = environ.get("LS_COLORS", "")
|
||||
elif text_colour_set is LSColoursEnum.solarized_dark_256:
|
||||
_lsc = artifact.ls_colours.solarized_dark_256
|
||||
elif text_colour_set is LSColoursEnum.solarized_light:
|
||||
_lsc = artifact.ls_colours.solarized_light
|
||||
elif text_colour_set is LSColoursEnum.solarized_dark:
|
||||
_lsc = artifact.ls_colours.solarized_dark
|
||||
elif text_colour_set is LSColoursEnum.solarized_universal:
|
||||
_lsc = artifact.ls_colours.solarized_universal
|
||||
elif text_colour_set is LSColoursEnum.nord:
|
||||
_lsc = artifact.ls_colours.nord
|
||||
elif text_colour_set is LSColoursEnum.trapdoor:
|
||||
_lsc = artifact.ls_colours.trapdoor
|
||||
else:
|
||||
never(text_colour_set)
|
||||
|
||||
lsc = parse_lsc(_lsc, discrete_colours=discrete_colours)
|
||||
mode_pre = lsc.mode_pre
|
||||
mode_post = lsc.mode_post
|
||||
ext_exact = lsc.exts
|
||||
name_exact: Mapping[str, HLgroup] = {}
|
||||
name_glob = lsc.name_glob
|
||||
else:
|
||||
if text_colour_set is TextColourSetEnum.nerdtree_syntax_light:
|
||||
text_colour = artifact.text_colours.nerdtree_syntax_light
|
||||
elif text_colour_set is TextColourSetEnum.nerdtree_syntax_dark:
|
||||
text_colour = artifact.text_colours.nerdtree_syntax_dark
|
||||
else:
|
||||
never(text_colour_set)
|
||||
|
||||
mode_pre = {}
|
||||
mode_post = {}
|
||||
ext_exact = gen_hl(FM_HL_PREFIX, mapping=text_colour.ext_exact)
|
||||
name_exact = gen_hl(FM_HL_PREFIX, mapping=text_colour.name_exact)
|
||||
name_glob = gen_hl(FM_HL_PREFIX, mapping=text_colour.name_glob)
|
||||
|
||||
if icon_colour_set is IconColourSetEnum.github:
|
||||
icon_exts = gen_hl(FM_HL_PREFIX, mapping=artifact.icon_colours.github)
|
||||
elif icon_colour_set is IconColourSetEnum.none:
|
||||
icon_exts = gen_hl(FM_HL_PREFIX, mapping={})
|
||||
else:
|
||||
never(icon_colour_set)
|
||||
|
||||
groups = tuple(
|
||||
chain(
|
||||
icon_exts.values(),
|
||||
mode_pre.values(),
|
||||
mode_post.values(),
|
||||
ext_exact.values(),
|
||||
name_exact.values(),
|
||||
name_glob.values(),
|
||||
),
|
||||
)
|
||||
|
||||
context = HLcontext(
|
||||
groups=groups,
|
||||
icon_exts=_trans(icon_exts),
|
||||
mode_pre=_trans(mode_pre),
|
||||
mode_post=_trans(mode_post),
|
||||
ext_exact=_trans(ext_exact),
|
||||
name_exact=_trans(name_exact),
|
||||
name_glob=_trans(name_glob),
|
||||
particular_mappings=particular_mappings,
|
||||
)
|
||||
|
||||
return icons, context
|
||||
@ -1,303 +0,0 @@
|
||||
from dataclasses import dataclass
|
||||
from enum import Enum, IntEnum, auto
|
||||
from itertools import chain, repeat
|
||||
from typing import (
|
||||
AbstractSet,
|
||||
Callable,
|
||||
Iterator,
|
||||
Mapping,
|
||||
MutableMapping,
|
||||
MutableSet,
|
||||
Optional,
|
||||
Tuple,
|
||||
Union,
|
||||
)
|
||||
from uuid import uuid4
|
||||
|
||||
from pynvim_pp.highlight import HLgroup
|
||||
from std2.coloursys import rgb_to_hex
|
||||
|
||||
from ..consts import FM_HL_PREFIX
|
||||
from ..fs.types import Mode
|
||||
|
||||
|
||||
class _Style(IntEnum):
|
||||
bold = auto()
|
||||
dimmed = auto()
|
||||
italic = auto()
|
||||
underline = auto()
|
||||
blink = auto()
|
||||
blink_fast = auto()
|
||||
reverse = auto()
|
||||
hidden = auto()
|
||||
strikethrough = auto()
|
||||
|
||||
|
||||
class _Ground(Enum):
|
||||
fore = auto()
|
||||
back = auto()
|
||||
|
||||
|
||||
class _AnsiColour(IntEnum):
|
||||
black = auto()
|
||||
red = auto()
|
||||
green = auto()
|
||||
yellow = auto()
|
||||
blue = auto()
|
||||
magenta = auto()
|
||||
cyan = auto()
|
||||
white = auto()
|
||||
|
||||
bright_black = auto()
|
||||
bright_red = auto()
|
||||
bright_green = auto()
|
||||
bright_yellow = auto()
|
||||
bright_blue = auto()
|
||||
bright_magenta = auto()
|
||||
bright_cyan = auto()
|
||||
bright_white = auto()
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class _Colour:
|
||||
r: int
|
||||
g: int
|
||||
b: int
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class _Styling:
|
||||
styles: AbstractSet[_Style]
|
||||
foreground: Union[_AnsiColour, _Colour, None]
|
||||
background: Union[_AnsiColour, _Colour, None]
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class LSC:
|
||||
mode_pre: Mapping[Mode, HLgroup]
|
||||
mode_post: Mapping[Optional[Mode], HLgroup]
|
||||
exts: Mapping[str, HLgroup]
|
||||
name_glob: Mapping[str, HLgroup]
|
||||
|
||||
|
||||
_ANSI_RANGE = range(256)
|
||||
_RGB_RANGE = range(256)
|
||||
|
||||
_STYLE_TABLE: Mapping[str, _Style] = {str(code + 0): code for code in _Style}
|
||||
|
||||
_GROUND_TABLE: Mapping[str, _Ground] = {
|
||||
str(code): ground
|
||||
for code, ground in chain(
|
||||
zip(chain(range(30, 39), range(90, 98)), repeat(_Ground.fore)),
|
||||
zip(chain(range(40, 49), range(100, 108)), repeat(_Ground.back)),
|
||||
)
|
||||
}
|
||||
|
||||
_COLOUR_TABLE: Mapping[str, _AnsiColour] = {
|
||||
str(code): colour
|
||||
for code, colour in chain(
|
||||
((c + 29 if c <= 8 else c + 31, c) for c in _AnsiColour),
|
||||
((c + 89 if c <= 8 else c + 91, c) for c in _AnsiColour),
|
||||
)
|
||||
}
|
||||
|
||||
_RGB_TABLE: AbstractSet[str] = {"38", "48"}
|
||||
|
||||
_E_BASIC_TABLE: Mapping[int, _AnsiColour] = {i: c for i, c in enumerate(_AnsiColour)}
|
||||
|
||||
_E_GREY_TABLE: Mapping[int, _Colour] = {
|
||||
i: _Colour(r=s, g=s, b=s)
|
||||
for i, s in enumerate((round(step / 23 * 255) for step in range(24)), 232)
|
||||
}
|
||||
|
||||
|
||||
def _parse_8(codes: Iterator[str]) -> Union[_AnsiColour, _Colour, None]:
|
||||
try:
|
||||
ansi_code = int(next(codes, ""))
|
||||
except ValueError:
|
||||
return None
|
||||
else:
|
||||
if ansi_code in _ANSI_RANGE:
|
||||
basic = _E_BASIC_TABLE.get(ansi_code)
|
||||
if basic:
|
||||
return basic
|
||||
grey = _E_GREY_TABLE.get(ansi_code)
|
||||
if grey:
|
||||
return grey
|
||||
ratio = 255 / 5
|
||||
code = ansi_code - 16
|
||||
r = code // 36
|
||||
g = code % 36 // 6
|
||||
b = code % 36 % 6
|
||||
return _Colour(r=round(r * ratio), g=round(g * ratio), b=round(b * ratio))
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def _parse_24(codes: Iterator[str]) -> Optional[_Colour]:
|
||||
try:
|
||||
r, g, b = int(next(codes, "")), int(next(codes, "")), int(next(codes, ""))
|
||||
except ValueError:
|
||||
return None
|
||||
else:
|
||||
if r in _RGB_RANGE and g in _RGB_RANGE and b in _RGB_RANGE:
|
||||
return _Colour(r=r, g=g, b=b)
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
_PARSE_TABLE: Mapping[
|
||||
str, Callable[[Iterator[str]], Union[_AnsiColour, _Colour, None]]
|
||||
] = {
|
||||
"5": _parse_8,
|
||||
"2": _parse_24,
|
||||
}
|
||||
|
||||
|
||||
_SPECIAL_PRE_TABLE: Mapping[str, Mode] = {
|
||||
"bd": Mode.block_device,
|
||||
"ca": Mode.file_w_capacity,
|
||||
"cd": Mode.char_device,
|
||||
"di": Mode.folder,
|
||||
"do": Mode.door,
|
||||
"ex": Mode.executable,
|
||||
"ln": Mode.link,
|
||||
"mh": Mode.multi_hardlink,
|
||||
"or": Mode.orphan_link,
|
||||
"ow": Mode.other_writable,
|
||||
"pi": Mode.pipe,
|
||||
"sg": Mode.set_gid,
|
||||
"so": Mode.socket,
|
||||
"st": Mode.sticky,
|
||||
"su": Mode.set_uid,
|
||||
"tw": Mode.sticky_other_writable,
|
||||
}
|
||||
|
||||
|
||||
_SPECIAL_POST_TABLE: Mapping[str, Optional[Mode]] = {
|
||||
"fi": Mode.file,
|
||||
"no": None,
|
||||
}
|
||||
|
||||
_UNUSED = {
|
||||
"mi": "colour of missing symlink pointee",
|
||||
"cl": "ANSI clear",
|
||||
"ec": "ANSI end_code",
|
||||
"lc": "ANSI left_code",
|
||||
"rc": "ANSI right_code",
|
||||
"rs": "ANSI reset",
|
||||
}
|
||||
|
||||
assert _UNUSED
|
||||
|
||||
|
||||
_HL_STYLE_TABLE: Mapping[_Style, Optional[str]] = {
|
||||
_Style.bold: "bold",
|
||||
_Style.dimmed: None,
|
||||
_Style.italic: "italic",
|
||||
_Style.underline: "underline",
|
||||
_Style.blink: None,
|
||||
_Style.blink_fast: None,
|
||||
_Style.reverse: "reverse",
|
||||
_Style.hidden: None,
|
||||
_Style.strikethrough: "strikethrough",
|
||||
}
|
||||
|
||||
|
||||
def _parse_codes(
|
||||
codes: str,
|
||||
) -> Iterator[Union[_Style, Tuple[_Ground, Union[_AnsiColour, _Colour]]]]:
|
||||
it = (code.lstrip("0") for code in codes.split(";"))
|
||||
for code in it:
|
||||
style = _STYLE_TABLE.get(code)
|
||||
if style:
|
||||
yield style
|
||||
continue
|
||||
ground = _GROUND_TABLE.get(code)
|
||||
ansi_colour = _COLOUR_TABLE.get(code)
|
||||
if ground and ansi_colour:
|
||||
yield ground, ansi_colour
|
||||
elif ground and code in _RGB_TABLE:
|
||||
code = next(it, "")
|
||||
parse = _PARSE_TABLE.get(code)
|
||||
if parse:
|
||||
colour = parse(it)
|
||||
if colour:
|
||||
yield ground, colour
|
||||
|
||||
|
||||
def _parse_styling(codes: str) -> _Styling:
|
||||
styles: MutableSet[_Style] = set()
|
||||
colours: MutableMapping[_Ground, Union[_AnsiColour, _Colour]] = {}
|
||||
for ret in _parse_codes(codes):
|
||||
if isinstance(ret, _Style):
|
||||
styles.add(ret)
|
||||
elif isinstance(ret, tuple):
|
||||
ground, colour = ret
|
||||
colours[ground] = colour
|
||||
|
||||
styling = _Styling(
|
||||
styles=styles,
|
||||
foreground=colours.get(_Ground.fore),
|
||||
background=colours.get(_Ground.back),
|
||||
)
|
||||
return styling
|
||||
|
||||
|
||||
def _parseHLGroup(styling: _Styling, discrete_colours: Mapping[str, str]) -> HLgroup:
|
||||
fg, bg = styling.foreground, styling.background
|
||||
name = f"{FM_HL_PREFIX}_ls_{uuid4().hex}"
|
||||
cterm = {
|
||||
style
|
||||
for style in (_HL_STYLE_TABLE.get(style) for style in styling.styles)
|
||||
if style
|
||||
}
|
||||
ctermfg = fg.value - 1 if isinstance(fg, _AnsiColour) else None
|
||||
ctermbg = bg.value - 1 if isinstance(bg, _AnsiColour) else None
|
||||
guifg = (
|
||||
rgb_to_hex(fg.r, fg.g, fg.b)
|
||||
if isinstance(fg, _Colour)
|
||||
else (discrete_colours.get(fg.name) if isinstance(fg, _AnsiColour) else None)
|
||||
)
|
||||
guibg = (
|
||||
rgb_to_hex(bg.r, bg.g, bg.b)
|
||||
if isinstance(bg, _Colour)
|
||||
else (discrete_colours.get(bg.name) if isinstance(bg, _AnsiColour) else None)
|
||||
)
|
||||
group = HLgroup(
|
||||
name=name,
|
||||
cterm=cterm,
|
||||
ctermfg=ctermfg,
|
||||
ctermbg=ctermbg,
|
||||
guifg=guifg,
|
||||
guibg=guibg,
|
||||
)
|
||||
return group
|
||||
|
||||
|
||||
def parse_lsc(ls_colours: str, discrete_colours: Mapping[str, str]) -> LSC:
|
||||
hl_lookup = {
|
||||
key: _parseHLGroup(_parse_styling(val), discrete_colours=discrete_colours)
|
||||
for key, _, val in (
|
||||
segment.partition("=") for segment in ls_colours.strip(":").split(":")
|
||||
)
|
||||
}
|
||||
|
||||
mode_pre = {
|
||||
mode: hl
|
||||
for indicator, mode in _SPECIAL_PRE_TABLE.items()
|
||||
if (hl := hl_lookup.pop(indicator, None))
|
||||
}
|
||||
mode_post = {
|
||||
mode: hl
|
||||
for indicator, mode in _SPECIAL_POST_TABLE.items()
|
||||
if (hl := hl_lookup.pop(indicator, None))
|
||||
}
|
||||
|
||||
_ext_keys = tuple(
|
||||
key for key in hl_lookup if key.startswith("*.") and key.count(".") == 1
|
||||
)
|
||||
exts = {key[1:]: hl_lookup.pop(key) for key in _ext_keys}
|
||||
|
||||
lsc = LSC(exts=exts, mode_pre=mode_pre, mode_post=mode_post, name_glob=hl_lookup)
|
||||
return lsc
|
||||
@ -1,25 +0,0 @@
|
||||
from os import sep
|
||||
from os.path import relpath
|
||||
from pathlib import Path, PurePath
|
||||
from string import whitespace
|
||||
|
||||
from ..state.types import State
|
||||
|
||||
_WS = {*whitespace} - {"\t"}
|
||||
|
||||
|
||||
def encode_for_display(text: str) -> str:
|
||||
encoded = "".join(
|
||||
char.encode("unicode_escape").decode("utf-8") if char in _WS else char
|
||||
for char in text
|
||||
)
|
||||
return encoded
|
||||
|
||||
|
||||
def display_path(path: PurePath, state: State) -> str:
|
||||
raw = relpath(path, start=state.root.path)
|
||||
name = encode_for_display(raw)
|
||||
if Path(path).is_dir():
|
||||
return f"{name}{sep}"
|
||||
else:
|
||||
return name
|
||||
@ -1,345 +0,0 @@
|
||||
from collections import UserString
|
||||
from enum import IntEnum, auto
|
||||
from fnmatch import fnmatch
|
||||
from functools import lru_cache
|
||||
from locale import strxfrm
|
||||
from os.path import extsep, sep
|
||||
from pathlib import PurePath
|
||||
from typing import Any, Callable, Iterator, Optional, Sequence, Tuple, Union, cast
|
||||
|
||||
from pynvim_pp.lib import encode
|
||||
from std2.platform import OS, os
|
||||
from std2.types import never
|
||||
|
||||
from ..fs.cartographer import is_dir, user_ignored
|
||||
from ..fs.types import Mode, Node
|
||||
from ..nvim.types import Markers
|
||||
from ..settings.types import Settings
|
||||
from ..state.types import Diagnostics, FilterPattern, Index, Selection
|
||||
from ..version_ctl.types import VCStatus
|
||||
from .ops import encode_for_display
|
||||
from .types import Badge, Derived, Highlight, Sortby
|
||||
|
||||
|
||||
class _CompVals(IntEnum):
|
||||
FOLDER = auto()
|
||||
FILE = auto()
|
||||
|
||||
|
||||
_Str = Union[str, UserString]
|
||||
_Render = Tuple[str, Sequence[Highlight], Sequence[Badge]]
|
||||
_NRender = Tuple[Node, str, Sequence[Highlight], Sequence[Badge]]
|
||||
|
||||
|
||||
class _str(UserString):
|
||||
def __lt__(self, _: _Str) -> bool:
|
||||
return False
|
||||
|
||||
def __gt__(self, _: _Str) -> bool:
|
||||
return True
|
||||
|
||||
|
||||
_EMPTY = _str("")
|
||||
|
||||
|
||||
def _suffixx(path: PurePath) -> _Str:
|
||||
if path.suffix:
|
||||
return strxfrm(path.suffix)
|
||||
elif path.stem.startswith(extsep):
|
||||
return strxfrm(path.stem)
|
||||
else:
|
||||
return _EMPTY
|
||||
|
||||
|
||||
def _lax_suffix(path: PurePath) -> str:
|
||||
return path.suffix or path.name
|
||||
|
||||
|
||||
@lru_cache(maxsize=None)
|
||||
def _gen_comp(sortby: Sequence[Sortby]) -> Callable[[Node], Any]:
|
||||
def comp(node: Node) -> Sequence[Any]:
|
||||
if node.cache.sort_by is None:
|
||||
|
||||
def cont() -> Iterator[Any]:
|
||||
for sb in sortby:
|
||||
if sb is Sortby.is_folder:
|
||||
yield _CompVals.FOLDER if is_dir(node) else _CompVals.FILE
|
||||
elif sb is Sortby.ext:
|
||||
yield "" if is_dir(node) else _suffixx(node.path)
|
||||
elif sb is Sortby.file_name_lower:
|
||||
yield strxfrm(node.path.name.casefold())
|
||||
elif sb is Sortby.file_name:
|
||||
yield strxfrm(node.path.name)
|
||||
else:
|
||||
never(sb)
|
||||
|
||||
node.cache.sort_by = tuple(cont())
|
||||
return node.cache.sort_by
|
||||
|
||||
return comp
|
||||
|
||||
|
||||
def _vc_ignored(node: Node, vc: VCStatus) -> bool:
|
||||
path = node.path
|
||||
if (ignored := vc.ignore_cache.get(path, None)) is not None:
|
||||
return ignored
|
||||
else:
|
||||
ignored = not vc.ignored.isdisjoint({path} | {*map(PurePath, path.parents)})
|
||||
vc.ignore_cache[path] = ignored
|
||||
return ignored
|
||||
|
||||
|
||||
def _gen_spacer(depth: int) -> str:
|
||||
return (depth * 2 - 1) * " "
|
||||
|
||||
|
||||
def _paint(
|
||||
settings: Settings,
|
||||
index: Index,
|
||||
selection: Selection,
|
||||
markers: Markers,
|
||||
diagnostics: Diagnostics,
|
||||
vc: VCStatus,
|
||||
follow_links: bool,
|
||||
show_hidden: bool,
|
||||
current: Optional[PurePath],
|
||||
) -> Callable[[Node, int], Optional[_Render]]:
|
||||
icons = settings.view.icons
|
||||
context = settings.view.hl_context
|
||||
|
||||
def search_icon_hl(node: Node, ignored: bool) -> Optional[str]:
|
||||
if ignored:
|
||||
return context.particular_mappings.ignored
|
||||
else:
|
||||
return context.icon_exts.get(_lax_suffix(node.path))
|
||||
|
||||
def search_text_hl(node: Node, ignored: bool) -> Optional[str]:
|
||||
if ignored:
|
||||
return context.particular_mappings.ignored
|
||||
|
||||
s_modes = sorted(node.mode)
|
||||
for mode in s_modes:
|
||||
if os is OS.windows and mode is Mode.other_writable:
|
||||
pass
|
||||
elif hl := context.mode_pre.get(mode):
|
||||
return hl
|
||||
|
||||
if hl := context.name_exact.get(node.path.name):
|
||||
return hl
|
||||
|
||||
for pattern, hl in context.name_glob.items():
|
||||
if fnmatch(node.path.name, pattern):
|
||||
return hl
|
||||
|
||||
if hl := context.ext_exact.get(_lax_suffix(node.path)):
|
||||
return hl
|
||||
|
||||
for mode in s_modes:
|
||||
if hl := context.mode_post.get(mode):
|
||||
return hl
|
||||
else:
|
||||
return context.mode_post.get(None)
|
||||
|
||||
def gen_status(path: PurePath) -> str:
|
||||
selected = (
|
||||
icons.status.selected if path in selection else icons.status.not_selected
|
||||
)
|
||||
active = icons.status.active if path == current else icons.status.inactive
|
||||
return f"{selected}{active}"
|
||||
|
||||
def gen_decor_pre(node: Node, depth: int) -> Iterator[str]:
|
||||
yield _gen_spacer(depth)
|
||||
yield gen_status(node.path)
|
||||
|
||||
def gen_icon(node: Node) -> Iterator[str]:
|
||||
yield " "
|
||||
if is_dir(node):
|
||||
if node.pointed and not follow_links:
|
||||
yield icons.link.normal
|
||||
elif node.path in index:
|
||||
yield icons.folder.open
|
||||
else:
|
||||
yield icons.folder.closed
|
||||
else:
|
||||
yield (
|
||||
(
|
||||
icons.name_exact.get(node.path.name, "")
|
||||
or icons.ext_exact.get(_lax_suffix(node.path), "")
|
||||
or next(
|
||||
(
|
||||
v
|
||||
for k, v in icons.name_glob.items()
|
||||
if fnmatch(node.path.name, k)
|
||||
),
|
||||
icons.default_icon,
|
||||
)
|
||||
)
|
||||
if settings.view.use_icons
|
||||
else icons.default_icon
|
||||
)
|
||||
yield " "
|
||||
|
||||
def gen_name(node: Node) -> Iterator[str]:
|
||||
yield encode_for_display(node.path.name)
|
||||
if not settings.view.use_icons and is_dir(node):
|
||||
yield sep
|
||||
|
||||
def gen_decor_post(node: Node) -> Iterator[str]:
|
||||
mode = node.mode
|
||||
if Mode.orphan_link in mode:
|
||||
yield " "
|
||||
yield icons.link.broken
|
||||
elif Mode.link in mode:
|
||||
yield " "
|
||||
if is_dir(node) and not follow_links:
|
||||
if node.path in index:
|
||||
yield icons.folder.open
|
||||
else:
|
||||
yield icons.folder.closed
|
||||
else:
|
||||
yield icons.link.normal
|
||||
|
||||
def gen_badges(path: PurePath) -> Iterator[Badge]:
|
||||
l = ""
|
||||
if diagnostic := diagnostics.get(path, {}):
|
||||
l = " "
|
||||
dl = len(diagnostic)
|
||||
for idx, (severity, count) in enumerate(sorted(diagnostic.items())):
|
||||
group = context.particular_mappings.diagnostics.get(
|
||||
severity, context.particular_mappings.diagnostic_unknown
|
||||
)
|
||||
lhs, rhs = not idx, idx + 1 == dl
|
||||
r = " " if dl > 1 and not rhs else ""
|
||||
if lhs:
|
||||
yield Badge(
|
||||
text="{", group=context.particular_mappings.diagnostic_context
|
||||
)
|
||||
yield Badge(text=f"{count}{r}", group=group)
|
||||
if rhs:
|
||||
yield Badge(
|
||||
text="}", group=context.particular_mappings.diagnostic_context
|
||||
)
|
||||
|
||||
if marks := markers.bookmarks.get(path):
|
||||
ordered = "".join(sorted(marks))
|
||||
yield Badge(
|
||||
text=f"{l}<{ordered}>",
|
||||
group=context.particular_mappings.bookmarks,
|
||||
)
|
||||
|
||||
if qf_count := markers.quick_fix.get(path):
|
||||
yield Badge(
|
||||
text=f"{l}({qf_count})",
|
||||
group=context.particular_mappings.quickfix,
|
||||
)
|
||||
|
||||
if stat := vc.status.get(path):
|
||||
yield Badge(
|
||||
text=f"{l}[{stat}]",
|
||||
group=context.particular_mappings.version_control,
|
||||
)
|
||||
|
||||
def gen_highlights(
|
||||
node: Node, pre: str, icon: str, name: str, ignored: bool
|
||||
) -> Iterator[Highlight]:
|
||||
icon_begin = len(encode(pre))
|
||||
icon_end = icon_begin + len(encode(icon))
|
||||
text_begin = icon_end
|
||||
text_end = len(encode(name)) + text_begin
|
||||
|
||||
if icon_group := search_icon_hl(node, ignored=ignored):
|
||||
hl = Highlight(group=icon_group, begin=icon_begin, end=icon_end)
|
||||
yield hl
|
||||
|
||||
if text_group := search_text_hl(node, ignored=ignored):
|
||||
hl = Highlight(group=text_group, begin=text_begin, end=text_end)
|
||||
yield hl
|
||||
|
||||
def show(node: Node, depth: int) -> Optional[_Render]:
|
||||
_user_ignored = user_ignored(node, ignores=settings.ignores)
|
||||
vc_ignored = _vc_ignored(node, vc=vc)
|
||||
ignored = vc_ignored or _user_ignored
|
||||
|
||||
if depth and _user_ignored and not show_hidden:
|
||||
return None
|
||||
else:
|
||||
pre = "".join(gen_decor_pre(node, depth=depth))
|
||||
icon = "".join(gen_icon(node))
|
||||
name = "".join(gen_name(node))
|
||||
post = "".join(gen_decor_post(node))
|
||||
|
||||
line = f"{pre}{icon}{name}{post}"
|
||||
badges = tuple(gen_badges(node.path))
|
||||
highlights = tuple(
|
||||
gen_highlights(node, pre=pre, icon=icon, name=name, ignored=ignored)
|
||||
)
|
||||
return line, highlights, badges
|
||||
|
||||
return show
|
||||
|
||||
|
||||
def render(
|
||||
node: Node,
|
||||
*,
|
||||
settings: Settings,
|
||||
index: Index,
|
||||
selection: Selection,
|
||||
filter_pattern: Optional[FilterPattern],
|
||||
markers: Markers,
|
||||
diagnostics: Diagnostics,
|
||||
vc: VCStatus,
|
||||
follow_links: bool,
|
||||
show_hidden: bool,
|
||||
current: Optional[PurePath],
|
||||
) -> Derived:
|
||||
show = _paint(
|
||||
settings,
|
||||
index=index,
|
||||
selection=selection,
|
||||
markers=markers,
|
||||
diagnostics=diagnostics,
|
||||
vc=vc,
|
||||
follow_links=follow_links,
|
||||
show_hidden=show_hidden,
|
||||
current=current,
|
||||
)
|
||||
comp = _gen_comp(settings.view.sort_by)
|
||||
keep_open = {node.path}
|
||||
|
||||
def render(node: Node, *, depth: int, cleared: bool) -> Iterator[_NRender]:
|
||||
clear = (
|
||||
cleared
|
||||
or not filter_pattern
|
||||
or fnmatch(node.path.name, filter_pattern.pattern)
|
||||
)
|
||||
|
||||
if rend := show(node, depth):
|
||||
|
||||
def gen_children() -> Iterator[_NRender]:
|
||||
for child in sorted(node.children.values(), key=comp):
|
||||
yield from render(child, depth=depth + 1, cleared=clear)
|
||||
|
||||
children = tuple(gen_children())
|
||||
if clear or children or node.path in keep_open:
|
||||
yield (node, *rend)
|
||||
yield from iter(children)
|
||||
|
||||
rendered = render(node, depth=0, cleared=False)
|
||||
_nodes, _lines, _highlights, _badges = zip(*rendered)
|
||||
nodes, lines, highlights, badges = (
|
||||
cast(Sequence[Node], _nodes),
|
||||
cast(Sequence[str], _lines),
|
||||
cast(Sequence[Sequence[Highlight]], _highlights),
|
||||
cast(Sequence[Sequence[Badge]], _badges),
|
||||
)
|
||||
hashed = tuple(str(hash(zipped)) for zipped in zip(lines, highlights, badges))
|
||||
path_row_lookup = {node.path: idx for idx, node in enumerate(nodes)}
|
||||
derived = Derived(
|
||||
lines=lines,
|
||||
highlights=highlights,
|
||||
badges=badges,
|
||||
hashed=hashed,
|
||||
node_row_lookup=nodes,
|
||||
path_row_lookup=path_row_lookup,
|
||||
)
|
||||
return derived
|
||||
@ -1,74 +0,0 @@
|
||||
from dataclasses import dataclass
|
||||
from enum import Enum, auto
|
||||
from pathlib import PurePath
|
||||
from typing import Mapping, Optional, Sequence
|
||||
|
||||
from pynvim_pp.highlight import HLgroup
|
||||
|
||||
from chad_types import IconGlyphs
|
||||
|
||||
from ..fs.types import Mode, Node
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class HLGroups:
|
||||
bookmarks: str
|
||||
ignored: str
|
||||
marks: str
|
||||
quickfix: str
|
||||
diagnostics: Mapping[int, str]
|
||||
diagnostic_unknown: str
|
||||
diagnostic_context: str
|
||||
version_control: str
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class HLcontext:
|
||||
groups: Sequence[HLgroup]
|
||||
icon_exts: Mapping[str, str]
|
||||
mode_pre: Mapping[Mode, str]
|
||||
mode_post: Mapping[Optional[Mode], str]
|
||||
name_exact: Mapping[str, str]
|
||||
name_glob: Mapping[str, str]
|
||||
ext_exact: Mapping[str, str]
|
||||
particular_mappings: HLGroups
|
||||
|
||||
|
||||
class Sortby(Enum):
|
||||
is_folder = auto()
|
||||
ext = auto()
|
||||
file_name_lower = auto()
|
||||
file_name = auto()
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class ViewOptions:
|
||||
hl_context: HLcontext
|
||||
icons: IconGlyphs
|
||||
sort_by: Sequence[Sortby]
|
||||
time_fmt: str
|
||||
use_icons: bool
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Badge:
|
||||
text: str
|
||||
group: str
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Highlight:
|
||||
begin: int
|
||||
end: int
|
||||
group: str
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class Derived:
|
||||
lines: Sequence[str]
|
||||
highlights: Sequence[Sequence[Highlight]]
|
||||
badges: Sequence[Sequence[Badge]]
|
||||
|
||||
hashed: Sequence[str]
|
||||
node_row_lookup: Sequence[Node]
|
||||
path_row_lookup: Mapping[PurePath, int]
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user