Emacs.org ~ May 2019
Coding Your Comments
When I decided to make the switch to rolling my own ~/.emacs.d directory, I knew that I was going to end up seeing a lot of new code. First, I've never set up emacs before, so there will be lots of new packages to learn and things like that. Second, I've never really used a Lisp before, so there would be lots of new things to learn there as well. I knew I needed a way to document all the stuff I was learning as I set this up. This was especially true since I would be learning which setup worked for me as I went.
One of the appeals of Emacs from the beginning was org-mode. And one of the appeals of org-mode is org-babel and Literate Programming. Literate Programming, much like Emacs, is nothing new. The basic premise of LP is that you write a single document which is both your documentation and your code. Then, you can "tangle" out the code to create the program or you can "weave" out the documentation. Org-mode is seemingly custom-built for this.
Emacs.org
Here's how I have set this up.
- I have created a git repository called dotfiles, hosted to bitbucket.
- I created a file called
emacs.org
in the repo. - I outline my init.el file in
emacs.org
, just like I would any other orgmode document. - I use
#+begin_src elisp
blocks to hold the actual configuration. - I use the command
C-c C-v t
to tangle the blocks out into my ~/.emacs.d/init.el file.
All tangling is controlled by a :PROPERTIES: drawer on the topmost header containing the following line: :header-args: :tangle ~/.emacs.d/init.el
This line causes all SRC blocks to tangle to that file.
Notes on This Iteration
I am sharing this emacs config knowing full well that it is broken in several places.
Fixing the places it is broken is one of the main impetuses for doing this project.
I have indicated the places where I know it to be broken, but there may be places where I don't know it is broken.
If you see one of those, please let me know.
Overall, use this file at your own risk as not all of it is tested and some of it is definitely broken.
Without further ado, here is my emacs.org
file as it stands on 29 May 2019.
Emacs
This file contains the source for my emacs config, which is then generated into my ~/.emacs.d directory via org-babel. This inspration for this setup is this dotfile which I found while searching about creating a literate emacs config. I realized with just a little bit of work, I could put all my dotfiles in a single org file. I'm not sure a single org file is practical, and right now I have zsh split out into its own file. Emacs is my main editor and the initial test case for making this work. There will be zero comments in my init.el file.
Initial Setup
Debugging essentials. This turns debugging on to begin with. That way, if something breaks during init, I get dumped into a debugger and can try to fix it. I switch it back off at the end.
(setq debug-on-error t) (setq debug-on-quit t)
This sets up all the things needed for all the subsequent things.
Specifically, the package
and use-package
packages.
I have also added the code used to track loading time.
(defconst emacs-start-time (current-time)) (require 'package) (setq package-enable-at-startup nil) (setq package-archives '(("org" . "http://orgmode.org/elpa/") ("gnu" . "http://elpa.gnu.org/packages/") ("melpa" . "http://melpa.org/packages/"))) (package-initialize) (unless (package-installed-p 'use-package) (package-refresh-contents) (package-install 'use-package)) (require 'use-package) (setq use-package-always-ensure t) (let ((elapsed (float-time (time-subtract (current-time) emacs-start-time)))) (message "Loaded packages in %.3fs" elapsed)) (setq gc-cons-threshold 100000)
Setup user info. The setenv here is meant to try to fix an issue described in more detail under the exec-path-from-shell header.
(setq user-full-name "Jonathan Bennett" user-mail-address "doulos05@gmail.com") (setenv "SHELL" "/usr/local/bin/zsh")
Alarm Bell
Replace audible alarms with a visual bell.
(setq ring-bell-function (lambda () (let ((orig-fg (face-foreground 'mode-line))) (set-face-foreground 'mode-line "#F2804F") (run-with-idle-timer 0.1 nil (lambda (fg) (set-face-foreground 'mode-line fg)) orig-fg))))
EVIL Mode
Enable Vim and modal editing. This is the area I expect to change and grow the most as I add new evil keybindings.
(use-package evil :init (setq evil-want-integration t) (setq evil-want-keybinding nil) :config (use-package evil-leader) (use-package evil-surround :config (global-evil-surround-mode)) (use-package evil-indent-textobject)) (global-evil-leader-mode 1) (setq evil-leader/leader "<SPC>") (evil-leader/set-key "e" 'helm-find-files "b" 'helm-buffers-list "k" 'kill-buffer "K" 'kill-this-buffer "j" 'org-journal-new-entry) (evil-mode 1)
Exec-path-from-shell
As part of their ongoing war against developers, the Captains of industry in Cupertino have designed Macs so that GUI Emacs only ever reads environment variables set for the system shell.
This is obviously user hostile behavior since their system shell (bash) is from 2007.
This package is designed to work around this.
This quit working when I switched from the Homebrew Emacs install to the Emacs for Mac OSX version.
The cause was that the new version sets the variable shell-file-name
whereas the Homebrew version did not.
This new code sets the variable explicitly to my shell.
This fixes numerous bugs I was having connected to not being able to find my environment variables.
(use-package exec-path-from-shell :ensure t :init (if (string-equal system-type "darwin") (setq shell-file-name "/usr/local/bin/zsh") (setq exec-path-from-shell-variables '("PATH" "MANPATH" "PKG_CONFIG_PATH")) (exec-path-from-shell-initialize)))
Helm
Helm is the searching framework that I use. The primary reason I use this over Ido is because its what Spacemacs uses, so that's what I got used to. Much of the configuration for Helm comes from this Self-rolled Spacemacs init.el.
(use-package helm :init (setq helm-split-window-default-side 'other) (helm-mode 1) :config (define-key helm-find-files-map (kbd "<backtab>") #'helm-select-action) (define-key helm-find-files-map (kbd "C-i") #'helm-execute-persistent-action) :bind (("M-x" . helm-M-x) ("M-y" . helm-show-kill-ring) ("C-x C-f" . helm-find-files) ("C-c o" . helm-occur) ("C-x b" . helm-mini) ("C-x r b" . helm-bookmarks) ("C-h a" . helm-apropos) ("C-h d" . helm-info-at-point) ("C-c L" . helm-locate) ("C-c r" . helm-resume) ("C-c i" . helm-imenu)))
Projectile
Projectile is a project management tool. I'll need it to replace the fancy parts of PyCharm. I'm still working on expanding my use of Projectile. This will almost certainly be the focus of one or more of my weeks during the Year of Emacs.
(use-package projectile :config (projectile-mode t))
Yasnippet
Yasnippet does snippets and completion. Another section ripe for growth. I plan to expand this dramatically once I explore Yasnippets in more detail during the Year of Emacs.
(use-package yasnippet ; Snippets :ensure t :config (setq yas-verbosity 1) ; No need to be so verbose (setq yas-wrap-around-region t) (setq yas-snippet-dirs (append yas-snippet-dirs '("~/dotfiles/yasnippets"))) (yas-reload-all) (yas-global-mode)) (use-package yasnippet-snippets ; Collection of snippets :ensure t)
DONE Company
Company is the auto-completion framework that I use. It isn't really fully configured because of an issue I'm currently having with Pyenv and Emacs.
(use-package company :ensure t :defer t :diminish (company-mode . " ⓐ") :init (global-company-mode) :config (setq company-tooltip-align-annotations t company-idle-delay 0.2 ;; min prefix of 2 chars company-minimum-prefix-length 2 company-require-match nil)) (use-package company-quickhelp ; Show help in tooltip :ensure t :defer t :init (with-eval-after-load 'company (company-quickhelp-mode))) (use-package company-jedi :ensure t :defer t :init (defun enable-jedi() (setq-local company-backends (append '(company-jedi) company-backends))) (with-eval-after-load 'company (add-hook 'python-mode-hook 'enable-jedi)))
Python
This install the tools I use for Python Programming and configures my Python buffers.
elpy
Elpy is an expansion of the default Python mode. This will see significant expansion during my weeks on Python programming in Emacs.
(use-package elpy :config (elpy-enable))
DONE Pyenv-mode
Pyenv-mode makes elpy pyenv-aware. Unfortunately, right now it isn't working because my Emacs refuses to find the dotfiles for zsh, only for the system install of Bash.
(use-package pyenv-mode :config (pyenv-mode))
Org-mode
Org-mode is the thing that brought me to Emacs. There are a lot of customizations here.
Org QoL
This handles the Quality of life part of Org-mode. First, org-bullets beautifies the leading asterisks. Then, we hide the extra asterisks. Finally, we set the global shortcuts for org-store-link, org-agenda, and org-capture.
(use-package org-bullets :config (add-hook 'org-mode-hook (lambda () (org-bullets-mode t)))) (setq org-hide-leading-stars t) (global-set-key (kbd "C-c l") 'org-store-link) (global-set-key (kbd "C-c a") 'org-agenda) (global-set-key (kbd "C-c c") 'org-capture) (add-hook 'org-mode-hook 'org-indent-mode)
Source Editing
These settings beautify the SRC blocks in Org-mode documents by adding syntax highlighting. Essential for how I'm doing my dotfiles.
(setq org-src-fontify-natively t)
Org Babel
Org Babel is what does the tangling of source blocks into separate programs. For now, this just sets our language list.
(org-babel-do-load-languages 'org-babel-load-languages '((python . t) (emacs-lisp . t) (shell . t) (latex . t) (sql . t)))
These settings prevent the conversion of spaces into tabs (necessary for Python code exports)
(setq org-src-preserve-indentation t
org-edit-src-content-indentation t)
Academic Paper Writing
Here are the settings I have used for writing academic papers. I write my papers in orgmode, then export them to PDF via LaTeX. This is one of the most fleshed out areas of my dotfiles, in large part because 90% of my Emacs time for the last 6 months has been related to my Master's Thesis in some way.
This sets the master bibtex file.
(use-package helm-bibtex :config (setq helm-bibtex-bibliography '("~/zotero.bib")) (add-hook 'Tex-mode-hook (lambda () (define-key Tex-mode-map "\C-ch" 'helm-bibtex)))) (setq reftex-default-bibliography '("~/zotero.bib")) (setq bibtex-completion-pdf-field "file") (setq helm-bibtex-notes-path "~/nextcloud/org/debugging/litreview.org")
I use org-ref to manage my citations in my papers. This is the section for the support and configuration for org-ref.
(use-package org-ref :config (setq org-ref-bibiliography-notes "~/nextcloud/org/debugging/litreview.org") (setq org-ref-default-bibliography "~/zotero.bib"))
This block corrects the way that the TOC is displayed. It is SUPER important for the apa6 class that follows. APA6 has very strong opinions about how the TOC should be displayed, opinions that conflict directly with the default settings for exporting from orgmode.
(defun org-export-latex-no-toc (depth) (when depth (format "%% Org-mode is exporting headings to %s levels.\n" depth))) (setq org-export-latex-format-toc-function 'org-export-latex-no-toc)
Add apa6 to the org-latex-classes export for writing academic papers in APA6 format.
(add-to-list 'org-latex-classes '("apa6" "\\documentclass{apa6}" ("\\section{%s}" . "\\section*{%s}") ("\\subsection{%s}" . "\\subsection*{%s}") ("\\subsubsection{%s}" . "\\subsubsection*{%s}") ("\\paragraph{%s}" . "\\paragraph*{%s}") ("\\subparagraph{%s}" . "\\subparagraph*{%s}")))
This describes the export process from orgmode to LaTeX to PDF.
(setq org-latex-pdf-process '("latexmk -pdflatex='pdflatex -interaction nonstopmode' -pdf -bibtex -f %f")) (use-package ox-pandoc)
DONE PDF-tools
Linux Install
The shell block below installs the libraries needed to run this on Linux. There is another workflow you have to use on MacOS, but I have not gotten it to work yet
sudo apt install libpng-dev zlib1g-dev sudo apt install lib-poppler-glib-dev sudo apt install libpoppler-private-dev sudo apt install imagemagick
MacOS Install
If anybody knows how to do this and have it work... So far, emacs cannot find libffi despite it being added to several different paths that it should be able to see.
PDF-tools config
PDF-tools allows me to annotate and view pdfs INSIDE emacs. This ties in with helm-bibtex for lit reviews. It's super awesome when it works, but thanks to Apple....
(if (string-equal system-type "darwin") (setenv "pkg_config_path" (concat "/usr/local/Cellar/zlib/1.2.8/lib/pkgconfig" ":" "/usr/local/lib/pkgconfig:/opt/X11/lib/pkgconfig" (getenv "pkg_config_path")))) (use-package pdf-tools :pin manual ;; manually update :config ;; initialise (pdf-tools-install) ;; open pdfs scaled to fit page (setq-default pdf-view-display-size 'fit-page) ;; automatically annotate highlights (setq pdf-annot-activate-created-annotations t) ;; use normal isearch (define-key pdf-view-mode-map (kbd "C-s") 'isearch-forward))
Agenda Settings
I use org-journal for taking Notes during the day as part of the Agile Results methodology.
(use-package org-journal :init (setq org-journal-dir "~/nextcloud/org/journal") (setq org-journal-file-format "%Y%m%d.org") :config (setq org-journal-date-prefix "#+TITLE: Daily Note for ")) (org-journal-update-auto-mode-alist)
This sets up org-agenda. I use org-agenda to track my schedule, my todos, and my upcoming tasks.
(load-library "find-lisp") (setq org-agenda-files (find-lisp-find-files "~/nextcloud/org" "\\.org$")) (setq org-log-done t) (setq org-agenda-start-day "-1d") (setq org-agenda-span 8) (setq org-agenda-start-on-weekday nil) (setq org-deadline-warning-days 31) (setq org-agenda-tags-width -70)
This function disables line numbers in the org-agenda view. This is necessary so that tags don't overflow into the next line.
(defun my/disable-line-numbers (&rest __) (display-line-numbers-mode -1)) (add-hook 'org-agenda-finalize-hook 'my/disable-line-numbers)
Org-capture
Setup for org-capture. I currently am only using a todo capture, but I will be adding captures for behavior and class notes over the summer.
(setq org-default-notes-file (concat org-directory "~/org/gtd.org")) (setq org-capture-templates '(("t" "Todo" entry (file+headline "~/nextcloud/org/gtd.org" "Tasks") "* TODO %?\n %i\n %a")))
Org2Web
I use org2web to publish my Github Pages account. This configuration will need to be tweaked as I am aware of at least a few issues with how the page is displaying.
(use-package org2web :config (org2web-add-project '("jonathanabennett.github.io" :repository-directory "~/nextcloud/org/blog/" :remote (git "git@github.com:jonathanabennett/jonathanabennett.github.io.git" "master") :site-domain "https://jonathanabennett.github.io/" :site-main-title "Jonathan Bennett's Blog" :site-sub-title "Emacs, Python, and Education" :theme (worg) :source-browse-url ("Github" "https://jonathanabennett/jonathanabennett.github.io.git"))))
Dash
Copied from Sacha Chua's dotfile. This looks like it isn't relevant for me because focused on elisp. I've dropped this header here as a note in case I need it later.
Winner
Copied from Sacha Chua's dotfile. I don't understand what this does yet so I haven't added it. But it is on my list of things to research in Emacs.
Which-key
Which-key tells you what keys can complete the chord you have started. This is an essential package when you're learning Emacs. It should be in the init.el of every beginner.
(use-package which-key :ensure t :init (setq which-key-separator " ") (setq which-key-prefix-prefix "+") :config (which-key-mode))
Theme
Currently using Dracula, but this is where it would get changed.
(use-package dracula-theme :init (load-theme 'dracula t))
ERC
I use ERC to chat.
(eval-after-load "erc" '(progn (setq erc-nick "doulos05") (setq erc-user-full-name "Jonathan Bennett") (setq erc-autojoin-channels-alist '(("irc.freenode.net" "#python"))))) (defun my-erc () (interactive) (erc-tls :server "irc.freenode.net" :port 7000))
Magit
Magit is git in Emacs.
Magit is AMAZING.
Even more amazing to me is the fact that this package adds so much value to my life with just a single line in my init.el
file.
It will be interesting to see how much this section changes when I come to it during the Year of Emacs posts.
(use-package magit)
Misc
Here are miscellaneous configurations
Backup File management
I use git for backup of all my text files. I don't need backup files from emacs, they just clutter the space. This removes all backup files.
(setq make-backup-files nil) (setq auto-save-default nil) (setq create-lockfiles nil)
Editing QOL
Turn on matching parens highlighting.
(show-paren-mode 1)
Sentences end with a single space.
(setq sentence-end-double-space nil)
Scrolling is smoother and I can scroll with the mouse if I need to.
(setq scroll-step 1) (setq mouse-wheel-scroll-amount '(1 ((shift) . 1))) (setq mouse-wheel-progressive-speed nil) (setq mouse-wheel-follow-mouse 't) (setq redisplay-dont-pause t)
Turn on line wrapping everywhere.
(global-visual-line-mode 1)
When on a modern Emacs, turn on line numbers everywhere.
(when (version<= "26.0.50" emacs-version ) (global-display-line-numbers-mode))
Where to find aspell on a Mac, I need to modify this so that it points to the right place on Linux. But I'm not using Linux right now, so I don't have that path offhand.
(setq ispell-program-name "/usr/local/bin/aspell")
Wrapup
Unset debugging mode and print how long it took to launch
(setq debug-on-error nil) (setq debug-on-quit nil) (let ((elapsed (float-time (time-subtract (current-time) emacs-start-time)))) (message "Loading settings...done (%.3fs)" elapsed)) (put 'narrow-to-region 'disabled nil)