aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--nix/users/fcuny/configs/emacs/init.el465
-rw-r--r--nix/users/fcuny/configs/emacs/site-lisp/init-base.el183
-rw-r--r--nix/users/fcuny/configs/emacs/site-lisp/init-completion.el54
-rw-r--r--nix/users/fcuny/configs/emacs/site-lisp/init-llm.el36
-rw-r--r--nix/users/fcuny/configs/emacs/site-lisp/init-programming.el198
-rw-r--r--nix/users/fcuny/configs/emacs/site-lisp/init-ui.el50
-rw-r--r--nix/users/fcuny/emacs.nix19
7 files changed, 545 insertions, 460 deletions
diff --git a/nix/users/fcuny/configs/emacs/init.el b/nix/users/fcuny/configs/emacs/init.el
index 36d05be..a6cc8c7 100644
--- a/nix/users/fcuny/configs/emacs/init.el
+++ b/nix/users/fcuny/configs/emacs/init.el
@@ -4,77 +4,15 @@
;;; Code:
-(setq backup-inhibited t) ;; no backups
-(setq create-lockfiles nil) ;; don't use a lock file
+(add-to-list 'load-path (concat user-emacs-directory (convert-standard-filename "site-lisp/")))
-(setq auto-save-default nil) ;; no auto save
-(setq confirm-kill-emacs #'yes-or-no-p) ;; ask before killing emacs
-(setq cursor-in-non-selected-windows nil) ;; keep cursors and highlights in current window only
-(setq delete-by-moving-to-trash t) ;; delete files by moving them to the trash
-(setq highlight-nonselected-windows nil) ;; don't highlight inactive windows
-(setq history-delete-duplicates t) ;; delete duplicate from history
-(setq initial-major-mode 'fundamental-mode) ;; default mode for the scratch buffer
-(setq initial-scratch-message "") ;; makes the scratch buffer empty
-(setq midnight-period (* 3600 6)) ;; clear buffer every 6 hours
-(setq mode-line-default-help-echo nil) ;; don't say anything on mode-line mouseover
-(setq require-final-newline t) ;; ensure a new line is present at the bottom of files
-(setq ring-bell-function 'ignore) ;; really no bell
-(setq sentence-end-double-space nil) ;; it matters for filling
-(setq use-short-answers t) ;; use y-or-n
-(setq visible-bell nil) ;; no bell
-(setq bidi-display-reordering nil) ;; disable bidirectional text support for slight performance bonus
-(setq column-number-mode t) ;; show column number in the mode line
-
-(global-set-key (kbd "M-j") 'join-line)
-
-(use-package recentf
- :hook (after-init . recentf-mode)
- :custom
- (recentf-max-saved-items 1000)
- (recentf-max-menu-items 25)
- (recentf-save-file-modes nil)
- (recentf-keep nil)
- (recentf-auto-cleanup nil)
- (recentf-initialize-file-name-history nil)
- (recentf-filename-handlers nil)
- (recentf-show-file-shortcuts-flag nil))
-
-(use-package midnight
- :custom
- ;; every 6 hours
- (midnight-period (* 3600 6)))
-
-(use-package imenu
- :config
- (setq imenu-auto-rescan t))
-
-(use-package autorevert
- :hook (after-init . global-auto-revert-mode)
- :custom
- (auto-revert-use-notify nil))
-
-(use-package time
- :commands (world-clock)
- :hook (after-init . display-time-mode)
- :config
- (setq display-time-format " %a %e %b, %H:%M ")
- (setq display-time-24hr-format t)
- (setq display-time-interval 60)
- (setq display-time-default-load-average nil)
- (setq display-time-world-list t)
-
- ;; M-x shell RET timedatectl list-timezones
- (setq zoneinfo-style-world-list '(("America/Los_Angeles" "Berkeley")
- ("America/Chicago" "Chicago")
- ("UTC" "UTC")
- ("Europe/Paris" "Paris")))
+(use-package exec-path-from-shell
+ :init (exec-path-from-shell-initialize))
- ;; M-x world-clock
- (setq world-clock-list t)
- (setq world-clock-time-format "%z %R %a %d %b (%Z)")
- (setq world-clock-buffer-name "*world-clock*") ; Placement handled by `display-buffer-alist'
- (setq world-clock-timer-enable t)
- (setq world-clock-timer-second 60))
+(require 'init-base)
+(require 'init-ui)
+(require 'init-completion)
+(require 'init-programming)
(use-package server
:config
@@ -82,68 +20,6 @@
(unless (server-running-p)
(server-start)))
-(use-package ibuffer
- :bind ("C-x C-b" . ibuffer)
- :custom
- (ibuffer-expert t)
- (ibuffer-show-empty-filter-groups nil)
- (ibuffer-jump-offer-only-visible-buffers t)
- (ibuffer-never-show-predicates '("^ "))
- (ibuffer-use-other-window t)
- (ibuffer-filter-group-name-face '(:inherit (font-lock-string-face bold))))
-
-(use-package which-key
- :diminish
- :hook (after-init . which-key-mode))
-
-(use-package saveplace
- :config
- (save-place-mode t))
-
-(use-package savehist
- :hook (after-init . savehist-mode)
- :custom
- (savehist-file (locate-user-emacs-file "savehist"))
- (history-length 100)
- (history-delete-duplicates t)
- (savehist-save-minibuffer-history t))
-
-(use-package magit
- :bind ("C-x g" . magit-status)
- :custom
- (magit-diff-refine-hunk t)
- (magit-repository-directories '(("~/workspace" . 1)))
- (magit-repolist-column-flag-alist '((magit-untracked-files . "N")
- (magit-unstaged-files . "U")
- (magit-staged-files . "S")))
- (magit-repolist-columns '(("Name" 25 magit-repolist-column-ident nil)
- ("" 3 magit-repolist-column-flag)
- ("Version" 25 magit-repolist-column-version
- ((:sort magit-repolist-version<)))
- ("B<U" 3 magit-repolist-column-unpulled-from-upstream
- ((:right-align t)
- (:sort <)))
- ("B>U" 3 magit-repolist-column-unpushed-to-upstream
- ((:right-align t)
- (:sort <)))
- ("Path" 99 magit-repolist-column-path nil)))
- (magit-clone-default-directory "~/workspace/")
- :config
- ;; show ANSI colors in the process buffer, so it's easier to read what's going on
- ;; for some reasons if it's in the `:custom' section it does not get set
- (setq magit-process-finish-apply-ansi-colors t))
-
-(use-package git-link
- :defines git-link-remote-alist
- :bind ("C-c Y" . git-link)
- :commands (git-link git-link-commit git-link-homepage)
- :custom
- (git-link-open-in-browser t)
- :config
- ;; sets up roblox git enterprise as a git-link handler
- (add-to-list 'git-link-remote-alist '("github\\.rblx\\.com" git-link-github))
- (add-to-list 'git-link-commit-remote-alist '("github\\.rblx\\.com" git-link-commit-github)))
-
(use-package eshell
:commands (eshell eshell-command)
:bind (("C-r" . consult-history))
@@ -157,331 +33,6 @@
(eshell-stringify-t nil)
(eshell-term-name "ansi"))
-(use-package project
- :bind
- (("C-x p ." . project-dired)
- ("C-x p <return>" . project-dired))
- :custom
- (project-switch-commands
- '(
- (consult-project-buffer "buffer" ?b)
- (project-dired "dired" ?d)
- (magit-project-status "magit status" ?g)
- (project-find-file "find file" ?p)
- (consult-ripgrep "rigprep" ?r)))
- (setq project-mode-line t)
- (setq project-key-prompt-style t)) ; Emacs 30
-
-(use-package rg
- :custom
- (rg-group-result t)
- (rg-show-columns t)
- (rg-align-line-number-field-length 3)
- (rg-align-column-number-field-length 3)
- (rg-align-line-column-separator "#")
- (rg-align-position-content-separator "|")
- (rg-hide-command nil)
- (rg-align-position-numbers t)
- (rg-command-line-flags '("--follow")))
-
-(use-package exec-path-from-shell
- :init (exec-path-from-shell-initialize))
-
-(use-package elec-pair
- :hook (prog-mode . electric-pair-mode))
-
-(use-package eldoc
- :diminish
- :hook ((emacs-lisp-mode) . eldoc-mode)
- :custom
- (eldoc-idle-delay 1)
- (eldoc-documentation-strategy #'eldoc-documentation-default)
- ;; Don't resize the echo area if the documentation is longer. This is very
- ;; distracting when combined with Eglot's highlight functionality.
- (eldoc-echo-area-use-multiline-p nil))
-
-(use-package compile
- :hook (compilation-filter . ansi-color-compilation-filter)
- :custom
- (compilation-always-kill t)
- (compilation-context-lines 10)
- (compilation-disable-input t)
- (compilation-scroll-output 'first-error)
- (compilation-scroll-output t)
- (compilation-skip-threshold 2)
- ;; Save all buffers on M-x `compile'
- (compilation-ask-about-save nil))
-
-(use-package eglot
- :after yasnippet
- :bind (:map eglot-mode-map
- ("C-c l a" . eglot-code-actions)
- ("C-c l r" . eglot-rename)
- ("C-c l f" . eglot-format-buffer))
- :hook ((go-mode . eglot-ensure)
- (python-mode . eglot-ensure)
- (nix-mode . eglot-ensure))
- :custom
- (eglot-send-changes-idle-time 0.1)
- :config
- (setq eglot-autoshutdown t
- ;; Disable logging of events.
- eglot-events-buffer-size 0)
- (setq-default eglot-workspace-configuration
- '(:pylsp (:plugins (:ruff (:enabled t)))
- :nil (:formatting (:command ["nixfmt"]))
- :gopls (:usePlaceholders t
- :staticcheck t
- :completeUnimported t
- :matcher "CaseSensitive")))
- ;; uses https://github.com/nix-community/nixd for the LSP server instead of rnix
- (add-to-list 'eglot-server-programs '(nix-mode . ("nil"))))
-
-(use-package emacs-lisp-mode
- :bind (:map emacs-lisp-mode-map
- ("C-c C-r" . eval-region)
- ("C-c C-d" . eval-defun)
- ("C-c C-b" . eval-buffer))
- :hook ((emacs-lisp-mode . flymake-mode)))
-
-(use-package go-mode
- :hook ((go-mode . (lambda () (setq tab-width 4)))
- (go-mode . (lambda () (add-hook 'before-save-hook 'eglot-format-buffer nil t))))
- :bind (:map go-mode-map
- ("C-c C-c" . compile))
- :config
- (with-eval-after-load 'exec-path-from-shell
- (exec-path-from-shell-copy-envs '("GOPATH" "GOBIN"))))
-
-(use-package gotest
- :after go-mode
- :custom
- (go-test-verbose t))
-
-(use-package nix-mode
- :hook ((nix-mode . (lambda () (add-hook 'before-save-hook 'eglot-format-buffer nil t))))
- :custom
- (nix-indent-function 'nix-indent-line))
-
-(use-package python-mode)
-
-(use-package ruby-mode)
-
-(use-package json-mode)
-
-(use-package json-reformat
- :after json-mode)
-
-(use-package jq-mode
- :mode "\\.jq\\'")
-
-(use-package terraform-mode
- :mode "\.tf\\'")
-
-(use-package hcl-mode
- :mode "\.nomad\\'")
-
-(use-package toml-mode)
-
-(use-package yaml-mode)
-
-(use-package docker
- :bind ("C-c d" . docker)
- :diminish
- :init
- (use-package docker-image :commands docker-images)
- (use-package docker-volume :commands docker-volumes)
- (use-package docker-network :commands docker-containers)
- (use-package docker-compose :commands docker-compose)
-
- (use-package docker-container
- :commands docker-containers
- :custom
- (docker-containers-shell-file-name "/bin/bash")
- (docker-containers-show-all nil)))
-
-(use-package docker-compose-mode
- :mode "docker-compose.*\.yml\\'")
-
-(use-package dockerfile-mode
- :mode "Dockerfile[a-zA-Z.-]*\\'")
-
-(use-package protobuf-mode
- :mode "\\.proto\\'")
-
-(use-package css-mode
- :custom
- (css-indent-offset 2)
- (cssm-indent-level 1))
-
-(use-package fringe
- :custom (fringe-mode '(8 . 0)))
-
-(use-package whitespace
- :init
- (global-whitespace-mode t)
- :custom
- (whitespace-style '(face
- tabs
- spaces
- tab-mark
- space-mark
- trailing
- missing-newline-at-eof
- space-after-tab::tab
- space-after-tab::space
- space-before-tab::tab
- space-before-tab::space)))
-
-(use-package dired
- :hook (dired-mode . dired-omit-mode)
- :bind (:map dired-mode-map
- ( "." . dired-omit-mode))
- :custom
- (dired-omit-files (rx (seq bol ".")))
- (dired-use-ls-dired t)
- (dired-clean-up-buffers-too nil)
- (dired-dwim-target t)
- (dired-hide-details-hide-information-lines nil)
- (dired-hide-details-hide-symlink-targets nil)
- (dired-recursive-copies 'always)
- (dired-recursive-deletes 'always)
- (dired-no-confirm
- '(byte-compile chgrp chmod chown copy hardlink symlink touch)))
-
-(defun my/rename-this-buffer-and-file ()
- "Renames current buffer and file it is visiting."
- (interactive)
- (let ((name (buffer-name))
- (filename (buffer-file-name))
- (read-file-name-function 'read-file-name-default))
- (if (not (and filename (file-exists-p filename)))
- (error "Buffer '%s' is not visiting a file!" name)
- (let ((new-name (read-file-name "New name: " filename)))
- (cond ((get-buffer new-name)
- (error "A buffer named '%s' already exists!" new-name))
- (t
- (rename-file filename new-name 1)
- (rename-buffer new-name)
- (set-visited-file-name new-name)
- (set-buffer-modified-p nil)
- (message "File '%s' successfully renamed to '%s'" name (file-name-nondirectory new-name))))))))
-
-(use-package direnv
- :custom
- (direnv-always-show-summary nil)
- :config
- (direnv-mode))
-
-(use-package flymake
- :bind (:prefix "C-c !"
- :prefix-map flymake-prefix-map
- ("l" . consult-flymake)
- ("d" . flymake-show-buffer-diagnostics)
- ("D" . flymake-show-project-diagnostics)
- ("n" . flymake-goto-next-error)
- ("p" . flymake-goto-prev-error))
- :hook
- (prog-mode . flymake-mode)
- :custom
- (flymake-start-on-save-buffer t)
- (flymake-fringe-indicator-position 'left-fringe)
- (flymake-suppress-zero-counters t)
- (flymake-proc-compilation-prevents-syntax-check t)
- (flymake-no-changes-timeout 9999)
- (elisp-flymake-byte-compile-load-path load-path))
-
-(use-package consult
- :commands (consult-ripgrep consult-buffer consult-imenu)
- :bind (("C-c m" . consult-mode-command)
- ("C-x b" . consult-buffer)
- ("C-x r b" . consult-bookmark)
- ("C-x p b" . consult-project-buffer)
- ("C-c i" . consult-imenu)
- ("M-g e" . consult-compile-error)
- ("M-g M-g" . consult-goto-line)
- ("M-g m" . consult-mark)
- ("M-g k" . consult-global-mark)))
-
-(use-package corfu
- :custom
- (corfu-auto t)
- :bind ("M-/" . completion-at-point)
- :hook ((after-init . global-corfu-mode)
- (global-corfu-mode . corfu-popupinfo-mode)))
-
-(use-package cape)
-
-(use-package marginalia
- :hook (after-init . marginalia-mode))
-
-(use-package orderless
- :custom
- (completion-styles '(orderless basic))
- (completion-category-defaults nil))
-
-(use-package vertico
- :hook ((after-init . vertico-mode)))
-
-(use-package consult-imenu
- :after (consult))
-
-(use-package corfu-popupinfo
- :after corfu
- :hook (corfu-mode . corfu-popupinfo-mode)
- :custom
- (corfu-popupinfo-delay '(0.25 . 0.1))
- (corfu-popupinfo-hide nil))
-
-(use-package modus-themes
- :custom
- (modus-themes-italic-constructs t)
- (modus-themes-syntax '(alt-syntax green-strings))
- (modus-themes-mode-line '(moody accented borderless))
- (modus-themes-tabs-accented t)
-
- (modus-themes-completions
- '((matches . (extrabold background))
- (selection . (semibold accented))
- (popup . (accented))))
-
- (modus-themes-fringe 'subtle)
- (modus-themes-lang-checkers '(text-also straight-underline))
- (modus-themes-hl-line '(accented))
- (modus-themes-subtle-line-numbers t)
- (modus-themes-markup '(bold italic))
- (modus-themes-paren-match '(bold))
- (modus-themes-region '())
-
- :config
- (load-theme 'modus-operandi)
- (enable-theme 'modus-operandi-tinted))
-
-(defvar fcuny/op-item-cache nil)
-
-(defun fcuny/read-op-item (op-item-path)
- "Read and cache OP-ITEM-PATH item."
- (or (cdr (assoc op-item-path fcuny/op-item-cache))
- (let ((key (string-trim-right
- (shell-command-to-string (format "op read '%s'" op-item-path)))))
- (unless (string-match-p "\\[ERROR\\]" key)
- (push (cons op-item-path key) fcuny/op-item-cache)
- key))))
-
-(use-package gptel
- :custom
- (gptel-default-mode 'org-mode)
- :config
- (gptel-make-anthropic "Claude" :stream t :key (lambda () (fcuny/read-op-item "op://Private/anthropic llm/credential"))))
-
-(use-package aidermacs
- :bind ("C-c a" . aidermacs-transient-menu)
- :custom
- (aider-args '("--no-check-update" "--no-show-model-warnings"))
- (aidermacs-default-model "claude-3-7-sonnet-latest")
- :config
- (setenv "ANTHROPIC_API_KEY" (fcuny/read-op-item "op://Private/anthropic llm/credential")))
-
-;;; early-init.el ends here
+;;; init.el ends here
;; byte-compile-warnings: (not docstrings lexical noruntime)
;; End:
diff --git a/nix/users/fcuny/configs/emacs/site-lisp/init-base.el b/nix/users/fcuny/configs/emacs/site-lisp/init-base.el
new file mode 100644
index 0000000..0699619
--- /dev/null
+++ b/nix/users/fcuny/configs/emacs/site-lisp/init-base.el
@@ -0,0 +1,183 @@
+;;; init-base.el --- base configuration -*- lexical-binding: t -*-
+;; Author: Franck Cuny <franck@fcuny.net>
+
+;;; Commentary:
+
+;; commentary
+
+;;; Code:
+
+(setq backup-inhibited t) ;; no backups
+(setq create-lockfiles nil) ;; don't use a lock file
+
+(setq auto-save-default nil) ;; no auto save
+(setq confirm-kill-emacs #'yes-or-no-p) ;; ask before killing emacs
+(setq cursor-in-non-selected-windows nil) ;; keep cursors and highlights in current window only
+(setq delete-by-moving-to-trash t) ;; delete files by moving them to the trash
+(setq highlight-nonselected-windows nil) ;; don't highlight inactive windows
+(setq history-delete-duplicates t) ;; delete duplicate from history
+(setq initial-major-mode 'fundamental-mode) ;; default mode for the scratch buffer
+(setq initial-scratch-message "") ;; makes the scratch buffer empty
+(setq midnight-period (* 3600 6)) ;; clear buffer every 6 hours
+(setq mode-line-default-help-echo nil) ;; don't say anything on mode-line mouseover
+(setq require-final-newline t) ;; ensure a new line is present at the bottom of files
+(setq ring-bell-function 'ignore) ;; really no bell
+(setq sentence-end-double-space nil) ;; it matters for filling
+(setq use-short-answers t) ;; use y-or-n
+(setq visible-bell nil) ;; no bell
+(setq bidi-display-reordering nil) ;; disable bidirectional text support for slight performance bonus
+(setq column-number-mode t) ;; show column number in the mode line
+
+(global-set-key (kbd "M-j") 'join-line)
+
+(use-package recentf
+ :hook (after-init . recentf-mode)
+ :custom
+ (recentf-max-saved-items 1000)
+ (recentf-max-menu-items 25)
+ (recentf-save-file-modes nil)
+ (recentf-keep nil)
+ (recentf-auto-cleanup nil)
+ (recentf-initialize-file-name-history nil)
+ (recentf-filename-handlers nil)
+ (recentf-show-file-shortcuts-flag nil))
+
+
+
+(use-package midnight
+ :custom
+ ;; every 6 hours
+ (midnight-period (* 3600 6)))
+
+(use-package imenu
+ :config
+ (setq imenu-auto-rescan t))
+
+(use-package autorevert
+ :hook (after-init . global-auto-revert-mode)
+ :custom
+ (auto-revert-use-notify nil))
+
+(use-package time
+ :commands (world-clock)
+ :hook (after-init . display-time-mode)
+ :config
+ (setq display-time-format " %a %e %b, %H:%M ")
+ (setq display-time-24hr-format t)
+ (setq display-time-interval 60)
+ (setq display-time-default-load-average nil)
+ (setq display-time-world-list t)
+
+ ;; M-x shell RET timedatectl list-timezones
+ (setq zoneinfo-style-world-list '(("America/Los_Angeles" "Berkeley")
+ ("America/Chicago" "Chicago")
+ ("UTC" "UTC")
+ ("Europe/Paris" "Paris")))
+
+ ;; M-x world-clock
+ (setq world-clock-list t)
+ (setq world-clock-time-format "%z %R %a %d %b (%Z)")
+ (setq world-clock-buffer-name "*world-clock*") ; Placement handled by `display-buffer-alist'
+ (setq world-clock-timer-enable t)
+ (setq world-clock-timer-second 60))
+
+(use-package ibuffer
+ :bind ("C-x C-b" . ibuffer)
+ :custom
+ (ibuffer-expert t)
+ (ibuffer-show-empty-filter-groups nil)
+ (ibuffer-jump-offer-only-visible-buffers t)
+ (ibuffer-never-show-predicates '("^ "))
+ (ibuffer-use-other-window t)
+ (ibuffer-filter-group-name-face '(:inherit (font-lock-string-face bold))))
+
+
+
+(use-package which-key
+ :diminish
+ :hook (after-init . which-key-mode))
+
+
+
+
+(use-package saveplace
+ :config
+ (save-place-mode t))
+
+
+
+(use-package savehist
+ :hook (after-init . savehist-mode)
+ :custom
+ (savehist-file (locate-user-emacs-file "savehist"))
+ (history-length 100)
+ (history-delete-duplicates t)
+ (savehist-save-minibuffer-history t))
+
+(use-package project
+ :bind
+ (("C-x p ." . project-dired)
+ ("C-x p <return>" . project-dired))
+ :custom
+ (project-switch-commands
+ '(
+ (consult-project-buffer "buffer" ?b)
+ (project-dired "dired" ?d)
+ (magit-project-status "magit status" ?g)
+ (project-find-file "find file" ?p)
+ (consult-ripgrep "rigprep" ?r)))
+ (setq project-mode-line t)
+ (setq project-key-prompt-style t))
+
+ ; Emacs 30
+
+(use-package rg
+ :custom
+ (rg-group-result t)
+ (rg-show-columns t)
+ (rg-align-line-number-field-length 3)
+ (rg-align-column-number-field-length 3)
+ (rg-align-line-column-separator "#")
+ (rg-align-position-content-separator "|")
+ (rg-hide-command nil)
+ (rg-align-position-numbers t)
+ (rg-command-line-flags '("--follow")))
+
+(use-package dired
+ :hook (dired-mode . dired-omit-mode)
+ :bind (:map dired-mode-map
+ ( "." . dired-omit-mode))
+ :custom
+ (dired-omit-files (rx (seq bol ".")))
+ (dired-use-ls-dired t)
+ (dired-clean-up-buffers-too nil)
+ (dired-dwim-target t)
+ (dired-hide-details-hide-information-lines nil)
+ (dired-hide-details-hide-symlink-targets nil)
+ (dired-recursive-copies 'always)
+ (dired-recursive-deletes 'always)
+ (dired-no-confirm
+ '(byte-compile chgrp chmod chown copy hardlink symlink touch)))
+
+(defun my/rename-this-buffer-and-file ()
+ "Renames current buffer and file it is visiting."
+ (interactive)
+ (let ((name (buffer-name))
+ (filename (buffer-file-name))
+ (read-file-name-function 'read-file-name-default))
+ (if (not (and filename (file-exists-p filename)))
+ (error "Buffer '%s' is not visiting a file!" name)
+ (let ((new-name (read-file-name "New name: " filename)))
+ (cond ((get-buffer new-name)
+ (error "A buffer named '%s' already exists!" new-name))
+ (t
+ (rename-file filename new-name 1)
+ (rename-buffer new-name)
+ (set-visited-file-name new-name)
+ (set-buffer-modified-p nil)
+ (message "File '%s' successfully renamed to '%s'" name (file-name-nondirectory new-name))))))))
+
+
+(provide 'init-base)
+
+;;; init-base.el ends here
diff --git a/nix/users/fcuny/configs/emacs/site-lisp/init-completion.el b/nix/users/fcuny/configs/emacs/site-lisp/init-completion.el
new file mode 100644
index 0000000..fc01a39
--- /dev/null
+++ b/nix/users/fcuny/configs/emacs/site-lisp/init-completion.el
@@ -0,0 +1,54 @@
+;;; init-completion.el --- Configure completion -*- lexical-binding: t -*-
+;; Author: Franck Cuny <franck@fcuny.net>
+
+;;; Commentary:
+
+;; Configure completions
+
+;;; Code:
+
+(use-package consult
+ :commands (consult-ripgrep consult-buffer consult-imenu)
+ :bind (("C-c m" . consult-mode-command)
+ ("C-x b" . consult-buffer)
+ ("C-x r b" . consult-bookmark)
+ ("C-x p b" . consult-project-buffer)
+ ("C-c i" . consult-imenu)
+ ("M-g e" . consult-compile-error)
+ ("M-g M-g" . consult-goto-line)
+ ("M-g m" . consult-mark)
+ ("M-g k" . consult-global-mark)))
+
+(use-package corfu
+ :custom
+ (corfu-auto t)
+ :bind ("M-/" . completion-at-point)
+ :hook ((after-init . global-corfu-mode)
+ (global-corfu-mode . corfu-popupinfo-mode)))
+
+(use-package cape)
+
+(use-package marginalia
+ :hook (after-init . marginalia-mode))
+
+(use-package orderless
+ :custom
+ (completion-styles '(orderless basic))
+ (completion-category-defaults nil))
+
+(use-package vertico
+ :hook ((after-init . vertico-mode)))
+
+(use-package consult-imenu
+ :after (consult))
+
+(use-package corfu-popupinfo
+ :after corfu
+ :hook (corfu-mode . corfu-popupinfo-mode)
+ :custom
+ (corfu-popupinfo-delay '(0.25 . 0.1))
+ (corfu-popupinfo-hide nil))
+
+(provide 'init-completion)
+
+;;; init-completion.el ends here
diff --git a/nix/users/fcuny/configs/emacs/site-lisp/init-llm.el b/nix/users/fcuny/configs/emacs/site-lisp/init-llm.el
new file mode 100644
index 0000000..4654613
--- /dev/null
+++ b/nix/users/fcuny/configs/emacs/site-lisp/init-llm.el
@@ -0,0 +1,36 @@
+;;; init-llm.el --- Configure LLMs -*- lexical-binding: t -*-
+;; Author: Franck Cuny <franck@fcuny.net>
+
+;;; Commentary:
+
+;; Configure completions
+
+;;; Code:
+(defvar fcuny/op-item-cache nil)
+
+(defun fcuny/read-op-item (op-item-path)
+ "Read and cache OP-ITEM-PATH item."
+ (or (cdr (assoc op-item-path fcuny/op-item-cache))
+ (let ((key (string-trim-right
+ (shell-command-to-string (format "op read '%s'" op-item-path)))))
+ (unless (string-match-p "\\[ERROR\\]" key)
+ (push (cons op-item-path key) fcuny/op-item-cache)
+ key))))
+
+(use-package gptel
+ :custom
+ (gptel-default-mode 'org-mode)
+ :config
+ (gptel-make-anthropic "Claude" :stream t :key (lambda () (fcuny/read-op-item "op://Private/anthropic llm/credential"))))
+
+(use-package aidermacs
+ :bind ("C-c a" . aidermacs-transient-menu)
+ :custom
+ (aider-args '("--no-check-update" "--no-show-model-warnings"))
+ (aidermacs-default-model "claude-3-7-sonnet-latest")
+ :config
+ (setenv "ANTHROPIC_API_KEY" (fcuny/read-op-item "op://Private/anthropic llm/credential")))
+
+(provide 'init-llm)
+
+;;; init-llm.el ends here
diff --git a/nix/users/fcuny/configs/emacs/site-lisp/init-programming.el b/nix/users/fcuny/configs/emacs/site-lisp/init-programming.el
new file mode 100644
index 0000000..b3712e7
--- /dev/null
+++ b/nix/users/fcuny/configs/emacs/site-lisp/init-programming.el
@@ -0,0 +1,198 @@
+;;; init-programming.el --- Configure things related to programming -*- lexical-binding: t -*-
+;; Author: Franck Cuny <franck@fcuny.net>
+
+;;; Commentary:
+
+;; Configure things related to programming
+
+;;; Code:
+
+(use-package magit
+ :bind ("C-x g" . magit-status)
+ :custom
+ (magit-diff-refine-hunk t)
+ (magit-repository-directories '(("~/workspace" . 1)))
+ (magit-repolist-column-flag-alist '((magit-untracked-files . "N")
+ (magit-unstaged-files . "U")
+ (magit-staged-files . "S")))
+ (magit-repolist-columns '(("Name" 25 magit-repolist-column-ident nil)
+ ("" 3 magit-repolist-column-flag)
+ ("Version" 25 magit-repolist-column-version
+ ((:sort magit-repolist-version<)))
+ ("B<U" 3 magit-repolist-column-unpulled-from-upstream
+ ((:right-align t)
+ (:sort <)))
+ ("B>U" 3 magit-repolist-column-unpushed-to-upstream
+ ((:right-align t)
+ (:sort <)))
+ ("Path" 99 magit-repolist-column-path nil)))
+ (magit-clone-default-directory "~/workspace/")
+ :config
+ ;; show ANSI colors in the process buffer, so it's easier to read what's going on
+ ;; for some reasons if it's in the `:custom' section it does not get set
+ (setq magit-process-finish-apply-ansi-colors t))
+
+(use-package git-link
+ :defines git-link-remote-alist
+ :bind ("C-c Y" . git-link)
+ :commands (git-link git-link-commit git-link-homepage)
+ :custom
+ (git-link-open-in-browser t)
+ :config
+ ;; sets up roblox git enterprise as a git-link handler
+ (add-to-list 'git-link-remote-alist '("github\\.rblx\\.com" git-link-github))
+ (add-to-list 'git-link-commit-remote-alist '("github\\.rblx\\.com" git-link-commit-github)))
+
+(use-package elec-pair
+ :hook (prog-mode . electric-pair-mode))
+
+(use-package eldoc
+ :diminish
+ :hook ((emacs-lisp-mode) . eldoc-mode)
+ :custom
+ (eldoc-idle-delay 1)
+ (eldoc-documentation-strategy #'eldoc-documentation-default)
+ ;; Don't resize the echo area if the documentation is longer. This is very
+ ;; distracting when combined with Eglot's highlight functionality.
+ (eldoc-echo-area-use-multiline-p nil))
+
+(use-package compile
+ :hook (compilation-filter . ansi-color-compilation-filter)
+ :custom
+ (compilation-always-kill t)
+ (compilation-context-lines 10)
+ (compilation-disable-input t)
+ (compilation-scroll-output 'first-error)
+ (compilation-scroll-output t)
+ (compilation-skip-threshold 2)
+ ;; Save all buffers on M-x `compile'
+ (compilation-ask-about-save nil))
+
+(use-package direnv
+ :custom
+ (direnv-always-show-summary nil)
+ :config
+ (direnv-mode))
+
+(use-package flymake
+ :bind (:prefix "C-c !"
+ :prefix-map flymake-prefix-map
+ ("l" . consult-flymake)
+ ("d" . flymake-show-buffer-diagnostics)
+ ("D" . flymake-show-project-diagnostics)
+ ("n" . flymake-goto-next-error)
+ ("p" . flymake-goto-prev-error))
+ :hook
+ (prog-mode . flymake-mode)
+ :custom
+ (flymake-start-on-save-buffer t)
+ (flymake-fringe-indicator-position 'left-fringe)
+ (flymake-suppress-zero-counters t)
+ (flymake-proc-compilation-prevents-syntax-check t)
+ (flymake-no-changes-timeout 9999)
+ (elisp-flymake-byte-compile-load-path load-path))
+
+(use-package eglot
+ :bind (:map eglot-mode-map
+ ("C-c l a" . eglot-code-actions)
+ ("C-c l r" . eglot-rename)
+ ("C-c l f" . eglot-format-buffer))
+ :hook ((go-mode . eglot-ensure)
+ (python-mode . eglot-ensure)
+ (nix-mode . eglot-ensure))
+ :custom
+ (eglot-send-changes-idle-time 0.1)
+ :config
+ (setq eglot-autoshutdown t
+ ;; Disable logging of events.
+ eglot-events-buffer-size 0)
+ (setq-default eglot-workspace-configuration
+ '(:pylsp (:plugins (:ruff (:enabled t)))
+ :nil (:formatting (:command ["nixfmt"]))
+ :gopls (:usePlaceholders t
+ :staticcheck t
+ :completeUnimported t
+ :matcher "CaseSensitive")))
+ ;; uses https://github.com/nix-community/nixd for the LSP server instead of rnix
+ (add-to-list 'eglot-server-programs '(nix-mode . ("nil"))))
+
+(use-package emacs-lisp-mode
+ :bind (:map emacs-lisp-mode-map
+ ("C-c C-r" . eval-region)
+ ("C-c C-d" . eval-defun)
+ ("C-c C-b" . eval-buffer))
+ :hook ((emacs-lisp-mode . flymake-mode)))
+
+(use-package go-mode
+ :hook ((go-mode . (lambda () (setq tab-width 4)))
+ (go-mode . (lambda () (add-hook 'before-save-hook 'eglot-format-buffer nil t))))
+ :bind (:map go-mode-map
+ ("C-c C-c" . compile))
+ :config
+ (with-eval-after-load 'exec-path-from-shell
+ (exec-path-from-shell-copy-envs '("GOPATH" "GOBIN"))))
+
+(use-package gotest
+ :after go-mode
+ :custom
+ (go-test-verbose t))
+
+(use-package nix-mode
+ :hook ((nix-mode . (lambda () (add-hook 'before-save-hook 'eglot-format-buffer nil t))))
+ :custom
+ (nix-indent-function 'nix-indent-line))
+
+(use-package python-mode)
+
+(use-package ruby-mode)
+
+(use-package json-mode)
+
+(use-package json-reformat
+ :after json-mode)
+
+(use-package jq-mode
+ :mode "\\.jq\\'")
+
+(use-package terraform-mode
+ :mode "\.tf\\'")
+
+(use-package hcl-mode
+ :mode "\.nomad\\'")
+
+(use-package toml-mode)
+
+(use-package yaml-mode)
+
+(use-package docker
+ :bind ("C-c d" . docker)
+ :diminish
+ :init
+ (use-package docker-image :commands docker-images)
+ (use-package docker-volume :commands docker-volumes)
+ (use-package docker-network :commands docker-containers)
+ (use-package docker-compose :commands docker-compose)
+
+ (use-package docker-container
+ :commands docker-containers
+ :custom
+ (docker-containers-shell-file-name "/bin/bash")
+ (docker-containers-show-all nil)))
+
+(use-package docker-compose-mode
+ :mode "docker-compose.*\.yml\\'")
+
+(use-package dockerfile-mode
+ :mode "Dockerfile[a-zA-Z.-]*\\'")
+
+(use-package protobuf-mode
+ :mode "\\.proto\\'")
+
+(use-package css-mode
+ :custom
+ (css-indent-offset 2)
+ (cssm-indent-level 1))
+
+(provide 'init-programming)
+
+;;; init-programming.el ends here
diff --git a/nix/users/fcuny/configs/emacs/site-lisp/init-ui.el b/nix/users/fcuny/configs/emacs/site-lisp/init-ui.el
new file mode 100644
index 0000000..e239978
--- /dev/null
+++ b/nix/users/fcuny/configs/emacs/site-lisp/init-ui.el
@@ -0,0 +1,50 @@
+;;; init-ui.el --- User interface config. -*- lexical-binding: t -*-
+
+;;; Commentary:
+
+;; User interface settings.
+
+;;; Code:
+
+(use-package whitespace
+ :init
+ (global-whitespace-mode t)
+ :custom
+ (whitespace-style '(face
+ tabs
+ tab-mark
+ trailing
+ missing-newline-at-eof)))
+
+(use-package fringe
+ :custom (fringe-mode '(8 . 0)))
+
+;; | 数字 | アルファベット | 日本語 | 絵文字 |
+;; | 0123 | abcdefghijklmn | あいう | 🍎🍎🍎 |
+(set-face-attribute 'default nil :family "Source Code Pro" :height 150)
+
+(use-package modus-themes
+ :custom
+ (modus-themes-italic-constructs t)
+ (modus-themes-syntax '(alt-syntax green-strings))
+ (modus-themes-mode-line '(moody accented borderless))
+ (modus-themes-tabs-accented t)
+
+ (modus-themes-completions
+ '((matches . (extrabold background))
+ (selection . (semibold accented))
+ (popup . (accented))))
+
+ (modus-themes-fringe 'subtle)
+ (modus-themes-lang-checkers '(text-also straight-underline))
+ (modus-themes-hl-line '(accented))
+ (modus-themes-subtle-line-numbers t)
+ (modus-themes-markup '(bold italic))
+ (modus-themes-paren-match '(bold))
+ (modus-themes-region '())
+
+ :init
+ (load-theme 'modus-operandi-tinted t))
+
+(provide 'init-ui)
+;;; init-ui.el ends here
diff --git a/nix/users/fcuny/emacs.nix b/nix/users/fcuny/emacs.nix
index cc3dc3a..849c6b4 100644
--- a/nix/users/fcuny/emacs.nix
+++ b/nix/users/fcuny/emacs.nix
@@ -1,4 +1,4 @@
-{ pkgs, ... }:
+{ pkgs, lib, ... }:
let
packages =
epkgs: with epkgs; [
@@ -36,10 +36,23 @@ let
yasnippet
yasnippet-capf
];
+ emacsFiles = [
+ "early-init.el"
+ "init.el"
+ "site-lisp/init-base.el"
+ "site-lisp/init-completion.el"
+ "site-lisp/init-llm.el"
+ "site-lisp/init-programming.el"
+ "site-lisp/init-ui.el"
+ ];
+ mkEmacsFile = file: {
+ ".config/emacs/${file}" = {
+ source = ./configs/emacs/${file};
+ };
+ };
in
{
- home.file.".config/emacs/early-init.el".source = ./configs/emacs/early-init.el;
- home.file.".config/emacs/init.el".source = ./configs/emacs/init.el;
+ home.file = lib.mkMerge (map mkEmacsFile emacsFiles);
programs.emacs = {
enable = true;