diff --git a/home-cli.nix b/home-cli.nix index 48a4288..f6fd851 100644 --- a/home-cli.nix +++ b/home-cli.nix @@ -2,10 +2,9 @@ let secrets = import ./secrets.nix; - nixvim = import (builtins.fetchGit { url = "https://github.com/nix-community/nixvim"; }); in { - home.stateVersion = "24.11"; + home.stateVersion = "26.05"; home.username = "dustinswan"; home.shell.enableShellIntegration = true; @@ -16,7 +15,6 @@ in }; imports = [ - nixvim.homeModules.nixvim ./home-nvim.nix ]; @@ -25,7 +23,7 @@ in bitwarden-cli awscli2 claude-code - claude-code-acp + # claude-code-acp opencode # see also: aider; toad; fd poppler-utils # pdftotext @@ -48,16 +46,17 @@ in cacert nodejs typescript + bun pnpm rustc cargo uv blade-formatter nixd # Nix language server - nodePackages.typescript-language-server - nodePackages.stylelint - nodePackages.js-beautify - nodePackages.intelephense + typescript-language-server + stylelint + js-beautify + intelephense dict ispell aspell @@ -80,6 +79,7 @@ in }; home.sessionPath = [ + "$HOME/.cache/.bun/bin" "$HOME/.local/bin" "$HOME/.cargo/bin" "$HOME/.npm-global/bin" diff --git a/home-gui.nix b/home-gui.nix index 41e68ae..63391c7 100644 --- a/home-gui.nix +++ b/home-gui.nix @@ -1,10 +1,11 @@ { pkgs, ... }: { - fonts.fontconfig.enable = true; + # fonts.fontconfig.enable = true; home.packages = with pkgs; [ localsend + # deskflow ]; programs.sioyek.enable = true; @@ -12,8 +13,6 @@ programs.halloy = { enable = true; settings = { - # theme = "catppuccin-mocha"; - servers.liberachat = { nickname = "sw4n"; server = "irc.libera.chat"; @@ -31,7 +30,7 @@ font-family = "Iosevka NFM"; font-size = 12; font-thicken = true; - theme = "dark:One Half Dark,light:One Half Light"; + theme = "dark:TokyoNight Storm,light:TokyoNight Day"; background-opacity = 0.95; background-blur-radius = 15; window-padding-x = 12; @@ -44,22 +43,22 @@ }; }; - # programs.zed-editor = { - # enable = true; - # userSettings = { - # vim_mode = true; - # theme = { - # mode = "system"; - # light = "Catppuccin Latte"; - # dark = "Catppuccin Frappé"; - # }; - # buffer_font_size = 16; - # buffer_font_family = "Iosevka Nerd Font Mono"; - # vim = { - # enable_vim_sneak = true; - # use_smartcase_find = true; - # }; - # format_on_save = "off"; - # }; - # }; + programs.zed-editor = { + enable = true; + userSettings = { + vim_mode = true; + theme = { + mode = "system"; + light = "Tokyo Night Light"; + dark = "Tokyo Night Storm"; + }; + buffer_font_size = 16; + buffer_font_family = "Iosevka Nerd Font Mono"; + vim = { + enable_vim_sneak = true; + use_smartcase_find = true; + }; + format_on_save = "off"; + }; + }; } diff --git a/home-nvim.nix b/home-nvim.nix index ebc3284..d3e4489 100644 --- a/home-nvim.nix +++ b/home-nvim.nix @@ -1,153 +1,21 @@ -{ ... }: +{ pkgs, ... }: { - programs.nixvim = { + programs.neovim = { enable = true; viAlias = true; vimAlias = true; - withNodeJs = true; - withRuby = true; - - opts = { - number = true; - ignorecase = true; - smartcase = true; - - tabstop = 4; - shiftwidth = 4; - softtabstop = 0; - expandtab = true; - smarttab = true; - - clipboard = "unnamedplus"; - }; - - globals = { - mapleader = " "; - maplocalleader = " "; - }; - - autoCmd = [ - { - event = [ "BufRead" "BufNewFile" ]; - pattern = [ "*.cg" ]; - command = "setlocal tabstop=2 shiftwidth=2"; - } - ]; - - keymaps = [ - { key = "e"; action = "Neotree toggle"; } - { key = "f"; action = "Tv files"; } - { key = "/"; action = "Tv text"; } - { key = "bd"; action = "bdelete"; } - { key = "nd"; action = "NoiceDismiss"; } - { key = "xx"; action = "Trouble diagnostics toggle"; } - { key = ""; action = "bnext"; } - { key = ""; action = "bprev"; } - { key = "s"; mode = [ "n" "x" "o" ]; action.__raw = "function() require('flash').jump() end"; options.desc = "Flash"; } - { key = "S"; mode = [ "n" "x" "o" ]; action.__raw = "function() require('flash').treesitter() end"; options.desc = "Flash Treesitter"; } - ]; - - plugins = { - # avante.enable = true; - bufferline.enable = true; - cmp = { - enable = true; - autoEnableSources = true; - settings = { - sources = [ - { name = "nvim_lsp"; } - { name = "path"; } - { name = "buffer"; } - ]; - mapping = { - "" = "cmp.mapping.select_next_item()"; - "" = "cmp.mapping.select_prev_item()"; - "" = "cmp.mapping.confirm({ select = false })"; - "" = "cmp.mapping.abort()"; - }; - }; - }; - cmp-nvim-lsp.enable = true; - cmp-buffer.enable = true; - cmp-path.enable = true; - codecompanion = { - enable = true; - settings = { - strategies = { - chat = { adapter = "claude_code"; }; - inline = { adapter = "claude_code"; }; - }; - }; - }; - commentary.enable = true; - csvview.enable = true; - dashboard.enable = true; - emmet.enable = true; - flash = { - enable = true; - settings.jump.autojump = true; - # settings.modes.search.enabled = true; - }; - gitsigns.enable = true; - lazygit.enable = true; - lint.enable = true; - lualine.enable = true; - luasnip.enable = true; - lsp = { - enable = true; - inlayHints = true; - servers = { - eslint.enable = true; - elixirls.enable = true; - html.enable = true; - lua_ls.enable = true; - nil_ls.enable = true; - # phpactor.enable = true; - intelephense.enable = true; - intelephense.package = null; - # rust-analyzer.enable = true; - ts_ls.enable = true; - roc_ls.enable = true; - roc_ls.package = null; - }; - }; - none-ls = { - enable = true; - sources.formatting.blade_formatter.enable = true; - sources.formatting.blade_formatter.package = null; - }; - # lsp-format.enable = true; - lsp-lines.enable = true; - # markview.enable = true; - neo-tree.enable = true; - notify.enable = true; - nix.enable = true; - noice.enable = true; - nvim-autopairs.enable = true; - orgmode = { - enable = true; - settings.org_agenda_files = "~/Sync/Notes/*"; - settings.org_default_notes_file = "~/Sync/Notes/Main.org"; - }; - persistence.enable = true; - vim-surround.enable = true; - tmux-navigator.enable = true; - todo-comments.enable = true; - treesitter.enable = true; - trim = { - enable = true; - settings = { - highlight = true; - trim_on_write = false; - ft_blocklist = [ "dashboard" ]; - }; - }; - trouble.enable = true; - ts-autotag.enable = true; - tv.enable = true; - web-devicons.enable = true; - which-key.enable = true; - }; }; + + xdg.configFile."nvim/init.lua".source = ./init.lua; + + home.packages = with pkgs; [ + # LSP servers (others already in home-cli.nix: nixd, typescript-language-server, intelephense) + vscode-langservers-extracted # eslint, html, css, json + elixir-ls + lua-language-server + + # Treesitter parser compilation + tree-sitter + ]; } diff --git a/init.lua b/init.lua new file mode 100644 index 0000000..646dc95 --- /dev/null +++ b/init.lua @@ -0,0 +1,208 @@ +---@diagnostic disable: undefined-global + +-- Options +vim.o.number = true +vim.o.ignorecase = true +vim.o.smartcase = true +vim.o.tabstop = 4 +vim.o.shiftwidth = 4 +vim.o.expandtab = true +vim.o.smarttab = true +vim.o.clipboard = 'unnamedplus' +vim.o.completeopt = 'menuone,noselect,popup' + +vim.g.mapleader = ' ' +vim.g.maplocalleader = ' ' + +-- Autocmds +vim.api.nvim_create_autocmd({ 'BufRead', 'BufNewFile' }, { + pattern = '*.cg', + command = 'setlocal tabstop=2 shiftwidth=2', +}) + +-- Helper +local gh = function(repo) return 'https://github.com/' .. repo end + +-- Plugins +vim.pack.add({ + -- Dependencies + gh('nvim-lua/plenary.nvim'), -- lua utility functions used by many plugins + gh('MunifTanjim/nui.nvim'), -- UI component library used by neo-tree + gh('nvim-tree/nvim-web-devicons'), -- file type icons + + -- Theme + gh('folke/tokyonight.nvim'), -- auto light/dark theme, follows OS appearance + + -- UI + gh('akinsho/bufferline.nvim'), -- tab bar for open buffers, :bnext/:bprev + gh('nvim-lualine/lualine.nvim'), -- status line at bottom + gh('nvim-neo-tree/neo-tree.nvim'), -- file explorer, e to toggle + gh('folke/which-key.nvim'), -- shows available keybinds after pressing a key + gh('folke/trouble.nvim'), -- diagnostics list, xx to toggle + gh('folke/todo-comments.nvim'), -- highlights TODO/FIXME/HACK in comments + + -- Editor + gh('folke/flash.nvim'), -- quick jump, press s then type target chars + gh('kylechui/nvim-surround'), -- cs"' to change surrounding " to ' + gh('windwp/nvim-autopairs'), -- auto-close brackets and quotes + gh('cappyzawa/trim.nvim'), -- highlights and trims trailing whitespace + gh('christoomey/vim-tmux-navigator'), -- ctrl-h/j/k/l to move between vim and tmux panes + gh('folke/persistence.nvim'), -- auto-saves and restores sessions per directory + + -- Git + gh('lewis6991/gitsigns.nvim'), -- git diff markers in the sign column + + -- Formatting + gh('nvimtools/none-ls.nvim'), -- bridge external formatters/linters to LSP + + -- Language support + gh('hat0uma/csvview.nvim'), -- aligned column view for CSV files + gh('mattn/emmet-vim'), -- expand abbreviations, e.g. div>ul>li then ctrl-y, + gh('nvim-orgmode/orgmode'), -- org-mode notes/agenda in nvim + { src = gh('nvim-treesitter/nvim-treesitter'), version = 'main' }, -- syntax tree parsing for highlighting/code nav + + -- AI + gh('supermaven-inc/supermaven-nvim'), -- inline ghost-text suggestions, Tab to accept + + -- Fuzzy finder + gh('alexpasmantier/television.nvim'), -- fuzzy finder, f for files, / for text +}, { confirm = false }) + +-- Theme (auto light/dark based on OS appearance) +require('tokyonight').setup({ + style = 'storm', + light_style = 'day', +}) +vim.cmd.colorscheme('tokyonight') + +-- Plugin configs +require('bufferline').setup() +require('lualine').setup() +require('neo-tree').setup({}) +require('which-key').setup() +require('trouble').setup() +require('todo-comments').setup() +require('flash').setup({ jump = { autojump = true } }) +require('nvim-surround').setup() +require('nvim-autopairs').setup() +require('trim').setup({ + highlight = true, + trim_on_write = false, + ft_blocklist = { 'dashboard' }, +}) +require('persistence').setup() +require('gitsigns').setup() +require('csvview').setup() +require('supermaven-nvim').setup({}) +require('orgmode').setup({ + org_agenda_files = '~/Sync/Notes/*', + org_default_notes_file = '~/Sync/Notes/Main.org', +}) +-- none-ls (blade_formatter) +local null_ls = require('null-ls') +null_ls.setup({ + sources = { + null_ls.builtins.formatting.blade_formatter, + }, +}) + +-- Treesitter +vim.api.nvim_create_autocmd('FileType', { + callback = function() + pcall(vim.treesitter.start) + end, +}) + +-- New UI (0.12+) +require('vim._core.ui2').enable({}) + +-- Diagnostics +vim.diagnostic.config({ virtual_lines = true }) + +-- LSP +vim.lsp.config('*', { + root_markers = { '.git' }, +}) + +vim.lsp.config('elixirls', { + cmd = { 'elixir-ls' }, + filetypes = { 'elixir', 'eelixir', 'heex', 'surface' }, + root_markers = { 'mix.exs', '.git' }, +}) + +vim.lsp.config('html', { + cmd = { 'vscode-html-language-server', '--stdio' }, + filetypes = { 'html' }, +}) + +vim.lsp.config('lua_ls', { + cmd = { 'lua-language-server' }, + filetypes = { 'lua' }, + root_markers = { '.luarc.json', '.luarc.jsonc', '.git' }, + settings = { + Lua = { runtime = { version = 'LuaJIT' } }, + }, +}) + +vim.lsp.config('nixd', { + cmd = { 'nixd' }, + filetypes = { 'nix' }, + root_markers = { 'flake.nix', 'default.nix', 'shell.nix', '.git' }, +}) + +vim.lsp.config('intelephense', { + cmd = { 'intelephense', '--stdio' }, + filetypes = { 'php' }, + root_markers = { 'composer.json', '.git' }, +}) + +vim.lsp.config('ts_ls', { + cmd = { 'typescript-language-server', '--stdio' }, + filetypes = { 'typescript', 'typescriptreact', 'javascript', 'javascriptreact' }, + root_markers = { 'tsconfig.json', 'jsconfig.json', 'package.json', '.git' }, +}) + +vim.lsp.config('roc_ls', { + cmd = { 'roc_language_server' }, + filetypes = { 'roc' }, + root_markers = { '.git' }, +}) + +vim.lsp.enable({ + 'elixirls', 'html', 'lua_ls', 'nixd', + 'intelephense', 'ts_ls', 'roc_ls', +}) + +-- LSP attach: completion + inlay hints +vim.api.nvim_create_autocmd('LspAttach', { + callback = function(args) + local client = vim.lsp.get_client_by_id(args.data.client_id) + if client and client.supports_method('textDocument/inlayHint') then + vim.lsp.inlay_hint.enable(true, { bufnr = args.buf }) + end + vim.lsp.completion.enable(true, args.data.client_id, args.buf) + end, +}) + +-- Keymaps +vim.keymap.set('n', 'e', 'Neotree toggle') +vim.keymap.set('n', 'f', 'Tv files') +vim.keymap.set('n', '/', 'Tv text') +vim.keymap.set('n', 'bd', 'bdelete') +vim.keymap.set('n', 'xx', 'Trouble diagnostics toggle') +vim.keymap.set('n', '', 'bnext') +vim.keymap.set('n', '', 'bprev') +vim.keymap.set({ 'n', 'x', 'o' }, 's', function() require('flash').jump() end, { desc = 'Flash' }) +vim.keymap.set({ 'n', 'x', 'o' }, 'S', function() require('flash').treesitter() end, { desc = 'Flash Treesitter' }) + +-- Completion keymaps +vim.keymap.set('i', '', function() + return vim.fn.pumvisible() == 1 and '' or '' +end, { expr = true }) +vim.keymap.set('i', '', function() + return vim.fn.pumvisible() == 1 and '' or '' +end, { expr = true }) +vim.keymap.set('i', '', function() + return (vim.fn.pumvisible() == 1 and vim.fn.complete_info({ 'selected' }).selected >= 0) + and '' or '' +end, { expr = true })