mirror of
https://github.com/iofq/nvim.nix.git
synced 2026-01-23 08:55:16 -06:00
Clean up rice
This commit is contained in:
parent
50ac04fdb9
commit
f66e3dde6a
15 changed files with 317 additions and 629 deletions
11
.github/workflows/main.yml
vendored
11
.github/workflows/main.yml
vendored
|
|
@ -13,8 +13,7 @@ jobs:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- package_name: full
|
- package_name: neovim
|
||||||
- package_name: minimal
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: DeterminateSystems/nix-installer-action@main
|
- uses: DeterminateSystems/nix-installer-action@main
|
||||||
|
|
@ -23,17 +22,17 @@ jobs:
|
||||||
id: build
|
id: build
|
||||||
run: |
|
run: |
|
||||||
nix bundle \
|
nix bundle \
|
||||||
-o nvim-${{ matrix.package_name }}.AppImage \
|
-o ${{ matrix.package_name }}.AppImage \
|
||||||
--bundler github:ralismark/nix-appimage \
|
--bundler github:ralismark/nix-appimage \
|
||||||
--extra-experimental-features nix-command \
|
--extra-experimental-features nix-command \
|
||||||
--extra-experimental-features flakes .#${{ matrix.package_name }}
|
--extra-experimental-features flakes .#${{ matrix.package_name }}
|
||||||
echo "Done building AppImage for nvim-${{ matrix.package_name }}"
|
echo "Done building AppImage for ${{ matrix.package_name }}"
|
||||||
- name: Upload bundle to release
|
- name: Upload bundle to release
|
||||||
if: github.ref == 'refs/heads/master'
|
if: github.ref == 'refs/heads/master'
|
||||||
uses: svenstaro/upload-release-action@v2
|
uses: svenstaro/upload-release-action@v2
|
||||||
with:
|
with:
|
||||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
file: "nvim-${{ matrix.package_name }}.AppImage"
|
file: "${{ matrix.package_name }}.AppImage"
|
||||||
asset_name: "nvim-x86_64-linux-${{ matrix.package_name }}.AppImage"
|
asset_name: "${{ matrix.package_name }}-x86_64-linux.AppImage"
|
||||||
tag: latest
|
tag: latest
|
||||||
overwrite: true
|
overwrite: true
|
||||||
|
|
|
||||||
251
config/init.lua
251
config/init.lua
|
|
@ -1,6 +1,245 @@
|
||||||
require("minimal-init")
|
--------------------
|
||||||
require("nvim-treesitter-conf")
|
-- Mini
|
||||||
require("lsp-conf")
|
--------------------
|
||||||
require("colors")
|
require("mini-conf")
|
||||||
require("git-conf")
|
|
||||||
require("oil-conf")
|
--------------------
|
||||||
|
-- Toggleterm
|
||||||
|
--------------------
|
||||||
|
require("toggleterm").setup{
|
||||||
|
open_mapping = [[<C-\>]],
|
||||||
|
direction = "float",
|
||||||
|
close_on_exit = true,
|
||||||
|
}
|
||||||
|
|
||||||
|
--------------------
|
||||||
|
-- Telescope
|
||||||
|
--------------------
|
||||||
|
local telescope = require("telescope.builtin")
|
||||||
|
vim.keymap.set("n", "<leader>fb", telescope.buffers, {noremap = true, silent = true})
|
||||||
|
vim.keymap.set("n", "<leader>ff", telescope.find_files, {noremap = true, silent = true})
|
||||||
|
vim.keymap.set("n", "<leader>fg", telescope.git_files, {noremap = true, silent = true})
|
||||||
|
vim.keymap.set("n", "<leader>fv", telescope.command_history, {noremap = true, silent = true})
|
||||||
|
vim.keymap.set("n", "<leader>fa", telescope.live_grep, {noremap = true, silent = true})
|
||||||
|
vim.keymap.set("n", "<leader>f8", telescope.grep_string, {noremap = true, silent = true})
|
||||||
|
vim.keymap.set("n", "<leader>f<BS>", telescope.resume, {noremap = true, silent = true})
|
||||||
|
vim.keymap.set("n", "<leader>fs", telescope.git_status, {noremap = true, silent = true})
|
||||||
|
|
||||||
|
local telescope = require("telescope")
|
||||||
|
telescope.setup({
|
||||||
|
defaults = {
|
||||||
|
layout_strategy = "vertical",
|
||||||
|
layout_config = { width = .90, },
|
||||||
|
prompt_title = false,
|
||||||
|
results_title = false,
|
||||||
|
preview_title = false,
|
||||||
|
vimgrep_arguments = {
|
||||||
|
"rg",
|
||||||
|
"--color=never",
|
||||||
|
"--no-heading",
|
||||||
|
"--hidden",
|
||||||
|
"--with-filename",
|
||||||
|
"--line-number",
|
||||||
|
"--column",
|
||||||
|
"--smart-case"
|
||||||
|
},
|
||||||
|
mappings = {
|
||||||
|
i = {
|
||||||
|
["wq"] = require("telescope.actions").close,
|
||||||
|
["<Esc>"] = require("telescope.actions").close,
|
||||||
|
["<C-k>"] = require("telescope.actions").move_selection_previous,
|
||||||
|
["<C-j>"] = require("telescope.actions").move_selection_next,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
telescope.load_extension("fzf")
|
||||||
|
|
||||||
|
--------------------
|
||||||
|
-- Treesitter
|
||||||
|
--------------------
|
||||||
|
require("nvim-treesitter.configs").setup {
|
||||||
|
ensure_installed = {},
|
||||||
|
highlight = {
|
||||||
|
enable = true,
|
||||||
|
},
|
||||||
|
indent = {
|
||||||
|
enable = true,
|
||||||
|
},
|
||||||
|
textobjects = {
|
||||||
|
select = {
|
||||||
|
enable = true,
|
||||||
|
lookahead = true,
|
||||||
|
keymaps = {
|
||||||
|
["af"] = "@function.outer",
|
||||||
|
["if"] = "@function.inner",
|
||||||
|
["aa"] = "@statement.outer",
|
||||||
|
["ia"] = "@parameter.inner",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
move = {
|
||||||
|
enable = true,
|
||||||
|
set_jumps = true, -- whether to set jumps in the jumplist
|
||||||
|
goto_next_start = {
|
||||||
|
[']]'] = '@function.outer',
|
||||||
|
[']a'] = '@parameter.inner',
|
||||||
|
},
|
||||||
|
goto_previous_start = {
|
||||||
|
['[['] = '@function.outer',
|
||||||
|
['[a'] = '@parameter.inner',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
swap = {
|
||||||
|
enable = true,
|
||||||
|
swap_next = {
|
||||||
|
["s]"] = "@parameter.inner",
|
||||||
|
},
|
||||||
|
swap_previous = {
|
||||||
|
["s["] = "@parameter.inner",
|
||||||
|
},
|
||||||
|
}, },
|
||||||
|
incremental_selection = {
|
||||||
|
enable = true,
|
||||||
|
keymaps = {
|
||||||
|
init_selection = '<CR>',
|
||||||
|
node_incremental = '<TAB>',
|
||||||
|
node_decremental = '<S-TAB>',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
--------------------
|
||||||
|
-- LSP Config
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
-- Setup language servers.
|
||||||
|
local lspconfig = require('lspconfig')
|
||||||
|
lspconfig.gopls.setup { on_attach = function(_, bufnr)
|
||||||
|
vim.api.nvim_command("au BufWritePre <buffer> lua vim.lsp.buf.format { async = false }")
|
||||||
|
end
|
||||||
|
}
|
||||||
|
lspconfig.pyright.setup {}
|
||||||
|
lspconfig.nil_ls.setup {}
|
||||||
|
lspconfig.phpactor.setup {}
|
||||||
|
|
||||||
|
-- Global mappings.
|
||||||
|
-- See `:help vim.diagnostic.*` for documentation on any of the below functions
|
||||||
|
vim.keymap.set('n', '<leader>de', vim.diagnostic.open_float)
|
||||||
|
vim.keymap.set('n', '[d', vim.diagnostic.goto_prev)
|
||||||
|
vim.keymap.set('n', ']d', vim.diagnostic.goto_next)
|
||||||
|
|
||||||
|
vim.diagnostic.config({
|
||||||
|
virtual_text = true,
|
||||||
|
underline = true,
|
||||||
|
update_in_insert = false,
|
||||||
|
})
|
||||||
|
-- Use LspAttach autocommand to only map the following keys
|
||||||
|
-- after the language server attaches to the current buffer
|
||||||
|
vim.api.nvim_create_autocmd('LspAttach', {
|
||||||
|
group = vim.api.nvim_create_augroup('UserLspConfig', {}),
|
||||||
|
callback = function(ev)
|
||||||
|
-- Enable completion triggered by <c-x><c-o>
|
||||||
|
vim.bo[ev.buf].omnifunc = 'v:lua.vim.lsp.omnifunc'
|
||||||
|
-- Buffer local mappings.
|
||||||
|
-- See `:help vim.lsp.*` for documentation on any of the below functions
|
||||||
|
local opts = { buffer = ev.buf }
|
||||||
|
vim.keymap.set('n', 'K', vim.lsp.buf.hover, opts)
|
||||||
|
vim.keymap.set('n', '<leader>rn', vim.lsp.buf.rename, opts)
|
||||||
|
vim.keymap.set({ 'n', 'v' }, '<leader>da', vim.lsp.buf.code_action, opts)
|
||||||
|
vim.keymap.set("n", "<leader>dd", "<cmd>Telescope lsp_definitions<cr>", { buffer = bufnr })
|
||||||
|
vim.keymap.set("n", "<leader>di", "<cmd>Telescope lsp_implementations<cr>", { buffer = bufnr })
|
||||||
|
vim.keymap.set("n", "<leader>dr", "<cmd>Telescope lsp_references<cr>", { buffer = bufnr })
|
||||||
|
vim.keymap.set("n", "<leader>dt", "<cmd>Telescope lsp_type_definitions<cr>", { buffer = bufnr })
|
||||||
|
vim.keymap.set("n", "<leader>ds", "<cmd>Telescope lsp_document_symbols<cr>", { buffer = bufnr })
|
||||||
|
vim.keymap.set('n', '<space>df', function()
|
||||||
|
vim.lsp.buf.format { async = true }
|
||||||
|
end, opts)
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
--------------------
|
||||||
|
-- Git
|
||||||
|
--------------------
|
||||||
|
require('gitsigns').setup{
|
||||||
|
signcolumn = false,
|
||||||
|
numhl = true,
|
||||||
|
on_attach = function()
|
||||||
|
local gs = package.loaded.gitsigns
|
||||||
|
vim.keymap.set("n", "<leader>gg", gs.preview_hunk)
|
||||||
|
vim.keymap.set('n', '<leader>gb', function() gs.blame_line{full=true} end)
|
||||||
|
vim.keymap.set('n', '<leader>gr', gs.reset_hunk)
|
||||||
|
vim.keymap.set('v', '<leader>gr', function() gs.reset_hunk {vim.fn.line('.'), vim.fn.line('v')} end)
|
||||||
|
-- Navigation
|
||||||
|
vim.keymap.set('n', ']g', function()
|
||||||
|
if vim.wo.diff then return ']c' end
|
||||||
|
vim.schedule(function() gs.next_hunk() end)
|
||||||
|
return '<Ignore>'
|
||||||
|
end, {expr=true})
|
||||||
|
|
||||||
|
vim.keymap.set('n', '[g', function()
|
||||||
|
if vim.wo.diff then return '[c' end
|
||||||
|
vim.schedule(function() gs.prev_hunk() end)
|
||||||
|
return '<Ignore>'
|
||||||
|
end, {expr=true})
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
|
local neogit = require('neogit')
|
||||||
|
neogit.setup {integrations = {diffview = true}}
|
||||||
|
vim.keymap.set('n', '<leader>ng', neogit.open)
|
||||||
|
|
||||||
|
require("diffview")
|
||||||
|
|
||||||
|
--------------------
|
||||||
|
-- Oil & Undo
|
||||||
|
--------------------
|
||||||
|
local oil = require('oil')
|
||||||
|
oil.setup({
|
||||||
|
columns = {
|
||||||
|
"permissions",
|
||||||
|
"size"
|
||||||
|
},
|
||||||
|
view_options = {
|
||||||
|
show_hidden = true
|
||||||
|
},
|
||||||
|
keymaps = {
|
||||||
|
["wq"] = "actions.close"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
vim.keymap.set("n", "<leader>c", oil.toggle_float, {noremap = true, silent = true});
|
||||||
|
|
||||||
|
vim.keymap.set("n", "<leader>u", "<cmd>UndotreeToggle<cr>")
|
||||||
|
|
||||||
|
--------------------
|
||||||
|
-- Refactoring
|
||||||
|
--------------------
|
||||||
|
require('refactoring').setup({
|
||||||
|
prompt_func_return_type = { go = true, },
|
||||||
|
prompt_func_param_type = { go = true, },
|
||||||
|
show_success_message = true,
|
||||||
|
})
|
||||||
|
|
||||||
|
require("telescope").load_extension("refactoring")
|
||||||
|
vim.keymap.set(
|
||||||
|
{"n"},
|
||||||
|
"<leader>rr",
|
||||||
|
function() require('telescope').extensions.refactoring.refactors() end
|
||||||
|
)
|
||||||
|
--------------------
|
||||||
|
-- Colors
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
require("rose-pine").setup({
|
||||||
|
variant = "moon",
|
||||||
|
styles = {
|
||||||
|
bold = false,
|
||||||
|
italic = false,
|
||||||
|
transparency = true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
vim.cmd.colorscheme "rose-pine-main"
|
||||||
|
|
||||||
|
--------------------
|
||||||
|
-- include our config last to override
|
||||||
|
--------------------
|
||||||
|
require("nvim-conf")
|
||||||
|
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
require("rose-pine").setup({
|
|
||||||
variant = "moon",
|
|
||||||
styles = {
|
|
||||||
bold = false,
|
|
||||||
italic = false,
|
|
||||||
transparency = true,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
vim.cmd.colorscheme "rose-pine-main"
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
require('gitsigns').setup{
|
|
||||||
signcolumn = false,
|
|
||||||
numhl = true,
|
|
||||||
on_attach = function()
|
|
||||||
local gs = package.loaded.gitsigns
|
|
||||||
vim.keymap.set("n", "<leader>gg", gs.preview_hunk)
|
|
||||||
vim.keymap.set('n', '<leader>gb', function() gs.blame_line{full=true} end)
|
|
||||||
vim.keymap.set('n', '<leader>gs', gs.stage_hunk)
|
|
||||||
vim.keymap.set('n', '<leader>gr', gs.reset_hunk)
|
|
||||||
vim.keymap.set('v', '<leader>gr', function() gs.reset_hunk {vim.fn.line('.'), vim.fn.line('v')} end)
|
|
||||||
vim.keymap.set('v', '<leader>gs', function() gs.stage_hunk {vim.fn.line('.'), vim.fn.line('v')} end)
|
|
||||||
-- Navigation
|
|
||||||
vim.keymap.set('n', ']g', function()
|
|
||||||
if vim.wo.diff then return ']c' end
|
|
||||||
vim.schedule(function() gs.next_hunk() end)
|
|
||||||
return '<Ignore>'
|
|
||||||
end, {expr=true})
|
|
||||||
|
|
||||||
vim.keymap.set('n', '[g', function()
|
|
||||||
if vim.wo.diff then return '[c' end
|
|
||||||
vim.schedule(function() gs.prev_hunk() end)
|
|
||||||
return '<Ignore>'
|
|
||||||
end, {expr=true})
|
|
||||||
end
|
|
||||||
}
|
|
||||||
|
|
||||||
local neogit = require('neogit')
|
|
||||||
neogit.setup {}
|
|
||||||
vim.keymap.set('n', '<leader>ng', neogit.open)
|
|
||||||
|
|
@ -1,43 +0,0 @@
|
||||||
-- Setup language servers.
|
|
||||||
local lspconfig = require('lspconfig')
|
|
||||||
lspconfig.gopls.setup { on_attach = function(_, bufnr)
|
|
||||||
vim.api.nvim_command("au BufWritePre <buffer> lua vim.lsp.buf.format { async = false }")
|
|
||||||
end
|
|
||||||
}
|
|
||||||
lspconfig.pyright.setup {}
|
|
||||||
lspconfig.nil_ls.setup {}
|
|
||||||
|
|
||||||
-- Global mappings.
|
|
||||||
-- See `:help vim.diagnostic.*` for documentation on any of the below functions
|
|
||||||
vim.keymap.set('n', '<leader>de', vim.diagnostic.open_float)
|
|
||||||
vim.keymap.set('n', '[d', vim.diagnostic.goto_prev)
|
|
||||||
vim.keymap.set('n', ']d', vim.diagnostic.goto_next)
|
|
||||||
|
|
||||||
vim.diagnostic.config({
|
|
||||||
virtual_text = true,
|
|
||||||
underline = true,
|
|
||||||
update_in_insert = false,
|
|
||||||
})
|
|
||||||
-- Use LspAttach autocommand to only map the following keys
|
|
||||||
-- after the language server attaches to the current buffer
|
|
||||||
vim.api.nvim_create_autocmd('LspAttach', {
|
|
||||||
group = vim.api.nvim_create_augroup('UserLspConfig', {}),
|
|
||||||
callback = function(ev)
|
|
||||||
-- Enable completion triggered by <c-x><c-o>
|
|
||||||
vim.bo[ev.buf].omnifunc = 'v:lua.vim.lsp.omnifunc'
|
|
||||||
-- Buffer local mappings.
|
|
||||||
-- See `:help vim.lsp.*` for documentation on any of the below functions
|
|
||||||
local opts = { buffer = ev.buf }
|
|
||||||
vim.keymap.set('n', 'K', vim.lsp.buf.hover, opts)
|
|
||||||
vim.keymap.set('n', '<leader>rn', vim.lsp.buf.rename, opts)
|
|
||||||
vim.keymap.set({ 'n', 'v' }, '<leader>ac', vim.lsp.buf.code_action, opts)
|
|
||||||
vim.keymap.set("n", "<leader>dd", "<cmd>Telescope lsp_definitions<cr>", { buffer = bufnr })
|
|
||||||
vim.keymap.set("n", "<leader>di", "<cmd>Telescope lsp_implementations<cr>", { buffer = bufnr })
|
|
||||||
vim.keymap.set("n", "<leader>dr", "<cmd>Telescope lsp_references<cr>", { buffer = bufnr })
|
|
||||||
vim.keymap.set("n", "<leader>dt", "<cmd>Telescope lsp_type_definitions<cr>", { buffer = bufnr })
|
|
||||||
vim.keymap.set("n", "<leader>ds", "<cmd>Telescope lsp_document_symbols<cr>", { buffer = bufnr })
|
|
||||||
vim.keymap.set('n', '<space>df', function()
|
|
||||||
vim.lsp.buf.format { async = true }
|
|
||||||
end, opts)
|
|
||||||
end,
|
|
||||||
})
|
|
||||||
|
|
@ -1,49 +0,0 @@
|
||||||
require("nvim-treesitter.configs").setup {
|
|
||||||
ensure_installed = {},
|
|
||||||
highlight = {
|
|
||||||
enable = true,
|
|
||||||
},
|
|
||||||
indent = {
|
|
||||||
enable = true,
|
|
||||||
},
|
|
||||||
textobjects = {
|
|
||||||
select = {
|
|
||||||
enable = true,
|
|
||||||
lookahead = true,
|
|
||||||
keymaps = {
|
|
||||||
["af"] = "@function.outer",
|
|
||||||
["if"] = "@function.inner",
|
|
||||||
["aa"] = "@statement.outer",
|
|
||||||
["ia"] = "@parameter.inner",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
move = {
|
|
||||||
enable = true,
|
|
||||||
set_jumps = true, -- whether to set jumps in the jumplist
|
|
||||||
goto_next_start = {
|
|
||||||
[']]'] = '@function.outer',
|
|
||||||
[']a'] = '@parameter.inner',
|
|
||||||
},
|
|
||||||
goto_previous_start = {
|
|
||||||
['[['] = '@function.outer',
|
|
||||||
['[a'] = '@parameter.inner',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
swap = {
|
|
||||||
enable = true,
|
|
||||||
swap_next = {
|
|
||||||
["s]"] = "@parameter.inner",
|
|
||||||
},
|
|
||||||
swap_previous = {
|
|
||||||
["s["] = "@parameter.inner",
|
|
||||||
},
|
|
||||||
}, },
|
|
||||||
incremental_selection = {
|
|
||||||
enable = true,
|
|
||||||
keymaps = {
|
|
||||||
init_selection = '<CR>',
|
|
||||||
node_incremental = '<TAB>',
|
|
||||||
node_decremental = '<S-TAB>',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
local oil = require('oil')
|
|
||||||
oil.setup({
|
|
||||||
columns = {
|
|
||||||
"permissions",
|
|
||||||
"size"
|
|
||||||
},
|
|
||||||
view_options = {
|
|
||||||
show_hidden = true
|
|
||||||
},
|
|
||||||
keymaps = {
|
|
||||||
["wq"] = "actions.close"
|
|
||||||
}
|
|
||||||
})
|
|
||||||
vim.keymap.set("n", "<leader>c", oil.toggle_float, {noremap = true, silent = true});
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
||||||
local telescope = require("telescope.builtin")
|
|
||||||
vim.keymap.set("n", "<leader>fb", telescope.buffers, {noremap = true, silent = true})
|
|
||||||
vim.keymap.set("n", "<leader>ff", telescope.find_files, {noremap = true, silent = true})
|
|
||||||
vim.keymap.set("n", "<leader>fg", telescope.git_files, {noremap = true, silent = true})
|
|
||||||
vim.keymap.set("n", "<leader>fv", telescope.command_history, {noremap = true, silent = true})
|
|
||||||
vim.keymap.set("n", "<leader>fa", telescope.live_grep, {noremap = true, silent = true})
|
|
||||||
vim.keymap.set("n", "<leader>f8", telescope.grep_string, {noremap = true, silent = true})
|
|
||||||
vim.keymap.set("n", "<leader>f<BS>", telescope.resume, {noremap = true, silent = true})
|
|
||||||
vim.keymap.set("n", "<leader>fs", telescope.git_status, {noremap = true, silent = true})
|
|
||||||
|
|
||||||
local telescope = require("telescope")
|
|
||||||
telescope.setup({
|
|
||||||
defaults = {
|
|
||||||
layout_strategy = "vertical",
|
|
||||||
layout_config = { width = .90, },
|
|
||||||
prompt_title = false,
|
|
||||||
results_title = false,
|
|
||||||
preview_title = false,
|
|
||||||
vimgrep_arguments = {
|
|
||||||
"rg",
|
|
||||||
"--color=never",
|
|
||||||
"--no-heading",
|
|
||||||
"--hidden",
|
|
||||||
"--with-filename",
|
|
||||||
"--line-number",
|
|
||||||
"--column",
|
|
||||||
"--smart-case"
|
|
||||||
},
|
|
||||||
mappings = {
|
|
||||||
i = {
|
|
||||||
["wq"] = require("telescope.actions").close,
|
|
||||||
["<Esc>"] = require("telescope.actions").close,
|
|
||||||
["<C-k>"] = require("telescope.actions").move_selection_previous,
|
|
||||||
["<C-j>"] = require("telescope.actions").move_selection_next,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
telescope.load_extension("fzf")
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
require("toggleterm").setup{
|
|
||||||
open_mapping = [[<C-\>]],
|
|
||||||
direction = "float",
|
|
||||||
close_on_exit = true,
|
|
||||||
}
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
require("mini-conf")
|
|
||||||
require("toggleterm-conf")
|
|
||||||
require("telescope-conf")
|
|
||||||
-- include our config last to override
|
|
||||||
require("nvim-conf")
|
|
||||||
334
filewatch.py
334
filewatch.py
|
|
@ -1,334 +0,0 @@
|
||||||
#!/usr/bin/python
|
|
||||||
|
|
||||||
import os
|
|
||||||
import subprocess
|
|
||||||
import time
|
|
||||||
import glob
|
|
||||||
import syslog
|
|
||||||
import multiprocessing as mp
|
|
||||||
from datetime import datetime
|
|
||||||
from epicutils import getpretend,setpretend
|
|
||||||
|
|
||||||
#-----------------------------------------------------------------------------#
|
|
||||||
# This script is used to transfer files between Epic and Hosting. Files in #
|
|
||||||
# /home/epichosted.com/<user>/to_epichosting will go to #
|
|
||||||
# /nfs/temp/<user>/from_epic, and files in /nfs/temp/<user>/to_epic will go #
|
|
||||||
# to /home/epichosted.com/<user>/from_epichosting. Along the way, a forever #
|
|
||||||
# copy of each file is taken. #
|
|
||||||
#-----------------------------------------------------------------------------#
|
|
||||||
|
|
||||||
# Some initial settings are needed
|
|
||||||
setpretend(False)
|
|
||||||
domain = subprocess.check_output('realm list --name-only'.split()).strip()
|
|
||||||
# domain = subprocess.check_output('dnsdomainname').strip()
|
|
||||||
tempdir = "/nfs/temp"
|
|
||||||
homedir = "/home/{0}".format(domain)
|
|
||||||
largedir = "/nfs/temp/large"
|
|
||||||
log = ("./{0}.log_{1}".format(
|
|
||||||
"filewatch", datetime.today().strftime("%m%d%Y")
|
|
||||||
)
|
|
||||||
)
|
|
||||||
logfile = open(log,'a')
|
|
||||||
|
|
||||||
def parseArgs():
|
|
||||||
import argparse
|
|
||||||
parser = argparse.ArgumentParser(description='File transfer')
|
|
||||||
parser.add_argument('--type', choices=['epic', 'hosting', 'testlab'],
|
|
||||||
required=False,
|
|
||||||
help="Where files from this server are coming from and going to."
|
|
||||||
)
|
|
||||||
args = parser.parse_args()
|
|
||||||
if args.type:
|
|
||||||
return args.type
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
|
|
||||||
# Logging utility
|
|
||||||
def tolog(message):
|
|
||||||
tosyslog(message)
|
|
||||||
|
|
||||||
def tosyslog(message):
|
|
||||||
if not getpretend():
|
|
||||||
syslog.syslog(message)
|
|
||||||
|
|
||||||
# Alert email
|
|
||||||
def emailBody(file):
|
|
||||||
import datetime
|
|
||||||
import os
|
|
||||||
body = ("This alert is about your recent SFTP file transfer.\n\n"
|
|
||||||
"Digital Guardian has classified your file as containing sensitive information "
|
|
||||||
"including PHI or PII. Your file has been quarantined but can be moved pending "
|
|
||||||
"additional review.\n\n"
|
|
||||||
"File: {0}\n"
|
|
||||||
"Size: {1}kB\n"
|
|
||||||
"Date: {2}\n\n"
|
|
||||||
"If your file contains PHI:\n\tProvide the Security Team with the Sherlock SLG "
|
|
||||||
"you will be attaching the file to.\n\n"
|
|
||||||
"If your file does not contain PHI:\n\tProvide the Security Team a short description "
|
|
||||||
"of the contents so we can improve our flagging rules.\n\n"
|
|
||||||
"If this is an after-hours case and you need the file immediately:\n\tCall the "
|
|
||||||
"Security on-call representative.\n"
|
|
||||||
).format(
|
|
||||||
file, (os.path.getsize(file)/1000.0), datetime.datetime.now()
|
|
||||||
)
|
|
||||||
return body
|
|
||||||
|
|
||||||
# Send email
|
|
||||||
def sendEmail(file):
|
|
||||||
import smtplib
|
|
||||||
import socket
|
|
||||||
from email.mime.text import MIMEText
|
|
||||||
siemList = "soc@epichosted.com"
|
|
||||||
msg = MIMEText(emailBody(file))
|
|
||||||
msg['Subject'] = "Digital Guardian File Transfer Quarantine"
|
|
||||||
msg['From'] = "tdcr-sftp01@test.lab"
|
|
||||||
msg['To'] = "{0}@{1}, {2}".format(file.split('/')[3], ('.').join(socket.getfqdn().split('.')[1:]), siemList)
|
|
||||||
s = smtplib.SMTP('localhost')
|
|
||||||
s.sendmail(msg['From'], msg['To'].split(','), msg.as_string())
|
|
||||||
s.quit()
|
|
||||||
|
|
||||||
# Check if a file is too large to send.
|
|
||||||
def checkfilesize(file):
|
|
||||||
# Get file size in bytes
|
|
||||||
size = os.path.getsize(file)
|
|
||||||
# Arbitrarily set at 100MB
|
|
||||||
if file.startswith(homedir) and file.split('/')[4] == 'hosting':
|
|
||||||
maxsize = 0
|
|
||||||
else:
|
|
||||||
# maxsize = 100000000
|
|
||||||
return True
|
|
||||||
# If the file is too big, stop it from sending.
|
|
||||||
if size >= maxsize:
|
|
||||||
return False
|
|
||||||
else:
|
|
||||||
return True
|
|
||||||
|
|
||||||
# Scan file
|
|
||||||
def scanfileav(file):
|
|
||||||
cmd = ["uvscan", file]
|
|
||||||
try:
|
|
||||||
result = subprocess.check_output(cmd)
|
|
||||||
except Exception, e:
|
|
||||||
tolog("{0} failed its file scan.".format(file))
|
|
||||||
return False
|
|
||||||
else:
|
|
||||||
tolog(result)
|
|
||||||
return True
|
|
||||||
|
|
||||||
# DG classification flags to stop
|
|
||||||
def taginDgClassFlags(tag):
|
|
||||||
tolog("Tag is {0}.".format(tag))
|
|
||||||
#flags = ["PCI_DATA_LOW", "PCI_DATA_MEDIUM", "PCI_DATA_HIGH",
|
|
||||||
# "PHI_DATA_LOW", "PHI_DATA_MEDIUM", "PHI_DATA_HIGH",
|
|
||||||
# "PII_DATA_LOW", "PII_DATA_MEDIUM", "PII_DATA_HIGH",
|
|
||||||
# "TEST"]
|
|
||||||
flags = ["DLP_PHI_DATA", "DLP_PII_DATA"]
|
|
||||||
if tag in flags:
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
|
|
||||||
# Check DG classification
|
|
||||||
def scanfiledlp(file):
|
|
||||||
import subprocess
|
|
||||||
# Need to do read on file to classify with DG
|
|
||||||
open(file, 'r').close()
|
|
||||||
output = subprocess.Popen(["/dgagent/dgciapp", file], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
||||||
if output.stdout:
|
|
||||||
outputOut = output.stdout.read()
|
|
||||||
lines = outputOut.split('#012')[0].split('\n')
|
|
||||||
for line in lines:
|
|
||||||
if line.startswith("tag:"):
|
|
||||||
tag = line.split(":")[1].strip().split('\'')[1]
|
|
||||||
return tag
|
|
||||||
if not output.stdout and output.stderr:
|
|
||||||
tolog("A DG error occurred: {0}".format(output.stderr.read()))
|
|
||||||
return None
|
|
||||||
|
|
||||||
# Check if tag is okay to move
|
|
||||||
def checkDGscan(file):
|
|
||||||
#tolog("Checking DG classification of {0}.".format(file))
|
|
||||||
#tag = scanfiledlp(file)
|
|
||||||
#if tag:
|
|
||||||
# if taginDgClassFlags(tag):
|
|
||||||
# tolog("{0} was tagged by DG: {1}. Moving to quarantine.".format(file, tag))
|
|
||||||
# return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
# Copy a file from one place to another.
|
|
||||||
def copyfile(source, destination):
|
|
||||||
try:
|
|
||||||
# Only do the copy if we're not pretending.
|
|
||||||
if not getpretend():
|
|
||||||
p = subprocess.Popen(
|
|
||||||
['cp','--preserve=mode,ownership',source,destination]
|
|
||||||
)
|
|
||||||
p.wait()
|
|
||||||
# Catch OS errors
|
|
||||||
except OSError, e:
|
|
||||||
tolog("Couldn't copy {0} to {1}. Error: {2}.".format(
|
|
||||||
source, destination, e
|
|
||||||
)
|
|
||||||
)
|
|
||||||
tosyslog("ERROR,{0},{1},{2}".format(source,destination,e))
|
|
||||||
else:
|
|
||||||
tosyslog("COMPLETE,{0},{1},{2}".format(
|
|
||||||
source,destination,os.path.getsize(destination)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
# Get forever location
|
|
||||||
def getforever(source, timestamp):
|
|
||||||
direlems = source.split('/')
|
|
||||||
direlems[1]="nfs"
|
|
||||||
direlems[2]="forever"
|
|
||||||
direlems.insert(5, str(timestamp))
|
|
||||||
direlems.pop(-1)
|
|
||||||
# Rebuild directory in /nfs/forever
|
|
||||||
forevercopydir = '/'.join(direlems)
|
|
||||||
return forevercopydir
|
|
||||||
|
|
||||||
# Copy a file to /nfs/forever.
|
|
||||||
def copytoforever(file, timestamp):
|
|
||||||
forevercopydir = getforever(file, timestamp)
|
|
||||||
forevercopy = os.path.join(forevercopydir,os.path.basename(file))
|
|
||||||
copyfile(file,forevercopy)
|
|
||||||
subprocess.check_call(['gzip',forevercopy])
|
|
||||||
|
|
||||||
# Move a file from one place to another. This will delete the original
|
|
||||||
# at the end.
|
|
||||||
def movefile(source, destination, timestamp):
|
|
||||||
try:
|
|
||||||
# Copy the file to /nfs/forever
|
|
||||||
copytoforever(source, timestamp)
|
|
||||||
destdir = os.path.dirname(destination)
|
|
||||||
if not getpretend():
|
|
||||||
# Copy the file, then delete it.
|
|
||||||
copyfile(source, destination)
|
|
||||||
os.remove(source)
|
|
||||||
# Catch OS errors
|
|
||||||
except OSError, e:
|
|
||||||
tolog("Could not move {0} to {1}. Error: {2}.".format(
|
|
||||||
source, destination, e
|
|
||||||
)
|
|
||||||
)
|
|
||||||
tosyslog("ERROR,{0},{1},{2}".format(source,destination,e))
|
|
||||||
|
|
||||||
# Move a large file to be handled by CSMs
|
|
||||||
def movetolarge(source, timestamp):
|
|
||||||
direlems = source.split('/')
|
|
||||||
direlems[1] = "nfs"
|
|
||||||
direlems[2] = "temp"
|
|
||||||
direlems.insert(3, "large")
|
|
||||||
largedest = '/'.join(direlems)
|
|
||||||
if not os.path.isdir(os.path.dirname(largedest)):
|
|
||||||
os.makedirs(os.path.dirname(largedest))
|
|
||||||
movefile(source, largedest, timestamp)
|
|
||||||
|
|
||||||
# Check if file is open. There is a race condition here, but there's not much
|
|
||||||
# I can do about that.
|
|
||||||
def checkclosed(file):
|
|
||||||
size1 = os.path.getsize(file)
|
|
||||||
time.sleep(5)
|
|
||||||
size2 = os.path.getsize(file)
|
|
||||||
if size1 == size2:
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def processonefile(args):
|
|
||||||
source = args[0]
|
|
||||||
destination = args[1]
|
|
||||||
timestamp = args[2]
|
|
||||||
closed = False
|
|
||||||
closed = checkclosed(source)
|
|
||||||
if not closed:
|
|
||||||
tolog("{0} is open. Skipping.".format(source))
|
|
||||||
return
|
|
||||||
#sizeok = checkfilesize(source)
|
|
||||||
scanok = scanfileav(source)
|
|
||||||
dgok = checkDGscan(source)
|
|
||||||
if scanok and dgok:
|
|
||||||
movefile(source, destination, timestamp)
|
|
||||||
else:
|
|
||||||
tolog("{0} is too large and will have to be moved manually. Moving to "
|
|
||||||
"/nfs/temp/large.".format(source))
|
|
||||||
tosyslog("LARGE,{0},{1}.".format(source, os.path.getsize(source)))
|
|
||||||
sendEmail(source)
|
|
||||||
movetolarge(source, timestamp)
|
|
||||||
|
|
||||||
# Get destination
|
|
||||||
def getdest(direction, source):
|
|
||||||
destination = ""
|
|
||||||
if direction == "to":
|
|
||||||
destination = source.replace(homedir,tempdir,1).replace(
|
|
||||||
"outgoing","incoming",1)
|
|
||||||
elif direction == "from":
|
|
||||||
destination = source.replace(tempdir,homedir,1).replace(
|
|
||||||
"outgoing","incoming",1)
|
|
||||||
return destination
|
|
||||||
|
|
||||||
# Build destination directories
|
|
||||||
def builddestdirs(jobs):
|
|
||||||
dirs = []
|
|
||||||
for job in jobs:
|
|
||||||
source = job[0]
|
|
||||||
destination = job[1]
|
|
||||||
timestamp = job[2]
|
|
||||||
dest = os.path.dirname(destination)
|
|
||||||
if not dest in dirs:
|
|
||||||
dirs.append(dest)
|
|
||||||
forever = getforever(source, timestamp)
|
|
||||||
if not forever in dirs:
|
|
||||||
dirs.append(forever)
|
|
||||||
for dir in dirs:
|
|
||||||
if not os.path.isdir(dir):
|
|
||||||
# tolog("Creating {0}.".format(dir))
|
|
||||||
os.makedirs(dir)
|
|
||||||
|
|
||||||
# Go through each user directory in /nfs/temp and /home/<domain>
|
|
||||||
def walktree(basedir, direction):
|
|
||||||
jobs = []
|
|
||||||
timestamp = time.time()
|
|
||||||
for userdir in os.listdir(basedir):
|
|
||||||
if xferType:
|
|
||||||
userdir = userdir + '/{0}'.format(xferType)
|
|
||||||
if direction == "to":
|
|
||||||
filedir = os.path.join(basedir,userdir,"outgoing")
|
|
||||||
elif direction == "from":
|
|
||||||
filedir = os.path.join(basedir,userdir,"outgoing")
|
|
||||||
if not os.path.isdir(os.path.join(basedir,userdir)):
|
|
||||||
next
|
|
||||||
for root, dirs, files in os.walk(filedir):
|
|
||||||
for file in files:
|
|
||||||
source = os.path.join(root, file)
|
|
||||||
destination = getdest(direction, source)
|
|
||||||
jobs.append([source,destination,str(timestamp)])
|
|
||||||
for dir in dirs:
|
|
||||||
fulldir = os.path.join(root,dir)
|
|
||||||
if os.listdir(fulldir) == []:
|
|
||||||
try:
|
|
||||||
os.rmdir(fulldir)
|
|
||||||
except OSError, e:
|
|
||||||
tolog("Could not remove {0} because an error "
|
|
||||||
"occurred. Error: {1}.".format(fulldir, e))
|
|
||||||
if jobs == []:
|
|
||||||
return
|
|
||||||
builddestdirs(jobs)
|
|
||||||
pool.map(processonefile, jobs)
|
|
||||||
|
|
||||||
pool = mp.Pool(processes=50)
|
|
||||||
xferType = parseArgs()
|
|
||||||
while True:
|
|
||||||
if logfile.closed:
|
|
||||||
logfile = open(log,'a')
|
|
||||||
try:
|
|
||||||
walktree(homedir,"to")
|
|
||||||
walktree(tempdir,"from")
|
|
||||||
except Exception, e:
|
|
||||||
tosyslog("An error occurred: {0}.".format(e))
|
|
||||||
raise Exception("An error occurred: {0}.".format(e))
|
|
||||||
else:
|
|
||||||
time.sleep(5)
|
|
||||||
logfile.close()
|
|
||||||
|
|
||||||
6
flake.lock
generated
6
flake.lock
generated
|
|
@ -20,11 +20,11 @@
|
||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1712883908,
|
"lastModified": 1722009787,
|
||||||
"narHash": "sha256-icE1IJE9fHcbDfJ0+qWoDdcBXUoZCcIJxME4lMHwvSM=",
|
"narHash": "sha256-JIAhqboOU/JZ8p49lTzTqZbYvPmV6ciUDoQhpLab94w=",
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "a0c9e3aee1000ac2bfb0e5b98c94c946a5d180a9",
|
"rev": "9014875e6f995a84dd72072e5ef73313e5665faa",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
|
||||||
47
flake.nix
47
flake.nix
|
|
@ -4,7 +4,7 @@
|
||||||
nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
|
nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
|
||||||
flake-utils.url = "github:numtide/flake-utils";
|
flake-utils.url = "github:numtide/flake-utils";
|
||||||
};
|
};
|
||||||
outputs = inputs @ {self, nixpkgs, flake-utils, ...}:
|
outputs = {self, nixpkgs, flake-utils, ...}:
|
||||||
flake-utils.lib.eachDefaultSystem (system: let
|
flake-utils.lib.eachDefaultSystem (system: let
|
||||||
recursiveMerge = attrList: let
|
recursiveMerge = attrList: let
|
||||||
f = attrPath:
|
f = attrPath:
|
||||||
|
|
@ -24,53 +24,33 @@
|
||||||
plugins = import ./plugins.nix {
|
plugins = import ./plugins.nix {
|
||||||
inherit pkgs;
|
inherit pkgs;
|
||||||
};
|
};
|
||||||
base = {
|
|
||||||
viAlias = true;
|
|
||||||
vimAlias = true;
|
|
||||||
withRuby = false;
|
|
||||||
withPython3 = false;
|
|
||||||
};
|
|
||||||
dependencies = with pkgs; [
|
dependencies = with pkgs; [
|
||||||
ripgrep
|
ripgrep
|
||||||
];
|
|
||||||
full-dependencies = with pkgs; [
|
|
||||||
gopls
|
gopls
|
||||||
pyright
|
pyright
|
||||||
nil
|
nil
|
||||||
] ++ dependencies;
|
phpactor
|
||||||
|
];
|
||||||
neovim-with-deps = recursiveMerge [
|
neovim-with-deps = recursiveMerge [
|
||||||
pkgs.neovim-unwrapped
|
pkgs.neovim-unwrapped
|
||||||
{ buildInputs = dependencies; }
|
{ buildInputs = dependencies; }
|
||||||
];
|
];
|
||||||
neovim-with-full-deps = recursiveMerge [
|
|
||||||
pkgs.neovim-unwrapped
|
|
||||||
{ buildInputs = full-dependencies; }
|
|
||||||
];
|
|
||||||
baseRC = ''
|
baseRC = ''
|
||||||
lua << EOF
|
lua << EOF
|
||||||
package.path = "${self}/config/?.lua;" .. "${self}/config/lua/?.lua;" .. package.path
|
package.path = "${self}/config/?.lua;" .. "${self}/config/lua/?.lua;" .. package.path
|
||||||
vim.o.runtimepath = "${self}/config," .. vim.o.runtimepath
|
vim.o.runtimepath = "${self}/config," .. vim.o.runtimepath
|
||||||
'';
|
'';
|
||||||
in rec {
|
in rec {
|
||||||
packages.full = pkgs.wrapNeovim neovim-with-full-deps (base // {
|
packages.neovim = pkgs.wrapNeovim neovim-with-deps ({
|
||||||
|
viAlias = true;
|
||||||
|
vimAlias = true;
|
||||||
|
withRuby = false;
|
||||||
withPython3 = true;
|
withPython3 = true;
|
||||||
extraMakeWrapperArgs = ''--prefix PATH : "${pkgs.lib.makeBinPath full-dependencies}"'';
|
|
||||||
configure = {
|
|
||||||
customRC =
|
|
||||||
baseRC
|
|
||||||
+ pkgs.lib.readFile ./config/init.lua
|
|
||||||
+ ''EOF'';
|
|
||||||
packages.plugins = {
|
|
||||||
start = plugins.base ++ plugins.extra;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
});
|
|
||||||
packages.minimal = pkgs.wrapNeovim neovim-with-deps (base // {
|
|
||||||
extraMakeWrapperArgs = ''--prefix PATH : "${pkgs.lib.makeBinPath dependencies}"'';
|
extraMakeWrapperArgs = ''--prefix PATH : "${pkgs.lib.makeBinPath dependencies}"'';
|
||||||
configure = {
|
configure = {
|
||||||
customRC =
|
customRC =
|
||||||
baseRC
|
baseRC
|
||||||
+ pkgs.lib.readFile ./config/minimal-init.lua
|
+ pkgs.lib.readFile ./config/init.lua
|
||||||
+ ''EOF'';
|
+ ''EOF'';
|
||||||
packages.plugins = {
|
packages.plugins = {
|
||||||
start = plugins.base;
|
start = plugins.base;
|
||||||
|
|
@ -78,13 +58,10 @@
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
apps.full = flake-utils.lib.mkApp {
|
apps.neovim = flake-utils.lib.mkApp {
|
||||||
drv = packages.full; name = "neovim"; exePath = "/bin/nvim";
|
drv = packages.neovim; name = "neovim"; exePath = "/bin/nvim";
|
||||||
};
|
};
|
||||||
apps.minimal = flake-utils.lib.mkApp {
|
apps.default = apps.neovim;
|
||||||
drv = packages.minimal; name = "neovim"; exePath = "/bin/nvim";
|
packages.default = packages.neovim;
|
||||||
};
|
|
||||||
apps.default = apps.full;
|
|
||||||
packages.default = packages.full;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
25
plugins.nix
25
plugins.nix
|
|
@ -1,19 +1,20 @@
|
||||||
{pkgs, ...}:
|
{pkgs, ...}:
|
||||||
{
|
{
|
||||||
base = with pkgs.vimPlugins; [
|
base = with pkgs.vimPlugins; [
|
||||||
telescope-nvim
|
diffview-nvim
|
||||||
telescope-fzf-native-nvim
|
|
||||||
toggleterm-nvim
|
|
||||||
mini-nvim
|
|
||||||
];
|
|
||||||
extra = with pkgs.vimPlugins; [
|
|
||||||
rose-pine
|
|
||||||
gitsigns-nvim
|
gitsigns-nvim
|
||||||
oil-nvim
|
mini-nvim
|
||||||
nvim-lspconfig
|
|
||||||
nvim-treesitter.withAllGrammars
|
|
||||||
nvim-treesitter-textobjects
|
|
||||||
vim-nix
|
|
||||||
neogit
|
neogit
|
||||||
|
nvim-lspconfig
|
||||||
|
nvim-treesitter-textobjects
|
||||||
|
nvim-treesitter.withAllGrammars
|
||||||
|
oil-nvim
|
||||||
|
refactoring-nvim
|
||||||
|
rose-pine
|
||||||
|
telescope-fzf-native-nvim
|
||||||
|
telescope-nvim
|
||||||
|
toggleterm-nvim
|
||||||
|
undotree
|
||||||
|
vim-nix
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue