#+auto_tangle: t
#+OPTIONS: html-style:nil
* About This Tangle
** Customize This Tangle
Set these variable src blocks before tangling. When these are set,
simply type =C-c C-v t= to build your emacs config.
Set this to configure [[Configuring offlineimap][offlineimap]] correctly. It should be your email
password.
#+name: emailpw
#+begin_src conf
PUTSOMETHINGHERE
#+end_src
** Tags used in this file
- =prereq= indicates that this involves installing something on the
underlying system, and is not part of the tangle
- =disabled= indicates that the name of the code block under this
heading has been disabled. I perform this disabling by commenting
out the name of the block so that the tangle operation does
nothing when encountering it. Some blocks are a pain to run
everytime I want to tangle this file, so by marking them as
disabled I can easily see the blocks that might need to be
enabled on a fresh emacs install.
So, to use this file for the very first time you must
1) run the code tagged prereq, then
2) fill in the [[*Customize This Tangle][customize]] section, above, then
3) enable the disabled sections (by uncommenting the code blocks they contain)
4) then run the tangle.
* init.el
This section generates the init.el file in the .emacs.d
directory. Emacs reads this file on startup.
Because init.el is generated afresh whenever =org-babel-tangle= is
called, and because the default behavior of emacs is to
programmatically place customizations at the end of the init.el
file, it is prudent to set a =custom-file= location explicitly.
After setting custom file, emacs is configured. Because many other
configuration options depend on properly configured packages, the
packages are setup first. After that, the order of the setup
operations is more or less insignificant.
#+begin_src elisp :tangle ~/.emacs.d/init.el :noweb no-export :results none
;;;; init.el
;;;; DO NOT EDIT: This file has been generated by org-babel-tangle
;;;; from a source file called init-el.org.
(setq custom-file (concat user-emacs-directory "custom.el"))
(load custom-file 'noerror)
<>
<>
<>
<>
<>
<>
<>
<>
<>
<>
#+end_src
** Packages Setup Config
#+name: packages-setup-config
#+begin_src elisp :results none
;; PACKAGES SETUP
(require 'cl)
(defun my-package-install (package &optional dont-select)
(package-install package dont-select))
(require 'package)
(add-to-list 'package-archives
'("melpa" . "https://melpa.org/packages/") t)
(add-to-list 'package-archives
'("elpa" . "https://elpa.gnu.org/packages/") t)
(package-initialize)
(package-refresh-contents)
(package-install 'use-package)
#+end_src
* Leader Keys
#+name: my-leader-keys-config
#+begin_src elisp :noweb no-export :results none
<>
<>
<>
<>
#+end_src
I have written a custom leader key system called "my-leader-keys". A
leader key system emulates menus. An initial key (M-m for me) opens
the top level menu. The menu presents a key to press that either leads
to the next menu or run a specific interative function.
It all starts with the =def-my-command= macro, which associates a key
to a menu of commands. Each 'command' is just an interactive function.
** My Leader Keys Definition
#+name: my-leader-key-system
#+begin_src elisp :results none
;; Leader Keys System
(setq lexical-binding t)
(defmacro def-my-command (name forms)
`(defun ,name (ch)
(interactive (let ((input (read-char (my-prompt-string ,forms))))
(list input)))
(let ((command (assoc ch ,forms)))
(when command
(call-interactively (caddr command))))))
;; a helper function for navigating command menus
(defun my-prompt-string (&optional forms)
(concat "Options: "
(mapconcat 'identity
(mapcar #'cadr
(if forms forms *my-leader-command-forms*))
", ")))
#+end_src
** My Leader Key Toplevel Menu
The leader key system wouldn't be much good without a top-level leader
key. Here the inital leader key menu is defined and bound to M-m.
#+name: my-leader-key-toplevel-menu
#+begin_src elisp :results none
;; Leader Key Entry Point
(setq imenu-auto-rescan t)
(def-my-command my-leader-command
'((?/ "[/] search buffer" swiper)
(?q "[q]uery replace" query-replace)
(?i "[i]menu" imenu)
(?' "['] shell" persp-shell--jump-to-persp-shell)
(?b "[b]uffers" my-buffer-command)
(?c "[c]apture" org-capture)
(?a "[a]applications" my-utilities-command)
(?t "[t]hemes" my-theme-cycler)
(?l "[l]ayouts" my-perspective-command)
(?w "[w]indows" my-window-comand)
(?p "[p]rojectile" my-projectile-command)
(?m "[m]ajor mode" my-major-mode-command)
(?f "[f]ind file" find-file)
(?s "[s]lime selection" my-lisp-switch-command)
(?z "[z]ettel" my-zettel-subcommand)
))
(global-set-key (kbd "M-m") 'my-leader-command)
#+end_src
** My leader Key Major Mode Menu
#+name: my-leader-key-major-mode-menu
#+begin_src elisp :results none
(defvar my-major-mode-list nil "subcommands by major-mode")
(setf my-major-mode-list
'(;(haxe-mode my-haxe-mode-command)
(org-mode my-org-command)
(zettel-mode my-zettel-mode-command)
(slime-repl-mode my-lisp-mode-command)
(pdf-view-mode my-pdf-view-mod-command)
(lisp-mode my-lisp-mode-command)))
(defun my-major-mode-command ()
(interactive)
(let ((mode-command (assoc major-mode my-major-mode-list)))
(when mode-command
(call-interactively (cadr mode-command)))))
#+end_src
** My leader key utilities and applications menu
#+name: my-leader-key-applications-menu
#+begin_src elisp :results none
(def-my-command my-utilities-command
'((?o "org clock [o]ut" org-clock-out)
(?r "org [r]esume last" org-clock-in-last)
(?c "[c]alendar" cfw:open-org-calendar)
(?a "[a]genda" org-agenda)
(?b "[b]ooks" calibredb)
(?d "[d]eft" toggle-deft)
(?f "el[f]eed" elfeed)
(?j "[j]ournal" toggle-journal)
(?s "[s]ecrets" toggle-secrets)
(?p "[p]astebin" cicadas-paste-current-buffer)))
#+end_src
* Org Mode Configs
#+name: org-mode-config
#+begin_src elisp :noweb no-export
<>
<>
<>
#+end_src
** Org Mode Main Config
#+name: org-mode-main-config
#+begin_src elisp :noweb no-export
(package-install 'org)
(setq org-duration-format 'h:mm)
(setq org-edit-src-content-indentation 0)
(setq org-goto-interface 'outline-path-completion
org-goto-max-level 10
org-outline-path-complete-in-steps nil)
(setq org-imenu-depth 10)
(defun my-org-up-heading ()
(interactive)
(org-up-heading-safe))
(defun my-org-down-heading ()
(interactive)
(org-down-element))
(defun personal-log-insert ()
(interactive)
(org-insert-heading)
(delete-backward-char 1)
(insert "* ")
(insert (current-time-string)))
(defun org-insert-internal-link (title)
(interactive "sHeading: ")
(insert "[[*")
(call-interactively 'complete-symbol)
(insert (format "][%s]]" title)))
(defun org-insert-named-code-block (name lang)
(interactive "sName: \nsLanguage: ")
(insert "#+name: ")
(insert name)
(insert "\n")
(insert (format "#+begin_src %s :noweb no-export\n\n#+end_src" lang)))
#+end_src
** Org Mode and Babel Configuration
#+name: org-mode-babel-config
#+begin_src elisp :results none
(package-install 'graphviz-dot-mode)
(package-install 'ob-haxe)
(add-hook 'org-mode-hook
(lambda () (org-toggle-inline-images)))
(org-babel-do-load-languages
'org-babel-load-languages
'((emacs-lisp . t)
(lisp . t)
(haxe . t)
(dot . t)
(C . t)
(shell . t)))
(add-to-list 'org-src-lang-modes
'("dot" . graphviz-dot))
#+end_src
** My-Leader Key for Org Major Mode
#+name: org-mode-leader-key-menu
#+begin_src elisp :results none :noweb no-export
(def-my-command my-org-command
'((?/ "[/] sparse tree" org-sparse-tree)
(?g "[g]oto" org-goto)
(?u "[u]p heading" my-org-up-heading)
(?d "[d]own heading" my-org-down-heading)
(?p "[p]revious heading" org-previous-visible-heading)
(?n "[n]next heading" org-next-visible-heading)
(?r "Org [r]efile" org-refile)
(?k "Org [k]ut" org-cut-special)
(?s "Org [s]ort" org-sort)
(?A "Org [A]rchive" org-archive-subtree)
(?i "[i]insertion" my-org-insertion-subcommand)
(?E "[E]xport" my-org-export-subcommand)
(?e "[e]dit a code block" org-edit-src-code)
(?N "[N]arrow" org-narrow-to-subtree)
(?W "[W]iden" widen)
(?I "[I]mages toggle" org-toggle-inline-images)
(?c "table re[c]alculate" org-table-recalculate)
(?C "[C]lock" my-org-clock-command)))
(def-my-command my-org-clock-command
'((?c "[c]lock in" org-clock-in)
(?o "clock [o]ut" org-clock-out)
(?r "clock [r]eport" org-clock-report)))
(def-my-command my-org-export-subcommand
'((?t "[t]angle file" org-babel-tangle)
(?e "[e]xport options" org-export-dispatch)))
(def-my-command my-org-insertion-subcommand
'((?l "internal [l]ink" org-insert-internal-link)
(?L "external [L]ink" org-insert-link)
(?d "[d]ated log entry" personal-log-insert)
(?D "[D]eadline" org-deadline)
(?T "[T]imestamp" org-time-stamp)
(?f "[f]ootnote" org-footnote-new)
(?b "named code [b]lock" org-insert-named-code-block)
(?s "[s]tructure template" org-insert-structure-template)))
#+end_src
* UI
#+name: ui-config
#+begin_src elisp :noweb no-export :results none
;;; UI
<>
<>
<>
<>
<>
<>
<>
<>
<>
#+end_src
** UI Chrome
I like for my emacs to have as little UI chrome as possible, and to
have a consistent UI experience. So I disable the blinking cursor, I
set cursor type to 'box by default, and I disable menu, tool, and
scroll bars.
#+name: ui-chrome-config
#+begin_src elisp :results none
;; UI Chrome
(blink-cursor-mode 0)
(setq-default cursor-type 'box)
(menu-bar-mode 0)
(tool-bar-mode 0)
(scroll-bar-mode -1)
(toggle-frame-fullscreen)
(defun transparency (value)
"Sets the transparency of the frame window. 0=transparent/100=opaque"
(interactive (let* ((prompt (concat "Transparency Value 0 - 100 opaque ["
(prin1-to-string (frame-parameter (selected-frame) 'alpha))
"]:"))
(input (read-number prompt)))
(list input)))
(set-frame-parameter (selected-frame) 'alpha value))
#+end_src
** Modeline Config
#+name: ui-modeline-config
#+begin_src elisp :results none
(package-install 'doom-modeline)
(require 'doom-modeline)
(doom-modeline-mode 1)
#+end_src
** Tweaks
Bits and bobs.
I globally unset the C-z keybinding because it is easy to hit by
accident and causes the window to suddenly close.
In addition, for some programming langauges, tabs should not be used
to perform indtentation of source code. To ensure that no indentation
does not, by default, use tabs, I set indent-tabs-mode to nil.
#+name: ui-tweaks-config
#+begin_src elisp :results none
(global-unset-key "\C-z")
(setq-default indent-tabs-mode nil)
(global-hl-line-mode 1)
#+end_src
** Fonts Config
I use Victor Mono for most coding work, and Linux Libertine for my
variable pitch font. Variable pitch fonts are good for e.g. reading
the web using =eww= and writing in distraction-free mode with
=writeroom=.
Fonts must generally be installed. Linux libertine came preinstalled
with my Debian system (running Gnome 3), but Victor Mono had to be
installed manually. I downloaded it from [[https://rubjo.github.io/victor-mono/][here]] and then installed it
using the =font-manager= application.
Running these two commands should install the font.
: sudo apt install font-manager
: font-manager -i ~/Downlaods/VictorMonoAll.zip
#+name: ui-fonts-config
#+begin_src elisp :results none
;; FONTS
(add-to-list 'default-frame-alist
'(font . "Victor Mono-10"))
(set-face-attribute 'variable-pitch nil
:family "Linux Libertine"
:height 1.25)
#+end_src
** Bells and Whistles
#+name: ui-bells-and-wistles
#+begin_src elisp :results none
(package-install 'org-superstar)
(require 'org-superstar)
(add-hook 'org-mode-hook (lambda ()
(org-superstar-mode 1)
(visual-line-mode)))
#+end_src
** My Leader Keys
** Completions Engine
#+name: ui-completion-engine
#+begin_src elisp :results none
(package-install 'ivy)
(package-install 'smex)
(package-install 'swiper)
(ivy-mode 1)
(setq ivy-use-selectable-prompt t)
(smex-initialize)
(global-set-key (kbd "M-x") 'smex)
#+end_src
** Buffers, Windows, and Perspectives
#+name: ui-windows-and-perspectives
#+begin_src elisp :noweb no-export :results none
<>
<>
<>
<>
#+end_src
*** Packages
#+name: ui-windows-and-perspectives-packages
#+begin_src elisp :results none
(package-install 'perspective)
(persp-mode)
(package-install 'rotate)
(package-install 'window-numbering)
(window-numbering-mode)
(package-install 'resize-window)
(require 'resize-window)
#+end_src
*** Window Leader Key Menu
#+name: ui-window-leader-key-menu
#+begin_src elisp :results none
(setq fit-window-to-buffer-horizontally t)
(defun my-fit-window-to-buffer ()
(interactive)
(fit-window-to-buffer)
(resize-window--enlarge-horizontally))
(def-my-command my-window-comand
'((?/ "[/] vertical splitter" split-window-horizontally)
(?- "[-] horoziontal splitter" split-window-vertically)
(?b "[b]alance windows" balance-windows)
(?t "[t]ransparency" transparency)
(?k "[k]ill window" delete-window)
(?m "[m]aximise window" delete-other-windows)
(?R "[R]otate window" rotate-window)
(?r "[r]esize widnows" resize-window)
(?f "[f]it window" my-fit-window-to-buffer)
(?p "font [p]itch shift" variable-pitch-mode)
(?v "[v]isual line mode" visual-line-mode)
(?w "[w]riteroom mode" writeroom-mode)))
#+end_src
*** Buffer Leader Key Menu
#+name: ui-buffer-leader-key-menu
#+begin_src elisp :results none
(def-my-command my-buffer-command
'((?b "switch [b]uffers" ivy-switch-buffer)
(?s "[s]ave buffer" save-buffer)
(?S "[S]ave all buffers" save-some-buffers)
(?k "[k]ill buffer" kill-buffer)))
#+end_src
*** Perspectives Leader Key Menu
#+name: ui-perspectives-leader-key-menu
#+begin_src elisp :results none
(def-my-command my-perspective-command
'((?s "[s]witch perspective" persp-switch)
(?k "[k]ill perspective" persp-kill)
(?d "[d]rop buffer" persp-remove-buffer)
(?n "re[n]ame perspective" persp-rename)
(?a "[a]dd buffer" persp-add-buffer)))
#+end_src
** Themes
#+name: ui-themes
#+begin_src elisp :noweb no-export :results none
<>
<>
#+end_src
*** Installed Themes
#+name: ui-themes-installed
#+begin_src elisp :results none
(package-install 'autothemer) ;; for custom themes
(setq my-installed-themes
'(dracula-theme
zenburn-theme
moe-theme
notink-theme
punpun-theme
solo-jazz-theme
tao-theme
yoshi-theme
srcery-theme
subatomic-theme
chocolate-theme
poet-theme
white-sand-theme
foggy-night-theme))
(dolist (package my-installed-themes)
(when (not (package-installed-p package))
(package-install package)))
;; starting theme
(load-theme 'dracula t)
#+end_src
*** Theme Switcher
#+name: ui-themes-theme-switcher
#+begin_src elisp :results none
(setq *my-themes*
'(punpun-light
white-sand
leuven
solo-jazz
tao-yang
notink
zenburn
subatomic
foggy-night
chocolate
dracula
;; halloweenie ;; <-- ONLY DURING OCTOBER
yoshi
srcery
tao-yin
punpun-dark))
(defun my-theme-string ()
(if (car custom-enabled-themes)
(format "%s is current" (car custom-enabled-themes))
""))
(defun my-theme-cycler ()
(interactive)
(let ((still-cycling t))
(message (format "%s [n]ext or [p]evious. Anything else to quit."
(my-theme-string)))
(while still-cycling
(let ((char (read-key)))
(cond
((eq char ?n) (my-theme-command-next))
((eq char ?p) (my-theme-command-previous))
(t (setq still-cycling nil))))
(message (format "%s [n]ext or [p]evious. Anything else to quit."
(my-theme-string))))))
(defun my-theme-command-next ()
(interactive)
(let* ((active-theme (car custom-enabled-themes))
(next-theme (cadr (cl-member active-theme *my-themes*))))
(when active-theme (disable-theme active-theme))
(if next-theme (load-theme next-theme t)
(load-theme (car *my-themes*) t))
(setq cursor-type 'box)
(setq-default cursor-type 'box)))
(defun my-theme-command-previous ()
(interactive)
(let* ((active-theme (car custom-enabled-themes))
(themes (reverse *my-themes*))
(next-theme (cadr (cl-member active-theme themes))))
(when active-theme (disable-theme active-theme))
(if next-theme (load-theme next-theme t)
(load-theme (car themes) t))
(setq cursor-type 'box)
(setq-default cursor-type 'box)))
#+end_src
*** Halloweenie
#+name: halloweenie
#+begin_src elisp :tangle ~/.emacs.d/halloweenie-theme.el
;; halloweenie - a Halloween emacs color theme.
;; Copyright (C) 2021 Colin Okay
;;
;; This program is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;;
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see .
;; Spooky times all.
(require 'autothemer)
(autothemer-deftheme
halloweenie "Ghost, Ghouls, and worst of all: Pumpkin Spice"
((((class color) (min-colors #xFFFFFF)))
(halloweenie-pitch "#1c1c1c")
(halloweenie-night "#1f213a")
(halloweenie-blood "#a2270d")
(halloweenie-potion "#832ea1")
(halloweenie-slime "#15ed0a")
(halloweenie-jackolantern "#FF9430")
(halloweenie-spellglow "#d478e0")
(halloweenie-bone "#E8E7D5")
(halloweenie-rot "#6Bc980")
(halloweenie-ghost "#C1CAE8")
(halloweenie-shine "#70c2ca")
(halloweenie-cateyes "#ffde38")
(halloweenie-evileyes "#FF1F1F"))
(
(default (:foreground halloweenie-bone :background halloweenie-pitch) :weight 'semi-bold)
(error (:foreground halloweenie-evileyes :weight 'semi-bold))
(cursor (:background halloweenie-slime))
(region (:background "black"))
(hl-line (:background halloweenie-night))
(link (:background halloweenie-potion))
(mode-line (:background halloweenie-jackolantern :foreground halloweenie-pitch))
(mode-line-emphasis (:foreground halloweenie-pitch :weight 'bold))
(font-lock-comment-face (:foreground halloweenie-slime))
(font-lock-string-face (:foreground halloweenie-rot))
(font-lock-type-face (:foreground halloweenie-cateyes :weight 'ultra-bold))
(font-lock-constant-face (:foreground halloweenie-evileyes :weight 'extra-bold))
(font-lock-variable-name-face ( :weight 'bold :foreground halloweenie-spellglow))
(font-lock-function-name-face (:foreground halloweenie-spellglow :weight 'bold :slant 'italic))
(font-lock-builtin-face (:foreground halloweenie-jackolantern :weight 'semi-bold))
(font-lock-keyword-face (:foreground halloweenie-jackolantern :weight 'extra-bold))
;; org
(org-todo (:weight 'bold :foreground halloweenie-evileyes))
(org-done (:weight 'bold :foreground halloweenie-rot ))
;; doom modeline
(doom-modeline-project-dir
(:foreground halloweenie-pitch :weight 'bold ))
(doom-modeline-project-root-dir
(:foreground halloweenie-blood :weight 'bold))
;; persp
(persp-selected-face
(:foreground halloweenie-blood :weight 'bold :slant 'italic))))
(provide-theme 'halloweenie)
#+end_src
** Org
*** Org mode tweaks
# #+name: ui-org-mode-tweaks
#+begin_src elisp :noweb no-export :results none
(add-hook 'org-mode-hook
'(lambda ()
(mapc
(lambda (face) ;; Other fonts with fixed-pitch.
(set-face-attribute face nil :inherit 'fixed-pitch :height 100))
(list 'org-code
'org-link
'org-block
'org-table
'org-block-begin-line
'org-block-end-line
'org-meta-line
'org-document-info-keyword))))
(setq org-adapt-indentation nil)
#+end_src
* Communications
#+name: communications-config
#+begin_src elisp :noweb no-export :results none
<>
<>
;;<>
;; <>
#+end_src
** ERC
ERC is an IRC client that is built into Emacs. You can use it to
log into irc servers and chat with other nerds. ERC is very
communicative about changes in status in a particular IRC channel
-- too informative. It prints messages everytime somebody joins or
leaves a room or quits the server altogether. This can be a bit
annoying - active rooms will often contain just as many join/part
messages as chat messages. So this little snippit configures ERC
to hide certain kinds of message:
#+name: erc-config
#+begin_src elisp :results none
;;; ERC
(setq erc-hide-list '("JOIN" "QUIT" "PART"))
#+end_src
** Cicadas Pastebin
*** bepasty from emacs
First you need to install ~pastebinit~
: sudo apt install pastebinit
Then you should get the pastebin creds from somebody who has them and
put them into a file called ~$HOME/.bepasty-key~.
Then put the following into yoru config.
#+name: cicadas-bepasty
#+begin_src elisp :noweb no-export :results none
(defun read-file-into-string (f)
(with-temp-buffer
(insert-file-contents f)
(buffer-string)))
(setq cicadas-paste-pw (read-file-into-string "~/.bepasty-key"))
(defun cicadas-paste-current-buffer ()
(interactive)
(let ((tmpfile
(concat "/tmp/" (buffer-name))))
(write-region nil nil tmpfile)
(let ((url
(first (last (butlast
(split-string
(shell-command-to-string
(format "pastebinit -i %s -p %s -t '%s' -f text/plain"
tmpfile
cicadas-paste-pw
(buffer-name)))
"\n"))))))
(delete-file tmpfile)
(kill-new url)
(message "Pasted to %s (on kill ring)" url))))
#+end_src
*** SCPASTE :disabled:
# #+name: cicadas-scpaste
#+begin_src elisp :results none
(package-install 'scpaste)
(setq scpaste-http-destination "http://cicadas.surf/pastebin"
scpaste-scp-destination "colin@cicadas.surf:/srv/http/www.cicadas.surf/pastebin"
scpaste-user-name "Colin"
scpaste-user-address "https://hyperthings.garden")
#+end_src
** Mail on emacs
*** Installing dependencies :prereq:
On debian 11, I was able to run this to install dependencies.
#+begin_src bash
sudo apt-get install -y libgmime-3.0-dev libxapian-dev \
mu4e guile-3.0-dev html2text xdg-utils offlineimap
#+end_src
*** Configuring offlineimap :disabled:
The blocks in this file are used to separately tangle to an ~/.offlineimparc
See the file at
/usr/share/doc/offlineimap3/examples/offlineimap.conf for more
info.
# #+begin_src conf :tangle ~/.offlineimaprc :noweb no-export :results none
[general]
accounts = Cicadas, ToyfulSpace
[Account Cicadas]
localrepository = CicadasLocal
remoterepository = CicadasRemote
[Repository CicadasLocal]
type = Maildir
localfolders = ~/Maildir/Cicadas
[Repository CicadasRemote]
type = IMAP
remotehost = imap.migadu.com
remoteuser = colin@cicadas.surf
remotepass = <>
ssl = yes
sslcacertfile = /etc/ssl/certs/ca-certificates.crt
[Account ToyfulSpace]
localrepository = ToyfulSpaceLocal
remoterepository = ToyfulSpaceRemote
[Repository ToyfulSpaceLocal]
type = Maildir
localfolders = ~/Maildir/ToyfulSpace
[Repository ToyfulSpaceRemote]
type = IMAP
remotehost = imap.migadu.com
remoteuser = okay@toyful.space
remotepass = <>
ssl = yes
sslcacertfile = /etc/ssl/certs/ca-certificates.crt
#+end_src
**** Setup Mu and Sync Initial Mails :setup:
#+begin_src bash
mu init --maildir=~/Maildir --my-address=colin@cicadas.surf --my-address=okay@toyful.space && \
offlineimap -a Cicadas && offlineimap -a ToyfulSpace && \
mu index
#+end_src
*** Confuguring Mu4e :disabled:
# #+name: mu4e-config
#+begin_src elisp :noweb no-export :results none
(require 'mu4e)
<>
<>
(setq mu4e-contexts
(list
<>
<>))
;; For viewing patches in emails
(package-install 'message-view-patch)
(add-hook 'mu4e-view-mode-hook 'message-view-patch-highlight)
#+end_src
**** Mu4e Sendmail Config
#+name: mu4e-sendmail-config
#+begin_src elisp :results none
(require 'smtpmail)
(setq mail-user-agent 'mu4e-user-agent
message-send-mail-function 'smtpmail-send-it
smtpmail-stream-type 'tls
smtpmail-default-smtp-server "smtp.migadu.com"
smtpmail-smtp-server "smtp.migadu.com"
smtpmail-smtp-service 465)
#+end_src
**** Mu4e mail sync command
#+name: mu4e-fetch-and-sync-mail-config
#+begin_src elisp :results none
(setq mu4e-get-mail-command "offlineimap -a Cicadas && offlineimap -a ToyfulSpace")
#+end_src
**** Mu4e Contexts
#+name: cicadas-mu4e-context
#+begin_src elisp :results none
(make-mu4e-context
:name "Cicadas"
:enter-func (lambda () (mu4e-message "Entering Cicadas Context"))
:leave-func (lambda () (mu4e-message "Leaving Cicadas Context"))
:match-func (lambda (msg)
(when msg
(mu4e-message-contact-field-matches msg :to "colin@cicadas.surf")))
:vars '((user-full-name . "Colin Okay")
(user-mail-address . "colin@cicadas.surf")
(smtpmail-smtp-user . "colin@cicadas.surf")
(mu4e-sent-folder . "/Cicadas/Sent")
(mu4e-compose-signature . "Making Things Wiggle\nColin\n")))
#+end_src
#+name: toyfulspace-mu4e-context
#+begin_src elisp :results none
(make-mu4e-context
:name "Toyful Space"
:enter-func (lambda () (mu4e-message "Entering Toyful Space Context"))
:leave-func (lambda () (mu4e-message "Leaving Toyful Space Context"))
:match-func (lambda (msg)
(when msg
(mu4e-message-contact-field-matches msg :to "okay@toyful.space")))
:vars '((user-full-name . "Colin Okay")
(user-mail-address . "okay@toyful.space")
(smtpmail-smtp-user . "okay@toyful.space")
(mu4e-sent-folder . "/ToyfulSpace/Sent")
(mu4e-compose-signature . "Making Things Wiggle\nColin\n")))
#+end_src
* Time Managment
#+name: time-management-config
#+begin_src elisp :noweb no-export :results none
;;; TIME MANAGMENT
(setq org-enforce-todo-dependencies t
org-enforce-todo-checkbox-dependencies t)
(setq org-edit-src-content-indentation 0)
<>
<>
<>
<>
#+end_src
** CALFW calendar
#+name: calfw-org-config
#+begin_src elisp :noweb no-export :results none
(package-install 'calfw)
(package-install 'calfw-org)
(require 'calfw)
(require 'calfw-org)
#+end_src
** Org Refile
#+name: org-refile-config
#+begin_src elisp :results none
(setq my-org-refile-directory "~/notes/deft/")
(defun my-org-refile-targets ()
(loop for fname in (directory-files my-org-refile-directory)
when (string-match "\.org$" fname)
collect (concat my-org-refile-directory fname)))
(setq org-refile-targets
'((my-org-refile-targets :maxlevel . 5)))
#+end_src
** Org Capture
#+name:org-capture-config
#+begin_src elisp :results none
(setq org-capture-templates
(quote
(("i" "Inbox" entry
(file+headline "~/notes/deft/project-Planner.org" "INBOX")
"")
("j" "Journal" entry
(file+olp+datetree "~/notes/circadian.org.cpt")
"")
("c" "Calendar" entry
(file+headline "~/notes/deft/project-Planner.org" "CALENDAR")
"* %?\n %(cfw:org-capture-day)"))))
;; ("i" "Inbox" entry
;; (file "~/notes/deft/project-Inbox.org")
;; "")
#+end_src
** Org Agenda
#+name: org-agenda-config
#+begin_src elisp :noweb no-export :results none
(custom-set-variables
'(org-directory "~/notes/deft")
'(org-agenda-files "~/notes/org-agenda-files"))
(add-hook 'org-agenda-mode-hook
(lambda ()
(local-set-key (kbd "M-m") 'my-leader-command)))
#+end_src
* Reading, Notes, and Writing
#+name: reading-notes-and-writing-config
#+begin_src elisp :noweb no-export :results none
<>
<>
<>
<>
<>
<>
<>
<>
<>
<>
<>
<>
<>
#+end_src
** Calibre db
#+name: calibre-config
#+begin_src elisp :results none
(package-install 'calibredb)
(require 'calibredb)
(setq calibredb-root-dir "~/Books")
(setq calibredb-db-dir (expand-file-name "metadata.db" calibredb-root-dir))
#+end_src
** PDF tools for Reading and Annotating PDFS
*** PDF Tools
#+name: pdf-tools
#+begin_src elisp :results none
(package-install 'pdf-tools)
(pdf-tools-install)
#+end_src
*** Some functions to quickly annotate
#+name: pdf-mode-config
#+begin_src elisp :results none
(defun my-pdf-annot-at-position (pos)
"Return annotation at POS in the selected window.
POS should be an absolute image position as a cons \(X . Y\).
Alternatively POS may also be an event position, in which case
`posn-window' and `posn-object-x-y' is used to find the image
position.
Return nil, if no annotation was found."
(let (window)
(when (posnp pos)
(setq window (posn-window pos)
pos (posn-object-x-y pos)))
(save-selected-window
(when window (select-window window 'norecord))
(let* ((annots (pdf-annot-getannots (pdf-view-current-page)))
(size (pdf-view-image-size))
(rx (/ (car pos) (float (car size))))
(ry (/ (cdr pos) (float (cdr size))))
(rpos (cons rx ry)))
(cl-some (lambda (a)
(and (cl-some
(lambda (e)
(pdf-util-edges-inside-p e rpos))
(pdf-annot-get-display-edges a))
a))
annots)))))
(defun my-pdf-annot-add-text-annotation ()
(interactive)
(let ((annot
(or (my-pdf-annot-at-position '(0 . 0))
(pdf-annot-add-text-annotation '(0 . 0)))))
(pdf-annot-edit-contents annot)))
(def-my-command my-pdf-view-mod-command
'((?/ "[/] search pdf" pdf-occur)
(?l "[l]ist annotations" pdf-annot-list-annotations)
(?m "[m]idnight mode" pdf-view-midnight-minor-mode)
(?n "add [n]ote" my-pdf-annot-add-text-annotation)))
#+end_src
** Nov for Reading EPUBs
#+name: nov-mode-config
#+begin_src elisp :results none
(package-install 'nov)
(add-to-list 'auto-mode-alist '("\\.epub\\'" . nov-mode))
#+end_src
** Elfeed for Reading RSS Feeds
#+name: elfeed-config
#+begin_src elisp :results none
(package-install 'elfeed)
(require 'elfeed)
(setq elfeed-feeds
'(
("https://pointersgonewild.com/feed/" frontpage blog programming)
("https://blog.einval.com/index.rss" blog debian linux)
("https://justinehsmith.substack.com/feed" blog newsletter frontpage)
("https://paper.wf/boutade/feed/" blog newsletter frontpage)
("https://rogersbacon.substack.com/feed" blog newsletter frontpage)
("https://www.residentcontrarian.com/feed" blog newsletter frontpage)
("https://learnui.design/blog/feed.xml" design blog ui webdev)
("https://theconvivialsociety.substack.com/feed"
culture media blog newsletter frontpage technology)
("https://mr.gy/blog/index.xml" blog frontpage)
("https://knowablemagazine.org/rss" science blog culture frontpage)
("https://stop.zona-m.net/feed.xml" blog linux yro floss)
("https://blog.veitheller.de/feed.rss" blog)
("https://existentialcomics.com/rss.xml" philosophy comic)
("http://jacek.zlydach.pl/blog/feed.xml" blog lisp frontpage)
("https://wingolog.org/feed/atom" blog frontpage)
("https://www.unixsheikh.com/feed.rss" blog frontpage sysadmin)
("https://ingrids.space/index.xml" blog frontpage)
("https://ngnghm.github.io/feeds/all.rss.xml" lisp programming coolness frontpage)
("https://computer.rip/rss.xml" frontpage)
("http://waywardmonkeys.org/feeds/all.atom.xml" lisp frontpage)
("https://www.sicpers.info/rss" frontpage)
("https://manuelmoreale.com/feed" frontpage)
("https://www.stephendiehl.com/feed.rss" frontpage)
("https://www.raphkoster.com/feed/" frontpage gamedev)
("https://surfingcomplexity.frontpage/feed/" frontpage dev)
("https://fukamachi.hashnode.dev/rss.xml" lisp frontpage)
("https://hyperthings.garden/feeds/colins-daily-log.xml" frontpage)
("https://frontpage.ncase.me/rss" frontpage )
("https://staticadventures.netlib.re/rss.xml" frontpage yro libre)
("https://realcoopstories.org/index.xml" frontpage coops socialism)
("https://mckinley.cc/frontpage/rss.xml" frontpage)
("https://rusingh.com/feeds/" frontpage)
("https://babbagefiles.xyz/posts/index.xml" frontpage lisp)
("https://stumbles.id.au/feeds/all.atom.xml" frontpage guix)
("https://stragu.gitlab.io/feed.xml" frontpage)
("http://gamestudies.org/rss.php" journal gamedev)
("https://www.attacus.net/feed.xml" tech yro)
("https://frontpage.metaobject.com/feeds/posts/default" frontpage programming)
("http://cowlark.com/feed.rss" frontpage retrocomputing)
("https://sfconservancy.org/feeds/frontpage/" foss floss)
("https://aeon.co/feed.rss" philosophy culture magazine frontpage)
("http://malisper.me/category/postgres/feed/" frontpage lisp)
("https://infovore.org/feed/" frontpage culture media)
("https://adam.nels.onl/rss.xml" lisp frontpage)
("https://funcall.frontpagespot.com/feeds/6629439843004430442/comments/default" frontpage lisp)
("https://hkvim.com/rss.xml" emacs frontpage)
("http://turtleware.eu/rss.xml" lisp frontpage)
("https://hyperthings.garden/rss/all-posts.xml" frontpage)
("https://spwhitton.name/frontpage/index.rss" lisp frontpage)
("https://tymoon.eu/api/reader/atom" lisp frontpage gamedev)
("https://hacks.mozilla.org/feed/" frontpage technology)
("https://alliedmedia.tumblr.com/rss" media social)
("https://frontpage.acolyer.org/feed/" academic computerscience)
("https://frontpage.fourthbit.com/atom.xml" scheme programming)
("http://ajroach42.com/feed.xml" frontpage smallinternet)
("https://codeascraft.com/atom" dev web)
("https://daily.jstor.org/feed/" science culture frontpage)
("https://feeds.feedburner.com/GamasutraIndependentNews" games news)
("https://feeds.feedburner.com/HypocriteReader" hypocritereader magazine culture)
("https://feeds.feedburner.com/codinghorror" dev web)
("https://feeds.feedburner.com/ieeespectrum/automaton" technology)
("https://feeds2.feedburner.com/NoTechMagazine" magazine notech anarchism diy culture)
("https://feeds2.feedburner.com/typepad/krisdedecker/lowtechmagazineenglish"
magazine diy culture)
("https://harpers.org/feed/" harpers news culture frontpage)
("https://haxe.org/frontpage/rss/" haxe programming)
("https://kcpdchief.frontpagespot.com/feeds/posts/default" police kansascity)
("https://markburgess.org/frontpage_feed.xml" cs science culture)
("https://mkremins.github.io/atom.xml" programming hci)
("https://nlpers.frontpagespot.com/feeds/posts/default" nlp)
("https://prog21.dadgum.com/atom.xml" dev fp games)
("https://publicdomainreview.org/feed/" culture frontpage )
("https://smbc-comics.com/rss.php" comic)
("https://www.allthingsdistributed.com/atom.xml" scalability devops)
("https://www.comicsgrid.com/gateway/plugin/WebFeedGatewayPlugin/rss2/"
comics academic journal culture)
("https://www.otaku-dad.com/rss.php" comic anime)
("https://www.philosophybites.libsyn.com/rss" podcast philosophy)
("https://www.viruscomix.com/rss.xml" comic)
("https://www.whompcomic.com/feed/" comic)
("http://feedproxy.google.com/brainpickings/rss" frontpage humanities)
("http://retro-style.software-by-mabe.com/frontpage-atom-feed" lisp frontpage)
;("http://rss.ngfiles.com/weeklytop10.xml" gamedev community dorkistry)
("http://rss.slashdot.org/Slashdot/slashdotMain" news technology)
("https://code.haxe.org/rss.xml" programming)
("https://common-lisp.net/project/ecl/rss.xml" lisp)
("https://datagubbe.se/atom.xml" blog frontpage)
("https://freedom-to-tinker.com/feed/rss/" technology yro)
("https://haxe.org/frontpage/rss/" programming)
("https://kircode.com/feed" frontpage gamedev haxe)
("https://librelounge.org/rss-feed-ogg.rss" podcast foss yro)
("https://nalaginrut.com/feed/atom" frontpage programming)
("https://planet.lisp.org/rss20.xml" lisp)
("https://pluralistic.net/feed/" yro technology)
("https://wasmweekly.news/feed.xml" programming)
("https://www.eff.org/rss" yro)
("https://www.filfre.net/feed/rss/" dorkistry frontpage technology)
("https://www.fsf.org/static/fsforg/rss/news.xml" yro foss floss)
("https://www.gnome.org/feed/" linux foss floss)
("https://www.reddit.com/r/GCSolidarity/new/.rss" reddit lisp)
("https://www.reddit.com/r/common_lisp/new/.rss" reddit lisp)
("https://www.reddit.com/r/lisp/new/.rss" reddit lisp)
("https://www.reddit.com/r/lispadvocates/new/.rss" reddit lisp)
("https://www.rifters.com/crawl/?feed=rss2" frontpage)
("https://www.techdirt.com/techdirt_rss.xml" news technology yro)
("http://turtleware.eu/rss.xml" frontpage lisp)
("https://emacsninja.com/feed.atom" emacs frontpage lisp)
("http://ruricolist.frontpagespot.com/feeds/posts/default" frontpage lisp writing)
("https://www.epic.org/index.xml" yro)
("https://freedom.press/news/feed/" yro )
("https://frontpage.nearlyfreespeech.net/category/news/feed/" frontpage)
("https://www.schneier.com/feed/atom" yro security)
("https://40ants.com/lisp-project-of-the-day/rss.xml" lisp frontpage)
("https://alhassy.github.io/rss.xml" lisp frontpage)
("https://ambrevar.xyz/atom.xml" lisp frontpage)
("https://thesephist.com/index.xml" frontpage programming)
("https://herman.bearfrontpage.dev/feed/" frontpage)
("https://hugo.md/index.xml" frontpage)
("https://capitalaspower.com/frontpage/rss" frontpage activism)
("https://twobithistory.org/feed.xml" frontpage culture)
("https://lambdaland.org/index.xml" frontpage dev)
("https://anarc.at/frontpage/index.rss" yro )
("https://feeds.transistor.fm/hope-in-source" podcast foss floss)
("https://www.sapiens.org/feed/" culture)
("http://tech.oeru.org/rss.xml" foss floss)
("https://yogthos.net/feed.xml" frontpage dev)
("https://psyche.co/feed" culture mind science philosphy magazine)
("https://davelane.nz/rss.xml" foss floss)
("http://frontpages.harvard.edu/doc/feed/" yro)
("https://themarkup.org/feeds/rss.xml" yro)
("https://mdhughes.tech/feed/" frontpage)
("https://uglyduck.ca/feed.xml" frontpage)
("https://xn--gckvb8fzb.com/index.xml" frontpage yro tech)
("https://apenwarr.ca/log/rss.php" frontpage)
("https://joeyh.name/blog/index.rss" frontpage blog)
("http://fossforce.com/feed/" floss blog yro)
("https://xkcd.com/rss.xml" comic)))
(setq-default elfeed-search-filter "@2-weeks-ago +unread +frontpage")
#+end_src
** Zettelgunk
Zettelgunk is a half-hearted zettelkasten system I am sometimes
working on.
#+name: zettelgunk
#+begin_src elisp :results none
(load "~/notes/elisp/zettel-mode/zettel.el")
(setq zettel-directory "~/notes/zettel/")
(def-my-command my-zettel-mode-command
'((?b "[b]ack " zettel-jump-back)
(?t "[t]ag browse" zettel-browse-tags)
(?f "[f]ind note" zettel-browse-notes)
(?/ "[/] term search" zettel-search-notes)
(?h "[h]istorical browse (days)" zettel-browse-notes-days-ago)
(?r "browse by [r]everse link" zettel-browse-notes-linking-here)))
(def-my-command my-zettel-subcommand
'((?/ "[/] search notes" zettel-search-notes)
(?f "[f]ind note" zettel-browse-notes)
(?t "[t]ag browse" zettel-browse-tags)
(?h "[h]istorical browse (days)" zettel-browse-notes-days-ago)
(?n "[n]ew note" zettel-spanking-new-note)
(?z "[z]ettel" zettel)))
#+end_src
** CCRYPT
ccrypt is a standard unix encryption tool. It ships with emacs
bindings that allow users to encrypt and ecrypt files just by
opening and saving them. Such files have a .cpt extension.
#+name: ccrypt
#+begin_src elisp :results none
(load "~/notes/ps-ccrypt.el")
#+end_src
** Toggler
Toggler.el is some code I wrote ages ago. Its sole purpose is to
toggle some file/buffers for easy access.
for now all of the toggling happens in toggler.el, but it shoul be facotred a bit.
#+name: toggler
#+begin_src elisp :results none
(load "~/notes/elisp/toggler.el")
#+end_src
** Deft
#+name: deft
#+begin_src elisp :results none
(package-install 'deft)
(require 'subr-x) ;; what i this?
(setq deft-directory "~/notes/deft/")
(setq deft-use-filename-as-title nil)
(setq deft-use-filter-string-for-filename t)
(setq deft-extensions '("org"))
#+end_src
** Writeroom
#+name: writeroom
#+begin_src elisp :results none
(package-install 'writeroom-mode)
(setq my-writeroom-theme 'poet)
(setq my-writeroom-cached-theme nil)
(add-hook 'writeroom-mode-enable-hook
(lambda ()
(when my-writeroom-theme
(setf my-writeroom-cached-theme
(car custom-enabled-themes))
(disable-theme (car custom-enabled-themes))
(load-theme my-writeroom-theme))
(variable-pitch-mode)))
(add-hook 'writeroom-mode-disable-hook
(lambda ()
(variable-pitch-mode 0)
(disable-theme (car custom-enabled-themes))
(when my-writeroom-cached-theme
(enable-theme my-writeroom-cached-theme))
(setf my-writeroom-cached-theme nil)))
#+end_src
** EWW config
#+name: eww-config
#+begin_src elisp :noweb no-export
(setq browse-url-browser-function 'eww-browse-url)
#+end_src
#+RESULTS: eww-config
: eww-browse-url
** Markdown Editing
#+name: markdown-editing
#+begin_src elisp :noweb no-export
(package-install 'markdown-mode)
#+end_src
#+RESULTS: markdown-editing
** Writefreely
Writefreely is a federated blogging service. The [[https://github.com/dangom/writefreely.el][writefreely.el]]
package lets you publish to writefreely blogs from the comfort of
emacs.
*** Prereqs
First, you need to get an auth token. The following will dump one to a json document.
#+begin_src shell
curl "https://read.cicadas.surf/api/auth/login" \
-H "Content-Type: application/json" -X POST \
-d '{"alias": "your-user-name", "pass": "your-pw"}' > wf-token.json
#+end_src
Next, open that json document and cop the value of the "access_token"
field into a file called =~/.cicadas-wf.token=. When you do, don't
keep the string quoted - leave it unquoted in that .token file.
*** Writefreely Config
#+name: writefreely-config
#+begin_src elisp :noweb no-export :results none
(package-install 'writefreely)
(require 'writefreely)
(setq writefreely-instance-url "https://read.cicadas.surf/"
writefreely-instance-api-endpoint "https://read.cicadas.surf/api"
writefreely-auth-token (read-file-into-string "~/.cicadas-wf.token"))
#+end_src
* Software Development
#+name: software-development-config
#+begin_src elisp :noweb no-export :results none
(show-paren-mode 1)
<>
<>
<>
<>
<>
;; <>
<>
<>
#+end_src
** Literate Programming
Hacks and tweaks for literate programming. Org auto tangle will tangle
a file whenever it is saved.
#+name: literate-programming
#+begin_src elisp :noweb no-export :results none
(package-install 'org-auto-tangle)
(require 'org-auto-tangle)
(add-hook 'org-mode-hook 'org-auto-tangle-mode)
#+end_src
** Tools Essential To Development
#+name: software-dev-essentials
#+begin_src elisp :noweb no-export :results none
(package-install 'flycheck)
(package-install 'magit)
(package-install 'paredit)
(package-install 'ag)
(package-install 'lice)
<>
<>
#+end_src
*** Projectile
#+name: projectile
#+begin_src elisp :results none
(require 'cl-lib)
(package-install 'projectile)
(projectile-mode +1)
(setq projectile-project-search-path '("~/projects/"))
(setq projectile-indexing-method 'alien)
(setq org-duration-format 'h:mm)
(def-my-command my-projectile-command
'((?/ "[/] search project" project-find-regexp)
(?r "[r]eplace in project" projectile-replace)
(?b "project [b]uffers" projectile-ibuffer)
(?o "[o]pen a project" projectile-switch-project)
(?g "ma[g]it" magit-status)
(?j "[j]ump to file" projectile-find-file-dwim)))
#+end_src
*** Company
#+name: company
#+begin_src elisp :results none
(package-install 'company)
(add-hook 'after-init-hook 'global-company-mode)
#+end_src
** Shell Config
#+name: shell-config
#+begin_src elisp :noweb no-export :results none
(defun persp-shell--shell-name ()
(format "*shell %s*" (persp-current-name)))
(defun persp-shell--shell-buffer-p (buffer)
(string-equal (buffer-name buffer)
(persp-shell--shell-name)))
(defun persp-shell--shell ()
(cl-find-if 'persp-shell--shell-buffer-p
(persp-buffers (persp-curr))))
(defun persp-shell--jump-to-persp-shell ()
(interactive)
(let ((buff (persp-shell--shell)))
(if buff (switch-to-buffer-other-window buff)
(shell (persp-shell--shell-name)))))
#+end_src
** Eshell :disabled:
# #+name: shell-config
#+begin_src elisp :noweb no-export :results none
<>
<>
#+end_src
*** Eshell Prompt
The ehsell prompt can be customized
#+name: eshell-prompt-config
#+begin_src elisp :results none
(defun shortened-path (path max-len)
"Return a modified version of `path', replacing some components
with single characters starting from the left to try and get
the path down to `max-len'"
(let* ((components (split-string (abbreviate-file-name path) "/"))
(len (+ (1- (length components))
(cl-reduce '+ components :key 'length)))
(str ""))
(while (and (> len max-len)
(cdr components))
(setq str (concat str (if (= 0 (length (car components)))
"/"
(string (elt (car components) 0) ?/)))
len (- len (1- (length (car components))))
components (cdr components)))
(concat str (cl-reduce (lambda (a b) (concat a "/" b)) components))))
(defun rjs-eshell-prompt-function ()
(concat (shortened-path (eshell/pwd) 30)
(if (= (user-uid) 0) " # " " $ ")))
(setq eshell-prompt-function 'rjs-eshell-prompt-function)
#+end_src
*** Persp-Eshell
Persp eshell ensures that there is at most one eshell buffer that can
be easily reache per "perspective" It depends on perspectives.
#+name: persp-eshell
#+begin_src elisp :results none
;; relies on the package 'perspective' from melpa
(defun persp-eshell--eshell-buffer-p (buffer)
(string-prefix-p "*eshell*" (buffer-name buffer)))
(defun persp-eshell--persp-eshell ()
(cl-find-if 'persp-eshell--eshell-buffer-p
(persp-buffers (persp-curr))))
(defun persp-eshell--get-next-eshell-n ()
(let ((n 0))
(while (get-buffer (format "*eshell*<%i>" n))
(cl-incf n))
n))
;; bind this to a key of your choice
(defun persp-eshell--jump-to-persp-eshell ()
(interactive)
(let ((buff (persp-eshell--persp-eshell)))
(if buff (switch-to-buffer-other-window buff)
(eshell (persp-eshell--get-next-eshell-n)))))
#+end_src
** Common Lisp
#+name: common-lisp-config
#+begin_src elisp :noweb no-export :results none
<>
<>
<>
<>
#+end_src
*** Packages
#+name: common-lisp-packages
#+begin_src elisp :results none
(package-install 'paredit)
(package-install 'slime)
(package-install 'slime-company)
#+end_src
*** Starting SLIME with different Lisps
#+name: common-lisp-switch-commands
#+begin_src elisp :results none
(defvar my-current-slime-name "sbcl")
(setq inferior-lisp-program "~/lisp/sbcl/current/bin/sbcl")
(defmacro start-slime-with (str name)
`(lambda ()
(interactive)
(setq inferior-lisp-program ,str)
(setq my-current-slime-name ,name)
(my-switch-to-slime)))
(defun slime-in-this-layout-p (name)
(cl-find-if (lambda (buffer)
(string-search (format "slime-repl %s" name)
(or (buffer-name buffer) "")))
(persp-buffers (persp-curr))))
(defun my-switch-to-slime ()
(interactive)
(let ((buff (slime-in-this-layout-p my-current-slime-name)))
(if buff (switch-to-buffer-other-window buff)
(slime))))
(def-my-command my-lisp-switch-command
`((?' "['] repl" my-switch-to-slime)
(?s "[s]bcl" ,(start-slime-with "~/lisp/sbcl/current/bin/sbcl" "sbcl"))
(?e "[e]cl" ,(start-slime-with "ecl" "ecl"))
(?c "[c]cl" ,(start-slime-with "~/lisp/ccl/lx86cl64" "ccl"))))
#+end_src
*** Lisp Mode Leader Key command
Requires installation of the hyperspec and cltl packages on debain
from debian contrib
: sudo apt install cltl hyperspec
#+name: common-lisp-mode-command
#+begin_src elisp :results none
(def-my-command my-lisp-mode-command
'((?' "['] open slime repl" my-switch-to-slime)
(?c "[c]ompile form" slime-compile-defun)
(?l "[l]oad file" slime-load-file)
(?< "[<] list callers" slime-list-callers)
(?> "[>] list callees" slime-list-callees)
(?d "[d]ocumentation" slime-documentation)
(?\t "[TAB] inspect-presentation" slime-inspect-presentation-at-point)
(?B "Open CLTL2 [B]ook" open-cltl2)
(?h "[h]yperspec lookup" hyperspec-lookup)))
(defun open-cltl2 ()
(interactive)
(eww "file:///usr/share/doc/cltl/clm/clm.html"))
(with-eval-after-load 'lisp-mode
(progn
(setq common-lisp-hyperspec-root "file:///usr/share/doc/hyperspec/")))
#+end_src
*** Editing Config
#+name: common-lisp-editing-config
#+begin_src elisp :results none
(slime-setup '(slime-fancy slime-company))
(setq slime-company-completion 'fuzzy
slime-company-after-completion 'slime-company-just-one-space)
(autoload 'enable-paredit-mode "paredit" "Turn on pseudo-structural editing of Lisp code." t)
(add-hook 'emacs-lisp-mode-hook #'enable-paredit-mode)
(add-hook 'eval-expression-minibuffer-setup-hook #'enable-paredit-mode)
(add-hook 'ielm-mode-hook #'enable-paredit-mode)
(add-hook 'lisp-mode-hook #'enable-paredit-mode)
(add-hook 'lisp-interaction-mode-hook #'enable-paredit-mode)
(add-hook 'scheme-mode-hook #'enable-paredit-mode)
(add-hook 'clojure-mode-hook #'paredit-mode)
(add-to-list 'auto-mode-alist (cons "\\.parenscript\\'" 'lisp-mode))
(add-to-list 'auto-mode-alist (cons "\\.lass\\'" 'lisp-mode))
(add-to-list 'auto-mode-alist (cons "\\.spinneret\\'" 'lisp-mode))
(defun space-for-delimiter-after-$-p (delimiter endp)
(not (char-equal ?$ (char-before (point)))))
(defun space-for-delimiter-after-@-p (delimiter endp)
(not (char-equal ?@ (char-before (point)))))
(defun space-for-delimiter-after-p-p (delimiter endp)
(not (char-equal ?P (char-before (point)))))
(setq paredit-space-for-delimiter-predicates
(list 'space-for-delimiter-after-$-p
'space-for-delimiter-after-@-p
'space-for-delimiter-after-p-p))
#+end_src
** Haxe
#+name: haxe-config
#+begin_src elisp :results none
(package-install 'battle-haxe)
(use-package haxe-mode
:mode ("\\.hx\\'" . haxe-mode)
:no-require t
:init
(require 'js)
(define-derived-mode haxe-mode js-mode "Haxe"
"Haxe syntax highlighting mode. This is simply using js-mode for now."))
(use-package battle-haxe
:hook (haxe-mode . battle-haxe-mode)
:bind (("M-," . #'pop-global-mark) ;To get back after visiting a definition
:map battle-haxe-mode-map
("M-." . #'battle-haxe-goto-definition)
("M-/" . #'battle-haxe-helm-find-references))
:custom
(battle-haxe-yasnippet-completion-expansion t "Keep this if you want yasnippet to expand completions when it's available.")
(battle-haxe-immediate-completion nil "Toggle this if you want to immediately trigger completion when typing '.' and other relevant prefixes."))
#+end_src
** Web Development
#+name: webdev-setup
#+begin_src elisp :results none
(package-install 'json-mode)
(package-install 'skewer-mode)
#+end_src
** WASM
#+name: wasm-setup
#+begin_src elisp :noweb no-export :results none
(if (not (file-exists-p "~/.emacs.d/wat-mode"))
(shell-command "git clone https://github.com/devonsparks/wat-mode ~/.emacs.d/wat-mode"))
(add-to-list 'load-path "~/.emacs.d/wat-mode")
(require 'wat-mode)
#+end_src
#+RESULTS: wasm-setup
: wat-mode
** CPP development
*** Language Server :prereq:
clangd is the language server, [[https://github.com/rizsotto/Bear][bear]] is "a tool that generates
a compilation database for clang tooling.
#+begin_src shell :noweb no-export
sudo apt install clangd bear
#+end_src
*** CPP IDE setup
#+name: cpp-ide
#+begin_src elisp :noweb no-export :results none
(mapc #'package-install
'(lsp-mode yasnippet flycheck dap-mode ivy-xref))
(add-hook 'c-mode-hook 'lsp)
(add-hook 'c++-mode-hook 'lsp)
(with-eval-after-load 'lsp-mode
(require 'dap-cpptools)
(yas-global-mode))
#+end_src
* Bells And Whistles
#+name: bells-and-whistles
#+begin_src elisp :noweb no-export :results none
<>
#+end_src
** Lifecoach
A few functions to start a process where, periodically, motivational
messages echo to the echo area.
#+name: lifecoach
#+begin_src elisp :noweb no-export :results none
(setq lifecoach-messages
'(
"You are the only hope you have! Keep working!"
"You get hack on stuff you thought up... Keep going!"
"You don't have to be working a real job! Enjoy this!"
"Trust the process. Act and React!"
"Resistence points in the direction of courage. Step into courage!"
"There is one path in the world that non can walk but you. Where does it lead? Don't ask, Walk!"
"Get it done. Then start the next one!"
"Interact! Hack forward!"
"Money would be nice. Thinking about it wont help. Ship!"
"This is your work. Love it!"
"What if it works? Don't give up!"
"Dont play the finite games. Keep making moves!"
"There is no escape from now. Be free here. Love the task!"
"Be Tosk! Challenge the hunter! Surprise him. Delight him."
"Expect anything worthwhile to take a long time. This is worth it!"
"To know what you're going to draw, you must begin drawing!"
"Fire and motion. Move forward a little each day."
"Enthusiasm at the price of reinventing the wheel pays for itself."
"This is really happening. This is reality. Create More of The Real!"
"Allow yourself the uncomfortable luxury of changing your mind."
"Do nothing for prestige or status or money or approval alone."
"When people try to tell you who you are, don’t believe them."
"Presence is far more intricate and rewarding an art than productivity."
"Follow Your Wierd"
"Do you. -- Charlie Kauffman"
"Prefer to work on things you can own"
"Beauty rests on necessities"
"Every day we see people who are busy distorting their talents in order to enhance their popularity or to make money that they could do without."
"Problems worthy of attack prove their worth by fighting back"
"To work continuously at the highest level a person needs to be challenged continuously."
"Difficulty is an essential element in the creative process."
"There's a million races being run. You just got to get in one of them and win"
"To invent your own life's meaning is not easy, but it's still allowed, and I think you'll be happier for the trouble"
"Ever tried. Ever failed. No matter. Try Again. Fail again. Fail better"
"Welcome the accidents."
"Occassion that invites no accidents invites nothing and need not occur, for everything is known already."
"What is the harder thing? Why is it harder?"
"What does the perfectionist want? And the artist?"
"What are you doing right now? What do you want one year from now?"
"Which impulse is the saboteur?"
"Is your exahaustion real?"
"Don't be ashamed of the carrot - what is the carrot?"
"Who benefits when you do?"
"How committed do you feel? Where's the evidence?"
"Why do you resist?"
"What exactly are your 'core values'?"
"What captures your attention? Is your attention ever rewarded?"
"What is an ideal future?"
"Can you work another ten minutes?"
"Do you understand the why?"
))
(setq lifecoach-idle-timer nil)
(defun lifecoach-message ()
(message
"Lifecoach says: %s"
(nth (random (length lifecoach-messages))
lifecoach-messages)))
(defun lifecoach-start ()
(interactive)
(when lifecoach-idle-timer
(cancel-timer lifecoach-idle-timer))
(setf lifecoach-idle-timer
(run-with-idle-timer 30 t #'lifecoach-message)))
(defun lifecoach-stop ()
(interactive)
(when lifecoach-idle-timer
(cancel-timer lifecoach-idle-timer))
(setf lifecoach-idle-timer nil))
#+end_src
* Overwrites
#+name: overwrites
#+begin_src elisp :noweb no-export :results none
(setq-default cursor-type 'box)
(setq cursor-type 'box)
#+end_src