;;; $DOOMDIR/config.el -*- lexical-binding: t; -*- ;;;; Misc settings ;; start Emacs as a server process (server-start) ;; user info (setq user-full-name "Jeffrey Serio" user-mail-address "hyperreal@fedoraproject.org") (setq doom-user-dir "~/sync/doom/") (after! projectile (setq projectile-project-root-files-bottom-up (remove ".git" projectile-project-root-files-bottom-up))) ;; This sets the frame dimensions and position on the screen when on moonshadow host. ;; Also sets the font size for moonshadow host. (when (string= (system-name) "moonshadow") (setq fontsize 18) (setq default-frame-alist '((height . 54) (width . 154) (left . 1720) (top . 0) (vertical-scroll-bars . nil) (horizontal-scroll-bars . nil)))) ;; This sets the frame to be full screen maximized on evergloam host. ;; Also sets the font size for evergloam host. (when (string= (system-name) "evergloam") (setq fontsize 18) (add-to-list 'default-frame-alist '(fullscreen . maximized))) ;; Set fonts (setq monofontfam "JetBrainsMono Nerd Font Mono") (setq doom-font (font-spec :family monofontfam :size fontsize) doom-variable-pitch-font (font-spec :family "Rubik") doom-unicode-font (font-spec :family monofontfam :size fontsize) doom-big-font (font-spec :family monofontfam :size fontsize)) ;; Use catppuccin-mocha theme (setq doom-theme 'catppuccin) (setq catppuccin-flavor 'mocha) ;; Backups (setq backup-directory-alist '(("." . "~/sync/emacs/backups"))) (with-eval-after-load 'tramp (add-to-list 'tramp-backup-directory-alist (cons tramp-file-name-regexp nil))) (setq delete-old-versions -1) (setq version-control t) (setq vc-make-backup-files t) (setq auto-save-file-name-transforms '((".*" "~/sync/emacs/auto-save-list/" t))) ;; History (setq savehist-file "~/sync/emacs/savehist") (savehist-mode 1) (setq history-length t) (setq history-delete-duplicates t) (setq savehist-save-minibuffer-history 1) (setq savehist-additional-variables '(kill-ring search-ring regexp-search-ring)) ;; Display time in the modeline (display-time-mode 1) ;; Sentences end with a single space because it's right and proper (setq sentence-end-double-space nil) ;; This determines the style of line numbers in effect. If set to `nil', line ;; numbers are disabled. For relative line numbers, set this to `relative'. (setq display-line-numbers-type 'relative) ;; Make vterm open in another window (setq vterm-other-window 1) ;; Keybinding to kill-whole-line (global-set-key (kbd "M-9") 'kill-whole-line) ;; trim newline from string output (defun string-trim-final-newline (string) "Trim the last newline character from string. Used with `shell-command-to-string'. Source: https://emacs.stackexchange.com/a/21906" (let ((len (length string))) (cond ((and (> len 0) (eql (aref string (- len 1)) ?\n)) (substring string 0 (- len 1))) (t string)))) ;; wrapper around `shell-command-to-string' to remove newline (defun shell-command-output-string (command) (string-trim-final-newline (shell-command-to-string command))) ;; Copy all or text selection (defun xah-copy-all-or-region () "Put the whole buffer content to `kill-ring', or text selection if there's one. Respects `narrow-to-region'. URL `https://ergomacs.org/emacs/emacs_copy_cut_all_or_region.html' Version 2015-08-22" (interactive) (if (use-region-p) (progn (kill-new (buffer-substring (region-beginning) (region-end))) (message "Text selection copied.")) (progn (kill-new (buffer-string)) (message "Buffer content copied.")))) ;; Cut all or text selection (defun xah-cut-all-or-region () "Cut the whole buffer content to `kill-ring', or text selection if there's one. Respects `narrow-to-region'. URL `https://ergomacs.org/emacs/emacs_copy_cut_all_or_region.html' Version 2015-08-22" (interactive) (if (use-region-p) (progn (kill-new (buffer-substring (region-beginning) (region-end))) (delete-region (region-beginning) (region-end))) (progn (kill-new (buffer-string)) (delete-region (point-min) (point-max))))) ;; open URL in Firefox (defun browse-host-firefox (url &rest ignored) "Browse URL with the host's Firefox using distrobox-exec." (interactive "sURL: ") (shell-command (concat "firefox " url))) (setq browse-url-browser-function 'browse-host-firefox) ;; after copy Ctrl+c in Linux X11, you can paste by `yank' in emacs (setq select-enable-clipboard t) ;; after mouse selection copy in X11, you can paste by `yank' in emacs (setq select-enable-primary t) ;; set keybinding for paste (global-set-key (kbd "C-S-V") #'clipboard-yank) ;; Smart home key (defun smart-beginning-of-line () "Move point to first non-whitespace character or beginning-of-line. Move point to the first non-whitespace character on this line. If point was already at that position, move point to beginning of line." (interactive "^") (let ((oldpos (point))) (back-to-indentation) (and (= oldpos (point)) (beginning-of-line)))) (global-set-key (kbd "") 'smart-beginning-of-line) (global-set-key (kbd "") 'end-of-line) ;; Autoformat on save (setq +format-on-save-enabled-modes '(emacs-lisp-mode python-mode)) ;; UTF-8 (prefer-coding-system 'utf-8) (when (display-graphic-p) (setq x-select-request-type '(UTF8_STRING COMPOUND_TEXT TEXT STRING))) ;;;; artbollocks-mode ;;;; https://github.com/sachac/artbollocks-mode (setq artbollocks-weasel-words-regex (concat "\\b" (regexp-opt '("one of the" "should" "just" "etc" "sort of" "kind of" "a lot" "probably" "maybe" "perhaps" "I think" "really" "pretty" "utilize" "leverage") t) "\\b")) ;;;; undo-tree-mode - visualize undos and branches (global-undo-tree-mode) (setq undo-tree-visualizer-timestamps t) (setq undo-tree-visualizer-diff t) (setq undo-tree-history-directory-alist '(("." . "~/sync/emacs/backups/undo-tree"))) ;;;; evil-nerd-commenter (global-set-key (kbd "M-;") 'evilnc-comment-or-uncomment-lines) (global-set-key (kbd "C-c l") 'evilnc-quick-comment-or-uncomment-to-the-line) (global-set-key (kbd "C-c c") 'evilnc-copy-and-comment-lines) (global-set-key (kbd "C-c p") 'evilnc-comment-or-uncomment-paragraphs) ;;;; org-mode (add-hook 'org-mode-hook (lambda () (org-superstar-mode 1))) (require 'org-protocol) (setq org-modules '(org-agenda org-annotate-file org-choose org-collector )) (eval-after-load 'org '(org-load-modules-maybe t)) (setq org-directory "~/sync/org/") (setq org-default-notes-file "~/sync/org/inbox.org") (setq org-agenda-files '("~/sync/org/inbox.org")) ;; support selecting lines by using shift (setq org-support-shift-select t) ;; org-mode tags (setq org-tag-alist (quote (("@archiving" .?a) ("@calendar" .?d) ("@config" . ?c) ("@errand" . ?e) ("@fedora" . ?f) ("@homelab" . ?l) ("@homemaking" . ?m) ("@journal" . ?j) ("@log" . ?w) ("@reading" . ?r) ("@selfcare" . ?s)))) ;; org-mode keybindings (with-eval-after-load 'org (bind-key "C-c $" 'org-archive-subtree) (bind-key "C-c r" 'org-capture) (bind-key "C-c R" 'org-roam-capture) (bind-key "C-c a" 'org-agenda) (bind-key "C-c l" 'org-store-link) (bind-key "C-c L" 'org-insert-link-global) (bind-key "C-c O" 'org-open-at-point-global)) (setq org-use-effective-time t) ;; org-refile (setq org-reverse-note-order t) ; new notes prepended (setq org-refile-use-outline-path 'file) (setq org-outline-path-complete-in-steps nil) (setq org-refile-allow-creating-parent-nodes 'confirm) (setq org-refile-use-cache nil) (setq org-blank-before-new-entry '((heading . t) (plain-list-item . t))) (setq org-refile-targets `((("~/sync/org/inbox.org" "~/sync/org/grocery.org") . (:maxlevel .5)))) ;; org-todo-keywords (with-eval-after-load 'org (setq org-todo-keywords '((sequence "STARTED(s)" "TODO(t)" "WAITING(w@/!)" "IDEA(i)" "SOMEDAY(.)" "BLOCKED(k@/!)" "|" "DONE(x!)" "CANCELLED(c)") (sequence "PROJECT" "|" "DONE(x)") (sequence "MAYBE(,0)" "CHOSEN(c,+)" "|" "REJECTED"))) ;; catppuccin palette (setq org-todo-keyword-faces '(("STARTED" . (:foreground "#a6d189" :weight bold)) ("TODO" . (:foreground "#a6e3a1" :weight bold)) ("WAITING" . (:foreground "#f9e2af" :weight bold)) ("IDEA" . (:foreground "#74c7ec" :weight bold)) ("SOMEDAY" . (:foreground "#f2cdcd" :weight bold)) ("BLOCKED" . (:foreground "#c6d0f5" :weight bold)) ("DONE" . (:foreground "#f38ba8" :weight bold)) ("CANCELLED" . (:foreground "#e78284" :weight bold)) ("MAYBE" . (:foreground "#c6d0f5" :weight bold)) ("CHOSEN" . (:foreground "#89b4fa" :weight bold)) ("REJECTED" . (:foreground "#d20f39" :weight bold))))) (setq org-log-done 'time) (setq org-popup-calendar-for-date-prompt nil) ;; org-roam (setq org-roam-directory "~/sync/org-roam") (org-roam-db-autosync-mode) ;; org-roam-capture-template (setq org-roam-capture-templates '(("m" "main" plain "%?" :if-new (file+head "main/${slug}.org" "#+title: ${title}\n") :immediate-finish t :unnarrowed t) ("r" "reference" plain "%?" :if-new (file+head "reference/${title}.org" "#+title: ${title}\n") :immediate-finish t :unnarrowed t) ("s" "self" plain "%?" :if-new (file+head "self/${slug}.org" "#+title: ${title}\n#+filetags: :self:\n") :unnarrowed t) ("S" "self-entry" entry "* %U\n%?" :target (file "self/${slug}.org") :empty-lines 1 :unnarrowed t) ("c" "cookbook" plain "* %^{Recipe title}\n :PROPERTIES:\n :source-url:%?\n :servings:\n :prep-time:\n :cook-time:\n :ready-in:\n :END:\n** Ingredients\n \n** Directions\n\n" :if-new (file "recipes/${title}.org") :unnarrowed t))) ;; org-capture-templates (setq org-capture-templates '(("p" "Inbox" entry (file+headline "~/sync/org/inbox.org" "Inbox") "* %^{Title}\nSource: %u, %c\n #+BEGIN_QUOTE\n%i\n#+END_QUOTE\n\n%?" :empty-lines-before 1 :unnarrowed t :immediate-finish t) ("L" "Link" entry (file+headline "~/sync/org/inbox.org" "Inbox") "* %? [[%:link][%:description]] \nCaptured on: %U" :empty-lines-before 1 :unnarrowed t :immediate-finish t) ("d" "Calendar" entry (file "~/sync/org/calendar.org") "* TODO %?" :empty-lines-before 1 :unnarrowed t) ("j" "Journal" entry (file+olp+datetree "~/sync/org/journal.org") "* %U\n%?" :empty-lines-before 1 :unnarrowed t) ("r" "Reading" entry (file "~/sync/org/reading.org") "* %a\n%U\n%^{PROMPT}" :empty-lines-before 1 :unnarrowed t :immediate-finish t))) (defun hyperreal/org-capture-slipbox () (interactive) (org-capture nil "s")) ;;;; python-mode ;; set bpython as python shell interpreter (add-hook! python-mode-hook (setq python-shell-interpreter "bpython")) ;; enable elpy (elpy-enable) ;; set tab width; use flake8 as python-flymake-command, python-check-command (setq python-indent-offset 4) (add-hook 'python-mode-hook (lambda () (setq-local tab-width 4) (setq-local python-flymake-command '("flake8" "--max-doc-length=72", "--ignore=E211,E999,F401,F821,W503")) (setq-local python-check-command "flake8 --max-doc-length=72 --ignore=E211,E999,F401,F821,W503")) 70) ;; use Pyright LSP (add-hook 'python-mode-hook (lambda () (require 'lsp-pyright) (lsp))) (defun run-black-pep8 () "Run `black -l 79' on the current Python file." (interactive) (shell-command-to-string (format "black -l 79 %s" (shell-quote-argument (buffer-file-name))))) ;; autoformat on save with `run-black-pep8' (add-hook 'elpy-mode-hook (lambda () (add-hook 'before-save-hook 'run-black-pep8))) ;; colorize compilation buffer ;; from https://sachachua.com/dotemacs/index.html#orga33bac5 (require 'ansi-color) (defun colorize-compilation-buffer () (when (eq major-mode 'compilation-mode) (let ((inhibit-read-only t)) (ansi-color-apply-on-region compilation-filter-start (point-max))))) (add-hook 'compilation-filter-hook 'colorize-compilation-buffer) ;;;; go-mode ;; completion for GoLang (add-hook 'completion-at-point-functions 'go-complete-at-point) ;; Go - lsp-mode (defun lsp-go-install-save-hooks () (add-hook 'before-save-hook #'lsp-format-buffer t t) (add-hook 'before-save-hook #'lsp-organize-imports t t)) (add-hook 'go-mode-hook #'lsp-go-install-save-hooks) ;; Start LSP Mode (add-hook 'go-mode-hook #'lsp-deferred) ;;;; helpful (global-set-key (kbd "C-h f") #'helpful-callable) (global-set-key (kbd "C-h v") #'helpful-variable) (global-set-key (kbd "C-h k") #'helpful-key) (global-set-key (kbd "C-h x") #'helpful-command) (global-set-key (kbd "C-c C-d") #'helpful-at-point) ;;;; dired (after! dired (setq dired-listing-switches "-laGh1v --group-directories-first") (setq dired-confirm-shell-command nil dired-no-confirm t dired-deletion-confirmer '(lambda (x) t) dired-recursive-deletes 'always)) ;;;; dictionary (global-set-key (kbd "C-c l") #'dictionary-lookup-definition) (setq dictionary-server "dict.org") ;;;; centaur-tabs (global-set-key (kbd "s-{") 'centaur-tabs-switch-group) (global-set-key (kbd "s-h") 'centaur-tabs-backward-tab) (global-set-key (kbd "s-l") 'centaur-tabs-forward-tab) (setq centaur-tabs-buffer-show-groups t) (defun centaur-tabs-buffer-groups () "`centaur-tabs-buffer-groups' control buffers' group rules. Group centaur-tabs with mode if buffer is derived from `eshell-mode' `emacs-lisp-mode' `dired-mode' `org-mode' `magit-mode' All buffer names starting with * will group to \"Emacs\". Other buffer groups by `centaur-tabs-get-group-name' wit project name." (list (cond ((or (string-equal "*" (substring (buffer-name) 0 1)) (memq major-mode '(magit-process-mode magit-status-mode magit-diff-mode magit-log-mode magit-file-mode magit-blob-mode magit-blame-mode ))) "Emacs") ((derived-mode-p 'prog-mode) "Editing") ((derived-mode-p 'dired-mode) "Dired") ((memq major-mode '(helpful-mode help-mode)) "Help") ((memq major-mode '(org-mode org-agenda-clockreport-mode org-src-mode org-agenda-mode org-beamer-mode org-indent-mode org-bullets-mode org-agenda-log-mode diary-mode org-roam-mode)) "OrgMode") (t (centaur-tabs-get-group-name (current-buffer)))))) ;; prevent access to specified buffers (defun centaur-tabs-hide-tab (x) "Do not show given buffer in tabs." (let ((name (format "%s" x))) (or ;; Current window is not dedicated window. (window-dedicated-p (selected-window)) ;; Buffer name does not match blacklisted buffers. (string-prefix-p "*epc" name) (string-prefix-p "*Compile-Log*" name) (string-prefix-p "*lsp" name) (string-prefix-p "*tramp" name) (string-prefix-p "*help" name) (string-prefix-p "*Help" name) ;; Buffer is not a magit buffer. (and (string-prefix-p "magit" name) (not (file-name-extension name))) ))) ;;;; elfeed (setq elfeed-protocol-enabled-protocols '(fever)) (elfeed-protocol-enable) (setq elfeed-protocol-fever-update-unread-only t) (setq elfeed-feeds (list (list "fever+https://hyperreal@rss.hyperreal.coffee" :api-url "https://rss.hyperreal.coffee/api/fever.php" :password (shell-command-output-string "pass show freshrss/hyperreal"))))