Beckwith Tangled Emacs Initialization
Table of Contents
- 1. Installation
- 2. Notes
- 3. Personal Information
- 4. Local customizations (custom.el)
- 5. Small Settings
- 5.1. Package archives
- 5.2. Binding Keys
- 5.3. Path
- 5.4. Backups
- 5.5. Super keys
- 5.6. Hydra
- 5.7. Delight
- 5.8. Personal Keymaps
- 5.9. Minibuffer History
- 5.10. Abbrev
- 5.11. Hippie Expand
- 5.12. Emacs Bookmarks
- 5.13. Writegood Mode
- 5.14. Spell Checking
- 5.15. Proselint
- 5.16. Development
- 5.17. Read-only helpers
- 5.18. Default File encoding
- 5.19. Ediff single frame
- 5.20. Git
- 5.21. Open/Edit This file
- 5.22. Sounds
- 5.23. Midnight Mode
- 5.24. Which Key
- 5.25. Ace Utilities
- 5.26. Edit Server
- 5.27. Regexp-Builder
- 5.28. IBuffer
- 5.29. Multiple Cursors
- 5.30. Expand Region
- 5.31. Hooks
- 5.32. Recentf
- 5.33. Executable Scripts on save
- 5.34. Scroll Screen Position
- 5.35. Unique Buffer Names
- 5.36. Focus Mode
- 5.37. Relative line numbers
- 5.38. ImageMagick
- 5.39. PDF Tools
- 5.40. Helpful
- 5.41. All the icons
- 5.42. Discover my mode
- 5.43. Easy Kill
- 5.44. Undo Tree
- 5.45. Adaptive Fill
- 6. Style
- 7. BNB Helpers
- 8. Auto-completion
- 9. File Management
- 10. Smart Tabs
- 11. CUA mode
- 12. Paredit
- 13. Paxedit
- 14. Projectile
- 15. Programming Languages
- 16. Selectrum
- 17. Shells
- 18. AucTeX
- 19. Markdown
- 20. Orgmode
- 20.1. Orgmode Initialization
- 20.2. Auto mode
- 20.3. Hooks
- 20.4. Keys
- 20.5. Org TODO Configuration
- 20.6. Capture
- 20.7. Refile
- 20.8. Agenda
- 20.9. Export
- 20.10. Clocking
- 20.11. Modules
- 20.12. Babel
- 20.13. Miscellaneous Settings
- 20.14. Pretty Org-mode
- 20.15. Org Repo Todo PENDING
- 20.16. Org projectile PENDING
- 20.17. Org Ref
- 20.18. Org Noter
- 20.19. Org Roam
- 20.20. Org QL
- 21. Calc
- 22. Server
- 23. Local customizations (custom.el)
- 24. Local customizations (user-login-name)
This document tangles (in literate programming style) the necessary commands to initialize Emacs to my liking and the documentation for my choices.
To clone, go to the github repository. For a pretty view, head over to the generated page.
1 Installation
My init.el
file is quite simple and is generated by the following
block. Essentially, I just have to install this package
(bnb-emacs
) in the ~/.emacs.d/
directory and run the following
code block (C-c C-c
) to bootstrap the system.
;;; init.el --- bnbeckwith config -*- eval: (read-only-mode 1) -*- (require 'package) (setq package-enable-at-startup nil) (package-initialize) (require 'ob-tangle) (org-babel-load-file "~/.emacs.d/bnb-emacs/Readme.org")
From there on, the bootstrapping is simple. Emacs finds
~/.emacs.d/init.el
and runs the code. The first step is to
initialize the packages I have installed via ELPA and others.
Next, I load ob-tangle
(part of org-mode
). Then
org-babel-load-file
extracts the emacs-lisp code blocks in this
document and loads the resulting Readme.org
.
As I add packages or lines to this document, my initialization is already in place and ready to go.
If you are reading this online, the html version of this file is generated by using `bnb/export-readme` explained in Styled HTML Export.
2 Notes
This section has specific notes that are relevant to my emacs setup in general and this document in particular.
2.1 Emacs Build
My current flavor of Emacs comes from: https://github.com/d12frosted/homebrew-emacs-plus
2.2 Pending sections
There are some features that I like to take on a trial run. These are marked with the PENDING tag to help me remember and evaluate.
2.3 Performance
By utilizing elements of use-package
, I can keep an eye on
troublesome packages during startup. Together, these turn on
reporting and set the minimum time to consider when building the
report.
(setq use-package-verbose t
use-package-compute-statistics t
use-package-minimum-reported-time 0)
The generated messages will be found in the *Messsages*
buffer.
3 Personal Information
The full name is used for email messages.
(setq user-full-name "Benjamin Beckwith")
4 Local customizations (custom.el)
I typically use the customize interface to generate any local settings such as proxies, paths, fonts, etc. that may vary from machine to machine. This keeps the setup the same and allows for only some details to differ.
I like to set the custom file explicitly. Mine resides in the
~/.emacs.d/
directory. This code block loads it if it exists.
(setq custom-file "~/.emacs.d/custom.el") (if (file-exists-p custom-file) (load-file custom-file)) (with-eval-after-load "bind-key" (bind-key "<f7>" (lambda () (interactive (find-file custom-file)))))
If the file doesn't exist, Emacs
will still use the file if any
changes are made through the custom interface.
Sometimes I'll get bad settings or cruft in that file. I now have a
key, <F7>
, for easy navigation to wherever the custom-file
points.
5 Small Settings
The next sections encompass some small settings to make Emacs mine (and maybe yours). There is a loose order of dependency, but even then it isn't strict.
5.1 Package archives
I like to pull from the popular list of package archives.
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
I install the packages with these repositories. This may take some time the first time it runs.
Once the repositories are defined, it's time to bootstrap the
package system and use-package
in general since I use it
everywhere.
(unless (package-installed-p 'use-package) (package-refresh-contents) (package-install 'use-package)) (setq use-package-verbose t use-package-always-ensure nil) (require 'use-package)
5.1.1 From Source
Quelpa grabs and builds packages from source (e.g. Github). I have found a few things not in any package archive yet that I'd like to have automatically installed.
Along with the quelpa
package, quelpa-use-package
adds a
handler to use-package
making it fit in nicely with the rest of
my configuration.
(use-package quelpa) (use-package quelpa-use-package :ensure t) ;; Handle the `use-package-always-ensure' setting (quelpa-use-package-activate-advice)
5.1.2 Load the latest files
Always pick the latest version of the library to load.
(setq load-prefer-newer t)
5.1.3 Paradox
The paradox interface offers a few enhancements over the included
package
package. It adds github stars in the package listing,
performs autoremoval of packages, and installs packages in parallel.
(use-package paradox :ensure t :delight " ፨" :commands (paradox-list-packages))
5.2 Binding Keys
For binding keys, I use the bind-key
package. Not only does it
easily bind keys, but it does so with some nice features.
(use-package bind-key :bind ("C-h B" . describe-personal-keybindings))
By using bind-key
, you can specify the keystrokes that invoke a
command. This is regular behavior that you can already achieve in
Emacs and will result in a global binding.
If you also want to override any possible minor-mode bindings of
the same keys, you can use bind-key*
instead.
There is also an unbind-key
to, of course, remove any binding.
The real kicker is that it will keep track of these bindings and let you see a summary of your customizations with
M-x describe-personal-keybindings
This is bound to C-h B
above.
5.3 Path
Sometimes Emacs' idea of path differs from the shell. The package
exec-path-from-shell
seeks to bring those in line with each other.
(use-package exec-path-from-shell :ensure t :config (exec-path-from-shell-initialize))
5.4 Backups
Sensible backup settings from https://www.emacswiki.org/emacs/BackupDirectory
(setq backup-by-copying t create-lockfiles nil backup-directory-alist '((".*" . "~/.saves")) ;; auto-save-file-name-transforms `((".*" "~/.saves" t)) delete-old-versions t kept-new-versions 6 kept-old-versions 2 version-control t)
Here's a quick rundown of the settings:
backup-by-copying
- Use copying to create backups when
t
create-lockfiles
- Don't use lockfiles if
nil
backup-directory-alist
- List of regexp/location pairs of where to backup files
auto-save-file-name-transforms
- Transform file names before autosave
delete-old-versions
- Delete excess backups silently if
t
kept-new-versions
- Number of newest versions to keep
kept-old-versions
- Number of oldest versions to keep
version-control
- When
t
, make numeric backup versions always
5.5 Super keys
I like to be able to use the command (or super or hyper) keys for shortcuts. I need to take care to not interfere with the built-in shortcuts or my bindings will not work.
(setq mac-function-modifier 'hyper
mac-pass-command-to-system nil
mac-right-option-modifier 'super
mac-right-command-modifier 'super
mac-right-control-modifier 'hyper
mac-command-modifier 'meta
mac-control-modifier 'ctrl
mac-option-modifier 'none)
Note that the right option
and command
keys will pass through
to the system. This is especially cool for the option
key on a
mac that lets insert special characters directly. (E.g. á or ∑ or
®)
Inspiration for the keys comes from wisdom and wonder.
5.6 Hydra
Sometimes it is useful to go into a command mode that lets you quickly do a few different actions. Hydra does that and more.
By defining specific hydras, you can group together commands with documentation. Think of it as a mini-control-panel. I include it here and use it elsewhere when grouping commands. (See 5.8.1 for an example)
(use-package hydra :ensure t)
5.7 Delight
The mode line can get pretty busy showing all of the package
names. delight
helps tone it down by removing some packages from
showing up, or changing their name to something shorter.
(use-package delight :ensure t)
5.8 Personal Keymaps
These are inspired from http://endlessparentheses.com/the-toggle-map-and-wizardry.html.
5.8.1 Toggle Map
This toggle map shows the current toggleable settings with
shortcut keys for enabling. The amaranth color makes this buffer
stay around until I press q
.
(defmacro toggle-setting-string (setting) `(if (and (boundp ',setting) ,setting) '[x] '[_])) (bind-key "C-x t" (defhydra hydra-toggle (:color amaranth) " _c_ column-number : %(toggle-setting-string column-number-mode) _b_ orgtbl-mode : %(toggle-setting-string orgtbl-mode) _x_/_X_ trans : %(identity bnb/transparency) _e_ debug-on-error: %(toggle-setting-string debug-on-error) _s_ orgstruct-mode : %(toggle-setting-string orgstruct-mode) _m_ hide mode-line : %(toggle-setting-string bnb/hide-mode-line-mode) _u_ debug-on-quit : %(toggle-setting-string debug-on-quit) _h_ diff-hl-mode : %(toggle-setting-string diff-hl-mode) _f_ auto-fill : %(toggle-setting-string auto-fill-function) _B_ battery-mode : %(toggle-setting-string display-battery-mode) _t_ truncate-lines: %(toggle-setting-string truncate-lines) _l_ highlight-line : %(toggle-setting-string hl-line-mode) _r_ read-only : %(toggle-setting-string buffer-read-only) _n_ line-numbers : %(toggle-setting-string linum-mode) _w_ whitespace : %(toggle-setting-string whitespace-mode) _N_ relative lines : %(if (eq linum-format 'linum-relative) '[x] '[_]) " ("c" column-number-mode nil) ("e" toggle-debug-on-error nil) ("u" toggle-debug-on-quit nil) ("f" auto-fill-mode nil) ("t" toggle-truncate-lines nil) ("r" dired-toggle-read-only nil) ("w" whitespace-mode nil) ("b" orgtbl-mode nil) ("s" orgstruct-mode nil) ("x" bnb/transparency-next nil) ("B" display-battery-mode nil) ("X" bnb/transparency-previous nil) ("h" diff-hl-mode nil) ("l" hl-line-mode nil) ("n" linum-mode nil) ("N" linum-relative-toggle nil) ("m" bnb/hide-mode-line-mode nil) ("q" nil)))
5.8.2 Elisp Maps
Here are some nice-to-have features when in elisp-mode.
(bind-key "C-c e" (defhydra hydra-elisp-cmds (:color blue) ("b" eval-buffer "eval buffer") ("e" toggle-debug-on-error "debug-on-error") ("f" emacs-lisp-byte-compile-and-load "byte-compile-and-load") ("r" eval-region "eval-region") ("q" nil)) emacs-lisp-mode-map)
There is one block for execuing items and another for looking up
specific elisp
help.
(bind-key "C-h e" (defhydra hydra-elisp-help (:color blue) ("e" view-echo-area-messages "view-echod-area-messages") ("f" find-function "find-function") ("k" find-function-on-key "find-function-on-key") ("l" find-library "find-library") ("v" find-variable "find-variable") ("V" apropos-value "apropos-value") ("i" info-display-manual "info-display-manual") ("q" nil)) emacs-lisp-mode-map)
5.8.3 Small bindings
This sections contains smaller bindings (or overrides) that I use to customize functionality.
- Whitespace
Handle the emptiness without staring too long into the void.
- Whitespace Mode
A little setup for
whitespace-mode
to diminish the mode and cleanup on save.(use-package whitespace :ensure nil :config (setq whitespace-line-column nil) :hook (before-save . whitespace-cleanup) :delight whitespace-mode)
- Deletion
By default,
M-\
performsdelete-horizontal-space
and will consume all of the whitespace present.I'd like it to be smart and leave one or no spaces if possible. The
fixup-whitespace
function will do that.(bind-key "M-k" 'fixup-whitespace)
- Whitespace Mode
- Scroll window up/down
In addition to moving the cursor, it is also interesting to scroll the screen (without moving the cursor with respect to the frame).
(defun bnb/scroll-up-1 () "Scroll up by one line." (interactive) (cua-scroll-up 1)) (defun bnb/scroll-down-1 () "Scroll down by one line." (interactive) (cua-scroll-down 1)) (bind-keys ("M-n" . bnb/scroll-up-1) ("M-p" . bnb/scroll-down-1))
- Align Regexp
When selecting a region, a quick trip to
align-regexp
can align all of that nasty text.(bind-key "C-c TAB" 'align-regexp)
5.8.4 Kill current buffer
Another great tip from Pragmatic Emacs, use kill-this-buffer
to
kill the current buffer instead of asking which one. I'm not
overriding the C-x k
default, but added a C-x C-k
alternative.
(defun bnb/kill-this-buffer () "Kill the current buffer" (interactive) (kill-buffer (current-buffer))) (bind-keys ("C-x C-k" . bnb/kill-this-buffer))
5.9 Minibuffer History
Let's get rid of duplicates in the minibuffer history.
(setq history-delete-duplicates t)
This saves the minibuffer histories to preserve across emacs sessions.
(setq savehist-additional-variables '(search-ring regexp-search-ring) savehist-file "~/.emacs.d/savehist") (savehist-mode t)
5.10 Abbrev
The following block is courtesy of Endless Parentheses.
(bind-key "C-x C-i" 'bnb/ispell-word-then-abbrev) (defun bnb/ispell-word-then-abbrev (p) "Call `ispell-word'. Then create an abbrev for the correction made. With prefix P, create local abbrev. Otherwise, it will be global." (interactive "P") (let ((bef (downcase (or (thing-at-point 'word) ""))) aft) (call-interactively 'ispell-word) (setq aft (downcase (or (thing-at-point 'word) ""))) (unless (string= aft bef) (message "\"%s\" now expands to \"%s\" %sally" bef aft (if p "loc" "glob")) (define-abbrev (if p global-abbrev-table local-abbrev-table) bef aft)))) (use-package abbrev :delight " ⚆" :config (setq save-abbrevs t) (setq-default abbrev-mode t))
5.11 Hippie Expand
Try to expand the text before point in an intelligent way. Repeat the keypress to cycle through options.
(bind-key "M-/" 'hippie-expand)
5.12 Emacs Bookmarks
http://emacswiki.org/emacs/BookMarks
Keystroke | Action |
---|---|
C-x r m |
Set a bookmark |
C-x r b |
Jump to a bookmark |
C-x r l |
List your bookmarks |
M-x bookmark-delete |
Delete bookmark by name |
I will auto-save my bookmarks.
(setq bookmark-save-flag t)
5.13 Writegood Mode
This mode installs through the ELPA system.
(use-package writegood-mode :ensure t :bind ("C-c g" . writegood-mode) ("C-c C-g g" . writegood-grade-level) ("C-c C-g e" . writegood-reading-ease))
5.14 Spell Checking
This site has an interesting suggestion on how to use aspell
for
CamelCase spell checking.
(cond ((executable-find "aspell") (setq ispell-program-name (executable-find "aspell") ispell-extra-args '("--sug-mode=ultra" "--lang=en_US"))) (t (setq ispell-program-name nil) (message "No aspell found!"))) (bind-key "H-$" 'ispell-word)
5.15 Proselint
(with-eval-after-load "flycheck-mode" (flycheck-define-checker proselint "A linter for prose" :command ("proselint" source-inplace) :error-patterns ((warning line-start (file-name) ":" line ":" column ": " (id (one-or-more (not (any " ")))) (message (one-or-more not-newline) (zero-or-more "\n" (any " ") (one-or-more not-newline))) line-end)) :modes (text-mode markdown-mode gfm-mode org-mode)) (add-to-list 'flycheck-checkers 'proselint))
5.16 Development
For any lisp development, the following is nice to have.
(show-paren-mode t)
While developing, documentation is nice to have handy and automatic.
(add-hook 'cperl-mode-hook 'turn-on-eldoc-mode) (add-hook 'eshell-mode-hook 'turn-on-eldoc-mode)
5.17 Read-only helpers
For read-only files, look at them in view-mode
which will enable
vi-style navigation.
(use-package view :delight " 👁" :init (setq view-read-only t) :bind (:map view-mode-map ("n" . next-line ) ("p" . previous-line) ("j" . next-line ) ("k" . previous-line) ("l" . forward-char) ("h" . bnb/view/h) ("q" . bnb/view/q)) :config (defun bnb/view/h () "Setup a function to go backwards a character" (interactive) (forward-char -1)) (defun bnb/view/q () "Setup a function to quit `view-mode`" (interactive) (view-mode -1)))
5.18 Default File encoding
I like to have the files be utf-8
by default. Do
let me know if I shouldn't do this, will you?
Set utf-8
for all coding systems except for the clipboard on
windows. That one gets utf-16le
to be compatible.
(prefer-coding-system 'utf-8) (set-default-coding-systems 'utf-8) (set-terminal-coding-system 'utf-8) (set-keyboard-coding-system 'utf-8) (set-language-environment 'utf-8) (setq buffer-file-coding-system 'utf-8 x-select-request-type '(UTF8_STRING COMPOUND_TEXT TEXT STRING)) ;; MS Windows clipboard is UTF-16LE (when (eq system-type 'windows-nt) (set-clipboard-coding-system 'utf-16le-dos))
5.19 Ediff single frame
I really dislike the multi-frame mode of ediff
. It is confusing
to use and really messes up my dwm usage. By explicitly setting
the following setting, it forces ediff
to use only one
frame.
(setq ediff-window-setup-function 'ediff-setup-windows-plain)
Now the control window will be a small window instead of a separate frame.
5.20 Git
5.20.1 Magit
Magit is a git interface for Emacs.
Here I set a global key for magit-status
. Think 'G' looks
like 6.
(use-package magit :ensure t :bind ("<f6>" . magit-status) :config (setq magit-last-seen-setup-instructions "1.4.0"))
- Release 1.4.0
This magit release warns about auto-revert of buffers. This is turned on by default and I will keep that setting. To turn off the magit warning, I set
magit-last-seen-setup-instructions
to 1.4.0 as shown above. - Forge
Forge is the replacement for magithub. It uses `ghub` to work with git forges such as github and gitlab.
(use-package forge :ensure t :commands (forge-pull))
- Magit Todos
Within the 5.20.1 interface, show any todos listed in the files under version control.
(use-package magit-todos :ensure t :after magit :hook (magit-mode . magit-todos-mode))
5.20.2 Smerge
Somewhere along the line, smerge
was added. To facilitate
editing merge conflicts, this hydra helps me do the work.
(add-hook 'smerge-mode-hook (lambda () (bind-key "C-c ^ h" (defhydra hydra-smerge (:color amaranth) ("a" smerge-keep-all "Keep all") ("b" smerge-keep-base "Keep base") ("m" smerge-keep-mine "Keep mine") ("o" smerge-keep-other "Keep other") ("n" smerge-next "Next conflict") ("p" smerge-previous "Previous conflict") ("r" smerge-resolve "Keep mine") ("q" nil "quit")) smerge-mode-map)))
5.21 Open/Edit This file
When I hit <F5>
, open this file for editing. That way, any
time I have something I need to remember for my emacs setting, it
is just a button-push away.
(bind-key "<f5>" (lambda () (interactive) (find-file "~/.emacs.d/bnb-emacs/Readme.org")))
5.22 Sounds
I dislike the bell ringing when I hit C-g
. To silence the bell,
just set the ring-bell-function
to nil
.
(setq visual-bell nil ring-bell-function `(lambda () nil))
5.23 Midnight Mode
This mode looks at midnight and kills any inactive buffers. By default, inactive means is any buffer untouched for three days.
(use-package midnight :ensure t :defer 10)
5.24 Which Key
This helpful little package makes it easy to remember emacs
prefixed commands. Start typing a prefix such as C-x
after a
brief delay, the options for any following commands are shown.
I am using a setup that tries the right side of emacs first, and punts to a bottom window if there is not enough room.
(use-package which-key :ensure t :delight which-key-mode :init (which-key-mode) (which-key-setup-side-window-right-bottom) (setq which-key-max-description-length 60))
5.25 Ace Utilities
5.25.1 Ace Flyspell
Turn on ace-flyspell when flyspell is enabled.
(use-package ace-flyspell :ensure t :commands (ace-flyspell-setup) :bind ("H-s" . hydra-fly/body) :hook (flyspell-mode . ace-flyspell-setup) :init (defhydra hydra-fly (:color pink) ("n" flyspell-goto-next-error "Next error") ("c" ispell-word "Correct word") ("j" ace-flyspell-jump-word "Jump word") ("." ace-flyspell-dwim "dwim") ("q" nil "Quit")))
5.25.2 Ace Isearch
Supercharge isearch
to vary its behavior depending on the
input. The C-'
key let's me jump to the isearch match easily
with the ace-jump
methods.
(use-package ace-isearch :ensure t :bind (:map isearch-mode-map ("C-'" . ace-isearch-jump-during-isearch)) :delight ace-isearch-mode :config (global-ace-isearch-mode t) (setq ace-isearch-input-length 8))
5.25.3 Ace Link
In modes with links, use o
to jump to links. Map M-o
to do the
same in org-mode
.
(use-package ace-link :ensure t :bind (:map org-mode-map ("M-o" . ace-link-org)) :config (ace-link-setup-default))
5.25.4 Ace Window
Instead of C-x o
traversal, ace-window
mode provides numbers
for quick window access
Set the keys to something other than the default numbers. Note that this also limits the number of windows that can be used, but given my usage, I doubt it goes up to 'j' often.
Also, I modify the face attribute to make the window numbers large.
After reading the wiki, I supercharged the interface for ace-window
.
(use-package ace-window :ensure t :bind ("H-a" . ace-window) ("<f9> a" . ace-window) :config (setq aw-keys '(?j ?k ?l ?\; ?n ?m) aw-leading-char-style 'path aw-dispatch-always t aw-dispatch-alist '((?x aw-delete-window "Ace - Delete Window") (?c aw-swap-window "Ace - Swap window") (?n aw-flip-window "Ace - Flip window") (?v aw-split-window-vert "Ace - Split Vert Window") (?h aw-split-window-horz "Ace - Split Horz Window") (?m delete-other-windows "Ace - Maximize Window") (?b balance-windows))) (defhydra hydra-window-size (:color amaranth) "Window size" ("h" shrink-window-horizontally "shrink horizontal") ("j" shrink-window "shrink vertical") ("k" enlarge-window "enlarge vertical") ("l" enlarge-window-horizontally "enlarge horizontal") ("q" nil "quit")) (add-to-list 'aw-dispatch-alist '(?w hydra-window-size/body) t) (defhydra hydra-window-frame (:color red) "Frame" ("f" make-frame "new frame") ("x" delete-frame "delete frame") ("q" nil "quit")) (add-to-list 'aw-dispatch-alist '(?\; hydra-window-frame/body) t) (defhydra hydra-window-scroll (:color amaranth) "Scroll other window" ("n" scroll-other-window "scroll") ("p" scroll-other-window-down "scroll down") ("q" nil "quit")) (add-to-list 'aw-dispatch-alist '(?o hydra-window-scroll/body) t) (set-face-attribute 'aw-leading-char-face nil :height 2.0))
5.25.5 Avy Goto
It is time to make some shortcuts for jumping to see if they make sense for me. The interesting feature that I can use is that these highlight text an all shown buffers.
(use-package avy :ensure t :bind ("H-SPC" . avy-goto-char-timer) ("H-w" . avy-goto-word-1) ("H-c" . avy-goto-char-2) ("H-l" . avy-goto-line) ("H-d" . avy-goto-word-0) ("<f9> SPC" . avy-goto-char-timer) ("C-c g" . avy-goto-word-1) ("M-g l" . avy-goto-line) ("M-g c" . avy-goto-char-2) ("M-g w" . avy-goto-word-0))
The commands begin with the normal prefix of M-g
for the goto
commands and use l,c and w for lines, characters and words
respectively.
The char version I use here is the two-element version. For single character jumping, I have the Ace Isearch mode below that will facilitate quick jumping.
5.25.6 Avy Zap
Zap to char using avy.
(use-package avy-zap :ensure t :bind ("M-z" . avy-zap-to-char-dwim) ("M-Z" . avy-zap-up-to-char-dwim))
5.26 Edit Server
The edit server talks to Chrome and uses emacs to edit any text areas. I start this server here.
(use-package edit-server :ensure t :defer 10 :init (edit-server-start))
Chrome needs to have the proper extension installed there too for the installation to be complete.
5.27 Regexp-Builder
Emacs regular expressions are not the easiest to use out of the box. Emacs now has regexp-builder to assist you in building the correct regexp as you type.
However, to complicate matters, there are five different syntaxes
of regular expression that the builder can use. The string
syntax is what I tend to use most in searching and replacing, so I
will make that my default.
(setq reb-re-syntax 'string)
Key Binding | Meaning |
---|---|
C-c TAB |
Switch syntax |
C-c C-e |
Sub-expression mode (show matching groups) |
C-c C-s/r |
Search forward/backward |
C-c C-w |
Copy regexp to kill ring |
C-c C-q |
Quit the builder |
Be sure to consult the syntax of regular expressions to learn more about the weird backslashing.
5.28 IBuffer
Use ibuffer
instead of list-buffers
for buffer management. The
most visible difference being the coloring that ibuffer
uses.
I also squash any empty groups from being displayed and add hooks to automatically set the filter groups and update contents.
(bind-key "C-x C-b" 'ibuffer) (setq ibuffer-show-empty-filter-groups nil) (add-hook 'ibuffer-mode-hook '(lambda () (ibuffer-auto-mode 1) (ibuffer-switch-to-saved-filter-groups "Standard")))
5.28.1 Groups
The buffer list splits into arbitrary groups for easier
management. Below I create an "Org" group for org-mode
buffers.
(setq ibuffer-saved-filter-groups '(("Standard" ("Emacs" (or (filename . ".*bnb-emacs.*") (mode . emacs-lisp-mode))) ("Org" (mode . org-mode)) ("Magit" (name . "\*magit")) ("Mail" (or (mode . message-mode) (mode . mail-mode))) ("HTML" (mode . html-mode)) ("Help" (or (name . "\*Help\*") (name . "\*Apropos\*") (name . "\*info\*"))))))
- VC Grouping
The
ibuffer-vc
package provides groups according to version control sets. Here I setup a small keybinding to get to the filtered vc groups. The keys/ R
will go back to the standard view.(use-package ibuffer-vc :ensure t :bind (:map ibuffer-mode-map ("/ v" . ibuffer-vc-set-filter-groups-by-vc-root)))
5.29 Multiple Cursors
This interface is a mix of an example on the hydra wiki and my own additions.
I think that the key thing is remembering to not have this affect all cursors when prompted. Otherwise, it seems, the cursors are duplicated in strange ways.
(use-package multiple-cursors :ensure t :bind ("H-m" . hydra-mc/body) ("C-x m" . hydra-mc/body) ("s-<mouse-1>" . mc/add-cursor-on-click) ("C-x M" . compose-mail) :config (defhydra hydra-mc (:hint nil) " ^Up^ ^Down^ ^Miscellaneous^ ----------------------------------------------------------- [_p_] Next [_n_] Next [_l_] Edit lines [_x_] Arrows [_P_] Skip [_N_] Skip [_a_] Mark all [_g_] Regexp [_M-p_] Unmark [_M-n_] Unmark [_q_] Quit" ("l" mc/edit-lines :exit t) ("a" mc/mark-all-like-this-dwim :exit t) ("n" mc/mark-next-like-this) ("N" mc/skip-to-next-like-this) ("M-n" mc/unmark-next-like-this) ("p" mc/mark-previous-like-this) ("P" mc/skip-to-previous-like-this) ("M-p" mc/unmark-previous-like-this) ("g" mc/mark-all-in-region-regexp :exit t) ("r" mc/mark-sgml-tag-pair :exit t) ("x" mc/mark-more-like-this-extended) ("q" nil)) (add-hydra-mc-funcs)) (defun add-hydra-mc-funcs () "Add my hydra-mc funcs to the proper whitelist" (let* ((hydra-mc-funcs (cl-remove-if-not 'functionp (apply #'append hydra-mc/heads))) (mc-funcs-to-ignore (cl-intersection hydra-mc-funcs mc--default-cmds-to-run-once)) (funcs-to-whitelist (cl-mapcar (lambda (x) (intern (concat "hydra-mc/" (symbol-name x)))) mc-funcs-to-ignore))) (let (value) (dolist (element funcs-to-whitelist nil) (add-to-list 'mc/cmds-to-run-once element)))))
5.30 Expand Region
Nice way to expand selections to semantic regions. Read more on https://github.com/magnars/expand-region.el.
(use-package expand-region :ensure t :bind ("C-=" . er/expand-region))
5.31 Hooks
In general, hooks may be best with other configuration items, but if they are just pieces on their own, they belong here.
5.31.1 Ensure proper lisping
(add-hook 'after-save-hook 'check-parens nil t)
5.31.2 Auto Reverting in modes
For view-only buffers rendering content, it is useful to have them
auto-revert
in case of changes.
(add-hook 'doc-view-mode-hook 'auto-revert-mode) (add-hook 'image-mode 'auto-revert-mode)
5.32 Recentf
I enable emacs remembering recently open files.
(recentf-mode t)
5.33 Executable Scripts on save
Taken from: http://mbork.pl/2015-01-10_A_few_random_Emacs_tips
(add-hook 'after-save-hook 'executable-make-buffer-file-executable-if-script-p)
5.34 Scroll Screen Position
This is one of those cool finds for a problem I mostly knew that I
had. I often hit C-v
by accident and lose my place. With the
following setting, M-v
completely undoes the scroll leaving the
cursor back in the original position.
(setq scroll-preserve-screen-position 'always)
Thanks to http://irreal.org/blog/?p=3963 for the tip.
5.35 Unique Buffer Names
When editing files with the same name, but different location, a unique identifier (based on path) is preferred over a number.
(use-package uniquify :defer 10 :config (setq uniquify-buffer-name-style 'post-forward uniquify-separator ":"))
5.36 Focus Mode
Dim everything except for the thing-at-point. Improves focus when reading code and text.
(use-package focus :ensure t :bind ("C-c f" . focus-mode) ("C-c F" . focus-read-only-mode))
5.37 Relative line numbers
(use-package linum-relative :defer 10 :ensure t)
5.38 ImageMagick
Register file types if we can.
(when (fboundp 'imagemagick-register-types)
(imagemagick-register-types))
5.39 PDF Tools
This replaces the built-in DocView for PDF files. Find out the details on the repo.
(defcustom bnb/homebrew-prefix "" "Prefix to use for an alternative path to homebrew items" :type 'string :group 'bnb) (setenv "PKG_CONFIG_PATH" (let ((hbp bnb/homebrew-prefix)) (setq pdf-info-epdfinfo-program (concat hbp "/usr/local/bin/epdfinfo")) (mapconcat 'identity (list (concat hbp "/usr/local/Cellar/libffi/3.2.1/lib/pkgconfig") (concat hbp "/usr/local/Cellar/zlib/1.2.8/lib/pkgconfig") (concat hbp "/usr/local/lib/pkgconfig") "/opt/X11/lib/pkgconfig") ":"))) (use-package pdf-tools :defer t :ensure t :hook (pdf-view-mode . (lambda () (nlinum-mode 0))) :config (custom-set-variables '(pdf-tools-handle-upgrades nil)) (setq-default pdf-view-display-size 'fit-page) (pdf-loader-install))
5.40 Helpful
(use-package helpful :ensure t :bind ("C-h f" . helpful-function) ("C-h x" . helpful-command) ("C-h z" . helpful-macro))
5.41 All the icons
https://github.com/domtronn/all-the-icons.el
(use-package all-the-icons :ensure t :defer 10)
5.41.1 All the icons Dired
Dired can also make use of pretty icons. Because of this integration,
sunrise-commander
also gets some nice icons.
(use-package all-the-icons-dired :ensure t :commands (all-the-icons-dired-mode) :hook (dired-mode . all-the-icons-dired-mode))
5.42 Discover my mode
If you ever wanted to know what keybindings were active in the current buffer for the current mode, then it is now just a keypress away.
(use-package discover-my-major :ensure t :bind (("C-h C-m" . discover-my-major) ("C-h C-d" . discover-my-mode)))
5.43 Easy Kill
While looking for a way to store the filename in the clipboard, I ran across easy-kill. Not only will it grab the filename, but provides ways to grab all sorts of fun things.
(use-package easy-kill :bind ("M-w" . easy-kill) :ensure t)
5.44 Undo Tree
It's time to give undo-tree another try. The following hydra makes repeated undo/redo easier.
(use-package undo-tree :delight "¬" :ensure t :config (global-undo-tree-mode) (defhydra hydra-undo-tree (:color yellow :hint nil) " _p_: undo _n_: redo _s_: save _l_: load " ("p" undo-tree-undo) ("n" undo-tree-redo) ("s" undo-tree-save-history) ("l" undo-tree-load-history) ("u" undo-tree-visualize "visualize" :color blue) ("q" nil "quit" :color blue)) (global-set-key (kbd "H-,") 'hydra-undo-tree/body))
5.45 Adaptive Fill
Try to keep any prefixed elements of the first line for paragraph filling.
(use-package filladapt :delight " ▦" :ensure t :commands filladapt-mode :init (setq-default filladapt-mode t) :hook ((text-mode . filladapt-mode) (org-mode . turn-off-filladapt-mode) (prog-mode . turn-off-filladapt-mode)))
6 Style
The following sections describe items that affect the visual elements of Emacs.
6.1 Frame Changes
These following items make Emacs really beautiful on every platform. I remove the menu bar, tool bar and the scroll bar for starters. Then, I setup the fringe area with some items
(if (fboundp 'menu-bar-mode) (menu-bar-mode -1)) (if (fboundp 'tool-bar-mode) (tool-bar-mode -1)) (if (fboundp 'scroll-bar-mode) (scroll-bar-mode -1))
6.2 Window Changes
In the fringe area, I like to have markers to show me where the buffer begins/ends on the right. On the left, I have emacs show little dashes where empty lines exist.
In the title bar, I have it print the buffer name, full file name and size.
(setq-default indicate-buffer-boundaries 'right) (setq-default indicate-empty-lines t) (setq-default frame-title-format '("%b %f %I"))
6.3 Faces
6.3.1 Default Fonts
I love Source Code Pro, but I'm giving Fira Code a try for some extra ligature fun.
https://github.com/tonsky/FiraCode/wiki/Setting-up-Emacs
(use-package ring :bind ("H-f" . bnb/font-next) ("H-F" . bnb/font-prev) :config (defun bnb/filter-existing-fonts (fl) "Filter the list for only existing fonts" (seq-filter #'font-info fl)) (setq bnb/fontlist '( "-*-Lunar Mono-*-expanded-*-12" "-*-Lunar Mono-*-*-*-12" "Fira Code-13" "Source Code Pro-13") bnb/font-ring (ring-convert-sequence-to-ring (seq-filter #'font-info bnb/fontlist)) bnb/font (ring-ref bnb/font-ring 0)) (defun bnb/font-apply (font) "Change the default font to FONT." (set-frame-font (setq bnb/font font)) (message "Set default font to %s" bnb/font)) (defun bnb/font-next () "Cycle the default font to the next in the ring." (interactive) (bnb/font-apply (ring-next bnb/font-ring bnb/font))) (defun bnb/font-prev () "Cycle the default font to the previous in the ring." (interactive) (bnb/font-apply (ring-prev bnb/font-ring bnb/font))) (set-frame-font bnb/font)) (defconst fira-code-font-lock-keywords-alist (mapcar (lambda (regex-char-pair) `(,(car regex-char-pair) (0 (prog1 () (compose-region (match-beginning 1) (match-end 1) ;; The first argument to concat is a string containing a literal tab ,(concat " " (list (decode-char 'ucs (cadr regex-char-pair))))))))) '(("\\(www\\)" #Xe100) ("[^/]\\(\\*\\*\\)[^/]" #Xe101) ("\\(\\*\\*\\*\\)" #Xe102) ("\\(\\*\\*/\\)" #Xe103) ("\\(\\*>\\)" #Xe104) ("[^*]\\(\\*/\\)" #Xe105) ("\\(\\\\\\\\\\)" #Xe106) ("\\(\\\\\\\\\\\\\\)" #Xe107) ("\\({-\\)" #Xe108) ("\\(\\[\\]\\)" #Xe109) ("\\(::\\)" #Xe10a) ("\\(:::\\)" #Xe10b) ("[^=]\\(:=\\)" #Xe10c) ("\\(!!\\)" #Xe10d) ("\\(!=\\)" #Xe10e) ("\\(!==\\)" #Xe10f) ("\\(-}\\)" #Xe110) ("\\(--\\)" #Xe111) ("\\(---\\)" #Xe112) ("\\(-->\\)" #Xe113) ("[^-]\\(->\\)" #Xe114) ("\\(->>\\)" #Xe115) ("\\(-<\\)" #Xe116) ("\\(-<<\\)" #Xe117) ("\\(-~\\)" #Xe118) ("\\(#{\\)" #Xe119) ("\\(#\\[\\)" #Xe11a) ("\\(##\\)" #Xe11b) ("\\(###\\)" #Xe11c) ("\\(####\\)" #Xe11d) ("\\(#(\\)" #Xe11e) ("\\(#\\?\\)" #Xe11f) ("\\(#_\\)" #Xe120) ("\\(#_(\\)" #Xe121) ("\\(\\.-\\)" #Xe122) ("\\(\\.=\\)" #Xe123) ("\\(\\.\\.\\)" #Xe124) ("\\(\\.\\.<\\)" #Xe125) ("\\(\\.\\.\\.\\)" #Xe126) ("\\(\\?=\\)" #Xe127) ("\\(\\?\\?\\)" #Xe128) ("\\(;;\\)" #Xe129) ("\\(/\\*\\)" #Xe12a) ("\\(/\\*\\*\\)" #Xe12b) ("\\(/=\\)" #Xe12c) ("\\(/==\\)" #Xe12d) ("\\(/>\\)" #Xe12e) ("\\(//\\)" #Xe12f) ("\\(///\\)" #Xe130) ("\\(&&\\)" #Xe131) ("\\(||\\)" #Xe132) ("\\(||=\\)" #Xe133) ("[^|]\\(|=\\)" #Xe134) ("\\(|>\\)" #Xe135) ("\\(\\^=\\)" #Xe136) ("\\(\\$>\\)" #Xe137) ("\\(\\+\\+\\)" #Xe138) ("\\(\\+\\+\\+\\)" #Xe139) ("\\(\\+>\\)" #Xe13a) ("\\(=:=\\)" #Xe13b) ("[^!/]\\(==\\)[^>]" #Xe13c) ("\\(===\\)" #Xe13d) ("\\(==>\\)" #Xe13e) ("[^=]\\(=>\\)" #Xe13f) ("\\(=>>\\)" #Xe140) ("\\(<=\\)" #Xe141) ("\\(=<<\\)" #Xe142) ("\\(=/=\\)" #Xe143) ("\\(>-\\)" #Xe144) ("\\(>=\\)" #Xe145) ("\\(>=>\\)" #Xe146) ("[^-=]\\(>>\\)" #Xe147) ("\\(>>-\\)" #Xe148) ("\\(>>=\\)" #Xe149) ("\\(>>>\\)" #Xe14a) ("\\(<\\*\\)" #Xe14b) ("\\(<\\*>\\)" #Xe14c) ("\\(<|\\)" #Xe14d) ("\\(<|>\\)" #Xe14e) ("\\(<\\$\\)" #Xe14f) ("\\(<\\$>\\)" #Xe150) ("\\(<!--\\)" #Xe151) ("\\(<-\\)" #Xe152) ("\\(<--\\)" #Xe153) ("\\(<->\\)" #Xe154) ("\\(<\\+\\)" #Xe155) ("\\(<\\+>\\)" #Xe156) ("\\(<=\\)" #Xe157) ("\\(<==\\)" #Xe158) ("\\(<=>\\)" #Xe159) ("\\(<=<\\)" #Xe15a) ("\\(<>\\)" #Xe15b) ("[^-=]\\(<<\\)" #Xe15c) ("\\(<<-\\)" #Xe15d) ("\\(<<=\\)" #Xe15e) ("\\(<<<\\)" #Xe15f) ("\\(<~\\)" #Xe160) ("\\(<~~\\)" #Xe161) ("\\(</\\)" #Xe162) ("\\(</>\\)" #Xe163) ("\\(~@\\)" #Xe164) ("\\(~-\\)" #Xe165) ("\\(~=\\)" #Xe166) ("\\(~>\\)" #Xe167) ("[^<]\\(~~\\)" #Xe168) ("\\(~~>\\)" #Xe169) ("\\(%%\\)" #Xe16a) ;; ("\\(x\\)" #Xe16b) This ended up being hard to do properly so i'm leaving it out. ("[^:=]\\(:\\)[^:=]" #Xe16c) ("[^\\+<>]\\(\\+\\)[^\\+<>]" #Xe16d) ("[^\\*/<>]\\(\\*\\)[^\\*/<>]" #Xe16f)))) (defun add-fira-code-symbol-keywords () (font-lock-add-keywords nil fira-code-font-lock-keywords-alist)) ;;(add-fira-code-symbol-keywords)
6.3.2 Trying out fonts on Windows
(defun bnb/windows-set-font () "Use Windows font selection to set the default font." (interactive) (set-face-attribute 'default nil :font (w32-select-font)))
6.3.3 Dynamic Font sizes
Changing font sizes in presentations is crucial to have at hand. I
use the following keybindings. C--
overrides the negative
argument function, but that one is also accessible by M--
.
(defun bnb/change-frame-font-size (fn) "Change the frame font size according to function FN." (let* ((font-name (frame-parameter nil 'font)) (decomposed-font-name (x-decompose-font-name font-name)) (font-size (string-to-number (aref decomposed-font-name 5)))) (aset decomposed-font-name 5 (int-to-string (funcall fn font-size))) (set-frame-font (x-compose-font-name decomposed-font-name)))) (defun bnb/frame-text-scale-increase () "Increase the frame font size by 1." (interactive) (bnb/change-frame-font-size '1+)) (defun bnb/frame-text-scale-decrease () "Decrease the frame font size by 1." (interactive) (bnb/change-frame-font-size '1-)) (bind-keys ("C-+" . text-scale-increase) ("C--" . text-scale-decrease) ("s--" . bnb/frame-text-scale-decrease) ("s-+" . bnb/frame-text-scale-increase) ("s-=" . bnb/frame-text-scale-increase))
6.3.4 Mode Line Style
I dislike the box around the mode-line
making it look like a
button. I disable (set to nil
) this face attribute, box
, to
get a flat feel. Be sure to do it to all mode-line
faces that
have this attribute.
(set-face-attribute 'mode-line nil :box nil) (set-face-attribute 'mode-line-inactive nil :box nil) (set-face-attribute 'mode-line-highlight nil :box nil)
6.3.5 Missing Glyphs
If I ever use a font with a missing glyph, this will let Emacs check the Symbola font for the missing data.
Download Symbola if you do not have it.
(set-fontset-font "fontset-default" nil (font-spec :size 20 :name "Symbola"))
6.3.6 Cursor width
Make the cursor the full width of the character at point.
(setq x-stretch-cursor t)
6.4 Themes
I used to have something else from Greg Hendershot, but now I created my own theme override and layer it corectly.
(defun bnb/disable-all-themes () "Disable all enabled themes." (interactive) (mapc #'disable-theme custom-enabled-themes))
On creating themes: https://www.gnu.org/software/emacs/manual/html_node/emacs/Creating-Custom-Themes.html#Creating-Custom-Themes
6.4.1 Extra Themes
I like to have a few options for themes easily available. This set respresents my favorite go-to combinations.
(use-package minimal-theme :ensure t :defer t) (use-package gruvbox-theme :ensure t :defer t) (use-package material-theme :ensure t :defer t) (use-package tango-plus-theme :ensure t :defer t) (use-package color-theme-sanityinc-tomorrow :ensure t :defer t) ;; dichromacy ;; adwaita
6.5 Sky Color Clock
This is a nice addition to any modeline. In a little block, it shows the date, time, moon phase
(use-package sky-color-clock :defer 10 :quelpa (sky-color-clock :fetcher github :repo "zk-phi/sky-color-clock") :config (sky-color-clock-initialize 40) (setq sky-color-clock-enable-emoji-icon t) (sky-color-clock-initialize-openweathermap-client bnb/openweathermap-api-key bnb/openweathermap-city-id))
6.6 Doom Modeline
(use-package doom-modeline :ensure t :init (doom-modeline-mode t) :config (setq doom-modeline-height 0))
6.7 ⁂ Mode
Let's try ⁂-mode for an interesting mini-buffer line.
(defun bnb/smaller-sky-color () (let* ((scc (sky-color-clock)) (len (length scc))) (add-face-text-property 0 len '(:height 90) t scc) (add-face-text-property 0 len '(:justification right) t scc) scc)) (use-package asterism-mode :quelpa (asterism-mode :fetcher gitlab :repo "lunarstudio/asterism-mode") :config (setq ⁂-format '((:eval (bnb/smaller-sky-color)))))
6.8 Font lock profiling
Allow for profiling of font-locking.
(use-package font-lock-profiler :commands (font-lock-profiler-start font-lock-profiler-buffer font-lock-profiler-region))
6.9 Pretty Symbols
Emacs can be so pretty sometimes.
6.9.1 Pretty mode
(use-package pretty-mode :disabled :config (global-pretty-mode t) (pretty-activate-groups '(:sub-and-superscripts :greek :arithmetic-nary)))
6.9.2 Prettify symbols mode
Some reading to consider:
- http://endlessparentheses.com/using-prettify-symbols-in-clojure-and-elisp-without-breaking-indentation.html
- https://www.emacswiki.org/emacs/PrettySymbolsForLanguages
(use-package prog-mode ; Contains pretty-symbols-mode :config (setq prettify-symbols-unprettify-at-point 'right-edge) (global-prettify-symbols-mode t) :hook (python-mode . (lambda () (mapc (lambda (pair) (push pair prettify-symbols-alist)) '(;; Syntax ("def" . ?ℱ) ("not" . ?❗) ("in" . ?∈) ("not in" . ?∉) ("return" . ?⟼) ("yield" . ?⟻) ("for" . ?∀) ;; Base Types ("int" . ?ℤ) ("float" . ?ℝ) ("str" . ?𝕊) ("True" . ?𝕋) ("False" . ?𝔽) ;; Mypy ("Dict" . ?𝔇) ("List" . ?ℒ) ("Tuple" . ?⨂) ("Set" . ?Ω) ("Iterable" . ?𝔊) ("Any" . ?❔) ("Union" . ?∪))))))
6.10 Color
6.10.1 Rainbow Mode
In order to see the colors in the buffer this mode higlights color words and definitions with their values.
(use-package rainbow-mode :commands (rainbow-mode) :ensure t)
6.10.2 KureColor
Color helper KureColor allows easy modifications of hue, saturation and brightness.
(use-package kurecolor :bind (("H-k" . kurecolor-increase-hue-by-step) ("H-j" . kurecolor-decrease-hue-by-step) ("s-k" . kurecolor-increase-saturation-by-step) ("s-j" . kurecolor-decrease-saturation-by-step) ("s-l" . kurecolor-increase-brightness-by-step) ("s-h" . kurecolor-decrease-brightness-by-step)) :ensure t)
7 BNB Helpers
This is a collection of code specific to how I use emacs. Some are from different websites or other Emacs users.
7.1 Workweeks
This is vestigal content from my Intel days and this generates their idea of a work week number.
(defun bnb/workweek () "Return the current workweek number." (interactive) (let* ((now (current-time)) (weeks (string-to-number (format-time-string "%W" now))) (days (time-to-day-in-year now)) (daynum (string-to-number (format-time-string "%w" now))) (left (% days 7))) (if (and (= 0 daynum) (= left 0)) weeks (+ 1 weeks)))) (defun bnb/workweek-string () "Convert the current workweek into a string. The string is of the format WW##." (interactive) (concat "WW" (number-to-string (bnb/workweek)))) (require 'calendar) (defun bnb/workweek-from-gregorian (&optional date) "Calculate the workweek from the Gregorian calendar." (let* ((date (or date (calendar-current-date))) (year (calendar-extract-year date)) (fst (calendar-day-of-week (list 1 1 year))) (x (if (>= fst 4)1 0))) (+ x (car (calendar-iso-from-absolute (calendar-absolute-from-gregorian date)))))) (setq calendar-week-start-day 1 calendar-intermonth-text '(propertize (format "%2d" (bnb/workweek-from-gregorian (list month day year))) 'font-lock-face 'font-lock-function-name-face))
7.2 Better window splitting functions
http://www.reddit.com/r/emacs/comments/25v0eo/you_emacs_tips_and_tricks/chldury
These settings split the window and load a previous buffer (instead of the same buffer in both). This has a better chance of being what I want when splitting strings.
(defun bnb/vplit-last-buffer () "When splitting the frame, load the last visited buffer." (interactive) (split-window-vertically) (other-window 1 nil) (switch-to-next-buffer)) (defun bnb/hsplit-last-buffer () "When splitting the frame, load the last visited buffer." (interactive) (split-window-horizontally) (other-window 1 nil) (switch-to-next-buffer)) (bind-keys ("C-x 2" . bnb/vplit-last-buffer) ("C-x 3" . bnb/hsplit-last-buffer))
7.3 Weekly Time Reporting
This is a function to create an entry like a datetree, but using years and workweeks instead.
(defun bnb/find-year-create (year) "Find or create a [YEAR] in an Org journal." (let ((re "^\\**[ \t]+\\([12][0-9]\\{3\\}\\)") match) (org-narrow-to-subtree) (goto-char (point-min)) (while (and (setq match (re-search-forward re nil t)) (goto-char (match-beginning 1)) (< (string-to-number (match-string 1)) year))) (cond ((not match) (goto-char (point-max)) (or (bolp) (newline)) (insert (format "** %s\n" year))) ((= (string-to-number (match-string 1)) year) (goto-char (point-at-bol))) (t (beginning-of-line 1) (insert (format "** %s\n" year)))))) (defun bnb/find-ww-create (ww) "Find or create a [WW] (workweek) in an Org journal." (let ((re "^\\**[ \t]+\\WW\\([0-9]\\{2\\}\\)") match) (org-narrow-to-subtree) (goto-char (point-min)) (while (and (setq match (re-search-forward re nil t)) (goto-char (match-beginning 1)) (< (string-to-number (match-string 1)) ww))) (cond ((not match) (goto-char (point-max)) (or (bolp) (newline)) (insert (format "*** WW%02d\n" ww))) ((= (string-to-number (match-string 1)) ww) (goto-char (point-at-bol))) (t (beginning-of-line 1) (insert (format "*** WW%02d\n" ww)))))) (defun bnb/insert-weekly-time-sheet () "Generated and insert a weekly time sheet generated from the default Org Agenda." (with-temp-buffer (insert (concat "#+BEGIN: clocktable :maxlevel 3 :scope agenda-with-archives :block lastweek :fileskip0 t :properties (\"Score\") :indent nil \n" "#+TBLFM: $6='(org-clock-time% @2$4 $3..$5);%.1f::@2$2=vsum(@3$2..@>$2)\n" "#+END:\n\n")) (goto-char (point-min)) (org-update-dblock) (buffer-substring (point-min) (point-max)))) (defun bnb/insert-weekly-clocking () "Insert the weekly clocking clocking data." (let ((year (number-to-string (nth 2 (calendar-gregorian-from-absolute (org-today))))) (ww (bnb/workweek))) (goto-char (point-min)) (goto-char (cdr (org-id-find "clocking"))) (bnb/find-year-create (string-to-number year)) (bnb/find-ww-create ww)))
7.4 Weekly Score Goal in Org-Agenda
I use a scoring system to keep track of my overall progress. This involves scoring my tasks and attributing my idea of impact of a particular done item.
To use these numbers, I do a weekly review on Monday and compare the numbers to past years/weeks/etc. To keep pushing forward, this little bit of code will insert a running status at the top of my agenda.
If I am on track for the given day (at or above the scaled goal), all is green. Otherwise, I get a warning type formatting above 80% and error type formatting under.
;; Define my goal to hit (defvar bnb/weekly-score-goal 42) ;; Add up all the scores from DONE items in the agenda files (defun bnb/agenda-score-goal () "Add up scores from done items. In the agenda, this will show the number of done items and the target goal from `bnb/weekly-score-goal`." (let* ((score ;; Add up all scores from DONE items (apply '+ (org-map-entries (lambda () (string-to-number (or (org-entry-get (point) "Score") "0"))) "/DONE" 'agenda))) (scaled-goal (* bnb/weekly-score-goal (/ (string-to-number (format-time-string "%w")) 5.0))) (face (cond ((>= score scaled-goal) 'success) ((>= score (* .8 scaled-goal)) 'warning) (t 'error))) (goal-label (format "✧ Score Goal (%d): " scaled-goal)) (goal-metric (format "%d/%d\n" score bnb/weekly-score-goal)) (header-size (+ (string-width goal-label) (string-width goal-metric))) (goal-separator (concat (make-string header-size ?┄) "\n"))) (insert (concat (propertize goal-label 'face 'org-agenda-structure) (propertize goal-metric 'face face) (propertize goal-separator 'face 'org-agenda-structure))))) ;; This hook runs first in the agenda (and before it is set to read-only) (add-hook 'org-agenda-mode-hook 'bnb/agenda-score-goal)
7.5 Auto-display agenda
John Weigley shows a way to display the agenda after some period of inactivity.
(defun bnb/jump-to-org-agenda () "Create and jump to the bnb org agenda." (interactive) (let ((buf (get-buffer "*Org Agenda*")) wind) (if buf (if (setq wind (get-buffer-window buf)) (select-window wind) (if (called-interactively-p) (progn (select-window (display-buffer buf t t)) (org-fit-window-to-buffer)) (with-selected-window (display-buffer buf) (org-fit-window-to-buffer)))) (bnb/org-agenda-with-tip nil)))) (defun bnb/idle-agenda (&optional arg) "Set or cancel idle agenda timer based on [ARG]." (interactive "P") (setq bnb/iagenda (if arg (cancel-timer bnb/iagenda) (run-with-idle-timer 3600 t 'bnb/jump-to-org-agenda))))
7.6 Transparency
Using the ring
package, these commands will cycles through transparency settings.
(use-package ring :commands (bnb/transparency-apply bnb/transparency-next bnb/transparency-previous bnb/transparency-cycle bnb/transparency-add) :config (setq bnb/transparency-ring (ring-convert-sequence-to-ring (list '(100 100) '(100 50) '(100 10) '(95 50) '(90 50) '(85 50))) bnb/transparency (ring-ref bnb/transparency-ring 0)) (defun bnb/transparency-apply (trans) "Apply the TRANS alpha value to the frame." (set-frame-parameter (selected-frame) 'alpha (setq bnb/transparency trans))) (defun bnb/transparency-next () "Apply the next transparency value in the ring `bnb/transparency-ring`." (interactive) (bnb/transparency-apply (ring-next bnb/transparency-ring bnb/transparency))) (defun bnb/transparency-previous () "Apply the previous transparency value in the ring `bnb/transparency-ring`." (interactive) (bnb/transparency-apply (ring-previous bnb/transparency-ring bnb/transparency))) (defun bnb/transparency-cycle () "Cycle to the next transparency setting." (interactive) (bnb/transparency-next)) (defun bnb/transparency-add (active inactive) "Add ACTIVE and INACTIVE transparency values to the ring." (interactive "nActive Transparency:\nnInactive Transparency:") (ring-insert+extend bnb/transparency-ring (list active inactive) t) (bnb/transparency-apply (list active inactive))))
7.7 Styled HTML Export
This is how I get the one-page html output for Github Pages. There are two main parts to setting up and executing the export.
First, I use a SETUPFILE
from
https://github.com/fniessen/org-html-themes. Specifically, I use
the readtheorg style.
Second, I setup the emacs theme correctly for nice code output. Syntax highlighting in the export will pull from the current theme. I don't want this. Instead, I want to specify which theme to use for every export.
The code below stores away the current list of enabled themes
before disabling them all. Then, it enables my preferred export
theme (sanityinc-tomorrow-day
) before performing the
export. Finally, it disables the last theme and renables all of the
ones on the list.
(defun bnb/export-readme () "Export the tangled org setting as html. `sanityinc-tomorrow-day` is used to style the code exports." (interactive) (let ((themes custom-enabled-themes)) (mapc 'disable-theme themes) (load-theme 'sanityinc-tomorrow-day) (org-html-export-to-html) (disable-theme 'sanityinc-tomorrow-day) (mapcar 'load-theme (reverse themes))))
7.8 Auto-indent when pasting
Automatically indent pasted blocks of text.
(dolist (command '(yank yank-pop)) (eval `(defadvice ,command (after indent-region activate) (and (not current-prefix-arg) (let ((mark-even-if-inactive transient-mark-mode)) (indent-region (region-beginning) (region-end) nil))))))
7.9 Hide mode line
This is a fun one I picked from a now defunct website. This block of code hides the mode-line for the current buffer (window).
;; Setup buffer-local behavior (defvar-local bnb/hide-mode-line-mode nil) ;; Setup minor mode (define-minor-mode bnb/hide-mode-line-mode "Minor mode to hide mode-line in current buffer" :init-value nil :global nil :variable bnb/hide-mode-line-mode :group 'editing-basics (if bnb/hide-mode-line-mode (setq bnb/hide-mode-line-mode/saved-format mode-line-format mode-line-format nil) (setq mode-line-format bnb/hide-mode-line-mode/saved-format bnb/hide-mode-line-mode/saved-format nil)) (force-mode-line-update) (redraw-display) (when (and (called-interactively-p 'interactive) bnb/hide-mode-line-mode) (run-with-idle-timer 0 nil 'message (concat "Goodbye mode line!" "Use M-x bnb/hide-mode-line-mode to make the mode-line appear")))) ;; Bind global key (bind-key "H-0" 'bnb/hide-mode-line-mode)
7.10 Org-column resizing
In order to resize the face when `org-column` mode is on, some
advice is in order. The face used has a set :height
that is not
overridden by custom face settings.
To have a custom height, this advice prepends the list with an anonymous face with a height of 0.8. This setting happens first, so it wins.
(defun bnb/org-overlay-font-override (orig-fn beg end &optional txt face) (let ((bnbface (cons '(:height 0.8) face))) (funcall orig-fn beg end txt bnbface))) (advice-add 'org-columns--new-overlay :around #'bnb/org-overlay-font-override) ;(advice-remove 'org-columns--new-overlay #'bnb/org-overlay-font-override)
8 Auto-completion
Let the machine help with typing!
8.1 Company
Company Mode is an in-buffer completion system. To get started, I need to load the mode and bind some keys.
(use-package company :ensure t :delight company-mode :hook (after-init . global-company-mode) :bind (("C-<tab>" . company-complete-common-or-cycle) ("C-<tab>" . company-complete-org-mode-map) :map company-active-map ("s-<tab>" . company-complete-common-or-cycle) ("C-n" . company-select-next) ("C-p" . company-select-previous) ("M-<" . company-select-first) ("M->" . company-select-last)) :config ;; Turn off the auto downcasing of things (setq company-dabbrev-downcase nil company-show-numbers t company-tooltip-align-annotations t company-selection-wrap-around t company-tooltip-flip-when-above t company-dabbrev-code-everywhere t company-dabbrev-code-ignore-case t))
8.2 Yasnippet
(use-package yasnippet :ensure t :hook (prog-mode . yas-minor-mode) (text-mode . yas-minor-mode) :config (yas-reload-all))
9 File Management
9.1 Dired
These are part of the dired-hacks repository.
(use-package dired-hacks-utils :defer t :ensure t) (use-package dired-filter :defer t :hook (dired-mode . dired-filter-mode) :ensure t :bind ("C-c C-d f" . dired-filter-mode) :bind-keymap ("C-c C-f" . dired-filter-map)) (use-package dired-rainbow :defer t :ensure t :config (progn (dired-rainbow-define-chmod directory "#6cb2eb" "d.*") (dired-rainbow-define html "#eb5286" ("css" "less" "sass" "scss" "htm" "html" "jhtm" "mht" "eml" "mustache" "xhtml")) (dired-rainbow-define xml "#f2d024" ("xml" "xsd" "xsl" "xslt" "wsdl" "bib" "json" "msg" "pgn" "rss" "yaml" "yml" "rdata")) (dired-rainbow-define document "#9561e2" ("docm" "doc" "docx" "odb" "odt" "pdb" "pdf" "ps" "rtf" "djvu" "epub" "odp" "ppt" "pptx")) (dired-rainbow-define markdown "#ffed4a" ("org" "etx" "info" "markdown" "md" "mkd" "nfo" "pod" "rst" "tex" "textfile" "txt")) (dired-rainbow-define database "#6574cd" ("xlsx" "xls" "csv" "accdb" "db" "mdb" "sqlite" "nc")) (dired-rainbow-define media "#de751f" ("mp3" "mp4" "MP3" "MP4" "avi" "mpeg" "mpg" "flv" "ogg" "mov" "mid" "midi" "wav" "aiff" "flac")) (dired-rainbow-define image "#f66d9b" ("tiff" "tif" "cdr" "gif" "ico" "jpeg" "jpg" "png" "psd" "eps" "svg")) (dired-rainbow-define log "#c17d11" ("log")) (dired-rainbow-define shell "#f6993f" ("awk" "bash" "bat" "sed" "sh" "zsh" "vim")) (dired-rainbow-define interpreted "#38c172" ("py" "ipynb" "rb" "pl" "t" "msql" "mysql" "pgsql" "sql" "r" "clj" "cljs" "scala" "js")) (dired-rainbow-define compiled "#4dc0b5" ("asm" "cl" "lisp" "el" "c" "h" "c++" "h++" "hpp" "hxx" "m" "cc" "cs" "cp" "cpp" "go" "f" "for" "ftn" "f90" "f95" "f03" "f08" "s" "rs" "hi" "hs" "pyc" ".java")) (dired-rainbow-define executable "#8cc4ff" ("exe" "msi")) (dired-rainbow-define compressed "#51d88a" ("7z" "zip" "bz2" "tgz" "txz" "gz" "xz" "z" "Z" "jar" "war" "ear" "rar" "sar" "xpi" "apk" "xz" "tar")) (dired-rainbow-define packaged "#faad63" ("deb" "rpm" "apk" "jad" "jar" "cab" "pak" "pk3" "vdf" "vpk" "bsp")) (dired-rainbow-define encrypted "#ffed4a" ("gpg" "pgp" "asc" "bfe" "enc" "signature" "sig" "p12" "pem")) (dired-rainbow-define fonts "#6cb2eb" ("afm" "fon" "fnt" "pfb" "pfm" "ttf" "otf")) (dired-rainbow-define partition "#e3342f" ("dmg" "iso" "bin" "nrg" "qcow" "toast" "vcd" "vmdk" "bak")) (dired-rainbow-define vc "#0074d9" ("git" "gitignore" "gitattributes" "gitmodules")) (dired-rainbow-define-chmod executable-unix "#38c172" "-.*x.*"))) (use-package dired-narrow :defer t :bind (:map dired-mode-map ("C-c C-d n" . dired-narrow-fuzzy) ("C-c C-d r" . dired-narrow-regexp)) :ensure t) (use-package dired-collapse :defer t :bind ("C-c C-d c" . dired-collapse-mode) :ensure t)
Also, there is a nice faculty to run an external command on a given
file with =!=
.
9.2 Neotree
Neotree is a file sidebar for navigation.
(use-package neotree :ensure t :commands (neotree) :bind ("H-t" . neotree-toggle) :config (setq neo-theme (if (display-graphic-p) 'icons 'arrow)))
9.3 OSX Dictionary
Search Dictionary.app
from the comfort of an Emacs buffer.
(use-package osx-dictionary :ensure t :bind ("C-c d" . osx-dictionary-search-word-at-point) ("C-c i" . osx-dictionary-search-input))
9.4 OSX Reveal
Show files in finder.
(use-package reveal-in-osx-finder :ensure t :bind ("C-c z" . reveal-in-osx-finder))
10 Smart Tabs
SmartTabs try to do the right thing regarding tabs/spaces in
indentation/alignment. It installs through the package interface. Look for
smart-tabs-mode
.
By default, I'm enabling it in all modes that I can.
Since we are dealing with tabs here, I also take the time to set the default width to 4. Because of the way this mode works, any change in the default width will result in code that still aligns.
(use-package smart-tabs-mode :defer 10 :ensure t :init (setq-default indent-tabs-mode nil) (smart-tabs-insinuate 'c 'cperl 'c++) (setq-default tab-width 2))
10.1 Notes
To re-tab the whole file, use C-x h C-M-\
.
11 CUA mode
CUA has a primary feature of enabling cut, copy, paste and undo shortcuts compatible with most applications (C-x, C-c, C-v). However, it also has interesting rectangle features and that is why I enable it. I also happen to turn off those other bindings and prefer the emacs defaults.
(cua-mode t)
(setq cua-enable-cua-keys nil)
11.1 Bindings
11.1.1 CUA Rectangles
These take place with an active rectangle. To start/cancel a
rectangle use C-RET
.
Keys | Function |
---|---|
M-<arrow> | Move rectangle overlay |
C-SPACE | Activate region bounded by rectangle |
M-a | Align all words at the left edge |
M-b | Fill rectangle with blanks (tabs and spaces) |
M-c | Closes the rectangle by removing left edge blanks |
M-f | Fills the rectangle with a single character (prompt) |
M-i | Increases number found on each line of rectangle |
M-k | Kills the rectangle as normal multi-line kill |
M-l | Downcases the rectangle |
M-m | Copies the rectangle for normal multi-line paste |
M-n | Fills each line with increasing numbers (prompt) |
M-o | Opens the rect by moving hilighted text right and filling with blanks |
M-p | Toggles virtual straight rectangle edges |
M-P | Inserts tabs and spaces to make real straight edges |
M-q | Performs text filling on the rectangle |
M-q | Performs text filling on the rectangle |
M-r | Replaces REGEXP (prompt) by STRING (prompt) in rectangle |
M-R | Reverse the lines in the rectangle |
M-s | Fills each line of the rectangle with the same STRING (prompt) |
M-t | Performs text fill of the rectangle with TEXT (prompt) |
M-u | Upcases the rectangle |
M-<Vertical Bar> | Runs shell command on rectangle |
M-' | Restricts rectangle to lines with CHAR (prompt) at left column |
M-/ | Restricts rectangle to lines matching REGEXP (prompt) |
C-? | Shows a brief list of the above commands. |
M-C-<UP/DOWN> | Scrolls the lines INSIDE the rectangle up/down |
11.1.2 CUA Global Mark
The global mark feature enables a target the receives any typed/copied/killed text from any buffer (even the current one).
Key | function |
---|---|
<ch> | All characters (including newlines) you type are inserted at the global mark! |
C-x | If you cut a region or rectangle, it is automatically inserted at the global mark, and the global mark is advanced. |
C-c | If you copy a region or rectangle, it is immediately inserted at the global mark, and the global mark is advanced. |
C-v | Copies a single character to the global mark. |
C-d | Moves (i.e. deletes and inserts) a single character to the global mark. |
backspace | deletes the character before the global mark |
delete | deletes the character after the global mark. |
S-C-space | Jumps to and cancels the global mark. |
C-u S-C-space | Cancels the global mark (stays in current buffer). |
TAB | Indents the current line or rectangle to the column of the global mark. |
12 Paredit
I added paredit-mode
to several of the lisp modes that follow.
(use-package paredit :ensure t :delight " 🍐" :commands (paredit-mode))
13 Paxedit
Maybe even more power for lisp coding? Paxedit repo
(use-package paxedit :ensure t :delight " ꁀ" :commands (paxedit-mode) :bind ("M-<right>" . paxedit-transpose-forward) ("M-<left>" . paxedit-transpose-backward) ("M-<up>" . paxedit-backward-up) ("M-<down>" . paxedit-backward-end) ("M-b" . paxedit-previous-symbol) ("M-f" . paxedit-next-symbol) ("C-%" . paxedit-copy) ("C-&" . paxedit-kill) ("C-*" . paxedit-delete) ("C-^" . paxedit-sexp-raise) ("M-u" . paxedit-symbol-change-case) ("C-@" . paxedit-symbol-copy) ("C-#" . paxedit-symbol-kill))
14 Projectile
Handling project buffers and files may be easier with projectile. Currently under evaluation.
From the Hydra Wiki, the additional hydras launch the projectile functions.
(use-package projectile :ensure t :bind ("C-c p" . projectile-command-map) ("C-x w" . hydra-projectile-other-window/body) ("C-c C-p" . hydra-projectile/body) :config (use-package counsel-projectile :after (projectile) :ensure t :bind (:map projectile-command-map ("s s" . counsel-projectile-rg) ("p" . counsel-projectile-switch-project))) (when (eq system-type 'windows-nt) (setq projectile-indexing-method 'native)) (setq projectile-enable-caching t projectile-require-project-root t projectile-mode-line '(:eval (format " 🛠[%s]" (projectile-project-name))) projectile-completion-system 'default) (add-to-list 'projectile-globally-ignored-directories "node_modules") (projectile-mode) (defhydra hydra-projectile-other-window (:color teal) "projectile-other-window" ("f" projectile-find-file-other-window "file") ("g" projectile-find-file-dwim-other-window "file dwim") ("d" projectile-find-dir-other-window "dir") ("b" projectile-switch-to-buffer-other-window "buffer") ("q" nil "cancel" :color blue)) (defhydra hydra-projectile (:color teal :hint nil) " PROJECTILE: %(projectile-project-root) Find File Search/Tags Buffers Cache ------------------------------------------------------------------------------------------ _C-f_: file _r_: ag _i_: Ibuffer _c_: cache clear _ff_: file dwim _g_: update gtags _b_: switch to buffer _x_: remove known project _fd_: file curr dir _o_: multi-occur _C-k_: Kill all buffers _X_: cleanup non-existing _r_: recent file ^^^^_z_: cache current _d_: dir " ("r" counsel-projectile-rg) ("b" projectile-switch-to-buffer) ("c" projectile-invalidate-cache) ("d" projectile-find-dir) ("C-f" projectile-find-file) ("ff" projectile-find-file-dwim) ("fd" projectile-find-file-in-directory) ("g" ggtags-update-tags) ("C-g" ggtags-update-tags) ("i" projectile-ibuffer) ("K" projectile-kill-buffers) ("C-k" projectile-kill-buffers) ("m" projectile-multi-occur) ("o" projectile-multi-occur) ("C-p" projectile-switch-project "switch project") ("p" projectile-switch-project) ("s" projectile-switch-project) ("r" projectile-recentf) ("x" projectile-remove-known-project) ("X" projectile-cleanup-known-projects) ("z" projectile-cache-current-file) ("`" hydra-projectile-other-window/body "other window") ("q" nil "cancel" :color blue)))
15 Programming Languages
15.1 Utilities
15.1.1 Flycheck
(use-package flycheck :ensure t :defer 10 ;:init (global-flycheck-mode) :config (bind-key "H-!" (defhydra hydra-toggle (:color amaranth) " _c_ Check buffer _x_ Explain error _n_ Next error _h_ Show error _p_ Previous error _l_ Show all errors _s_ Select syntax checker _C_ Clear errors _?_ Describe syntax checker " ("c" flycheck-buffer) ("n" flycheck-next-error) ("p" flycheck-previous-error) ("l" flycheck-list-errors) ("C" flycheck-clear-errors) ("x" flycheck-explain-error-at-point) ("h" flycheck-display-error-at-point) ("s" flycheck-select-checker) ("?" flycheck-describe-checker) ("q" nil))))
15.1.2 Prog fill
(use-package prog-fill :ensure t :commands (prog-fill) :config (setq prog-fill-floating-close-paren-p nil prog-fill-break-method-immediate-p t))
15.1.3 Language Server Protocol
Key | Function |
---|---|
C-M-i | completion at point |
M-. | Goto definition |
M-? | Symbol references |
M-x | Rename |
(use-package lsp-mode :defer :ensure t)
15.2 C++
Oh my! I finally have a C++ addition to make!
15.2.1 Compilation Buffers
I forget where I snarfed this from, but it does a great job fixing the ANSI escape sequences in compilation buffers.
(require 'ansi-color) (defun colorize-compilation-buffer () (toggle-read-only) (ansi-color-apply-on-region compilation-filter-start (point)) (toggle-read-only)) (add-hook 'compilation-filter-hook 'colorize-compilation-buffer)
15.3 Elisp
When modified emacs-lisp
, it is most helpful to use paredit
and
eldoc
.
(add-hook 'emacs-lisp-mode-hook 'paredit-mode) (add-hook 'emacs-lisp-mode-hook 'paxedit-mode) (add-hook 'emacs-lisp-mode-hook 'turn-on-eldoc-mode)
15.4 Javascript
Let's make some javascript settings!
(setq js-indent-level 2)
Additional setup from https://emacs.cafe/emacs/javascript/setup/2017/04/23/emacs-setup-javascript.html
15.4.1 JS2
(use-package js2-mode :ensure t :mode "\\.js\\'" :hook (js2-mode . #'js2-imenu-extras-mode) :config (setq js2-basic-offset 2))
(use-package js2-refactor :ensure t :after js2-mode :functions (js2r-add-keybindings-with-prefix) :bind (:map js2-mode-map ("C-k" . js2r-kill)) :config (js2r-add-keybindings-with-prefix "C-c C-r"))
(use-package xref-js2 :ensure t :after js2-mode :hook (js2-mode . (lambda () (add-hook 'xref-backend-functions #'xref-js2-xref-backend nil t))))
15.5 Rust
(use-package rustic :ensure t :bind (:map rustic-mode-map ("C-c C-c j" . lsp-ui-imenu) ("C-c C-c f" . lst-find-references) ("C-c C-c l" . flycheck-list-errors) ("C-c C-c a" . lsp-execute-code-action) ("C-c C-c n" . lsp-rename) ("C-c C-c q" . lsp-workspace-restart) ("C-c C-c Q" . lsp-workspace-shutdown) ("C-c C-c s" . lsp-rust-analyzer-status) ("C-c C-c e" . lsp-rust-analyzer-expand-macro) ("C-c C-c d" . dap-hydra) ("C-c C-c h" . lsp-ui-doc-glance)) :config (setq rustic-format-on-save t) :hook ((rustic-mode . flycheck-mode) (rustic-mode . electric-pair-mode))) (defun bnb/rustic-mode-hook () (when buffer-file-name (setq-local buffer-save-without-query t))) (use-package lsp-mode :ensure t :commands lsp :custom (lsp-rust-analyzer-cargo-watch-command "clippy") (lsp-edoc-render-all t) (lsp-idle-delay 0.6) (lsp-rust-analyzer-server-display-inlay-hints t) :hook (lsp-mode . lsp-ui-mode)) (use-package lsp-ui :ensure t :commands lsp-ui-mode :custom (lsp-ui-peek-always-show t) (lsp-ui-sideline-show-hover t) (lsp-ui-doc-enable nil)) (use-package cargo :ensure t :mode ("Cargo.toml\\'" . (lambda () (progn (toml-mode) (cargo-minor-mode t)))) :hook (rust-mode . cargo-minor-mode) :bind-keymap ("C-c c" . cargo-mode-map)) (use-package toml-mode :quelpa (toml-mode :fetcher github :repo "dryman/toml-mode.el") :mode "\\.toml\\'")
15.6 Sass
(use-package sass-mode :defer :ensure t)
15.7 Web Mode
For all of the webish-stuff, this mode works well. Let's enable it on the right things.
(use-package web-mode :defer :ensure t :bind ("H-b" . browse-url-of-file) :config (add-to-list 'auto-mode-alist '("\\.[agj]sp\\'" . web-mode)) (add-to-list 'auto-mode-alist '("\\.erb\\'" . web-mode)) (add-to-list 'auto-mode-alist '("\\.hbs\\'" . web-mode)) (add-to-list 'auto-mode-alist '("\\.mustache\\'" . web-mode)) (add-to-list 'auto-mode-alist '("\\.djhtml\\'" . web-mode)) (add-to-list 'auto-mode-alist '("\\.svelte\\'" . web-mode)) (setq web-mode-engines-alist '(("handlebars" . "\\.hbs\\'"))) (defun bnb/web-mode-hook () "Setup indentation when loading `web-mode`." (setq web-mode-markup-indent-offset 2 web-mode-css-indent-offset 2 web-mode-code-indent-offset 2)) :hook (web-mode . bnb/web-mode-hook))
15.8 HTML
15.8.1 Impatient mode
In order to play nicely with HTML+, it needs to be added to the filters of impatient mode.
(use-package impatient-mode :ensure t :mode "\\.html\\'" :config (add-to-list 'imp-default-user-filters '(mhtml-mode . nil)))
15.8.2 Emmet
Emmet mode allows for terse description of nested elements. There is great documentation on the approach at emmet.io.
(use-package emmet-mode :ensure t :commands (emmet-mode) :hook ((web-mode . emmet-mode) (sgml-mode . emmet-mode) (css-mode . emmet-mode)))
15.9 Plantuml
Not a programming language, but certainly a language.
(use-package plantuml-mode :defer :ensure t)
15.10 Pollen
(use-package pollen-mode :ensure t :defer t :mode (("\\.pp\\'" . pollen-mode))) (use-package company-pollen :defer t :ensure t)
16 Selectrum
(defun bnb/buffer-backward-kill-dwim (&optional arg) (interactive "p") (cond ((looking-back "/") (backward-kill-sexp)) (t (delete-backward-char 1)))) (use-package selectrum :ensure t :bind (:map selectrum-minibuffer-map (("DEL" . #'bnb/buffer-backward-kill-dwim))) :config (selectrum-mode t) (setq selectrum-count-style 'current/matches selectrum-show-indices nil file-name-shadow-properties '(invisible t))) (use-package selectrum-prescient :ensure t :after selectrum :custom (completion-styles '(flex substring partial-completion)) :config (setq prescient-persist-mode t) (selectrum-prescient-mode t))
16.1 Consult
https://github.com/minad/consult
(use-package consult :ensure t :bind (;; C-c bindings ("C-c h" . consult-history) ("C-c m" . consult-mode-command) ("C-c b" . consult-bookmark) ("C-c k" . consult-macro) ("C-c o" . consult-outline) ;; C-x bindings ("C-x b" . consult-buffer) ("C-x 4 b" . consult-buffer-other-window) ("C-x 5 b" . consult-buffer-other-frame) ("C-x r x" . consult-register) ("C-x r b" . consult-bookmark) ;; Custom M bindings ("M-g o" . consult-ouline) ("M-y" . consult-yank-pop)) :init (fset 'multi-occur #'consult-multi-occur))
16.2 Marginalia
https://github.com/minad/marginalia
(use-package marginalia :ensure t :init (marginalia-mode) (setq marginalia-annotators '(marginalia-annotators-heavy marginalia-annotators-light)))
17 Shells
There are two useful shells in emacs: eshell
and
ansi-term
.
17.1 Ansi Term
Some of the following settings were stolen from https://ogbe.net/emacsconfig.html.
These settings close ansi-term
when I exit the shell. They also
default to just launching zsh
instead of asking me
(preferred). Then it closes by setting up a hook to ensure some
nice functionality in the terminal mode window.
(defadvice term-sentinel (around bnb/advise-term-sentinel (proc msg)) (if (memq (process-status proc) '(signal exit)) (let ((buffer (process-buffer proc))) ad-do-it (kill-buffer buffer)) ad-do-it)) (ad-activate 'term-sentinel) (defadvice ansi-term (before force-zsh) (interactive (list "/bin/zsh"))) (ad-activate 'ansi-term) (defun bnb/term-mode-hook () "Setup `term-mode`." (goto-address-mode) (setq-local term-buffer-maximum-size 10000)) (add-hook 'term-mode-hook 'bnb/term-mode-hook) (defalias 'zsh 'ansi-term) (setq ansi-term-color-vector [term term-color-black term-color-red term-color-green term-color-yellow term-color-blue term-color-magenta term-color-cyan term-color-white] ansi-color-faces-vector [default bold shadow italic underline bold bold-italic bold])
17.2 Eshell
Built-in Eshell can provide a shell that works the same on windows or GNU/Linux. One of the really cool features is that you can define commands to use (like aliases) within the shell and have them directly integrate with emacs.
17.2.1 Eshell Settings
Turn off any $PAGER
settings inherited in the
environment. Because this is running in Emacs, there is no need
for a pager.
(setenv "PAGER" "cat")
17.2.2 Eshell Commands
Fast fingers are used to typing emacs
at a prompt to open a
file. This gives the same behavior in eshell
.
(defun eshell/emacs (&rest args) "Open a file in emacs the natural way" (if (null args) ;; If emacs is called by itself, then just go to emacs directly (bury-buffer) ;; If opening multiple files with a directory name, e.g. ;; > emacs bar/bar.txt foo.txt ;; then the names must be expanded to complete file paths. ;; Otherwise, find-file will look in the current directory which ;; would fail for 'foo.txt' in the example above. (mapc #'find-file (mapcar #'expand-file-name (eshell-flatten-list (reverse args))))))
One can also keep the shell active and open files in the other window.
(defun eshell/emo (&rest args) (mapc (lambda (f) (save-selected-window (find-file-other-window f))) (mapcar #'expand-file-name (eshell-flatten-list (reverse args)))))
I also setup some command aliases. Here, I create a long listing,
ll
, alias for ls
, a llc
varient with colored output, and an
emacs shortcut.
(with-eval-after-load "em-alias" '(progn (eshell/alias "em" "emacs") (eshell/alias "ll" "ls -Aloh") (eshell/alias "llc" "*ls -AlohG --color=always")))
On a windows box, setup grep to be a cygwin version.
(when (eq system-type 'windows-nt) (with-eval-after-load "eshell" (defun eshell/grep (&rest args) (eshell-grep "c:/cygwin/bin/grep.exe" args t))))
For Magit, there are some niceties to add.
(defun eshell/gst (&rest args) (magit-status-internal (pop args) nil) (eshell/echo)) (defun eshell/gd (&rest args) (magit-diff-unstaged) (eshell/echo)) (defun eshell/gds (&rest args) (magit-diff-staged) (eshell/echo))
17.2.3 Plan 9 Smart Shells
See the complete guide to mastering Eshell for more on this. Basically, the cursor stays on the command for editing if necessary.
(require 'eshell) (require 'em-smart) (setq eshell-where-to-jump 'begin) (setq eshell-review-quick-commands nil) (setq eshell-smart-space-goes-to-end t) (add-hook 'eshell-mode-hook 'eshell-smart-initialize)
18 AucTeX
Superb handling of TeX documents.
(use-package tex-site :defer 10 :ensure auctex :hook ((LaTeX-mode . flyspell-mode) (LaTeX-mode . LaTeX-math-mode) (LaTeX-mode . auto-fill-mode) (LaTeX-mode . orgtbl-mode) (doc-view-mode . auto-revert-mode)) :config (setq TeX-auto-untabify t TeX-auto-save t TeX-save-query nil TeX-parse-self t TeX-output-view-style (if (eq system-type 'windows-nt) (quote (("^pdf$" "." "SumatraPDF.exe -reuse-instance %o") ("^html?$" "." "start %o"))) (quote (("^pdf$" "." "evince -f %o") ("^html?$" "." "start %o")))) TeX-command-extra-options "-shell-escape" TeX-PDF-mode 1 TeX-engine 'xetex) (setq-default TeX-master nil) (add-to-list 'org-latex-packages-alist '("" "tikz" t)) (add-to-list 'org-latex-packages-alist '("" "minted" t)) (setq org-latex-create-formula-image-program 'imagemagick) (eval-after-load "preview" '(add-to-list 'preview-default-preamble "\\PreviewEnvironment{tikzpicture}" t)))
18.1 RefTeX
RefTeX provides navigation, easy references, easy citations and integrates well into AUCTeX.
(add-hook 'LaTeX-mode-hook 'turn-on-reftex)
Keystroke | Function |
---|---|
C-c = | Show TOC and jump to sections |
C-c ( | Insert a label |
C-c ) | Reference a label |
C-c [ | Insert a citation (from BibTex db) |
C-c < | Index entry |
C-c > | View index |
C-c & | View crossref |
18.2 TeX Settings
Here are some nice features to have enabled. Parse-self and auto-save will parse the file on load and save respectively. Untabify will remove tabs (real ones) before saving.
I also have a default of TeX-master
set to nil
. I used to have
it set to "master" as recommended in the documentation, but I had
bad results for LaTeX files generated on the fly.
For viewing the output, I can specify the command to use on the files generated in the process. However, the programs differ on GNU/Linux and Windows, so I have differing settings below.
18.3 XeTeX settings
To get more beautiful fonts, I use the XeTeX processor. I also use this in PDF mode.
18.4 DocView
Have docview
automatically revert the buffer.
19 Markdown
Everything can't be as nice as org-mode. Oh well.
(use-package markdown-mode :ensure t :commands (markdown-mode gfm-mode) :mode (("README\\.md\\'" . gfm-mode) ("\\.md\\'" . markdown-mode) ("\\.markdown\\'" . markdown-mode)) :init (setq markdown-command "multimarkdown"))
20 Orgmode
The one feature I cannot do without. Let's set up some basics.
20.1 Orgmode Initialization
Here are the initial settings that will invoke org-mode or need to be set when it is loaded.
(use-package org-mode :ensure org :delight (org-mode "🦄" :major) :mode "\\.org\\(.gpg|_archive\\)?\\'" :bind ("C-c t" . orgtbl-mode) ("C-c l" . org-store-link) ("C-c r" . org-capture) ("C-c b" . org-iswitchb) ("<f12>" . org-agenda) ("H-z" . org-agenda) ("H-g" . org-mac-grab-link) ("<apps>" . org-agenda) ("<f9> v" . visible-mode) ("<f9> g" . org-clock-goto) ("<f9> i" . org-clock-in) ("<f9> o" . org-clock-out) :config (bind-key "M-i" 'org-toggle-inline-images org-mode-map) :hook (org-babel-after-execute . (lambda () (org-display-inline-images t t))))
20.2 Auto mode
I add gpg and _archive to the list of known org files. These two
alternative extensions are for either encrypted org files
(.org.gpg
) or for archives (.org_archive
).
This mode is set above with use-package
.
20.3 Hooks
There are three hooks to consider. These are initialized in 20.1. First, I add in a keystroke to toggle the inline images.
The next hook just saves the org files opened before exiting emacs – just in case.
(add-hook 'bnb/kill-emacs-hooks 'org-save-all-org-buffers 'append)
The final hook shows images automatically. When I execute babel
to get graphs from my work logs, I hate having to toggle the inline
images on/off again. Here is a hook from Rick Frankel to save the
day.
20.4 Keys
20.4.1 Global
Some org-mode features are so useful that I need to have them be available globally.
- orgtbl-mode Use orgtbl in other modes
- org-store-link Store a link (context-aware) to the current location
- org-agenda Launch the agenda
- org-capture Capture a task/note
- org-iswitchb Switch org buffers
- visible-mode Show the file as-is (no special org handling)
- org-clock-in/org-clock-out Clock in/out of current subtree
20.4.2 Speed
Using org-mode efficiently for task management is best done with
speed keys. This are in effect when the cursor is on the first *
of a headline. And they come with an easy cheat-sheet by typing
?
. I enable this feature and add some of my own commands.
(setq org-use-speed-commands t org-speed-commands (quote (("0" . delete-window) ("1" . delete-other-windows) ("2" . split-window-vertically) ("3" . split-window-horizontally) ("h" . hide-other) ("s" . org-save-all-org-buffers) ("z" . org-add-note) ("N" . org-narrow-to-subtree) ("W" . widen) ("m" . org-mark-subtree) ("C" . org-global-cycle))))
20.5 Org TODO Configuration
This is the meat of what Org can do. Keeping track of todo items with due dates, tags, etc. is really powerful. And I get to customize it to suit my needs and my workflow.
20.5.1 Keywords
The keywords that org uses in the headlines exist as sequences describing the state changes. The sequences describe how you can cycle through the different states. However, I don't cycle through states and just select them. I find that is better for the large list of possibilities here.
The characters in ()
also
allow fast access to these states described here.
(setq org-todo-keywords (quote ((sequence "TODO(t)" "NEXT(n)" "|" "DONE(d!/!)") (sequence "WAITING(w@/!)" "SOMEDAY(s!)" "|" "CANCELED(c@/!)") (sequence "CANCELED(c@/!)"))))
I used to set org-todo-keyword-faces, but now I rely on theme settings.
20.5.2 Tags
Org uses tags on headlines for organization. I don't currently
use them much. I organize mainly by file with a file tag
specified via in-buffer settings (#+FILETAGS
).
However, a global tag list provides a selection list for the tagging interface. I use 'project' as my tag to easily differentiate simple tasks from more complex ones.
(setq org-tag-alist '(("PROJECT" . ?p)))
20.5.3 Mechanics
The todo interface allows easy selection of states and triggers on certain states to store notes.
Instead of cycling through states (and possibly triggering log entries), I prefer fast entry to jump right to the correct state. I also turn off the S-cursor transitions as state changes to avoid the logging prompts.
(setq org-use-fast-todo-selection t) (setq org-treat-S-cursor-todo-selection-as-state-change nil)
Upon changing the state of todo items, I can automatically add/remove tags with the following list. It's a bit lispy, but describes what happens upon entry in the specified state. The state named as a string has tuples of tags and flags. 't' indicates to set the flag, empty means to remove it.
(setq org-todo-state-tags-triggers (quote (("CANCELED" ("CANCELED" . t)) ("WAITING" ("WAITING" . t)) ("SOMEDAY" ("SOMEDAY" . t)) (done ("WAITING")) ("TODO" ("WAITING") ("CANCELED")) ("NEXT" ("WAITING")) ("DONE" ("WAITING") ("CANCELED")))))
Along with tags and states are priorities. I do not use task priorities myself so I turn them off.
(setq org-enable-priority-commands nil)
- Logging
Org allows logging of states. I turn this on to prompt myself for reasons behind specific state changes. There is also a setting to set a different drawer for clocking and logs.
(setq org-log-done (quote note) org-log-redeadline (quote time) org-log-reschedule (quote time) org-log-into-drawer t org-drawers '("PROPERTIES" "LOGBOOK" "CLOCK"))
- Sub-tasks
Naturally, some tasks are projects composed of smaller sub-tasks. Org allows for this as well. I like to enforce the dependencies of regular todo items and plain checkbox lists. In this way, the overall item cannot change to done without the completion of the sub-tasks.
(setq org-enforce-todo-checkbox-dependencies t org-enforce-todo-dependencies t)
Because of the previous enforcement of state, I can also automatically infer when a parent state is complete. The following code marks the parent complete once the sub-tasks are all done.
(defun org-summary-todo (n-done n-not-done) "Switch entry to DONE when all sub-entries are done, to TODO otherwise." (let (org-log-done org-log-states) (org-todo (if (= n-not-done 0) "DONE" "TODO")))) (add-hook 'org-after-todo-statistics-hook 'org-summary-todo)
20.6 Capture
Capturing is crucial to a task system and in this vein, org is no slouch. The capture templates define what get captures, where it goes, and what the user needs to type.
(setq org-capture-templates '(("t" "Todo" entry (file "~/Documents/Org/Refile.org") "* TODO %?\n %U\n%^{Score}p" :clock-in t :clock-resume t) ("r" "todo (Remember location)" entry (file "~/Documents/Org/Refile.org") "* TODO %?\n %U\n %a" :clock-in t :clock-resume t) ("n" "Note" entry (file "~/Documents/Org/Refile.org") "* %? :NOTE:\n %U\n %a\n :CLOCK:\n :END:") ("c" "Capture current TODO mix in table" table-line (file+headline "~/Documents/Org/WeeklyReports.org" "Burndown") "%(bnb/org-count-tasks-by-status)") ("s" "Capture Weekly Score in table" table-line (file+headline "~/Documents/Org/WeeklyReports.org" "Scores") "%(bnb/add-weekly-score-table-entry)") ("e" "Capture Weekly time in table" table-line (file+headline "~/Documents/Org/WeeklyReports.org" "Minutes") "%(bnb/org-time-logged-table-entry)") ("u" "Url" entry (file "~/Documents/Org/Refile.org") "* TODO %?\n %U\n\n %(org-mac-chrome-get-frontmost-url)") ("m" "Mail" entry (file "~/Documents/Org/Refile.org") "* TODO %?\n %U\n\n %(org-mac-message-get-links \"s\")")))
There are five main capture templates here. The first two store a todo item in my Refile.org file. The only difference is automatic (contextual) link storage in the second case.
The next item simply stores a note. The next for "Weekly Report" is a work in progress. I think that I'll have to either settle for a proper datetree or write a custom function.
The final item is not for direct use, but through the
org-protocol
interface and org-outlook
usage. This lets me
add a link to an Outlook message on windows. I can then get an
email at work, mark it to store in emacs and quickly get back to
the message later.
20.6.1 Capture-template helpers for data tables
These helpers provide functionality used in the capture templates above.
Modified from Sacha Chua, this code get the current mix of tasks in the agenda files. I use this as part of my weekly review for task amount and mix at a glance.
(defun bnb/org-count-tasks-by-status () "Create a table entry for the tracking of task mix." (interactive) (let ((counts (make-hash-table :test 'equal)) (today (format-time-string "%Y-%m-%d" (current-time))) values output) (org-map-entries (lambda () (let ((status (elt (org-heading-components) 2))) (when status (puthash status (1+ (or (gethash status counts) 0)) counts)))) "-HOME" 'agenda) (setq values (mapcar (lambda (x) (or (gethash x counts) 0)) '("DONE" "TODO" "WAITING" "CANCELLED" "SOMEDAY"))) (setq output (concat "| " today " | " (mapconcat 'number-to-string values " | ") " | " (number-to-string (apply '+ values)) " | " (number-to-string (round (/ (* 100.0 (car values)) (apply '+ values)))) "% |")) (if (called-interactively-p 'any) (insert output) output)))
I also have a helper function to get the score of done tasks closed within the last week. I store this in a table line with year and workweek number.
(defun bnb/add-weekly-score-table-entry () "Track my weekly scores in a table." (let ((score (apply '+ (org-map-entries (lambda () (string-to-number (or (org-entry-get (point) "Score") "0"))) "/DONE" 'agenda))) (year (format-time-string "%Y" (current-time))) (ww (number-to-string (bnb/workweek)))) (format "| %s | %s | %s |" year ww score)))
How about the hours logged last week? Let's give that a go.
(defun bnb/org-time-logged-table-entry (&optional additional-weeks) "Insert table of minutes per category. Optionally provide ADDITIONAL-WEEKS to get more history" (interactive "P") (unless additional-weeks (setq additional-weeks 0)) (let* ((minh (make-hash-table :test 'equal)) (now (decode-time)) (start (encode-time 0 0 0 (- (nth 3 now) (nth 6 now) (* 7 (or additional-weeks 1))) (nth 4 now) (nth 5 now))) (today (format-time-string "%Y-%m-%d" (current-time)))) ;; Collect minutes clocked per category (org-map-entries (lambda () (let ((category (org-entry-get-with-inheritance "CATEGORY" t)) (minutes (org-clock-sum-current-item start))) (puthash category (+ minutes (or (gethash category minh) 0)) minh))) "LEVEL=1" 'agenda) ;; Print out table lines (let ((rows nil)) (maphash (lambda (k v) (when (> v 0) (setq rows (cons (format "| %s | %s | %d |" today k v) rows)))) minh) (if (called-interactively-p 'any) (insert (mapconcat 'identity rows "\n")) (mapconcat 'identity rows "\n")))))
20.7 Refile
Refiling notes is also spectacular with Org. That is what makes it possible for me to simply put every captured item into Refile.org and worry about organization later.
For my setup, I use separate files that hold a singular Tasks headline. Because of that, I turn on caching first.
For the refile targets, I will allow up to 2 levels of search for filing in any of the agenda files. For refiling within the current file, I set the max to five levels. Anything deeper than six levels will exhaust the depth of my thought.
Finally, I set the filenames to be first for refiling.
(setq org-refile-use-cache t org-refile-targets '((org-agenda-files :maxlevel . 2) (nil :maxlevel . 5)) org-refile-use-outline-path 'file)
20.8 Agenda
Once I have captured and refiled my tasks, I need to remember to do them and see what is on the agenda. The ways to view the tasks at hand are nicely programmable.
Some basic settings control small tidbits in the agenda. I turn on tags in the agenda line, show the logged items for the day, and only show a time grid if a scheduled tasks exists.
(setq org-agenda-show-inherited-tags t org-agenda-log-mode-items '(clock) org-agenda-clockreport-parameter-plist '(:link nil :maxlevel 2 :fileskip0 t) ;;org-agenda-block-separator ?┄ org-agenda-block-separator nil org-agenda-dim-blocked-tasks nil org-agenda-inhibit-startup t org-agenda-breadcrumbs-separator " ❱ ")
20.8.1 Category Icons
Org-mode can show category icons in some agenda views. The
underlying setting is just an alist
of categories and the icons
to use.
(setq org-agenda-category-icon-alist `(("[rR]efile" ,(list (all-the-icons-faicon "inbox")) nil nil :ascent center) ("[Pp]ersonal" ,(list (all-the-icons-faicon "tasks")) nil nil :ascent center) (".*" ,(list (all-the-icons-material "tab")) nil nil :ascent center)))
20.8.2 Views
The key to knowing what work there is the agenda views. These
provide a landscape to list, filter or manipulate
tasks. org-agenda-custom-commands
defines which views are
available by default.
First, I define a little helper function (from Sacha Chua) to display a note with agenda.
(defun bnb/org-agenda-with-tip (arg) "Show agenda for ARG days." (org-agenda-list arg) (let ((inhibit-read-only t) (pos (point))) (goto-char (point-max)) (goto-char pos)))
WIP from: https://github.com/fniessen/emacs-leuven/blob/master/org-custom-agenda-views.el
;; Reset everything to nil (setq org-agenda-custom-commands nil)
(add-to-list 'org-agenda-custom-commands '("o" "My Agenda" ((todo "TODO" ( (org-agenda-overriding-header "\n⚡ Do Today\n┄┄┄┄┄┄┄┄┄┄") (org-agenda-remove-tags t) (org-agenda-prefix-format " %-2i %-15b") (org-agenda-todo-keyword-format "") )) (agenda "" ( (org-agenda-start-day "+0d") (org-agenda-span 5) (org-agenda-overriding-header "⚡ Schedule\n┄┄┄┄┄┄┄┄┄┄") (org-agenda-repeating-timestamp-show-all nil) (org-agenda-remove-tags t) (org-agenda-prefix-format " %-3i %-15b %t%s") (org-agenda-todo-keyword-format " ☐ ") (org-agenda-current-time-string "⮜┈┈┈┈┈┈┈ now") (org-agenda-scheduled-leaders '("" "")) (org-agenda-time-grid (quote ((daily today remove-match) (0900 1200 1500 1800 2100) " " "┈┈┈┈┈┈┈┈┈┈┈┈┈"))) )) )))
(add-to-list 'org-agenda-custom-commands '("b" "Agenda" bnb/org-agenda-with-tip))
(add-to-list 'org-agenda-custom-commands '("c" . "COLLECT...") t)
(add-to-list 'org-agenda-custom-commands '("cb" "CollectBox" ((alltodo ""))))
(add-to-list 'org-agenda-custom-commands '("f" . "FOCUS...") t)
(add-to-list 'org-agenda-custom-commands `("f." "Today" ((agenda "" ((org-agenda-entry-types '(:timestamp :sexp)) (org-agenda-overriding-header (concat "CALENDAR Today" (format-time-string "%a %d" (current-time)))) (org-agenda-span 'day))) (tags-todo "LEVEL=1+REFILE" ((org-agenda-overriding-header "COLLECTBOX (Unscheduled)"))) (tags-todo "DEADLINE=\"<+0d>\"" ((org-agenda-overriding-header "DUE TODAY") (org-agenda-skip-function '(org-agenda-skip-entry-if 'notedeadline)) (org-agenda-sorting-strategy '(priority-down)))) (tags-todo "DEADLINE<\"<+0d>\"" ((org-agenda-overriding-header "OVERDUE") (org-agenda-skip-function '(org-agenda-skip-entry-if 'notedeadline)) (org-agenda-sorting-strategy '(priority-down)))) (agenda "" ((org-agenda-entry-types '(:scheduled)) (org-agenda-overriding-header "SCHEDULED") (org-agenda-skip-function '(org-agenda-skip-entry-if 'todo 'done)) (org-agenda-sorting-strategy '(priority-down time-down)) (org-agenda-span 'day) (org-agenda-start-on-weekday nil) (org-agenda-time-grid nil))) (todo "DONE" ((org-agenda-overriding-header "COMPLETED")))) ((org-agenda-format-date "") (org-agenda-start-with-clockreport-mode nil))) t)
(add-to-list 'org-agenda-custom-commands '("fh" "Hotlist" ((tags-todo "DEADLINE<\"<+0d>\"" ((org-agenda-overriding-header "OVERDUE"))) (tags-todo "DEADLINE>=\"<+0d>\"+DEADLINE<=\"<+1w>\"" ((org-agenda-overriding-header "DUE IN NEXT 7 DAYS"))) (tags-todo "DEADLINE=\"\"+FLAGGED|DEADLINE>\"<+1w>\"+FLAGGED" ((org-agenda-overriding-header "FLAGGED")))) ((org-agenda-todo-ignore-scheduled 'future))) t)
(add-to-list 'org-agenda-custom-commands '("r" . "REVIEW...") t) (add-to-list 'org-agenda-custom-commands '("ra" . "All Tasks...") t)
(add-to-list 'org-agenda-custom-commands '("rad" "All Tasks (grouped by Due Date)" ((tags-todo "DEADLINE<\"<+0d>\"" ((org-agenda-overriding-header "OVERDUE") (org-agenda-skip-function '(org-agenda-skip-entry-if 'notdeadline)))) (tags-todo "DEADLINE=\"<+0d>\"" ((org-agenda-overriding-header "DUE TODAY") (org-agenda-skip-function '(org-agenda-skip-entry-if 'notdeadline)))) (tags-todo "DEADLINE=\"<+1d>\"" ((org-agenda-overriding-header "DUE TOMORROW") (org-agenda-skip-function '(org-agenda-skip-entry-if 'notdeadline)))) (tags-todo "DEADLINE>\"<+1d>\"+DEADLINE<=\"<+7d>\"" ((org-agenda-overriding-header "DUE WITHIN A WEEK") (org-agenda-skip-function '(org-agenda-skip-entry-if 'notdeadline)))) (tags-todo "DEADLINE>\"<+7d>\"+DEADLINE<=\"<+28d>\"" ((org-agenda-overriding-header "DUE WITHIN A MONTH") (org-agenda-skip-function '(org-agenda-skip-entry-if 'notdeadline)))) (tags-todo "DEADLINE>\"<+28d>\"" ((org-agenda-overriding-header "DUE LATER") (org-agenda-skip-function '(org-agenda-skip-entry-if 'notdeadline)))) (tags-todo "TODO={WAIT}" ((org-agenda-overriding-header "WAITING FOR") (org-agenda-skip-function '(org-agenda-skip-entry-if 'deadline)))) (todo "" ((org-agenda-overriding-header "WAITING FOR") (org-agenda-skip-function '(org-agenda-skip-entry-if 'deadline))))) ((org-agenda-sorting-strategy '(priority-down)) (org-agenda-write-buffer-name "All Tasks (grouped by Due Date)")) "~/Documents/Org/all-tasks-by-due-date.pdf") t)
(add-to-list 'org-agenda-custom-commands '("ra1" "All Tasks with a due date" ((alltodo "")) ((org-agenda-overriding-header "All Tasks (sorted by Due Date)") (org-agenda-skip-function '(org-agenda-skip-entry-if 'notdeadline)) (org-agenda-sorting-strategy '(deadline-up)))) t)
(add-to-list 'org-agenda-custom-commands '("rag" "Grouped Tasks") ())
(add-to-list 'org-agenda-custom-commands '("rt" . "Timesheet...") t)
;; Show what happened today. (add-to-list 'org-agenda-custom-commands '("rtd" "Daily Timesheet" ((agenda "")) ((org-agenda-log-mode-items '(clock closed)) (org-agenda-overriding-header "DAILY TIMESHEET") (org-agenda-show-log 'clockcheck) (org-agenda-span 'day) (org-agenda-start-with-clockreport-mode t) (org-agenda-time-grid nil))) t) ;; Show what happened this week. (add-to-list 'org-agenda-custom-commands '("rtw" "Weekly Timesheet" ((agenda "")) ( ;; (org-agenda-format-date "") (org-agenda-overriding-header "WEEKLY TIMESHEET") (org-agenda-skip-function '(org-agenda-skip-entry-if 'timestamp)) (org-agenda-span 'week) (org-agenda-start-on-weekday 1) (org-agenda-start-with-clockreport-mode t) (org-agenda-time-grid nil))) t)
(add-to-list 'org-agenda-custom-commands '("rc" . "Calendar...") t) (add-to-list 'org-agenda-custom-commands '("rc7" "Events and appointments for 7 days" ((agenda "")) ((org-agenda-entry-types '(:timestamp :sexp)) ;; (org-agenda-overriding-header "Calendar for 7 days") (org-agenda-span 'week) (org-agenda-format-date "\n%a %d") ;; (org-agenda-date-weekend ... new face ...) (org-agenda-time-grid nil))) t)
(add-to-list 'org-agenda-custom-commands '("rw" "Weekly review" ((tags "CATEGORY={@REFILE}&LEVEL<=2" ((org-agenda-overriding-header "NEW TASKS"))) (agenda "" ((org-agenda-clockreport-mode t) (org-agenda-format-date (concat "\n" "%Y-%m-%d" " %a " (make-string (window-width) ?_))) (org-agenda-overriding-header "PAST WEEK") (org-agenda-prefix-format " %?-11t %i %-12:c% s") (org-agenda-show-log 'clockcheck) (org-agenda-span 7) (org-agenda-start-day "-1w") (org-deadline-warning-days 0))) (agenda "" ((org-agenda-overriding-header "NEXT MONTH") (org-agenda-span 'month) (org-agenda-start-day "+0d") (org-deadline-warning-days 0))) (todo "PROJECT" ((org-agenda-overriding-header "PROJECT LIST"))) (todo "DONE|PROJECTDONE" ((org-agenda-overriding-header "Candidates to be archived"))))))
(use-package org-super-agenda :defer :ensure t :quelpa (org-super-agenda :fetcher github :repo "alphapapa/org-super-agenda") :config (org-super-agenda-mode t) (add-to-list 'org-agenda-custom-commands '("rag" "Grouped Tasks" ((todo "" ((org-super-agenda-groups '((:name "All Tasks" :auto-category t)))))))) (add-to-list 'org-agenda-custom-commands '("f1" "Score 1 Tasks" ((tags "+Score=1" ((org-super-agenda-groups '((:name "Score 1 Tasks" :auto-category t)))))))) (add-to-list 'org-agenda-custom-commands '("f2" "Score 2 Tasks" ((tags "+Score=2" ((org-super-agenda-groups '((:name "Score 1 Tasks" :auto-category t)))))))) (add-to-list 'org-agenda-custom-commands '("f3" "Score 3 Tasks" ((tags "+Score=3" ((org-super-agenda-groups '((:name "Score 1 Tasks" :auto-category t)))))))) (add-to-list 'org-agenda-custom-commands '("f5" "Score 5 Tasks" ((tags "+Score=5" ((org-super-agenda-groups '((:name "Score 1 Tasks" :auto-category t)))))))) (add-to-list 'org-agenda-custom-commands '("f8" "Score 8 Tasks" ((tags "+Score=8" ((org-super-agenda-groups '((:name "Score 1 Tasks" :auto-category t)))))))))
Phew! That is a lot of lisp! It is easiest to describe each view by the key that triggers it.
a
Agenda with tip (keystroke tip)w
Tasks waiting on somethingr
Refile New notes and tasksn
Next Any task with the NEXT tagA
Tasks ready for Archiveu
Upcoming tasks Scheduled or due in the next week.U
Unscheduled tasksP
Printable agenda Formats tasks at the top with upcoming items below.S
Scoreless tasks Use this to get the scoreless tasks and edit in column modeh
Habits#
Stuck projectsz
Agenda with Personal Filesc
Select default clocking task
20.9 Export
Here are some global export settings make sense for HTML and \LaTeX.
20.9.1 HTML
For HTML, I just want to inline the links to images.
(setq org-export-html-inline-images t)
I also used to suppress the postamble with
org-export-html-postamble
.
(setq org-html-postamble nil)
I'll use the fancy HTML5 export by default.
(setq org-html-doctype "html5" org-html-html5-fancy t)
I like to have striped tables in email, but this is terribly
difficult due to cruddy CSS support. Luckily,
org-html-table-row-tags
saves the day and assigns the right
classes to the table rows. Now styling can be done in CSS-reduced
instances.
(setq org-html-table-row-tags (cons '(cond (top-row-p "<tr class=\"tr-top\">") (bottom-row-p "<tr class=\"tr-bottom\">") (t (if (= (mod row-number 2) 1) "<tr class=\"tr-odd\">" "<tr class=\"tr-even\">"))) "</tr>"))
20.9.2 LaTeX
For \LaTeX, I want to convert fragments to images, and use minted
for any source blocks. I also want to have xelatex
as the
backend.
(setq org-export-latex-listings 'minted org-export-latex-custom-lang-environments '((emacs-lisp "common-lispcode")) org-export-latex-minted-options '() org-highlight-latex-and-related '(latex script entities) org-latex-to-pdf-process '("xelatex -shell-escape -interaction nonstopmode -output-directory %o %f" "xelatex -shell-escape -interaction nonstopmode -output-directory %o %f" "xelatex -shell-escape -interaction nonstopmode -output-directory %o %f"))
Also, I want to enable some of the other contributed exporters. To do this, simply require the files necessary that are not on by default.
I add exporters for github-flavored markdown and tufte html.
(use-package ox-gfm :defer 10) (use-package ox-tufte :defer 10)
20.9.3 EPUB
E-readers may be a thing that sticks around.
(use-package ox-epub :after org-mode)
20.10 Clocking
I have found clocking to be useful in understanding where my time goes. And Org makes this easy, fast and painless to do. So very nice.
The clock has some general settings around persistence (resuming clocks), history length and resuming a task after clocking in twice (interrupted task).
(org-clock-persistence-insinuate)
(setq org-clock-history-length 28
org-clock-in-resume t)
Behavior of the clock can change to accommodate other needs. I like having clocks log into a specific drawer. Also, it is nice to remove zero-time clocks and clock out automatically when an item completes.
(setq org-clock-into-drawer "CLOCK" org-clock-out-remove-zero-time-clocks t org-clock-out-when-done t)
Two settings help resolve most clock issues that I have seen. Persisting the clock across sessions helps prevent loss of time by accident. Auto-resolution of open clocks help prompt how to handle the situation where a dangling clock exists.
(setq org-clock-persist 'history
org-clock-auto-clock-resolution 'when-no-clock-is-running)
Two final settings regarding clocking setup how I change and view the clocks. I want any clock reports to include the currently clocked task as well. And for clock editing, I change to 15 minute increments.
(setq org-clock-report-include-clocking-task t
org-time-stamp-rounding-minutes '(1 15))
20.11 Modules
Org-modules allow for specific functionality within org-mode.
(setq org-modules
'(org-bbdb
org-bibtex
org-crypt
org-gnus
org-id
org-info
org-jsinfo
org-habit
org-inlinetask
org-irc
org-plot
org-protocol
org-bookmark
org-calc))
20.11.1 Habit
Some tasks repeat, but you still want to log when you have done
it. I use this to help me always do my weekly or yearly
reviews. By including it in org-modules
, habits get activated.
My one setting blow sets a width for the graph in Agenda View.
(setq org-habit-graph-column 50)
20.12 Babel
(org-babel-do-load-languages 'org-babel-load-languages '((calc . t) (C . t) (ditaa . t) (dot . t) (emacs-lisp . t) (gnuplot . t) (latex . t) (maxima . t) (perl . t) (plantuml . t) (python . t) (ruby . t) (shell . t) (sqlite . t) (sql . t) (R . t)))
20.12.1 Extra Babel Packages
(use-package ob-http :after org-mode) (use-package ob-restclient :after org-mode :ensure t :quelpa (ob-restclient :fetcher github :repo "alf/ob-restclient.el") :config (org-babel-do-load-languages 'org-babel-load-languages (append org-babel-load-languages '((restclient . t)))))
20.13 Miscellaneous Settings
20.13.1 Columns
The default columns are as follows.
(setq org-columns-default-format "%80ITEM(Task) %5Score{+} %10Effort(Effort){:} %10CLOCKSUM")
20.13.2 Automatically save org files
I like to save early and often. In earlier versions of orgmode, I sometimes had the capture buffer/timer crash on me. So, now I save at the top of every hour to be sure.
(run-at-time "00:59" 3600 'org-save-all-org-buffers)
20.13.3 File Applications
This list lets org know how to handle the links of given file
types. Most things open inside emacs
, but the others
set to default rely on the OS to supply a program.
(setq org-file-apps '((auto-mode . emacs) ("\\.x?html?\\'" . default) ("\\.pdf\\'" . default) ("\\.mm\\'" . default)))
20.13.4 Goto Interface
By using C-c C-j
, you can jump easily around a large orgfile
such as this one. Naturally, the interface you use to do so is
customizable.
I explicitly set it to the default because I sometimes go back
and forth with the default and outline-path-completion
setting.
(setq org-goto-interface 'outline-path)
20.13.5 Special Control Keys
Orgmode has a different idea of some of the default emacs commands to make it easier to work with the structures involved.
For C-a
or C-e
within a headline, it will only try to
navigate the headline text the first time. Additional keypresses
will move to the true beginning/ending of lines.
C-k
also can behave specially in headlines depending on its
location. When point is at the beginning, it will kill the
headline and the folded subtree below. In the middle of a
headline, it kills the headline text up to the tags. After the
headline text, it kills the tags.
(setq org-special-ctrl-a/e t
org-special-ctrl-k t)
20.13.6 Auto-revert mode
If the org files are under DVCS like git, then the edits may happen while open in emacs.
This is a global setting, but most useful for the org files that exists elsewhere.
(use-package autorevert :diminish " " :custom (global-auto-revert-mode t))
20.13.7 IDO Integration
IDO integrates well into orgmode. Anytime completion is necessary, I like to use the IDO mechanics.
The outline-path-completion
may conflict with IDO, so then it
is best to have it not use IDO in this case.
(setq org-completion-use-ido t
org-outline-path-complete-in-steps nil)
20.13.8 Display settings
There are a collection of settings that define how the headlines, subtrees, and notes render.
For the headline stars, there are two settings of note. I am explicit that I do not want only odd levels. I also like to hide the leading stars.
(setq org-odd-levels-only nil
org-hide-leading-stars nil)
Cycling the headline states can produce different views of the
files. I like this to be as compact as possible, so I try to
squash the lines between the collapsed trees. There is also a
flag to open a file collapsed. This I like too – I get a
compact view of the file and can jump to a relevant section with
C-c C-j
.
(setq org-cycle-separator-lines 0
org-startup-folded 'content)
When using SRC-blocks, org can provide highlighting native to the SRC type. Note that this may slow down some files.
(setq org-src-fontify-natively t)
20.13.9 Insertion
I define when org should leave a blank line before an item. In my case it is headings and plain list items.
(setq org-blank-before-new-entry '((heading)
(plain-list-item)))
Also, when inserting a new heading, do so after the current subtree.
(setq org-insert-heading-respect-content t)
20.13.10 Properties
(setq org-global-properties '(("STYLE_ALL" . "habit") ("Effort_ALL" . "0:10 0:30 1:00 2:00 3:00 4:00") ("Score_ALL" . "1 2 3 5 8")))
20.13.11 Teleport
From the Kitchin Group, I can have a nice teleport function for org sections. Using a speed command on the current headline kills it and then presents avy-style markers to select the insertion point.
By default the teleported headline will be inserted after the target. With a prefix argument, it will preceed the target.
(defun bnb/org-teleport (&optional arg) "Teleport the current heading to after a headline selected with avy. With a prefix ARG move the headline to before the selected headline. With a numeric prefix, set the headline level. If ARG is positive, move after, and if negative, move before." (interactive "P") ;; Kill current headline (org-mark-subtree) (kill-region (region-beginning) (region-end)) ;; Jump to a visible headline (avy-with avy-goto-line (avy--generic-jump "^\\*+" nil avy-style)) (cond ;; Move before and change headline level ((and (numberp arg) (> 0 arg)) (save-excursion (yank)) ;; arg is what we want, second is what we have ;; if n is positive, we need to demote (increase level) (let ((n (- (abs arg) (car (org-heading-components))))) (cl-loop for i from 1 to (abs n) do (if (> 0 n) (org-promote-subtree) (org-demote-subtree))))) ;; Move after and change level ((and (numberp arg) (< 0 arg)) (org-mark-subtree) (goto-char (region-end)) (when (eobp) (insert "\n")) (save-excursion (yank)) ;; n is what we want and second is what we have ;; if n is positive, we need to demote (let ((n (- (abs arg) (car (org-heading-components))))) (cl-loop for i from 1 to (abs n) do (if (> 0 n) (org-promote-subtree) (org-demote-subtree))))) ;; move to before selection ((equal arg '(4)) (save-excursion (yank))) ;; move to after selection (t (org-mark-subtree) (goto-char (region-end)) (when (eobp) (insert "\n")) (save-excursion (yank)))) (outline-hide-leaves))
(add-to-list 'org-speed-commands (cons "k" (lambda () (org-mark-subtree) (kill-region (region-beginning) (region-end))))) (add-to-list 'org-speed-commands (cons "q" (lambda () (avy-with avy-goto-line (avy--generic-jump "^\\*+" nil avy-style))))) (add-to-list 'org-speed-commands (cons "T" 'bnb/org-teleport))
20.13.12 Plantuml
Setup the path for orgmode to find the jar needed.
(setq org-plantuml-jar-path "/usr/local/Cellar/plantuml/1.2017.18/libexec/plantuml.jar")
20.14 Pretty Org-mode
This collection of settings enhances the visual appeal when working in org-mode.
First, some initial built-in settings to make.
(setq org-hide-leading-stars t
org-hide-emphasis-markers t
org-fontify-done-headline t
org-pretty-entities t)
Here's some fun
(add-hook 'org-mode-hook (lambda () (mapc (lambda (pair) (push pair prettify-symbols-alist)) '(("#+BEGIN_SRC" . "⌈") ("#+END_SRC" . "⌊") ("#+begin_src" . "⌈") ("#+end_src" . "⌊") (">=" . "≥") ("=>" . "⇨")))))
20.14.1 Org Bullets
(use-package org-bullets :ensure t :custom (org-bullets-bullet-list '("◉" "◊" "○" "⧫" "✸" "⬨" "⬟" "⬧" "⬢" "⬫" "⌑" "⬪" "▱")) (org-ellipsis "˯") ;; Options: ˯⇂↯⤵🠻🢗 :hook (org-mode . org-bullets-mode))
20.15 Org Repo Todo PENDING
Make it easy to setup a TODO.org
from within a repo. I use this
to capture thoughts while coding
(use-package org-repo-todo :ensure t :bind ("s-;" . ort/capture-todo) ("s-'" . ort/capture-checkitem) ("s-`" . ort/goto-todos))
20.16 Org projectile PENDING
Make it easy to capture tasks into the right projects and setup a project todo.
(use-package org-projectile :bind ("C-c n p" . org-projectile:project-todo-completing-read) :ensure t :config (org-projectile:per-repo) (add-to-list 'org-capture-templates (org-projectile:project-todo-entry)) (setq org-agenda-files (append org-agenda-files (org-projectile:todo-files)) org-projectile:per-repo-filename "Tasks.org"))
20.17 Org Ref
(use-package org-ref :defer 10 :config (setq org-ref-notes-directory "~/Documents/Personal/Org/Biblio/" org-ref-bibliography-notes "~/Documents/Personal/Org/Biblio/index.org" org-ref-default-bibliography '("~/Documents/Personal/Org/Biblio/index.bib") org-ref-pdf-directory "~/Documents/Personal/Org/Biblio/lib"))
20.18 Org Noter
Taking notes in a PDF is a useful trick. org-noter
lets me do just that.
(use-package org-noter :ensure t :bind ("H-n" . org-noter))
20.19 Org Roam
The best of all worlds? Org-mode and a Zettelkasten system? Yes, Org-roam sets up a knowledge capture and organization system built on the principles of a Zettelkasten system.
(use-package org-roam :ensure t :delight " 𝕫" :hook (after-init . org-roam-setup) :init (setq org-roam-v2-ack t) :custom (org-roam-directory "~/Documents/zettel") :bind ((("C-c n i" . org-roam-node-insert) ("C-c n f" . org-roam-node-find) ("C-c n c" . org-roam-capture) ("C-c n I" . org-roam-insert-immediate)) :map org-roam-mode-map (("C-c n l" . org-roam) ("C-c n t" . org-roam-dailies-find-today) ("C-c n w" . org-roam-dailies-find-tomorrow) ("C-c n d" . org-roam-date) ("C-c n f" . org-roam-find-file) ("C-c n g" . org-roam-show-graph))))
20.19.1 Company Org Roam
(use-package company-org-roam :ensure t :quelpa (company-org-roam :fetcher github :repo "org-roam/company-org-roam") :config (push 'company-org-roam company-backends))
20.20 Org QL
(use-package org-ql :ensure t :quelpa (org-ql :fetcher github :repo "alphapapa/org-ql") :commands (org-ql-search) :config (progn (require 'org-habit)) :ensure t)
21 Calc
Working in computer land, I add these additional units to calc
.
(use-package calc :commands (calc) :init (setq math-additional-units '((GiB "1024 * MiB" "Giga Byte") (MiB "1024 * KiB" "Mega Byte") (KiB "1024 * B" "Kilo Byte") (B nil "Byte") (Gib "1024 * Mib" "Giga bit") (Mib "1024 * Kib" "Mega bit") (Kib "1024 * b" "Kilo bit") (b nil "bit") )))
22 Server
Using Emacs as a server is a great way to keep the power responsive.
(when (and (or (eq system-type 'windows-nt) (eq system-type 'darwin)) (not (and (boundp 'server-clients) server-clients)) (not (daemonp))) (server-start))
I need to look into the TCP connections to see how that work across machines. Perhaps it can be useful in a multi-machine work environment.
23 Local customizations (custom.el)
I typically use the customize interface to generate any local settings such as proxies, paths, fonts, etc. that may vary from machine to machine.
(setq custom-file "~/.emacs.d/custom.el") (load-file custom-file)
24 Local customizations (user-login-name)
I also intend to have a generic call to an installed local file
that may need to behave differently from custom.el
. This loads
last so that it can modify any existing setting made here to work
on the specific system in question.
In the code below, I add ~/.emacs.d/
to the load path and have a
protected call to load-library
. If the file exists, it gets
loaded, otherwise the error normally returned if the file is
non-existent gets ignored.
(condition-case err (progn (load-file (format "~/.emacs.d/%s.el" user-login-name)) (message "Loaded local settings file %s.el" user-login-name)) (file-error (message "Skipping %s library as it does not exist." user-login-name)) nil)