mirror of
https://github.com/correl/dotfiles.git
synced 2024-11-22 03:00:05 +00:00
1675 lines
62 KiB
Org Mode
1675 lines
62 KiB
Org Mode
#+TITLE: DOOM Emacs Configuration
|
|
#+STARTUP: indent overview
|
|
#+PROPERTY: header-args :tangle config.el
|
|
|
|
* Look And Feel
|
|
** Theme
|
|
I'm feeling the shades of purple theme lately.
|
|
#+begin_src emacs-lisp
|
|
(setq doom-theme 'doom-shades-of-purple)
|
|
#+end_src
|
|
** Default font
|
|
#+begin_src emacs-lisp
|
|
(setq doom-font (font-spec :family "Inconsolata" :size 16))
|
|
#+end_src
|
|
** Dashboard
|
|
Customize the Doom Emacs dashboard with commissioned artwork, chosen randomly.
|
|
The dashboard can be reloaded with the =g= key.
|
|
|
|
#+begin_src emacs-lisp
|
|
(defun my/choice (&rest things)
|
|
(let ((index (random (length things))))
|
|
(nth index things)))
|
|
|
|
(defun my/dashboard-randomize ()
|
|
(interactive)
|
|
(let ((logo (my/choice "~/Pictures/Patreon/Jon Bliss/phoenix-and-catgirl-500.png"
|
|
"~/Pictures/Patreon/Jon Bliss/Bassist-final-transparent-500.png"
|
|
"~/Pictures/Patreon/Jon Bliss/catgirl-final-transparent-500.png"
|
|
"~/Pictures/Patreon/Jon Bliss/lapiz-final-transparent-500.png"
|
|
"~/Pictures/Patreon/Jon Bliss/Poledancer-final-transparent-500.png"
|
|
"~/Pictures/Patreon/Jon Bliss/Hacker-final-transparent-500.png"
|
|
"~/Pictures/Patreon/Bee/IMG_3666_transparent_500.png")))
|
|
|
|
(setq fancy-splash-image logo)
|
|
(if (called-interactively-p)
|
|
(+doom-dashboard-reload))))
|
|
|
|
(my/dashboard-randomize)
|
|
(map!
|
|
:map +doom-dashboard-mode-map
|
|
"g" #'my/dashboard-randomize)
|
|
#+end_src
|
|
** Frame transparency
|
|
Set the background transparency to 90% so my wallpaper shows through.
|
|
|
|
#+begin_src emacs-lisp
|
|
(set-frame-parameter (selected-frame) 'alpha '(98 . 98))
|
|
(add-to-list 'default-frame-alist '(alpha . (98 . 98)))
|
|
#+end_src
|
|
** Comic Sans Mono
|
|
Why not, it's fun 🤣
|
|
|
|
Adds a command to switch to the monospaced Comic Sans font, and make it the
|
|
default font for PHP buffers.
|
|
|
|
https://dtinth.github.io/comic-mono-font/
|
|
|
|
#+begin_src emacs-lisp
|
|
(defun my/buffer-face-comic-mono ()
|
|
(interactive)
|
|
(setq buffer-face-mode-face '(:family "Comic Mono"))
|
|
(buffer-face-mode))
|
|
|
|
(after! php-mode
|
|
(add-hook 'php-mode-hook #'my/buffer-face-comic-mono))
|
|
#+end_src
|
|
** Mixed Pitch
|
|
Facilitates mixing monospace and proportional fonts. I'm using an MIT-licensed
|
|
version of the [[https://github.com/edwardtufte/et-book][Edward Tufte book font]] because it's /gorgeous/.
|
|
#+begin_src emacs-lisp
|
|
(use-package! mixed-pitch
|
|
:hook ((org-mode markdown-mode rst-mode) . mixed-pitch-mode))
|
|
(setq doom-variable-pitch-font (font-spec :family "ETBookOT"))
|
|
#+end_src
|
|
* UX Improvements
|
|
** Disable C-z backgrounding when the GUI is loaded
|
|
|
|
In OSX, this minimizes the window. It's incredibly annoying, and I accidentally
|
|
hit it too much. I also can't think of any reason I'd want to background Emacs
|
|
outside of a terminal session.
|
|
|
|
#+begin_src emacs-lisp
|
|
(if (display-graphic-p)
|
|
(global-unset-key (kbd "C-z")))
|
|
#+end_src
|
|
** Custom settings
|
|
Store options set via =customize-*= in a separate file (Emacs stores
|
|
them in =init.el= by default).
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq custom-file "~/.emacs.d/custom.el")
|
|
(if (file-exists-p custom-file)
|
|
(load custom-file))
|
|
|
|
(setf custom-safe-themes t)
|
|
#+END_SRC
|
|
** Eval and Replace
|
|
Replace an s-expression with its value. Taken from [[http://emacsredux.com/blog/2013/06/21/eval-and-replace/][Emacs Redux]].
|
|
|
|
#+begin_src emacs-lisp
|
|
(defun eval-and-replace ()
|
|
"Replace the preceding sexp with its value."
|
|
(interactive)
|
|
(backward-kill-sexp)
|
|
(condition-case nil
|
|
(prin1 (eval (read (current-kill 0)))
|
|
(current-buffer))
|
|
(error (message "Invalid expression")
|
|
(insert (current-kill 0)))))
|
|
|
|
(global-set-key (kbd "C-)") 'eval-and-replace)
|
|
#+end_src
|
|
** Prompt for unsafe local variables
|
|
Doom sets this to =:safe=, logging unsafe variables for later addressing. I'd
|
|
rather continue to be prompted.
|
|
|
|
#+begin_src emacs-lisp
|
|
(setq enable-local-variables t)
|
|
#+end_src
|
|
* Writing
|
|
|
|
** BibTeX
|
|
Tell Emacs where to find my bibliography files. I keep most everything in my
|
|
Calibre library, which I regularly export and keep synced via Nextcloud.
|
|
|
|
#+begin_src emacs-lisp
|
|
(setq my/bibliographies
|
|
'("~/Documents/bibliography/references.bib"
|
|
"~/Documents/bibliography/calibre.bib"))
|
|
#+end_src
|
|
*** Helm BibTeX
|
|
#+begin_src emacs-lisp
|
|
(setq bibtex-completion-bibliography my/bibliographies
|
|
bibtex-completion-pdf-field "File"
|
|
bibtex-completion-notes-path "~/org/roam")
|
|
#+end_src
|
|
*** Citar
|
|
#+begin_src emacs-lisp
|
|
(setq citar-bibliography my/bibliographies
|
|
citar-notes-paths '("~/org/roam"))
|
|
#+end_src
|
|
** Org
|
|
:PROPERTIES:
|
|
:header-args: :tangle no :noweb-ref org
|
|
:END:
|
|
|
|
Configure a variety of options and tools for [[https://orgmode.org][Org Mode]], the markup I use for
|
|
everything from simple notes to task management.
|
|
|
|
#+begin_src emacs-lisp :noweb yes :tangle "config.el" :noweb-ref org-all
|
|
(after! org
|
|
<<org>>)
|
|
#+end_src
|
|
|
|
*** Override DOOM indentation behavior
|
|
#+begin_src emacs-lisp
|
|
(defun my/org-init-babel ()
|
|
(setq org-src-preserve-indentation nil))
|
|
|
|
(add-hook! 'org-mode-hook #'my/org-init-babel)
|
|
#+end_src
|
|
*** Disable DOOM's centralized attachment system
|
|
It's incompatible with all of the org files I already have using the standard
|
|
setup.
|
|
#+begin_src emacs-lisp
|
|
(setq org-attach-directory "data/")
|
|
(remove-hook! 'org-load-hook
|
|
#'(+org-init-centralized-attachments-h))
|
|
#+end_src
|
|
*** Agenda
|
|
Set up my agenda view. I use separate files for my personal TODOs and my work
|
|
TODOs, synced externally using Nextcloud.
|
|
|
|
#+begin_src emacs-lisp
|
|
(after! org-agenda
|
|
(require 'f)
|
|
|
|
(setq my/agenda-files '((personal . ("~/Nextcloud/org/personal.org"))
|
|
(work . ("~/Nextcloud/org/aweber.org")))
|
|
|
|
org-agenda-files (-filter #'f-exists?
|
|
(-concat
|
|
(if (string-equal (system-name) "s1326.ofc.lair")
|
|
(cdr (assoc 'work my/agenda-files))
|
|
(cdr (assoc 'personal my/agenda-files))))))
|
|
|
|
(setq org-stuck-projects
|
|
'("+LEVEL=1/-DONE" ("TODO" "NEXT" "NEXTACTION") nil ""))
|
|
|
|
;; https://www.tompurl.com/2015-12-29-emacs-eisenhower-matrix.html
|
|
(setq org-tag-alist '(("important" . ?i)
|
|
("urgent" . ?u)))
|
|
|
|
(setq org-agenda-custom-commands
|
|
'(("n" "Agenda and all TODOs"
|
|
((agenda "" ((org-agenda-span 'week)))
|
|
(tags-todo "DEADLINE<=\"<+7d>\""
|
|
((org-agenda-overriding-header "Due soon")))
|
|
(todo ""
|
|
((org-agenda-overriding-header "Unscheduled")
|
|
(org-agenda-skip-function '(org-agenda-skip-entry-if 'scheduled 'deadline)))))
|
|
|
|
((org-agenda-start-with-log-mode t)
|
|
(org-agenda-start-day nil)
|
|
(org-agenda-span 'day)
|
|
(org-agenda-log-mode-items '(clock state closed)))
|
|
("~/Public/org/agenda.html"
|
|
"~/Public/org/agenda.ics"))
|
|
("l" "Log"
|
|
agenda ""
|
|
((org-agenda-span 'fortnight)
|
|
(org-agenda-start-day "-1w")
|
|
(org-agenda-start-with-log-mode t)
|
|
(org-agenda-log-mode-items '(clock state closed))
|
|
(org-agenda-include-deadlines nil)
|
|
(org-agenda-skip-scheduled-delay-if-deadline t))
|
|
("~/Public/org/agenda-log.html"))
|
|
("e" "Eisenhower Matrix"
|
|
((tags-todo "+important+urgent"
|
|
((org-agenda-overriding-header "Do")))
|
|
(tags-todo "+important-urgent"
|
|
((org-agenda-overriding-header "Decide")))
|
|
(tags-todo "-important+urgent"
|
|
((org-agenda-overriding-header "Delegate")))
|
|
(tags-todo "-important-urgent"
|
|
((org-agenda-overriding-header "Delete"))))
|
|
((org-agenda-start-with-log-mode t)
|
|
(org-agenda-span 'day)
|
|
(org-agenda-log-mode-items '(clock state closed))))))
|
|
|
|
(defun my/org-agenda-timeline ()
|
|
(interactive)
|
|
(let ((org-agenda-files (list (buffer-file-name))))
|
|
(org-agenda)))
|
|
|
|
(setq org-agenda-start-on-weekday nil)
|
|
(setq org-agenda-span 'fortnight)
|
|
(setq org-agenda-todo-ignore-scheduled 'future)
|
|
(setq org-agenda-tags-todo-honor-ignore-options t)
|
|
(setq org-agenda-skip-deadline-prewarning-if-scheduled t)
|
|
(add-hook 'org-agenda-finalize-hook (lambda () (hl-line-mode)))
|
|
|
|
(setq
|
|
org-icalendar-use-scheduled '(todo-start event-if-todo)
|
|
org-icalendar-combined-agenda-file (expand-file-name "~/Documents/org.ics")))
|
|
#+end_src
|
|
*** LaTeX Export
|
|
**** Document Classes
|
|
Tell Emacs about all of the LaTeX classes I use to export documents.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(use-package! ox-latex
|
|
:config
|
|
(seq-map (apply-partially #'add-to-list 'org-latex-classes)
|
|
'(("koma-letter"
|
|
"\\documentclass{scrlttr2}"
|
|
("\\section{%s}" . "\\section*{%s}")
|
|
("\\subsection{%s}" . "\\subsection*{%s}")
|
|
("\\subsubsection{%s}" . "\\subsubsection*{%s}")
|
|
("\\paragraph{%s}" . "\\paragraph*{%s}")
|
|
("\\subparagraph{%s}" . "\\subparagraph*{%s}"))
|
|
("koma-article"
|
|
"\\documentclass{scrartcl}"
|
|
("\\section{%s}" . "\\section*{%s}")
|
|
("\\subsection{%s}" . "\\subsection*{%s}")
|
|
("\\subsubsection{%s}" . "\\subsubsection*{%s}")
|
|
("\\paragraph{%s}" . "\\paragraph*{%s}")
|
|
("\\subparagraph{%s}" . "\\subparagraph*{%s}"))
|
|
("koma-book"
|
|
"\\documentclass{scrbook}"
|
|
("\\section{%s}" . "\\section*{%s}")
|
|
("\\subsection{%s}" . "\\subsection*{%s}")
|
|
("\\subsubsection{%s}" . "\\subsubsection*{%s}")
|
|
("\\paragraph{%s}" . "\\paragraph*{%s}")
|
|
("\\subparagraph{%s}" . "\\subparagraph*{%s}"))
|
|
("koma-book-chapters"
|
|
"\\documentclass{scrbook}"
|
|
("\\chapter{%s}" . "\\chapter*{%s}")
|
|
("\\section{%s}" . "\\section*{%s}")
|
|
("\\subsection{%s}" . "\\subsection*{%s}")
|
|
("\\subsubsection{%s}" . "\\subsubsection*{%s}")
|
|
("\\paragraph{%s}" . "\\paragraph*{%s}")
|
|
("\\subparagraph{%s}" . "\\subparagraph*{%s}"))
|
|
("koma-report"
|
|
"\\documentclass{scrreprt}"
|
|
("\\chapter{%s}" . "\\chapter*{%s}")
|
|
("\\section{%s}" . "\\section*{%s}")
|
|
("\\subsection{%s}" . "\\subsection*{%s}")
|
|
("\\subsubsection{%s}" . "\\subsubsection*{%s}")
|
|
("\\paragraph{%s}" . "\\paragraph*{%s}")
|
|
("\\subparagraph{%s}" . "\\subparagraph*{%s}"))
|
|
("memoir"
|
|
"\\documentclass{memoir}"
|
|
("\\section{%s}" . "\\section*{%s}")
|
|
("\\subsection{%s}" . "\\subsection*{%s}")
|
|
("\\subsubsection{%s}" . "\\subsubsection*{%s}")
|
|
("\\paragraph{%s}" . "\\paragraph*{%s}")
|
|
("\\subparagraph{%s}" . "\\subparagraph*{%s}"))
|
|
("hitec"
|
|
"\\documentclass{hitec}"
|
|
("\\section{%s}" . "\\section*{%s}")
|
|
("\\subsection{%s}" . "\\subsection*{%s}")
|
|
("\\subsubsection{%s}" . "\\subsubsection*{%s}")
|
|
("\\paragraph{%s}" . "\\paragraph*{%s}")
|
|
("\\subparagraph{%s}" . "\\subparagraph*{%s}"))
|
|
("paper"
|
|
"\\documentclass{paper}"
|
|
("\\section{%s}" . "\\section*{%s}")
|
|
("\\subsection{%s}" . "\\subsection*{%s}")
|
|
("\\subsubsection{%s}" . "\\subsubsection*{%s}")
|
|
("\\paragraph{%s}" . "\\paragraph*{%s}")
|
|
("\\subparagraph{%s}" . "\\subparagraph*{%s}"))
|
|
("letter"
|
|
"\\documentclass{letter}"
|
|
("\\section{%s}" . "\\section*{%s}")
|
|
("\\subsection{%s}" . "\\subsection*{%s}")
|
|
("\\subsubsection{%s}" . "\\subsubsection*{%s}")
|
|
("\\paragraph{%s}" . "\\paragraph*{%s}")
|
|
("\\subparagraph{%s}" . "\\subparagraph*{%s}"))
|
|
("tufte-handout"
|
|
"\\documentclass{tufte-handout}"
|
|
("\\section{%s}" . "\\section*{%s}")
|
|
("\\subsection{%s}" . "\\subsection*{%s}")
|
|
("\\subsubsection{%s}" . "\\subsubsection*{%s}")
|
|
("\\paragraph{%s}" . "\\paragraph*{%s}")
|
|
("\\subparagraph{%s}" . "\\subparagraph*{%s}"))
|
|
("tufte-book"
|
|
"\\documentclass{tufte-book}"
|
|
("\\section{%s}" . "\\section*{%s}")
|
|
("\\subsection{%s}" . "\\subsection*{%s}")
|
|
("\\subsubsection{%s}" . "\\subsubsection*{%s}")
|
|
("\\paragraph{%s}" . "\\paragraph*{%s}")
|
|
("\\subparagraph{%s}" . "\\subparagraph*{%s}"))
|
|
("tufte-book-chapters"
|
|
"\\documentclass{tufte-book}"
|
|
("\\chapter{%s}" . "\\chapter*{%s}")
|
|
("\\section{%s}" . "\\section*{%s}")
|
|
("\\subsection{%s}" . "\\subsection*{%s}")
|
|
("\\subsubsection{%s}" . "\\subsubsection*{%s}")
|
|
("\\paragraph{%s}" . "\\paragraph*{%s}")
|
|
("\\subparagraph{%s}" . "\\subparagraph*{%s}"))
|
|
("labbook"
|
|
"\\documentclass{labbook}"
|
|
("\\chapter{%s}" . "\\chapter*{%s}")
|
|
("\\section{%s}" . "\\section*{%s}")
|
|
("\\subsection{%s}" . "\\labday{%s}")
|
|
("\\subsubsection{%s}" . "\\experiment{%s}")
|
|
("\\paragraph{%s}" . "\\paragraph*{%s}")
|
|
("\\subparagraph{%s}" . "\\subparagraph*{%s}"))
|
|
("thermal-paper"
|
|
"\\documentclass{paper}
|
|
\\usepackage[paperwidth=52mm]{geometry}"
|
|
("\\section{%s}" . "\\section*{%s}")
|
|
("\\subsection{%s}" . "\\subsection*{%s}")
|
|
("\\subsubsection{%s}" . "\\subsubsection*{%s}")
|
|
("\\paragraph{%s}" . "\\paragraph*{%s}")
|
|
("\\subparagraph{%s}" . "\\subparagraph*{%s}")))))
|
|
#+END_SRC
|
|
**** DnD
|
|
This adds an additional LaTeX export option that outputs documents resembling a
|
|
Dungeons and Dragons manual.
|
|
|
|
#+begin_src emacs-lisp
|
|
(use-package! ox-dnd
|
|
:after ox)
|
|
#+end_src
|
|
*** Capture templates
|
|
Set up my capture templates for making new notes and journal entries.
|
|
|
|
#+begin_src emacs-lisp
|
|
(setq org-capture-templates
|
|
`(
|
|
;; Personal
|
|
("j" "Journal Entry" plain
|
|
(file+datetree "~/org/journal.org")
|
|
"%U\n\n%?" :empty-lines-before 1)
|
|
("t" "TODO" entry
|
|
(file+headline "~/Nextcloud/org/personal.org" "Unsorted")
|
|
"* TODO %^{Description}\n%?")
|
|
("n" "Note" entry
|
|
(file+headline "~/Nextcloud/org/personal.org" "Notes")
|
|
"* %^{Description}\n%U\n\n%?")
|
|
;; Org-Protocol
|
|
("b" "Bookmark" entry
|
|
(file+headline "~/org/bookmarks.org" "Unsorted")
|
|
"* %^{Title}\n\n Source: %u, %c\n\n %i")
|
|
("p" "Webpage" entry
|
|
(file "~/org/articles.org")
|
|
"* %a\n\n%U %?\n\n%:initial")
|
|
|
|
;; Email
|
|
;; https://martinralbrecht.wordpress.com/2016/05/30/handling-email-with-emacs/
|
|
("r" "respond to email (mu4e)"
|
|
entry (file+headline "~/org/todo.org" "Email")
|
|
"* REPLY to [[mailto:%:fromaddress][%:fromname]] on %a\nDEADLINE: %(org-insert-time-stamp (org-read-date nil t \"+1d\"))\n%U\n\n"
|
|
:immediate-finish t
|
|
:prepend t)
|
|
|
|
;; Work
|
|
("w" "Work")
|
|
("wt" "Work TODO" entry
|
|
(file+headline "~/Nextcloud/org/aweber.org" "Unsorted")
|
|
"* TODO %^{Description}\n%?")
|
|
("wl" "Log Work Task" entry
|
|
(file+datetree "~/org-aweber/worklog.org")
|
|
"* %^{Description} %^g\nAdded: %U\n\n%?"
|
|
:clock-in t
|
|
:clock-keep t)
|
|
("wL" "Log Work Task (no clock)" entry
|
|
(file+datetree "~/org-aweber/worklog.org")
|
|
"* %^{Description} %^g\nAdded: %U\n\n%?")
|
|
("wj" "Log work on JIRA issue" entry
|
|
(file+datetree "~/org-aweber/worklog.org")
|
|
,(concat
|
|
"* %?\n"
|
|
":PROPERTIES:\n"
|
|
":JIRA_ID: %^{JIRA_ID}\n"
|
|
":END:\n"
|
|
"Added: %U\n\n"
|
|
"[[jira:%\\1][%\\1]]")
|
|
:clock-in t
|
|
:clock-keep t)
|
|
("wr" "respond to email (mu4e)"
|
|
entry (file+headline "~/Nextcloud/org/aweber.org" "Unsorted")
|
|
"* REPLY to [[mailto:%:fromaddress][%:fromname]] on %a\nDEADLINE: %(org-insert-time-stamp (org-read-date nil t \"+1d\"))\n%U\n\n"
|
|
:immediate-finish t
|
|
:prepend t)))
|
|
#+end_src
|
|
*** Custom ID generation
|
|
Because I'm all kinds of crazy, I like the custom IDs of my work log entries to
|
|
be based on their headings.
|
|
|
|
#+begin_src emacs-lisp
|
|
(use-package! org-id
|
|
:after org
|
|
:config
|
|
|
|
;; https://writequit.org/articles/emacs-org-mode-generate-ids.html#automating-id-creation
|
|
(defun eos/org-custom-id-get (&optional pom create prefix)
|
|
"Get the CUSTOM_ID property of the entry at point-or-marker POM.
|
|
If POM is nil, refer to the entry at point. If the entry does
|
|
not have an CUSTOM_ID, the function returns nil. However, when
|
|
CREATE is non nil, create a CUSTOM_ID if none is present
|
|
already. PREFIX will be passed through to `org-id-new'. In any
|
|
case, the CUSTOM_ID of the entry is returned."
|
|
(interactive)
|
|
(org-with-point-at pom
|
|
(let ((id (org-entry-get nil "CUSTOM_ID")))
|
|
(cond
|
|
((and id (stringp id) (string-match "\\S-" id))
|
|
id)
|
|
(create
|
|
(setq id (org-id-new (concat prefix "h")))
|
|
(org-entry-put pom "CUSTOM_ID" id)
|
|
(org-id-add-location id (buffer-file-name (buffer-base-buffer)))
|
|
id)))))
|
|
|
|
(defun eos/org-add-ids-to-headlines-in-file ()
|
|
"Add CUSTOM_ID properties to all headlines in the current
|
|
file which do not already have one. Only adds ids if the
|
|
`auto-id' option is set to `t' in the file somewhere. ie,
|
|
,#+OPTIONS: auto-id:t"
|
|
(interactive)
|
|
(save-excursion
|
|
(widen)
|
|
(goto-char (point-min))
|
|
(when (re-search-forward "^#\\+OPTIONS:.*auto-id:t" (point-max) t)
|
|
(org-map-entries (lambda () (eos/org-id-get (point) 'create)))))
|
|
(save-excursion
|
|
(widen)
|
|
(goto-char (point-min))
|
|
(when (re-search-forward "^#\\+OPTIONS:.*auto-id:worklog" (point-max) t)
|
|
(let ((my/org-worklog-id-depth 2))
|
|
(org-map-entries (lambda () (my/org-worklog-id-get (point) 'create))))))
|
|
(save-excursion
|
|
(widen)
|
|
(goto-char (point-min))
|
|
(when (re-search-forward "^#\\+OPTIONS:.*auto-id:readable" (point-max) t)
|
|
(let ((my/org-worklog-id-depth 0))
|
|
(org-map-entries (lambda () (my/org-worklog-id-get (point) 'create)))))))
|
|
|
|
;; automatically add ids to saved org-mode headlines
|
|
(add-hook 'org-mode-hook
|
|
(lambda ()
|
|
(add-hook 'before-save-hook
|
|
(lambda ()
|
|
(when (and (eq major-mode 'org-mode)
|
|
(eq buffer-read-only nil))
|
|
(eos/org-add-ids-to-headlines-in-file))))))
|
|
|
|
(defun my/org-remove-all-ids ()
|
|
(interactive)
|
|
(save-excursion
|
|
(widen)
|
|
(goto-char (point-min))
|
|
(org-map-entries (lambda () (org-entry-delete (point) "CUSTOM_ID")))))
|
|
|
|
(defvar my/org-worklog-id-depth 2)
|
|
(defun my/org-worklog-id-new (&optional prefix)
|
|
(let ((path (or (-drop my/org-worklog-id-depth (org-get-outline-path t))
|
|
(last (org-get-outline-path t)))))
|
|
(mapconcat
|
|
(lambda (s)
|
|
(->> s
|
|
(s-downcase)
|
|
(s-replace-regexp "[^[:alnum:]]+" "-")))
|
|
path
|
|
"-")))
|
|
|
|
(defun my/org-worklog-id-get (&optional pom create prefix)
|
|
(interactive)
|
|
(org-with-point-at pom
|
|
(let ((id (org-entry-get nil "CUSTOM_ID")))
|
|
(cond
|
|
((and id (stringp id) (string-match "\\S-" id))
|
|
id)
|
|
(create
|
|
(setq id (my/org-worklog-id-new prefix))
|
|
(org-entry-put pom "CUSTOM_ID" id)
|
|
id))))))
|
|
|
|
#+end_src
|
|
*** Publish projects
|
|
Tell Emacs how to build the document collections I export to HTML.
|
|
|
|
#+begin_src emacs-lisp
|
|
(require 'org-attach)
|
|
|
|
(setq org-html-mathjax-options
|
|
'((path "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.2/MathJax.js?config=TeX-AMS-MML_HTMLorMML")))
|
|
|
|
(setq org-re-reveal-root "https://cdn.jsdelivr.net/reveal.js/3.0.0/")
|
|
|
|
(defun my/org-work-publish-to-html (plist filename pub-dir)
|
|
(message "Publishing %s" filename)
|
|
(cond ((string-match-p "slides.org$" filename)
|
|
(org-re-reveal-publish-to-reveal plist filename pub-dir))
|
|
(t (let ((org-html-head
|
|
(concat
|
|
;; Tufte
|
|
;; "<link rel=\"stylesheet\" href=\"" my/org-base-url "styles/tufte-css/tufte.css\"/>"
|
|
;; "<link rel=\"stylesheet\" href=\"" my/org-base-url "styles/tufte-css/latex.css\"/>"
|
|
|
|
;; Org-Spec
|
|
;; "<link href=\"https://fonts.googleapis.com/css?family=Roboto+Slab:400,700|Inconsolata:400,700\" rel=\"stylesheet\" type=\"text/css\" />"
|
|
;; "<link rel=\"stylesheet\" href=\"" my/org-base-url "styles/org-spec/style.css\"/>"
|
|
|
|
;; "<link rel=\"stylesheet\" type=\"text/css\" href=\"" my/org-base-url "css/info.css\" />"
|
|
|
|
;; ReadTheOrg
|
|
"<link rel=\"stylesheet\" type=\"text/css\" href=\"" my/org-base-url "styles/readtheorg/css/htmlize.css\"/>"
|
|
"<link rel=\"stylesheet\" type=\"text/css\" href=\"" my/org-base-url "styles/readtheorg/css/readtheorg.css\"/>"
|
|
"<link rel=\"stylesheet\" type=\"text/css\" href=\"" my/org-base-url "css/info.css\" />"
|
|
"<script src=\"https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js\"></script>"
|
|
"<script src=\"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js\"></script>"
|
|
"<script type=\"text/javascript\" src=\"" my/org-base-url "styles/lib/js/jquery.stickytableheaders.min.js\"></script>"
|
|
"<script type=\"text/javascript\" src=\"" my/org-base-url "styles/readtheorg/js/readtheorg.js\"></script>"
|
|
|
|
;; Bigblow
|
|
;; "<link rel=\"stylesheet\" type=\"text/css\" href=\"" my/org-base-url "styles/bigblow/css/htmlize.css\"/>"
|
|
;; "<link rel=\"stylesheet\" type=\"text/css\" href=\"" my/org-base-url "styles/bigblow/css/bigblow.css\"/>"
|
|
;; "<link rel=\"stylesheet\" type=\"text/css\" href=\"" my/org-base-url "styles/bigblow/css/hideshow.css\"/>"
|
|
;; "<script type=\"text/javascript\" src=\"" my/org-base-url "styles/bigblow/js/jquery-1.11.0.min.js\"></script>"
|
|
;; "<script type=\"text/javascript\" src=\"" my/org-base-url "styles/bigblow/js/jquery-ui-1.10.2.min.js\"></script>"
|
|
;; "<script type=\"text/javascript\" src=\"" my/org-base-url "styles/bigblow/js/jquery.localscroll-min.js\"></script>"
|
|
;; "<script type=\"text/javascript\" src=\"" my/org-base-url "styles/bigblow/js/jquery.scrollTo-1.4.3.1-min.js\"></script>"
|
|
;; "<script type=\"text/javascript\" src=\"" my/org-base-url "styles/bigblow/js/jquery.zclip.min.js\"></script>"
|
|
;; "<script type=\"text/javascript\" src=\"" my/org-base-url "styles/bigblow/js/bigblow.js\"></script>"
|
|
;; "<script type=\"text/javascript\" src=\"" my/org-base-url "styles/bigblow/js/hideshow.js\"></script>"
|
|
;; "<script type=\"text/javascript\" src=\"" my/org-base-url "styles/lib/js/jquery.stickytableheaders.min.js\"></script>"
|
|
)))
|
|
(save-excursion
|
|
(save-restriction
|
|
(org-html-publish-to-html plist filename pub-dir)))))))
|
|
|
|
;; (setq my/org-base-url (concat "/~" (getenv "USER") "/org/"))
|
|
(setq my/org-base-url "/")
|
|
(setq my/org-base-url "https://correlr.gitlab.aweber.io/org/")
|
|
|
|
(setq org-publish-project-alist
|
|
`(
|
|
;; ("work-common"
|
|
;; :base-directory "~/org/common"
|
|
;; :publishing-directory "~/Public/org"
|
|
;; :base-extension "css\\|gif\\|jpe?g\\|png\\|svg"
|
|
;; :recursive t
|
|
;; :publishing-function org-publish-attachment)
|
|
("work-themes"
|
|
:base-directory "~/.emacs.local.d/org-html-themes/styles"
|
|
:publishing-directory "~/Public/org/styles"
|
|
:base-extension "js\\|css\\|gif\\|jpe?g\\|png\\|svg\\|ogv"
|
|
:recursive t
|
|
:publishing-function org-publish-attachment)
|
|
("work-html"
|
|
:base-directory "~/org-aweber"
|
|
:base-extension "org"
|
|
;; :exclude "\\(^knowledge-transfer.org$\\|-archive.org$\\)"
|
|
:exclude "\\(^README.org$\\|^worklog\\|roam/.*\\)"
|
|
:publishing-directory "~/Public/org"
|
|
:publishing-function (my/org-work-publish-to-html
|
|
org-org-publish-to-org
|
|
org-babel-tangle-publish)
|
|
|
|
;; :htmlized-source t
|
|
;; :html-head "<link rel=\"stylesheet\" type=\"text/css\" href=\"http://thomasf.github.io/solarized-css/solarized-dark.min.css\" />"
|
|
;; :html-head-extra "<link rel=\"stylesheet\" type=\"text/css\" href=\"/~croush/org/css/org.css\" />"
|
|
;; :setup-file "~/.emacs.local.d/org-html-themes/setup/theme-readtheorg-local.setup"
|
|
:html-link-home ,my/org-base-url
|
|
:html-doctype "html5"
|
|
:html-html5-fancy t
|
|
:with-sub-superscript nil
|
|
:section-numbers nil
|
|
;; :infojs-opt "path:http://thomasf.github.io/solarized-css/org-info.min.js view:showall"
|
|
:auto-sitemap t
|
|
:sitemap-filename "index.org"
|
|
:sitemap-title "Correl Roush's Org Documents"
|
|
:sitemap-sort-folders last
|
|
:recursive t)
|
|
("work-roam-html"
|
|
:base-directory "~/org-aweber/roam"
|
|
:base-extension "org"
|
|
:publishing-directory "~/Public/org/roam"
|
|
:recursive t
|
|
:with-toc nil
|
|
:section-numbers nil
|
|
:auto-sitemap t
|
|
:sitemap-filename "index.org"
|
|
:sitemap-title "Correl Roush's Org Roam Notes"
|
|
:publishing-function org-html-publish-to-html
|
|
:html-head "<link rel=\"stylesheet\" href=\"https://gongzhitaao.org/orgcss/org.css\"/>")
|
|
("work-assets"
|
|
:base-directory "~/org-aweber"
|
|
:base-extension "css\\|gif\\|jpe?g\\|png\\|svg\\|pdf\\|ogv\\|py\\|html\\|ya?ml"
|
|
:include (".gitlab-ci.yml")
|
|
:publishing-directory "~/Public/org"
|
|
:publishing-function org-publish-attachment
|
|
:display-custom-times t
|
|
:recursive t)
|
|
("work-todo"
|
|
:base-directory "~/Nextcloud/org"
|
|
:exclude ".*"
|
|
:include ("aweber.org")
|
|
:html-head "<link rel=\"stylesheet\" href=\"styles/tufte-css/tufte.css\"/>"
|
|
:html-head-extra "<link rel=\"stylesheet\" href=\"styles/tufte-css/latex.css\"/>"
|
|
|
|
:publishing-directory "~/Public/org"
|
|
:publishing-function org-html-publish-to-tufte-html)
|
|
("work" :components ("work-html" "work-roam-html" "work-todo" "work-assets" "work-themes"))
|
|
|
|
("dotfiles-common"
|
|
:base-directory "~/dotfiles"
|
|
:publishing-directory "~/Public/dotfiles"
|
|
:base-extension "css\\|gif\\|jpe?g\\|png\\|svg"
|
|
:recursive t
|
|
:publishing-function org-publish-attachment)
|
|
("dotfiles-html"
|
|
:base-directory "~/dotfiles"
|
|
:base-extension "org"
|
|
:publishing-directory "~/Public/dotfiles"
|
|
:publishing-function (org-html-publish-to-html
|
|
org-babel-tangle-publish)
|
|
:htmlized-source t
|
|
:html-head "<link rel=\"stylesheet\" type=\"text/css\" href=\"http://thomasf.github.io/solarized-css/solarized-dark.min.css\" />"
|
|
:html-head-extra "<link rel=\"stylesheet\" type=\"text/css\" href=\"/~croush/org/css/org.css\" />"
|
|
:html-link-home "/~croush/dotfiles/"
|
|
:html-doctype "html5"
|
|
:html-html5-fancy t
|
|
:with-sub-superscript nil
|
|
:infojs-opt "path:http://thomasf.github.io/solarized-css/org-info.min.js view:showall"
|
|
:auto-sitemap t
|
|
:sitemap-filename "index.org"
|
|
:sitemap-title "Correl Roush's Dotfiles"
|
|
:sitemap-sort-folders last
|
|
:recursive t)
|
|
("dotfiles-assets"
|
|
:base-directory "~/dotfiles"
|
|
:base-extension "css\\|gif\\|jpe?g\\|png\\|svg"
|
|
:publishing-directory "~/Public/dotfiles"
|
|
:publishing-function org-publish-attachment
|
|
:recursive t)
|
|
("dotfiles" :components ("dotfiles-common" "dotfiles-html" "dotfiles-assets"))
|
|
|
|
("personal-themes"
|
|
:base-directory "~/.emacs.local.d/org-html-themes/styles"
|
|
:publishing-directory "~/Public/personal/styles"
|
|
:base-extension "js\\|css\\|gif\\|jpe?g\\|png\\|svg"
|
|
:recursive t
|
|
:publishing-function org-publish-attachment)
|
|
("personal-html"
|
|
:base-directory "~/org"
|
|
:base-extension "org"
|
|
:publishing-directory "~/Public/personal"
|
|
:recursive t
|
|
:with-toc t
|
|
:auto-sitemap t
|
|
:sitemap-title "Correl Roush's Org Files"
|
|
:sitemap-filename "index.org"
|
|
:publishing-function org-html-publish-to-tufte-html
|
|
:html-head ,(concat
|
|
;; Tufte
|
|
"<link rel=\"stylesheet\" href=\"" my/org-base-url "styles/tufte-css/tufte.css\"/>"
|
|
"<link rel=\"stylesheet\" href=\"" my/org-base-url "styles/tufte-css/latex.css\"/>"))
|
|
;; Org-Spec
|
|
;; "<link href=\"http://fonts.googleapis.com/css?family=Roboto+Slab:400,700|Inconsolata:400,700\" rel=\"stylesheet\" type=\"text/css\" />"
|
|
;; "<link href=\"http://demo.thi.ng/org-spec/css/style.css\" rel=\"stylesheet\" type=\"text/css\" />"
|
|
|
|
("personal-files"
|
|
:base-directory "~/org"
|
|
:base-extension "css\\|gif\\|jpe?g\\|png\\|svg"
|
|
:publishing-directory "~/Public/personal"
|
|
:recursive t
|
|
:publishing-function org-publish-attachment)
|
|
("personal-assets"
|
|
:base-directory "~/org"
|
|
:base-extension "css\\|gif\\|jpe?g\\|png\\|svg\\|pdf"
|
|
:publishing-directory "~/Public/personal"
|
|
:publishing-function org-publish-attachment
|
|
:recursive t)
|
|
("personal" :components ("personal-themes" "personal-html" "personal-files" "personal-assets"))
|
|
|
|
("journal"
|
|
:base-directory "~/org"
|
|
:exclude ".*"
|
|
:include ("journal.org")
|
|
:publishing-directory "~/journal"
|
|
:publishing-function (org-html-publish-to-html
|
|
org-latex-export-to-pdf))
|
|
|
|
("roam-html"
|
|
:base-directory "~/org/roam"
|
|
:base-extension "org"
|
|
:publishing-directory "~/Public/roam"
|
|
:recursive t
|
|
:with-toc nil
|
|
:section-numbers nil
|
|
:auto-sitemap nil
|
|
:publishing-function org-html-publish-to-html
|
|
:html-head "<link rel=\"stylesheet\" href=\"https://gongzhitaao.org/orgcss/org.css\"/>")
|
|
|
|
("roam-assets"
|
|
:base-directory "~/org/roam"
|
|
:base-extension "css\\|js\\|json\\|gif\\|jpe?g\\|png\\|svg\\|pdf"
|
|
:publishing-directory "~/Public/roam"
|
|
:publishing-function org-publish-attachment
|
|
:recursive t)
|
|
("roam" :components ("roam-html" "roam-assets"))
|
|
|
|
("sicp-html"
|
|
:base-directory "~/code/sicp"
|
|
:base-extension "org"
|
|
:publishing-directory "~/Public/sicp"
|
|
:publishing-function (org-html-publish-to-html
|
|
org-org-publish-to-org
|
|
org-babel-tangle-publish)
|
|
:htmlized-source t
|
|
:html-head "<link rel=\"stylesheet\" type=\"text/css\" href=\"http://thomasf.github.io/solarized-css/solarized-light.min.css\" />"
|
|
:html-link-home "/"
|
|
:html-doctype "html5"
|
|
:html-html5-fancy t
|
|
:with-sub-superscript nil
|
|
:auto-sitemap t
|
|
:sitemap-filename "index.org"
|
|
:sitemap-title "SICP Exercises and Notes"
|
|
:sitemap-sort-folders last
|
|
:recursive t)
|
|
("sicp-assets"
|
|
:base-directory "~/code/sicp"
|
|
:base-extension "css\\|gif\\|jpe?g\\|png\\|svg\\|scheme\\|pl"
|
|
:publishing-directory "~/Public/sicp"
|
|
:publishing-function org-publish-attachment
|
|
:recursive t)
|
|
("sicp" :components ("sicp-html" "sicp-assets"))))
|
|
|
|
|
|
|
|
;; Don't prompt for babel evaluation, ever.
|
|
(setq org-confirm-babel-evaluate nil)
|
|
|
|
(require 'ox-confluence)
|
|
(defun my/org-publish ()
|
|
(interactive)
|
|
(org-publish "work")
|
|
(let ((org-link-abbrev-alist (seq-concatenate 'list org-link-abbrev-alist
|
|
'(("jira" . "https://jira.aweber.io/browse/")
|
|
("gitlab" . "https://gitlab.aweber.io/")))))
|
|
(org-store-agenda-views))
|
|
(shell-command "org-publish"))
|
|
|
|
(bind-key "C-c o p" #'my/org-publish)
|
|
#+end_src
|
|
*** Enhanced Confluence export
|
|
Adds [[https://github.com/correl/ox-confluence-en][my own package]] that extends the built-in Confluence wiki markup exporter
|
|
with better formatting and macro support.
|
|
|
|
#+begin_src emacs-lisp
|
|
(use-package! ox-confluence-en
|
|
:after ox
|
|
:commands ox-confluence-en-export-as-confluence)
|
|
#+end_src
|
|
*** Reload images on source execution
|
|
Force images to redisplay after executing a source code block, so I can
|
|
immediately see the result of regenerating graphs and diagrams.
|
|
|
|
#+begin_src emacs-lisp
|
|
(defun my/redisplay-org-images ()
|
|
(when org-inline-image-overlays
|
|
(org-redisplay-inline-images)))
|
|
|
|
(add-hook 'org-babel-after-execute-hook
|
|
'my/redisplay-org-images)
|
|
#+end_src
|
|
*** Sticky headers
|
|
Keeps the current heading visible at the top of the Emacs window.
|
|
|
|
#+begin_src emacs-lisp
|
|
(use-package! org-sticky-header
|
|
:hook (org-mode . org-sticky-header-mode)
|
|
:config (setq org-sticky-header-full-path 'full))
|
|
#+end_src
|
|
*** Library of Babel
|
|
|
|
Load shared code snippets to be used in org documents.
|
|
|
|
#+begin_src emacs-lisp
|
|
(let ((org-dirs '("~/org" "~/org-aweber")))
|
|
(seq-map #'org-babel-lob-ingest
|
|
(seq-filter #'f-exists?
|
|
(seq-map (lambda (path) (f-join path "library-of-babel.org"))
|
|
org-dirs))))
|
|
#+end_src
|
|
*** Nicer looking timestamps
|
|
#+begin_src emacs-lisp
|
|
(setq org-time-stamp-custom-formats '("<%A, %B %d %Y>" . "<%A, %B %d %Y %H:%M>"))
|
|
|
|
(defun org-export-filter-timestamp-remove-brackets (timestamp backend info)
|
|
"removes relevant brackets from a timestamp"
|
|
(cond
|
|
((org-export-derived-backend-p backend 'latex)
|
|
(replace-regexp-in-string "[<>]\\|[][]" "" timestamp))
|
|
((org-export-derived-backend-p backend 'ascii)
|
|
(replace-regexp-in-string "[<>]\\|[][]" "" timestamp))
|
|
((org-export-derived-backend-p backend 'html)
|
|
(replace-regexp-in-string "&[lg]t;\\|[][]" "" timestamp))))
|
|
|
|
(after! ox
|
|
(add-to-list
|
|
'org-export-filter-timestamp-functions
|
|
'org-export-filter-timestamp-remove-brackets))
|
|
#+end_src
|
|
*** Tufte HTML
|
|
Gorgeous HTML exports.
|
|
|
|
#+begin_src emacs-lisp
|
|
(use-package! ox-tufte
|
|
:after ox)
|
|
#+end_src
|
|
*** Journal
|
|
#+begin_src emacs-lisp
|
|
(use-package org-journal
|
|
:if (f-dir? "~/org-aweber")
|
|
:custom
|
|
(org-journal-date-prefix "#+title: ")
|
|
(org-journal-file-format "%Y-%m-%d.org")
|
|
(org-journal-dir "~/org-aweber")
|
|
(org-journal-date-format "%A, %d %B %Y"))
|
|
#+end_src
|
|
*** Ref
|
|
Tools for linking and taking notes on books and papers.
|
|
|
|
#+begin_src emacs-lisp
|
|
(use-package! org-ref
|
|
:config
|
|
(setq reftex-default-bibliography my/bibliographies)
|
|
;; see org-ref for use of these variables
|
|
(setq org-ref-bibliography-notes "~/Documents/bibliography/notes.org"
|
|
org-ref-default-bibliography my/bibliographies
|
|
org-ref-pdf-directory "~/Documents/bibliography/bibtex-pdfs/"))
|
|
#+end_src
|
|
*** Roam
|
|
Powerful cross-linked note-taking.
|
|
|
|
https://orgroam.com
|
|
|
|
**** Capture templates
|
|
#+begin_src emacs-lisp
|
|
(setq org-roam-capture-templates
|
|
'(("d" "default" plain "%?" :target
|
|
(file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}
|
|
")
|
|
:unnarrowed t)))
|
|
#+end_src
|
|
|
|
**** Add backlinks to org-roam exports
|
|
#+begin_src emacs-lisp
|
|
(use-package! org-roam-export-backlinks
|
|
:commands org-roam-export-backlinks-preprocessor
|
|
:init
|
|
(add-to-list 'org-export-before-processing-hook
|
|
#'org-roam-export-backlinks-preprocessor))
|
|
#+end_src
|
|
**** Org Roam Bibtex
|
|
Make it easy to take notes on books and papers that I'm reading.
|
|
|
|
#+begin_src emacs-lisp
|
|
(use-package! org-roam-bibtex
|
|
:after org-roam
|
|
:hook (org-roam . org-roam-bibtex-mode)
|
|
:bind (:map org-mode-map
|
|
(("C-c n r b" . orb-note-actions))))
|
|
#+end_src
|
|
**** Org Roam UI
|
|
Provides a fun way to browse through a collection of notes.
|
|
|
|
#+begin_src emacs-lisp
|
|
(use-package! org-roam-ui
|
|
:after org-roam
|
|
:commands org-roam-ui-mode
|
|
:config
|
|
(setq org-roam-ui-sync-theme t
|
|
org-roam-ui-follow t
|
|
org-roam-ui-update-on-save t
|
|
org-roam-ui-open-on-start t))
|
|
#+end_src
|
|
**** Use writeroom in org-roam buffers
|
|
Makes for a much nicer note-taking experience.
|
|
|
|
#+begin_src emacs-lisp
|
|
(defun my/org-roam-writeroom ()
|
|
;; Use a buffer-local local variables hook to ensure the org-roam-directory is
|
|
;; set properly
|
|
(add-hook 'hack-local-variables-hook
|
|
(lambda ()
|
|
(when (and org-roam-directory
|
|
(f-ancestor-of?
|
|
(expand-file-name org-roam-directory)
|
|
(or (buffer-file-name) default-directory)))
|
|
(writeroom-mode t)))
|
|
nil t))
|
|
|
|
(add-hook! 'org-mode-hook #'my/org-roam-writeroom)
|
|
#+end_src
|
|
**** Provide seamless switching between org-roam slipboxes
|
|
When we visit a buffer in a different slip box (different =org-roam-directory=)
|
|
than we were visiting previously, ensure the cache is updated.
|
|
|
|
#+begin_src emacs-lisp
|
|
(defvar my/org-roam-directory-cache (list
|
|
(cons (expand-file-name org-roam-directory)
|
|
(expand-file-name org-roam-db-location))))
|
|
|
|
(after! savehist
|
|
(add-to-list 'savehist-additional-variables
|
|
'my/org-roam-directory-cache))
|
|
|
|
(defun my/org-roam-directory--lookup (path)
|
|
(alist-get path my/org-roam-directory-cache nil nil #'s-equals?))
|
|
|
|
(defun my/org-roam-directory--update ()
|
|
(setq my/org-roam-directory-cache
|
|
(cons (cons org-roam-directory org-roam-db-location)
|
|
(seq-filter
|
|
(lambda (x) (not (s-equals? org-roam-directory (car x))))
|
|
my/org-roam-directory-cache))))
|
|
|
|
(add-hook! 'org-roam-buffer-prepare-hook #'my/org-roam-directory--update)
|
|
|
|
(defun my/org-roam-find-in-directory ()
|
|
(interactive)
|
|
(let* ((org-roam-directory (completing-read "Roam Directory"
|
|
(mapcar #'car my/org-roam-directory-cache)))
|
|
(org-roam-db-location (my/org-roam-directory--lookup
|
|
org-roam-directory)))
|
|
(org-roam-find-file)))
|
|
|
|
(map! :leader
|
|
(:prefix-map ("n" . "notes")
|
|
(:prefix ("r" . "roam")
|
|
:desc "Find file in slipbox" "F" #'my/org-roam-find-in-directory)))
|
|
#+end_src
|
|
|
|
When setting up additional slipboxes, be sure to set both =org-roam-directory=
|
|
/and/ =org-roam-db-location=. An example =.dir-locals.el=:
|
|
|
|
#+begin_example
|
|
((nil . ((eval . (setq-local org-roam-directory (expand-file-name "./")
|
|
org-roam-db-location (expand-file-name "./org-roam.db"))))))
|
|
#+end_example
|
|
*** Sidebar
|
|
Display a sidebar with file-local todos and scheduling.
|
|
|
|
#+begin_src emacs-lisp
|
|
(use-package! org-sidebar
|
|
:bind (:map org-mode-map
|
|
(("C-c l v s" . org-sidebar-toggle)
|
|
("C-c l v S" . org-sidebar-tree-toggle)))
|
|
:commands (org-sidebar
|
|
org-sidebar-toggle
|
|
org-sidebar-tree
|
|
org-sidebar-tree-toggle))
|
|
#+end_src
|
|
*** Transclusion
|
|
Show linked org document sections inline.
|
|
|
|
#+begin_src emacs-lisp
|
|
(use-package! org-transclusion
|
|
:after org
|
|
:init
|
|
(map!
|
|
:map global-map "<f12>" #'org-transclusion-add
|
|
:leader
|
|
:prefix "n"
|
|
:desc "Org Transclusion Mode" "t" #'org-transclusion-mode))
|
|
#+end_src
|
|
*** Ditaa
|
|
Download and use a recent version of [[https://github.com/stathissideris/ditaa][ditaa]] for rendering ASCII diagrams.
|
|
|
|
#+begin_src emacs-lisp
|
|
(after! ob-ditaa
|
|
(let ((jar-url "https://github.com/stathissideris/ditaa/releases/download/v0.11.0/ditaa-0.11.0-standalone.jar")
|
|
(jar-path (concat doom-etc-dir "ditaa.jar")))
|
|
(unless (f-exists? jar-path)
|
|
(url-copy-file jar-url jar-path))
|
|
(setq org-ditaa-jar-path jar-path
|
|
org-ditaa-eps-jar-path jar-path)))
|
|
#+end_src
|
|
** ReStructuredText
|
|
#+begin_src emacs-lisp
|
|
(use-package! polymode
|
|
:defer t)
|
|
|
|
(use-package! poly-rst
|
|
:mode ("\\.rst\\'" . poly-rst-mode))
|
|
#+end_src
|
|
** Unfill
|
|
Does the opposite of =fill (M-q)=, removing line breaks from a paragraph or
|
|
region.
|
|
|
|
#+begin_src emacs-lisp
|
|
(use-package! unfill
|
|
:commands (unfill-paragraph
|
|
unfill-region)
|
|
:bind ("M-Q" . unfill-paragraph))
|
|
#+end_src
|
|
* Reading
|
|
** Epub reader
|
|
A major mode for reading and navigating =.epub= files.
|
|
|
|
#+begin_src emacs-lisp
|
|
(use-package! nov
|
|
:mode ("\\.epub\\'" . nov-mode)
|
|
:config
|
|
(setq nov-save-place-file (concat doom-cache-dir "nov-places")))
|
|
#+end_src
|
|
** Kanji Mode
|
|
Minor mode for displaying Japanese characters' stroke orders.
|
|
|
|
#+begin_src emacs-lisp
|
|
(use-package! kanji-mode
|
|
:commands kanji-mode)
|
|
#+end_src
|
|
** Kanji Glasses Mode
|
|
Study kanji by overlaying hiragana readings.
|
|
|
|
#+begin_src emacs-lisp
|
|
(use-package! kanji-glasses-mode
|
|
:commands kanji-glasses-mode)
|
|
#+end_src
|
|
* Coding
|
|
** Arduino
|
|
#+begin_src emacs-lisp
|
|
(use-package! arduino-mode
|
|
:mode "\\.ino\\'")
|
|
|
|
(use-package! arduino-cli-mode
|
|
:hook arduino-mode
|
|
:custom
|
|
(arduino-cli-warnings 'all)
|
|
(arduino-cli-verify t))
|
|
#+end_src
|
|
** Erlang
|
|
*** Kerl
|
|
Select the active erlang installation managed with [[https://github.com/kerl/kerl][kerl]].
|
|
|
|
#+begin_src emacs-lisp
|
|
(use-package! kerl
|
|
:commands (kerl-use))
|
|
#+end_src
|
|
** Lisp
|
|
*** Paredit
|
|
Adds shortcuts to edit the structure of lisp code.
|
|
|
|
#+begin_src emacs-lisp
|
|
(use-package! paredit
|
|
:hook ((emacs-lisp-mode . enable-paredit-mode)))
|
|
#+end_src
|
|
** OpenSCAD
|
|
Mode for editing OpenSCAD 3D modeling files. Files can be opened externally for
|
|
live-updated previews within OpenSCAD itself using =C-c C-o=.
|
|
|
|
#+begin_src emacs-lisp
|
|
(use-package! scad-mode
|
|
:mode "\\.scad\\'")
|
|
#+end_src
|
|
* Applications
|
|
** Email
|
|
Configure MU4E to read email synced from my personal and work accounts.
|
|
|
|
#+begin_src emacs-lisp
|
|
(use-package! mu4e
|
|
:bind (("<f9>" . mu4e))
|
|
:config
|
|
|
|
(require 'f)
|
|
|
|
(setq mu4e-maildir "~/Mail")
|
|
|
|
(setq user-full-name "Correl Roush")
|
|
(setq mu4e-contexts
|
|
(list (make-mu4e-context
|
|
:name "work"
|
|
:vars `((user-mail-address . "correlr@aweber.com")
|
|
(mu4e-drafts-folder . "/Work/[Gmail]/Drafts")
|
|
(mu4e-sent-folder . "/Work/[Gmail]/Sent Mail")
|
|
(mu4e-trash-folder . "/Work/[Gmail]/Trash")
|
|
(mu4e-maildir-shortcuts . (("/Work/INBOX" . ?i)
|
|
("/Work/[Gmail]/All Mail" . ?a)
|
|
("/Work/[Gmail]/Starred" . ?S)
|
|
("/Work/[Gmail]/Sent Mail" . ?s)
|
|
("/Work/[Gmail]/Trash" . ?t)))
|
|
(mu4e-compose-signature . ,(with-temp-buffer
|
|
(insert-file-contents "~/.signature-aweber")
|
|
(buffer-string)))
|
|
(smtpmail-smtp-user . "correlr@aweber.com")
|
|
(smtpmail-smtp-server . "smtp.gmail.com")
|
|
(smtpmail-smtp-service . 465)
|
|
(smtpmail-stream-type . ssl)))))
|
|
(when (f-exists?
|
|
(f-join mu4e-maildir "Personal"))
|
|
(add-to-list
|
|
'mu4e-contexts
|
|
(make-mu4e-context
|
|
:name "personal"
|
|
:vars `((user-mail-address . "correl@gmail.com")
|
|
(mu4e-drafts-folder . "/Personal/[Gmail]/Drafts")
|
|
(mu4e-sent-folder . "/Personal/[Gmail]/Sent Mail")
|
|
(mu4e-trash-folder . "/Personal/[Gmail]/Trash")
|
|
(mu4e-maildir-shortcuts . (("/Personal/INBOX" . ?i)
|
|
("/Personal/[Gmail]/All Mail" . ?a)
|
|
("/Personal/[Gmail]/Starred" . ?S)
|
|
("/Personal/[Gmail]/Sent Mail" . ?s)
|
|
("/Personal/[Gmail]/Trash" . ?t)))
|
|
(mu4e-compose-signature . ,(with-temp-buffer
|
|
(insert-file-contents "~/.signature")
|
|
(buffer-string)))
|
|
(smtpmail-smtp-user . "correl@gmail.com")
|
|
(smtpmail-smtp-server . "smtp.gmail.com")
|
|
(smtpmail-smtp-service . 465)
|
|
(smtpmail-stream-type . ssl)))))
|
|
(setq mu4e-context-policy 'pick-first)
|
|
(setq mu4e-compose-context-policy 'ask)
|
|
(setq mu4e-compose-dont-reply-to-self t)
|
|
(setq mu4e-index-lazy-check nil)
|
|
(setq mu4e-headers-include-related nil)
|
|
(setq mu4e-headers-skip-duplicates t)
|
|
(setq mu4e-user-mail-address-list '("correlr@aweber.com"
|
|
"correl@gmail.com")))
|
|
#+end_src
|
|
|
|
Prefer sending HTML-formatted messages with plain text as a fallback option
|
|
(alternative formats should be specified in increasing level of preference per
|
|
[[https://www.w3.org/Protocols/rfc1341/7_2_Multipart.html][RFC-1341]]).
|
|
|
|
#+begin_src emacs-lisp
|
|
(use-package! org-msg
|
|
:after mu4e
|
|
:config
|
|
(setq org-msg-default-alternatives '(text html)
|
|
org-msg-options "html-postamble:nil toc:nil author:nil email:nil ^:nil"))
|
|
#+end_src
|
|
** Chat
|
|
*** Circe
|
|
#+begin_src emacs-lisp
|
|
(after! circe
|
|
(set-irc-server!
|
|
"liberachat"
|
|
`(:tls nil
|
|
:host "znc.phoenixinquis.is-a-geek.org"
|
|
:port 8667
|
|
:nick "correl"
|
|
:user "correl/liberachat"
|
|
:pass (lambda (&rest _) (+pass-get-secret "Social/znc.phoenixinquis.is-a-geek.org/correl"))))
|
|
(set-irc-server!
|
|
"twitch"
|
|
`(:tls nil
|
|
:host "znc.phoenixinquis.is-a-geek.org"
|
|
:port 8667
|
|
:nick "correl"
|
|
:user "correl/twitch"
|
|
:pass (lambda (&rest _) (+pass-get-secret "Social/znc.phoenixinquis.is-a-geek.org/correl")))))
|
|
#+end_src
|
|
** Music
|
|
Configure EMMS for playing music files on my computer.
|
|
|
|
#+begin_src emacs-lisp
|
|
(use-package! emms
|
|
:commands (emms
|
|
emms-play-file
|
|
emms-play-directory
|
|
emms-smart-browse)
|
|
:config
|
|
(let ((emms-player-base-format-list
|
|
;; Add some VGM formats to the list for VLC to play
|
|
(append emms-player-base-format-list '("nsf" "spc" "gym"))))
|
|
(require 'emms-player-vlc))
|
|
(require 'emms-setup)
|
|
(emms-all)
|
|
(setq emms-player-list '(emms-player-vlc))
|
|
;; Use the installed VLC app if we're in OSX
|
|
(if (f-exists? "/Applications/VLC.app/Contents/MacOS/VLC")
|
|
(setq emms-player-vlc-command-name
|
|
"/Applications/VLC.app/Contents/MacOS/VLC")))
|
|
|
|
(map! :leader
|
|
(:prefix-map ("x" . "EMMS")
|
|
:desc "Play file" "f" #'emms-play-file
|
|
:desc "Play directory" "d" #'emms-play-directory
|
|
:desc "Smart Browser" "b" #'emms-smart-browse))
|
|
#+end_src
|
|
** News Aggregation
|
|
Read blogs and articles from the RSS feeds I follow.
|
|
|
|
#+begin_src emacs-lisp
|
|
(use-package! elfeed
|
|
:commands (elfeed my/elfeed my/elfeed-emacs my/elfeed-blogs)
|
|
:bind
|
|
(("<f2>" . elfeed)
|
|
("C-c n n" . my/elfeed)
|
|
("C-c n a" . my/elfeed-all)
|
|
("C-c n e" . my/elfeed-emacs)
|
|
("C-c n b" . my/elfeed-blogs))
|
|
:init
|
|
(global-set-key [f2] 'elfeed)
|
|
|
|
:config
|
|
(use-package! elfeed-org
|
|
:config (progn (elfeed-org)
|
|
(setq rmh-elfeed-org-files '("~/org/elfeed.org"))))
|
|
|
|
(defun my/elfeed-with-filters (filters)
|
|
(elfeed)
|
|
(setq elfeed-search-filter
|
|
(if (listp filters) (mapconcat #'identity filters " ")
|
|
filters))
|
|
(elfeed-search-update :force))
|
|
|
|
(defun my/elfeed ()
|
|
(interactive)
|
|
(my/elfeed-with-filters "@6-months-ago +unread"))
|
|
|
|
(defun my/elfeed-all ()
|
|
(interactive)
|
|
(my/elfeed-with-filters "@6-months-ago"))
|
|
|
|
(defun my/elfeed-emacs ()
|
|
(interactive)
|
|
(my/elfeed-with-filters "@6-months-ago +emacs +unread"))
|
|
|
|
(defun my/elfeed-blogs ()
|
|
(interactive)
|
|
(my/elfeed-with-filters "@6-months-ago +unread +blog"))
|
|
|
|
(add-hook! 'elfeed-show-mode-hook #'mixed-pitch-mode))
|
|
#+end_src
|
|
** Kubernetes
|
|
Manage a Kubernetes cluster and set up remote shell/file access via TRAMP.
|
|
|
|
#+begin_src emacs-lisp
|
|
(use-package! kubernetes
|
|
:commands (kubernetes-overview)
|
|
:config)
|
|
|
|
(set-popup-rule! "^\\*kubernetes" :ignore t)
|
|
|
|
(use-package! kubernetes-tramp
|
|
:commands (eshell find-file)
|
|
:config
|
|
(setq tramp-remote-shell-executable "sh"))
|
|
#+end_src
|
|
** Twitter
|
|
It's Twitter, in Emacs.
|
|
|
|
#+begin_src emacs-lisp
|
|
(define-key! twittering-mode-map
|
|
"f" #'twittering-favorite
|
|
"F" #'twittering-unfavorite)
|
|
#+end_src
|
|
** Project Management
|
|
*** Projectile
|
|
Pre-load Projectile with projects in my usual code directories.
|
|
|
|
#+begin_src emacs-lisp
|
|
(after! projectile
|
|
(require 'dash)
|
|
(require 'f)
|
|
|
|
(setq projectile-switch-project-action #'magit-status)
|
|
(let ((project-directories (-filter #'f-directory?
|
|
'("~/code"
|
|
"~/git"))))
|
|
(-map
|
|
(lambda (directory)
|
|
(-map (lambda (project)
|
|
(-> (concat project "/") ;; Projectile likes trailing slashes
|
|
(projectile-add-known-project)))
|
|
(-filter (lambda (f) (and (not (s-ends-with? "." f))
|
|
(f-directory? f)))
|
|
(-map (lambda (f) (concat directory "/" f))
|
|
(directory-files directory)))))
|
|
project-directories))
|
|
|
|
(projectile-cleanup-known-projects))
|
|
#+end_src
|
|
*** Jira
|
|
Add some commands for interacting with Jira within org documents.
|
|
|
|
#+begin_src emacs-lisp
|
|
(after! org
|
|
(use-package jira-api
|
|
:config (setq jira-api-host "jira.aweber.io"
|
|
jira-api-user "correlr"))
|
|
|
|
(defun my/org-clock-last-time-in-seconds ()
|
|
(save-excursion
|
|
(let ((end (save-excursion (org-end-of-subtree))))
|
|
(when (re-search-forward (concat org-clock-string
|
|
".*\\(\\[[^]]+\\]\\)--\\(\\[[^]]+\\]\\)")
|
|
end t)
|
|
(let* ((start (match-string 1))
|
|
(end (match-string 2)))
|
|
(floor (- (org-time-string-to-seconds end)
|
|
(org-time-string-to-seconds start))))))))
|
|
|
|
(defun my/org-jira-add-worklog-latest ()
|
|
(interactive)
|
|
(let ((jira-id (org-entry-get (point) "JIRA_ID"))
|
|
(seconds (my/org-clock-last-time-in-seconds)))
|
|
(when (and jira-id seconds)
|
|
(jira-api-log-work jira-id seconds)
|
|
(message
|
|
(format "Logged %d minutes to %s on JIRA"
|
|
(/ seconds 60)
|
|
jira-id)))))
|
|
|
|
(defun my/org-jira-add-worklog-total ()
|
|
(interactive)
|
|
(let ((jira-id (org-entry-get (point) "JIRA_ID"))
|
|
(seconds (* 60 (org-clock-sum-current-item))))
|
|
(when (and jira-id seconds)
|
|
(jira-api-log-work jira-id seconds)
|
|
(message
|
|
(format "Logged %d minutes to %s on JIRA"
|
|
(/ seconds 60)
|
|
jira-id)))))
|
|
|
|
(defun my/org-clock-add-jira-worklog-last ()
|
|
"Add a work log entry to a JIRA.
|
|
To log work to JIRA, set a property named JIRA_ID on the entry to be
|
|
logged to a JIRA issue ID."
|
|
(interactive)
|
|
(save-excursion
|
|
(save-window-excursion
|
|
(org-clock-goto)
|
|
(my/org-jira-add-worklog-latest))))
|
|
|
|
(defun my/org-jira-browse ()
|
|
(interactive)
|
|
(-if-let (jira-id (org-entry-get (point) "JIRA_ID"))
|
|
(let ((protocol (if jira-api-use-ssl "https" "http")))
|
|
(browse-url
|
|
(concat
|
|
protocol "://" jira-api-host "/browse/" jira-id)))))
|
|
|
|
(defun my/org-jira-list ()
|
|
(interactive)
|
|
(let ((buffer (generate-new-buffer "*org-jira*")))
|
|
(switch-to-buffer buffer)
|
|
(org-mode)
|
|
(insert "ohai")
|
|
(setq-local buffer-read-only t)
|
|
(display-buffer buffer)))
|
|
|
|
;; (add-hook 'org-clock-out-hook 'my/org-clock-add-jira-worklog-last)
|
|
|
|
(map! :map org-mode-map
|
|
"C-c j t" #'my/org-jira-add-worklog-total
|
|
"C-c j l" #'my/org-jira-add-worklog-latest
|
|
"C-c j b" #'my/org-jira-browse
|
|
"C-c j c" #'jira-api-create-issue-from-heading
|
|
"C-c j u" #'jira-api-update-issue-from-heading))
|
|
#+end_src
|
|
** Source Control
|
|
#+begin_src emacs-lisp
|
|
(after! forge
|
|
(add-to-list
|
|
'forge-alist
|
|
'("gitlab.aweber.io" "gitlab.aweber.io/api/v4" "gitlab.aweber.io" forge-gitlab-repository)))
|
|
#+end_src
|
|
** Eshell
|
|
*** Change directory in the context of a remote host
|
|
Add an =lcd= command that functions similarly to =cd=, but is scoped to the
|
|
remote host being accessed. Basically means I can use =lcd /= and other absolute
|
|
paths and not worry about being bounced back to my local filesystem.
|
|
|
|
#+begin_src emacs-lisp
|
|
(defun eshell/lcd (&optional directory)
|
|
(interactive)
|
|
(if (file-remote-p default-directory)
|
|
(with-parsed-tramp-file-name default-directory nil
|
|
(eshell/cd (tramp-make-tramp-file-name
|
|
(tramp-file-name-method v)
|
|
(tramp-file-name-user v)
|
|
(tramp-file-name-domain v)
|
|
(tramp-file-name-host v)
|
|
(tramp-file-name-port v)
|
|
(or directory "")
|
|
(tramp-file-name-hop v))))
|
|
(eshell/cd directory)))
|
|
#+end_src
|
|
*** Disable company autocompletion on remote hosts
|
|
#+begin_src emacs-lisp
|
|
(defun my/toggle-shell-autocomplete ()
|
|
(when (fboundp 'company-mode)
|
|
(company-mode (if (file-remote-p default-directory) -1 1))))
|
|
|
|
(add-hook! 'eshell-directory-change-hook #'my/toggle-shell-autocomplete)
|
|
#+end_src
|
|
** Background Processes
|
|
Manage background services
|
|
#+begin_src emacs-lisp
|
|
(use-package! prodigy
|
|
:defer 2
|
|
:config
|
|
|
|
(global-set-key (kbd "<f7>") 'prodigy)
|
|
|
|
(prodigy-define-tag
|
|
:name 'work)
|
|
(prodigy-define-tag
|
|
:name 'personal)
|
|
|
|
;; https://martinralbrecht.wordpress.com/2016/05/30/handling-email-with-emacs/
|
|
(when (executable-find "imapnotify")
|
|
(prodigy-define-tag
|
|
:name 'email
|
|
:ready-message "Checking Email using IMAP IDLE. Ctrl-C to shutdown.")
|
|
(prodigy-define-service
|
|
:name "imapnotify-work"
|
|
:command "imapnotify"
|
|
:args (list "-c" (expand-file-name "~/.config/imap_inotify/work.js"))
|
|
:tags '(email work autostart)
|
|
:kill-signal 'sigkill)
|
|
(unless (string-equal "croush" (user-login-name))
|
|
(prodigy-define-service
|
|
:name "imapnotify-personal"
|
|
:command "imapnotify"
|
|
:args (list "-c" (expand-file-name "~/.config/imap_inotify/personal.js"))
|
|
:tags '(email personal autostart)
|
|
:kill-signal 'sigkill)))
|
|
(when (f-exists? (expand-file-name "~/code/elm-dashboard"))
|
|
(prodigy-define-service
|
|
:name "elm-dashboard"
|
|
:command "python"
|
|
:args '("-m" "SimpleHTTPServer" "3000")
|
|
:cwd (expand-file-name "~/code/elm-dashboard")
|
|
:tags '(personal elm)
|
|
:stop-signal 'sigkill
|
|
:kill-process-buffer-on-stop t))
|
|
(when (f-exists? (expand-file-name "~/git/www"))
|
|
(prodigy-define-service
|
|
:name "AWeber WWW"
|
|
:command "npm"
|
|
:args '("start")
|
|
:cwd (expand-file-name "~/git/www")
|
|
:tags '(work)))
|
|
(when (f-exists? (expand-file-name "~/Public/org"))
|
|
(prodigy-define-service
|
|
:name "Org Documents"
|
|
:command "python"
|
|
:args '("-m" "http.server" "3001")
|
|
:cwd (expand-file-name "~/Public/org")
|
|
:tags '(work autostart)
|
|
:kill-signal 'sigkill))
|
|
(when (f-exists? (expand-file-name "~/Public/roam"))
|
|
(prodigy-define-service
|
|
:name "Org Roam Documents"
|
|
:command "python"
|
|
:args '("-m" "http.server" "3002")
|
|
:cwd (expand-file-name "~/Public/roam")
|
|
:tags '(personal autostart)
|
|
:kill-signal 'sigkill))
|
|
(mapcar
|
|
#'prodigy-start-service
|
|
(-concat (prodigy-services-tagged-with 'autostart))))
|
|
#+end_src
|
|
** Screen Sharing
|
|
*** Showing keypresses
|
|
#+begin_src emacs-lisp
|
|
(use-package! keypression
|
|
:commands (keypression-mode)
|
|
:bind (("C-c t k" . keypression-mode))
|
|
:config
|
|
(setq keypression-fade-out-delay 2.0
|
|
keypression-cast-command-name t
|
|
keypression-combine-same-keystrokes t
|
|
keypression-combine-format "%s (%d times)"
|
|
keypression-y-offset 100
|
|
keypression-font-face-attribute '(:height 400 :weight bold)))
|
|
#+end_src
|
|
** UUID Generation
|
|
#+begin_src emacs-lisp
|
|
(use-package! uuidgen
|
|
:commands (uuidgen))
|
|
#+end_src
|
|
** Wordle
|
|
#+begin_src emacs-lisp
|
|
(use-package! wordle
|
|
:commands (wordel wordel-marathon))
|
|
#+end_src
|
|
* Operating Systems
|
|
** Linux
|
|
*** EXWM
|
|
**** Set Emacs + EXWM as the default X window manager
|
|
|
|
#+begin_src sh :tangle ~/.dmrc
|
|
[Desktop]
|
|
session=~/.doom.d/start-exwm.sh
|
|
#+end_src
|
|
|
|
#+begin_src sh :tangle start-exwm.sh :shebang #!/bin/sh
|
|
emacs -mm -l ~/.doom.d/exwm.el
|
|
#+end_src
|
|
**** Configure EXWM
|
|
- Sets the desktop background
|
|
- Starts a bar/system tray and various applets
|
|
- Sets up workspaces
|
|
- Names X window buffers based on which application is running
|
|
#+begin_src emacs-lisp :tangle exwm.el
|
|
(defun my/exwm-update-class ()
|
|
(exwm-workspace-rename-buffer exwm-class-name))
|
|
(defun my/run-in-background (command)
|
|
(let ((command-parts (split-string command "[ ]+")))
|
|
(apply #'call-process `(,(car command-parts) nil 0 nil ,@(cdr command-parts)))))
|
|
(defun my/set-desktop-background ()
|
|
(interactive)
|
|
(start-process-shell-command "feh" nil "feh --bg-scale ~/Pictures/Wallpapers/1520742811045.png"))
|
|
(defun my/exwm-init-hook ()
|
|
;; Start tint2 bar
|
|
(my/run-in-background "tint2")
|
|
;; Start system tray applets
|
|
(my/run-in-background "nm-applet")
|
|
(my/run-in-background "pasystray")
|
|
(my/run-in-background "blueman-applet")
|
|
(my/run-in-background "nextcloud --background")
|
|
(my/run-in-background "compton"))
|
|
(use-package! exwm
|
|
:config
|
|
(setq exwm-input-global-keys
|
|
`(([?\s-r] . exwm-reset)
|
|
([?\s-w] . exwm-workspace-switch)
|
|
,@(mapcar (lambda (i)
|
|
`(,(kbd (format "s-%d" i)) .
|
|
(lambda ()
|
|
(interactive)
|
|
(exwm-workspace-switch-create ,(- i 1)))))
|
|
(number-sequence 1 9))
|
|
([?\s-&] . (lambda (command)
|
|
(interactive (list (read-shell-command "$ ")))
|
|
(start-process-shell-command command nil command)))))
|
|
(setq exwm-workspace-number 4)
|
|
(exwm-input-set-key (kbd "s-SPC") #'counsel-linux-app)
|
|
(add-hook! 'exwm-update-class-hook #'my/exwm-update-class)
|
|
(add-hook! 'exwm-init-hook #'my/exwm-init-hook)
|
|
(my/set-desktop-background)
|
|
(exwm-enable))
|
|
(use-package! exwm-config
|
|
:after exwm)
|
|
(use-package! desktop-environment
|
|
:after exwm
|
|
:config
|
|
(desktop-environment-mode))
|
|
#+end_src
|
|
***** Application launcher
|
|
Use counsel as an application launcher. Scans for =.desktop= files in all the
|
|
usual places.
|
|
#+begin_src emacs-lisp
|
|
(use-package! counsel
|
|
:custom (counsel-linux-app-format-function #'counsel-linux-app-format-function-name-only)
|
|
:config (counsel-mode 1))
|
|
#+end_src
|
|
** OSX
|
|
*** Editing binary-compressed plist files
|
|
From https://www.emacswiki.org/emacs/MacOSXPlist#toc1
|
|
#+begin_src emacs-lisp
|
|
;; Allow editing of binary .plist files.
|
|
(add-to-list 'jka-compr-compression-info-list
|
|
["\\.plist$"
|
|
"converting text XML to binary plist"
|
|
"plutil"
|
|
("-convert" "binary1" "-o" "-" "-")
|
|
"converting binary plist to text XML"
|
|
"plutil"
|
|
("-convert" "xml1" "-o" "-" "-")
|
|
nil nil "bplist"])
|
|
|
|
;;It is necessary to perform an update!
|
|
(jka-compr-update)
|
|
#+end_src
|
|
* Miscellaneous Nonsense
|
|
** BRING ON THE ...
|
|
A silly interactive method for generating horizontal and vertical text.
|
|
|
|
#+CAPTION: M-x bring-on-the RET cats RET
|
|
#+begin_example
|
|
B R I N G O N T H E C A T S
|
|
R
|
|
I
|
|
N
|
|
G
|
|
|
|
O
|
|
N
|
|
|
|
T
|
|
H
|
|
E
|
|
|
|
C
|
|
A
|
|
T
|
|
S
|
|
#+end_example
|
|
|
|
#+begin_src emacs-lisp
|
|
(defun bring-on-the (thing)
|
|
(interactive "sBring on the: ")
|
|
(let ((upthing (seq-into (s-upcase (s-concat "bring on the " thing)) 'list)))
|
|
(insert
|
|
(s-concat
|
|
(seq-into
|
|
(-interleave upthing (-repeat (length upthing) 32))
|
|
'string)
|
|
"\n"
|
|
(seq-into
|
|
(-interleave (rest upthing) (-repeat (1- (length upthing)) ?\n))
|
|
'string)))))
|
|
#+end_src
|
|
** OwO Mode
|
|
Make reading an open buffer an exercise in insanity.
|
|
|
|
#+begin_src emacs-lisp
|
|
(use-package! owo-mode
|
|
:commands owo-mode)
|
|
#+end_src
|
|
** Elcord
|
|
Emits rich presence to Discord.
|
|
|
|
#+begin_src emacs-lisp
|
|
(use-package! elcord
|
|
:config
|
|
(setq elcord-display-buffer-details nil
|
|
elcord-quiet t
|
|
elcord-editor-icon "emacs_material_icon"
|
|
elcord-use-major-mode-as-main-icon t)
|
|
(elcord-mode t))
|
|
#+end_src
|