commit a5cf3fa2c03f123c8175ea627a16b2dcd679ec0b Author: Audrey Dutcher Date: Wed Feb 19 02:33:35 2025 -0700 initial commit diff --git a/configuration-desktop.nix b/configuration-desktop.nix new file mode 100644 index 0000000..f3fc087 --- /dev/null +++ b/configuration-desktop.nix @@ -0,0 +1,38 @@ +{ config, lib, pkgs, ... }: +{ + networking.networkmanager.enable = true; + + # Enable the X11 windowing system. + services.xserver.enable = true; + + # Enable CUPS to print documents. + services.printing.enable = true; + + # Enable sound. + services.pipewire = { + enable = true; + pulse.enable = true; + }; + + # Enable touchpad support (enabled default in most desktopManager). + services.libinput.enable = true; + + virtualisation.docker = { + enable = true; + storageDriver = "zfs"; + logDriver = "journald"; + }; + + services.displayManager.sddm = { + enable = true; + wayland.enable = true; + }; + services.desktopManager.plasma6 = { + enable = true; + }; + + programs = { + firefox.enable = true; + kdeconnect.enable = true; + }; +} diff --git a/configuration.nix b/configuration.nix new file mode 100644 index 0000000..f9a41b3 --- /dev/null +++ b/configuration.nix @@ -0,0 +1,85 @@ +{ config, lib, pkgs, ... }: + +{ + imports = [ ./overlays/packages.nix ]; + + # Use the systemd-boot EFI boot loader. + boot.loader.systemd-boot.enable = true; + boot.loader.systemd-boot.memtest86.enable = true; + boot.loader.efi.canTouchEfiVariables = true; + boot.loader.efi.efiSysMountPoint = "/boot"; + + nix.settings.extra-experimental-features = "nix-command flakes"; + + # Select internationalisation properties. + i18n.defaultLocale = "en_US.UTF-8"; + console = { + font = "Lat2-Terminus16"; + #keyMap = "us"; + useXkbConfig = true; # use xkb.options in tty. + }; + + # Configure keymap in X11 + services.xserver.xkb.layout = "us"; + services.xserver.xkb.options = "caps:escape"; + + users.defaultUserShell = pkgs.zsh; + # Define a user account. Don't forget to set a password with ‘passwd’. + users.users.audrey = { + isNormalUser = true; + extraGroups = [ "wheel" "docker" ]; + packages = with pkgs; [ ]; + }; + + environment.systemPackages = with pkgs; [ + wget + curl + btop + tmux + nixfmt-rfc-style + ]; + + programs = { + zsh.enable = true; + htop.enable = true; + git.enable = true; + neovim = { + enable = true; + defaultEditor = true; + vimAlias = true; + viAlias = true; + configure = { + # lmao + customRC = '' + ${builtins.readFile ./dotfiles/nvim-init.vim} + lua << EOF + ${builtins.readFile ./dotfiles/nvim-init.lua} + EOF + ''; + packages.myVimPackage = with pkgs.vimPlugins; { + start = [ + rust-vim + vim-tmux-navigator + popup-nvim + vim-sleuth + nvim-lspconfig + rust-tools-nvim + nvim-lint + nvim-cmp + lsp-status-nvim + telescope-nvim + nvim-treesitter.withAllGrammars + sweetie-nvim + vim-nix + csharpls-extended-lsp-nvim + ]; + opt = []; + }; + }; + }; + }; + + # Enable the OpenSSH daemon. + services.openssh.enable = true; +} + diff --git a/dotfiles/nvim-init.lua b/dotfiles/nvim-init.lua new file mode 100644 index 0000000..bbf3171 --- /dev/null +++ b/dotfiles/nvim-init.lua @@ -0,0 +1,451 @@ +-- https://github.com/neovim/neovim/issues/23725#issuecomment-1561364086 +local ok, wf = pcall(require, "vim.lsp._watchfiles") +if ok then + -- disable lsp watcher. Too slow on linux + wf._watchfunc = function() + return function() end + end +end + +local rt = require("rust-tools") +local lint = require('lint') +local lspconfig = require('lspconfig') +tb = require("telescope.builtin") + +require('telescope').setup({ + defaults = { + sorting_strategy = "ascending", + }, +}) + +require("nvim-treesitter.configs").setup { + auto_install = false, + highlight = { + enable = true, + disable = function(lang, buf) + local max_filesize = 100 * 1024 * 1024 -- 100 MB + local ok, stats = pcall(vim.loop.fs_stat, vim.api.nvim_buf_get_name(buf)) + if ok and stats and stats.size > max_filesize then + return true + end + end, + }, + indent = { + enable = true + } +} + +-- completion +local cmp = require('cmp') + +-- Global setup. +cmp.setup({ + snippet = { + expand = function(args) + end, + }, + window = { + -- completion = cmp.config.window.bordered(), + -- documentation = cmp.config.window.bordered(), + }, + mapping = cmp.mapping.preset.insert({ + [''] = cmp.mapping.scroll_docs(-4), + [''] = cmp.mapping.scroll_docs(4), + [''] = cmp.mapping.complete(), + [''] = cmp.mapping.confirm({ select = true }), + }), + sources = cmp.config.sources({ + { name = 'nvim_lsp' }, + --{ name = 'vsnip' }, -- For vsnip users. + -- { name = 'luasnip' }, -- For luasnip users. + -- { name = 'snippy' }, -- For snippy users. + -- { name = 'ultisnips' }, -- For ultisnips users. + }, { + { name = 'buffer' }, + }), + completion = { + autocomplete = false, + keyword_length = 1, + }, +}) + +-- Setup lspconfig. +--local capabilities = require('cmp_nvim_lsp').default_capabilities() +local lsp_status = require('lsp-status') + +local function nilfunc() + return nil +end + +--capabilities = vim.tbl_extend('keep', capabilities, lsp_status.capabilities) +_last_picker = nil +_last_ctx = nil +-- NOTE: this is currently unused because it so sucks. use gr instead! +local function telescope_middleware(func, ctxfunc) + local function inner() + if ctxfunc == nil then + ctx = nil + else + ctx = ctxfunc() + end + if func == _last_picker and vim.deep_equal(ctx, _last_ctx) then + tb.resume() + else + _last_picker = func + _last_ctx = ctx + func() + end + end + return inner +end + +local function tokenctx() + cursor0 = vim.api.nvim_win_get_cursor(0) + vim.cmd.normal("lb") + cursor = vim.api.nvim_win_get_cursor(0) + word = vim.call('expand','') + vim.api.nvim_win_set_cursor(0, cursor0) + return {cursor, word} +end + +local function lsp_keybinds(client, bufnr) + local bufopts = { noremap=true, silent=true, buffer=bufnr } + vim.keymap.set("n", "gd", tb.lsp_definitions, bufopts) + vim.keymap.set("n", "gD", tb.lsp_implementations, bufopts) + vim.keymap.set("n", "gt", tb.lsp_type_definitions, bufopts) + vim.keymap.set("n", "K", vim.lsp.buf.hover, bufopts) + vim.keymap.set('n', 'gu', tb.lsp_references, bufopts) -- "usages" + vim.keymap.set('n', 'ge', telescope_line_diagnostics, bufopts) -- "errors" + vim.keymap.set('n', 'gE', function() tb.diagnostics({ severity_limit=vim.diagnostic.severity.WARN }) end, bufopts) -- "errors" + vim.keymap.set('n', 'gaE', tb.diagnostics, bufopts) -- "errors" + --vim.api.nvim_command('inoremap ') + --vim.api.nvim_buf_set_option(bufnr, 'omnifunc', 'v:lua.vim.lsp.omnifunc') + vim.keymap.set('i', '', vim.lsp.buf.completion, bufopts) + vim.keymap.set('i', '', vim.lsp.buf.code_action, bufopts) + vim.keymap.set('n', '', vim.lsp.buf.code_action, bufopts) + lsp_status.on_attach(client) +end + +vim.keymap.set('n', '[e', function() vim.diagnostic.goto_prev{float=false, severity={min=vim.diagnostic.severity.WARN}} end, nil) +vim.keymap.set('n', ']e', function() vim.diagnostic.goto_next{float=false, severity={min=vim.diagnostic.severity.WARN}} end, nil) +vim.keymap.set('n', 'gf', tb.live_grep, nil) +vim.keymap.set('n', 'gn', tb.find_files, nil) +vim.keymap.set('n', 'gr', tb.resume, nil) + +local pickers = require("telescope.pickers") +local finders = require("telescope.finders") +local previewers = require("telescope.previewers") +local conf = require("telescope.config").values +local actions = require("telescope.actions") +local action_state = require("telescope.actions.state") +local make_entry = require("telescope.make_entry") + +lsp_status.config { + indicator_errors = 'E', + indicator_warnings = 'W', + indicator_info = 'i', + indicator_hint = '?', + indicator_ok = 'Ok', + diagnostics = false, +} + +lsp_status.register_progress() + +function telescope_line_diagnostics(opts) + opts = opts or {} + local diags = vim.diagnostic.get(0, { + lnum = opts.lnum or vim.api.nvim_win_get_cursor(0)[1] - 1, + severity = {min = opts.severity_limit or vim.diagnostic.severity.HINT}, + }) + if diags[1] == nil then + print("No issues under cursor") + return + end + + if diags[2] == nil then + show_full_diagnostic(diags[1]) + return + end + + pickers.new(opts, { + prompt_title = "Line Issues", + finder = finders.new_table { + results = diags, + entry_maker = function(diag) + return make_entry.set_default_entry_mt({ + value = diag, + text = diag.message, + display = diag.message:gsub("\n", " - "), + ordinal = diag.message, + }, opts) + end + }, + sorter = conf.generic_sorter(opts), + previewer = previewers.new_buffer_previewer { + define_preview = function(self, entry, status) + local text = vim.split(render_full_diagnostic_and_debug(entry.value), '\n') + vim.api.nvim_buf_set_lines(self.state.bufnr, 0, -1, true, text) + end + }, + attach_mappings = function(prompt_bufnr, map) + actions.select_default:replace(function() + actions.close(prompt_bufnr) + local entry = action_state.get_selected_entry() + show_full_diagnostic(entry.value) + end) + return true + end, + }):find() +end + +function render_full_diagnostic(diag) + if diag.user_data and diag.user_data.lsp and diag.user_data.lsp.data and diag.user_data.lsp.data.rendered then + return diag.user_data.lsp.data.rendered + end + if diag.message then + return diag.message + end + error("Bad diagnostic value") +end + +function render_full_diagnostic_and_debug(diag) + return render_full_diagnostic(diag) .. '\n\n' .. vim.inspect(diag) +end + +function show_full_diagnostic(diag) + local buf = nil; + local win = nil; + for _, win2 in ipairs(vim.api.nvim_tabpage_list_wins(0)) do + if string.match(vim.api.nvim_buf_get_name(vim.api.nvim_win_get_buf(win2)), "$") then + win = win2 + buf = vim.api.nvim_win_get_buf(win) + vim.api.nvim_set_current_win(win) + break + end + end + if buf == nil then + vim.cmd('bel split') + win = vim.api.nvim_get_current_win() + buf = vim.api.nvim_create_buf(false, true) + vim.api.nvim_win_set_buf(win, buf) + vim.api.nvim_buf_set_option(buf, "bufhidden", "delete") + vim.api.nvim_buf_set_name(buf, "") + end + local text = vim.split(render_full_diagnostic_and_debug(diag), '\n') + vim.api.nvim_buf_set_lines(buf, 0, -1, true, text) + vim.api.nvim_win_set_cursor(win, { 1, 0 }) +end + + + +function show_preview_diagnostic(diag) + local width = vim.api.nvim_get_option('columns') - 15 + local lines = vim.split(diag.message, "\n") + local message = lines[1] + + if #lines > 1 and #message <= 20 then + message = message .. ' ' .. lines[2] + end + + --while true do + -- local m = message:match("^[Ee]rror") + -- if m == nil then m = message:match("^[Ww]arning") end + -- if m == nil then m = message:match("^%d+:") end + -- if m == nil then m = message:match("^[: ]+") end + + -- if m == nil then + -- break + -- else + -- message = message.sub(#m + 1, #message) + -- end + --end + + if width > 0 and #message >= width then + message = message:sub(1, width) .. '...' + end + + vim.api.nvim_echo({{message}}, false, {}) +end + +rust_root_dir = function(fname) + local primary = lspconfig.util.root_pattern('rust-toolchain')(fname) + local fallback = lspconfig.util.root_pattern('Cargo.toml')(fname) + return primary or fallback +end + +local pipe = io.popen('rustup which rust-analyzer --toolchain nightly') +local rust_analyzer = pipe:read() +pipe = io.popen('which clangd') +clangd = pipe:read() +if clangd == nil then + pipe = io.popen('which clangd15') + clangd = pipe:read() +end +pipe = io.popen('which bash-language-server') +bashls = pipe:read() +pipe.close() +if rust_analyzer ~= nil then + rt.setup({ + server = { + on_attach = lsp_keybinds, + capabilities = capabilities, + root_dir = rust_root_dir, + cmd = {rust_analyzer}, + }, + }) +end +lspconfig.pyright.setup{ + on_attach = lsp_keybinds, + capabilities = capabilities, + settings = { + python = { + analysis = { + autoSearchPaths = false, + diagnosticMode = "openFilesOnly", + useLibraryCodeForTypes = false, + }, + }, + }, +} +if clangd ~= nil then + lspconfig.clangd.setup{ + on_attach = lsp_keybinds, + capabilities = capabilities, + cmd = {clangd, "--limit-references=1000000" }, + handlers = lsp_status.extensions.clangd.setup(), + init_options = { + clangdFileStatus = true + }, + single_file_support = false, + } +end +lspconfig.nil_ls.setup{ + on_attach = lsp_keybinds, + capabilities = capabilities, +} +lspconfig.csharp_ls.setup{ + on_attach = lsp_keybinds, + capabilities = capabilities, +} +if bashls ~= nil then + lspconfig.bashls.setup{ + on_attach = lsp_keybinds, + capabilities = capabilities, + cmd = {bashls, "start" }, + } +end +lspconfig.gopls.setup{ + on_attach = lsp_keybinds, + capabilities = capabilities, +} +lspconfig.ts_ls.setup{ + on_attach = lsp_keybinds, + capabilities = capabilities, +} +lspconfig.lua_ls.setup{ + on_attach = lsp_keybinds, + capabilities = capabilities, + settings = { + Lua = { + workspace = { + library = {"/home/audrey/loenn_stubs.lua"}, + }, + }, + }, +} +lspconfig.ocamllsp.setup{ + on_attach = lsp_keybinds, + capabilities = capabilities, +} + +--vim.api.nvim_create_autocmd({ "BufWritePost", "BufReadPost" }, { +-- callback = function() +-- lint.try_lint() +-- end +--}) + +--lint.linters_by_ft = { +-- python = {'ruff'}, +-- rust = {}, +--} + +-- LSP Diagnostics Options Setup +local sign = function(opts) + vim.fn.sign_define(opts.name, { + texthl = opts.name, + text = opts.text, + numhl = '' + }) +end + +sign({name = 'DiagnosticSignError', text = '!'}) +sign({name = 'DiagnosticSignWarn', text = '-'}) +--sign({name = 'DiagnosticSignHint', text = '.'}) +--sign({name = 'DiagnosticSignInfo', text = '+'}) + +vim.diagnostic.config({ + virtual_text = false, + signs = { + severity = {min = vim.diagnostic.severity.WARN}, + }, + update_in_insert = true, + underline = true, + severity_sort = true, + float = { + border = 'rounded', + source = 'always', + header = '', + prefix = '', + }, +}) + +vim.api.nvim_create_autocmd({ 'DiagnosticChanged' }, { + callback = function(args) + local diags = args.data.diagnostics + for _, diag in pairs(diags) do + if diag.severity == vim.diagnostic.severity.ERROR then + show_preview_diagnostic(diag) + return + end + end + vim.api.nvim_echo({{''}}, false, {}) + end, +}) + +vim.api.nvim_create_autocmd({ 'CursorMoved' }, { + callback = function() + local diags = vim.diagnostic.get(0, { + lnum = vim.api.nvim_win_get_cursor(0)[1] - 1, + severity = {min = vim.diagnostic.severity.WARN}, + }) + for _, diag in pairs(diags) do + show_preview_diagnostic(diag) + break + end + end +}) + +vim.api.nvim_create_user_command('Fmt', function() vim.lsp.buf.format({}) end, {}) + +show = function(x) + vim.notify(vim.inspect(x)) +end + +vim.g.sweetie = { + palette = { + dark = { + bg_alt = "#151523" + } + }, + overrides = { + StatusLineNC = { fg = "#eeffee", bg = "#151523" }, + StatusLine = {fg = "#ffffff", bg = "#151523", bold = true }, + MatchParen = { fg = '#ae920a', reverse = false }, + Search = { fg = '#ae920a', bg = "#0b658e" }, + } +} +if vim.env.TERM == "tmux" or vim.env.TERM == "xterm" then + vim.cmd.colorscheme("default") +else + vim.cmd.colorscheme("sweetie") +end diff --git a/dotfiles/nvim-init.vim b/dotfiles/nvim-init.vim new file mode 100644 index 0000000..04eecb9 --- /dev/null +++ b/dotfiles/nvim-init.vim @@ -0,0 +1,23 @@ +set nocompatible +set nu +set ttimeout +set ttimeoutlen=0 +set mouse= +set clipboard=unnamedplus +set ruler +set signcolumn=yes +set termguicolors +autocmd! +if $TERM != "xterm" && $TERM != "tmux" + inoremap :TmuxNavigateLeft + inoremap :TmuxNavigateDown + inoremap :TmuxNavigateUp + inoremap :TmuxNavigateRight +endif +" Disable tmux navigator when zooming the Vim pane +let g:tmux_navigator_disable_when_zoomed = 1 + +filetype plugin on +syntax on + +nnoremap :noh diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..ad6d107 --- /dev/null +++ b/flake.lock @@ -0,0 +1,27 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1739758141, + "narHash": "sha256-uq6A2L7o1/tR6VfmYhZWoVAwb3gTy7j4Jx30MIrH0rE=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "c618e28f70257593de75a7044438efc1c1fc0791", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-24.11", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..bfa7af4 --- /dev/null +++ b/flake.nix @@ -0,0 +1,10 @@ +{ + inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11"; + outputs = { self, nixpkgs }: { + nixosConfigurations = let + sitesFiles = builtins.readDir ./sites; + sitesNames = builtins.filter (name: builtins.pathExists ./sites/${name}/configuration.nix) (builtins.attrNames sitesFiles); + configurations = builtins.listToAttrs (builtins.map (name: {inherit name; value = nixpkgs.lib.nixosSystem { modules = [ ./configuration.nix ./sites/${name}/configuration.nix ]; }; }) sitesNames); + in configurations; + }; +} diff --git a/overlays/packages.nix b/overlays/packages.nix new file mode 100644 index 0000000..44bdd74 --- /dev/null +++ b/overlays/packages.nix @@ -0,0 +1,36 @@ +{ config, lib, pkgs, ... }: + +let overlay = final: prev: { + vimPlugins = prev.vimPlugins.extend (final': prev': { + sweetie-nvim = final.callPackage ../pkgs/sweetie.nix {}; + }); + zfs_2_2 = prev.zfs_2_2.overrideAttrs (final': prev': { + patches = prev'.patches ++ [(final.fetchpatch { + url = "https://git.lain.faith/haskal/dragnpkgs/raw/commit/f4348768df564166762793aed43803675e251926/pkgs/zfs/0001-ZED-add-support-for-desktop-notifications-D-Bus.patch"; + hash = "sha256-vwGHiLKSjJor4A+r599DlvSHXkDuuLSSQ4/tWFALMKU="; + })]; + }); +}; + +in { + nixpkgs.overlays = [ overlay ]; + + services.zfs.zed = { + settings = { + PATH = lib.mkForce (lib.makeBinPath [ + config.boot.zfs.package + pkgs.coreutils + pkgs.curl + pkgs.gawk + pkgs.gnugrep + pkgs.gnused + pkgs.nettools + pkgs.util-linux + + pkgs.systemd + ]); + + ZED_USE_DBUS = "1"; + }; + }; +} diff --git a/pkgs/sweetie.nix b/pkgs/sweetie.nix new file mode 100644 index 0000000..06bfe74 --- /dev/null +++ b/pkgs/sweetie.nix @@ -0,0 +1,17 @@ +{ + vimUtils, + fetchFromGitHub, +}: +let + pname = "sweetie.nvim"; + version = "3.2.0"; +in +vimUtils.buildVimPlugin { + inherit pname version; + src = fetchFromGitHub { + owner = "NTBBloodbath"; + repo = pname; + tag = "v${version}"; + hash = "sha256-hAe6bc8JON5krl2U7ib/bk17MHOr3TVPxtp4xw2mHS8="; + }; +} diff --git a/sites/daisy/configuration.nix b/sites/daisy/configuration.nix new file mode 100644 index 0000000..10775f9 --- /dev/null +++ b/sites/daisy/configuration.nix @@ -0,0 +1,23 @@ +{ config, lib, pkgs, ... }: + +{ + imports = [ ./hardware-configuration.nix ../configuration-desktop.nix ]; + + boot.initrd.supportedFilesystems = [ "zfs" ]; + boot.initrd.systemd.enable = true; + services.zfs.autoScrub.enable = true; + services.zfs.trim.enable = true; + # fstrim is also enabled by nixos-hardware, but only runs for /boot + + networking.hostName = "daisy"; + networking.hostId = "293a1290"; + + # Set your time zone. + time.timeZone = "America/Phoenix"; + + # Open ports in the firewall. + networking.firewall.allowedTCPPorts = [ 22 80 443 1337 ]; + networking.firewall.allowedUDPPorts = [ 1337 ]; + + system.stateVersion = "24.11"; +} diff --git a/sites/daisy/hardware-configuration.nix b/sites/daisy/hardware-configuration.nix new file mode 100644 index 0000000..0bcedb3 --- /dev/null +++ b/sites/daisy/hardware-configuration.nix @@ -0,0 +1,52 @@ +# Do not modify this file! It was generated by ‘nixos-generate-config’ +# and may be overwritten by future invocations. Please make changes +# to /etc/nixos/configuration.nix instead. +{ config, lib, pkgs, modulesPath, ... }: + +{ + imports = + [ (modulesPath + "/installer/scan/not-detected.nix") + ]; + + boot.initrd.availableKernelModules = [ "xhci_pci" "thunderbolt" "nvme" "usb_storage" "sd_mod" ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ "kvm-intel" ]; + boot.extraModulePackages = [ ]; + + fileSystems."/" = + { device = "system/local/root"; + fsType = "zfs"; + }; + + fileSystems."/nix" = + { device = "system/local/nix"; + fsType = "zfs"; + }; + + fileSystems."/var" = + { device = "system/local/var"; + fsType = "zfs"; + }; + + fileSystems."/home" = + { device = "system/home"; + fsType = "zfs"; + }; + + fileSystems."/boot" = + { device = "/dev/disk/by-uuid/8261-4807"; + fsType = "vfat"; + }; + + swapDevices = [ ]; + + # Enables DHCP on each ethernet and wireless interface. In case of scripted networking + # (the default) this is the recommended approach. When using systemd-networkd it's + # still possible to use this option, but it's recommended to use it in conjunction + # with explicit per-interface declarations with `networking.interfaces..useDHCP`. + networking.useDHCP = lib.mkDefault true; + # networking.interfaces.wlp0s20f3.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; +}