#+TITLE: Emacs Configuration #+PROPERTY: header-args :tangle ~/.emacs.d/init.el :mkdirp yes #+auto_tangle: t #+STARTUP: overview * System information Check the ~$HOSTNAME~ to set a variable for different devices #+begin_src emacs-lisp (defvar is-zeus (equal (system-name) "zeus")) (defvar is-hermes (equal (system-name) "hermes")) (defvar is-phone (equal (system-name) "localhost")) #+end_src Setup default browser as ~mullvad-browser~ #+begin_src emacs-lisp (setq browse-url-browser-function 'browse-url-generic browse-url-generic-program "mullvad-browser") #+end_src Set backup fails at ~~/Trash~ #+begin_src emacs-lisp (setq backup-directory-alist '((".*" . "~/.Trash"))) #+end_src * Setting up Packages ** List of required packages Request the following packages: #+begin_src emacs-lisp (defconst my-package-list '(org-snooze org-drill all-the-icons all-the-icons-dired all-the-icons-ivy-rich dap-mode toc-org emojify doom-themes gruvbox-theme doom-modeline counsel vterm multi-vterm which-key ivy ivy-rich helpful password-store org org-modern org-roam visual-fill-column rainbow-delimiters flycheck lsp-mode lsp-ui json-mode rjsx-mode typescript-mode python-mode pyvenv company company-box magit elfeed elfeed-goodies paredit corfu monkeytype sudo-edit consult alsamixer simple-httpd eshell-syntax-highlighting org-superstar pdf-tools org-auto-tangle slime slime-company chatgpt org-download eshell-git-prompt eshell-vterm hackernews circe)) #+end_src ** Installation & activation Set ~package-archives~, and install packages #+begin_src emacs-lisp (setq package-archives '(("melpa" . "https://melpa.org/packages/") ("org" . "https://orgmode.org/elpa/") ("elpa" . "https://elpa.gnu.org/packages/") ("jcs-elpa" . "https://jcs-emacs.github.io/jcs-elpa/packages/"))) (package-initialize) (unless package-archive-contents (package-refresh-contents)) (defvar my-missing-packages '() "List populated at each startup. Contains the list of packages that need to be installed.") (dolist (p my-package-list) (when (not (package-installed-p p)) (add-to-list 'my-missing-packages p))) (when my-missing-packages (message "Emacs is now refreshing its package database...") (package-refresh-contents) ;; Install the missing packages (dolist (p my-missing-packages) (message "Installing `%s' .." p) (package-install p)) (setq my-missing-packages '())) (unless (package-installed-p 'use-package) (package-install 'use-package)) ;; set and load custom.el (setq custom-file (concat user-emacs-directory "custom.el")) (load custom-file 'noerror) #+end_src * UI Settings ** Basic UI Fonts and basic appearance settings #+begin_src emacs-lisp (setq inhibit-startup-message t) (setq initial-scratch-message nil) ;; Transparency (set-frame-parameter (selected-frame) 'alpha '(90 95)) (add-to-list 'default-frame-alist '(alpha 90 90)) (add-hook 'dired-mode-hook 'all-the-icons-dired-mode) (if is-zeus (display-battery-mode 0) (display-battery-mode 1)) (when (equal is-phone nil) (scroll-bar-mode -1) (set-fringe-mode 10)) (tool-bar-mode -1) (tooltip-mode -1) (menu-bar-mode -1) (which-key-mode 1) (blink-cursor-mode -1) (menu-bar--visual-line-mode-enable) (global-visual-line-mode 1) (require 'emojify) (if (version< emacs-version "29") (setq global-emojify-mode 1) (setq global-emojify-mode 0)) (setq visible-bell t) (column-number-mode) (global-display-line-numbers-mode 0) (menu-bar--display-line-numbers-mode-relative) ;;Disable line numbers for some modes (dolist (mode '(pdf-view-mode-hook org-mode-hook term-mode-hook shell-mode-hook eshell-mode-hook vterm-mode-hook elfeed)) (add-hook mode (lambda () (display-line-numbers-mode 0)))) (defvar apollo/default-font-size 140) (when is-hermes (setq apollo/default-font-size 120)) (set-face-attribute 'default nil :font "JetBrains Mono" :height apollo/default-font-size) (set-face-attribute 'fixed-pitch nil :font "JetBrains Mono" :height apollo/default-font-size) (set-face-attribute 'variable-pitch nil :font "JetBrains Mono" :height apollo/default-font-size :weight 'regular) #+end_src ** Theme & modeline #+begin_src emacs-lisp (load-theme 'doom-ayu-dark t) (doom-modeline-mode 1) (setq doom-modeline-height 35) #+end_src ** Ivy #+begin_src emacs-lisp (use-package ivy :diminish :bind (("C-s" . swiper) :map ivy-minibuffer-map ("TAB" . ivy-alt-done) ("C-l" . ivy-alt-done) ("C-j" . ivy-next-line) ("C-k" . ivy-previous-line) :map ivy-switch-buffer-map ("C-k" . ivy-previous-line) ("C-l" . ivy-done) ("C-d" . ivy-switch-buffer-kill) :map ivy-reverse-i-search-map ("C-k" . ivy-previous-line) ("C-d" . ivy-reverse-i-search-kill)) :config (ivy-mode 1) (setq ivy-use-selectable-prompt t)) (ivy-rich-mode 1) (all-the-icons-ivy-rich-mode 1) #+end_src ** Helpful #+begin_src emacs-lisp (use-package helpful :custom (counsel-describe-function-function #'helpful-callable) (counsel-describe-variable-function #'helpful-variable) :bind ([remap describe-function] . counsel-describe-function) ([remap describe-command] . helpful-command) ([remap describe-variable] . counsel-describe-variable) ([remap describe-key] . helpful-key)) #+end_src * Dired ** All-the-icons.el #+begin_src emacs-lisp ;;; all-the-icons-dired.el --- Shows icons for each file in dired mode -*- lexical-binding: t; -*- ;;; Code: (require 'cl-lib) (require 'dired) (require 'all-the-icons) (defface all-the-icons-dired-dir-face '((((background dark)) :foreground "white") (((background light)) :foreground "black")) "Face for the directory icon" :group 'all-the-icons-faces) (defcustom all-the-icons-dired-v-adjust 0.01 "The default vertical adjustment of the icon in the dired buffer." :group 'all-the-icons :type 'number) (defvar all-the-icons-dired-mode) (defun all-the-icons-dired--add-overlay (pos string) "Add overlay to display STRING at POS." (let ((ov (make-overlay (1- pos) pos))) (overlay-put ov 'all-the-icons-dired-overlay t) (overlay-put ov 'after-string string))) (defun all-the-icons-dired--overlays-in (beg end) "Get all all-the-icons-dired overlays between BEG to END." (cl-remove-if-not (lambda (ov) (overlay-get ov 'all-the-icons-dired-overlay)) (overlays-in beg end))) (defun all-the-icons-dired--overlays-at (pos) "Get all-the-icons-dired overlays at POS." (apply #'all-the-icons-dired--overlays-in `(,pos ,pos))) (defun all-the-icons-dired--remove-all-overlays () "Remove all `all-the-icons-dired' overlays." (save-restriction (widen) (mapc #'delete-overlay (all-the-icons-dired--overlays-in (point-min) (point-max))))) (defun all-the-icons-dired--refresh () "Display the icons of files in a dired buffer." (all-the-icons-dired--remove-all-overlays) (save-excursion (goto-char (point-min)) (while (not (eobp)) (when (dired-move-to-filename nil) (let ((file (dired-get-filename 'relative 'noerror))) (when file (let ((icon (if (file-directory-p file) (all-the-icons-icon-for-dir file :face 'all-the-icons-dired-dir-face :v-adjust all-the-icons-dired-v-adjust) (all-the-icons-icon-for-file file :v-adjust all-the-icons-dired-v-adjust)))) (if (member file '("." "..")) (all-the-icons-dired--add-overlay (point) " \t") (all-the-icons-dired--add-overlay (point) (concat icon "\t"))))))) (forward-line 1)))) (defun all-the-icons-dired--refresh-advice (fn &rest args) "Advice function for FN with ARGS." (apply fn args) (when all-the-icons-dired-mode (all-the-icons-dired--refresh))) (defun all-the-icons-dired--setup () "Setup `all-the-icons-dired'." (when (derived-mode-p 'dired-mode) (setq-local tab-width 1) (advice-add 'dired-readin :around #'all-the-icons-dired--refresh-advice) (advice-add 'dired-revert :around #'all-the-icons-dired--refresh-advice) (advice-add 'dired-internal-do-deletions :around #'all-the-icons-dired--refresh-advice) (advice-add 'dired-insert-subdir :around #'all-the-icons-dired--refresh-advice) (advice-add 'dired-do-kill-lines :around #'all-the-icons-dired--refresh-advice) (with-eval-after-load 'dired-narrow (advice-add 'dired-narrow--internal :around #'all-the-icons-dired--refresh-advice)) (all-the-icons-dired--refresh))) (defun all-the-icons-dired--teardown () "Functions used as advice when redisplaying buffer." (advice-remove 'dired-readin #'all-the-icons-dired--refresh-advice) (advice-remove 'dired-revert #'all-the-icons-dired--refresh-advice) (advice-remove 'dired-internal-do-deletions #'all-the-icons-dired--refresh-advice) (advice-remove 'dired-narrow--internal #'all-the-icons-dired--refresh-advice) (advice-remove 'dired-insert-subdir #'all-the-icons-dired--refresh-advice) (advice-remove 'dired-do-kill-lines #'all-the-icons-dired--refresh-advice) (all-the-icons-dired--remove-all-overlays)) ;;;###autoload (define-minor-mode all-the-icons-dired-mode "Display all-the-icons icon for each files in a dired buffer." :lighter " all-the-icons-dired-mode" (when (and (derived-mode-p 'dired-mode) (display-graphic-p)) (if all-the-icons-dired-mode (all-the-icons-dired--setup) (all-the-icons-dired--teardown)))) #+end_src Hook with ~dired-mode~ #+begin_src emacs-lisp (add-hook 'dired-mode-hook 'all-the-icons-dired-mode) #+end_src * Org-mode ** Org-Roam #+begin_src emacs-lisp ;; Set directory & autocompletions (setq org-roam-directory "~/Notes") ;; Activate autosync (org-roam-db-autosync-enable) ;; Keybindings (global-set-key (kbd "C-c n l") 'org-roam-buffer-toggle) (global-set-key (kbd "C-c n f") 'org-roam-node-find) (global-set-key (kbd "C-c n i") 'org-roam-node-insert) (define-key org-mode-map (kbd "C-c c") 'completion-at-point) #+end_src *** Templates #+begin_src emacs-lisp (setq org-roam-capture-templates '(("d" "default" plain "%?" :if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n") :unnarrowed t) ("b" "book notes" plain (file "~/Notes/Templates/BookNoteTemplate.org") :if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n") :unnarrowed t) ("l" "programming language" plain "* Characteristics\n\n- Family: %?\n- Inspired by: \n\n* Reference:\n\n" :if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n") :unnarrowed t) ("p" "MUS" plain "* Goals\n\n%?\n\n* Tasks\n\n** TODO Add initial tasks\n\n* Dates\n\n" :if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n#+filetags: MUS") :unnarrowed t))) #+end_src ** Themes *** Dracula #+begin_src emacs-lisp (defun apollo/org-theme-dracula () "Enable Dracula theme for Org headers." (interactive) (dolist (face '((org-level-1 1.7 "#8be9fd" extra-bold) (org-level-2 1.6 "#bd93f9" extra-bold) (org-level-3 1.5 "#50fa7b" bold) (org-level-4 1.4 "#ff79c6" semi-bold) (org-level-5 1.3 "#9aedfe" normal) (org-level-6 1.2 "#caa9fa" normal) (org-level-7 1.1 "#5af78e" normal) (org-level-8 1.0 "#ff92d0" normal))) (set-face-attribute (nth 0 face) nil :font "JetBrains Mono" :weight (nth 3 face) :height (nth 1 face) :foreground (nth 2 face))) (set-face-attribute 'org-table nil :font "JetBrains Mono" :weight 'normal :height 1.0 :foreground "#bfafdf")) #+end_src *** Darkone #+begin_src emacs-lisp (defun apollo/org-theme-darkone () "Enable Darkone theme for Org headers." (interactive) (dolist (face '((org-level-1 1.70 "#51afef" bold) (org-level-2 1.55 "#7FBCD2" bold) (org-level-3 1.40 "#da8548" bold) (org-level-4 1.20 "#da8548" semi-bold) (org-level-5 1.20 "#5699af" normal) (org-level-6 1.20 "#a9a1e1" normal) (org-level-7 1.10 "#46d9ff" normal) (org-level-8 1.00 "#ff6c6b" normal))) (set-face-attribute (nth 0 face) nil :font "Jetbrains Mono" :weight (nth 3 face) :height (nth 1 face) :foreground (nth 2 face))) (set-face-attribute 'org-table nil :font "Jetbrains Mono" :weight 'normal :height 1.0 :foreground "#A66CFF")) #+end_src *** Gruvbox #+begin_src emacs-lisp (defun apollo/org-theme-gruvbox () "Enable Darkone theme for Org headers." (interactive) (dolist (face '((org-level-1 1.70 "#fb4934" bold) (org-level-2 1.55 "#98971a" bold) (org-level-3 1.40 "#458588" bold) (org-level-4 1.20 "#b16286" semi-bold) (org-level-5 1.20 "#689d6a" normal) (org-level-6 1.20 "#d3869b" normal) (org-level-7 1.10 "#8ec07c" normal) (org-level-8 1.00 "#ebdbb2" normal))) (set-face-attribute (nth 0 face) nil :font "Jetbrains Mono" :weight (nth 3 face) :height (nth 1 face) :foreground (nth 2 face))) (set-face-attribute 'org-table nil :font "Jetbrains Mono" :weight 'normal :height 1.0 :foreground "#A66CFF")) #+end_src *** Org Modern #+begin_src emacs-lisp (modify-all-frames-parameters '((right-divider-width . 5) (internal-border-width . 5))) (dolist (face '(window-divider window-divider-first-pixel window-divider-last-pixel)) (face-spec-reset-face face) (set-face-foreground face (face-attribute 'default :background))) (set-face-background 'fringe (face-attribute 'default :background)) (setq ;; Edit settings org-auto-align-tags nil org-tags-column 0 org-catch-invisible-edits 'show-and-error org-special-ctrl-a/e t org-insert-heading-respect-content t ;; Org styling, hide markup etc. org-hide-emphasis-markers t org-pretty-entities t ;; Agenda styling org-agenda-tags-column 0 org-agenda-block-separator ?─ org-agenda-time-grid '((daily today require-timed) (800 1000 1200 1400 1600 1800 2000) " ┄┄┄┄┄ " "┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄") org-agenda-current-time-string "⭠ now ─────────────────────────────────────────────────") (global-org-modern-mode) #+end_src ** Settings #+begin_src emacs-lisp (require 'ox-md nil t) (require 'org-download) (require 'org-drill) (setq org-directory "~/org/" org-agenda-files '("~/org/agenda.org") org-default-notes-file (expand-file-name "notes.org" org-directory) org-ellipsis " ▼ " org-log-done 'time org-hide-emphasis-markers nil ;;change to t to hide emphasis markers org-table-convert-region-max-lines 20000 org-agenda-start-log-mode t org-log-done 'time org-log-into-drawer t org-indent-mode t org-todo-keywords ;; This overwrites the default Doom org-todo-keywords '((sequence "TODO(t)" ;; A task that is ready to be tackled "BLOG(b)" ;; Blog writing assignments "GYM(g)" ;; Things to accomplish at the gym "WAIT(w)" ;; Something is holding up this task "|" ;; The pipe necessary to separate "active" states and "inactive" states "DONE(d)" ;; Task has been completed "CANCELLED(c)" )) org-superstar-headline-bullets-list '("◉" "●" "○" "●" "○" "●" "◆") org-superstar-itembullet-alist '((?+ . ?➤) (?- . ?✦))) ;; changes +/- symbols in item lists) #+end_src Keybindings: #+begin_src emacs-lisp (define-key org-mode-map (kbd "C-c t") 'org-time-stamp-inactive) #+end_src Hooks: #+begin_src emacs-lisp (add-hook 'org-mode-hook 'apollo/org-theme-gruvbox) (add-hook 'org-mode-hook 'flyspell-mode) (add-hook 'org-mode-hook 'toc-org-mode) #+end_src ** Babel #+begin_src emacs-lisp (defadvice org-edit-src-code (around set-buffer-file-name activate compile) (let ((file-name (buffer-file-name))) ;; (1) ad-do-it ;; (2) (setq buffer-file-name file-name))) ;; (3) (org-babel-do-load-languages 'org-babel-load-languages '((emacs-lisp . t) (python . t))) (setq org-structure-template-alist '(("e" . "src emacs-lisp") ("p" . "src python") ("l" . "src lisp") ("b" . "src bash") ("q" . "QUOTE"))) ;;Auto tangle (add-hook 'org-mode-hook 'org-auto-tangle-mode) #+end_src * Markdown ** Theme #+begin_src emacs-lisp (defun apollo/markdown-theme () (interactive) (dolist (face '(markdown-header-face-1 :height 2.0)))) #+end_src ** Settings #+begin_src emacs-lisp (setq markdown-header-scaling t) (use-package markdown-mode :ensure t :mode (".md" . gfm-mode) :init (setq markdown-command "multimarkdown")) #+end_src * Programming ** Essentials #+begin_src emacs-lisp (electric-pair-mode 1) (global-flycheck-mode) (use-package company :after lsp-mode :hook (lsp-mode . company-mode) :bind (:map company-active-map ("" . company-complete-selection)) (:map lsp-mode-map ("" . company-indent-or-complete-common)) :custom (company-minimum-prefix-length 1) (company-idle-delay 0.0)) (use-package dap-mode :custom (lsp-enable-dap-auto-configure nil) :config (dap-ui-mode 1)) (use-package company-box :hook (company-mode . company-box-mode)) #+end_src *** Magit #+begin_src emacs-lisp (use-package magit :custom (magit-display-buffer-function #'magit-display-buffer-same-window-except-diff-v1)) #+end_src ** Emacs lisp #+begin_src emacs-lisp (setq tab-always-indent 'complete) (add-to-list 'completion-styles 'initials t) (add-hook 'emacs-lisp-mode-hook #'rainbow-delimiters-mode) (add-hook 'emacs-lisp-mode-hook #'company-mode) #+end_src ** Common Lisp #+begin_src emacs-lisp (setq inferior-lisp-program "sbcl") (slime-setup '(slime-fancy slime-company)) (add-hook 'lisp-mode-hook #'rainbow-delimiters-mode) (add-hook 'lisp-mode-hook #'company-mode) #+end_src ** LSP #+begin_src emacs-lisp (defun apollo/lsp-mode-setup () (setq lsp-headerline-breadcrumb-segments '(path-up-to-project file symbols)) (lsp-headerline-breadcrumb-mode)) (use-package lsp-mode :commands (lsp lsp-deferred) :hook (lsp-mode . apollo/lsp-mode-setup) :init (setq lsp-keymap-prefix "C-c l") ;; Or 'C-l', 's-l' :config (lsp-enable-which-key-integration t) (setq lsp-pyls-server-command "~/.local/bin/pylsp")) (use-package lsp-ui :hook (lsp-mode . lsp-ui-mode) :custom (lsp-ui-doc-position 'bottom)) #+end_src ** Python #+begin_src emacs-lisp (use-package python-mode :ensure t :mode ".py" :hook (python-mode . lsp-deferred) :custom (dap-python-debugger 'debugpy) :config (require 'dap-python)) (use-package pyvenv :config (pyvenv-mode 1)) #+end_src ** JSON #+begin_src emacs-lisp (use-package json-mode :mode ".json" :hook (json-mode . lsp-deferred)) #+end_src ** Javascript #+begin_src emacs-lisp (use-package rjsx-mode :mode ".js" :hook (rjsx-mode . lsp-deferred) :config (defadvice js-jsx-indent-line (after js-jsx-indent-line-after-hack activate) "Workaround sgml-mode and follow airbnb component style." (save-excursion (beginning-of-line) (if (looking-at-p "^ +\/?> *$") (delete-char sgml-basic-offset))))) #+end_src * Elfeed ** Feeds #+begin_src emacs-lisp (require 'elfeed) (require 'elfeed-goodies) (setq elfeed-feeds (quote ( ("https://hackaday.com/blog/feed/" hackaday linux) ("https://thanosapollo.com/public/feed.xml" me) ("https://protesilaos.com/news.xml" protesilaos) ("https://protesilaos.com/codelog.xml" proetesilaos) ("https://guix.gnu.org/feeds/blog.atom" gnu guix) ("https://thanosapollo.com/posts/index.xml" thanos me) ("https://rss.nytimes.com/services/xml/rss/nyt/Science.xml" NYT science news) ("https://rss.nytimes.com/services/xml/rss/nyt/Health.xml" NYT med news) ("https://rss.nytimes.com/services/xml/rss/nyt/World.xml" NYT world news) ("https://thanosapollo.com/posts/index.xml" thanos) ("http://nullprogram.com/feed/" emacs linux) ("https://drewdevault.com/blog/index.xml" sourcehut drewdevault) ("https://spacepub.space/feeds/videos.xml?videoChannelId=2" drewdevault youtube) ("https://www.youtube.com/feeds/videos.xml?channel_id=UCVls1GmFKf6WlTraIb_IaJg" video dt) ("https://www.youtube.com/feeds/videos.xml?channel_id=UC7YOGHUfC1Tb6E4pudI9STA" video mental) ("https://www.youtube.com/feeds/videos.xml?channel_id=UCAiiOTio8Yu69c3XnR7nQBQ" video daviwil) ("https://videos.lukesmith.xyz/feeds/videos.atom?sort=-publishedAt&isLocal=true" video luke) ("https://www.youtube.com/feeds/videos.xml?channel_id=UCrc2iv2-G1FZ3VscM3zu2jg" video zoogirl) ("https://www.youtube.com/feeds/videos.xml?channel_id=UC0uTPqBCFIpZxlz_Lv1tk_g" video prot) ("https://www.youtube.com/feeds/videos.xml?channel_id=UCq6VFHwMzcMXbuKyG7SQYIg" video moist) ("https://www.youtube.com/feeds/videos.xml?channel_id=UC05XpvbHZUQOfA6xk4dlmcw" video djware) ("https://archlinux.org/feeds/news/" ArchLinux Latest) ("https://www.youtube.com/feeds/videos.xml?channel_id=UCsBjURrPoezykLs9EqgamOA" fireship video) ("https://www.youtube.com/feeds/videos.xml?channel_id=UCl-J-ovSJhA3or73Q2uVpow" medicosperf video) ("https://www.youtube.com/feeds/videos.xml?channel_id=UCSuHzQ3GrHSzoBbwrIq3LLA" naomi video)))) #+end_src ** Watch Videos Create function to watch videos using ~mpv~ #+begin_src emacs-lisp (defun elfeed-v-mpv (url) "Watch a video from URL in MPV" (async-shell-command (format "mpv \"%s\"" url))) (defun elfeed-view-mpv (&optional use-generic-p) "Youtube-feed link" (interactive "P") (let ((entries (elfeed-search-selected))) (cl-loop for entry in entries do (elfeed-untag entry 'unread) when (elfeed-entry-link entry) do (elfeed-v-mpv it)) (mapc #'elfeed-search-update-entry entries) (unless (use-region-p) (forward-line)))) #+end_src ** Settings & Keys #+begin_src emacs-lisp (define-key elfeed-search-mode-map (kbd "v") 'elfeed-view-mpv) (define-key elfeed-search-mode-map (kbd "U") 'elfeed-update) (setq elfeed-goodies/entry-pane-size 0.65) (elfeed-goodies/setup) #+end_src * PDF #+begin_src emacs-lisp ;;Add pdf-isearch-minor-mode hook, otherwise isearch will be buggy ;;Darkmode hook, cause I don't want color or light in my life, I'm a vampire. (add-hook 'pdf-view-mode-hook 'pdf-isearch-minor-mode) (add-hook 'pdf-view-mode-hook 'pdf-view-midnight-minor-mode) (add-to-list 'auto-mode-alist '("\\.pdf\\'" . pdf-view-mode)) #+end_src * mu4e ** Setting up mail #+begin_src emacs-lisp ;; Check if we have mu4e available ;; if t load mu4e settings (when (require 'mu4e nil 'noerror) (setq mu4e-update-interval (* 10 60)) (setq mu4e-get-mail-command "mbsync -a") (setq mu4e-maildir-list "~/Mail/Inbox") (defun set-mu4e-context (context-name full-name mail-address signature server) "Return a mu4e context named CONTEXT-NAME with :match-func matching folder name CONTEXT-NAME in Maildir. The context's `user-mail-address', `user-full-name' and `mu4e-compose-signature'`smtpmail-smpt-server' is set to MAIL-ADDRESS FULL-NAME SIGNATURE and SERVER respectively. Special folders are set to context specific folders." (let ((dir-name (concat "/" context-name))) (make-mu4e-context :name context-name ;; we match based on the maildir of the message :match-func `(lambda (msg) (when msg (string-match-p ,(concat "^" dir-name) (mu4e-message-field msg :maildir)))) :vars `((user-mail-address . ,mail-address) (user-full-name . ,full-name) (mu4e-sent-folder . ,(concat dir-name "/Sent")) (mu4e-drafts-folder . ,(concat dir-name "/Drafts")) (mu4e-trash-folder . ,(concat dir-name "/Trash")) (mu4e-trash-folder . ,(concat dir-name "/Starred")) (mu4e-refile-folder . ,(concat dir-name "/Archive")) (smtpmail-smtp-service . ,465) (smtpmail-smtp-server . ,server) (mu4e-compose-signature . ,signature))))) ;;Fixing duplicate UID errors when using mbsync and mu4e (setq mu4e-change-filenames-when-moving t) (setq mu4e-maildir-shortcuts '(("/Fastmail/Inbox" . ?i) ("/Fastmail/Sent" . ?s) )) (setq mu4e-contexts `(, (set-mu4e-context "Fastmail" "Thanos Apollo" "public@thanosapollo.com" "Thanos\nhttps://thanosapollo.com" "smtp.fastmail.com"))) ;; (setq smtpmail-smtp-service 465 ;; smtpmail-stream-type 'ssl ;; smtpmail-smtp-server "smtp.fastmail.com") (setq message-send-mail-function 'smtpmail-send-it smtpmail-stream-type 'ssl)) #+end_src ** Actions #+begin_src emacs-lisp (setq mu4e-view-actions (delete-dups (append '(("gapply git patches" . mu4e-action-git-apply-patch) ("mgit am patch" . mu4e-action-git-apply-mbox) ("bb4 am patch" . mu4e-action-git-apply-b4) ("ssetup reword list with b4" . mu4e-action-setup-reword-b4) ("crun checkpatch script" . my-mu4e-action-run-check-patch) ("MCheck if merged" . my-mu4e-action-check-if-merged))))) #+end_src * Eshell ** Completions #+begin_src emacs-lisp ;;;; sudo completion (defun pcomplete/sudo () "Completion rules for the `sudo' command." (let ((pcomplete-ignore-case t)) (pcomplete-here (funcall pcomplete-command-completion-function)) (while (pcomplete-here (pcomplete-entries))))) ;;;; systemctl completion (defcustom pcomplete-systemctl-commands '("disable" "enable" "status" "start" "restart" "stop" "reenable" "list-units" "list-unit-files") "p-completion candidates for `systemctl' main commands" :type '(repeat (string :tag "systemctl command")) :group 'pcomplete) (defvar pcomplete-systemd-units (split-string (shell-command-to-string "(systemctl list-units --all --full --no-legend;systemctl list-unit-files --full --no-legend)|while read -r a b; do echo \" $a\";done;")) "p-completion candidates for all `systemd' units") (defvar pcomplete-systemd-user-units (split-string (shell-command-to-string "(systemctl list-units --user --all --full --no-legend;systemctl list-unit-files --user --full --no-legend)|while read -r a b;do echo \" $a\";done;")) "p-completion candidates for all `systemd' user units") (defun pcomplete/systemctl () "Completion rules for the `systemctl' command." (pcomplete-here (append pcomplete-systemctl-commands '("--user"))) (cond ((pcomplete-test "--user") (pcomplete-here pcomplete-systemctl-commands) (pcomplete-here pcomplete-systemd-user-units)) (t (pcomplete-here pcomplete-systemd-units)))) ;;;; man completion (defvar pcomplete-man-user-commands (split-string (shell-command-to-string "apropos -s 1 .|while read -r a b; do echo \" $a\";done;")) "p-completion candidates for `man' command") (defun pcomplete/man () "Completion rules for the `man' command." (pcomplete-here pcomplete-man-user-commands)) ;; hut completion (defcustom pcomplete-hut-commands '("builds" "export" "git" "graphql" "lists" "help" "hg" "init" "meta" "pages" "paste" "todo") "p-completion candidates for `hut' main commands" :type '(repeat (string :tag "hut command")) :group 'pcomplete) (defun pcomplete/hut () "Completion rules for `hut' command" (pcomplete-here (append pcomplete-hut-commands))) #+end_src ** Aliases & Paths #+begin_src emacs-lisp (defvar eshell-path-env (getenv "~/.local/bin")) (defun eshell-load-bash-aliases () "Read Bash aliases and add them to the list of eshell aliases." ;; Bash needs to be run - temporarily - interactively ;; in order to get the list of aliases. (with-temp-buffer (call-process "bash" nil '(t nil) nil "-ci" "alias") (goto-char (point-min)) (while (re-search-forward "alias \\(.+\\)='\\(.+\\)'$" nil t) (eshell/alias (match-string 1) (match-string 2))))) (defalias 'o 'find-file) (add-hook 'eshell-alias-load-hook 'eshell-load-bash-aliases) #+end_src ** Prompt #+begin_src emacs-lisp (eshell-git-prompt-use-theme 'powerline) (eshell-syntax-highlighting-global-mode 1) (setq eshell-highlight-prompt t) #+end_src ** Multi Eshell #+begin_src emacs-lisp (defun if-void (arg default) (if (boundp arg) (eval arg) default )) (defgroup multi-eshell nil "Simple support for having multiple shells open." :group 'languages) (defcustom multi-eshell-shell-function '(eshell) "Command called to create shell" :group 'multi-eshell) (defcustom multi-eshell-name "*eshell*" "The name of the buffer opened by the shell command." :type 'string :group 'multi-eshell) (defun multi-eshell-function () "This function opens the appropriate shell." (eval multi-eshell-shell-function) ) ;;;(defvar multi-eshell-function `(shell) ) ;;; Defines the shell. ('shell) or ('eshell) ;(defvar multi-eshell-name "*eshell*") ;;; Name of default shell or eshell buffer (defvar multi-eshell-ring (make-ring 100) "This stores a bunch of buffers, which are shells created by multi-eshell." ) (setq multi-eshell-index 0 ) (defvar multi-eshell-last-buffer nil) (defun multi-eshell-is-current-buffer-current-multi-eshell (&optional ignored) "Checks if current buffer is the current multi-eshell." (eq (current-buffer) (ring-ref multi-eshell-ring multi-eshell-index)) ) (defun multi-eshell-switch-to-current-shell (&optional ignored) "Switch to shell buffer." (if (buffer-live-p (ring-ref multi-eshell-ring multi-eshell-index)) (switch-to-buffer (ring-ref multi-eshell-ring multi-eshell-index)) ) ) (defun multi-eshell-current-shell (&optional ignored) "Returns the current multi-eshell." (ring-ref multi-eshell-ring multi-eshell-index) ) (defun multi-eshell-switch-to-next-live-shell (&optional ignored) "Switches to the next live shell. Creates one if none exists." (interactive "p") (let ((still-looking t) (empty nil)) (while (and still-looking (not empty)) (if (ring-empty-p multi-eshell-ring) (progn (setq empty t) (multi-eshell 1) ) (progn (if (buffer-live-p (ring-ref multi-eshell-ring multi-eshell-index)) (progn (setq multi-eshell-index (+ multi-eshell-index 1)) (switch-to-buffer (ring-ref multi-eshell-ring multi-eshell-index)) (setq still-looking nil) ) (ring-remove multi-eshell-ring multi-eshell-index) ) ) ) ) ) ) ;;;###autoload (defun multi-eshell-go-back (&optional ignored) "Switch to buffer multi-eshell-last-buffer." (interactive "p") (if (buffer-live-p multi-eshell-last-buffer) (switch-to-buffer multi-eshell-last-buffer) (message "Last buffer visited before multi-eshell is gone. Nothing to go back to..") )) ;;;###autoload (defun multi-eshell-switch (&optional ignored) "If current buffer is not an multi-eshell, switch to current multi-eshell buffer. Otherwise, switch to next multi-eshell buffer." (interactive "p") (progn (setq multi-eshell-last-buffer (current-buffer)) (let ((still-looking t) (empty nil)) (if (ring-empty-p multi-eshell-ring) (multi-eshell 1) (if (and (buffer-live-p (multi-eshell-current-shell) ) (not (eq (multi-eshell-current-shell) (current-buffer)))) (switch-to-buffer (multi-eshell-current-shell)) (multi-eshell-switch-to-next-live-shell) ) ) ))) ;;;###autoload (defun multi-eshell (&optional numshells) "Creates a shell buffer. If one already exists, this creates a new buffer, with the name '*shell*', where n is chosen by the function generate-new-buffer-name." (interactive "p") (progn (setq multi-eshell-last-buffer (current-buffer)) (dotimes (i (if-void 'numshells 1) nil) (let ( (tempname (generate-new-buffer-name "*tempshell*")) (new-buff-name (generate-new-buffer-name multi-eshell-name)) (localdir default-directory) ) (if (eq (get-buffer multi-eshell-name) nil) ;If a (progn (multi-eshell-function) ;(process-send-string (get-buffer-process new-buff-name) (concat "cd " localdir "\n")) (ring-insert multi-eshell-ring (current-buffer) ) (setq multi-eshell-index (+ multi-eshell-index 1)) ) (progn (interactive) (multi-eshell-function) (rename-buffer tempname) (multi-eshell-function) (rename-buffer new-buff-name ) (switch-to-buffer tempname) (rename-buffer multi-eshell-name) (switch-to-buffer new-buff-name) ;(process-send-string (get-buffer-process new-buff-name) (concat "cd " localdir "\n")) (ring-insert multi-eshell-ring (current-buffer) ) (setq multi-eshell-index (+ multi-eshell-index 1)) ) ) ) ) ) ) (defun shell-with-name (name) "Creates a shell with name given by the first argument, and switches to it. If a buffer with name already exists, we simply switch to it." (let ((buffer-of-name (get-buffer name)) (tempname (generate-new-buffer-name "*tempshell*") ) ) (cond ((bufferp buffer-of-name) ;If the buffer exists, switch to it (assume it is a shell) (switch-to-buffer name)) ( (bufferp (get-buffer multi-eshell-name)) (progn (multi-eshell-function) (rename-buffer tempname) (multi-eshell-function) (rename-buffer name) (switch-to-buffer tempname) (rename-buffer multi-eshell-name) (switch-to-buffer name))) ( t (progn (multi-eshell-function) (rename-buffer name)))))) #+end_src ** Keybindings #+begin_src emacs-lisp (define-prefix-command 'thanos/eshell-map) (global-set-key (kbd "C-c e") 'thanos/eshell-map) (define-key thanos/eshell-map (kbd "o") 'multi-eshell) (define-key thanos/eshell-map (kbd "n") 'multi-eshell-switch) #+end_src * Circe #+begin_src emacs-lisp (setq circe-network-options `(("Libera Chat" :tls t :nick "thanosapollo" :sasl-username "thanosapollo" :sasl-password ,(password-store-get "liberachat/thanos_apollo") :channels ("#emacs-circe" "#emacs")))) #+end_src * Misc ** Random functions #+begin_src emacs-lisp (defun apollo/html-boostrap-boilerplate () "Insert html boilerplate with boostrap link." (interactive) (insert " My Title p

