diff --git a/nix/configuration/configuration.nix b/nix/configuration/configuration.nix index 236f2fc..f03dfe7 100644 --- a/nix/configuration/configuration.nix +++ b/nix/configuration/configuration.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, pkgs-unstable, ... }: +{ config, lib, pkgs, pkgs-unstable, home-manager, ... }: { imports = @@ -9,6 +9,8 @@ ./zfs.nix ./network.nix ./roles/sway + ./roles/emacs + ./roles/git ]; nix.settings.experimental-features = [ "nix-command" "flakes" ]; @@ -33,6 +35,14 @@ "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIAFNcSXwvy+brYTOGo56G93Ptuq2MmZsjvRWAfMqbmMLAAAABHNzaDo=" ]; }; + home-manager.users.talexander = { pkgs, ... }: { + home.packages = [ pkgs.atool pkgs.httpie ]; + programs.bash.enable = true; + + # The state version is required and should stay at the version you + # originally installed. + home.stateVersion = "24.11"; + }; # Automatic garbage collection nix.gc = { @@ -56,7 +66,6 @@ environment.defaultPackages = lib.mkForce []; environment.systemPackages = with pkgs; [ - git wget mg rsync @@ -112,8 +121,8 @@ unitConfig.DefaultDependencies = "no"; serviceConfig.Type = "oneshot"; script = '' - zfs rollback -r zroot/linux/root@blank - zfs rollback -r zroot/linux/home@blank + zfs rollback -r zroot/linux/nix/root@blank + zfs rollback -r zroot/linux/nix/home@blank echo "rollback complete" ''; }; @@ -121,8 +130,6 @@ environment.persistence."/persist" = { hideMounts = true; directories = [ - "/etc/nixos" # Contains system configuration, optional - "/etc/NetworkManager/system-connections" # Wifi settings "/var/lib/iwd" # Wifi settings "/var/lib/nixos" # Contains user information (uids/gids) ]; diff --git a/nix/configuration/flake.nix b/nix/configuration/flake.nix index addef4e..222784b 100644 --- a/nix/configuration/flake.nix +++ b/nix/configuration/flake.nix @@ -10,9 +10,11 @@ nixpkgs-b93b4e9b5.url = "github:NixOS/nixpkgs/b93b4e9b527904aadf52dba6ca35efde2067cbd4"; home-manager.url = "github:nix-community/home-manager/release-24.11"; home-manager.inputs.nixpkgs.follows = "nixpkgs"; + emacs-overlay.url = "github:nix-community/emacs-overlay/da2f552d133497abd434006e0cae996c0a282394"; + emacs-overlay.inputs.nixpkgs.follows = "nixpkgs"; }; - outputs = { self, nixpkgs, nixpkgs-unstable, nixpkgs-b93b4e9b5, impermanence, home-manager, ... }@inputs: let + outputs = { self, nixpkgs, nixpkgs-unstable, nixpkgs-b93b4e9b5, impermanence, home-manager, emacs-overlay, ... }@inputs: let base-system = {}; odoqemu = nixpkgs.lib.nixosSystem rec { system = "x86_64-linux"; diff --git a/nix/configuration/roles/emacs/default.nix b/nix/configuration/roles/emacs/default.nix new file mode 100644 index 0000000..a8c8f3d --- /dev/null +++ b/nix/configuration/roles/emacs/default.nix @@ -0,0 +1,41 @@ +{ config, lib, pkgs, ... }: + +#let +# full-emacs = (pkgs.writeScriptBin "emacs" '' +# #! ${pkgs.bash}/bin/bash +# exec ${pkgs.emacs-gtk}/bin/emacs --init-directory ${./emacs.d} "$@" +# ''); +#in +{ + imports = []; + + environment.systemPackages = with pkgs; [ + #(pkgs.symlinkJoin { + # name = "emacs"; + # paths = [ + # full-emacs + # pkgs.emacs-gtk + # ]; + #}) + + # (runCommand "default.el" {} '' + # mkdir -p $out/share/emacs/site-lisp + # cp ${myEmacsConfig} $out/share/emacs/site-lisp/default.el + # '') + ]; + + + #environment.systemPackages = with pkgs; [ + # (pkgs.emacsWithPackagesFromUsePackage { + # package = pkgs.emacsPgtkNativeComp; + # config = path/to/your/config.el; + + # # Optionally provide extra packages not in the configuration file. + # # extraEmacsPackages = epkgs: [ + # # epkgs.use-package; + # # ]; + # }) + #]; + + #nixpkgs.overlays = [ (emacs-overlay) ]; +} diff --git a/nix/configuration/roles/emacs/emacs.d/early-init.el b/nix/configuration/roles/emacs/emacs.d/early-init.el new file mode 100644 index 0000000..9e5dc46 --- /dev/null +++ b/nix/configuration/roles/emacs/emacs.d/early-init.el @@ -0,0 +1,25 @@ +(setq gc-cons-threshold (* 128 1024 1024)) ;; 128MiB Increase garbage collection threshold for performance (default 800000) +;; Increase amount of data read from processes, default 4k +(when (version<= "27.0" emacs-version) + (setq read-process-output-max (* 10 1024 1024)) ;; 10MiB + ) + +;; Suppress warnings +(setq byte-compile-warnings '(not obsolete)) +(setq warning-suppress-log-types '((comp) (bytecomp))) +(setq native-comp-async-report-warnings-errors 'silent) + +;; Set up default visual settings +(setq frame-resize-pixelwise t) +;; Disable toolbar & menubar +(menu-bar-mode -1) +(when (fboundp 'tool-bar-mode) + (tool-bar-mode -1)) +(when (display-graphic-p) + (context-menu-mode +1)) + +(setq default-frame-alist '((fullscreen . maximized) + (vertical-scroll-bars . nil) + (horizontal-scroll-bars . nil) + ;; Set dark colors in early-init to prevent flashes of white. + (background-color . "#000000"))) diff --git a/nix/configuration/roles/emacs/emacs.d/elisp/base-extensions.el b/nix/configuration/roles/emacs/emacs.d/elisp/base-extensions.el new file mode 100644 index 0000000..3c346c9 --- /dev/null +++ b/nix/configuration/roles/emacs/emacs.d/elisp/base-extensions.el @@ -0,0 +1,86 @@ +(use-package diminish) + +;; Eglot recommends pulling the latest of the standard libraries it +;; uses from ELPA if you're not tracking the current.config/emacsevelopment +;; branch. +(use-package xref + :pin gnu + ) + +(use-package eldoc + :pin gnu + :diminish + ) + +;; Other packages + +(use-package emacs + :config + (setq enable-recursive-minibuffers t) + + ;; Filter the M-x list base on the current mode + (setq read-extended-command-predicate #'command-completion-default-include-p) + + ;; Enable triggering completion with the tab key. + (setq tab-always-indent 'complete) + ) + +(use-package dashboard + :config + (dashboard-setup-startup-hook)) + +(when (version<= "26.0.50" emacs-version ) + (add-hook 'prog-mode-hook 'display-line-numbers-mode) + (add-hook 'prog-mode-hook 'column-number-mode) + ) + +;; Display a horizontal line instead of ^L for page break characters +(use-package page-break-lines + :diminish + :config + (global-page-break-lines-mode +1) + ) + +(use-package recentf + ;; This is an emacs built-in but we're pulling the latest version + :config + (setq recentf-max-saved-items 100) + (setq recentf-save-file (recentf-expand-file-name "~/.config/emacs/private/cache/recentf")) + (recentf-mode 1)) + +;; Persist history over Emacs restarts. Vertico sorts by history position. +(use-package savehist + ;; This is an emacs built-in but we're pulling the latest version + :config + (savehist-mode)) + +(use-package which-key + :diminish + :config + (which-key-mode)) + +(use-package windmove + :config + (windmove-default-keybindings)) + +(setq tramp-default-method "ssh") + +(use-package nginx-mode + :mode ( + ("headers\\.include\\'" . nginx-mode) + ) + :config + (setq nginx-indent-level 4)) + +(use-package systemd + :mode + (("\\.service\\'" . systemd-mode) + ("\\.timer\\'" . systemd-mode)) + ) + +(use-package pkgbuild-mode + :mode + (("PKGBUILD\\'" . pkgbuild-mode)) + ) + +(provide 'base-extensions) diff --git a/nix/configuration/roles/emacs/emacs.d/elisp/base-functions.el b/nix/configuration/roles/emacs/emacs.d/elisp/base-functions.el new file mode 100644 index 0000000..7859e83 --- /dev/null +++ b/nix/configuration/roles/emacs/emacs.d/elisp/base-functions.el @@ -0,0 +1,127 @@ +;; ========== Function to reload current file ================= + +(defun reload-file () + "Revert buffer without confirmation." + (interactive) + (revert-buffer :ignore-auto :noconfirm)) + +;; =========================================================== +;; ============= Run commands ================================ +(defun run-command-on-buffer (cmd &rest args) + "Run a command using the current buffer as stdin and replacing its contents if the command succeeds with the stdout from the command. This is useful for code formatters." + (let ( + (stdout-buffer (generate-new-buffer "tmp-stdout" t)) + (full-cmd (append '(call-process-region nil nil cmd nil stdout-buffer nil) args)) + ) + (unwind-protect + (let ((exit-status (eval full-cmd))) + (if (eq exit-status 0) + (save-excursion + (replace-buffer-contents stdout-buffer) + ) + (message "FAILED running command on buffer %s" (append (list cmd) args)) + ) + ) + (kill-buffer stdout-buffer) + ) + ) + ) + +(defun run-command-in-directory (dir cmd &rest args) + "Run a command in the specified directory. If the directory is nil, the directory of the file is used. The stdout result is trimmed of whitespace and returned." + (let ( + (default-directory (or dir default-directory)) + (stdout-buffer (generate-new-buffer "tmp-stdout" t)) + (full-cmd (append '(call-process cmd nil (list stdout-buffer nil) nil) args)) + ) + (unwind-protect + (let ((exit-status (condition-case nil (eval full-cmd) (file-missing nil)))) + (if (eq exit-status 0) + (progn + (with-current-buffer stdout-buffer + (string-trim (buffer-string)) + ) + ) + ) + ) + (kill-buffer stdout-buffer) + ) + ) + ) + +(defun load-directory (dir) + (let ((load-it (lambda (f) + (load-file (concat (file-name-as-directory dir) f))) + )) + (mapc load-it (directory-files dir nil "\\.el$")))) + +(defun generate-vc-link () + (interactive) + (or + (generate-github-link) + (generate-source-hut-link) + ) + ) + +(defun generate-github-link () + "Generate a permalink to the current line." + (interactive) + (let ( + (current-rev (vc-working-revision buffer-file-name)) + (line-number (line-number-at-pos)) + (repository-url (vc-git-repository-url buffer-file-name)) + (relative-path (file-relative-name buffer-file-name (vc-root-dir))) + ) + (save-match-data + (and (string-match "\\(git@github\.com:\\|https://github\.com/\\)\\([^/]+\\)/\\([^.]+\\).git" repository-url) + (let* ( + (gh-org (match-string 2 repository-url)) + (gh-repo (match-string 3 repository-url)) + (full-url (format "https://github.com/%s/%s/blob/%s/%s?plain=1#L%s" gh-org gh-repo current-rev relative-path line-number)) + ) + (message "%s" full-url) + (kill-new full-url) + t + ) + ) + ) + ) + ) + +(defun generate-source-hut-link () + "Generate a permalink to the current line." + (interactive) + (let ( + (current-rev (vc-working-revision buffer-file-name)) + (line-number (line-number-at-pos)) + (repository-url (vc-git-repository-url buffer-file-name)) + (relative-path (file-relative-name buffer-file-name (vc-root-dir))) + ) + (message "Using repo url %s" repository-url) + (save-match-data + (and (string-match "https://git.sr.ht/\\([^/]+\\)/\\([^/]+\\)" repository-url) + (let* ( + (sh-org (match-string 1 repository-url)) + (sh-repo (match-string 2 repository-url)) + (full-url (format "https://git.sr.ht/%s/%s/tree/%s/%s#L%s" sh-org sh-repo current-rev relative-path line-number)) + ) + (message "%s" full-url) + (kill-new full-url) + t + ) + ) + ) + ) + ) + +(defmacro when-linux (&rest body) + "Execute only when on Linux." + (declare (indent defun)) + `(when (eq system-type 'gnu/linux) ,@body)) + +(defmacro when-freebsd (&rest body) + "Execute only when on FreeBSD." + (declare (indent defun)) + `(when (eq system-type 'berkeley-unix) ,@body)) + +(provide 'base-functions) diff --git a/nix/configuration/roles/emacs/emacs.d/elisp/base-global-keys.el b/nix/configuration/roles/emacs/emacs.d/elisp/base-global-keys.el new file mode 100644 index 0000000..ae3d273 --- /dev/null +++ b/nix/configuration/roles/emacs/emacs.d/elisp/base-global-keys.el @@ -0,0 +1,12 @@ +;; Add your keys here, as such + +;; Disable the suspend frame hotkeys +(global-unset-key (kbd "C-z")) +(global-unset-key (kbd "C-x C-z")) + +;; dabbrev-expand. Seems to be some sort of dumb-expand. Accidentally hitting it when trying to use M-? +(global-unset-key (kbd "M-/")) + +(global-set-key (kbd "C-x g l") 'generate-vc-link) + +(provide 'base-global-keys) diff --git a/nix/configuration/roles/emacs/emacs.d/elisp/base-theme.el b/nix/configuration/roles/emacs/emacs.d/elisp/base-theme.el new file mode 100644 index 0000000..c1fd9a0 --- /dev/null +++ b/nix/configuration/roles/emacs/emacs.d/elisp/base-theme.el @@ -0,0 +1,15 @@ +;; Set theme +(load-theme 'tango-dark t) +(set-face-attribute 'default nil :background "black") +;; Bright yellow highlighting for selected region +(set-face-attribute 'region nil :background "#ffff50" :foreground "black") +;; Bright green cursor to distinguish from yellow region +(set-face-attribute 'cursor nil :background "#ccff66") +;; Hightlight the current line +(set-face-attribute 'line-number-current-line nil :foreground "white") +;; Set default font +(set-face-attribute 'default nil :height 100 :width 'regular :weight 'regular :family "Cascadia Mono") +;; Set fallback font for unicode glyphs +(set-fontset-font t 'emoji (font-spec :name "Noto Color Emoji") nil 'prepend) + +(provide 'base-theme) diff --git a/nix/configuration/roles/emacs/emacs.d/elisp/base.el b/nix/configuration/roles/emacs/emacs.d/elisp/base.el new file mode 100644 index 0000000..45a0dac --- /dev/null +++ b/nix/configuration/roles/emacs/emacs.d/elisp/base.el @@ -0,0 +1,94 @@ +(package-initialize) +(use-package use-package) + +(add-to-list 'package-archives + '("melpa" . "https://melpa.org/packages/") + ) + +(use-package auto-package-update + :ensure t + :config + (setq auto-package-update-delete-old-versions t + auto-package-update-interval 14) + (auto-package-update-maybe)) + +(defun assert-directory (p) + (unless (file-exists-p p) (make-directory p t)) + p + ) + +(defconst private-dir (expand-file-name "private" user-emacs-directory)) +(defconst temp-dir (format "%s/cache" private-dir) + "Hostname-based elisp temp directories") +(assert-directory (concat temp-dir "/auto-save-list/")) +(setq autoload-directory (concat user-emacs-directory (file-name-as-directory "elisp") (file-name-as-directory "autoload"))) +(add-to-list 'load-path (assert-directory autoload-directory)) + +(setq-default + ;; Disable backup files and lockfiles + make-backup-files nil + auto-save-default nil + create-lockfiles nil + ;; Unless otherwise specified, always install packages if they are absent. + use-package-always-ensure t + ;; Point custom-file at /dev/null so emacs does not write any settings to my dotfiles. + custom-file "/dev/null" + ;; Don't pop up a small window at the bottom of emacs at launch. + inhibit-startup-screen t + inhibit-startup-message t + ;; Don't show the list of buffers when opening many files. + inhibit-startup-buffer-menu t + ;; Give the scratch buffer a clean slate. + initial-major-mode 'fundamental-mode + initial-scratch-message nil + ;; Send prompts to mini-buffer not the GUI + use-dialog-box nil + ;; End files with line break + require-final-newline t + ;; Use spaces, not tabs + indent-tabs-mode nil + ;; Use a better frame title + frame-title-format '("" invocation-name ": "(:eval (if (buffer-file-name) + (abbreviate-file-name (buffer-file-name)) + "%b"))) + ;; Use 'y' or 'n' instead of 'yes' or 'no' + use-short-answers t + ;; Natively compile packages + package-native-compile t + ;; Confirm when opening a file that does not exist + confirm-nonexistent-file-or-buffer t + ;; Do not require double space to end a sentence. + sentence-end-double-space nil + ;; Show trailing whitespace + show-trailing-whitespace t + ;; Remove the line when killing it with ctrl-k + kill-whole-line t + ) + +;; (setq-default fringes-outside-margins t) + +;; Per-pixel scrolling instead of per-line +(pixel-scroll-precision-mode) + +;; Typed text replaces selection +(delete-selection-mode) + + +;; Delete trailing whitespace before save +(add-hook 'before-save-hook 'delete-trailing-whitespace) + +;; If the underlying file changes, reload it automatically. This is useful for moving around in git without confusing language servers. +(setopt auto-revert-avoid-polling t) +(setopt auto-revert-interval 5) +(setopt auto-revert-check-vc-info t) +(global-auto-revert-mode) + +;;;;; Performance +;; Run garbage collect when emacs is idle +(run-with-idle-timer 5 t (lambda () (garbage-collect))) +(add-function :after after-focus-change-function + (lambda () + (unless (frame-focus-state) + (garbage-collect)))) + +(provide 'base) diff --git a/nix/configuration/roles/emacs/emacs.d/elisp/common-lsp.el b/nix/configuration/roles/emacs/emacs.d/elisp/common-lsp.el new file mode 100644 index 0000000..66d10dc --- /dev/null +++ b/nix/configuration/roles/emacs/emacs.d/elisp/common-lsp.el @@ -0,0 +1,47 @@ +(use-package eglot + :pin gnu + :commands (eglot eglot-ensure) + :bind (:map eglot-mode-map + ;; M-. + ;; ([remap xref-find-definitions] . lsp-ui-peek-find-definitions) + ;; M-? + ;; ([remap xref-find-references] . lsp-ui-peek-find-references) + ("C-c C-a" . eglot-code-actions) + ;; C-M-. + ([remap xref-find-apropos] . #'consult-eglot-symbols) + ) + ;; :hook ( + ;; (eglot-managed-mode . (lambda () + ;; (when (eglot-managed-p) + ;; (corfu-mode +1) + ;; ) + ;; )) + ;; ) + :config + (fset #'jsonrpc--log-event #'ignore) ;; Disable logging LSP traffic for performance boost + (set-face-attribute 'eglot-highlight-symbol-face nil :background "#0291a1" :foreground "black") + (set-face-attribute 'eglot-mode-line nil :inherit 'mode-line :bold nil) + + + :custom + (eglot-autoshutdown t "Shut down server when last buffer is killed.") + (eglot-sync-connect 0 "Don't block on language server starting.") + (eglot-send-changes-idle-time 0.1) + ) + +(use-package consult-eglot + :commands (consult-eglot-symbols) + ) + +(use-package company + :after eglot + :hook (eglot-managed-mode . company-mode) + :config + (setq company-backends '((company-capf))) + (setq company-idle-delay 0) ;; Default 0.2 + ) + +;; (use-package company-box +;; :hook (company-mode . company-box-mode)) + +(provide 'common-lsp) diff --git a/nix/configuration/roles/emacs/emacs.d/elisp/lang-bash.el b/nix/configuration/roles/emacs/emacs.d/elisp/lang-bash.el new file mode 100644 index 0000000..bc3b1cc --- /dev/null +++ b/nix/configuration/roles/emacs/emacs.d/elisp/lang-bash.el @@ -0,0 +1,16 @@ +(require 'util-tree-sitter) + +(use-package bash-ts-mode + :ensure nil + :commands (bash-ts-mode) + :hook ( + (bash-ts-mode . (lambda () + (flymake-mode +1) + ))) + :init + (add-to-list 'major-mode-remap-alist '(sh-mode . bash-ts-mode)) + (add-to-list 'treesit-language-source-alist '(bash "https://github.com/tree-sitter/tree-sitter-bash")) + (unless (treesit-ready-p 'bash) (treesit-install-language-grammar 'bash)) + ) + +(provide 'lang-bash) diff --git a/nix/configuration/roles/emacs/emacs.d/elisp/lang-c.el b/nix/configuration/roles/emacs/emacs.d/elisp/lang-c.el new file mode 100644 index 0000000..59ce468 --- /dev/null +++ b/nix/configuration/roles/emacs/emacs.d/elisp/lang-c.el @@ -0,0 +1,49 @@ +(require 'common-lsp) +(require 'util-tree-sitter) + +(defun locate-compile-commands-file () + "See if compile_commands.json exists." + ;; This can be generated by prefixing the make command with `intercept-build15 --append` + (let ((compile-commands-file (locate-dominating-file (buffer-file-name) "compile_commands.json"))) + compile-commands-file + ) + ) + +(defun activate-c-eglot () + "Activate eglot for the c family of languages." + (when (locate-compile-commands-file) + (eglot-ensure) + (defclass my/eglot-c (eglot-lsp-server) () + :documentation + "Own eglot server class.") + + (add-to-list 'eglot-server-programs + '(c-ts-mode . (my/eglot-c "/usr/local/bin/clangd15"))) + (add-hook 'before-save-hook 'eglot-format-buffer nil 'local) + ) + ) + +(use-package c-mode + :mode ( + ("\\.c\\'" . c-ts-mode) + ("\\.h\\'" . c-or-c++-ts-mode) + ) + :commands (c-mode c-ts-mode) + :pin manual + :ensure nil + :hook ( + (c-ts-mode . (lambda () + (activate-c-eglot) + )) + ) + :init + (add-to-list 'major-mode-remap-alist '(c-mode . c-ts-mode)) + (add-to-list 'major-mode-remap-alist '(c++-mode . c++-ts-mode)) + (add-to-list 'major-mode-remap-alist '(c-or-c++-mode . c-or-c++-ts-mode)) + (add-to-list 'treesit-language-source-alist '(c "https://github.com/tree-sitter/tree-sitter-c")) + (add-to-list 'treesit-language-source-alist '(cpp "https://github.com/tree-sitter/tree-sitter-cpp")) + (unless (treesit-ready-p 'c) (treesit-install-language-grammar 'c)) + (unless (treesit-ready-p 'cpp) (treesit-install-language-grammar 'cpp)) + ) + +(provide 'lang-c) diff --git a/nix/configuration/roles/emacs/emacs.d/elisp/lang-dockerfile.el b/nix/configuration/roles/emacs/emacs.d/elisp/lang-dockerfile.el new file mode 100644 index 0000000..a14fde7 --- /dev/null +++ b/nix/configuration/roles/emacs/emacs.d/elisp/lang-dockerfile.el @@ -0,0 +1,13 @@ +(use-package dockerfile-ts-mode + :pin manual + :mode ( + ("Dockerfile\\'" . dockerfile-ts-mode) + ) + :commands (dockerfile-mode dockerfile-ts-mode) + :init + (add-to-list 'major-mode-remap-alist '(dockerfile-mode . dockerfile-ts-mode)) + (add-to-list 'treesit-language-source-alist '(dockerfile "https://github.com/camdencheek/tree-sitter-dockerfile")) + (unless (treesit-ready-p 'dockerfile) (treesit-install-language-grammar 'dockerfile)) + ) + +(provide 'lang-dockerfile) diff --git a/nix/configuration/roles/emacs/emacs.d/elisp/lang-go.el b/nix/configuration/roles/emacs/emacs.d/elisp/lang-go.el new file mode 100644 index 0000000..7040532 --- /dev/null +++ b/nix/configuration/roles/emacs/emacs.d/elisp/lang-go.el @@ -0,0 +1,33 @@ +(require 'common-lsp) +(require 'util-tree-sitter) + +(use-package go-ts-mode + :pin manual + :mode ( + ("\\.go\\'" . go-ts-mode) + ("/go\\.mod\\'" . go-mod-ts-mode) + ) + :commands (go-ts-mode go-mod-ts-mode) + :hook ( + (go-ts-mode . (lambda () + (when-linux + (eglot-ensure) + ) + )) + + (go-mod-ts-mode . (lambda () + (when-linux + (eglot-ensure) + ) + )) + + ;; (before-save . lsp-format-buffer) + ) + :init + (add-to-list 'treesit-language-source-alist '(go "https://github.com/tree-sitter/tree-sitter-go")) + (add-to-list 'treesit-language-source-alist '(gomod "https://github.com/camdencheek/tree-sitter-go-mod")) + (unless (treesit-ready-p 'go) (treesit-install-language-grammar 'go)) + (unless (treesit-ready-p 'gomod) (treesit-install-language-grammar 'gomod)) + ) + +(provide 'lang-go) diff --git a/nix/configuration/roles/emacs/emacs.d/elisp/lang-javascript.el b/nix/configuration/roles/emacs/emacs.d/elisp/lang-javascript.el new file mode 100644 index 0000000..310daee --- /dev/null +++ b/nix/configuration/roles/emacs/emacs.d/elisp/lang-javascript.el @@ -0,0 +1,177 @@ +(require 'common-lsp) +(require 'util-tree-sitter) + +(use-package json-ts-mode + :ensure nil + :pin manual + :mode ( + ("\\.json\\'" . json-ts-mode) + ) + :commands (json-ts-mode) + :hook ( + (json-ts-mode . (lambda () + (add-hook 'before-save-hook 'json-fmt-jq nil 'local) + )) + ) + :init + (add-to-list 'treesit-language-source-alist '(json "https://github.com/tree-sitter/tree-sitter-json")) + (unless (treesit-ready-p 'json) (treesit-install-language-grammar 'json)) + ) + +(defun json-fmt-jq () + "Run jq." + (run-command-on-buffer "jq" "--monochrome-output" ".") + ) + +(defun configure-typescript-language-server () + "Configures the typescript language server." + (when-linux + ;; Either initializationOptions or workspace/didChangeConfiguration works. + (setq eglot-workspace-configuration + (list (cons ':typescript '(:inlayHints (:includeInlayParameterNameHints + "all" + :includeInlayParameterNameHintsWhenArgumentMatchesName + t + :includeInlayFunctionParameterTypeHints + t + :includeInlayVariableTypeHints + t + :includeInlayVariableTypeHintsWhenTypeMatchesName + t + :includeInlayPRopertyDeclarationTypeHints + t + :includeInlayFunctionLikeReturnTypeHints + t + :includeInlayEnumMemberValueHints + t))))) + (eglot-ensure) + ;; (defclass my/eglot-typescript (eglot-lsp-server) () + ;; :documentation + ;; "Own eglot server class.") + + ;; (add-to-list 'eglot-server-programs + ;; '((js-mode js-ts-mode tsx-ts-mode typescript-ts-mode typescript-mode) . (my/eglot-typescript "typescript-language-server" "--stdio" :initializationOptions (:preferences (:includeInlayParameterNameHints + ;; "all" + ;; :includeInlayParameterNameHintsWhenArgumentMatchesName + ;; t + ;; :includeInlayFunctionParameterTypeHints + ;; t + ;; :includeInlayVariableTypeHints + ;; t + ;; :includeInlayVariableTypeHintsWhenTypeMatchesName + ;; t + ;; :includeInlayPRopertyDeclarationTypeHints + ;; t + ;; :includeInlayFunctionLikeReturnTypeHints + ;; t + ;; :includeInlayEnumMemberValueHints + ;; t))))) + ) + ) + +(use-package tsx-ts-mode + :ensure nil + :pin manual + :mode ( + ("\\.tsx\\'" . tsx-ts-mode) + ) + :commands (tsx-ts-mode) + :hook ( + (tsx-ts-mode . (lambda () + (when-linux + (configure-typescript-language-server) + ) + )) + ) + :init + (add-to-list 'treesit-language-source-alist '(tsx . ("https://github.com/tree-sitter/tree-sitter-typescript" "master" "tsx/src"))) + (unless (treesit-ready-p 'tsx) (treesit-install-language-grammar 'tsx)) + ) + + +(use-package typescript-ts-mode + :ensure nil + :pin manual + :mode ( + ("\\.ts\\'" . typescript-ts-mode) + ) + :commands (typescript-ts-mode) + :hook ( + (typescript-ts-mode . (lambda () + (configure-typescript-language-server) + )) + ) + :init + (add-to-list 'treesit-language-source-alist '(typescript . ("https://github.com/tree-sitter/tree-sitter-typescript" "master" "typescript/src"))) + (unless (treesit-ready-p 'typescript) (treesit-install-language-grammar 'typescript)) + ) + +(use-package js-ts-mode + :ensure nil + :pin manual + :mode ( + ("\\.js\\'" . js-ts-mode) + ) + :commands (js-ts-mode) + :hook ( + (js-ts-mode . (lambda () + (when-linux + (eglot-ensure) + ) + )) + ) + :init + (add-to-list 'treesit-language-source-alist '(javascript . ("https://github.com/tree-sitter/tree-sitter-javascript" "master" "src"))) + (unless (treesit-ready-p 'javascript) (treesit-install-language-grammar 'javascript)) + ) + +(defun prettier-fmt () + "Run prettier." + (run-command-on-buffer "prettier" "--stdin-filepath" buffer-file-name) + ) + + +(use-package css-ts-mode + :ensure nil + :pin manual + :mode ( + ("\\.css\\'" . css-ts-mode) + ) + :commands (css-ts-mode) + :custom (css-indent-offset 2) + :init + (add-to-list 'treesit-language-source-alist '(css "https://github.com/tree-sitter/tree-sitter-css")) + (unless (treesit-ready-p 'css) (treesit-install-language-grammar 'css)) + :hook ( + (css-ts-mode . (lambda () + (eglot-ensure) + (defclass my/eglot-css (eglot-lsp-server) () + :documentation + "Own eglot server class.") + + (add-to-list 'eglot-server-programs + '(css-ts-mode . (my/eglot-css "vscode-css-language-server" "--stdio"))) + ;; (add-hook 'before-save-hook 'eglot-format-buffer nil 'local) + (add-hook 'before-save-hook 'prettier-fmt nil 'local) + )) + ) + ) + + +(use-package web-mode + :mode (("\\.dust\\'" . dust-mode) + ) + :config + (setq web-mode-markup-indent-offset 2) + (setq web-mode-enable-current-element-highlight t) + ) + +;; Define a custom mode for dust so that org-mode handle #+BEGIN_SRC dust blocks +(define-derived-mode dust-mode web-mode "WebDust" + "Major mode for editing dust templates in web-mode." + (web-mode) + (web-mode-set-engine "dust") + ;; (setq web-mode-content-type "html") + ) + +(provide 'lang-javascript) diff --git a/nix/configuration/roles/emacs/emacs.d/elisp/lang-lua.el b/nix/configuration/roles/emacs/emacs.d/elisp/lang-lua.el new file mode 100644 index 0000000..7403f05 --- /dev/null +++ b/nix/configuration/roles/emacs/emacs.d/elisp/lang-lua.el @@ -0,0 +1,21 @@ +(defun lua-format-buffer () + "Run stylua." + (interactive) + (run-command-on-buffer "stylua" "--search-parent-directories" "--stdin-filepath" buffer-file-name "-") + ) + +(use-package lua-mode + :mode + (("\\.lua\\'" . lua-mode) + ("\\.rockspec\\'" . lua-mode)) + :commands lua-mode + :hook ( + (lua-mode . (lambda () + (add-hook 'before-save-hook 'lua-format-buffer nil 'local) + )) + ) + :custom + (lua-indent-level 4) + ) + +(provide 'lang-lua) diff --git a/nix/configuration/roles/emacs/emacs.d/elisp/lang-markdown.el b/nix/configuration/roles/emacs/emacs.d/elisp/lang-markdown.el new file mode 100644 index 0000000..dd9ddb8 --- /dev/null +++ b/nix/configuration/roles/emacs/emacs.d/elisp/lang-markdown.el @@ -0,0 +1,14 @@ +(use-package markdown-mode + :ensure t + :commands (markdown-mode gfm-mode) + :mode (("README\\.md\\'" . gfm-mode) + ("\\.md\\'" . markdown-mode) + ("\\.markdown\\'" . markdown-mode)) + :init (setq markdown-command "multimarkdown")) + +;; For code block editing +(use-package edit-indirect + :commands (edit-indirect-region edit-indirect-save edit-indirect-abort edit-indirect-commit edit-indirect-display-active-buffer) + ) + +(provide 'lang-markdown) diff --git a/nix/configuration/roles/emacs/emacs.d/elisp/lang-nix.el b/nix/configuration/roles/emacs/emacs.d/elisp/lang-nix.el new file mode 100644 index 0000000..9ba0abd --- /dev/null +++ b/nix/configuration/roles/emacs/emacs.d/elisp/lang-nix.el @@ -0,0 +1,22 @@ +(require 'common-lsp) +(require 'util-tree-sitter) + +(use-package nix-mode + :mode (("\\.nix\\'" . nix-mode) + ) + :commands nix-mode + :hook ( + (nix-mode . (lambda () + ;; (eglot-ensure) + ;; (defclass my/eglot-nix (eglot-lsp-server) () + ;; :documentation + ;; "Own eglot server class.") + + ;; (add-to-list 'eglot-server-programs + ;; '(nix-mode . (my/eglot-nix "nixd"))) + ;; (add-hook 'before-save-hook 'eglot-format-buffer nil 'local) + )) + ) + ) + +(provide 'lang-nix) diff --git a/nix/configuration/roles/emacs/emacs.d/elisp/lang-org.el b/nix/configuration/roles/emacs/emacs.d/elisp/lang-org.el new file mode 100644 index 0000000..4a9166d --- /dev/null +++ b/nix/configuration/roles/emacs/emacs.d/elisp/lang-org.el @@ -0,0 +1,81 @@ +(use-package org + :ensure nil + :commands org-mode + :bind ( + ("C-c l" . org-store-link) + ("C-c a" . org-agenda) + ("C--" . org-timestamp-down) + ("C-=" . org-timestamp-up) + ) + :hook ( + (org-mode . (lambda () + (org-indent-mode +1) + )) + ) + :config + (require 'org-tempo) + (setq org-export-latex-listings t) + (setq org-startup-truncated nil) + (setq org-startup-folded nil) + (setq org-src-fontify-natively t + org-src-tab-acts-natively t + org-confirm-babel-evaluate nil + ) + + ;; Show the full source of org-mode links instead of condensing them. I.E. render "[[foo]]" instead of "foo" + (setq org-descriptive-links nil) + + ;; Only interpret _ and ^ and sub and superscripts if they're of the form _{subscript} and ^{superscript} + (setq org-export-with-sub-superscripts '{}) + ;; Don't include a "validate" link at the bottom of html export + (setq org-html-validation-link nil) + + + (setq org-latex-listings 'minted) + (setq org-latex-minted-options '(("breaklines" "true") + ("breakanywhere" "true") + ("bgcolor" "mintedbg") ("frame" "single") ("framesep" "6pt") ("fontsize" "\\footnotesize"))) + + ;; TODO: There is an option to set the compiler, could be better than manually doing this here https://orgmode.org/manual/LaTeX_002fPDF-export-commands.html + ;; (setq org-latex-compiler "lualatex") + (setq org-latex-pdf-process + '("lualatex -shell-escape -interaction nonstopmode -output-directory %o %f" + "lualatex -shell-escape -interaction nonstopmode -output-directory %o %f" + "lualatex -shell-escape -interaction nonstopmode -output-directory %o %f")) + (add-to-list 'org-latex-packages-alist '("cache=false" "minted")) + (add-to-list 'org-latex-packages-alist '("" "svg")) + (add-to-list 'org-latex-packages-alist '("margin=2cm" "geometry" nil)) + + (add-to-list 'org-src-lang-modes '("dot" . "graphviz-dot")) + + (org-babel-do-load-languages 'org-babel-load-languages + '((shell . t) + (js . t) + (emacs-lisp . t) + (python . t) + (dot . t) + (css . t) + (gnuplot . t) + (sqlite . t) + )) + + (require 'color) + + (let ((bg (face-attribute 'default :background))) + (custom-set-faces + `(org-block ((t (:inherit default :background ,(color-lighten-name bg 15) :extend ,t)))) + `(org-block-begin-line ((t (:inherit default :background ,"#472300" :extend ,t)))) + `(org-block-end-line ((t (:inherit default :background ,"#472300" :extend ,t)))) + )) + ) + +(use-package org-bullets + :commands org-bullets-mode + :hook (org-mode . org-bullets-mode) + ) + +(use-package gnuplot-mode) +(use-package gnuplot) +(use-package graphviz-dot-mode) + +(provide 'lang-org) diff --git a/nix/configuration/roles/emacs/emacs.d/elisp/lang-python.el b/nix/configuration/roles/emacs/emacs.d/elisp/lang-python.el new file mode 100644 index 0000000..39382e5 --- /dev/null +++ b/nix/configuration/roles/emacs/emacs.d/elisp/lang-python.el @@ -0,0 +1,92 @@ +(require 'common-lsp) +(require 'util-tree-sitter) + +(defun python-backspace (arg) + "Special handling of python backspace." + (interactive "*p") + (if mark-active + (backward-delete-char-untabify arg) + (python-indent-dedent-line-backspace arg) + ) + ) + +(defun locate-venv-poetry () + "Find a poetry venv." + (run-command-in-directory nil "poetry" "env" "info" "-p") + ) + +(defun locate-pyproject-directory () + "Adapt lsp-python-ms for poetry." + (let ((pypoetry-file (locate-dominating-file (buffer-file-name) "pyproject.toml"))) + pypoetry-file + ) + ) + + +(defun python-fmt () + "format python." + (python-fmt-black) + (python-fmt-isort) + ) + +(defun python-fmt-black () + "Run black." + (run-command-on-buffer "black" "--quiet" "--fast" "-") + ) + +(defun python-fmt-isort () + "Run isort." + (run-command-on-buffer "isort" "-") + ) + +(defun add-poetry-venv-to-path () + "Add the bin folder in the poetry venv to exec-path." + (let ( + (venv-path (locate-venv-poetry)) + ) + (when venv-path + (make-local-variable 'exec-path) + (add-to-list 'exec-path (concat venv-path "/bin")) + ) + ) + ) + +(use-package python + :mode ("\\.py\\'" . python-ts-mode) + :commands (python-mode python-ts-mode) + :pin manual + :hook ( + (python-ts-mode . (lambda () + (when-linux + (when (executable-find "poetry") + (add-poetry-venv-to-path) + (let ((venv (locate-venv-poetry))) (when venv + (setq eglot-workspace-configuration + (list (cons ':python (list ':venvPath venv ':pythonPath (concat venv "/bin/python"))))) + )) + ) + (eglot-ensure) + ) + + ;; (when-freebsd + ;; (eglot-ensure) + ;; (defclass my/eglot-pylyzer (eglot-lsp-server) () + ;; :documentation + ;; "Own eglot server class.") + + ;; (add-to-list 'eglot-server-programs + ;; '(python-ts-mode . (my/eglot-pylyzer "pylyzer" "--server"))) + ;; ) + + (add-hook 'before-save-hook 'python-fmt nil 'local) + )) + ) + :bind ((:map python-ts-mode-map ([backspace] . python-backspace)) + ) + :init + (add-to-list 'major-mode-remap-alist '(python-mode . python-ts-mode)) + (add-to-list 'treesit-language-source-alist '(python "https://github.com/tree-sitter/tree-sitter-python")) + (unless (treesit-ready-p 'python) (treesit-install-language-grammar 'python)) + ) + +(provide 'lang-python) diff --git a/nix/configuration/roles/emacs/emacs.d/elisp/lang-rust.el b/nix/configuration/roles/emacs/emacs.d/elisp/lang-rust.el new file mode 100644 index 0000000..4e857bc --- /dev/null +++ b/nix/configuration/roles/emacs/emacs.d/elisp/lang-rust.el @@ -0,0 +1,92 @@ +(require 'common-lsp) +(require 'util-tree-sitter) + +(defun locate-rust-analyzer () + "Find rust-analyzer." + (let ((rust-analyzer-paths (list (locate-rust-analyzer-rustup) (locate-rust-analyzer-ansible-built) (locate-rust-analyzer-in-path)))) + (let ((first-non-nil-path (seq-find (lambda (elt) elt) rust-analyzer-paths))) + first-non-nil-path + ) + ) + ) + +(defun locate-rust-analyzer-rustup () + "Find rust-analyzer through rustup." + (run-command-in-directory nil "rustup" "which" "rust-analyzer") + ) + +(defun locate-rust-analyzer-ansible-built () + "Find rust-analyzer where the ansible playbook built it." + (let ((rust-analyzer-path "/opt/rust-analyzer/target/release/rust-analyzer")) + (when (file-exists-p rust-analyzer-path) + rust-analyzer-path + ) + ) + ) + +(defun locate-rust-analyzer-in-path () + "Find rust-analyzer in $PATH." + (executable-find "rust-analyzer") + ) + +(use-package rust-ts-mode + :pin manual + :mode ( + ("\\.rs\\'" . rust-ts-mode) + ) + :commands (rust-ts-mode) + :hook ( + (rust-ts-mode . (lambda () + (eglot-ensure) + ;; Disable on-type formatting which was incorrectly injecting parenthesis into my code. + (make-local-variable 'eglot-ignored-server-capabilities) + (add-to-list 'eglot-ignored-server-capabilities :documentOnTypeFormattingProvider) + ;; Configure initialization options + (let ((rust-analyzer-command (locate-rust-analyzer))) + (when rust-analyzer-command + ;; (add-to-list 'eglot-server-programs `(rust-ts-mode . (,rust-analyzer-command))) + (add-to-list 'eglot-server-programs `(rust-ts-mode . (,rust-analyzer-command :initializationOptions (:imports (:granularity (:enforce t :group "item") + :merge (:glob nil) + :prefix "self") + )))) + ) + ) + (add-hook 'before-save-hook 'eglot-format-buffer nil 'local) + )) + ) + :init + (add-to-list 'major-mode-remap-alist '(rust-mode . rust-ts-mode)) + (add-to-list 'treesit-language-source-alist '(rust "https://github.com/tree-sitter/tree-sitter-rust")) + (unless (treesit-ready-p 'rust) (treesit-install-language-grammar 'rust)) + :config + ;; Add keybindings for interacting with Cargo + (use-package cargo + :hook (rust-ts-mode . cargo-minor-mode)) + ) + +(use-package toml-ts-mode + :ensure nil + :pin manual + :mode ( + ("\\.toml\\'" . toml-ts-mode) + ) + :commands (toml-ts-mode) + :init + (add-to-list 'treesit-language-source-alist '(toml "https://github.com/tree-sitter/tree-sitter-toml")) + (unless (treesit-ready-p 'toml) (treesit-install-language-grammar 'toml)) + ) + +;; Set additional rust-analyzer settings: +;; +;; (add-to-list 'eglot-server-programs `(rust-ts-mode . (,rust-analyzer-command :initializationOptions (:cargo (:features "all"))))) +;; +;; In addition to the above, directory-specific settings can be written to a .dir-locals.el with the contents: +;; +;; ( +;; (rust-ts-mode . ((eglot-workspace-configuration +;; . (:rust-analyzer (:cargo (:noDefaultFeatures t :features ["compare" "tracing"])))) +;; )) +;; ) + + +(provide 'lang-rust) diff --git a/nix/configuration/roles/emacs/emacs.d/elisp/lang-terraform.el b/nix/configuration/roles/emacs/emacs.d/elisp/lang-terraform.el new file mode 100644 index 0000000..897ccd0 --- /dev/null +++ b/nix/configuration/roles/emacs/emacs.d/elisp/lang-terraform.el @@ -0,0 +1,38 @@ +(require 'common-lsp) +(require 'util-tree-sitter) + +(defun terraform-fmt () + "Run terraform fmt." + (run-command-on-buffer "terraform" "fmt" "-") + ) + + +(use-package hcl-mode + :mode (("\\.hcl\\'" . hcl-mode)) + :commands hcl-mode + :custom (hcl-indent-level 2) + :hook ( + (hcl-mode . (lambda () (unless (derived-mode-p 'terraform-mode) (add-hook 'before-save-hook 'terraform-fmt nil 'local)))) + ) + ) + +(use-package terraform-mode + :mode (("\\.tf\\'" . terraform-mode) + ("\\.tfvars\\'" . terraform-mode)) + :commands terraform-mode + :custom (terraform-indent-level 2) + :hook ( + (terraform-mode . (lambda () + (eglot-ensure) + (defclass my/eglot-terraform (eglot-lsp-server) () + :documentation + "Own eglot server class.") + + (add-to-list 'eglot-server-programs + '(terraform-mode . (my/eglot-terraform "terraform-ls" "serve"))) + (add-hook 'before-save-hook 'eglot-format-buffer nil 'local) + )) + ) + ) + +(provide 'lang-terraform) diff --git a/nix/configuration/roles/emacs/emacs.d/elisp/lang-xml.el b/nix/configuration/roles/emacs/emacs.d/elisp/lang-xml.el new file mode 100644 index 0000000..5f7c12e --- /dev/null +++ b/nix/configuration/roles/emacs/emacs.d/elisp/lang-xml.el @@ -0,0 +1,17 @@ +(defun xml-fmt () + "Run xmllint --format." + (run-command-on-buffer "xmllint" "--format" "-") + ) + +(use-package nxml-mode + :commands (nxml-mode) + :pin manual + :ensure nil + :hook ( + (nxml-mode . (lambda () + (add-hook 'before-save-hook 'xml-fmt nil 'local) + )) + ) + ) + +(provide 'lang-xml) diff --git a/nix/configuration/roles/emacs/emacs.d/elisp/lang-yaml.el b/nix/configuration/roles/emacs/emacs.d/elisp/lang-yaml.el new file mode 100644 index 0000000..bf8cde1 --- /dev/null +++ b/nix/configuration/roles/emacs/emacs.d/elisp/lang-yaml.el @@ -0,0 +1,27 @@ +(defun yaml-format-buffer () + "Run prettier." + (interactive) + (run-command-on-buffer "prettier" "--stdin-filepath" buffer-file-name) + ) + +(use-package yaml-ts-mode + :mode + ( + ("\\.y[a]?ml\\'" . yaml-ts-mode) + ("playbook\\.tmp\\'" . yaml-ts-mode) + ("environments/[^/]*/group_vars/[^/]*\\'" . yaml-ts-mode) + ("environments/[^/]*/host_vars/[^/]*\\'" . yaml-ts-mode) + ) + :commands (yaml-ts-mode) + :hook ( + (yaml-ts-mode . (lambda () + (add-hook 'before-save-hook 'yaml-format-buffer nil 'local) + )) + ) + :init + (add-to-list 'major-mode-remap-alist '(yaml-mode . yaml-ts-mode)) + (add-to-list 'treesit-language-source-alist '(yaml "https://github.com/ikatyang/tree-sitter-yaml")) + (unless (treesit-ready-p 'yaml) (treesit-install-language-grammar 'yaml)) + ) + +(provide 'lang-yaml) diff --git a/nix/configuration/roles/emacs/emacs.d/elisp/util-flymake.el b/nix/configuration/roles/emacs/emacs.d/elisp/util-flymake.el new file mode 100644 index 0000000..c35451b --- /dev/null +++ b/nix/configuration/roles/emacs/emacs.d/elisp/util-flymake.el @@ -0,0 +1,10 @@ +(use-package flymake + :pin manual + :ensure nil + :commands (flymake-mode) + :config + ;; Set the text before the brackets for flymake's modeline output to an empty string to make it less verbose. + (setq flymake-mode-line-lighter "") + ) + +(provide 'util-flymake) diff --git a/nix/configuration/roles/emacs/emacs.d/elisp/util-tree-sitter.el b/nix/configuration/roles/emacs/emacs.d/elisp/util-tree-sitter.el new file mode 100644 index 0000000..2dc791e --- /dev/null +++ b/nix/configuration/roles/emacs/emacs.d/elisp/util-tree-sitter.el @@ -0,0 +1,16 @@ +(use-package treesit + :pin manual + :ensure nil + :commands (treesit-install-language-grammar treesit-ready-p) + :init + (setq treesit-language-source-alist '()) + :config + ;; Default to the max level of detail in treesitter highlighting. This + ;; can be overridden in each language's use-package call with: + ;; + ;; :custom + ;; (treesit-font-lock-level 3) + (setq treesit-font-lock-level 4) + ) + +(provide 'util-tree-sitter) diff --git a/nix/configuration/roles/emacs/emacs.d/elisp/util-vertico.el b/nix/configuration/roles/emacs/emacs.d/elisp/util-vertico.el new file mode 100644 index 0000000..a1e003e --- /dev/null +++ b/nix/configuration/roles/emacs/emacs.d/elisp/util-vertico.el @@ -0,0 +1,61 @@ +(defun my/minibuffer-delete (arg) + "When looking for files, go up an entire directory with the backspace button if theres no text after the directory." + (interactive "p") + (if minibuffer-completing-file-name + (if (string-match-p ".*/$" (minibuffer-contents)) + (vertico-directory-delete-word arg) + (vertico-directory-delete-char arg)) + (delete-backward-char arg))) + +(use-package vertico + :config + (vertico-mode) + (vertico-mouse-mode) + + ;; Remove prefix when switching to tilde or root ("/") + (setq file-name-shadow-properties '(invisible t intangible t)) + (file-name-shadow-mode +1) + + (set-face-attribute 'vertico-current nil :inherit nil :background "#383b01") + :custom + (vertico-count 20) + ) + +;; Create an ido/ivy-like experience when selecting files. +(use-package vertico-directory + :after vertico + :ensure nil + :bind ( :map vertico-map + ("RET" . vertico-directory-enter) + :map minibuffer-local-map + ("DEL" . my/minibuffer-delete) + ) + ) + +(use-package consult + :custom + (completion-in-region-function #'consult-completion-in-region) + (xref-show-xrefs-function #'consult-xref) + (xref-show-definitions-function #'consult-xref) + (consult-project-root-function #'deadgrep--project-root) + :bind ( + ("C-. s" . consult-ripgrep) + ("C-s" . consult-line) + ("M-g g" . consult-goto-line) + ("C-. e" . consult-flymake) + ) + ) + +;; (use-package corfu +;; :commands (corfu-mode global-corfu-mode) +;; :custom +;; (corfu-auto t) +;; ) + +(use-package marginalia + :config (marginalia-mode)) + +(use-package orderless + :custom (completion-styles '(orderless))) + +(provide 'util-vertico) diff --git a/nix/configuration/roles/emacs/emacs.d/init.el b/nix/configuration/roles/emacs/emacs.d/init.el new file mode 100644 index 0000000..68b1a11 --- /dev/null +++ b/nix/configuration/roles/emacs/emacs.d/init.el @@ -0,0 +1,41 @@ +(add-to-list 'load-path (concat user-emacs-directory "elisp")) + +(require 'base) +(require 'base-theme) +(require 'base-extensions) +(require 'base-functions) +(require 'base-global-keys) + +(require 'util-vertico) + +(require 'util-flymake) + +(require 'lang-python) + +(require 'lang-javascript) + +(require 'lang-rust) + +(require 'lang-yaml) + +(require 'lang-org) + +(require 'lang-bash) + +(require 'lang-markdown) + +(require 'lang-lua) + +(require 'lang-terraform) + +(require 'lang-go) + +(require 'lang-dockerfile) + +(require 'lang-c) + +(require 'lang-xml) + +(require 'lang-nix) + +(load-directory autoload-directory) diff --git a/nix/configuration/roles/git/default.nix b/nix/configuration/roles/git/default.nix new file mode 100644 index 0000000..2fb6ca0 --- /dev/null +++ b/nix/configuration/roles/git/default.nix @@ -0,0 +1,15 @@ +{ config, lib, pkgs, ... }: + +{ + imports = []; + + environment.systemPackages = with pkgs; [ + git + ]; + + home-manager.users.talexander = { pkgs, ... }: { + home.file.".gitconfig" = { + source = ./files/gitconfig_home; + }; + }; +} diff --git a/nix/configuration/roles/git/files/gitconfig_home b/nix/configuration/roles/git/files/gitconfig_home new file mode 100644 index 0000000..a03f09d --- /dev/null +++ b/nix/configuration/roles/git/files/gitconfig_home @@ -0,0 +1,35 @@ +[user] + email = tom@fizz.buzz + name = Tom Alexander + signingkey = D3A179C9A53C0EDE +[push] + default = simple +[alias] + lg = log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit + bh = log --oneline --branches=* --remotes=* --graph --decorate + amend = commit --amend --no-edit +[core] + excludesfile = ~/.gitignore_global +[commit] + gpgsign = true +[pull] + rebase = true +[log] + date = local +[init] + defaultBranch = main + +# Use meld for `git difftool` and `git mergetool` +[diff] + tool = meld +[difftool] + prompt = false +[difftool "meld"] + cmd = meld "$LOCAL" "$REMOTE" +[merge] + tool = meld +[mergetool "meld"] + # Make the middle pane start with partially-merged contents: + cmd = meld "$LOCAL" "$MERGED" "$REMOTE" --output "$MERGED" + # Make the middle pane start without any merge progress: + # cmd = meld "$LOCAL" "$BASE" "$REMOTE" --output "$MERGED" diff --git a/nix/configuration/roles/sway/default.nix b/nix/configuration/roles/sway/default.nix index 1c99cc2..e5db1d2 100644 --- a/nix/configuration/roles/sway/default.nix +++ b/nix/configuration/roles/sway/default.nix @@ -37,6 +37,8 @@ exec ${pkgs.alacritty}/bin/alacritty include ${base-hotkeys} include ${display-configs} include ${window-management} +include ${movement} +include ${disable-focus-follows-mouse} include ~/.config/sway/config.d/*.conf include /etc/sway/config.d/* ''; @@ -140,6 +142,69 @@ mode "resize" { bindsym Escape mode "default" } bindsym $mod+r mode "resize" +''; + }; + movement = pkgs.writeTextFile { + name = "movement.conf"; + text = '' +# +# Moving around: +# + # Move your focus around + # bindsym $mod+$left focus left + # bindsym $mod+$down focus down + # bindsym $mod+$up focus up + # bindsym $mod+$right focus right + # or use $mod+[up|down|left|right] + bindsym $mod+Left focus left + bindsym $mod+Down focus down + bindsym $mod+Up focus up + bindsym $mod+Right focus right + + # _move_ the focused window with the same, but add Shift + bindsym $mod+Shift+$left move left + bindsym $mod+Shift+$down move down + bindsym $mod+Shift+$up move up + bindsym $mod+Shift+$right move right + # ditto, with arrow keys + bindsym $mod+Shift+Left move left + bindsym $mod+Shift+Down move down + bindsym $mod+Shift+Up move up + bindsym $mod+Shift+Right move right +# +# Workspaces: +# + # switch to workspace + bindsym $mod+1 workspace 1 + bindsym $mod+2 workspace 2 + bindsym $mod+3 workspace 3 + bindsym $mod+4 workspace 4 + bindsym $mod+5 workspace 5 + bindsym $mod+6 workspace 6 + bindsym $mod+7 workspace 7 + bindsym $mod+8 workspace 8 + bindsym $mod+9 workspace 9 + bindsym $mod+0 workspace 10 + # move focused container to workspace + bindsym $mod+Shift+1 move container to workspace 1 + bindsym $mod+Shift+2 move container to workspace 2 + bindsym $mod+Shift+3 move container to workspace 3 + bindsym $mod+Shift+4 move container to workspace 4 + bindsym $mod+Shift+5 move container to workspace 5 + bindsym $mod+Shift+6 move container to workspace 6 + bindsym $mod+Shift+7 move container to workspace 7 + bindsym $mod+Shift+8 move container to workspace 8 + bindsym $mod+Shift+9 move container to workspace 9 + bindsym $mod+Shift+0 move container to workspace 10 + # Note: workspaces can have any name you want, not just numbers. + # We just use 1-10 as the default. +''; + }; + disable-focus-follows-mouse = pkgs.writeTextFile { + name = "disable-focus-follows-mouse.conf"; + text = '' +# Disable focus following mouse +focus_follows_mouse no ''; }; in @@ -149,6 +214,7 @@ in environment.systemPackages = with pkgs; [ alacritty firefox + pcmanfm ]; hardware.graphics.enable = true;