This is my emacs configuration entry point. It is written in the literate programming style in this org-mode file. The embedded code blocks are extracted when the init.el file is loaded, and then the extracted files are loaded to complete the environmental configuration.
Pieces of this configuration have been taken from Magnar Sveen, Sascha Chua, Uncle Dave, David Wilson and a host of others referenced in various places on the internet, but primarily Emacs Wiki.
Obviously, you’ll want to change this to match your personal credentials.
(setq user-full-name "Brian O'Reilly"
user-mail-address "[email protected]")
which-key is a useful UI panel that appears when you start pressing any key binding in Emacs to offer you all possible completions for the prefix. For example, if you press C-c
(hold control and press the letter c
), a panel will appear at the bottom of the frame displaying all of the bindings under that prefix and which command they run. This is very useful for learning the possible key bindings in the mode of your current buffer.
(use-package which-key
:ensure t
:diminish which-key-mode
:config
(which-key-mode)
(setq which-key-idle-delay 1))
Sources for this section include Magnar Sveen and Sacha Chua.
The diminish package appears to have been subsumed into the Crux package by Bodizar Bhatzov.
(use-package diminish
:ensure t)
;; These functions are useful. Activate them. This use of #'put is
;; strange, but this feature uses symbol properties.
(put 'downcase-region 'disabled nil)
(put 'upcase-region 'disabled nil)
(put 'narrow-to-region 'disabled nil)
(put 'dired-find-alternate-file 'disabled nil)
;; Answering just 'y' or 'n' will do
(defalias 'yes-or-no-p 'y-or-n-p)
;; Keep all backup and auto-save files in one directory
(setq backup-directory-alist '(("." . "~/.emacs.d/backups")))
(setq auto-save-file-name-transforms '((".*" "~/.emacs.d/auto-save-list/" t)))
;; UTF-8 please
(setq locale-coding-system 'utf-8) ; pretty
(set-terminal-coding-system 'utf-8) ; pretty
(set-keyboard-coding-system 'utf-8) ; pretty
(set-selection-coding-system 'utf-8) ; please
(prefer-coding-system 'utf-8) ; with sugar on top
;; tabs never in code.
(setq-default indent-tabs-mode nil)
(setq-default indicate-empty-lines t)
;; Don't count two spaces after a period as the end of a sentence.
;; Just one space is needed.
(setq sentence-end-double-space nil)
;; delete the region when typing, as is conventional these days.
(delete-selection-mode t)
(show-paren-mode t)
(column-number-mode t)
(global-visual-line-mode)
(diminish 'visual-line-mode)
(setq uniquify-buffer-name-style 'forward)
;; -i gets alias definitions from .bash_profile
(setq shell-command-switch "-ic")
;; Don't beep at me
(setq visible-bell t)
;; when editing a script file, make sure it's executable when you save
;; it.
(add-hook 'after-save-hook
'executable-make-buffer-file-executable-if-script-p)
The following function for occur-dwim
is taken from Oleh Krehel from
his blog post at (or emacs irrelevant). It takes the current region or
the symbol at point as the default value for occur.
;; in practice, I don't use this much. The keybinding has been given
;; to another mode.
(defun occur-dwim ()
"Call `occur' with a sane default."
(interactive)
(push (if (region-active-p)
(buffer-substring-no-properties
(region-beginning)
(region-end))
(thing-at-point 'symbol))
regexp-history)
(call-interactively 'occur))
;; (bind-key "M-s o" 'occur-dwim)
Here we make page-break characters look pretty, instead of appearing
as ^L
in Emacs. Here’s an informative article called “Using
Page-Breaks in GNU Emacs” by Eric J. M. Ritz.
(use-package page-break-lines
:straight t)
In dired mode, it is useful to mark a bunch of files and then open them all in separate buffers. Function implementation taken from Stack Overflow, here: In Emacs dired, how to find/visit multiple files?
(eval-after-load "dired"
'(progn
(define-key dired-mode-map "F" 'my-dired-find-file)
(defun my-dired-find-file (&optional arg)
"Open each of the marked files, or the file under the
point, or when prefix arg, the next N files. "
(interactive "P")
(let* ((fn-list (dired-get-marked-files nil arg)))
(mapc 'find-file fn-list)))))
There are configurations to make when running Emacs on macOS (hence the “darwin” system-type check).
(when (string-equal system-type "darwin")
;; delete files by moving them to the trash
(setq delete-by-moving-to-trash t)
(setq trash-directory "~/.Trash")
;; Don't make new frames when opening a new file with Emacs
(setq ns-pop-up-frames nil)
;; set the Fn key as the hyper key
(setq ns-function-modifier 'hyper)
;; Use Command-` to switch between Emacs windows (not frames)
(bind-key "s-`" 'other-window)
;; Use Command-Shift-` to switch Emacs frames in reverse
(bind-key "s-~" (lambda() () (interactive) (other-window -1)))
;; Because of the keybindings above, set one for `other-frame'
(bind-key "s-1" 'other-frame)
;; Fullscreen!
(setq ns-use-native-fullscreen nil) ; Not Lion style
(bind-key "<s-return>" 'toggle-frame-fullscreen)
;; buffer switching
(bind-key "s-{" 'previous-buffer)
(bind-key "s-}" 'next-buffer)
;; Compiling
(bind-key "H-c" 'compile)
(bind-key "H-r" 'recompile)
(bind-key "H-s" (defun save-and-recompile () (interactive) (save-buffer) (recompile)))
;; disable the key that minimizes emacs to the dock because I don't
;; minimize my windows
;; (global-unset-key (kbd "C-z"))
(defun open-dir-in-finder ()
"Open a new Finder window to the path of the current buffer"
(interactive)
(start-process "mai-open-dir-process" nil "open" "."))
(bind-key "C-c o f" 'open-dir-in-finder)
(defun open-dir-in-iterm ()
"Open the current directory of the buffer in iTerm."
(interactive)
(let* ((iterm-app-path "/Applications/iTerm.app")
(iterm-brew-path "/opt/homebrew-cask/Caskroom/iterm2/1.0.0/iTerm.app")
(iterm-path (if (file-directory-p iterm-app-path)
iterm-app-path
iterm-brew-path)))
(start-process "mai-open-dir-process" nil "open" "-a" iterm-path ".")))
(bind-key "C-c o t" 'open-dir-in-iterm)
;; Not going to use these commands
(put 'ns-print-buffer 'disabled t)
(put 'suspend-frame 'disabled t))
exec-path-from-shell
makes the command-line path with Emacs’s shell
match the same one on macOS.
(use-package exec-path-from-shell
:if (memq window-system '(mac ns))
:ensure t
:init
(exec-path-from-shell-initialize))
(cond
((string-equal system-type "darwin")
(let* ((cmd "sw_vers -productVersion")
(macos-version (string-to-number
(cadr (split-string
(shell-command-to-string cmd)
"\\."))))
(elcapitan-version 11))
(when (>= macos-version elcapitan-version)
(setq visible-bell nil)
(setq ring-bell-function 'ignore)
;; El Capitan full screen animation is quick and delightful (enough to start using it).
(setq ns-use-native-fullscreen t))))
;; other system specific things in separate test subclauses
((string-equal system-type "gnu/linux")
(progn
(message "Gnu Linux System!")))
((string-equal system-type "windows-nt")
(progn
(message "Oh dear... you're using Windows. :("))))
Org mode is one of the killer applications that run inside Emacs. It turns plain text into data that can be used for computation. Often, that computation takes the form of making lists and organising your life, but it can be anything you can conceive that is ultimately computable.
It goes without saying that I also use it to manage my Emacs config.
Although Org mode ships with Emacs, the latest version can be installed externally. The configuration here follows the Org mode ELPA installation instructions.
Org mode is currently being installed right after use-package is initialised in init.el
. It must be configured immediately, particularly if the package is being provided via the straight
package manager, or you can get peculiar errors tangling this configuration file, and also when you enter an org file of any kind, where the configuration around faces and org functions just doesn’t work.
On Org mode version 9 I wasn’t able to execute source blocks out of the box. Others have run into the same issue too. The solution is to remove the .elc files from the package directory:
rm ${ORG_DIR}/*.elc
The efs/org-font-setup
function configures various text faces to tweak the sizes of headings and use variable width fonts in most cases so that it looks more like we’re editing a document in org-mode
. We switch back to fixed width (monospace) fonts for code blocks and tables so that they display correctly.
(defun efs/org-font-setup ()
;; Replace list hyphen with dot
(font-lock-add-keywords 'org-mode
'(("^ *\\([-]\\) "
(0 (prog1 () (compose-region (match-beginning 1) (match-end 1) "•"))))))
;; Set faces for heading levels
(dolist (face '((org-level-1 . 1.2)
(org-level-2 . 1.1)
(org-level-3 . 1.05)
(org-level-4 . 1.0)
(org-level-5 . 1.1)
(org-level-6 . 1.1)
(org-level-7 . 1.1)
(org-level-8 . 1.1)))
(if (string-equal system-type "darwin")
(set-face-attribute (car face) nil :font "Cantarell" :weight 'regular :height (cdr face))
(set-face-attribute (car face) nil :font "Droid Sans" :weight 'regular :height (cdr face))))
;; Ensure that anything that should be fixed-pitch in Org files appears that way
(set-face-attribute 'org-block nil :foreground nil :inherit 'fixed-pitch)
(set-face-attribute 'org-code nil :inherit '(shadow fixed-pitch))
(set-face-attribute 'org-table nil :inherit '(shadow fixed-pitch))
(set-face-attribute 'org-verbatim nil :inherit '(shadow fixed-pitch))
(set-face-attribute 'org-special-keyword nil :inherit '(font-lock-comment-face fixed-pitch))
(set-face-attribute 'org-meta-line nil :inherit '(font-lock-comment-face fixed-pitch))
(set-face-attribute 'org-checkbox nil :inherit 'fixed-pitch))
(efs/org-font-setup)
Speed commands are a nice and quick way to perform certain actions while at the beginning of a heading. It’s not activated by default.
See the doc for speed keys by checking out the documentation for speed keys in Org mode.
(setq org-use-speed-commands t)
(require 'org-tempo)
(setq org-image-actual-width 550)
(setq org-highlight-latex-and-related '(latex script entities))
(setq org-refile-targets
'(("Archive.org" :maxlevel . 1)
("Tasks.org" :maxlevel . 1)))
;; Save Org buffers after refiling!
(advice-add 'org-refile :after 'org-save-all-org-buffers)
This package is useful when you have a lot of data in various org tables in a given document, and you want to drop it into a table that synthesizes various pieces of data from the other tables, with or without additional processing.
(use-package orgtbl-aggregate
:straight t
:after org)
(bind-key "C-c c" 'org-capture)
(setq org-default-notes-file "~/Dropbox/Notes/notes.org")
Learned about this delq
and mapcar
trick from Sacha Chua’s config. This form will add the agenda file to the org-agenda-files list if the file actually exists at the place indicated. Remember to touch the file if you change this list.
(setq org-agenda-files
(delq nil
(mapcar (lambda (x) (and (file-exists-p x) x))
(list (expand-file-name "personal-agenda.org" site-org-files)
(expand-file-name "notes.org" site-org-files)
(expand-file-name "todos.org" site-org-files)
(expand-file-name "Tasks.org" site-org-files)
(expand-file-name "people.org" site-org-files)
(expand-file-name "Archive.org" site-org-files)))))
;; when we finish a todo, just mark it DONE and fold down the entry.
(defun org-toggle-todo-and-fold ()
(interactive)
(save-excursion
(org-back-to-heading t) ;; Make sure command works even if point is
;; below target heading
(cond ((looking-at "\*+ TODO")
(org-todo "DONE")
(hide-subtree))
((looking-at "\*+ DONE")
(org-todo "TODO")
(hide-subtree))
(t (message "Can only toggle between TODO and DONE.")))))
(define-key org-mode-map (kbd "C-c C-d") 'org-toggle-todo-and-fold)
(use-package org-roam
:straight t
:init
(setq org-roam-v2-ack t)
:config
(setf org-roam-directory (expand-file-name "Roam/" site-org-files))
(setf org-roam-dailies-directory (expand-file-name "Dailies/" org-roam-directory))
;; New capture template
(setq org-roam-dailies-capture-templates
'(("d" "daily" entry #'org-roam-capture--get-point
"* %?\n")))
(org-roam-setup)
:bind
(("C-c n l" . org-roam-buffer-toggle)
("C-c n f" . org-roam-node-find)
("C-c n g" . org-roam-graph)
("C-c n r" . org-roam-node-random)
(:map org-mode-map
("C-c n i" . org-roam-node-insert)
("C-c n o" . org-roam-get-create)
("C-c n t" . org-roam-tag-add)
("C-c n a" . org-roam-alias-add)
("C-c n l" . org-roam-buffer-toggle))))
(use-package org-roam-bibtex
:straight t
:after org-roam)
;; (use-package org-roam-server
;; :ensure t
;; :after org-roam)
Set up some global key bindings that integrate with Org Mode features.
(bind-key "C-c l" 'org-store-link)
(bind-key "C-c c" 'org-capture)
(bind-key "C-c a" 'org-agenda)
visual-fill-column will center org-mode
buffers. This gives a more pleasing effect when writing long documents in natural languages.
(defun efs/org-mode-visual-fill ()
(setq visual-fill-column-width 100
visual-fill-column-center-text t)
(visual-fill-column-mode 1))
(use-package visual-fill-column
:after org
:straight t
:hook (org-mode . efs/org-mode-visual-fill))
Makes it all look a bit nicer, I hate looking at asterisks. Also, see org-mode-setup
configuration function at the top of this file.
(use-package org-bullets
:straight t
:after org
:hook (org-mode . org-bullets-mode)
:custom
(org-bullets-bullet-list '("◉" "○" "●" "○" "●" "○" "●")))
The default value is -77, which is weird for smaller width windows. I’d rather have the tags align horizontally with the header. 45 is a good column number to do that.
(setq org-tags-column 45)
(setq org-tag-alist
'((:startgroup)
; Put mutually exclusive tags here
(:endgroup)
("@errand" . ?E)
("@home" . ?H)
("@work" . ?W)
("agenda" . ?a)
("planning" . ?p)
("publish" . ?P)
("batch" . ?b)
("note" . ?n)
("idea" . ?i)))
;; Configure custom agenda views
(setq org-agenda-custom-commands
'(("d" "Dashboard"
((agenda "" ((org-deadline-warning-days 7)))
(todo "NEXT"
((org-agenda-overriding-header "Next Tasks")))
(tags-todo "agenda/ACTIVE" ((org-agenda-overriding-header "Active Projects")))))
("n" "Next Tasks"
((todo "NEXT"
((org-agenda-overriding-header "Next Tasks")))))
("W" "Work Tasks" tags-todo "+work-email")
;; Low-effort next actions
("e" tags-todo "+TODO=\"NEXT\"+Effort<15&+Effort>0"
((org-agenda-overriding-header "Low Effort Tasks")
(org-agenda-max-todos 20)
(org-agenda-files org-agenda-files)))
("w" "Workflow Status"
((todo "WAIT"
((org-agenda-overriding-header "Waiting on External")
(org-agenda-files org-agenda-files)))
(todo "REVIEW"
((org-agenda-overriding-header "In Review")
(org-agenda-files org-agenda-files)))
(todo "PLAN"
((org-agenda-overriding-header "In Planning")
(org-agenda-todo-list-sublevels nil)
(org-agenda-files org-agenda-files)))
(todo "BACKLOG"
((org-agenda-overriding-header "Project Backlog")
(org-agenda-todo-list-sublevels nil)
(org-agenda-files org-agenda-files)))
(todo "READY"
((org-agenda-overriding-header "Ready for Work")
(org-agenda-files org-agenda-files)))
(todo "ACTIVE"
((org-agenda-overriding-header "Active Projects")
(org-agenda-files org-agenda-files)))
(todo "COMPLETED"
((org-agenda-overriding-header "Completed Projects")
(org-agenda-files org-agenda-files)))
(todo "CANC"
((org-agenda-overriding-header "Cancelled Projects")
(org-agenda-files org-agenda-files)))))))
(use-package doct
:straight t)
(setq org-capture-templates
`(("t" "Tasks / Projects")
("tt" "Task" entry (file+olp "~/Dropbox/OrgFiles/Tasks.org" "Inbox")
"* TODO %?\n %U\n %a\n %i" :empty-lines 1)
("j" "Journal Entries")
("jj" "Journal" entry
(file+olp+datetree "~/Dropbox/OrgFiles/Journal.org")
"\n* %<%I:%M %p> - Journal :journal:\n\n%?\n\n"
;; ,(dw/read-file-as-string "~/Notes/Templates/Daily.org")
:clock-in :clock-resume
:empty-lines 1)
("jm" "Meeting" entry
(file+olp+datetree "~/Dropbox/OrgFiles/Journal.org")
"* %<%I:%M %p> - %a :meetings:\n\n%?\n\n"
:clock-in :clock-resume
:empty-lines 1)
("w" "Workflows")
("we" "Checking Email" entry (file+olp+datetree "~/Dropbox/OrgFiles/Journal.org")
"* Checking Email :email:\n\n%?" :clock-in :clock-resume :empty-lines 1)
;; ("m" "Metrics Capture")
;; ("mw" "Weight" table-line (file+headline "~/Dropbox/OrgFiles/Metrics.org" "Weight")
;; "| %U | %^{Weight} | %^{Notes} |" :kill-buffer t)
))
(use-package ob-restclient
:straight t
:after org)
(use-package ob-js
:ensure t
:after org)
(org-babel-do-load-languages
'org-babel-load-languages
'((python . t)
(C . t)
(calc . t)
(latex . t)
(java . t)
(ruby . t)
(lisp . t)
(scheme . t)
(shell . t)
(sqlite . t)
(js . t)
(restclient . t)))
(defun my-org-confirm-babel-evaluate (lang body)
"Do not confirm evaluation for these languages."
(not (or (string= lang "C")
(string= lang "java")
(string= lang "python")
(string= lang "emacs-lisp")
(string= lang "sqlite")
(string= lang "resclient"))))
(setq org-confirm-babel-evaluate 'my-org-confirm-babel-evaluate)
I like to have source blocks properly syntax highlighted and with the editing popup window staying within the same window so all the windows don’t jump around. Also, having the top and bottom trailing lines in the block is a waste of space, so we can remove them.
I noticed that fontification doesn’t work with markdown mode when the
block is indented after editing it in the org src buffer—the leading
#s for headers don’t get fontified properly because they appear as Org
comments. Setting org-src-preserve-indentation
makes things
consistent as it doesn’t pad source blocks with leading spaces.
(setq org-src-fontify-natively t
org-src-window-setup 'current-window
org-src-strip-leading-and-trailing-blank-lines t
;; org-src-preserve-indentation t
org-src-tab-acts-natively t)
Pandoc converts between a huge number of different file formats.
(use-package ox-pandoc
:no-require t
:defer 10
:straight t)
I’ve had issues with getting BiBTeX to work correctly with the LaTeX exporter for PDF exporting. By changing the command to `latexmk` references appear in the PDF output like they should. Source: http://tex.stackexchange.com/a/161619.
(setq org-latex-pdf-process (list "latexmk -pdf %f"))
exporting to html sometimes (always?) requires htmlize
(use-package htmlize
:straight t)
Hail Hydra!
(use-package hydra
:straight t)
(defhydra hydra-zoom (global-map "<f2>")
"zoom"
("g" text-scale-increase "in")
("l" text-scale-decrease "out"))
Projectile is an awesome project manager, mostly because it recognizes
directories with a .git
directory as projects and helps you manage
them accordingly.
This makes sure that everything can be a project.
(use-package projectile
:straight t
:init
(projectile-mode 1))
(global-set-key (kbd "<f5>") 'projectile-compile-project)
My emacs session tends to build up an enormous buffer list over time, which is (barely) manageable with the use of Helm. I have stopped using Helm, so this might still be a good idea. What I’d like to do is associate specific groups of buffers with a ‘workspace’ in emacs, so that when I switch to that workspace, only the associated buffers appear in the buffer list. Apparently perspective.el can provide this functionality. Including here on a provisional basis. In practice I have not made this a part of my workflow, yet, so I’m not going to generate the package clause when this file is tangled.
(use-package perspective
:straight t
;; :bind
;; ("C-x C-b" . persp-list-buffers) ; or use a nicer switcher, see below
:config
(persp-mode))
Taken, with thanks, from dakrone/eos at github.
(global-set-key (kbd "C-x m") 'browse-url-at-point)
(use-package eww
:defer t
:init
(setq browse-url-browser-function
'((".*google.*maps.*" . browse-url-generic)
;; Github goes to firefox, but not gist
("http.*\/\/github.com" . browse-url-generic)
("groups.google.com" . browse-url-generic)
("docs.google.com" . browse-url-generic)
("melpa.org" . browse-url-generic)
("build.*\.elastic.co" . browse-url-generic)
(".*-ci\.elastic.co" . browse-url-generic)
("internal-ci\.elastic\.co" . browse-url-generic)
("zendesk\.com" . browse-url-generic)
("salesforce\.com" . browse-url-generic)
("stackoverflow\.com" . browse-url-generic)
("apache\.org\/jira" . browse-url-generic)
("thepoachedegg\.net" . browse-url-generic)
("zoom.us" . browse-url-generic)
("t.co" . browse-url-generic)
("twitter.com" . browse-url-generic)
("\/\/a.co" . browse-url-generic)
("youtube.com" . browse-url-generic)
("amazon.com" . browse-url-generic)
("slideshare.net" . browse-url-generic)
("." . eww-browse-url)))
(setq browser-url-secondary-browser-function 'browse-url-generic)
(setq browse-url-generic-program (executable-find "nyxt"))
(add-hook 'eww-mode-hook #'toggle-word-wrap)
(add-hook 'eww-mode-hook #'visual-line-mode)
:config
(use-package s :ensure t)
(define-key eww-mode-map "o" 'eww)
(define-key eww-mode-map "O" 'eww-browse-with-external-browser)
(define-key eww-mode-map "j" 'next-line)
(define-key eww-mode-map "k" 'previous-line))
(use-package eww-lnum
:straight t
:after eww
:config
(bind-key "f" #'eww-lnum-follow eww-mode-map)
(bind-key "U" #'eww-lnum-universal eww-mode-map))
(require 'ffap)
(defun browse-last-url-in-brower ()
(interactive)
(save-excursion
(ffap-next-url t t)))
;; (global-set-key (kbd "C-c u") 'browse-last-url-in-brower)
This is your new startup screen, together with projectile it works in unison and provides you with a quick look into your latest projects and files. Change the welcome message to whatever string you want and change the numbers to suit your liking, I find 5 to be enough.
(use-package dashboard
:ensure t
:config
(dashboard-setup-startup-hook)
(setq dashboard-startup-banner "~/.emacs.d/img/dashLogo.png")
(setq dashboard-items '((recents . 5)
(projects . 5)))
(setq dashboard-banner-logo-title "DeepSky Emacs"))
(use-package vterm
:straight t)
Don’t ask me what shell I want to use. In general this is a solved problem..
(defvar my-term-shell "/usr/bin/zsh")
(defadvice ansi-term (before force-bash)
(interactive (list my-term-shell)))
(ad-activate 'ansi-term)
Spending too much time flapping around between buffers, stuck in the interstitial space where work goes to die.
Also revisiting this in our retooling around orderless, consult, marginalia, and embark.
(use-package swiper
:ensure t
:bind ("C-s" . 'swiper))
source: http://ergoemacs.org/emacs/emacs_buffer_management.html
Auto-revert-mode updates buffers so that they reflect what is on the disk. This is particularly useful in the presence of git or other version control software which can change the files from beneath the buffers in emacs. source: Magnar Sveen
(add-hook 'dired-mode-hook 'auto-revert-mode)
(global-auto-revert-mode t)
;; Also auto refresh dired, but be quiet about it
(setq global-auto-revert-non-file-buffers t)
(setq auto-revert-verbose nil)
(use-package recentf
:bind ("C-x C-r" . helm-recentf)
:config
(recentf-mode t)
(setq recentf-max-saved-items 200))
most relevantly, sparql is used to define queries to the WikiData knowledge database.
(use-package sparql-mode
:straight t
;; :load-path "~/SourceCode/lisp/emacs_stuff/sparql-mode"
)
This really is the best PDF management system I’ve ever used.
(use-package pdf-tools
:ensure t
:config
;; (pdf-tools-install)
(setq-default pdf-view-display-size 'fit-width)
(setq pdf-annot-activate-created-annotations t))
(use-package tramp
:ensure t
:config
;; tramp hangs when remote has 'weird' prompt. Check in for this terminal type.
(setf tramp-terminal-type "tramp")
(add-to-list 'tramp-connection-properties
(list (regexp-quote "/ssh:[email protected]:")
"remote-shell" "/bin/sh")))
Convenient keybindings to resize windows.
(bind-key "C-s-<left>" 'shrink-window-horizontally)
(bind-key "C-s-<right>" 'enlarge-window-horizontally)
(bind-key "C-s-<down>" 'shrink-window)
(bind-key "C-s-<up>" 'enlarge-window)
Whenever I split windows, I usually do so and also switch to the other window as well, so might as well rebind the splitting key bindings to do just that to reduce the repetition.
(defun vsplit-other-window ()
"Splits the window vertically and switches to that window."
(interactive)
(split-window-vertically)
(other-window 1 nil))
(defun hsplit-other-window ()
"Splits the window horizontally and switches to that window."
(interactive)
(split-window-horizontally)
(other-window 1 nil))
(bind-key "C-x 2" 'vsplit-other-window)
(bind-key "C-x 3" 'hsplit-other-window)
Because sometimes you have to look at python code that came from a person with unusual editor defaults.
(use-package whitespace
:bind ("s-<f10>" . whitespace-mode))
(use-package aggressive-indent
:straight t
:config
(global-aggressive-indent-mode 1)
(add-to-list 'aggressive-indent-excluded-modes 'html-mode)
(add-to-list 'aggressive-indent-excluded-modes 'python-mode))
Dired configuration is split between init.el
and this clause in config.org
, for reasons related to the way that emacs is initialised in this regime. If dired is not configured early, emacs throws to the debugger with an error when dired is called in regular use. (I don’t know if this is still true.)
;; (use-package dired-single
;; :ensure t
;; :after dired)
(use-package all-the-icons-dired
:straight t
:after dired
:diminish all-the-icons-dired-mode
:hook (dired-mode . all-the-icons-dired-mode))
(use-package mu4e
:ensure nil
:defer 120
:load-path "/usr/share/emacs/site-lisp/mu4e/"
:config
;; this setting avoids mbsync problems
(setq mu4e-change-filenames-when-moving t)
;; update every 10 minutes
(setq mu4e-update-interval (* 10 60))
(setq mu4e-get-mail-command "mbsync -a")
(setq mu4e-maildir "~/Mail/GMail/")
(setq mu4e-drafts-folder "/[Gmail].Drafts")
(setq mu4e-sent-folder "/[Gmail].Sent Mail")
(setq mu4e-refile-folder "/[Gmail].All Mail")
(setq mu4e-trash-folder "/[Gmail].Trash")
(setq mu4e-headers-fields
'((:human-date . 25)
(:flags . 6)
(:from . 22)
(:to . 22)
(:thread-subject . nil)))
(setq mu4e-maildir-shortcuts
'(("/Inbox" . ?i)
("/[Gmail].Sent Mail" . ?s)
("/[Gmail].Trash" . ?t)
("/[Gmail].Drafts" . ?d)
("/[Gmail].All Mail" . ?a))))
Emacs is at it’s best when it just does things for you, or shows you the way. This can best be achieved using a number of small extensions. While on their own they might not be particularly impressive. Together they create a nice environment for you to work in.
Quickly edit ~/.emacs.d/config.org
. The Emacs way being the Emacs way, this specific keybinding turns out to be one of the most useful quality of life changes in this config, which is odd, considering the triviality of the feature.
(defun config-visit ()
(interactive)
(find-file "~/.emacs.d/config.org"))
(global-set-key (kbd "C-c e") 'config-visit)
Simply pressing Control-c r
will reload this file, very handy.
You can also manually invoke config-reload
.
(defun config-reload ()
"Reloads ~/.emacs.d/config.org at runtime"
(interactive)
(org-babel-load-file (expand-file-name "~/.emacs.d/config.org")))
(global-set-key (kbd "C-c r") 'config-reload)
Emacs treats camelCase strings as a single word by default, this changes said behaviour.
(global-subword-mode 1)
While changing buffers or workspaces, the first thing you do is look for your cursor. Unless you know its position, you can not move it efficiently. Every time you change buffers, the current position of your cursor will be briefly highlighted now.
(use-package beacon
:straight t
:config
(beacon-mode 1))
These are the packages that are neither built into Emacs nor required to achieve the base configuration state. feel free to add or remove as many or as few of these as you want; they generally reflect my own biases and developmental requirements, so it is unlikely that this list will be perfectly harmonic with your own needs.
Avy integrates with Ace window, and works like Ace Jump mode.
(use-package avy
:straight t
:config
(avy-setup-default)
(set-face-attribute 'avy-lead-face-0 nil :background "blue" :foreground "yellow")
(set-face-attribute 'avy-lead-face-1 nil :background "purple4" :foreground "goldenrod")
(set-face-attribute 'avy-lead-face-1 nil :background "SlateBlue4" :foreground "light goldenrod")
:bind ("s-s c" . avy-goto-char))
ace-window is a package that uses the same idea from ace-jump-mode for buffer navigation, but applies it to windows. The default keys are 1-9.
(use-package ace-window
:ensure t
:config
(ace-window-display-mode)
:bind ("s-o" . ace-window))
(use-package ag
:commands ag
:ensure t
:config
(setq ag-highlight-search t
ag-reuse-window nil
ag-reuse-buffers t))
(use-package android-mode
:ensure t
:defer t)
(use-package c-eldoc
:commands c-turn-on-eldoc-mode
:ensure t
:init (add-hook 'c-mode-hook #'c-turn-on-eldoc-mode))
;; (use-package clojure-mode
;; :defer t
;; :ensure t)
Collection of Ridiculously Useful eXtensions
(use-package crux
:straight t
:bind (("C-c o o" . crux-open-with)
("C-c u" . crux-view-url)))
(use-package vagrant
:straight t)
(use-package vagrant-tramp
:straight t)
(use-package docker
:defer t
:straight t)
(use-package docker-cli
:straight t)
(use-package docker-api
:straight t)
(use-package docker-compose-mode
:straight t)
;; (use-package tramp-docker
;; :straight t)
(use-package dockerfile-mode
:straight t)
According to their website, “Emmet — the essential toolkit for web-developers.”
(use-package emmet-mode
:ensure t
:commands emmet-mode
:config
(add-hook 'html-mode-hook 'emmet-mode)
(add-hook 'css-mode-hook 'emmet-mode))
(use-package flycheck
:ensure t
:diminish flycheck-mode
:init (global-flycheck-mode))
(use-package flycheck-cython
:ensure t
:after flycheck)
(use-package flycheck-clojure
:ensure t
:init (flycheck-clojure-setup))
(use-package flycheck-nim
:ensure t
:after flycheck)
Make low friction pastes to 0x0, forex sharing code to IRC
(use-package 0x0
:ensure t)
(use-package gist
:ensure t
:commands gist-list)
;; (use-package helm
;; :ensure t
;; ;; :diminish helm-mode
;; :init (progn
;; (use-package helm-config)
;; (setq helm-locate-command "mdfind -interpret -name %s %s"
;; helm-ff-newfile-prompt-p nil
;; helm-M-x-fuzzy-match t)
;; (helm-mode 1))
;; :bind ((:map helm-map
;; ("<tab>" . helm-execute-persistent-action)
;; ("C-c h" . helm-command-prefix)
;; ("C-x b" . helm-mini)
;; ("C-x C-b" . 'helm-buffers-list)
;; ("C-`" . helm-resume)))
;; :bind (("M-x" . helm-M-x)
;; ("C-x C-f" . helm-find-files))
;; :config
;; (helm-autoresize-mode 1))
;; (use-package helm-ag
;; :defer 10
;; :ensure t
;; :after helm
;; :bind ("C-c M-s" . helm-do-ag)
;; :config
;; (custom-set-variables
;; '(helm-ag-base-command "ag --nocolor --nogroup --ignore-case")
;; '(helm-ag-command-option "--all-text")
;; '(helm-ag-insert-at-point 'symbol)
;; '(helm-ag-ignore-buffer-patterrns '("\\.txt\\'" "\\.mkd\\'"))))
;; vertico is the base for our Helm exodus.
(use-package vertico
:straight t
:init
(vertico-mode 1)
:custom
(vertico-count 13)
(vertico-resize t)
(vertico-cycle t)
:config
(vertico-mode))
;; this will put most recent items at the top of any given vertico selection.
(use-package savehist
:straight t
:init
(savehist-mode))
;; completion selection (narrowing) enhancements.
(use-package consult
:straight t
:bind
("s-s o" . consult-outline)
("C-s" . consult-line)
("s-s s" . consult-ripgrep))
;; this is a completion style, which defines how we match against input.
(use-package orderless
:straight t
:custom
(completion-styles '(orderless))
(completion-category-overrides '((file (styles . (partial-completion)))))
(setq completion-category-defaults nil))
;; metadata around completion selections
(use-package marginalia
:straight t
:custom
(setq marginalia-annotators '(marginalia-annotators-heavy marginalia-annotators-light nil))
:init
(marginalia-mode 1))
;; actions within completion selections
(use-package embark
:straight t
:bind ("C-." . embark-act))
(use-package company
:ensure nil
:diminish company-mode
;; :bind (:map company-mode-map
;; (("C-n" . company-select-next)
;; ("C-p" . company-select-previous)
;; ("C-d" . company-show-doc-buffer)
;; ("M-." . company-show-location)))
:config
(progn
;; less than this and it disrupts typing when you aren't interested in completion.
(setq company-idle-delay 0.9)
(setq company-minimize-prefix-length 3)
;; company completion everywhere.
(add-hook 'after-init-hook 'global-company-mode)
(require 'color)
(let ((bg (face-attribute 'default :background)))
(custom-set-faces
`(company-tooltip ((t (:inherit default :background ,(color-lighten-name bg 2)))))
`(company-scrollbar-bg ((t (:background ,(color-lighten-name bg 10)))))
`(company-scrollbar-fg ((t (:background ,(color-lighten-name bg 5)))))
`(company-tooltip-selection ((t (:inherit font-lock-function-name-face))))
`(company-tooltip-common ((t (:inherit font-lock-constant-face))))))
(with-eval-after-load 'company
(define-key company-active-map (kbd "M-n") nil)
(define-key company-active-map (kbd "M-p") nil)
(define-key company-active-map (kbd "C-n") #'company-select-next)
(define-key company-active-map (kbd "C-p") #'company-select-previous)
(define-key company-active-map (kbd "SPC") #'company-abort))))
;; (use-package company-box
;; :after company)
(use-package company-quickhelp
:after (company)
:hook (company-mode . company-quickhelp-mode)
:config
(setq company-quickhelp-delay 1.0)
:ensure t)
I was struggling to find an acceptable english dictionary for local off-line use, and googling lead me to a salubrious link tree, starting with the ever productive Marcin Borkowski: Marcin Borkowski on using the right dictionary.
the tldr
is:
- Download the Webster’s dictionary in StarDict format, as Somers tells you to do. (Apparently it’s not “some strange format”, but a standard format for a digital dictionary.)
- Unzip the files and put them in ~/.stardict/dic
- Install sdcv, a command-line utility for accessing StarDict
dictionaries. (On Arch GNU/Linux with from the AUR with yay, it is
yay -S sdcv
.) - My config is using straight, so I’m accessing the sdcv package with the package manager, as below
- With point on a word to look up, say
M-x sdcv-search
, orM-x sdcv-search
anywhere and type in the word. - You can press
RET
on any word in the definitionto lookthat
one up. This is an inescapable rabbit hole for people of a certain disposition.
(use-package sdcv
:straight t)
This package gives richer help information, and makes interrogating emacs more fruitful.
(use-package helpful
:ensure t
:config
(global-set-key (kbd "C-h f") #'helpful-callable)
(global-set-key (kbd "C-h v") #'helpful-variable)
(global-set-key (kbd "C-h k") #'helpful-key)
;; Lookup the current symbol at point. C-c C-d is a common keybinding
;; for this in lisp modes.
(global-set-key (kbd "C-c C-d") #'helpful-at-point)
;; Look up *F*unctions (excludes macros).
;;
;; By default, C-h F is bound to `Info-goto-emacs-command-node'. Helpful
;; already links to the manual, if a function is referenced there.
(global-set-key (kbd "C-h F") #'helpful-function)
;; Look up *C*ommands.
;;
;; By default, C-h C is bound to describe `describe-coding-system'. I
;; don't find this very useful, but it's frequently useful to only
;; look at interactive functions.
(global-set-key (kbd "C-h C") #'helpful-command))
(use-package latex-extra
:defer t
:ensure t)
(use-package latex-preview-pane
:ensure t
:defer t)
A great interface for git projects. It’s much more pleasant to use than the git interface on the command line. Use an easy keybinding to access magit.
(use-package magit
:straight t
:defer t
:bind ("C-c g" . magit-status)
:config
(define-key magit-status-mode-map (kbd "q") 'magit-quit-session))
(use-package forge
:straight t
:defer t
:after magit
:config
(setq auth-source '("~/.authinfo")))
The following code makes magit-status run alone in the frame, and then restores the old window configuration when you quit out of magit.
No more juggling windows after commiting. It’s magit bliss.
;; full screen magit-status
(defadvice magit-status (around magit-fullscreen activate)
(window-configuration-to-register :magit-fullscreen)
ad-do-it ;; ad-do-it is a special marker for 'around advice that refers to the wrapped function.
(delete-other-windows))
(defun magit-quit-session ()
"Restores the previous window configuration and kills the magit buffer"
(interactive)
(kill-buffer)
(jump-to-register :magit-fullscreen))
(use-package markdown-mode
:ensure t
:mode (("\\.markdown\\'" . markdown-mode)
("\\.md\\'" . markdown-mode)))
We’ll also need to (require 'multiple-cusors)
because of an autoload issue.
(use-package multiple-cursors
:ensure t
:bind (("C-S-c C-S-c" . mc/edit-lines)
("C->" . mc/mark-next-like-this)
("C-<" . mc/mark-previous-like-this)
("C-c C-<" . mc/mark-all-like-this)
("C-!" . mc/mark-next-symbol-like-this)
("s-d" . mc/mark-all-dwim)))
Workspaces in Emacs.
(use-package perspective
:ensure t
:defer t
:config (persp-mode))
Project navigation and management library for Emacs.
(use-package projectile
:ensure t
:diminish projectile-mode
:commands (projectile-mode projectile-switch-project)
:bind ("C-c p p" . projectile-switch-project)
:config
(projectile-global-mode t)
(setq projectile-enable-caching t)
(setq projectile-switch-project-action 'projectile-dired))
(use-package quickrun
:defer 10
:ensure t
:bind ("H-q" . quickrun))
See Emacs Rocks! Episode 15 to learn how restclient can help out with
testing APIs from within Emacs. The HTTP calls you make in the buffer
aren’t constrainted within Emacs; there’s the
restclient-copy-curl-command
to get the equivalent curl
call
string to keep things portable.
(use-package restclient
:ensure t
;; :load-path "~/SourceCode/lisp/emacs_stuff/restclient.el"
:mode ("\\.restclient\\'" . restclient-mode))
Convenient package to create *scratch*
buffers that are based on the
current buffer’s major mode. This is more convienent than manually
creating a buffer to do some scratch work or reusing the initial
*scratch*
buffer.
(use-package scratch
:ensure t
:commands scratch)
(use-package shell-pop
:ensure t
:bind ("M-<f12>" . shell-pop))
I’m constantly looking for tools that make starting projects faster, and more correct. There seem to be dozens of them, at least one for every language. The workflow in these tools is always “Run the tool, then find the resulting project in Emacs.” … since most of my projects are written in Common Lisp, I live in Emacs pretty much all the time. It seems like a redundancy in tooling which is not necessary. Starting in emacs, and running the project skeleton tool is practically ideal, and would be bested only by a system running in an Emacs written in Common Lisp. At any rate, I’m looking at Skeletor to see how it fares under my generally unusual requirements.
(use-package skeletor
:ensure t
:custom
(skeletor-project-directory "~/SourceCode/lisp/"))
Live coding for HTML/CSS/JavaScript.
(use-package skewer-mode
:commands skewer-mode
:ensure t
:config (skewer-setup))
Quickly jumps between other symbols found at point in Emacs.
http://www.masteringemacs.org/article/smart-scan-jump-symbols-buffer
(use-package smartscan
:ensure t
:config (global-smartscan-mode 1)
:bind (("s-n" . smartscan-symbol-go-forward)
("s-p" . smartscan-symbol-go-backward)))
This makes it so C-n
-ing and C-p
-ing won’t make the buffer jump
around so much.
(use-package smooth-scrolling
:ensure t)
(use-package undo-tree
:straight t
:diminish undo-tree-mode
:config
(global-undo-tree-mode)
:custom
(undo-tree-auto-save-history nil))
I found out about this mode by looking through simple.el. I use it to see raw org-mode files without going to a different mode like text-mode, which is what I had done in order to see invisible text (with org hyperlinks). The entire buffer contents will be visible while still being in org mode.
(use-package visible-mode
:bind (("H-v" . visible-mode)
("s-<f2>" . visible-mode)))
;; (use-package w3m
;; :ensure t
;; :defer t
;; :config
;; (progn
;; (setq browse-url-browser-function 'w3m-browse-url)
;; (autoload 'w3m-browse-url "w3m" "Ask a WWW browser to show a URL." t)
;; (global-set-key "\C-xm" 'browse-url-at-point)
;; (setq w3m-use-cookies t)))
(use-package xquery-mode
:ensure t
:defer t)
Yeah, snippets! I start with snippets from Andrea Crotti’s collection and have also modified them and added my own.
It takes a few seconds to load and I don’t need them immediately when Emacs starts up, so we can defer loading yasnippet until there’s some idle time.
(use-package yasnippet
:straight t
:config
;; (setq yas-snippet-dirs (concat user-emacs-directory "snippets"))
(yas-reload-all)
(yas-global-mode))
(use-package yasnippet-snippets
:straight t
:after yasnippet)
(use-package common-lisp-snippets
:straight t
:after yasnippet)
zoom-frm
is a nice package that allows you to resize the text of
entire Emacs frames (this includes text in the buffer, mode line, and
minibuffer). The zoom-in/out
command acts similar to the
text-scale-adjust
command—you can chain zooming in, out, or
resetting to the default size once the command has been initially
called.
Changing the frame-zoom-font-difference
essentially enables a
“presentation mode” when calling toggle-zoom-frame
.
This mode is not available in elpa/melpa, so use-package will obviously not work in this case. If you are giving a lot of presentations with emacs, it is very useful, and you can still find the system at Emacs WIKI zoom-frm.el. Include it from init.el.
;; (use-package zoom-frm
;; :ensure t
;; :bind (("C-M-=" . zoom-in/out)
;; ("H-z" . toggle-zoom-frame)
;; ("s-<f1>" . toggle-zoom-frame))
;; :config
;; (setq frame-zoom-font-difference 10))
Load some computer-specific settings, such as the name and and email address. The way the settings are loaded is based off of Magnar Sveen’s config.
In my case, the computers I use usually use the same username (my
name, go figure), so instead of basing the specific settings from the
username, I use the hostname. The shell command hostname -s
gets the
hostname for the computer without any “domain information,” such as
the “.local” suffix.
Not using this right now.
;; (require 'subr-x) ;; #'string-trim
;; (defvar fade/user-settings-dir nil
;; "The directory with user-specific Emacs settings for this
;; user.")
;; ;; Settings for currently logged in user
;; (setq fade/user-settings-dir
;; (concat user-emacs-directory
;; "users/"
;; (string-trim (shell-command-to-string "hostname -s"))))
;; (add-to-list 'load-path fade/user-settings-dir)
;; ;; Load settings specific for the current user
;; (when (file-exists-p fade/user-settings-dir)
;; (mapc 'load (directory-files fade/user-settings-dir nil "^[^#].*el$")))
(use-package yatemplate
:straight t)
I don’t like the default way that Emacs handles indentation. For instance,
int main(int argc, char *argv[])
{
/* What's with the brace alignment? */
if (check)
{
}
return 0;
}
switch (number)
{
case 1:
doStuff();
break;
case 2:
doStuff();
break;
default:
break;
}
Luckily, I can modify the way Emacs formats code with this configuration.
(defun my-c-mode-hook ()
(setq c-basic-offset 4)
(c-set-offset 'substatement-open 0) ; Curly braces alignment
(c-set-offset 'case-label 4)) ; Switch case statements alignment
(add-hook 'c-mode-hook 'my-c-mode-hook)
(add-hook 'java-mode-hook 'my-c-mode-hook)
(use-package rust-mode
:straight t
:defer t)
(use-package csv-mode
:ensure t)
Extempore is a scheme defined for live performance programming. Leaving this stub here for now.
;; (use-package extempore-mode
;; :ensure t
;; :config
;; (setq extempore-path "/usr/bin/extempore"))
The jury has returned. Sly is superior to Slime.
(use-package sly
:load-path "~/SourceCode/lisp/sly"
:straight t
:defer t
:commands sly
:bind ("C-c M-o" . sly-mrepl-clear-repl)
:init
(progn
(setq sly-lisp-implementations
'((sbcl ("/usr/local/bin/sbcl" "--dynamic-space-size" "2500"))
(ccl ("/usr/bin/ros" "-L" "ccl-bin" "run"))
(ccl ("/usr/bin/ccl"))
(abcl ("/usr/local/src/abcl/abcl"))
(clisp ("/usr/bin/clisp"))
(ecl ("/usr/local/bin/ecl"))
(decl ("/usr/bin/ecl"))
(clojure ("/usr/bin/clojure"))))
(setq sly-kill-without-query-p t
sly-net-coding-system 'utf-8-unix
sly-complete-symbol*-fancy t
common-lisp-hyperspec "~/SourceCode/lisp/HyperSpec"))
:config
(progn
(require 'sly-autoloads)))
(use-package sly-asdf
;; :load-path "~/SourceCode/lisp/sly-asdf"
:straight t
:after sly)
(use-package sly-macrostep
:straight t
:after sly)
(use-package sly-named-readtables
:straight t
:after sly)
(use-package sly-repl-ansi-color
:straight t
:after sly)
(use-package sly-quicklisp
:straight t
:after sly)
I spend almost all of my time in emacs writing common lisp code, and in that endeavour, Paredit is the single most useful package in my configuration. It allows me to treat code as structure, moving forms in their entirety. It also ensures that the famous parenthesis are always balanced, and that I usually only have to type the opening 50% of them. This mode is useful in all programming languages for the paren matching features, but it is indespensible if you write any lisp dialect regularly.
(use-package paredit
:straight t
;; :diminish paredit-mode
:config
(progn
(autoload 'enable-paredit-mode "paredit" "Turn on pseudo-structural editing of Lisp code." t)
(add-hook 'emacs-lisp-mode-hook #'enable-paredit-mode)
(add-hook 'eval-expression-minibuffer-setup-hook #'enable-paredit-mode)
(add-hook 'ielm-mode-hook #'enable-paredit-mode)
(add-hook 'lisp-mode-hook #'enable-paredit-mode)
(add-hook 'lisp-interaction-mode-hook #'enable-paredit-mode)
(add-hook 'scheme-mode-hook #'enable-paredit-mode)
;; (add-hook 'slime-repl-mode-hook #'enable-paredit-mode)
(add-hook 'sly-mrepl-mode-hook #'enable-paredit-mode)
;; (add-hook 'slime-mode-hook #'enable-paredit-mode)
;; (add-hook 'clojure-mode-hook #'enable-paredit-mode)
;; (add-hook 'cider-repl-mode-hook #'enable-paredit-mode)
))
At the moment, we’re only really investigating Haskell in conjunction with the “Integrated Haskell Platform”, which itself carries a lot of dependency baggage. At any rate, we need to be able to edit haskell with at least the minimum viable editing facilities…
(use-package dante
:straight t)
(use-package direnv
:straight t)
(use-package attrap
:straight t)
(use-package shen-mode
:straight t
:ensure t)
(use-package hcl-mode
:defer t
:straight t)
(use-package terraform-mode
:defer t
:straight t
:after hcl-mode
:config
(add-hook 'terraform-mode-hook #'terraform-format-on-save-mode)
:custom
'(terraform-indent-level 2))
(use-package terraform-doc
:defer t
:straight t
:after terraform-mode
)
(use-package js2-mode
:ensure t
:init
(setq js-basic-indent 2)
(setq-default ;; js2-basic-indent 2
;; js2-basic-offset 2
;; js2-auto-indent-p t
;; js2-cleanup-whitespace t
;; js2-enter-indents-newline t
;; js2-indent-on-enter-key t
js2-global-externs (list "window" "module" "require" "buster" "sinon" "assert" "refute" "setTimeout" "clearTimeout" "setInterval" "clearInterval" "location" "__dirname" "console" "JSON" "jQuery" "$"))
(add-hook 'js2-mode-hook
(lambda ()
(push '("function" . ?ƒ) prettify-symbols-alist)))
(add-to-list 'auto-mode-alist '("\\.js$" . js2-mode))
:custom
(js2-basic-indent 2)
(js2-basic-offset 2)
(js2-auto-indent-p t)
(js2-cleanup-whitespace t)
(js2-enter-indents-newline t)
(js2-indent-on-enter-key t))
Color defined variables with color-identifiers-mode:
(use-package color-identifiers-mode
:ensure t
:init
(add-hook 'js2-mode-hook 'color-identifiers-mode))
While editing mode for JavaScript is baked into Emacs, it is quite important
to have flycheck validate the source based on jshint, and eslint.
Let’s prefer eslint
:
(add-hook 'js2-mode-hook
(lambda () (flycheck-select-checker "javascript-eslint")))
The js2-refactor mode should start with C-c .
and then a two-letter
mnemonic shortcut.
ef
isextract-function
: Extracts the marked expressions out into a new named function.em
isextract-method
: Extracts the marked expressions out into a new named method in an object literal.ip
isintroduce-parameter
: Changes the marked expression to a parameter in a local function.lp
islocalize-parameter
: Changes a parameter to a local var in a local function.eo
isexpand-object
: Converts a one line object literal to multiline.co
iscontract-object
: Converts a multiline object literal to one line.eu
isexpand-function
: Converts a one line function to multiline (expecting semicolons as statement delimiters).cu
iscontract-function
: Converts a multiline function to one line (expecting semicolons as statement delimiters).ea
isexpand-array
: Converts a one line array to multiline.ca
iscontract-array
: Converts a multiline array to one line.wi
iswrap-buffer-in-iife
: Wraps the entire buffer in an immediately invoked function expressionig
isinject-global-in-iife
: Creates a shortcut for a marked global by injecting it in the wrapping immediately invoked function expressionag
isadd-to-globals-annotation
: Creates a/*global */
annotation if it is missing, and adds the var at point to it.ev
isextract-var
: Takes a marked expression and replaces it with a var.iv
isinline-var
: Replaces all instances of a variable with its initial value.rv
isrename-var
: Renames the variable on point and all occurrences in its lexical scope.vt
isvar-to-this
: Changes localvar a
to bethis.a
instead.ao
isarguments-to-object
: Replaces arguments to a function call with an object literal of named arguments. Requires yasnippets.3i
isternary-to-if
: Converts ternary operator to if-statement.sv
issplit-var-declaration
: Splits avar
with multiple vars declared, into severalvar
statements.uw
isunwrap
: Replaces the parent statement with the selected region.
(use-package js2-refactor
:ensure t
:init (add-hook 'js2-mode-hook 'js2-refactor-mode)
:config (js2r-add-keybindings-with-prefix "C-c ."))
I also configure Skewer for my HTML and CSS files, we need to do the same for JavaScript:
(use-package skewer-mode
:ensure t
:init (add-hook 'js2-mode-hook 'skewer-mode))
Kick things off with run-skewer
, and then:
- C-x C-e
- `skewer-eval-last-expression’
- C-M-x
- `skewer-eval-defun’
- C-c C-k
- `skewer-load-buffer’
(use-package nim-mode
:ensure t)
Integrates with IPython., using elpy jedi, and virtualenvwrapper.
(use-package elpy
:ensure t
:config
(setq elpy-rpc-backend "jedi")
(setq python-shell-interpreter "ipython"
python-shell-interpreter-args "-i --simple-prompt")
(elpy-enable))
(use-package jedi
:ensure t
:init
(add-hook 'python-mode-hook 'jedi:setup)
:config
(local-set-key (kbd "M-.") 'jedi:goto-definition)
(local-set-key (kbd "M-,") 'jedi:goto-definition-pop-marker)
(local-set-key (kbd "M-?") 'jedi:show-doc)
(local-set-key (kbd "M-/") 'jedi:get-in-function-call)
(setq jedi:complete-on-dot t))
(use-package company-jedi
:ensure jedi
:ensure t
:config
(add-to-list 'company-backends 'company-jedi))
(use-package jinja2-mode
:ensure t)
(use-package virtualenvwrapper
:ensure t
:defer t
:config
(setq venv-location "~/.virtualenvs"))
Not using Racket much any more. When I do, drracket is sufficient.
;; (use-package racket-mode
;; :ensure t
;; :commands racket-mode
;; :config
;; (setq racket-smart-open-bracket-enable t))
;; (use-package geiser
;; :ensure t
;; :defer t
;; :config
;; (setq geiser-default-implementation '(racket)))
(use-package yaml-mode
:ensure t
:defer t
:config
(add-hook 'yaml-mode-hook '(lambda () (ansible 1))))
(use-package ansible
:ensure t
;; :load-path "~/SourceCode/lisp/emacs_stuff/emacs-ansible"
:defer t
:config
(use-package ansible-doc
:ensure t
:defer t)
(use-package ansible-vault
:ensure t
:defer t)
(use-package company-ansible
:ensure t
:defer t))
;; (use-package typescript-mode
;; :ensure t
;; :defer t)
(use-package web-mode
:ensure t)
(when window-system (add-hook 'prog-mode-hook 'hl-line-mode))
(defadvice hl-line-mode (after
dino-advise-hl-line-mode
activate compile)
(set-face-attribute 'hl-line nil
:inherit nil
:background (face-background 'highlight))
(set-face-background hl-line-face "#191970"))
Mostly useful if you are into web development or game development. Every time emacs encounters a hexadecimal code that resembles a color, it will automatically highlight it in the appropriate color. This is a lot cooler than you may think.
(use-package rainbow-mode
:ensure t
:diminish rainbow-mode
;; apply this mode to all programming modes.
:init
(add-hook 'prog-mode-hook 'rainbow-mode))
The modeline is the heart of emacs, it offers information at all times, it’s persistent and verbose enough to gain a full understanding of modes and states you are in.
One modeline-related setting that is missing and is instead placed at
the bottom is diminish
.
(use-package all-the-icons
:straight t)
I may not use spacemacs, since I do not like evil-mode and find spacemacs incredibly bloated and slow, however it would be stupid not to acknowledge the best parts about it, the theme and their modified powerline setup.
This enables spaceline, it looks better and works very well with my theme of choice.
;; (when window-system
;; (progn
;; (use-package spaceline
;; :ensure t
;; :config
;; ;; (mis)using use-package here to put config in an envelope.
;; (use-package spaceline-config
;; :config
;; (setq spaceline-buffer-encoding-abbrev-p t)
;; (setq spaceline-line-column-p t)
;; (setq spaceline-line-p t)
;; (spaceline-toggle-flycheck-info-off)
;; (spaceline-toggle-flycheck-error-off)
;; (spaceline-toggle-flycheck-warning-off)
;; (spaceline-toggle-version-control-on)
;; (spaceline-spacemacs-theme)))
;; (use-package spaceline-all-the-icons
;; :ensure t
;; :after spaceline
;; :config
;; (spaceline-all-the-icons-theme))))
;; (use-package telephone-line
;; :ensure t
;; :config
;; (setf telephone-line-primary-left-separator 'telephone-line-cubed-left
;; telephone-line-secondary-left-separator 'telephone-line-cubed-hollow-left
;; telephone-line-primary-right-separator 'telephone-line-cubed-right
;; telephone-line-secondary-right-separator 'telephone-line-cubed-hollow-right)
;; (setf telephone-line-height 24
;; telephone-line-evil-use-short-tag t)
;; ;; actually use it.
;; (telephone-line-mode 1))
(setq powerline-default-separator nil)
Show the current line and column for your cursor. We are not going to
have relative-linum-mode
in every major mode, so this is useful.
;; (setq line-number-mode t)
;; (setq column-number-mode t)
If you prefer the 12hr-format, change the variable to nil
instead of t
.
(setq display-time-24hr-format t)
(setq display-time-format "%H:%M - %d %B %Y")
(display-time-mode 1)
;; (use-package autothemer
;; :ensure t)
(setq inhibit-startup-message t)
custom colour themes generally enhance my experience of writing inside emacs, but when that theme is applied to an instance running inside a terminal, the effect is really just terrible. This mode kind of approximates the effect of a graphical emacs frame, in a text console.
(use-package color-theme-approximate
:ensure t
:config
(unless (display-graphic-p)
(autoload 'color-theme-approximate-on "color-theme-approximate")
(color-theme-approximate-on)))
A fun hack that is in practice unusable.
;; if this is set here, it is overwritten by the colour theme.
;; (set-cursor-color "yellow")
;; (when (display-graphic-p)
;; (progn
;; (defvar blink-cursor-colors (list
;; "dark slate blue"
;; "medium slate blue"
;; "light slate blue"
;; "steel blue"
;; "royal blue"
;; "light blue"
;; "cyan"
;; "cyan1"
;; "cyan2"
;; "cyan3"
;; "cyan4"
;; "spring green"
;; "yellow"
;; "orange"
;; "red"
;; "hot pink")
;; "On each blink the cursor will cycle to the next color in this list.")
;; (setq blink-cursor-count 0)
;; (setq blink-cursor-interval 0.3)
;; (defun blink-cursor-timer-function ()
;; "Zarza wrote this cyberpunk variant of timer `blink-cursor-timer'.
;; Warning: overwrites original version in `frame.el'.
;; This one changes the cursor color on each blink. Define colors in `blink-cursor-colors'."
;; (when (not (internal-show-cursor-p))
;; (when (>= blink-cursor-count (length blink-cursor-colors))
;; (setq blink-cursor-count 0))
;; (set-cursor-color (nth blink-cursor-count blink-cursor-colors))
;; (setq blink-cursor-count (+ 1 blink-cursor-count)))
;; (internal-show-cursor nil (not (internal-show-cursor-p))))))
Load the appropriate theme, and a utility for arbitrarily loading others.
(progn
;; on the terminal, the theme situation needs more attention.
(message "Loading DeepSky theme... ")
(load-theme 'deepsky-modus-fade t)
(message "Configuring mode-line appearance...")
(set-face-attribute `mode-line nil
:box nil)
(message "Setting cursor colour...")
(set-cursor-color "yellow"))
(defun switch-theme (theme)
"Disables any currently active themes and loads THEME."
;; This interactive call is taken from `load-theme'
(interactive
(list
(intern (completing-read "Load custom theme: "
(mapc 'symbol-name
(custom-available-themes))))))
(let ((enabled-themes custom-enabled-themes))
(mapc #'disable-theme custom-enabled-themes)
(load-theme theme t)))
(defun disable-active-themes ()
"Disables any currently active themes listed in `custom-enabled-themes'."
(interactive)
(mapc #'disable-theme custom-enabled-themes))
(bind-key "s-<f12>" 'switch-theme)
(bind-key "s-<f11>" 'disable-active-themes)
And here’s how we tell Emacs which font we want.
(if window-system
(progn
(add-to-list 'default-frame-alist '(font . "Envy Code R"))
;; (set-face-attribute 'variable-pitch nil :font "Cantarell" :height 120 :weight 'regular)
(set-face-attribute 'default nil :font "Envy Code R" :height 120)
(set-face-attribute 'fixed-pitch nil :font "Envy Code R-11")))
;; (set-face-attribute 'fixed-pitch nil :font "Fira Code Retina" :height 120)
When displaying the time with display-time-mode
, I don’t care about
the load average.
(setq display-time-default-load-average nil)
(use-package buffer-move
:ensure t
:config
(progn
(global-set-key (kbd "<C-M-s-up>") 'buf-move-up)
(global-set-key (kbd "<C-M-s-down>") 'buf-move-down)
(global-set-key (kbd "<C-M-s-left>") 'buf-move-left)
(global-set-key (kbd "<C-M-s-right>") 'buf-move-right)))
See the documentation for battery-mode-line-format
for the format
characters.
;; (setq battery-mode-line-format "[%b%p%% %t]")
Convenience bindings to use doc-view with the arrow keys.
(use-package doc-view
:commands doc-view-mode
:config
(define-key doc-view-mode-map (kbd "<right>") 'doc-view-next-page)
(define-key doc-view-mode-map (kbd "<left>") 'doc-view-previous-page))
(setq mouse-wheel-scroll-amount (quote (0.01)))
(use-package server
:config
(server-mode t))