Starting point

" )) (defun apollo/center-buffer () "Centers/Uncenters selected buffer" (interactive) (if visual-fill-column-center-text (setq visual-fill-column-center-text nil) (setq visual-fill-column-center-text t)) (visual-fill-column-mode 1)) (defun apollo/rofi-switch-window () "Navigate X11 buffers using rofi." (interactive) (start-process-shell-command "rofi" nil "rofi -show window")) (defun apollo/run-in-background (command) "Run COMMAND in the background." (let ((command-parts (split-string command "[ ]+"))) (apply #'call-process `(,(car command-parts) nil 0 nil ,@(cdr command-parts))))) (defun rofi () "Run Rofi." (interactive) (apollo/run-in-background "rofi -show drun")) (defun apollo/volume-increase () "Increase Volume." (interactive) (start-process-shell-command "amixer" nil "amixer sset Master 5%+")) (defun apollo/volume-decrease () "Decrease Volume." (interactive) (start-process-shell-command "amixer" nil "amixer sset Master 5%-")) (defun apollo/restore-wallpaper () "Set NAME as wallpaper." (interactive) (start-process-shell-command "feh" nil "feh --bg-scale ~/dotfiles/wallpaper.png")) (defun apollo/emacs-keys () "Swap caps with ctrl." (interactive) (start-process-shell-command "setxkbmap" nil "setxkbmap us -option ctrl:swapcaps")) (defun apollo/greek-keyboard () "Swap caps with ctrl." (interactive) (start-process-shell-command "setxkbmap" nil "setxkbmap gr")) (defun apollo/exwm-update-class () (exwm-workspace-rename-buffer exwm-class-name)) (defun eshell-new() "Open a new instance of eshell." (interactive) (eshell 'N)) (defun make-mini-geiser () (interactive) (split-window-below 60) (geiser nil)) (defun start-polybar () "Check which system is running, start polybar accordingly." (interactive) (if (string= (system-name) "fsociety") (start-process-shell-command "polybar" nil "polybar main & polybar second") (start-process-shell-command "polybar" nil "polybar main"))) (defun create-text-scratch () "create a scratch buffer" (interactive) (switch-to-buffer (get-buffer-create "*Text Scratch*")) (text-mode)) (defun create-scratch () (interactive) (switch-to-buffer (get-buffer-create "*scratch*")) (emacs-lisp-mode)) (defun get-mail-pass () (interactive) ;; Get fastmail API Key (insert (password-store-get-field "fastmail.com/thanosapollo.com" "API"))) (global-set-key (kbd "C-c p m") 'get-mail-pass) ;; #+end_src ** Chatgpt #+begin_src emacs-lisp (setq openai-key (password-store-get "chatgpt/api")) #+end_src ** Keybindings #+begin_src emacs-lisp (define-key dired-mode-map "b" 'dired-up-directory) (global-set-key (kbd "") 'keyboard-escape-quit) ;; Pass (global-set-key (kbd "C-c p i") 'password-store-insert) (global-set-key (kbd "C-c p e") 'password-store-edit) (global-set-key (kbd "C-c p g") 'password-store-generate) (define-prefix-command 'thanos/applications-map) (define-key thanos/applications-map (kbd "q") 'chatgpt-query) (define-key thanos/applications-map (kbd "m") 'mu4e) (define-key thanos/applications-map (kbd "t") 'counsel-load-theme) (define-key thanos/applications-map (kbd "f") 'elfeed) (define-key thanos/applications-map (kbd "i") 'circe) (global-set-key (kbd "C-c a") 'thanos/applications-map) (define-prefix-command 'Create) (define-key thanos/applications-map (kbd "C-c") 'Create) (define-key Create (kbd "t") 'create-text-scratch) (defvar thanos/vterm-map (make-sparse-keymap)) (define-prefix-command 'thanos/vterm-map) (define-key global-map (kbd "C-c v") 'thanos/vterm-map) (define-key thanos/vterm-map (kbd "n") 'multi-vterm-next) (define-key thanos/vterm-map (kbd "p") 'multi-vterm-prev) (define-key thanos/vterm-map (kbd "d") 'multi-vterm-dedicated-open) (define-key thanos/vterm-map (kbd "o") 'multi-vterm) #+end_src * Org-fc #+begin_src emacs-lisp (add-to-list 'load-path "~/Developer/org-fc/") (require 'org-fc) (require 'org-fc-hydra) (setq org-fc-directories '("~/org")) #+end_src