15 KiB
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.
(straight-use-package 'use-package)
(setq use-package-always-ensure t)
(use-package straight
:custom
(straight-use-package-by-default t))
As a lifetime vim user I need to evil keys set up early
Overrides
(setq custom-file (locate-user-emacs-file "custom-vars.el"))
(load custom-file 'noerror 'nomessage)
(setq global-auto-revert-non-file-buffers 't)
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
(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"))))
goto-chg
It also requires goto-chg
(use-package goto-chg)
Evil Mode
Now I hook in Evil mode
(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 "<leader>f f") 'file-file
(kbd "<leader>f s") 'save-buffer
(kbd "<leader>f r") 'recentf-open-files
(kbd "<leader>e e") 'eval-buffer)
Evil Collection
(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))
UI
(use-package treemacs :config
(evil-define-key 'normal 'global (kbd "<leader> f e") 'treemacs))
Enable which key mode
(which-key-mode)
Theming
Fonts / icons
Icons must be installed 'all-the-icons-install
(use-package all-the-icons
:if (display-graphic-p))
(use-package rainbow-delimiters :hook (prog-mode . rainbow-delimiters-mode))
UI System
(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)
Color Scheme -> load-theme here
(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))
Utilities
Completion
counsel
(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 "<f1> f") 'counsel-describe-function)
(global-set-key (kbd "<f1> v") 'counsel-describe-variable)
(global-set-key (kbd "<f1> o") 'counsel-describe-symbol)
(global-set-key (kbd "<f1> l") 'counsel-find-library)
(global-set-key (kbd "<f1> i") 'counsel-info-lookup-symbol)
(global-set-key (kbd "<f1> 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))
helpful
(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))
Org Mode
Org Roam
Presents a good example of use-package's capabilities.
(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)))
(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))
Capture Templates
Org Agenda
(setq org-columns-default-format "%50ITEM(Task) %10CLOCKSUM %16TIMESTAMP_IA")
Capture Templates
Agenda Related
[https://d12frosted.io/posts/2020-06-23-task-management-with-roam-vol1.html]
(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") ))
(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)
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)