;;; init.el --- This is where all emacs start. -*- lexical-binding: t -*- ;;; 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 server :config (setq server-client-instructions nil) (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<))) ("BU" 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)) :custom (eshell-hist-ignoredups t) (eshell-history-size 50000) (eshell-ls-dired-initial-args '("-h")) (eshell-ls-initial-args "-h") (eshell-ls-exclude-regexp "~\\'") (eshell-save-history-on-exit t) (eshell-stringify-t nil) (eshell-term-name "ansi")) (use-package project :bind (("C-x p ." . project-dired) ("C-x p " . 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 ;; byte-compile-warnings: (not docstrings lexical noruntime) ;; End: