{ pkgs, ... }: let vp = pkgs.vimPlugins; goose-nvim = pkgs.vimUtils.buildVimPlugin { pname = "goose-nvim"; version = "2024-11-14"; src = pkgs.fetchFromGitHub { owner = "azorng"; repo = "goose.nvim"; rev = "0698a59bfad00018cbe450be8d8e0896c46def80"; sha256 = "sha256-3Qj3HTrMX2dIPvK6/Z6pILZj7Xr2RZ33NwYCpu50vW4="; }; dependencies = [ vp.plenary-nvim ]; meta.homepage = "https://github.com/azorng/goose.nvim"; }; in { home.packages = [ pkgs.nodePackages.prettier pkgs.goose-cli pkgs.gemini-cli ]; programs.neovim = { enable = true; viAlias = true; vimAlias = true; vimdiffAlias = true; withPython3 = true; plugins = [ vp.plenary-nvim # # Git related plugins # vp.fugitive # vp.rhubarb vp.gitgutter vp.mini-icons { plugin = vp.alpha-nvim; type = "lua"; config = '' require'alpha'.setup(require'alpha.themes.dashboard'.config) ''; } # vp.lsp-zero-nvim # vp.nvim-cmp # vp.cmp-nvim-lsp # vp.nvim-lspconfig { plugin = vp.nvim-surround; type = "lua"; config = ''require("nvim-surround").setup({})''; } # { # plugin = vp.autoclose-nvim; # type = "lua"; # config = '' # require("autoclose").setup({}) # ''; # } vp.telescope-fzf-native-nvim { plugin = vp.telescope-nvim; type = "lua"; config = builtins.readFile ./nvim/telescope-config.lua; } # Better UI for input and selection vp.dressing-nvim # # Tree view # { # plugin = vp.chadtree; # type = "lua"; # config = '' # local chadtree = require("chadtree") # # local chadtree_settings = { } # vim.api.nvim_set_var("chadtree_settings", chadtree_settings) # # vim.keymap.set({ "n", "v" }, "v", "CHADopen", { desc = "Toggle file tree" }) # ''; # } vp.cmp-buffer # source for text in buffer vp.cmp-path # source for file system path vp.luasnip { plugin = vp.luasnip; type = "lua"; config = '' local luasnip = require("luasnip") local keymap = vim.keymap keymap.set({"i"}, "", function() luasnip.expand() end, {silent = true}) keymap.set({"i", "s"}, "", function() luasnip.jump( 1) end, {silent = true}) keymap.set({"i", "s"}, "", function() luasnip.jump(-1) end, {silent = true}) vim.keymap.set({"i", "s"}, "", function() if luasnip.choice_active() then luasnip.change_choice(1) end end, {silent = true}) -- loads vscode style snippets from installed plugins (eg. friendly-snippets) require("luasnip.loaders.from_vscode").lazy_load() require("luasnip.loaders.from_vscode").lazy_load({ paths = "${./nvim/snippets}" }) ''; } vp.cmp_luasnip vp.friendly-snippets { plugin = vp.nvim-cmp; type = "lua"; config = builtins.readFile ./nvim/nvim-cmp-config.lua; } # Undo tree { plugin = vp.undotree; type = "lua"; config = '' vim.keymap.set({ "n", "v" }, "u", vim.cmd.UndotreeToggle, { desc = "Toggle undo tree" }) ''; } vp.markdown-preview-nvim # # Detect tabstop and shiftwidth automatically # vp.sleuth # LSP # fidget moving while LSP is working { plugin = vp.fidget-nvim; type = "lua"; config = ''require("fidget").setup({})''; } vp.cmp-nvim-lsp vp.lsp-format-nvim { plugin = vp.nvim-lspconfig; type = "lua"; config = builtins.readFile ./nvim/nvim-lspconfig-config.lua; } # Cool color scheme { plugin = vp.nightfox-nvim; type = "lua"; config = '' vim.cmd [[colorscheme carbonfox]] ''; } vp.nvim-web-devicons # Set lualine as statusline { plugin = vp.lualine-nvim; config = '' require("lualine").setup({ options = { icons_enabled = false, theme = "carbonfox", component_separators = "|", section_separators = "", }, }) ''; type = "lua"; } # # Add indentation guides even on blank lines # { # # See `:help ibl` # plugin = vp.indent-blankline-nvim; # config = '' # require("ibl").setup({}) # ''; # type = "lua"; # } # "gcc" or "gcb" to comment visual regions/lines { plugin = vp.comment-nvim; config = '' require("Comment").setup({}) ''; type = "lua"; } vp.nvim-treesitter.withAllGrammars { plugin = vp.nvim-treesitter-textobjects; type = "lua"; config = '' require'nvim-treesitter.configs'.setup { textobjects = { select = { enable = true, -- Automatically jump forward to textobj, similar to targets.vim lookahead = true, keymaps = { -- You can use the capture groups defined in textobjects.scm ["af"] = "@function.outer", ["if"] = "@function.inner", ["ac"] = "@class.outer", -- You can optionally set descriptions to the mappings (used in the desc parameter of -- nvim_buf_set_keymap) which plugins like which-key display ["ic"] = { query = "@class.inner", desc = "Select inner part of a class region" }, -- You can also use captures from other query groups like `locals.scm` ["as"] = { query = "@scope", query_group = "locals", desc = "Select language scope" }, }, -- You can choose the select mode (default is charwise 'v') -- -- Can also be a function which gets passed a table with the keys -- * query_string: eg '@function.inner' -- * method: eg 'v' or 'o' -- and should return the mode ('v', 'V', or '') or a table -- mapping query_strings to modes. selection_modes = { ['@parameter.outer'] = 'v', -- charwise ['@function.outer'] = 'V', -- linewise ['@class.outer'] = '', -- blockwise }, -- If you set this to `true` (default is `false`) then any textobject is -- extended to include preceding or succeeding whitespace. Succeeding -- whitespace has priority in order to act similarly to eg the built-in -- `ap`. -- -- Can also be a function which gets passed a table with the keys -- * query_string: eg '@function.inner' -- * selection_mode: eg 'v' -- and should return true or false include_surrounding_whitespace = true, }, }, highlight = { enable = true, -- Setting this to true will run `:h syntax` and tree-sitter at the same time. -- Set this to `true` if you depend on 'syntax' being enabled (like for indentation). -- Using this option may slow down your editor, and you may see some duplicate highlights. -- Instead of true it can also be a list of languages additional_vim_regex_highlighting = false, }, incremental_selection = { enable = true, keymaps = { init_selection = "gnn", -- set to `false` to disable one of the mappings node_incremental = "grn", scope_incremental = "grc", node_decremental = "grm", }, }, indent = { enable = true } } ''; } # Highlighting { plugin = vp.nvim-colorizer-lua; type = "lua"; config = '' local colorizer = require ("colorizer") colorizer.setup { css = true, mode = "background", tailwind = true, } --[[ require("colorizer").attach_to_buffer(0, { mode = "background", css = true}) require("colorizer").detach_from_buffer(0, { mode = "virtualtext", css = true}) ]]-- ''; } # Formatting { plugin = vp.conform-nvim; type = "lua"; config = '' ''; } { plugin = vp.nvim-autopairs; type = "lua"; config = '' local npairs = require("nvim-autopairs") npairs.setup({check_ts = true}) ''; } { plugin = vp.nvim-ts-autotag; type = "lua"; config = '' require('nvim-ts-autotag').setup() vim.lsp.handlers['textDocument/publishDiagnostics'] = vim.lsp.with( vim.lsp.diagnostic.on_publish_diagnostics, { underline = true, virtual_text = { spacing = 5 }, update_in_insert = true, } ) ''; } vp.nvim-treesitter-context { plugin = vp.trouble-nvim; type = "lua"; config = '' require('trouble').setup() vim.keymap.set({"n"}, "xx", "Trouble diagnostics toggle") vim.keymap.set({"n"}, "xX", "Trouble diagnostics toggle filter.buf=0") vim.keymap.set({"n"}, "xq", "Trouble qflist toggle") vim.keymap.set({"n"}, "xl", "Trouble loclist toggle") ''; } { plugin = vp.conform-nvim; type = "lua"; config = '' require("conform").setup({ formatters_by_ft = { css = { "prettier" }, graphql = { "prettier" }, html = { "prettier" }, javascript = { "prettier" }, javascriptreact = { "prettier" }, json = { "prettier" }, markdown = { "prettier" }, svelte = { "prettier" }, typescript = { "prettier" }, typescriptreact = { "prettier" }, yaml = { "prettier" }, -- lua = { "stylua" } }, format_on_save = { -- These options will be passed to conform.format() timeout_ms = 500, lsp_format = "fallback", }, }) ''; } vp.diffview-nvim vp.neogit { plugin = vp.ollama-nvim; type = "lua"; # local token = readAll("${nixosConfig.age.secrets.ollama.path}") config = '' local conf = { -- url = string.format("https://bertof:%s@ollama.ricerca.sesar.di.unimi.it/", token), model = "codegemma:7b", options = { temperature = 0.6, num_ctx = 8192 } } local ollama = require("ollama") ollama.setup(conf) ''; } { plugin = goose-nvim; type = "lua"; config = '' require('goose').setup({ prefered_picker = nil, -- 'telescope', 'fzf', 'mini.pick', 'snacks', if nil, it will use the best available picker default_global_keymaps = true, -- If false, disables all default global keymaps keymap = { global = { toggle = 'gg', -- Open goose. Close if opened open_input = 'gi', -- Opens and focuses on input window on insert mode open_input_new_session = 'gI', -- Opens and focuses on input window on insert mode. Creates a new session open_output = 'go', -- Opens and focuses on output window toggle_focus = 'gt', -- Toggle focus between goose and last window close = 'gq', -- Close UI windows toggle_fullscreen = 'gf', -- Toggle between normal and fullscreen mode select_session = 'gs', -- Select and load a goose session goose_mode_chat = 'gmc', -- Set goose mode to `chat`. (Tool calling disabled. No editor context besides selections) goose_mode_auto = 'gma', -- Set goose mode to `auto`. (Default mode with full agent capabilities) configure_provider = 'gp', -- Quick provider and model switch from predefined list diff_open = 'gd', -- Opens a diff tab of a modified file since the last goose prompt diff_next = 'g]', -- Navigate to next file diff diff_prev = 'g[', -- Navigate to previous file diff diff_close = 'gc', -- Close diff view tab and return to normal editing diff_revert_all = 'gra', -- Revert all file changes since the last goose prompt diff_revert_this = 'grt', -- Revert current file changes since the last goose prompt }, window = { submit = '', -- Submit prompt (normal mode) submit_insert = '', -- Submit prompt (insert mode) close = '', -- Close UI windows stop = '', -- Stop goose while it is running next_message = ']]', -- Navigate to next message in the conversation prev_message = '[[', -- Navigate to previous message in the conversation mention_file = '@', -- Pick a file and add to context. See File Mentions section toggle_pane = '', -- Toggle between input and output panes prev_prompt_history = '', -- Navigate to previous prompt in history next_prompt_history = '' -- Navigate to next prompt in history } }, ui = { window_width = 0.35, -- Width as percentage of editor width input_height = 0.15, -- Input height as percentage of window height fullscreen = false, -- Start in fullscreen mode (default: false) layout = "right", -- Options: "center" or "right" floating_height = 0.8, -- Height as percentage of editor height for "center" layout display_model = true, -- Display model name on top winbar display_goose_mode = true -- Display mode on top winbar: auto|chat }, providers = { --[[ Define available providers and their models for quick model switching anthropic|azure|bedrock|databricks|google|groq|ollama|openai|openrouter Example: -- openrouter = { -- "anthropic/claude-3.5-sonnet", -- "openai/gpt-4.1", -- }, --]] ollama = { "gpt-oss:20b-cloud", "embeddinggemma:latest", "codegemma:2b", "gemma3:latest", "granite4:tiny-h", "deepseek-r1:7b", "codegemma:latest", "codegemma:7b", "qwen3:latest", "gemma3:12b", "deepseek-r1:14b", "qwen3:14b" } } }) ''; } ]; # settings = { ignorecase = true; }; # coc.enable = true; # extraConfig = '' # let g:airline_powerline_fonts = 1 # ''; extraLuaConfig = '' function readAll(file) local f = assert(io.open(file, "rb")) local content = f:read("*all") f:close() return string.gsub(content, "%s+", "") end -- Setup local o = vim.o local g = vim.g local opt = vim.opt -- Font o.guifont = "FiraCode Nerd Font Mono 10" -- Status bar o.laststatus = 3 o.showmode = false -- Clipboard -- o.clipboard = "unnamedplus" -- Cursor o.cursorline = true o.cursorlineopt = "number" -- Indenting o.expandtab = true o.shiftwidth = 2 o.smartindent = true o.tabstop = 2 o.softtabstop = 2 -- Search o.ignorecase = true o.smartcase = true -- Mouse o.mouse = "a" -- Numbers o.number = true -- Obisidan requirement o.conceallevel = 1 -- disable nvim intro -- opt.shortmess:append "sI" -- Symbols o.signcolumn = "yes" o.splitbelow = true o.splitright = true o.timeoutlen = 400 o.undofile = true -- interval for writing swap file to disk, also used by gitsigns o.updatetime = 250 -- go to previous/next line with h,l,left arrow and right arrow -- when cursor reaches end/beginning of line opt.whichwrap:append "<>[]hl" g.mapleader = " " -- treesitter folding opt.foldmethod = "expr" opt.foldexpr = "nvim_treesitter#foldexpr()" -- vim.cmd([[ set nofoldenable]]) opt.foldenable = false -- spell checking opt.spell = true opt.spelllang = "en_us" ''; }; }