diff --git a/.neoconf.json b/.neoconf.json new file mode 100644 index 0000000..862f185 --- /dev/null +++ b/.neoconf.json @@ -0,0 +1,13 @@ +{ + "lspconfig": { + "nixd": { + "nixd": { + "options": { + "nixos": { + "expr": "(builtins.getFlake (builtins.toString ./.)).nixosConfigurations.${builtins.replaceStrings [\"\n\"] [\"\"] (builtins.readFile \"/etc/hostname\")}.options" + } + } + } + } + } +} diff --git a/configuration.nix b/configuration.nix index 53480ad..5372ffb 100644 --- a/configuration.nix +++ b/configuration.nix @@ -9,7 +9,8 @@ ... }: with lib; -with lib.my; { +with lib.my; +{ # NixOS configuration nix = { settings = { @@ -28,7 +29,7 @@ with lib.my; { !include ${config.sops.templates."nix/access_tokens.conf".path} ''; package = pkgs.nixVersions.latest; - nixPath = ["nixpkgs=${inputs.nixpkgs}"]; + nixPath = [ "nixpkgs=${inputs.nixpkgs}" ]; }; nixpkgs.pkgs = pkgs; @@ -91,67 +92,85 @@ with lib.my; { # Global packages environment = { - systemPackages = with pkgs; [neovim git bash]; - variables = { - EDITOR = "nvim"; - }; - shells = with pkgs; [bash]; + systemPackages = with pkgs; [ + git + bash + ]; + shells = with pkgs; [ bash ]; }; # Linux Kernel settings boot = { - supportedFilesystems = ["ntfs"]; - - initrd.availableKernelModules = ["ehci_pci" "ahci" "nvme" "xhci_pci" "usbhid" "usb_storage" "sd_mod"]; + supportedFilesystems = [ "ntfs" ]; + + initrd.availableKernelModules = [ + "ehci_pci" + "ahci" + "nvme" + "xhci_pci" + "usbhid" + "usb_storage" + "sd_mod" + ]; loader.efi.canTouchEfiVariables = true; tmp.cleanOnBoot = true; plymouth = { enable = true; - themePackages = with pkgs; [nixos-blur-plymouth]; + themePackages = with pkgs; [ nixos-blur-plymouth ]; theme = "nixos-blur"; }; }; # SOPS - sops = let - base = "nix/access-tokens"; - secretNames = utils.recursiveReadSecretNames {inherit config base;}; - secrets = utils.readSecrets {inherit config base;}; - in { - templates = { - "nix/access_tokens.conf" = { - mode = "0440"; - group = config.users.groups.keys.name; - content = '' - access-tokens = ${ - lib.concatStringsSep " " - ( - builtins.map - (entry: "${entry}=${utils.mkSecretPlaceholder config [base entry]}") - (builtins.attrNames secrets) - ) - } - ''; + sops = + let + base = "nix/access-tokens"; + secretNames = utils.recursiveReadSecretNames { inherit config base; }; + secrets = utils.readSecrets { inherit config base; }; + in + { + templates = { + "nix/access_tokens.conf" = { + mode = "0440"; + group = config.users.groups.keys.name; + content = '' + access-tokens = ${ + lib.concatStringsSep " " ( + builtins.map ( + entry: + "${entry}=${ + utils.mkSecretPlaceholder config [ + base + entry + ] + }" + ) (builtins.attrNames secrets) + ) + } + ''; + }; }; + secrets = { + "users/${username}/password".neededForUsers = true; + } // lib.listToAttrs (builtins.map (v: lib.nameValuePair v { }) secretNames); }; - secrets = - {"users/${username}/password".neededForUsers = true;} - // lib.listToAttrs (builtins.map (v: lib.nameValuePair v {}) secretNames); - }; # User settings users.users.${username} = { isNormalUser = true; hashedPasswordFile = config.sops.secrets."users/${username}/password".path; description = "Krzysztof Saczuk"; - extraGroups = ["wheel" config.users.groups.keys.name]; + extraGroups = [ + "wheel" + config.users.groups.keys.name + ]; }; # Home-manager home-manager = { - extraSpecialArgs = {inherit pkgs lib;}; + extraSpecialArgs = { inherit pkgs lib; }; sharedModules = [ inputs.nix-colors.homeManagerModule inputs.sops-nix.homeManagerModule @@ -174,6 +193,25 @@ with lib.my; { services.xdg.enable = true; hardware.grub.enable = true; shell = { + neovim = { + enable = true; + lspPackages = with pkgs; [ + # Lua + lua-language-server + stylua + + # Nix + deadnix + statix + nixd + inputs.nixfmt.default + ]; + treesitterGrammars = [ + "lua" + "luap" + "nix" + ]; + }; fish = { enable = true; default = true; diff --git a/dotfiles/nvim/init.lua b/dotfiles/nvim/init.lua new file mode 100644 index 0000000..936caf9 --- /dev/null +++ b/dotfiles/nvim/init.lua @@ -0,0 +1,34 @@ +local lazy_path = vim.fn.stdpath("data") .. "/lazy/lazy.nvim" + +if not (vim.uv or vim.loop).fs_stat(lazy_path) then + vim.fn.system({ "git", "clone", "--filter=blob:none", "https://github.com/folke/lazy.nvim.git", "--branch=stable", + lazy_path }) +end + +vim.opt.rtp:prepend(lazy_path) + +if not pcall(require, "lazy") then + vim.api.nvim_echo( + { { ("Unable to load lazy from: %s\n"):format(lazy_path), "ErrorMsg" }, { "Press any key to exit...", "MoreMsg" } }, + true, {}) + vim.fn.getchar() + vim.cmd.quit() +end + +require("lazy").setup({ + { + "AstroNvim/AstroNvim", + version = "^4", + import = "astronvim.plugins", + opts = { + icons_enabled = true, + }, + }, + { + "nvim-treesitter/nvim-treesitter", + commit = vim.fn.readfile(vim.fn.stdpath("config") .. "/treesitter-rev", "", 1)[1], + }, + { import = "community" }, + { import = "plugins" }, + { import = "lsp" }, +}) diff --git a/dotfiles/nvim/lua/community.lua b/dotfiles/nvim/lua/community.lua new file mode 100644 index 0000000..f70ca4b --- /dev/null +++ b/dotfiles/nvim/lua/community.lua @@ -0,0 +1,11 @@ +---@type LazySpec +return { + { + "AstroNvim/astrocommunity", + branch = "main" + }, + { import = "astrocommunity.colorscheme.catppuccin" }, + { import = "astrocommunity.pack.lua" }, + { import = "astrocommunity.diagnostics.trouble-nvim" }, + { import = "astrocommunity.utility.hover-nvim" }, +} diff --git a/dotfiles/nvim/lua/lsp/nix.lua b/dotfiles/nvim/lua/lsp/nix.lua new file mode 100644 index 0000000..c72eb30 --- /dev/null +++ b/dotfiles/nvim/lua/lsp/nix.lua @@ -0,0 +1,38 @@ +---@type LazySpec +return { + { + "nvim-treesitter/nvim-treesitter", + opts = { + ensure_installed = { "nix" }, + }, + }, + { + "nvimtools/none-ls.nvim", + opts = function(_, opts) + local builtins = require("null-ls").builtins + + opts.sources = require("astrocore").list_insert_unique(opts.sources, { + builtins.code_actions.statix, + builtins.diagnostics.deadnix, + builtins.formatting.nixfmt, + }) + end, + }, + { + "AstroNvim/astrolsp", + ---@type AstroLSPOpts + opts = { + servers = { "nixd" }, + config = { + nixd = { + nixpkgs = { + expr = "import (builtins.getFlake (builtins.toString ./.)).inputs.nixpkgs { }" + }, + formatting = { + command = { "nixfmt" }, + }, + }, + }, + }, + }, +} diff --git a/dotfiles/nvim/lua/plugins/astrolsp.lua b/dotfiles/nvim/lua/plugins/astrolsp.lua new file mode 100644 index 0000000..430414a --- /dev/null +++ b/dotfiles/nvim/lua/plugins/astrolsp.lua @@ -0,0 +1,11 @@ +---@type LazySpec +return { + "AstroNvim/astrolsp", + ---@type AstroLSPOpts + opts = { + features = { + inlay_hints = true, + signature_help = true, + } + } +} diff --git a/dotfiles/nvim/lua/plugins/discord_rp.lua b/dotfiles/nvim/lua/plugins/discord_rp.lua new file mode 100644 index 0000000..9fb97ae --- /dev/null +++ b/dotfiles/nvim/lua/plugins/discord_rp.lua @@ -0,0 +1,8 @@ +---@type LazySpec +return { + "IogaMaster/neocord", + event = "VeryLazy", + opts = { + log_level = nil, + }, +} diff --git a/dotfiles/nvim/lua/plugins/mappings.lua b/dotfiles/nvim/lua/plugins/mappings.lua new file mode 100644 index 0000000..d2ffdd7 --- /dev/null +++ b/dotfiles/nvim/lua/plugins/mappings.lua @@ -0,0 +1,38 @@ +---@type LazySpec +return { + "AstroNvim/astrocore", + ---@type AstroCoreOpts + opts = { + mappings = { + n = { + -- Neotree: remember last source and make git the default + ["e"] = { "Neotree toggle source=git_status", desc = "Toggle Explorer" }, + ["o"] = { + function() + if vim.bo.filetype == "neo-tree" then + vim.cmd.wincmd("p") + else + vim.cmd.Neotree({ "focus", "source=last" }) + end + end, + desc = "Toggle Explorer Focus", + }, + -- Switch between tabs + [""] = { ":bprev" }, + [""] = { ":bnext" }, + + -- Disable hover.nvim when moving mouse + [""] = false, + }, + t = { + -- Easier escape from the toggleterm.nvim plugin + [""] = { "" }, + [""] = { "" }, + }, + c = { + -- Write file as sudo + ["w!!"] = { "w !sudo tee > /dev/null %", desc = "Write as sudo" }, + }, + } + }, +} diff --git a/dotfiles/nvim/lua/plugins/mason.lua b/dotfiles/nvim/lua/plugins/mason.lua new file mode 100644 index 0000000..1228e37 --- /dev/null +++ b/dotfiles/nvim/lua/plugins/mason.lua @@ -0,0 +1,29 @@ +-- customize mason plugins +local suggested_packages = {} + +--- Clear "ensure_installed" option but add pkgs to a "suggested-pkgs.json" file +--- so that missing pkgs can be installed via Nix dotfiles +local disable_auto_install = function(_, opts) + require("astrocore").list_insert_unique(suggested_packages, opts.ensure_installed or {}) + + local file = io.open(vim.fn.stdpath("data") .. "/suggested-pkgs.json", "w") + file:write(vim.fn.json_encode(suggested_packages)) + file:close() + + opts.ensure_installed = {} +end + +return { + { + "williamboman/mason-lspconfig.nvim", + opts = disable_auto_install, + }, + { + "jay-babu/mason-null-ls.nvim", + opts = disable_auto_install, + }, + { + "jay-babu/mason-nvim-dap.nvim", + opts = disable_auto_install, + }, +} diff --git a/dotfiles/nvim/lua/plugins/neo-tree.lua b/dotfiles/nvim/lua/plugins/neo-tree.lua new file mode 100644 index 0000000..0519fa3 --- /dev/null +++ b/dotfiles/nvim/lua/plugins/neo-tree.lua @@ -0,0 +1,7 @@ +---@type LazySpec +return { + "nvim-neo-tree/neo-tree.nvim", + opts = { + follow_current_file = true, + }, +} diff --git a/dotfiles/nvim/lua/plugins/neoconf.lua b/dotfiles/nvim/lua/plugins/neoconf.lua new file mode 100644 index 0000000..7cb8aaa --- /dev/null +++ b/dotfiles/nvim/lua/plugins/neoconf.lua @@ -0,0 +1,11 @@ +---@types LazySpec +return { + "folke/neoconf.nvim", + opts = { + import = { + vscode = false, + coc = false, + nlsp = false, + } + } +} diff --git a/dotfiles/nvim/lua/plugins/spaceless.lua b/dotfiles/nvim/lua/plugins/spaceless.lua new file mode 100644 index 0000000..055584e --- /dev/null +++ b/dotfiles/nvim/lua/plugins/spaceless.lua @@ -0,0 +1,9 @@ +---@type LazySpec +return { + { + "lewis6991/spaceless.nvim", + init = function() + require("spaceless").setup() + end, + }, +} diff --git a/dotfiles/nvim/lua/plugins/telescope-fzf-native.lua b/dotfiles/nvim/lua/plugins/telescope-fzf-native.lua new file mode 100644 index 0000000..bb93207 --- /dev/null +++ b/dotfiles/nvim/lua/plugins/telescope-fzf-native.lua @@ -0,0 +1,15 @@ +local data_dir = vim.fn.stdpath("data") +local telescope_dir = data_dir .. "/lazy/telescope-fzf-native.nvim" + +---@type LazySpec +-- override make command build since we provide the shared library with home-manager already +return { + "nvim-telescope/telescope-fzf-native.nvim", + build = "mkdir -p " + .. telescope_dir + .. "/build && ln -sf " + .. data_dir + .. "/lib/libfzf.so " + .. telescope_dir + .. "/build/libfzf.so", +} diff --git a/dotfiles/nvim/lua/plugins/treesitter.lua b/dotfiles/nvim/lua/plugins/treesitter.lua new file mode 100644 index 0000000..0c95ab1 --- /dev/null +++ b/dotfiles/nvim/lua/plugins/treesitter.lua @@ -0,0 +1,12 @@ +local data_dir = vim.fn.stdpath("data") +local build_cmd = "ln -sf " .. data_dir .. "/site/parser/*.so " .. data_dir .. "/lazy/nvim-treesitter/parser" + +---@type LazySpec +return { + "nvim-treesitter/nvim-treesitter", + build = build_cmd, + opts = function(_, opts) + vim.fn.system(build_cmd) + opts.auto_install = false; + end, +} \ No newline at end of file diff --git a/dotfiles/nvim/neovim.yml b/dotfiles/nvim/neovim.yml new file mode 100644 index 0000000..b9235ab --- /dev/null +++ b/dotfiles/nvim/neovim.yml @@ -0,0 +1,6 @@ +--- +base: lua51 + +globals: + vim: + any: true diff --git a/dotfiles/nvim/selene.toml b/dotfiles/nvim/selene.toml new file mode 100644 index 0000000..e7005c3 --- /dev/null +++ b/dotfiles/nvim/selene.toml @@ -0,0 +1,8 @@ +std = "neovim" + +[rules] +global_usage = "allow" +if_same_then_else = "allow" +incorrect_standard_library_use = "allow" +mixed_table = "allow" +multiple_statements = "allow" diff --git a/modules/desktop/apps.nix b/modules/desktop/apps.nix index e3a1fad..eeef4bf 100644 --- a/modules/desktop/apps.nix +++ b/modules/desktop/apps.nix @@ -1,14 +1,27 @@ -{ config, lib, pkgs, inputs, username, ... }: +{ + config, + lib, + pkgs, + inputs, + username, + ... +}: with lib; with builtins; let cfg = config.modules.desktop.apps; - mkAutostartModules = programs: - builtins.listToAttrs (builtins.map (desktop: { - name = desktop; - value = { autostartPrograms = programs; }; - }) (builtins.attrNames config.modules.desktop.wm)); -in { + mkAutostartModules = + programs: + builtins.listToAttrs ( + builtins.map (desktop: { + name = desktop; + value = { + autostartPrograms = programs; + }; + }) (builtins.attrNames config.modules.desktop.wm) + ); +in +{ options.modules.desktop.apps = { enable = mkEnableOption "general desktop applications"; }; @@ -19,10 +32,6 @@ in { home-manager.users.${username} = { programs.fish.shellAliases.open = "${getBin pkgs.xdg-utils}/bin/xdg-open"; home.packages = with pkgs; [ - # Nix - nixd - inputs.nixfmt.default - # Browser google-chrome diff --git a/modules/shell/fish.nix b/modules/shell/fish.nix index 64590d5..2d68a9b 100644 --- a/modules/shell/fish.nix +++ b/modules/shell/fish.nix @@ -6,9 +6,11 @@ username, ... }: -with lib; let +with lib; +let cfg = config.modules.shell.fish; -in { +in +{ options.modules.shell.fish = { enable = mkEnableOption "fish shell"; default = mkOption { @@ -21,7 +23,7 @@ in { config = mkIf cfg.enable { users.users."${username}".shell = mkIf cfg.default pkgs.fish; - environment.shells = mkIf cfg.default (with pkgs; [fish]); + environment.shells = mkIf cfg.default (with pkgs; [ fish ]); programs.fish.enable = true; home-manager.users.${username} = { @@ -38,7 +40,6 @@ in { re = "nh os switch -H ${hostname} && echo -e '\\033[32m>\\033[0m Done!'"; nfu = "nix flake update"; repl = "nix repl -f ''"; - vim = "nvim"; }; }; }; diff --git a/modules/shell/neovim.nix b/modules/shell/neovim.nix new file mode 100644 index 0000000..ee124a2 --- /dev/null +++ b/modules/shell/neovim.nix @@ -0,0 +1,109 @@ +{ + config, + lib, + pkgs, + username, + dotfiles, + ... +}: +with lib; +with lib.my; +let + cfg = config.modules.shell.neovim; + xdg = config.home-manager.users.${username}.xdg; + neovimPkg = config.home-manager.users.${username}.programs.neovim.finalPackage; + + normalizedGrammars = ( + lib.mapAttrs' + (name: value: { + name = lib.removePrefix "tree-sitter-" name; + inherit value; + }) + ( + lib.filterAttrs ( + name: _: lib.hasPrefix "tree-sitter-" name + ) pkgs.vimPlugins.nvim-treesitter.builtGrammars + ) + ); +in +{ + options.modules.shell.neovim = { + enable = mkEnableOption "neovim configuration"; + lspPackages = mkOption { + description = "LSP packages available to nvim."; + type = types.listOf types.package; + default = [ + pkgs.lua-language-server + pkgs.stylua + ]; + example = literalExpression "[ pkgs.nixd ]"; + }; + treesitterGrammars = mkOption { + description = "Treesitter grammars available to nvim."; + type = + with types; + coercedTo (listOf (enum (builtins.attrNames normalizedGrammars))) ( + grammars: + let + symlinks = lib.mapAttrsToList (name: grammar: ''ln -s ${grammar}/parser $out/${name}.so'') ( + filterAttrs (name: _: builtins.elem name grammars) normalizedGrammars + ); + in + (pkgs.runCommand "treesitter-grammars" { } '' + mkdir -p $out + ${concatStringsSep "\n" symlinks} + '').overrideAttrs + { + passthru.rev = pkgs.vimPlugins.nvim-treesitter.src.rev; + } + ) package; + default = [ ]; + example = literalExpression "[ \"lua\" ]"; + }; + }; + + config = mkIf (cfg.enable) { + home-manager.users.${username} = { + xdg = { + dataFile = { + "nvim/site/parser".source = cfg.treesitterGrammars; + "nvim/lib/libfzf.so".source = "${pkgs.vimPlugins.telescope-fzf-native-nvim}/build/libfzf.so"; + }; + configFile."nvim/lua".source = dotfiles.nvim.lua.source; + }; + + home.activation.nvim = hm.dag.entryAfter ["writeBoundary"] ( + let + treesitterRev = cfg.treesitterGrammars.rev; + nvimConfig = "${xdg.configHome}/nvim"; + in + '' + run echo "${treesitterRev}" > "${nvimConfig}/treesitter-rev" + + if [[ -f "${nvimConfig}/lazy-lock.json" ]]; then + if ! grep -q "${treesitterRev}" "${nvimConfig}/lazy-lock.json"; then + echo "lazy-lock.json file has outdated version of nvim-treesitter... updating it." + run ${getExe neovimPkg} --headless "+Lazy! update" +qa + fi + else + echo "lazy-lock.json file doesn't exist... creating it." + run ${getExe neovimPkg} --headless "+Lazy! update" +qa + fi + ''); + + programs.neovim = { + enable = true; + defaultEditor = true; + + withNodeJs = true; + withPython3 = true; + + vimAlias = true; + viAlias = true; + + extraPackages = cfg.lspPackages ++ (with pkgs; [git gcc]); + extraLuaConfig = lib.fileContents dotfiles.nvim."init.lua".source; + }; + }; + }; +} diff --git a/modules/shell/tools.nix b/modules/shell/tools.nix index 2ccbf4f..32ab367 100644 --- a/modules/shell/tools.nix +++ b/modules/shell/tools.nix @@ -6,9 +6,11 @@ ... }: with lib; -with lib.my; let +with lib.my; +let cfg = config.modules.shell.tools; -in { +in +{ options.modules.shell.tools = { enable = mkEnableOption "shell utility packages"; }; @@ -25,6 +27,7 @@ in { jq # Command-line JSON processor tre-command # Tree command, improved. lazydocker # The lazier way to manage everything docker + lazygit # simple terminal UI for git commands sd # Intuitive find & replace CLI (sed alternative) ripgrep # ripgrep recursively searches directories for a regex pattern while respecting your gitignore ]; @@ -33,6 +36,7 @@ in { fish = { shellAliases = with pkgs; { lzd = "${getExe lazydocker}"; + lg = "${getExe lazygit}"; tree = "${getExe tre-command}"; # On-demand tools