mirror of
https://github.com/larstvei/dot-emacs.git
synced 2024-11-26 07:28:31 +00:00
1334 lines
50 KiB
Org Mode
1334 lines
50 KiB
Org Mode
#+TITLE: Emacs configuration file
|
|
#+AUTHOR: Lars Tveito
|
|
#+BABEL: :cache yes
|
|
#+LATEX_HEADER: \usepackage{parskip}
|
|
#+LATEX_HEADER: \usepackage{inconsolata}
|
|
#+LATEX_HEADER: \usepackage[utf8]{inputenc}
|
|
#+PROPERTY: header-args :tangle yes
|
|
|
|
* About
|
|
|
|
This is an Emacs configuration file written in [[http://orgmode.org][Org mode]]. It is an attempt
|
|
to keep my =~/.emacs.d= tidy, but still be able to keep it all in one
|
|
file. I aim to briefly explain all my configurations as I go along!
|
|
|
|
I would not recommend using this configuration /as-is/, because it
|
|
probably contains a lot you don't really need. I do, however, hope people
|
|
find some golden nuggets that they can smuggle into their own configs.
|
|
|
|
If you really do want to try this config out, this is how I'd go about it:
|
|
|
|
Clone the repo.
|
|
#+BEGIN_SRC sh :tangle no
|
|
git clone https://github.com/larstvei/dot-emacs
|
|
#+END_SRC
|
|
|
|
Backup your old =~/.emacs.d= (if necessary).
|
|
#+BEGIN_SRC sh :tangle no
|
|
mv ~/.emacs.d ~/.emacs.d-bak
|
|
#+END_SRC
|
|
|
|
Backup your old =~/.emacs=-file (if necessary).
|
|
#+BEGIN_SRC sh :tangle no
|
|
mv ~/.emacs ~/.emacs-bak
|
|
#+END_SRC
|
|
|
|
And finally
|
|
#+BEGIN_SRC sh :tangle no
|
|
mv dot-emacs ~/.emacs.d
|
|
#+END_SRC
|
|
|
|
On first run it should install a bunch of packages (this might take a
|
|
while), and you might have to restart your Emacs the first time. If you
|
|
experience bugs, please let me know!
|
|
|
|
* Configurations
|
|
** Meta
|
|
|
|
All changes to the configuration should be done in =init.org=, *not* in =init.el=. Any changes in the =init.el= will be overwritten by saving =init.org=. The =init.el= in this repo should not be tracked by git, and
|
|
is replaced the first time Emacs is started (assuming it has been renamed
|
|
to =~/.emacs.d=).
|
|
|
|
Emacs can't load =.org=-files directly, but =org-mode= provides functions
|
|
to extract the code blocks and write them to a file. There are multiple
|
|
ways of handling this; like suggested by [[http://emacs.stackexchange.com/questions/3143/can-i-use-org-mode-to-structure-my-emacs-or-other-el-configuration-file][this StackOverflow post]], one
|
|
could just use =org-babel-load-file=, but I had problems with
|
|
byte-compilation. Previously I tracked both the =org.=- and =el.=-files,
|
|
but the git commits got a little messy. So here is a new approach.
|
|
|
|
When this configuration is loaded for the first time, the ~init.el~ is
|
|
the file that is loaded. It looks like this:
|
|
|
|
#+BEGIN_SRC emacs-lisp :tangle no
|
|
;; This file replaces itself with the actual configuration at first run.
|
|
|
|
;; We can't tangle without org!
|
|
(require 'org)
|
|
;; Open the configuration
|
|
(find-file (concat user-emacs-directory "init.org"))
|
|
;; tangle it
|
|
(org-babel-tangle)
|
|
;; load it
|
|
(load-file (concat user-emacs-directory "init.el"))
|
|
;; finally byte-compile it
|
|
(byte-compile-file (concat user-emacs-directory "init.el"))
|
|
#+END_SRC
|
|
|
|
It tangles the org-file, so that this file is overwritten with the actual
|
|
configuration.
|
|
|
|
There is no reason to track the =init.el= that is generated; by running
|
|
the following command =git= will not bother tracking it:
|
|
|
|
#+BEGIN_SRC sh :tangle no
|
|
git update-index --assume-unchanged init.el
|
|
#+END_SRC
|
|
|
|
If one wishes to make changes to the repo-version of =init.el= start
|
|
tracking again with:
|
|
|
|
#+BEGIN_SRC sh :tangle no
|
|
git update-index --no-assume-unchanged init.el
|
|
#+END_SRC
|
|
|
|
I want lexical scoping for the init-file, which can be specified in the
|
|
header. The first line of the configuration is as follows:
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
;;; -*- lexical-binding: t -*-
|
|
#+END_SRC
|
|
|
|
The =init.el= should (after the first run) mirror the source blocks in
|
|
the =init.org=. We can use =C-c C-v t= to run =org-babel-tangle=, which
|
|
extracts the code blocks from the current file into a source-specific
|
|
file (in this case a =.el=-file).
|
|
|
|
To avoid doing this each time a change is made we can add a function to
|
|
the =after-save-hook= ensuring to always tangle and byte-compile the =org=-document after changes.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defun tangle-init ()
|
|
"If the current buffer is init.org the code-blocks are
|
|
tangled, and the tangled file is compiled."
|
|
(when (equal (buffer-file-name)
|
|
(expand-file-name (concat user-emacs-directory "init.org")))
|
|
;; Avoid running hooks when tangling.
|
|
(let ((prog-mode-hook nil))
|
|
(org-babel-tangle)
|
|
(byte-compile-file (concat user-emacs-directory "init.el")))))
|
|
|
|
(add-hook 'after-save-hook 'tangle-init)
|
|
#+END_SRC
|
|
|
|
I'd like to keep a few settings private, so we load a =private.el= if it
|
|
exists after the init-file has loaded.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-hook
|
|
'after-init-hook
|
|
(lambda ()
|
|
(let ((private-file (concat user-emacs-directory "private.el")))
|
|
(when (file-exists-p private-file)
|
|
(load-file private-file))
|
|
(when custom-file
|
|
(load-file custom-file))
|
|
(server-start))))
|
|
#+END_SRC
|
|
|
|
A common optimization is to temporarily disable garbage collection during
|
|
initialization. Here, we set the ~gc-cons-threshold~ to a ridiculously large
|
|
number, and restore the default value after initialization.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(let ((old-gc-treshold gc-cons-threshold))
|
|
(setq gc-cons-threshold most-positive-fixnum)
|
|
(add-hook 'after-init-hook
|
|
(lambda () (setq gc-cons-threshold old-gc-treshold))))
|
|
#+END_SRC
|
|
|
|
** Packages
|
|
|
|
Managing extensions for Emacs is simplified using =package= which is
|
|
built in to Emacs 24 and newer. To load downloaded packages we need to
|
|
initialize =package=. =cl= is a library that contains many functions from
|
|
Common Lisp, and comes in handy quite often, so we want to make sure it's
|
|
loaded, along with =package=, which is obviously needed.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(require 'package)
|
|
#+END_SRC
|
|
|
|
Packages can be fetched from different mirrors, [[http://melpa.milkbox.net/#/][melpa]] is the largest
|
|
archive and is well maintained.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq package-archives
|
|
'(("GNU ELPA" . "https://elpa.gnu.org/packages/")
|
|
("MELPA Stable" . "https://stable.melpa.org/packages/")
|
|
("MELPA" . "https://melpa.org/packages/"))
|
|
package-archive-priorities
|
|
'(("MELPA Stable" . 10)
|
|
("GNU ELPA" . 5)
|
|
("MELPA" . 0)))
|
|
#+END_SRC
|
|
|
|
The configuration assumes that the packages listed below are
|
|
installed. To ensure we install missing packages if they are missing.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(let* ((package--builtins nil)
|
|
(packages
|
|
'(auctex ; Integrated environment for *TeX*
|
|
auto-compile ; automatically compile Emacs Lisp libraries
|
|
cider ; Clojure Interactive Development Environment
|
|
clj-refactor ; Commands for refactoring Clojure code
|
|
company ; Modular text completion framework
|
|
company-coq ; A collection of extensions PG's Coq mode
|
|
counsel ; Various completion functions using Ivy
|
|
counsel-projectile ; Ivy integration for Projectile
|
|
define-word ; display the definition of word at point
|
|
diff-hl ; Highlight uncommitted changes using VC
|
|
doom-themes ; An opinionated pack of modern color-themes
|
|
erlang ; Erlang major mode
|
|
expand-region ; Increase selected region by semantic units
|
|
focus ; Dim color of text in surrounding sections
|
|
golden-ratio ; Automatic resizing windows to golden ratio
|
|
gnu-apl-mode ; Integrate GNU APL with Emacs
|
|
haskell-mode ; A Haskell editing mode
|
|
ivy-posframe ; Using posframe to show Ivy
|
|
jedi ; Python auto-completion for Emacs
|
|
js2-mode ; Improved JavaScript editing mode
|
|
lsp-java ; Java support for lsp-mode
|
|
lsp-mode ; LSP mode
|
|
lsp-ui ; UI modules for lsp-mode
|
|
magit ; control Git from Emacs
|
|
markdown-mode ; Emacs Major mode for Markdown-formatted files
|
|
maude-mode ; Emacs mode for the programming language Maude
|
|
minizinc-mode ; Major mode for MiniZinc code
|
|
multiple-cursors ; Multiple cursors for Emacs
|
|
nano-modeline ; N Λ N O modeline
|
|
nano-theme ; N Λ N O theme
|
|
nix-mode ; Major mode for editing .nix files
|
|
olivetti ; Minor mode for a nice writing environment
|
|
org ; Outline-based notes management and organizer
|
|
org-bullets ; Show bullets in org-mode as UTF-8 characters
|
|
paredit ; minor mode for editing parentheses
|
|
pdf-tools ; Emacs support library for PDF files
|
|
projectile ; Manage and navigate projects in Emacs easily
|
|
proof-general ; A generic Emacs interface for proof assistants
|
|
racket-mode ; Major mode for Racket language
|
|
rustic ; Rust development environment
|
|
slime ; Superior Lisp Interaction Mode for Emacs
|
|
smex ; M-x interface with Ido-style fuzzy matching
|
|
try ; Try out Emacs packages
|
|
vterm ; A terminal via libvterm
|
|
which-key ; Display available keybindings in popup
|
|
z3-mode))) ; z3/SMTLIBv2 interactive development
|
|
(when (memq window-system '(mac ns))
|
|
(push 'exec-path-from-shell packages)
|
|
(push 'reveal-in-osx-finder packages))
|
|
(let ((packages (seq-remove 'package-installed-p packages)))
|
|
(when packages
|
|
;; Install uninstalled packages
|
|
(package-refresh-contents)
|
|
(mapc 'package-install packages))))
|
|
#+END_SRC
|
|
|
|
** Mac OS X
|
|
|
|
I run this configuration mostly on Mac OS X, so we need a couple of
|
|
settings to make things work smoothly. In the package section =exec-path-from-shell= is included (only if you're running OS X), this is
|
|
to include environment-variables from the shell. It makes using Emacs
|
|
along with external processes a lot simpler. I also prefer using the =Command=-key as the =Meta=-key.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(when (memq window-system '(mac ns))
|
|
(setq ns-pop-up-frames nil
|
|
mac-option-modifier nil
|
|
mac-command-modifier 'meta)
|
|
(exec-path-from-shell-initialize)
|
|
(when (fboundp 'mac-auto-operator-composition-mode)
|
|
(mac-auto-operator-composition-mode 1)))
|
|
#+END_SRC
|
|
|
|
** Sane defaults
|
|
|
|
These are what /I/ consider to be saner defaults.
|
|
|
|
We can set variables to whatever value we'd like using =setq=.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq auto-revert-interval 1 ; Refresh buffers fast
|
|
default-input-method "TeX" ; Use TeX when toggling input method
|
|
echo-keystrokes 0.1 ; Show keystrokes asap
|
|
frame-inhibit-implied-resize 1 ; Don't resize frame implicitly
|
|
inhibit-startup-screen t ; No splash screen please
|
|
initial-scratch-message nil ; Clean scratch buffer
|
|
recentf-max-saved-items 10000 ; Show more recent files
|
|
ring-bell-function 'ignore ; Quiet
|
|
scroll-margin 1 ; Space between cursor and top/bottom
|
|
sentence-end-double-space nil ; No double space
|
|
custom-file ; Customizations in a separate file
|
|
(concat user-emacs-directory "custom.el"))
|
|
;; Some mac-bindings interfere with Emacs bindings.
|
|
(when (boundp 'mac-pass-command-to-system)
|
|
(setq mac-pass-command-to-system nil))
|
|
#+END_SRC
|
|
|
|
Some variables are buffer-local, so changing them using =setq= will only
|
|
change them in a single buffer. Using =setq-default= we change the
|
|
buffer-local variable's default value.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq-default tab-width 4 ; Smaller tabs
|
|
fill-column 79 ; Maximum line width
|
|
truncate-lines t ; Don't fold lines
|
|
indent-tabs-mode nil ; Use spaces instead of tabs
|
|
split-width-threshold 160 ; Split verticly by default
|
|
split-height-threshold nil ; Split verticly by default
|
|
frame-resize-pixelwise t ; Fine-grained frame resize
|
|
auto-fill-function 'do-auto-fill) ; Auto-fill-mode everywhere
|
|
#+END_SRC
|
|
|
|
The =load-path= specifies where Emacs should look for =.el=-files (or
|
|
Emacs lisp files). I have a directory called =site-lisp= where I keep all
|
|
extensions that have been installed manually (these are mostly my own
|
|
projects).
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(let ((default-directory (concat user-emacs-directory "site-lisp/")))
|
|
(when (file-exists-p default-directory)
|
|
(setq load-path
|
|
(append
|
|
(let ((load-path (copy-sequence load-path)))
|
|
(normal-top-level-add-subdirs-to-load-path)) load-path))))
|
|
#+END_SRC
|
|
|
|
Answering /yes/ and /no/ to each question from Emacs can be tedious, a
|
|
single /y/ or /n/ will suffice.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(fset 'yes-or-no-p 'y-or-n-p)
|
|
#+END_SRC
|
|
|
|
To avoid file system clutter we put all auto saved files in a single
|
|
directory.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defvar emacs-autosave-directory
|
|
(concat user-emacs-directory "autosaves/")
|
|
"This variable dictates where to put auto saves. It is set to a
|
|
directory called autosaves located wherever your .emacs.d/ is
|
|
located.")
|
|
|
|
;; Sets all files to be backed up and auto saved in a single directory.
|
|
(setq backup-directory-alist
|
|
`((".*" . ,emacs-autosave-directory))
|
|
auto-save-file-name-transforms
|
|
`((".*" ,emacs-autosave-directory t)))
|
|
#+END_SRC
|
|
|
|
Set =utf-8= as preferred coding system.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(set-language-environment "UTF-8")
|
|
#+END_SRC
|
|
|
|
By default the =narrow-to-region= command is disabled and issues a
|
|
warning, because it might confuse new users. I find it useful sometimes,
|
|
and don't want to be warned.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(put 'narrow-to-region 'disabled nil)
|
|
#+END_SRC
|
|
|
|
Automaticly revert =doc-view=-buffers when the file changes on disk.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-hook 'doc-view-mode-hook 'auto-revert-mode)
|
|
#+END_SRC
|
|
|
|
** Modes
|
|
|
|
There are some modes that are enabled by default that I don't find
|
|
particularly useful. We create a list of these modes, and disable all of
|
|
these.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(dolist (mode
|
|
'(tool-bar-mode ; No toolbars, more room for text
|
|
scroll-bar-mode ; No scroll bars either
|
|
blink-cursor-mode)) ; The blinking cursor gets old
|
|
(funcall mode 0))
|
|
#+END_SRC
|
|
|
|
Let's apply the same technique for enabling modes that are disabled by
|
|
default.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(dolist (mode
|
|
'(abbrev-mode ; E.g. sopl -> System.out.println
|
|
column-number-mode ; Show column number in mode line
|
|
delete-selection-mode ; Replace selected text
|
|
dirtrack-mode ; directory tracking in *shell*
|
|
global-company-mode ; Auto-completion everywhere
|
|
global-diff-hl-mode ; Highlight uncommitted changes
|
|
global-so-long-mode ; Mitigate performance for long lines
|
|
counsel-projectile-mode ; Manage and navigate projects
|
|
recentf-mode ; Recently opened files
|
|
show-paren-mode ; Highlight matching parentheses
|
|
which-key-mode)) ; Available keybindings in popup
|
|
(funcall mode 1))
|
|
#+END_SRC
|
|
|
|
** Visual
|
|
|
|
Let's set things with [[https://github.com/rougier/nano-emacs][rougier's N Λ N O Emacs]].
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq nano-light-background "#fafafa")
|
|
(load-theme 'nano-light t)
|
|
(nano-modeline-mode 1)
|
|
#+END_SRC
|
|
|
|
It looks best if we add a small margin around the edges of the frame.
|
|
|
|
#+begin_src emacs-lisp
|
|
(add-to-list 'default-frame-alist '(internal-border-width . 24))
|
|
#+end_src
|
|
|
|
I want to be able to quickly switch between a light and a dark theme.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defun cycle-themes ()
|
|
"Returns a function that lets you cycle your themes."
|
|
(let ((themes '(nano-light nano-dark)))
|
|
(lambda ()
|
|
(interactive)
|
|
;; Rotates the thme cycle and changes the current theme.
|
|
(let ((rotated (nconc (cdr themes) (list (car themes)))))
|
|
(load-theme (car (setq themes rotated)) t))
|
|
(message (concat "Switched to " (symbol-name (car themes)))))))
|
|
#+END_SRC
|
|
|
|
Pick the first of the following fonts that is installed on the system.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(cond ((member "Roboto Mono" (font-family-list))
|
|
(set-face-attribute 'default nil :font "Roboto Mono-14"))
|
|
((member "Fira Code" (font-family-list))
|
|
(set-face-attribute 'default nil :font "Fira Code-15"))
|
|
((member "Inconsolata" (font-family-list))
|
|
(set-face-attribute 'default nil :font "Inconsolata-14")))
|
|
#+END_SRC
|
|
|
|
New in Emacs 24.4 is the =prettify-symbols-mode=! It's neat.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq-default prettify-symbols-alist '(("lambda" . ?λ)
|
|
("delta" . ?Δ)
|
|
("gamma" . ?Γ)
|
|
("phi" . ?φ)
|
|
("psi" . ?ψ)))
|
|
#+END_SRC
|
|
|
|
[[https://github.com/rnkn/olivetti][Olivetti]] is a package that simply centers the text of a buffer. It is very
|
|
simple and beautiful. The default width is just a bit short.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(with-eval-after-load 'olivetti
|
|
(setq-default olivetti-body-width 82)
|
|
(remove-hook 'olivetti-mode-on-hook 'visual-line-mode))
|
|
#+END_SRC
|
|
|
|
** Ivy
|
|
|
|
[[http://oremacs.com/swiper/][Ivy]] is a completion system, giving you completions and fuzzy search whenever
|
|
you interact with the minibuffer. I transitioned to Ivy from [[https://emacs-helm.github.io/helm/][Helm]], mainly
|
|
due to it being aesthetically noisy, and that I didn't fully take advantage
|
|
of all its features (which are numerous). Here are some customization's that
|
|
made the transition a bit easier.
|
|
|
|
#+begin_src emacs-lisp
|
|
(setq ivy-wrap t ; Easier access to the last candidate
|
|
ivy-height 25 ; Give me more candidates to look at
|
|
ivy-use-virtual-buffers t ; C-x b displays recents and bookmarks
|
|
ivy-count-format "(%d/%d) " ; Display both the index and the count
|
|
ivy-on-del-error-function 'ignore ; Lets me hold in backspace
|
|
ivy-posframe-min-width 100 ; Keep ivy reasonably narrow
|
|
ivy-posframe-height ivy-height ; Maintain the height given by ivy
|
|
ivy-virtual-abbreviate 'abbreviate) ; Disambiguate same file in different dirs
|
|
(ivy-mode 1)
|
|
(ivy-posframe-mode 1)
|
|
#+end_src
|
|
|
|
** PDF Tools
|
|
|
|
[[https://github.com/politza/pdf-tools][PDF Tools]] makes a huge improvement on the built-in [[http://www.gnu.org/software/emacs/manual/html_node/emacs/Document-View.html][doc-view-mode]]; the only
|
|
drawback is the =pdf-tools-install= (which has to be executed before the
|
|
package can be used) takes a couple of /seconds/ to execute. Instead of
|
|
running it at init-time, we'll run it whenever a PDF is opened. Note that
|
|
it's only slow on the first run!
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(pdf-loader-install)
|
|
#+END_SRC
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-hook 'pdf-view-mode-hook
|
|
(lambda () (setq header-line-format nil)))
|
|
#+END_SRC
|
|
|
|
** Completion
|
|
|
|
[[https://github.com/auto-complete/auto-complete][Auto-Complete]] has been a part of my config for years, but I want to try
|
|
out [[http://company-mode.github.io/][company-mode]]. If I code in an environment with good completion, I've
|
|
made an habit of trying to /guess/ function-names, and looking at the
|
|
completions for the right one. So I want a pretty aggressive completion
|
|
system, hence the no delay settings and short prefix length.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq company-idle-delay 0
|
|
company-echo-delay 0
|
|
company-dabbrev-downcase nil
|
|
company-minimum-prefix-length 2
|
|
company-selection-wrap-around t
|
|
company-transformers '(company-sort-by-occurrence
|
|
company-sort-by-backend-importance))
|
|
#+END_SRC
|
|
|
|
** Spelling
|
|
|
|
Flyspell offers on-the-fly spell checking. We can enable flyspell for all
|
|
text-modes with this snippet.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-hook 'text-mode-hook 'turn-on-flyspell)
|
|
#+END_SRC
|
|
|
|
To use flyspell for programming there is =flyspell-prog-mode=, that only
|
|
enables spell checking for comments and strings. We can enable it for all
|
|
programming modes using the =prog-mode-hook=.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-hook 'prog-mode-hook 'flyspell-prog-mode)
|
|
#+END_SRC
|
|
|
|
Tell Emacs what program is used for spell checking.
|
|
|
|
#+begin_src emacs-lisp
|
|
(setq ispell-program-name "aspell")
|
|
#+end_src
|
|
|
|
When working with several languages, we should be able to cycle through
|
|
the languages we most frequently use. Every buffer should have a separate
|
|
cycle of languages, so that cycling in one buffer does not change the
|
|
state in a different buffer (this problem occurs if you only have one
|
|
global cycle). We can implement this by using a [[http://www.gnu.org/software/emacs/manual/html_node/elisp/Closures.html][closure]].
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defun cycle-languages ()
|
|
"Changes the ispell dictionary to the first element in
|
|
ISPELL-LANGUAGES, and returns an interactive function that cycles
|
|
the languages in ISPELL-LANGUAGES when invoked."
|
|
(let ((ispell-languages (list "american" "norsk")))
|
|
(ispell-change-dictionary (car ispell-languages))
|
|
(lambda ()
|
|
(interactive)
|
|
;; Rotates the languages cycle and changes the ispell dictionary.
|
|
(let ((rotated (nconc (cdr ispell-languages) (list (car ispell-languages)))))
|
|
(ispell-change-dictionary (car (setq ispell-languages rotated)))))))
|
|
#+END_SRC =flyspell= signals an error if there is no spell-checking tool is
|
|
installed. We can advice =turn-on-flyspell= and =flyspell-prog-mode= to
|
|
only try to enable =flyspell= if a spell-checking tool is available. Also
|
|
we want to enable cycling the languages by typing =C-c l=, so we bind the
|
|
function returned from =cycle-languages=.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defadvice turn-on-flyspell (before check nil activate)
|
|
"Turns on flyspell only if a spell-checking tool is installed."
|
|
(when (executable-find ispell-program-name)
|
|
(local-set-key (kbd "C-c l") (cycle-languages))))
|
|
#+END_SRC
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defadvice flyspell-prog-mode (before check nil activate)
|
|
"Turns on flyspell only if a spell-checking tool is installed."
|
|
(when (executable-find ispell-program-name)
|
|
(local-set-key (kbd "C-c l") (cycle-languages))))
|
|
#+END_SRC
|
|
|
|
** Org
|
|
|
|
When editing org-files with source-blocks, we want the source blocks to
|
|
be themed as they would in their native mode.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq org-src-fontify-natively t
|
|
org-src-tab-acts-natively t
|
|
org-confirm-babel-evaluate nil
|
|
org-edit-src-content-indentation 0)
|
|
#+END_SRC
|
|
|
|
This is quite an ugly fix for allowing code markup for expressions like ="this string"=, because the quotation marks causes problems.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(with-eval-after-load 'org
|
|
(require 'org-tempo)
|
|
(setcar (nthcdr 2 org-emphasis-regexp-components) " \t\n,")
|
|
(custom-set-variables `(org-emphasis-alist ',org-emphasis-alist)))
|
|
#+END_SRC
|
|
|
|
Enable org-bullets when opening org-files.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-hook 'org-mode-hook (lambda () (org-bullets-mode 1)))
|
|
#+END_SRC
|
|
|
|
** Email
|
|
|
|
I've used Emacs for email in the past, where I've always had the need for a
|
|
more standard email client in addition. I'm going to give it another go.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defvar load-mail-setup
|
|
(and (file-exists-p "~/Maildir")
|
|
(executable-find "mbsync")
|
|
(executable-find "msmtp")
|
|
(executable-find "mu")))
|
|
#+END_SRC
|
|
|
|
I use [[http://www.djcbsoftware.nl/code/mu/mu4e.html][mu4e]] (which is a part of [[http://www.djcbsoftware.nl/code/mu/][mu]]) along with [[https://isync.sourceforge.io/][mbsync]].
|
|
|
|
#+begin_src emacs-lisp
|
|
(when load-mail-setup
|
|
(with-eval-after-load 'mu4e
|
|
(setq
|
|
user-full-name "Lars Tveito" ; Your full name
|
|
user-mail-address "larstvei@ifi.uio.no" ; And email-address
|
|
|
|
|
|
sendmail-program (executable-find "msmtp")
|
|
send-mail-function 'smtpmail-send-it
|
|
|
|
message-sendmail-f-is-evil t
|
|
message-sendmail-extra-arguments '("--read-envelope-from")
|
|
message-send-mail-function 'message-send-mail-with-sendmail
|
|
message-kill-buffer-on-exit t
|
|
|
|
mu4e-get-mail-command (concat (executable-find "mbsync") " -a")
|
|
mu4e-change-filenames-when-moving t
|
|
mu4e-user-mail-address-list '("larstvei@ifi.uio.no")
|
|
mu4e-maildir-shortcuts '(("/Inbox" . ?i) ("/Sent Items" . ?s))
|
|
|
|
mu4e-sent-folder "/Sent Items"
|
|
mu4e-trash-folder "/Deleted Items"
|
|
mu4e-trash-folder "/Drafts"
|
|
|
|
mu4e-use-fancy-chars t))
|
|
(autoload 'mu4e "mu4e" nil t))
|
|
#+end_src
|
|
|
|
** Interactive functions
|
|
<<sec:defuns>> =just-one-space= removes all whitespace around a point - giving it a
|
|
negative argument it removes newlines as well. We wrap a interactive
|
|
function around it to be able to bind it to a key. In Emacs 24.4 =cycle-spacing= was introduced, and it works like =just-one-space=, but
|
|
when run in succession it cycles between one, zero and the original
|
|
number of spaces.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defun cycle-spacing-delete-newlines ()
|
|
"Removes whitespace before and after the point."
|
|
(interactive)
|
|
(if (version< emacs-version "24.4")
|
|
(just-one-space -1)
|
|
(cycle-spacing -1)))
|
|
#+END_SRC
|
|
|
|
Often I want to find other occurrences of a word I'm at, or more
|
|
specifically the symbol (or tag) I'm at. The =isearch-forward-symbol-at-point= in Emacs 24.4 works well for this, but
|
|
I don't want to be bothered with the =isearch= interface. Rather jump
|
|
quickly between occurrences of a symbol, or if non is found, don't do
|
|
anything.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defun jump-to-symbol-internal (&optional backwardp)
|
|
"Jumps to the next symbol near the point if such a symbol
|
|
exists. If BACKWARDP is non-nil it jumps backward."
|
|
(let* ((point (point))
|
|
(bounds (find-tag-default-bounds))
|
|
(beg (car bounds)) (end (cdr bounds))
|
|
(str (isearch-symbol-regexp (find-tag-default)))
|
|
(search (if backwardp 'search-backward-regexp
|
|
'search-forward-regexp)))
|
|
(goto-char (if backwardp beg end))
|
|
(funcall search str nil t)
|
|
(cond ((<= beg (point) end) (goto-char point))
|
|
(backwardp (forward-char (- point beg)))
|
|
(t (backward-char (- end point))))))
|
|
|
|
(defun jump-to-previous-like-this ()
|
|
"Jumps to the previous occurrence of the symbol at point."
|
|
(interactive)
|
|
(jump-to-symbol-internal t))
|
|
|
|
(defun jump-to-next-like-this ()
|
|
"Jumps to the next occurrence of the symbol at point."
|
|
(interactive)
|
|
(jump-to-symbol-internal))
|
|
#+END_SRC
|
|
|
|
I sometimes regret killing the =*scratch*=-buffer, and have realized I
|
|
never want to actually kill it. I just want to get it out of the way, and
|
|
clean it up. The function below does just this for the =*scratch*=-buffer, and works like =kill-this-buffer= for any other
|
|
buffer. It removes all buffer content and buries the buffer (this means
|
|
making it the least likely candidate for =other-buffer=).
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defun kill-this-buffer-unless-scratch ()
|
|
"Works like `kill-this-buffer' unless the current buffer is the
|
|
,*scratch* buffer. In witch case the buffer content is deleted and
|
|
the buffer is buried."
|
|
(interactive)
|
|
(if (not (string= (buffer-name) "*scratch*"))
|
|
(kill-this-buffer)
|
|
(delete-region (point-min) (point-max))
|
|
(switch-to-buffer (other-buffer))
|
|
(bury-buffer "*scratch*")))
|
|
#+END_SRC
|
|
|
|
To duplicate either selected text or a line we define this interactive
|
|
function.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defun duplicate-thing (comment)
|
|
"Duplicates the current line, or the region if active. If an argument is
|
|
given, the duplicated region will be commented out."
|
|
(interactive "P")
|
|
(save-excursion
|
|
(let ((start (if (region-active-p) (region-beginning) (line-beginning-position)))
|
|
(end (if (region-active-p) (region-end) (line-end-position)))
|
|
(fill-column most-positive-fixnum))
|
|
(goto-char end)
|
|
(unless (region-active-p)
|
|
(newline))
|
|
(insert (buffer-substring start end))
|
|
(when comment (comment-region start end)))))
|
|
#+END_SRC
|
|
|
|
To tidy up a buffer we define this function borrowed from [[https://github.com/simenheg][simenheg]].
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defun tidy ()
|
|
"Ident, untabify and unwhitespacify current buffer, or region if active."
|
|
(interactive)
|
|
(let ((beg (if (region-active-p) (region-beginning) (point-min)))
|
|
(end (if (region-active-p) (region-end) (point-max))))
|
|
(indent-region beg end)
|
|
(whitespace-cleanup)
|
|
(untabify beg (if (< end (point-max)) end (point-max)))))
|
|
#+END_SRC
|
|
|
|
Org mode does currently not support synctex (which enables you to jump from
|
|
a point in your TeX-file to the corresponding point in the pdf), and it
|
|
[[http://comments.gmane.org/gmane.emacs.orgmode/69454][seems like a tricky problem]].
|
|
|
|
Calling this function from an org-buffer jumps to the corresponding section
|
|
in the exported pdf (given that the pdf-file exists), using pdf-tools.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defun org-sync-pdf ()
|
|
(interactive)
|
|
(let ((headline (nth 4 (org-heading-components)))
|
|
(pdf (concat (file-name-base (buffer-name)) ".pdf")))
|
|
(when (file-exists-p pdf)
|
|
(find-file-other-window pdf)
|
|
(pdf-links-action-perform
|
|
(cl-find headline (pdf-info-outline pdf)
|
|
:key (lambda (alist) (cdr (assoc 'title alist)))
|
|
:test 'string-equal)))))
|
|
#+END_SRC
|
|
|
|
The opposite of fill paragraph (from [[https://www.emacswiki.org/emacs/UnfillParagraph][EmacsWiki]]),
|
|
|
|
#+begin_src emacs-lisp
|
|
(defun unfill-paragraph ()
|
|
(interactive)
|
|
(let ((fill-column most-positive-fixnum))
|
|
(fill-paragraph nil (region-active-p))))
|
|
#+end_src
|
|
|
|
** Advice
|
|
|
|
An advice can be given to a function to make it behave differently. This
|
|
advice makes =eval-last-sexp= (bound to =C-x C-e=) replace the sexp with
|
|
the value.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defadvice eval-last-sexp (around replace-sexp (arg) activate)
|
|
"Replace sexp when called with a prefix argument."
|
|
(if arg
|
|
(let ((pos (point)))
|
|
ad-do-it
|
|
(goto-char pos)
|
|
(backward-kill-sexp)
|
|
(forward-sexp))
|
|
ad-do-it))
|
|
#+END_SRC
|
|
|
|
When interactively changing the theme (using =M-x load-theme=), the
|
|
current custom theme is not disabled. This often gives weird-looking
|
|
results; we can advice =load-theme= to always disable themes currently
|
|
enabled themes.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defadvice load-theme
|
|
(before disable-before-load (theme &optional no-confirm no-enable) activate)
|
|
(mapc 'disable-theme custom-enabled-themes))
|
|
#+END_SRC
|
|
|
|
** global-scale-mode
|
|
|
|
These functions provide something close to ~text-scale-mode~, but for every
|
|
buffer, including the minibuffer and mode line.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(let* ((default (face-attribute 'default :height))
|
|
(size default))
|
|
|
|
(defun global-scale-default ()
|
|
(interactive)
|
|
(global-scale-internal (setq size default)))
|
|
|
|
(defun global-scale-up ()
|
|
(interactive)
|
|
(global-scale-internal (setq size (+ size 20))))
|
|
|
|
(defun global-scale-down ()
|
|
(interactive)
|
|
(global-scale-internal (setq size (- size 20))))
|
|
|
|
(defun global-scale-internal (arg)
|
|
(set-face-attribute 'default (selected-frame) :height arg)
|
|
(set-temporary-overlay-map
|
|
(let ((map (make-sparse-keymap)))
|
|
(define-key map (kbd "C-=") 'global-scale-up)
|
|
(define-key map (kbd "C-+") 'global-scale-up)
|
|
(define-key map (kbd "C--") 'global-scale-down)
|
|
(define-key map (kbd "C-0") 'global-scale-default) map))))
|
|
#+END_SRC
|
|
|
|
* Mode specific
|
|
** LSP
|
|
|
|
LSP mode works really well, especially with languages like Java, which
|
|
traditionally has had quite poor Emacs support.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(with-eval-after-load 'lsp-mode
|
|
(define-key lsp-mode-map (kbd "C-c f") lsp-command-map)
|
|
(add-hook 'lsp-mode-hook #'lsp-enable-which-key-integration)
|
|
(add-hook 'lsp-mode-hook #'yas-minor-mode)
|
|
(add-hook 'lsp-mode-hook (lambda () (lsp-headerline-breadcrumb-mode 0)))
|
|
(add-to-list 'lsp-file-watch-ignored-directories "[/\\\\]\\.hypothesis\\'"))
|
|
#+END_SRC
|
|
|
|
** Compilation
|
|
|
|
I often run ~latexmk -pdf -pvc~ in a compilation buffer, which recompiles
|
|
the latex-file whenever it is changed. This often results in annoyingly
|
|
large compilation buffers; the following snippet limits the buffer size in
|
|
accordance with ~comint-buffer-maximum-size~, which defaults to 1024 lines.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-hook 'compilation-filter-hook 'comint-truncate-buffer)
|
|
#+END_SRC
|
|
|
|
** Shell
|
|
|
|
Inspired by [[https://github.com/torenord/.emacs.d][torenord]], I maintain quick access to shell buffers with bindings ~M-1~ to ~M-9~. In addition, the ~M-z~ toggles between the last visited
|
|
shell, and the last visited non-shell buffer. The following functions
|
|
facilitate this, and are bound in the [[Key bindings]] section.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(let ((last-vterm ""))
|
|
(defun toggle-vterm ()
|
|
(interactive)
|
|
(cond ((string-match-p "^\\vterm<[1-9][0-9]*>$" (buffer-name))
|
|
(goto-non-vterm-buffer))
|
|
((get-buffer last-vterm) (switch-to-buffer last-vterm))
|
|
(t (vterm (setq last-vterm "vterm<1>")))))
|
|
|
|
(defun switch-vterm (n)
|
|
(let ((buffer-name (format "vterm<%d>" n)))
|
|
(setq last-vterm buffer-name)
|
|
(cond ((get-buffer buffer-name)
|
|
(switch-to-buffer buffer-name))
|
|
(t (vterm buffer-name)
|
|
(rename-buffer buffer-name)))))
|
|
|
|
(defun goto-non-vterm-buffer ()
|
|
(let* ((r "^\\vterm<[1-9][0-9]*>$")
|
|
(vterm-buffer-p (lambda (b) (string-match-p r (buffer-name b))))
|
|
(non-vterms (cl-remove-if vterm-buffer-p (buffer-list))))
|
|
(when non-vterms
|
|
(switch-to-buffer (car non-vterms))))))
|
|
#+END_SRC
|
|
|
|
Don't query whether or not the ~shell~-buffer should be killed, just kill
|
|
it.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defadvice vterm (after kill-with-no-query nil activate)
|
|
(set-process-query-on-exit-flag (get-buffer-process ad-return-value) nil))
|
|
#+END_SRC
|
|
|
|
** Lisp
|
|
|
|
I use =Paredit= when editing lisp code, we enable this for all lisp-modes.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(dolist (mode '(cider-repl-mode
|
|
clojure-mode
|
|
ielm-mode
|
|
racket-mode
|
|
racket-repl-mode
|
|
slime-repl-mode
|
|
lisp-mode
|
|
emacs-lisp-mode
|
|
lisp-interaction-mode
|
|
scheme-mode))
|
|
;; add paredit-mode to all mode-hooks
|
|
(add-hook (intern (concat (symbol-name mode) "-hook")) 'paredit-mode))
|
|
#+END_SRC
|
|
|
|
*** Emacs Lisp
|
|
|
|
In =emacs-lisp-mode= we can enable =eldoc-mode= to display information
|
|
about a function or a variable in the echo area.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-hook 'emacs-lisp-mode-hook 'turn-on-eldoc-mode)
|
|
(add-hook 'lisp-interaction-mode-hook 'turn-on-eldoc-mode)
|
|
#+END_SRC
|
|
|
|
*** Common lisp
|
|
|
|
I use [[http://www.common-lisp.net/project/slime/][Slime]] along with =lisp-mode= to edit Common Lisp code. Slime
|
|
provides code evaluation and other great features, a must have for a
|
|
Common Lisp developer. [[http://www.quicklisp.org/beta/][Quicklisp]] is a library manager for Common Lisp,
|
|
and you can install Slime following the instructions from the site along
|
|
with this snippet.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defun activate-slime-helper ()
|
|
(when (file-exists-p "~/.quicklisp/slime-helper.el")
|
|
(load (expand-file-name "~/.quicklisp/slime-helper.el"))
|
|
(define-key slime-repl-mode-map (kbd "C-l")
|
|
'slime-repl-clear-buffer))
|
|
(remove-hook 'common-lisp-mode-hook #'activate-slime-helper))
|
|
|
|
(add-hook 'common-lisp-mode-hook #'activate-slime-helper)
|
|
#+END_SRC
|
|
|
|
We can specify what Common Lisp program Slime should use (I use SBCL).
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq inferior-lisp-program "sbcl")
|
|
#+END_SRC
|
|
|
|
More sensible =loop= indentation, borrowed from [[https://github.com/simenheg][simenheg]].
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq lisp-loop-forms-indentation 6
|
|
lisp-simple-loop-indentation 2
|
|
lisp-loop-keyword-indentation 6)
|
|
#+END_SRC
|
|
|
|
** Python
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq python-shell-interpreter "python3")
|
|
(add-hook 'python-mode-hook
|
|
(lambda () (setq forward-sexp-function nil)))
|
|
#+END_SRC
|
|
|
|
** C
|
|
|
|
The =c-mode-common-hook= is a general hook that work on all C-like
|
|
languages (C, C++, Java, etc...). I like being able to quickly compile
|
|
using =C-c C-c= (instead of =M-x compile=), a habit from =latex-mode=.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defun c-setup ()
|
|
(local-set-key (kbd "C-c C-c") 'compile))
|
|
|
|
(add-hook 'c-mode-hook 'c-setup)
|
|
#+END_SRC
|
|
|
|
** Java
|
|
|
|
Some statements in Java appear often, and become tedious to write
|
|
out. We can use abbrevs to speed this up.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(define-abbrev-table 'java-mode-abbrev-table
|
|
'(("psv" "public static void main(String[] args) {" nil 0)
|
|
("sopl" "System.out.println" nil 0)
|
|
("sop" "System.out.printf" nil 0)))
|
|
#+END_SRC
|
|
|
|
To be able to use the abbrev table defined above, =abbrev-mode= must be
|
|
activated.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-hook 'java-mode-hook 'lsp)
|
|
#+END_SRC
|
|
|
|
** Assembler
|
|
|
|
When writing assembler code I use =#= for comments. By defining =comment-start= we can add comments using =M-;= like in other programming
|
|
modes. Also in assembler should one be able to compile using =C-c C-c=.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defun asm-setup ()
|
|
(setq comment-start "#")
|
|
(local-set-key (kbd "C-c C-c") 'compile))
|
|
|
|
(add-hook 'asm-mode-hook 'asm-setup)
|
|
#+END_SRC
|
|
|
|
** LaTeX and org-mode LaTeX export =.tex=-files should be associated with =latex-mode= instead of =tex-mode=.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-to-list 'auto-mode-alist '("\\.tex\\'" . latex-mode))
|
|
#+END_SRC
|
|
|
|
Use [[http://mg.readthedocs.io/latexmk.html][latexmk]] for compilation by default.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-hook 'LaTeX-mode-hook
|
|
(lambda ()
|
|
(add-hook 'hack-local-variables-hook
|
|
(lambda ()
|
|
(setq-local compile-command
|
|
(concat "latexmk -pdf -pvc "
|
|
(if (eq TeX-master t)
|
|
(file-name-base (buffer-name))
|
|
TeX-master))))
|
|
t t)))
|
|
#+END_SRC
|
|
|
|
Use ~biblatex~ for bibliography.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(setq-default bibtex-dialect 'biblatex)
|
|
#+END_SRC
|
|
|
|
I like using the [[https://code.google.com/p/minted/][Minted]] package for source blocks in LaTeX. To make org
|
|
use this we add the following snippet.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(eval-after-load 'org
|
|
'(add-to-list 'org-latex-packages-alist '("" "minted")))
|
|
(setq org-latex-listings 'minted)
|
|
#+END_SRC
|
|
|
|
Because [[https://code.google.com/p/minted/][Minted]] uses [[http://pygments.org][Pygments]] (an external process), we must add the =-shell-escape= option to the =org-latex-pdf-process= commands. The =tex-compile-commands= variable controls the default compile command for
|
|
Tex- and LaTeX-mode, we can add the flag with a rather dirty statement
|
|
(if anyone finds a nicer way to do this, please let me know).
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(eval-after-load 'tex-mode
|
|
'(setcar (cdr (cddaar tex-compile-commands)) " -shell-escape "))
|
|
#+END_SRC
|
|
|
|
When exporting from Org to LaTeX, use ~latexmk~ for compilation.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(eval-after-load 'ox-latex
|
|
'(setq org-latex-pdf-process
|
|
'("latexmk -pdflatex='xelatex -shell-escape -interaction nonstopmode' -pdf -f %f")))
|
|
#+END_SRC
|
|
|
|
For my thesis, I need to use our university's LaTeX class, this snippet
|
|
makes that class available.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(eval-after-load "ox-latex"
|
|
'(progn
|
|
(add-to-list 'org-latex-classes
|
|
'("ifimaster"
|
|
"\\documentclass{ifimaster}
|
|
[DEFAULT-PACKAGES]
|
|
[PACKAGES]
|
|
[EXTRA]
|
|
\\usepackage{babel,csquotes,ifimasterforside,url,varioref}"
|
|
("\\chapter{%s}" . "\\chapter*{%s}")
|
|
("\\section{%s}" . "\\section*{%s}")
|
|
("\\subsection{%s}" . "\\subsection*{%s}")
|
|
("\\subsubsection{%s}" . "\\subsubsection*{%s}")
|
|
("\\paragraph{%s}" . "\\paragraph*{%s}")
|
|
("\\subparagraph{%s}" . "\\subparagraph*{%s}")))
|
|
(add-to-list 'org-latex-classes
|
|
'("easychair" "\\documentclass{easychair}"
|
|
("\\section{%s}" . "\\section*{%s}")
|
|
("\\subsection{%s}" . "\\subsection*{%s}")
|
|
("\\subsubsection{%s}" . "\\subsubsection*{%s}")
|
|
("\\paragraph{%s}" . "\\paragraph*{%s}")
|
|
("\\subparagraph{%s}" . "\\subparagraph*{%s}")))
|
|
(custom-set-variables '(org-export-allow-bind-keywords t))))
|
|
#+END_SRC
|
|
|
|
Use Emacs for opening the PDF file, when invoking ~C-c C-e l o~.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(require 'org)
|
|
(add-to-list 'org-file-apps '("\\.pdf\\'" . emacs))
|
|
(setq org-adapt-indentation t)
|
|
#+END_SRC
|
|
|
|
#+begin_src emacs-lisp
|
|
(setq org-babel-python-command "python3")
|
|
(org-babel-do-load-languages
|
|
'org-babel-load-languages
|
|
'((emacs-lisp . t)
|
|
(python . t)
|
|
(clojure . t)))
|
|
#+end_src
|
|
|
|
** Haskell =haskell-doc-mode= is similar to =eldoc=, it displays documentation in
|
|
the echo area. Haskell has several indentation modes - I prefer using =haskell-indent=.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-hook 'haskell-mode-hook 'interactive-haskell-mode)
|
|
(add-hook 'haskell-mode-hook 'turn-on-haskell-doc-mode)
|
|
(add-hook 'haskell-mode-hook 'turn-on-haskell-indent)
|
|
#+END_SRC
|
|
|
|
** Maude
|
|
|
|
Use =---= for comments in Maude.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-hook 'maude-mode-hook
|
|
(lambda ()
|
|
(setq-local comment-start "---")))
|
|
|
|
(with-eval-after-load 'maude-mode
|
|
(add-to-list 'maude-command-options "-no-wrap"))
|
|
#+END_SRC
|
|
|
|
** Minizinc
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-to-list 'auto-mode-alist '("\\.mzn\\'" . minizinc-mode))
|
|
|
|
(defun minizinc-setup ()
|
|
(let ((command (concat "minizinc " (buffer-file-name) " "))
|
|
(f (concat (file-name-base (buffer-file-name)) ".dzn")))
|
|
(local-set-key (kbd "C-c C-c") 'recompile)
|
|
(setq-local compile-command (concat command (if (file-exists-p f) f "")))))
|
|
|
|
(add-hook 'minizinc-mode-hook 'minizinc-setup)
|
|
#+END_SRC
|
|
|
|
** Coq
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(add-hook 'coq-mode-hook #'company-coq-mode)
|
|
#+END_SRC
|
|
|
|
** APL
|
|
|
|
#+begin_src emacs-lisp
|
|
(with-eval-after-load 'gnu-apl-mode
|
|
(setq gnu-apl-key-prefix ?`)
|
|
(gnu-apl--initialize-key-prefix 'gnu-apl-key-prefix ?`)
|
|
(add-hook 'gnu-apl-mode-hook (lambda () (activate-input-method "APL-Z")))
|
|
(add-hook 'gnu-apl-interactive-mode-hook (lambda () (activate-input-method "APL-Z"))))
|
|
#+end_src
|
|
|
|
** Rust
|
|
|
|
#+begin_src emacs-lisp
|
|
(setq lsp-rust-server 'rust-analyzer)
|
|
(setq lsp-rust-analyzer-cargo-watch-command "clippy")
|
|
#+end_src
|
|
|
|
* Key bindings
|
|
|
|
Inspired by [[http://stackoverflow.com/questions/683425/globally-override-key-binding-in-emacs][this StackOverflow post]] I keep a =custom-bindings-map= that
|
|
holds all my custom bindings. This map can be activated by toggling a
|
|
simple =minor-mode= that does nothing more than activating the map. This
|
|
inhibits other =major-modes= to override these bindings. I keep this at
|
|
the end of the init-file to make sure that all functions are actually
|
|
defined.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(defvar custom-bindings-map (make-keymap)
|
|
"A keymap for custom bindings.")
|
|
#+END_SRC
|
|
|
|
** Bindings for [[https://github.com/abo-abo/define-word][define-word]]
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(define-key custom-bindings-map (kbd "C-c D") 'define-word-at-point)
|
|
#+END_SRC
|
|
|
|
** Bindings for [[https://github.com/magnars/expand-region.el][expand-region]]
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(define-key custom-bindings-map (kbd "C->") 'er/expand-region)
|
|
(define-key custom-bindings-map (kbd "C-<") 'er/contract-region)
|
|
#+END_SRC
|
|
|
|
** Bindings for [[https://github.com/magnars/multiple-cursors.el][multiple-cursors]]
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(define-key custom-bindings-map (kbd "C-c e") 'mc/edit-lines)
|
|
(define-key custom-bindings-map (kbd "C-c a") 'mc/mark-all-like-this)
|
|
(define-key custom-bindings-map (kbd "C-c n") 'mc/mark-next-like-this)
|
|
#+END_SRC
|
|
|
|
** Bindings for [[https://magit.vc/][Magit]]
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(define-key custom-bindings-map (kbd "C-c m") 'magit-status)
|
|
#+END_SRC
|
|
|
|
** Bindings for [[https://github.com/abo-abo/swiper][Counsel]]
|
|
|
|
#+begin_src emacs-lisp
|
|
(global-set-key (kbd "C-c i") 'swiper-isearch)
|
|
(global-set-key (kbd "M-x") 'counsel-M-x)
|
|
(global-set-key (kbd "C-x C-f") 'counsel-find-file)
|
|
(global-set-key (kbd "M-y") 'counsel-yank-pop)
|
|
(global-set-key (kbd "C-x b") 'ivy-switch-buffer)
|
|
#+end_src
|
|
|
|
** Bindings for [[http://company-mode.github.io/][company-mode]]
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(define-key company-active-map (kbd "C-d") 'company-show-doc-buffer)
|
|
(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 "<tab>") 'company-complete)
|
|
#+END_SRC
|
|
|
|
** Bindings for [[https://github.com/bbatsov/projectile][Projectile]]
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(define-key projectile-mode-map (kbd "C-c p") 'projectile-command-map)
|
|
#+END_SRC
|
|
|
|
** Bindings for [[https://github.com/clojure-emacs/cider][Cider]]
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(with-eval-after-load 'cider
|
|
(define-key cider-repl-mode-map (kbd "C-l") 'cider-repl-clear-buffer))
|
|
#+END_SRC
|
|
|
|
** Bindings for [[https://github.com/rnkn/olivetti][Olivetti]]
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(define-key custom-bindings-map (kbd "C-c o") 'olivetti-mode)
|
|
#+END_SRC
|
|
|
|
** Bindings for mu4e
|
|
|
|
#+begin_src emacs-lisp
|
|
(define-key custom-bindings-map (kbd "C-x m") 'mu4e)
|
|
#+end_src
|
|
|
|
** Bindings for built-ins
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(define-key custom-bindings-map (kbd "M-u") 'upcase-dwim)
|
|
(define-key custom-bindings-map (kbd "M-c") 'capitalize-dwim)
|
|
(define-key custom-bindings-map (kbd "M-l") 'downcase-dwim)
|
|
(define-key custom-bindings-map (kbd "M-]") 'other-frame)
|
|
(define-key custom-bindings-map (kbd "C-j") 'newline-and-indent)
|
|
(define-key custom-bindings-map (kbd "C-c s") 'ispell-word)
|
|
(define-key comint-mode-map (kbd "C-l") 'comint-clear-buffer)
|
|
#+END_SRC
|
|
|
|
** Bindings for functions defined [[sec:defuns][above]].
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(define-key global-map (kbd "M-p") 'jump-to-previous-like-this)
|
|
(define-key global-map (kbd "M-n") 'jump-to-next-like-this)
|
|
(define-key custom-bindings-map (kbd "M-,") 'jump-to-previous-like-this)
|
|
(define-key custom-bindings-map (kbd "M-.") 'jump-to-next-like-this)
|
|
(define-key custom-bindings-map (kbd "C-c .") (cycle-themes))
|
|
(define-key custom-bindings-map (kbd "C-x k") 'kill-this-buffer-unless-scratch)
|
|
(define-key custom-bindings-map (kbd "C-c C-0") 'global-scale-default)
|
|
(define-key custom-bindings-map (kbd "C-c C-=") 'global-scale-up)
|
|
(define-key custom-bindings-map (kbd "C-c C-+") 'global-scale-up)
|
|
(define-key custom-bindings-map (kbd "C-c C--") 'global-scale-down)
|
|
(define-key custom-bindings-map (kbd "C-c j") 'cycle-spacing-delete-newlines)
|
|
(define-key custom-bindings-map (kbd "C-c d") 'duplicate-thing)
|
|
(define-key custom-bindings-map (kbd "<C-tab>") 'tidy)
|
|
(define-key custom-bindings-map (kbd "C-z") 'toggle-vterm)
|
|
(dolist (n (number-sequence 1 9))
|
|
(global-set-key (kbd (concat "M-" (int-to-string n)))
|
|
(lambda () (interactive) (switch-vterm n))))
|
|
(define-key custom-bindings-map (kbd "C-c C-q")
|
|
'(lambda ()
|
|
(interactive)
|
|
(focus-mode 1)
|
|
(focus-read-only-mode 1)))
|
|
(with-eval-after-load 'org
|
|
(define-key org-mode-map (kbd "C-'") 'org-sync-pdf))
|
|
#+END_SRC
|
|
|
|
Lastly we need to activate the map by creating and activating the =minor-mode=.
|
|
|
|
#+BEGIN_SRC emacs-lisp
|
|
(define-minor-mode custom-bindings-mode
|
|
"A mode that activates custom-bindings."
|
|
t nil custom-bindings-map)
|
|
#+END_SRC
|
|
* License
|
|
|
|
My Emacs configurations written in Org mode.
|
|
|
|
Copyright (c) 2013 - 2020 Lars Tveito
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|