* Emacs litterate config file I am using straight as the backend for use package and have thusly set it in [./early-init.el] ** Use-Package Install use-package and enable ':ensure t' globally. #+begin_src emacs-lisp (straight-use-package 'use-package) (setq use-package-always-ensure t) (use-package straight :custom (straight-use-package-by-default t)) #+end_src As a lifetime vim user I need to evil keys set up early ** Overrides #+begin_src emacs-lisp (setq custom-file (locate-user-emacs-file "custom-vars.el")) (load custom-file 'noerror 'nomessage) (setq global-auto-revert-non-file-buffers 't) #+end_src ** Evil Mode *** Undo-Tree evil mode requires undo-tree so I have it set to compress the undo files and enable undo-tree mode globally #+begin_src emacs-lisp (use-package undo-tree :config (global-undo-tree-mode) (setq undo-tree-auto-save-history t) (defadvice undo-tree-make-history-save-filename (after undo-tree activate) (setq ad-return-value (concat ad-return-value ".gz")))) #+end_src *** goto-chg It also requires goto-chg #+begin_src emacs-lisp (use-package goto-chg) #+end_src *** Evil Mode Now I hook in Evil mode #+begin_src emacs-lisp (use-package evil :config (evil-mode 1) (setq evil-search-module 'evil-search) (setq evil-shift-width 2) (setq evil-split-window-below 't) (setq evil-vsplit-window-right 't) (setq show-paren-mode 't) (setq evil-undo-system 'undo-tree)) (evil-set-leader '(normal visual motion) (kbd "SPC")) (evil-define-key 'normal 'global (kbd "f f") 'file-file (kbd "f s") 'save-buffer (kbd "f r") 'recentf-open-files (kbd "e e") 'eval-buffer) #+end_src *** Evil Collection #+begin_src emacs-lisp (use-package evil-collection :after evil :ensure t :config (evil-collection-init)) (use-package evil-org :after org :ensure t :hook (org-mode . (lambda () evil-org-mode)) :config (require 'evil-org-agenda) (evil-org-agenda-set-keys) (setf evil-org-key-theme '(navigation insert textobjects additional)) (setf org-special-ctrl-a/e t)) #+end_src ** UI #+begin_src emacs-lisp (use-package treemacs :config (evil-define-key 'normal 'global (kbd " f e") 'treemacs)) #+end_src Enable which key mode #+begin_src emacs-lisp (which-key-mode) #+end_src ** Theming *** Fonts / icons Icons must be installed 'all-the-icons-install #+begin_src emacs-lisp (use-package all-the-icons :if (display-graphic-p)) (use-package rainbow-delimiters :hook (prog-mode . rainbow-delimiters-mode)) #+end_src *** UI System #+begin_src emacs-lisp (require 'recentf) (recentf-mode 1) (setq history-length 50) (savehist-mode 1) (setq recentf-max-menu-items 25) (save-place-mode 1) (menu-bar-mode -1) (tool-bar-mode -1) (scroll-bar-mode -1) (global-display-line-numbers-mode 1) (hl-line-mode 1) (blink-cursor-mode 1) #+end_src *** Color Scheme -> load-theme here #+begin_src emacs-lisp (use-package doom-themes :ensure t :config ;; Global settings (defaults) (setq doom-themes-enable-bold t ; if nil, bold is universally disabled doom-themes-enable-italic t) ; if nil, italics is universally disabled (load-theme 'doom-tokyo-night t) (doom-themes-visual-bell-config) (doom-themes-neotree-config) (setq doom-themes-treemacs-theme "doom-tokyo-night") ; use "doom-colors" for less minimal icon theme (doom-themes-treemacs-config) ;; Corrects (and improves) org-mode's native fontification. (doom-themes-org-config)) #+end_src ** Utilities *** Completion **** counsel #+begin_src emacs-lisp (use-package counsel :config (counsel-mode)) (use-package swiper) (use-package ivy :config (ivy-mode) (setq ivy-use-virtual-buffers 't) (setq enable-recursive-minibuffers 't) (global-set-key "\C-s" 'swiper-isearch) (global-set-key (kbd "C-c C-r") 'ivy-resume) (global-set-key (kbd "M-x") 'counsel-M-x) (global-set-key (kbd "C-x C-f") 'counsel-find-file) (global-set-key (kbd " f") 'counsel-describe-function) (global-set-key (kbd " v") 'counsel-describe-variable) (global-set-key (kbd " o") 'counsel-describe-symbol) (global-set-key (kbd " l") 'counsel-find-library) (global-set-key (kbd " i") 'counsel-info-lookup-symbol) (global-set-key (kbd " u") 'counsel-unicode-char) (global-set-key (kbd "C-c g") 'counsel-git) (global-set-key (kbd "C-c j") 'counsel-git-grep) (global-set-key (kbd "C-c k") 'counsel-ag) (global-set-key (kbd "C-x l") 'counsel-locate) (global-set-key (kbd "C-S-o") 'counsel-rhythmbox) (define-key minibuffer-local-map (kbd "C-r") 'counsel-minibuffer-history)) (use-package all-the-icons-ivy-rich :ensure t :init (all-the-icons-ivy-rich-mode 1)) (use-package ivy-rich :ensure t :init (ivy-rich-mode 1)) #+end_src **** helpful #+begin_src emacs-lisp (use-package helpful :config (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-S-d") #'helpful-at-point)) #+end_src ** Org Mode *** Org Roam Presents a good example of use-package's capabilities. #+begin_src emacs-lisp (use-package org-roam :ensure t :after org :custom (org-roam-directory "~/org/roam") :bind (("C-c n l" . org-roam-buffer-toggle) ("C-c n f" . org-roam-node-find) ("C-c n i" . org-roam-node-insert) :map org-mode-map ("C-M-i" . completion-at-point)) :init (setq org-roam-v2-ack t) :config (org-roam-setup)) (setq org-roam-node-display-template (concat "${title:*} " (propertize "${tags:10}" 'face 'org-tag))) (setq org-roam-database-connector 'sqlite-builtin) (setq org-roam-capture-templates '(("d" "default" plain "%?" :target (file+head "${slug}.org" "#+title: ${title}\n") :unnarrowed t))) #+end_src #+begin_src (org-roam-capture-templates '(("d" "default" plain "%?" :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) ("b" "book notes" plain "\n* Source\n\nAuthor: %^{Author}\nTitle: ${title}\nYear: %^{Year}\n\n* Summary\n\n%?" :if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n") :unnarrowed t) ("p" "project" 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: Project") :unnarrowed t)) #+end_src **** Capture Templates #+begin_src emacs-lisp #+end_src *** Org Agenda #+begin_src emacs-lisp (setq org-columns-default-format "%50ITEM(Task) %10CLOCKSUM %16TIMESTAMP_IA") #+end_src *** Capture Templates **** Agenda Related :PROPERTIES: :ID: e81c993e-995d-492f-af46-73928c0a4fbd :END: [https://d12frosted.io/posts/2020-06-23-task-management-with-roam-vol1.html] #+begin_src emacs-lisp (setq org-capture-templates '(("t" "todo" entry (file org-default-notes-file) "* TODO %?\n%u\n%a\n" :clock-in t :clock-resume t) ("m" "Meeting" entry (file org-default-notes-file) "* MEETING with %? :MEETING:\n%t" :clock-in t :clock-resume t) ("d" "Diary" entry (file+datetree "~/org/diary.org") "* %?\n%U\n" :clock-in t :clock-resume t) ("i" "Idea" entry (file org-default-notes-file) "* %? :IDEA: \n%t" :clock-in t :clock-resume t) ("n" "Next Task" entry (file+headline org-default-notes-file "Tasks") "** NEXT %? \nDEADLINE: %t") )) #+end_src #+begin_src emacs-lisp (setq org-agenda-prefix-format '((agenda . " %i %-12(vulpea-agenda-category)%?-12t% s") (todo . " %i %-12(vulpea-agenda-category) ") (tags . " %i %-12(vulpea-agenda-category) ") (search . " %i %-12(vulpea-agenda-category) "))) (defun vulpea-agenda-category () "Get category of item at point for agenda. Category is defined by one of the following items: - CATEGORY property - TITLE keyword - TITLE property - filename without directory and extension Usage example: (setq org-agenda-prefix-format '((agenda . \" %(vulpea-agenda-category) %?-12t %12s\"))) Refer to `org-agenda-prefix-format' for more information." (let* ((file-name (when buffer-file-name (file-name-sans-extension (file-name-nondirectory buffer-file-name)))) (title (vulpea-buffer-prop-get "title")) (category (org-get-category))) (or (if (and title (string-equal category file-name)) title category) ""))) (defun vulpea-buffer-prop-get (name) "Get a buffer property called NAME as a string." (org-with-point-at 1 (when (re-search-forward (concat "^#\\+" name ": \\(.*\\)") (point-max) t) (buffer-substring-no-properties (match-beginning 1) (match-end 1))))) (setq org-agenda-prefix-format '((agenda . " %i %(vulpea-agenda-category 12)%?-12t% s") (todo . " %i %(vulpea-agenda-category 12) ") (tags . " %i %(vulpea-agenda-category 12) ") (search . " %i %(vulpea-agenda-category 12) "))) (defun vulpea-agenda-category (&optional len) "Get category of item at point for agenda. Category is defined by one of the following items: - CATEGORY property - TITLE keyword - TITLE property - filename without directory and extension When LEN is a number, resulting string is padded right with spaces and then truncated with ... on the right if result is longer than LEN. Usage example: (setq org-agenda-prefix-format '((agenda . \" %(vulpea-agenda-category) %?-12t %12s\"))) Refer to `org-agenda-prefix-format' for more information." (let* ((file-name (when buffer-file-name (file-name-sans-extension (file-name-nondirectory buffer-file-name)))) (title (vulpea-buffer-prop-get "title")) (category (org-get-category)) (result (or (if (and title (string-equal category file-name)) title category) ""))) (if (numberp len) (s-truncate len (s-pad-right len " " result)) result))) (defun vulpea-ensure-filetag () "Add respective file tag if it's missing in the current note." (interactive) (let ((tags (vulpea-buffer-tags-get)) (tag (vulpea--title-as-tag))) (when (and (seq-contains-p tags "people") (not (seq-contains-p tags tag))) (vulpea-buffer-tags-add tag)))) (defun vulpea--title-as-tag () "Return title of the current note as tag." (vulpea--title-to-tag (vulpea-buffer-title-get))) (defun vulpea--title-to-tag (title) "Convert TITLE to tag." (concat "@" (s-replace " " "" title))) (defun vulpea-tags-add () "Add a tag to current note." (interactive) ;; since https://github.com/org-roam/org-roam/pull/1515 ;; `org-roam-tag-add' returns added tag, we could avoid reading tags ;; in `vulpea-ensure-filetag', but this way it can be used in ;; different contexts while having simple implementation. (when (call-interactively #'org-roam-tag-add) (vulpea-ensure-filetag))) (defun org-roam-node-insert-wrapper (fn) "Insert a link to the note using FN. If inserted node has PEOPLE tag on it, tag the current outline accordingly." (interactive) (when-let* ((node (funcall fn)) (title (org-roam-node-title node)) (tags (org-roam-node-tags node))) (when (seq-contains-p tags "people") (save-excursion (ignore-errors (org-back-to-heading) (org-set-tags (seq-uniq (cons (vulpea--title-to-tag title) (org-get-tags nil t))))))))) (advice-add #'org-roam-node-insert :around #'org-roam-node-insert-wrapper) (defun my-vulpea-insert-handle (note) "Hook to be called on NOTE after `vulpea-insert'." (when-let* ((title (vulpea-note-title note)) (tags (vulpea-note-tags note))) (when (seq-contains-p tags "people") (save-excursion (ignore-errors (org-back-to-heading) (when (eq 'todo (org-element-property :todo-type (org-element-at-point))) (org-set-tags (seq-uniq (cons (vulpea--title-to-tag title) (org-get-tags nil t)))))))))) (defun vulpea--title-to-tag (title) "Convert TITLE to tag." (concat "@" (s-replace " " "" title))) (add-hook 'vulpea-insert-handle-functions #'my-vulpea-insert-handle) #+end_src * EXWM #+begin_src emacs-lisp (require 'exwm) ;; Set the initial workspace number. (setq exwm-workspace-number 4) ;; Make class name the buffer name. (add-hook 'exwm-update-class-hook (lambda () (exwm-workspace-rename-buffer exwm-class-name))) ;; Global keybindings. (setq exwm-input-global-keys `(([?\s-r] . exwm-reset) ;; s-r: Reset (to line-mode). ([?\s-w] . exwm-workspace-switch) ;; s-w: Switch workspace. ([?\s-&] . (lambda (cmd) ;; s-&: Launch application. (interactive (list (read-shell-command "$ "))) (start-process-shell-command cmd nil cmd))) ;; s-N: Switch to certain workspace. ,@(mapcar (lambda (i) `(,(kbd (format "s-%d" i)) . (lambda () (interactive) (exwm-workspace-switch-create ,i)))) (number-sequence 0 9)))) ;; Enable EXWM ;; let's get encryption established (setenv "GPG_AGENT_INFO" nil) ;; use emacs pinentry (setq auth-source-debug t) (setq epg-gpg-program "gpg2") ;; not necessary (require 'epa-file) (epa-file-enable) (setq epa-pinentry-mode 'loopback) (setq epg-pinentry-mode 'loopback) (pinentry-start) (require 'org-crypt) (org-crypt-use-before-save-magic) (require 'exwm-randr) (require 'exwm-systemtray) (setq exwm-randr-workspace-output-plist '(o "eDP-1")) (add-hook 'exwm-randr-screen-change-hook (lambda () (start-process-shell-command "xrandr" nil "xrandr --output eDP-1 --scale .5 --filter nearest"))) (exwm-randr-enable) (exwm-systemtray-enable)