You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

1911 lines
74 KiB

#+TITLE: emacs init file
#+AUTHOR: Jacopo De Simoi
#+EMAIL: jacopods@math.utoronto.ca
#+OPTIONS: *:t ::t
* TODO Make indentation uniform
* TODO Look at tangling at
[http://thewanderingcoder.com/2015/02/literate-emacs-configuration/]
although I'd rather do something like a local variable evaluation such as
# -*- eval: (add-hook 'before-save-hook icalendar-export-to-ics nil t) -*-
Or makefile approach
[https://emacs.stackexchange.com/questions/27126/is-it-possible-to-org-bable-tangle-an-org-file-from-the-command-line]
See also [http://orgmode.org/manual/Extracting-source-code.html#Extracting-source-code]
* Introduction
** ~setq~ vs ~setq-default~
Some variables are buffer-local, others are not; for non buffer-local
variables the two commands are equivalent; for the buffer-local variables,
setq acts on the current buffer, whereas setq-default sets the default
value of the variable for buffers that do not have a local value.
:source: [https://stackoverflow.com/a/18173666]
** Why not ~package.el~
it is convenient, but it is not git-based; ~borg.el~ is promising, but it is
way complicated; I can do everything by hand as soon as it is neatly
~org~-anized. In the end we use a few, but I plan to phase them out and
replace them with git submodules
* Files and dirs
Move ~Customize~ to a separate file
#+BEGIN_SRC emacs-lisp
(setq custom-file "~/.emacs.d/custom.el")
(load custom-file 'noerror)
#+END_SRC
Add relevant dirs to load path [This is somewhat undesirable; I should
uniformize the path-loading business at some point…]
#+BEGIN_SRC emacs-lisp
(let ((default-directory "~/.emacs.d/"))
(normal-top-level-add-subdirs-to-load-path)
(normal-top-level-add-to-load-path '("biblio.el"
"fringe-helper.el"
"multiple-cursors.el"
"expand-region.el"
"dash.el"
"webpaste.el"
"highlight-parentheses.el")))
#+END_SRC
Put autosave files (ie #foo#) and backup files (ie foo~) in ~/.emacs.d/.
create the autosave dir if necessary, since emacs won't.
#+BEGIN_SRC emacs-lisp
(make-directory "~/.emacs.d/autosaves/" t)
(make-directory "~/.emacs.d/backup/" t)
#+END_SRC
* Themes
Use (my clone of) the solarized theme
#+BEGIN_SRC emacs-lisp
(add-to-list 'custom-theme-load-path "/home/jacopods/.emacs.d/emacs-color-theme-solarized")
(load-theme 'lunarized t)
#+END_SRC
Use patched terminus font (this overrides the settings in Customize, but I
never could it to work otherwise). See the special treatment later on for
dealing with bold weight. To avoid flickering one should also set the font
in .Xresources
#+BEGIN_SRC emacs-lisp
(set-face-font 'default "-xos4-hackminus-medium-r-normal--20-200-72-72-c-100-ISO10646-1")
(set-face-font 'fixed-pitch "-xos4-hackminus-medium-r-normal--20-200-72-72-c-100-ISO10646-1")
(set-face-font 'fixed-pitch-serif "-xos4-hackminus-medium-r-normal--20-200-72-72-c-100-ISO10646-1")
(set-face-font 'variable-pitch "-xos4-hackminus-medium-r-normal--20-200-72-72-c-100-ISO10646-1")
#+END_SRC
* Global settings
** Global helper functions
This is a helper function used to set several global keys given in
provided as a parameter in ~binding-alist~
#+BEGIN_SRC emacs-lisp
(defun global-set-key-alist (binding-alist)
"This function iterates over the binding-alist, which should be an alist of key and binding and sets each binding in the global-key-map"
(mapcar
(lambda (binding)
(global-set-key (kbd (car binding)) (cdr binding))) binding-alist))
(defun define-key-alist (keymap binding-alist)
"This function iterates over the binding-alist, which should be an alist of key and binding and sets each binding in the global-key-map"
(mapcar
(lambda (binding)
(define-key keymap (kbd (car binding)) (cdr binding))) binding-alist))
#+END_SRC
This is a hack to remove slant and bold from all faces
#+BEGIN_SRC emacs-lisp
(defun wilder/fixup-faces ()
(mapc (lambda (face)
(set-face-attribute face nil :weight 'normal)
(set-face-attribute face nil :slant 'normal))
(face-list))
(set-face-font 'default "-xos4-hackminus-medium-r-normal--20-200-72-72-c-100-ISO10646-1"))
#+END_SRC
** Cosmetics
Prefer a minimal appearance: no menu, toolbar or scroll-bars; no
splash screens or messages
#+BEGIN_SRC emacs-lisp
(menu-bar-mode -1)
(tool-bar-mode 0)
(scroll-bar-mode -1)
(setq inhibit-startup-screen t
inhibit-startup-message t)
#+END_SRC
a blinking cursor keeps the gpu awake; add global hl-line mode to more
easily spot the cursor
#+BEGIN_SRC emacs-lisp
(blink-cursor-mode 0)
(set-default 'cursor-type 'box)
#+END_SRC
Set frame title
#+BEGIN_SRC emacs-lisp
(setq frame-title-format
'((buffer-file-name "%f"
(dired-directory dired-directory "%b")) " · emacs"));; · " (:eval (kde-current-activity-name)))) ;; "%S"))
#+END_SRC
Themed tooltips
#+BEGIN_SRC emacs-lisp
(setq x-gtk-use-system-tooltips nil)
#+END_SRC
Set =fill-column= to 72, which happens to be good for third-tiled frames
and it also is a reasonable standard
#+BEGIN_SRC emacs-lisp
(setq default-fill-column 72)
#+END_SRC
Highlight sexp (apparently I am not even using this)
#+BEGIN_SRC emacs-lisp
;(require 'highlight-sexps)
#+END_SRC
Try to get along with large margins
#+BEGIN_SRC emacs-lisp
(setq-default left-margin-width 3
right-margin-width 3)
(fringe-mode 10)
;(set-window-buffer nil (current-buffer))
#+END_SRC
** Mouseless
Disable mouse interaction with emacs
#+BEGIN_SRC emacs-lisp
(mouse-wheel-mode -1)
(setq mouse-autoselect-window nil
mouse-yank-at-point nil
focus-follows-mouse nil
mouse-highlight nil)
#+END_SRC
*** TODO Find out what of the above is necessary given the disable-mouse mode below
Use the ~disable-mouse~ package by Steve Purcell available at
[https://github.com/purcell/disable-mouse]
#+BEGIN_SRC emacs-lisp
(require 'disable-mouse)
(global-disable-mouse-mode)
#+END_SRC
** Window behavior
Prevent compilation window eating up other windows
#+BEGIN_SRC emacs-lisp
(setq compilation-window-height 12
compilation-scroll-output nil)
#+END_SRC
Prevent any automatic splitting to split vertically
#+BEGIN_SRC emacs-lisp
(setq split-height-threshold 0)
#+END_SRC
** Scrolling
Scrolling setup
#+BEGIN_SRC emacs-lisp
(setq redisplay-dont-pause t
scroll-margin 3
scroll-step 1
scroll-conservatively 10000
scroll-preserve-screen-position 1)
#+END_SRC
*** TODO find out what this was actually meant to do
#+BEGIN_SRC emacs-lisp
(setq-default display-buffer-reuse-frames t)
#+END_SRC
** Mode-line
#+BEGIN_SRC emacs-lisp
(setq-default mode-line-modified '(:eval (if (buffer-modified-p) "" "·"))
;Still needs some improvements, does not report Readonly state
mode-line-remote '(:eval (let ((s (format-mode-line "%@")))
(cond
((equal s "-") " ") ((equal s "@") "@") (t s)))))
(defface mode-line-indicator
'((t nil))
"mode-line active indicator"
:group 'mode-line-faces)
(defface mode-line-inactive-indicator
'((t nil))
"Inactive variant of indicator"
:group 'mode-line-faces)
;; This has some issues when two buffers are shown in different windows
;; There are some solutions but let us see if this works first
(defun mode-line-update-face (window)
"Update the `mode-line' face in WINDOW to indicate whether the window is selected."
(with-current-buffer (window-buffer window)
(if (eq (current-buffer) (window-buffer (selected-window)))
(face-remap-reset-base 'mode-line-indicator)
(face-remap-set-base 'mode-line-indicator (face-all-attributes 'mode-line-inactive-indicator)))))
(add-hook 'buffer-list-update-hook (lambda () (walk-windows #'mode-line-update-face nil t)))
(defvar wilder-buffer-vc-mode-line
'("%b" (vc-mode (:propertize
;; Strip the backend name from the VC status information
(:eval (let* ((backend (downcase (symbol-name (vc-backend (buffer-file-name)))))
(branch (substring vc-mode (+ (length backend) 2)))
(s (substring vc-mode (+ (length backend) 1) (+ (length backend) 2)))
(status (cond ((equal s "-") "") ((equal s ":") "!") (t s))))
(concat "·" branch status)))
face magit-branch-local))))
(defvar wilder-position
'("%p · %I" ))
(put 'wilder-buffer-vc-mode-line 'risky-local-variable t)
(put 'wilder-position 'risky-local-variable t)
(defvar wilder/mode-line-modes
(let ((recursive-edit-help-echo "Recursive edit, type C-M-c to get out"))
(list (propertize "%[" 'help-echo recursive-edit-help-echo)
'("" mode-name)
'("" mode-line-process)
" "
'("" minor-mode-alist)
(propertize "%n" 'help-echo "mouse-2: Remove narrowing from buffer"
'mouse-face 'mode-line-highlight
'local-map (make-mode-line-mouse-map
'mouse-2 #'mode-line-widen))
(propertize "%]" 'help-echo recursive-edit-help-echo)
" "))
"Mode line construct for displaying major and minor modes.")
(put 'wilder/mode-line-modes 'risky-local-variable t)
(setq-default header-line-format nil);'("%e" ));wilder-buffer-vc-mode-line))
(setq mode-line-separator
'(:eval (let* ((len-left (length (format-mode-line mode-line-format-left)))
(len-right (length (format-mode-line mode-line-format-right)))
(len-separator (- (+ (window-width) 2 2 2) (+ len-left len-right))))
(format (format "%%%ds" len-separator) ""))))
(setq mode-line-format-left
'("%e"
mode-line-front-space
mode-line-front-space
mode-line-front-space
; mode-line-mule-info
mode-line-modified
mode-line-remote
mode-line-frame-identification
wilder-buffer-vc-mode-line
" "
wilder-position))
(setq mode-line-format-right
'((:propertize " " face mode-line-indicator)
wilder/mode-line-modes
mode-line-misc-info
" "))
(put 'mode-line-format-left 'risky-local-variable t)
(put 'mode-line-format-right 'risky-local-variable t)
(put 'mode-line-separator 'risky-local-variable t)
(setq-default mode-line-format
'("%e" mode-line-format-left
mode-line-separator
mode-line-format-right))
#+END_SRC
The following has been found in [[https://www.masteringemacs.org/article/hiding-replacing-modeline-strings][here]] to clean up the modeline
#+BEGIN_SRC emacs-lisp
(defvar mode-line-cleaner-alist
`((auto-complete-mode . " α")
(yas/minor-mode . " υ")
(paredit-mode . " π")
(eldoc-mode . "")
(abbrev-mode . "")
(auto-fill-function . "")
(disable-mouse-global-mode . "")
(auto-revert-mode . "")
(helm-mode . " η" )
(smart-tab-mode . "")
(subword-mode . "")
(outshine-mode . " o")
(outline-minor-mode . "")
(reftex-mode . "")
(flyspell-mode . "")
;; Major modes
(lisp-interaction-mode . "λ")
(hi-lock-mode . "")
(python-mode . "Py")
(emacs-lisp-mode . "EL")
(tex-mode . "χ")
(latex-mode . "χ")
(TeX-latex-mode . "χ")
(org-mode . "Ω")
(org-agenda-mode . "Ω:Agenda"))
"Alist for `clean-mode-line'.
When you add a new element to the alist, keep in mind that you
must pass the correct minor/major mode symbol and a string you
want to use in the modeline *in lieu of* the original.")
(defun clean-mode-line ()
(interactive)
(loop for cleaner in mode-line-cleaner-alist
do (let* ((mode (car cleaner))
(mode-str (cdr cleaner))
(old-mode-str (cdr (assq mode minor-mode-alist))))
(when old-mode-str
(setcar old-mode-str mode-str))
;; major mode
(when (eq mode major-mode)
(setq mode-name mode-str)))))
(add-hook 'after-change-major-mode-hook 'clean-mode-line)
#+END_SRC
** Coding system
Prefer the utf-8 coding system globally. This helps with the issue of
magit not correctly staging hunks containing utf-8 characters.
See [https://github.com/magit/magit/issues/32]
#+BEGIN_SRC emacs-lisp
(prefer-coding-system 'utf-8)
#+END_SRC
** Mark handling
No transient mark is more flexible
#+BEGIN_SRC emacs-lisp
(transient-mark-mode 0)
#+END_SRC
But of course we need to /see/ the mark
#+BEGIN_SRC emacs-lisp
(require 'visible-mark)
(visible-mark-mode t)
(global-visible-mark-mode t)
#+END_SRC
The following are some convenient bindings; notice that on my layout F13 and
F14 are obtained by tapping the left and right shift respectively
#+BEGIN_SRC emacs-lisp
(defun jump-to-mark ()
"Jumps to the local mark, respecting the `mark-ring' order.
This is the same as using \\[set-mark-command] with the prefix argument."
(interactive)
(set-mark-command 1))
(defun just-activate-mark ()
(interactive)
(activate-mark))
(global-set-key-alist
'(("<f13>" . set-mark-command)
("<f14>" . set-mark-command)
("<M-f13>" . jump-to-mark)
("<M-f14>" . jump-to-mark)
("<S-f13>" . just-activate-mark)
("<S-f14>" . just-activate-mark)))
#+END_SRC
** Global bindings
Remove some bindings that I find supremely annoying.
Additionally, unbind the ~C-x o~ binding to force me using ~ace-window~
Finally, unbind the ~C-SPC~ to mark the point, as I am using LR-shift
Note that I will use ~C-SPC~ as a hydra below to deal with parenthesis
#+BEGIN_SRC emacs-lisp
(mapcar
(lambda (ch)
(global-unset-key (kbd ch)))
'("C-z" "C-x f" "<M-f4>" "C-M-u" "C-M-d" "C-x o" "C-SPC"))
#+END_SRC
Change {up,down}-list
#+BEGIN_SRC emacs-lisp
(global-set-key (kbd "C-M-i") 'down-list) ;; -i stands for /in/
(global-set-key (kbd "C-M-o") 'up-list) ;; -o stands for /out/
#+END_SRC
Add some opinionated bindings
#+BEGIN_SRC emacs-lisp
(global-set-key-alist
'(("C-M-d" . kill-sexp)
("C-M-<backspace>" . backward-kill-sexp)
("C-x k" . kill-this-buffer)
("C-S-v" . scroll-down-command)
("C-M-u" . universal-argument)))
#+END_SRC
** Disable commands
Enable narrow commands
#+BEGIN_SRC emacs-lisp
(put 'narrow-to-region 'disabled nil)
(put 'LaTeX-narrow-to-environment 'disabled nil)
(put 'narrow-to-page 'disabled nil)
#+END_SRC
** Smart beginning-of-line
This is a relatively smart way to go back to the beginning of the line
#+BEGIN_SRC emacs-lisp
(defun smart-line-beginning ()
"Move point to the beginning of text on the current line; if that
is already the current position of point, then move it to the
beginning of the line."
(interactive)
(let ((pt (point)))
(beginning-of-line-text)
(when (eq pt (point))
(beginning-of-line))))
(global-set-key (kbd "C-a") 'smart-line-beginning)
#+END_SRC
** White-space
Trailing whitespace is evil; get rid of it
#+BEGIN_SRC emacs-lisp
(setq-default show-trailing-whitespace t)
(add-hook 'before-save-hook 'delete-trailing-whitespace)
#+END_SRC
Define what is whitespace during a search
#+BEGIN_SRC emacs-lisp
(setq search-whitespace-regexp "[ \t\r\n]+")
#+END_SRC
Tabs are evil; get rid of them
#+BEGIN_SRC emacs-lisp
(setq c-basic-offset 4)
(setq-default tab-width 4
indent-tabs-mode nil)
#+END_SRC
*** TODO Have a look at ws-trim.el
It is conf'ble to avoid removing whitespace from lines that were not
modified; sounds like a good idea for git
[ftp://ftp.lysator.liu.se/pub/emacs/ws-trim.el]
** Show matching parens
Use ~show-paren~ for paren-highlighting
#+BEGIN_SRC emacs-lisp
(show-paren-mode 1)
#+END_SRC
*** TODO find out if there are better options out there
** Load hydra
#+BEGIN_SRC emacs-lisp
(require 'hydra)
#+END_SRC
** Abbrevs
Set up abbrevs
#+BEGIN_SRC emacs-lisp
(setq-default abbrev-mode t)
(read-abbrev-file "~/.abbrev_defs")
(setq save-abbrevs t)
#+END_SRC
** Spellcheck
Use flyspell
#+BEGIN_SRC emacs-lisp
(require 'flyspell-lazy)
(flyspell-lazy-mode 1)
(add-hook 'text-mode-hook 'flyspell-mode)
(setq flyspell-use-meta-tab nil)
(defface flyspell-margin-incorrect
'((t nil))
"flyspell-margin-incorrect"
:group 'flyspell)
(setq flyspell-before-incorrect-word-string
(propertize "." 'display `((margin left-margin)
,(propertize "×" 'face 'flyspell-margin-incorrect))))
#+END_SRC
** Fringe treatment
*** TODO try linum-relative
#+BEGIN_SRC emacs-lisp
; (require 'linum-relative)
; (linum-relative-mode 1)
#+END_SRC
Add line numbers globally
#+BEGIN_SRC emacs-lisp
; (global-linum-mode 1)
#+END_SRC
Highlight also the linum in the fringe
#+BEGIN_SRC emacs-lisp
; (require 'hlinum)
; (hlinum-activate)
#+END_SRC
Add marker for current line in the margin (see
[https://github.com/kyanagi/fringe-current-line] and
[https://github.com/nschum/fringe-helper.el] for inspiration)
#+BEGIN_SRC emacs-lisp
(require 'margin-current-line)
(global-margin-current-line-mode 1)
#+END_SRC
** Turn on echo mode
Display unfinished commands in the echo area after the specified delay.
#+BEGIN_SRC emacs-lisp
(setq echo-keystrokes 0.10)
#+END_SRC
** Disable completion buffer
Remove the completion buffer as soon as we get out of the minibuffer
#+BEGIN_SRC emacs-lisp
(add-hook 'minibuffer-exit-hook
'(lambda ()
(let ((buffer "*Completions*"))
(and (get-buffer buffer)
(kill-buffer buffer))) ))
#+END_SRC
** Auto save on compile
#+BEGIN_SRC emacs-lisp
(setq compilation-ask-about-save nil)
#+END_SRC
** Idle-kill
#+BEGIN_SRC emacs-lisp
(defun kill-buffers-on-idle ()
"Kill buffers that have the appropriate property set."
(save-excursion
(save-window-excursion
(dolist (b (buffer-list))
(when (and (with-current-buffer b (boundp 'buffer-close-on-idle))
(with-current-buffer b buffer-close-on-idle))
(with-current-buffer b (message "Killed %s" buffer-file-name))
(pop-to-buffer-same-window b)
(kill-buffer))))))
(run-with-idle-timer 180 t 'kill-buffers-on-idle)
#+END_SRC
** Calendar
#+BEGIN_SRC emacs-lisp
(add-hook 'calendar-load-hook
(lambda ()
(calendar-set-date-style 'european)))
;; first day of the week is monday instead of sunday:
(setq calendar-week-start-day 1
calendar-location-name "Toronto, ON Canada"
calendar-latitude 43.7
calendar-longitude -79.4)
#+END_SRC
** Use local proxy
I need this to route bibretrieve requests through my local proxy,
that in turn routes requests to ~mathscinet~ through the University network
#+BEGIN_SRC emacs-lisp
;; Use system proxy
(setq url-proxy-services '(("http" . "127.0.0.1:8118")
("https" . "127.0.0.1:8118")))
#+END_SRC
** Indicator
Change cursor color to reflect different layers on the keyboard
This is the handler
#+BEGIN_SRC emacs-lisp
(defun xkbvleds-indicator-signal-handler (indicator on)
(if on
(cond ((string-equal indicator "Greek")
(set-face-background 'cursor "#2aa198"))
((string-equal indicator "Math")
(set-face-background 'cursor "#cb4b16")))
(set-face-background 'cursor "#919191")))
#+END_SRC
Connect the signal from xkbvleds to the handler
#+BEGIN_SRC emacs-lisp
(require 'dbus)
;; Register for the signal indicatorChanged coming from our service. It is
;; important that the =service= argument is =nil=, otherwise the registration
;; would stop once the process is respawned.
(dbus-register-signal
:session nil "/org/xkbvleds" "org.xkbvleds" "indicatorChanged"
'xkbvleds-indicator-signal-handler)
#+END_SRC
** Tarmak-ready
Set up all possible combinations of modifiers
#+BEGIN_SRC emacs-lisp
(defun concat-recursive (b &optional a)
(if b
(append (concat-recursive (cdr b) (concat a (car b)))
(concat-recursive (cdr b) a))
(when a (list a))))
(setq modifier-combo (concat-recursive '("C-" "M-" "s-" "H-")))
#+END_SRC
Then list the swapped keys
#+BEGIN_SRC emacs-lisp
(setq tarmak1-swaps '(("j" . "e")
("e" . "k")
("k" . "n")
("n" . "j")))
#+END_SRC
** Transmission
#+BEGIN_SRC emacs-lisp
(require 'transmission)
(setq transmission-host "192.168.0.40")
#+END_SRC
* Main major modes
** org-mode
*** Require
Require the ~org~ package; I also occasionally use org-pomodoro
#+BEGIN_SRC emacs-lisp
(with-eval-after-load "org"
(define-key org-src-mode-map (kbd "C-c C-c") 'org-edit-src-exit)
(define-key org-src-mode-map (kbd "C-c C-k") nil) ;this conflicts with my LaTeX bindings
(define-key org-src-mode-map (kbd "C-c C-`") 'org-edit-src-abort))
(require 'org)
(require 'org-pomodoro)
#+END_SRC
*** Hooks
Enable ~auto-fill-mode~ (see [[[https://www.gnu.org/software/emacs/manual/html_node/emacs/Auto-Fill.html][the manual]]]: honestly I do not see
where I would not want to use this feature). Also, disable ~truncate-lines~
#+BEGIN_SRC emacs-lisp
(add-hook 'org-mode-hook 'turn-on-auto-fill)
(setq org-starting-truncated nil)
#+END_SRC
*** Cosmetics
Change the default ellipsis ~...~ to the unicode ellipsis ~…~ *Does not work properly*
#+BEGIN_SRC emacs-lisp
; (setq org-ellipsis "…")
#+END_SRC
*** Ligatures
These require a patched ~hackminus~ font. Too bad it does not work
for some reason
#+BEGIN_SRC emacs-lisp
;; (defun delayed-org-prettify ()
;; (prettify-symbols-mode 0)
;; (run-with-idle-timer 0 nil
;; (lambda ()
;; (prettify-symbols-mode 1)
;; (add-to-list 'prettify-symbols-alist '("**" . (? (Br . Bl) ?)))
;; (add-to-list 'prettify-symbols-alist '("***" . (? (Br . Bl) ? (Br . Bl) ?)))
;; (add-to-list 'prettify-symbols-alist '("****" . (? (Br . Bl) ? (Br . Bl) ? (Br . Bl) ?))))))
;;(add-hook 'org-mode-hook 'delayed-org-prettify)
#+END_SRC
*** Links
Open links with external stuff
#+BEGIN_SRC emacs-lisp
(setq org-file-apps
'((auto-mode . emacs)
("\\.x?html?\\'" . "xdg-open %s")
("\\.pdf\\'" . "xdg-open \"%s\"")))
#+END_SRC
*** Agenda
Set the canonical binding for the agenda
#+BEGIN_SRC emacs-lisp
(global-set-key (kbd "C-c a") 'org-agenda)
#+END_SRC
Define agenda files: the main one is ~master.org~, but then I have
a bunch of them on orgzly
#+BEGIN_SRC emacs-lisp
(setq org-agenda-files
'("~/org/master.org"
"~/org/next.org"
"~/org/orgzly/work.org"
"~/org/orgzly/scheduled.org"
"~/org/orgzly/hack.org"
"~/org/orgzly/live.org"
"~/org/orgzly/library.org"
"~/org/orgzly/refile.org"))
#+END_SRC
Default to daily agenda
#+BEGIN_SRC emacs-lisp
(setq org-agenda-span 1)
#+END_SRC
Prevent headlines to be marked as DONE if some sub-headings are
still TODO.
#+BEGIN_SRC emacs-lisp
(setq org-enforce-todo-dependencies t)
#+END_SRC
Do not show scheduled or deadline'd stuff in the Global TODO list
#+BEGIN_SRC emacs-lisp
(setq org-agenda-todo-ignore-deadlines 'all
org-agenda-todo-ignore-scheduled 'all)
#+END_SRC
Do not show stuff marked with DONE even if they have a deadline
#+BEGIN_SRC emacs-lisp
(setq org-agenda-skip-deadline-if-done t)
#+END_SRC
Custom separator
#+BEGIN_SRC emacs-lisp
(setq org-agenda-block-separator ?─)
#+END_SRC
Turn on speed keys
#+BEGIN_SRC emacs-lisp
(setq org-use-speed-commands t)
#+END_SRC
Ideally I should tag some tasks as “break” tasks, which are
suitable to be taken care of during a pomodoro break. Such tasks
should be marked with tags ~:5m:~ and ~:20m:~ according to the
estimate on the time it would take to take care of them
#+BEGIN_SRC emacs-lisp
(setq org-agenda-custom-commands
'(
("a" "Main agenda"
((agenda "")
(todo "NEXT|ONGOING")
(tags-todo "hack")
(tags-todo "5m")
(todo "TODO")))
("h" "Agenda and Android tasks"
((agenda "")
(tags-todo "Android")))
("5" "Agenda and Break tasks"
((agenda "")
(tags-todo "5m")
(tags-todo "20m")))))
#+END_SRC
Custom agenda view
#+BEGIN_SRC emacs-lisp
(defun org-agenda-prepare (&optional name)
(let ((filter-alist (if org-agenda-persistent-filter
(with-current-buffer
(get-buffer-create org-agenda-buffer-name)
(list `(tag . ,org-agenda-tag-filter)
`(re . ,org-agenda-regexp-filter)
`(effort . ,org-agenda-effort-filter)
`(cat . ,org-agenda-category-filter))))))
(if (org-agenda-use-sticky-p)
(progn
(put 'org-agenda-tag-filter :preset-filter nil)
(put 'org-agenda-category-filter :preset-filter nil)
(put 'org-agenda-regexp-filter :preset-filter nil)
;; Popup existing buffer
(org-agenda-prepare-window (get-buffer org-agenda-buffer-name)
filter-alist)
(message "Sticky Agenda buffer, use `r' to refresh")
(or org-agenda-multi (org-agenda-fit-window-to-buffer))
(throw 'exit "Sticky Agenda buffer, use `r' to refresh"))
(setq org-todo-keywords-for-agenda nil)
(put 'org-agenda-tag-filter :preset-filter
org-agenda-tag-filter-preset)
(put 'org-agenda-category-filter :preset-filter
org-agenda-category-filter-preset)
(put 'org-agenda-regexp-filter :preset-filter
org-agenda-regexp-filter-preset)
(put 'org-agenda-effort-filter :preset-filter
org-agenda-effort-filter-preset)
(if org-agenda-multi
(progn
(setq buffer-read-only nil)
(goto-char (point-max))
(unless (or (bobp) org-agenda-compact-blocks
(not org-agenda-block-separator))
(insert "\n"
(if (stringp org-agenda-block-separator)
org-agenda-block-separator
(make-string (window-width) org-agenda-block-separator))
"\n\n"))
(narrow-to-region (point) (point-max)))
(setq org-done-keywords-for-agenda nil)
;; Setting any org variables that are in org-agenda-local-vars
;; list need to be done after the prepare call
(org-agenda-prepare-window
(get-buffer-create org-agenda-buffer-name) filter-alist)
(setq buffer-read-only nil)
(org-agenda-reset-markers)
(let ((inhibit-read-only t)) (erase-buffer))
(org-agenda-mode)
(setq org-refile-targets '((org-agenda-files :level . 1)))
(setq org-refile-use-outline-path 'file)
(setq org-agenda-buffer (current-buffer))
(setq org-agenda-contributing-files nil)
(setq org-agenda-columns-active nil)
(org-agenda-prepare-buffers (org-agenda-files nil 'ifmode))
(setq org-todo-keywords-for-agenda
(org-uniquify org-todo-keywords-for-agenda))
(setq org-done-keywords-for-agenda
(org-uniquify org-done-keywords-for-agenda))
(setq org-agenda-last-prefix-arg current-prefix-arg)
(setq org-agenda-this-buffer-name org-agenda-buffer-name)
(and name (not org-agenda-name)
(setq-local org-agenda-name name)))
(setq buffer-read-only nil))))
(add-hook 'org-agenda-mode-hook
(lambda () (setq truncate-lines t)))
#+END_SRC
*** Automate saving
This will take care of most of the other stuff
#+BEGIN_SRC emacs-lisp
(add-hook 'auto-save-hook 'org-save-all-org-buffers)
#+END_SRC
*** Reverting stuff from orgzly
#+BEGIN_SRC emacs-lisp
(defun org-revert-all-orgzly-buffers (&optional ALL)
"Revert all Org buffers that are sitting in orgzly
Prompt for confirmation when there are unsaved changes. Be sure
you know what you are doing before letting this function
overwrite your changes."
(interactive)
(message "Reverting Orgzly buffers…")
(save-excursion
(save-window-excursion
(dolist (b (buffer-list))
(when (and (with-current-buffer b (derived-mode-p 'org-mode))
(with-current-buffer b buffer-file-name)
(with-current-buffer b (string-match-p "orgzly" default-directory)))
(pop-to-buffer-same-window b)
(revert-buffer t 'no-confirm)))))
(org-agenda-redo-all))
(define-key org-agenda-mode-map (kbd "Z") 'org-revert-all-orgzly-buffers)
#+END_SRC
*** Capture
Set default keybinding
#+BEGIN_SRC emacs-lisp
(global-set-key (kbd "C-c c") 'org-capture)
#+END_SRC
This is my capture template: it needs to be revised as I really do not use
The Idea, journal and break entry
#+BEGIN_SRC emacs-lisp
(setq org-default-notes-file "~/org/master.org")
(setq org-capture-templates
'(("t" "TODO today" entry (file+headline "~/org/master.org" "Tasks")
"* TODO %?\n SCHEDULED: %t" :clock-in t :clock-resume t)
("n" "TODO next" entry (file+headline "~/org/master.org" "Tasks")
"* NEXT %?\n " :clock-in t :clock-resume t)
("T" "TODO" entry (file+headline "~/org/master.org" "Tasks")
"* TODO %?\n %a" :clock-in t :clock-resume t)
("i" "Idea" entry (file+headline "~/org/master.org" "Ideas")
"* IDEA %?\n %u" :clock-in t :clock-resume t )
("j" "Journal" entry (file+datetree "~/org/master.org")
"* %?\n%U\n" :clock-in t :clock-resume t)
("b" "Break" entry (file+datetree "~/org/master.org")
"* break %?\n" :clock-in t :clock-resume t)
("e" "Mail To" entry (file+headline "~/org/master.org" "E-mails")
"* DONE mailto:%?")
("r" "Reply to" entry (file+headline "~/org/master.org" "E-mails")
"* DONE mailto:%?")))
#+END_SRC
*** LaTeX export
#+BEGIN_SRC emacs-lisp
; (add-to-list 'org-latex-classes
; '("amsart" "\\documentclass[11pt]{amsart}"
; ("\\section{%s}" . "\\section*{%s}")
; ("\\subsection{%s}" . "\\subsection*{%s}")
; ("\\subsubsection{%s}" . "\\subsubsection*{%s}")
; ("\\paragraph{%s}" . "\\paragraph*{%s}")
; ("\\subparagraph{%s}" . "\\subparagraph*{%s}")))
#+END_SRC
*** Source blocks
Add template for a source block in a few selected languages; for
now I have
- emacs-lisp
- shell
. This is useful for writing the emacs init file in literate form,
or dotfiles for other code. Since Org 9.2, the behavior that I
grew accustomed to (e.g. ~<el TAB~) )is implemented by ~org-tempo~, so I need to require that as well.
#+BEGIN_SRC emacs-lisp
(mapcar (lambda (structure-template)
(add-to-list 'org-structure-template-alist
structure-template))
'(("el" . "src emacs-lisp")
("sh" . "src sh")))
(require 'org-tempo)
#+END_SRC
Fontify src blocks
#+BEGIN_SRC emacs-lisp
(setq org-src-fontify-natively t)
#+END_SRC
*** Lowercase org blocks
There is a new trend to use lowercase in the org block
definitions; this gist (taken from the [[https://scripter.co/org-keywords-lower-case/][Scripter blog]]) lowercases
all instances in the current buffer
#+begin_src emacs-lisp
(defun modi/lower-case-org-keywords ()
"Lower case Org keywords and block identifiers.
Example: \"#+TITLE\" -> \"#+title\"
\"#+BEGIN_EXAMPLE\" -> \"#+begin_example\"
Inspiration:
https://code.orgmode.org/bzg/org-mode/commit/13424336a6f30c50952d291e7a82906c1210daf0."
(interactive)
(save-excursion
(goto-char (point-min))
(let ((case-fold-search nil)
(count 0))
;; Match examples: "#+FOO bar", "#+FOO:", "=#+FOO=", "~#+FOO~",
;; "‘#+FOO’", "“#+FOO”", ",#+FOO bar",
;; "#+FOO_bar<eol>", "#+FOO<eol>".
(while (re-search-forward "\\(?1:#\\+[A-Z_]+\\(?:_[[:alpha:]]+\\)*\\)\\(?:[ :=~’”]\\|$\\)" nil :noerror)
(setq count (1+ count))
(replace-match (downcase (match-string-no-properties 1)) :fixedcase nil nil 1))
(message "Lower-cased %d matches" count))))
#+end_src
*** Clocking
#+BEGIN_SRC emacs-lisp
;; Separate drawers for clocking and logs
(setq org-drawers (quote ("PROPERTIES" "CLOCKBOOK")))
;; Save clock data and state changes and notes in the CLOCK drawer
(setq org-clock-into-drawer "CLOCKBOOK")
;; Sometimes I change tasks I'm clocking quickly - this removes clocked tasks with 0:00 duration
(setq org-clock-out-remove-zero-time-clocks t)
;; Clock out when moving task to a done state
(setq org-clock-out-when-done t)
(setq org-clock-persist 'history)
(setq org-duration-format 'h:mm)
(setq org-clock-clocktable-default-properties '(:maxlevel 2 :scope subtree))
(org-clock-persistence-insinuate)
#+END_SRC
*** Tangle to different files
This is some some super-clever stuff. See
[https://emacs.stackexchange.com/questions/39032/tangle-the-same-src-block-to-different-files]
#+BEGIN_SRC emacs-lisp
(defun org-babel-tangle-collect-blocks-handle-tangle-list (&optional language tangle-file)
"Can be used as :override advice for `org-babel-tangle-collect-blocks'.
Handles lists of :tangle files."
(let ((counter 0) last-heading-pos blocks)
(org-babel-map-src-blocks (buffer-file-name)
(let ((current-heading-pos
(org-with-wide-buffer
(org-with-limited-levels (outline-previous-heading)))))
(if (eq last-heading-pos current-heading-pos) (cl-incf counter)
(setq counter 1)
(setq last-heading-pos current-heading-pos)))
(unless (org-in-commented-heading-p)
(let* ((info (org-babel-get-src-block-info 'light))
(src-lang (nth 0 info))
(src-tfiles (cdr (assq :tangle (nth 2 info))))) ; Tobias: accept list for :tangle
(unless (consp src-tfiles) ; Tobias: unify handling of strings and lists for :tangle
(setq src-tfiles (list src-tfiles))) ; Tobias: unify handling
(dolist (src-tfile src-tfiles) ; Tobias: iterate over list
(unless (or (string= src-tfile "no")
(and tangle-file (not (equal tangle-file src-tfile)))
(and language (not (string= language src-lang))))
;; Add the spec for this block to blocks under its
;; language.
(let ((by-lang (assoc src-lang blocks))
(block (org-babel-tangle-single-block counter)))
(setcdr (assoc :tangle (nth 4 block)) src-tfile) ; Tobias:
(if by-lang (setcdr by-lang (cons block (cdr by-lang)))
(push (cons src-lang (list block)) blocks)))))))) ; Tobias: just ()
;; Ensure blocks are in the correct order.
(mapcar (lambda (b) (cons (car b) (nreverse (cdr b)))) blocks)))
(defun org-babel-tangle-single-block-handle-tangle-list (oldfun block-counter &optional only-this-block)
"Can be used as :around advice for `org-babel-tangle-single-block'.
If the :tangle header arg is a list of files. Handle all files"
(let* ((info (org-babel-get-src-block-info))
(params (nth 2 info))
(tfiles (cdr (assoc :tangle params))))
(if (null (and only-this-block (consp tfiles)))
(funcall oldfun block-counter only-this-block)
(cl-assert (listp tfiles) nil
":tangle only allows a tangle file name or a list of tangle file names")
(let ((ret (mapcar
(lambda (tfile)
(let (old-get-info)
(cl-letf* (((symbol-function 'old-get-info) (symbol-function 'org-babel-get-src-block-info))
((symbol-function 'org-babel-get-src-block-info)
`(lambda (&rest get-info-args)
(let* ((info (apply 'old-get-info get-info-args))
(params (nth 2 info))
(tfile-cons (assoc :tangle params)))
(setcdr tfile-cons ,tfile)
info))))
(funcall oldfun block-counter only-this-block))))
tfiles)))
(if only-this-block
(list (cons (cl-caaar ret) (mapcar #'cadar ret)))
ret)))))
(advice-add 'org-babel-tangle-collect-blocks :override #'org-babel-tangle-collect-blocks-handle-tangle-list)
(advice-add 'org-babel-tangle-single-block :around #'org-babel-tangle-single-block-handle-tangle-list)
#+END_SRC
*** Append tangle
#+BEGIN_SRC emacs-lisp
(defun org-babel-tangle-append (filename)
"Append source code block at point to its tangle file.
The command works like `org-babel-tangle' with prefix arg
but `delete-file' is ignored."
(interactive)
(cl-letf (((symbol-function 'delete-file) #'ignore))
(org-babel-tangle '(4) filename)))
#+END_SRC
*** Tangle file
This can be used to tangle one or more files to their output files [[https://gitlab.com/to1ne/literate-dotfiles/blob/master/elisp/tangle.el][
Source on gitlab]]
#+BEGIN_SRC emacs-lisp
(defun tangle-file(&rest files nokill)
"Tangle FILES or all files in the project."
(when (null files)
(setq files command-line-args-left))
(dolist (file files)
(with-current-buffer (find-file-noselect file)
(org-babel-tangle)
; (unless nokill (kill-buffer))
)))
#+END_SRC
*** Export file
This can be used to tangle one or more files to their output files [[https://gitlab.com/to1ne/literate-dotfiles/blob/master/elisp/tangle.el][
Source on gitlab]]
#+BEGIN_SRC emacs-lisp
(defun export-org-file-pdf(&rest files nokill)
"Export FILES or all files in the project."
(when (null files)
(setq files command-line-args-left))
(dolist (file files)
(with-current-buffer (find-file-noselect file)
(org-latex-export-to-pdf)
(kill-buffer))))
#+END_SRC
*** Crypto stuff
#+BEGIN_SRC emacs-lisp
(require 'org-crypt)
(org-crypt-use-before-save-magic)
(setq org-tags-exclude-from-inheritance (quote ("crypt")))
(setq org-crypt-key "C86A9E7675295C62")
#+END_SRC
*** ox-export
Load ox-hugo
#+BEGIN_SRC emacs-lisp
(with-eval-after-load 'ox
(require 'ox-hugo))
#+END_SRC
** elisp
*** Paredit
#+BEGIN_SRC emacs-lisp
(autoload 'enable-paredit-mode "paredit" "Turn on
pseudo-structural editing of Lisp code." t)
(add-hook 'emacs-lisp-mode-hook #'enable-paredit-mode)
(require 'hydra)
(require 'highlight-parentheses)
(defun hydra-paren/hl-paren-force-fix ()
;;; This is needed b/c hl-parent caches the point position and
;;; refuses to update if the point did not move
(let ((hl-paren-last-point -1))
(hl-paren-highlight)))
(defun hydra-paren/pre ()
(unless (boundp 'hydra-paren/hpm)
(highlight-parentheses-mode 1))
(setq hydra-paren/hpm t))
(defun hydra-paren/post ()
(highlight-parentheses-mode -1)
(makunbound 'hydra-paren/hpm))
(global-set-key
(kbd "C-SPC")
(defhydra hydra-paren
(:pre hydra-paren/pre :post hydra-paren/post)
"paren slurp and barf"
("l" (progn
(paredit-forward-slurp-sexp)
(hydra-paren/hl-paren-force-fix)) "slurp forward")
("j" (progn
(paredit-forward-barf-sexp)
(hydra-paren/hl-paren-force-fix)) "barf forward")
("s" (progn
(paredit-backward-slurp-sexp)
(hydra-paren/hl-paren-force-fix)) "slurp backward")
("f" (progn
(paredit-backward-barf-sexp)
(hydra-paren/hl-paren-force-fix)) "barf backward")))
#+END_SRC
*** Replace last sexp
I use this a lot to evaluate (e.g.) quick computations in files
#+BEGIN_SRC emacs-lisp
(defun replace-last-sexp ()
(interactive)
(let ((value (eval (preceding-sexp))))
(kill-sexp -1)
(insert (format "%S" value))))
(global-set-key (kbd "C-c C-x C-e") #'replace-last-sexp)
#+END_SRC
** qml
Load ~qml-mode~
#+BEGIN_SRC emacs-lisp
(autoload 'qml-mode "qml-mode.el" t)
(add-to-list 'auto-mode-alist '("\\.qml\\'" . qml-mode))
#+END_SRC
** C and C++
*** Hooks
#+BEGIN_SRC emacs-lisp
;; (require 'doxymacs)
(add-hook 'c-mode-hook
(lambda ()
(subword-mode)
(doxymacs-mode)
(define-key c-mode-map (kbd "C-c C-c") 'make)))
(add-hook 'c++-mode-hook
(lambda ()
(subword-mode)
(doxymacs-mode)
(define-key c++-mode-map (kbd "C-c C-c") 'make)))
#+END_SRC
** TODO split --- LaTeX
*** TODO Setup ~reftex~
#+BEGIN_SRC emacs-lisp
(with-eval-after-load "reftex"
(setq reftex-cite-format "~\\cite{%l}"
reftex-plug-into-AUCTeX '(t t nil t t)
reftex-insert-label-flags '(t t)
reftex-label-alist
'(("thm" ?t "thm:" "~\\ref{%s}" thm (regexp "theorems?"))
("lem" ?l "lem:" "~\\ref{%s}" lem (regexp "lemma{ta}?"))
("prop" ?p "prp:" "~\\ref{%s}" prp (regexp "propositions?"))
("cor" ?c "cor:" "~\\ref{%s}" cor (regexp "corollary"))
("def" ?d "def:" "~\\ref{%s}" cor (regexp "defintions?")))))
;;; advice the auctex function to replace the
;;; lighter with somthing softer
(with-eval-after-load "auctex"
(defun cleanup-TeX-mode (&optional mode)
"Advice for the base auctex MODE naming"
(setq mode-name (replace-regexp-in-string "LaTeX" "χ" mode-name t))
(setq mode-name (replace-regexp-in-string "/" "·" mode-name)))
(advice-add 'TeX-set-mode-name :after 'cleanup-TeX-mode))
#+END_SRC
*** Setup ~latex-mode~
#+BEGIN_SRC emacs-lisp
(eval-after-load 'latex
'(progn
(font-lock-add-keywords 'latex-mode
`((,(rx "$") 0 'font-latex-sedate-face t)) t)
(defface font-latex-special-comment-face '((t (:foreground "#2aa198"))) "Cyan")
(font-lock-add-keywords 'latex-mode '(("^% \\([^*].*\\)" 1 'font-latex-special-comment-face t)))
(define-key-alist LaTeX-mode-map
'(("M-S-SPC" . TeX-insert-braces)
("C-c C-v" . wilder/TeX-insert-reference)
("C-M-<return>" . wilder/TeX-insert-align-dwim)
;; unbind return - NOTE it is important to unbind
;; <return> and not RET. If we unbind RET then C-m won't work
;; either.
("<return>" . (lambda() (interactive) (insert "\\")))
("S-<return>" . (lambda() (interactive) (insert "|")))
("C-c C-." . LaTeX-mark-environment)
("C-c C-k" . (lambda (r-begin r-end)
(interactive "r")
(add-delimiter "_{" "}" r-begin r-end)))
("C-c C-i" . (lambda (r-begin r-end)
(interactive "r")
(add-delimiter "^{" "}" r-begin r-end)))
("M-|" . (lambda (r-begin r-end)
(interactive "r")
(add-delimiter "|" "|" r-begin r-end)))
("M-," . (lambda (r-begin r-end)
(interactive "r")
(add-delimiter ", " ", " r-begin r-end)))
("M-\"" . (lambda (r-begin r-end)
(interactive "r")
(add-delimiter "" "" r-begin r-end)))
;; This is the rationale: C-M-SPC starts inline math C-M-RET starts display math
("C-M-SPC" . (lambda (r-begin r-end) (interactive "r") (add-delimiter "$" "$" r-begin r-end)))
("C-c C-d" . wilder/TeX-insert-todonote)
("C-M-d" . kill-sexp)
("C-M-i" . down-list) ;; -i stands for /in/
("C-M-o" . up-list) ;; -o stands for /out/
("<f4>" . ( lambda() (interactive) (message "Use C-c C-c")))
("C-c C-c" . ( lambda() (interactive) (compile "/home/jacopods/scripts/latex-mk")) )
("~" . wilder/TeX-replace-tilde)
("C-o" . wilder/open-line-and-indent)
;; Force moves around to be more “semantic”
("C-v" . goto-next-comment-line)
("M-v" . goto-previous-comment-line)
("C-x n c" . narrow-between-comments)
("C-S-v" . backward-paragraph)))
(mapcar (lambda (ch)
(define-key LaTeX-mode-map (kbd ch) 'insert-char-with-padding))
'("=" "" ">" "<" "" "" "" "" "" "" "" "×" "" ""))
;; Move around commands in the Right Way™
(modify-syntax-entry ?\\ "w" LaTeX-mode-syntax-table)
;; add fancy quotes to the syntax table
(modify-syntax-entry ?“ "(”" LaTeX-mode-syntax-table)
(modify-syntax-entry ?” ")“" LaTeX-mode-syntax-table)
(setq subword-forward-regexp "\\W*\\(\\([\\\\[:upper:]]*\\W?\\)[[:lower:][:digit:]]*\\)")
(setq subword-backward-regexp "\\(\\(\\W\\|[[:lower:][:digit:]]\\)\\([\\\\[:upper:]]+\\W*\\)\\|\\W\\w+\\)")))
#+END_SRC
*** Require
Load auctex, reftex and set up related hooks
#+BEGIN_SRC emacs-lisp
(require 'tex-site)
(require 'reftex)
#+END_SRC
*** Set default TeX options
#+BEGIN_SRC emacs-lisp
(setq-default TeX-master nil)
(setq TeX-auto-save t
TeX-parse-self t
TeX-insert-braces nil)
#+END_SRC
*** Appearance
No fontification for sub and superscripts
#+BEGIN_SRC emacs-lisp
(setq font-latex-fontify-script nil)
#+END_SRC
Add unicode quotes to the quote-list
#+BEGIN_SRC emacs-lisp
; (defvar font-latex-quote-list '(("``" "''") ("“" "”") ("<<" ">>" french) ("«" "»" french)) ;
#+END_SRC
Redefine fold ellipsis
#+BEGIN_SRC emacs-lisp
(setq TeX-fold-ellipsis "")
#+END_SRC
*** Default labels
#+BEGIN_SRC emacs-lisp
(setq LaTeX-equation-label "e_"
LaTeX-section-label "s_"
LaTeX-figure-label "f_")
#+END_SRC
*** Spell checking help
Do not spell-check inside the following commands. See
[https://tex.stackexchange.com/questions/117204/skip-spelling-in-emacs-for-the-content-of-a-user-macro]
#+BEGIN_SRC emacs-lisp
(setq ispell-tex-skip-alists
(list
(append
(car ispell-tex-skip-alists) ;tell ispell to ignore content of this:
'(("\\\\eqref" ispell-tex-arg-end)
("\\\\cite" ispell-tex-arg-end)
("\\\\author" ispell-tex-arg-end)
("\\\\address" ispell-tex-arg-end)
("\\\\include" ispell-tex-arg-end)
))
(cadr ispell-tex-skip-alists)))
#+END_SRC
*** Specialty functions
This function adds a pair of delimiters or surrounds the active region
with the given delimiters.
TODO it breaks when there is no mark
#+BEGIN_SRC emacs-lisp
(defun add-delimiter (delim-begin delim-end r-begin r-end)
"Add the pair of delimiters given in delim at the ends of the
region if it is activated"
(interactive "cBegin delimiter: \ncEnd delimiter: \nr")
(if (region-active-p)
(progn
(save-excursion
(goto-char r-end)
(insert delim-end)
(goto-char r-begin)
(insert delim-begin)))
(progn
(save-excursion
(insert delim-end))
(insert delim-begin))))
#+END_SRC
The following re-implements =TeX-insert-braces= to work with
negative argument
#+BEGIN_SRC emacs-lisp
(defun TeX-insert-braces (arg)
"Make a pair of braces around next ARG sexps and leave point inside.
No argument is equivalent to zero: just insert braces and leave point
between.
If there is an active region, ARG will be ignored, braces will be
inserted around the region, and point will be left after the
closing brace."
(interactive "P")
(if (TeX-active-mark)
(progn
(if (< (point) (mark))
(exchange-point-and-mark))
(insert TeX-grcl)
(save-excursion
(goto-char (mark))
(insert TeX-grop)))
(if (and arg (< arg 0))
(progn
(save-excursion
(backward-sexp (prefix-numeric-value (- 0 arg)))
(insert TeX-grop))
(insert TeX-grcl))
(insert TeX-grop)
(save-excursion
(if arg (forward-sexp (prefix-numeric-value arg)))
(insert TeX-grcl)))))
(defun TeX-back-insert-braces (arg)
(interactive "P")
(if arg (TeX-insert-braces (- 0 arg))
(insert TeX-grcl)))
#+END_SRC
This is a helper for [[https://www.gnu.org/software/emacs/manual/html_node/emacs/Dynamic-Abbrevs.html][Dynamic abbrev expansion]]
#+BEGIN_SRC emacs-lisp
(defun dabbrev-expand-helper ()
(interactive)
(call-interactively 'dabbrev-expand))
#+END_SRC
This inserts a char adding some whitespace padding whenever necessary
#+BEGIN_SRC emacs-lisp
(defun insert-char-with-padding (arg)
(interactive "*P")
(unless (string-match (string (preceding-char)) " \&")
(insert " "))
(self-insert-command (prefix-numeric-value arg))
(unless (char-equal (following-char) ?\s)
(insert " "))) ;; decide what to do with the point
#+END_SRC
This function opens a line and indents it
#+BEGIN_SRC emacs-lisp
(defun wilder/open-line-and-indent (arg)
"This function opens a line using (open-line) and indents it"
(interactive "p")
(open-line arg)
(save-excursion (forward-char arg) (unless (eolp) (indent-according-to-mode))))
#+END_SRC
This inserts a plain reference (or a reference to an equation with
prefix arg)
#+BEGIN_SRC emacs-lisp
(defun wilder/TeX-insert-reference (arg)
(interactive "P")
(insert "~")
(if arg (TeX-insert-macro "eqref")
(TeX-insert-macro "ref")))
#+END_SRC
This inserts a citation
#+BEGIN_SRC emacs-lisp
(defun wilder/TeX-insert-cite (arg)
(interactive "P")
(insert "~")
(TeX-insert-macro "cite"))
#+END_SRC
This inserts an ~align~ environment (or an ~align*~ with prefix arg)
#+BEGIN_SRC emacs-lisp
(defun wilder/TeX-insert-align (arg)
(interactive "P")
(if arg
(LaTeX-insert-environment "align")
(LaTeX-insert-environment "align*"))
(indent-according-to-mode))
(defun wilder/TeX-insert-align-dwim (arg)
(interactive "P")
(if (texmathp)
(let ((why (car texmathp-why)))
(cond ((string-prefix-p "$" why) (wilder/TeX-promote-inline-math arg))
((string-equal "equation*" why) (LaTeX-modify-environment "align*"))
((string-equal "equation" why) (LaTeX-modify-environment "align"))
((string-equal "align*" why) (when arg (LaTeX-modify-environment "align")))))
(wilder/TeX-insert-align arg)))
#+END_SRC
This replaces horizontal space with a tilde
#+BEGIN_SRC emacs-lisp
(defun wilder/TeX-replace-tilde (arg)
(interactive "P")
(delete-horizontal-space)
(insert "~"))
#+END_SRC
Insert a todonote at point or wrap the region in a todonote.
#+BEGIN_SRC emacs-lisp
(defun wilder/TeX-insert-todonote (arg r-begin r-end)
(interactive "P\nr")
(if arg
(add-delimiter "{\\todo[inline]{" "}}" r-begin r-end)
(add-delimiter "{\\todo{" "}}" r-begin r-end)))
#+END_SRC
Promote inline math to an align
#+BEGIN_SRC emacs-lisp
(defun wilder/char-punctuation-p (ch)
"returns t if the char is a punctuation"
(interactive)
(string-match (string ch) ".,:;"))
(defun wilder/TeX-promote-inline-math (arg)
(interactive "P")
(when (and (texmathp) (string-prefix-p "$" (car texmathp-why)))
(let* ((delim (car texmathp-why))
(pos (cdr texmathp-why))
(n (length delim)))
(goto-char pos)
(push-mark)
(delete-char n)
(search-forward delim)
(delete-backward-char n)
;; include punctuations in the align
(when (wilder/char-punctuation-p (char-after)) (forward-char))
(activate-mark)
(wilder/TeX-insert-align arg)
(pop-mark)
(pop-mark))))
#+END_SRC
Shadow the AucTeX version of this function
#+BEGIN_SRC emacs-lisp
(defun LaTeX-insert-environment (environment &optional extra)
"Insert LaTeX ENVIRONMENT with optional argument EXTRA."
(let ((active-mark (and (TeX-active-mark) (not (eq (mark) (point)))))
prefix content-start env-start env-end)
(when (and active-mark (< (mark) (point))) (exchange-point-and-mark))
;; Compute the prefix.
(when (and LaTeX-insert-into-comments (TeX-in-commented-line))
(save-excursion
(beginning-of-line)
(looking-at
(concat "^\\([ \t]*" TeX-comment-start-regexp "+\\)+[ \t]*"))
(setq prefix (match-string 0))))
;; What to do with the line containing point.
(cond (;; if the line contains only whitespace, delete them
(save-excursion (beginning-of-line)
(looking-at (concat prefix "[ \t]*$")))
(delete-region (match-beginning 0) (match-end 0)))
;; otherwise, something is written on the line. We can be
;; at the beginning of the text
((TeX-looking-at-backward (concat "^" prefix "[ \t]*")
(line-beginning-position))
;;this morally opens a new line
(beginning-of-line)
(newline)
(beginning-of-line 0))
((bolp)
(delete-horizontal-space)
(newline)
(beginning-of-line 0))
((looking-at "[ \t]*$")
(delete-horizontal-space)
(newline)
(when prefix (insert prefix))
(beginning-of-line))
(t
(delete-horizontal-space)
(newline 2)
(when prefix (insert prefix))
(beginning-of-line 0)))
;; What to do with the line containing mark.
(when active-mark
(save-excursion
(goto-char (mark))
(cond ((save-excursion (beginning-of-line)
(or (looking-at (concat prefix "[ \t]*$"))
(looking-at "[ \t]*$")))
(delete-region (match-beginning 0) (match-end 0)))
((TeX-looking-at-backward (concat "^" prefix "[ \t]*")
(line-beginning-position))
(beginning-of-line)
(newline)
(beginning-of-line 0))
((looking-at "[ \t]*$")
(delete-horizontal-space)
(insert-before-markers "\n")
;(newline)
(when prefix (insert prefix)))
(t
(delete-horizontal-space)
(insert-before-markers "\n")
(newline)
(when prefix (insert prefix))))))
;; Now insert the environment.
(when prefix (insert prefix))
(setq env-start (point))
(insert TeX-esc "begin" TeX-grop environment TeX-grcl)
(indent-according-to-mode)
(when extra (insert extra))
(setq content-start (line-beginning-position 2))
(unless active-mark
(newline)
(when prefix (insert prefix))
(newline))
(when active-mark (goto-char (mark)))
(when prefix (insert prefix))
(insert TeX-esc "end" TeX-grop environment TeX-grcl)
(end-of-line 0)
(if active-mark
(progn
(or (assoc environment LaTeX-indent-environment-list)
(if auto-fill-function
;; Fill the region only when `auto-fill-mode' is active.
(LaTeX-fill-region content-start (line-beginning-position 2))))
(set-mark content-start))
(indent-according-to-mode))
(save-excursion (beginning-of-line 2) (indent-according-to-mode))
(TeX-math-input-method-off)
(setq env-end (save-excursion
(search-forward
(concat TeX-esc "end" TeX-grop
environment TeX-grcl))
(match-beginning 0)))
(run-hook-with-args 'LaTeX-after-insert-env-hooks
environment env-start env-end)))
#+END_SRC
*** Patch auctex
I don't particularly like the way that the prefix arguments works
with font selection. The function below patches the annoying
behavior, by defaulting to the default behavior if the prefix
argument is 0
#+BEGIN_SRC emacs-lisp
(defun wilder/TeX-font (replace what)
"Insert template for font change command.
If REPLACE is not nil, replace current font. WHAT determines the font
to use, as specified by `TeX-font-list'."
(interactive "*P\nc")
(TeX-update-style)
(let* ((entry (assoc what TeX-font-list))
(in-math (texmathp))
(before (nth 1 entry))
(after (nth 2 entry)))
(setq replace (or replace (eq t (nth 3 entry)) (eq t (nth 5 entry))))
(if (and in-math (stringp (nth 3 entry)))
(setq before (nth 3 entry)
after (nth 4 entry)))
(setq arg (prefix-numeric-value replace))
(cond
((null entry)
(let ((help (concat
"Font list: "
"KEY TEXTFONT MATHFONT\n\n"
(mapconcat 'TeX-describe-font-entry
TeX-font-list "\n"))))
(with-output-to-temp-buffer "*Help*"
(set-buffer "*Help*")
(insert help))))
((and replace (eq 0 arg))
(funcall TeX-font-replace-function before after))
((and replace (< arg 0) )
(progn
(save-excursion
(backward-sexp (- 0 arg))
(insert before))
(insert after)))
((and replace (> arg 0))
(insert before)
(save-excursion
(forward-sexp arg)
(insert after)))
((TeX-active-mark)
(save-excursion
(cond ((> (mark) (point))
(insert before)
(goto-char (mark))
(insert after))
(t
(insert after)
(goto-char (mark))
(insert before)))))
(t
(insert before)
(save-excursion
(insert after))))))
(advice-add 'TeX-font :override #'wilder/TeX-font)
#+END_SRC
*** The hook
#+BEGIN_SRC emacs-lisp
(add-hook 'LaTeX-mode-hook
(lambda ()
(turn-on-reftex)
(setq comment-column 0)
(setq prettify-symbols-alist nil)
(add-to-list 'prettify-symbols-alist '("" . (? (Br . Bl) ? (Br . Bl) ?)))
(turn-on-auto-fill)
(subword-mode)
(TeX-fold-mode 1)
(outshine-mode)))
#+END_SRC
*** Load compilation filters
#+BEGIN_SRC emacs-lisp
(load "latex-compile-filters.el")
#+END_SRC
*** Load ~bibretrieve~
#+BEGIN_SRC emacs-lisp
(byte-recompile-directory "~/.emacs.d/bibretrieve" 0)
(load "bibretrieve")
(setq bibretrieve-backends '(("msn" . 10)))
(require 'biblio)
#+END_SRC
** TODO KDE integration
*** TODO cleanup and split
These functions connects to dbus to find out the current activity
id and name
#+BEGIN_SRC emacs-lisp
(defun kde-current-activity ()
"Returns the current KDE activity"
(substring (shell-command-to-string "qdbus org.kde.ActivityManager /ActivityManager/Activities org.kde.ActivityManager.Activities.CurrentActivity") 0 -1)
)
(defun kde-current-activity-name ()
"Returns the name of the current KDE activity"
(substring (shell-command-to-string (concat "qdbus org.kde.ActivityManager /ActivityManager/Activities org.kde.ActivityManager.Activities.ActivityName " (kde-current-activity))) 0 -1))
#+END_SRC
#+BEGIN_SRC emacs-lisp
(defun X-window-id-belongs-to-activity (window-id activity)
(= (shell-command (concat "xprop -id " window-id " | grep _KDE_NET_WM_ACTIVITIES | grep " activity ">/dev/null")) 0)
)
(defun select-frame-on-activity (activity)
(setq framelist (frame-list))
(setq done nil)
(while (and framelist (not done))
(setq cur (car framelist))
(setq cur-id (cdr (assq 'window-id (frame-parameters cur))))
(if cur-id (if (X-window-id-belongs-to-activity cur-id activity) (progn;
(setq done 't) (select-frame cur)) ))
(setq framelist (cdr framelist)))
done
)
(defun select-X-frame ()
(setq framelist (frame-list))
(setq done nil)
(while (and framelist (not done))
(setq cur (car framelist))
(setq cur-id (cdr (assq 'window-id (frame-parameters cur))))
(if cur-id (progn;
(setq done 't) (raise-frame cur)))
(setq framelist (cdr framelist)))
done
)
#+END_SRC
This function is used to raise the frame associated to the current
activity
*** TODO These entries should be added to the subtree once it is split
#+BEGIN_SRC emacs-lisp
(defun select-frame-on-current-activity ()
(select-frame-on-activity (kde-current-activity)))
#+END_SRC
I prefer to keep one server for each KDE activity, so
set the server name to be the name of the current activity
#+BEGIN_SRC emacs-lisp
; (setq server-name (kde-current-activity-name))
#+END_SRC
*** Journal
Setup ~org-journal~
#+BEGIN_SRC emacs-lisp
(require 'org-journal)
(setq org-journal-dir "~/org/journal"
org-journal-file-type 'yearly
org-journal-file-format "%Y"
org-journal-encrypt-journal t)
#+END_SRC
* Specialties
** beacon =beacon= is a package that helps finding the point when switching
buffers. I like the idea but the aesthetics is a bit baroque. I
should do the same with =flash-hline=
** flash-hline
This function is defined to help in training with new keybindings. It
acts as a visual bell which flashes the current line. It is (arbitrarily)
bound to F15 which is supposed to be triggered by some “illegal” key hit
#+BEGIN_SRC emacs-lisp
(defun flash-hline ()
"Flash the current line to emph some mistake"
(interactive)
(let ((fg (face-foreground 'default))
(bg (face-background 'hl-line)))
(set-face-background 'hl-line fg)
(run-with-timer
0.1 nil (lambda ()
(set-face-background 'hl-line "#303030") ))))
(global-set-key (kbd "<f15>") 'flash-hline)
#+END_SRC
** unfill-paragraph
This is authored by Stefan Monnier <foo at acm.org>. It is the opposite of
fill-paragraph
#+BEGIN_SRC emacs-lisp
(defun unfill-paragraph (&optional region)
"Takes a multi-line paragraph and makes it into a single line of text."
(interactive (progn (barf-if-buffer-read-only) '(t)))
(let ((fill-column (point-max))
;; This would override `fill-column' if it's an integer.
(emacs-lisp-docstring-fill-column t))
(fill-paragraph nil region)))
#+END_SRC
** kill-word
dwim manage space after kill-word. This has been morally pasted from
[[https://www.reddit.com/r/emacs/comments/3nlws0/automanage_spaces_post_word_kills/][this reddit post]]. The original version does not allow for double
spaces after a period.
#+BEGIN_SRC emacs-lisp
(defun modi/just-one-space-post-kill-word (&rest _)
"Function to manage white space after `kill-word' operations.
1. If point is at the beginning of the line after possibly some white space,
remove that white space and re-indent that line.
2. If there is space before or after the point, ensure that there is only
one white space around the point.
3. Otherwise, do nothing.
During the whole operation do not change the point position with respect to the
surrounding white space.
abc| def ghi <-- point on the left of white space after 'abc'
abc| ghi <-- point still before white space after calling this function
abc |def ghi <-- point on the right of white space before 'def'
abc |ghi <-- point still after white space after calling this function."
(save-excursion ; maintain the initial position of the pt with respect to space
(cond ((looking-back "^ *") ; remove extra space at beginning of line
(just-one-space 0)
(indent-according-to-mode))
((looking-back "\\. *")
(just-one-space 2))
((or (looking-at " ")
(looking-back " ")) ; adjust space only if it exists
(just-one-space 1))
(t ; do nothing otherwise, includes case where the point is at EOL
))))
;; Delete extra horizontal white space after `kill-word' and `backward-kill-word'
(advice-add 'kill-word :after #'modi/just-one-space-post-kill-word)
#+END_SRC
#+RESULTS:
** word-count
Add word count in modeline; useful to prepare those pesky grant
applications
#+BEGIN_SRC emacs-lisp
(require 'word-count)
#+END_SRC
** gist
Use [[https://github.com/defunkt/gist.el][gist.el]]
#+BEGIN_SRC emacs-lisp
(require 'gist)
#+END_SRC
* Main packages
** Magit
#+BEGIN_SRC emacs-lisp
(require 'magit)
(global-set-key (kbd "C-x C-g") 'magit-status)
(magit-add-section-hook 'magit-status-sections-hook
#'magit-insert-modules-overview
#'magit-insert-unpushed-to-pushremote
:append)
(magit-add-section-hook 'magit-status-sections-hook
#'magit-insert-untracked-files
#'magit-insert-modules-overview
:append)
#+END_SRC
*** magit-todos
#+BEGIN_SRC emacs-lisp
(require 'magit-todos)
#+END_SRC
** smart-tab
This package is a gem: it allows to make tab work dwim
#+BEGIN_SRC emacs-lisp
(require 'smart-tab)
(global-smart-tab-mode 1)
#+END_SRC
** Outshine
#+BEGIN_SRC emacs-lisp
(defvar outline-minor-mode-prefix "\M-#")
(setq outshine-use-speed-commands t)
(with-eval-after-load 'outshine
(define-key outshine-mode-map (kbd "C-M-i") nil))
(add-hook 'sh-mode-hook 'outshine-mode)
(require 'outshine)
(require 'outorg)
#+END_SRC
Cook up some extra narrowing function
#+BEGIN_SRC emacs-lisp
(defun goto-next-comment-line ()
(interactive)
(re-search-forward "^\\S<" nil 1)
(re-search-forward "^\\s<" nil 1)
(beginning-of-line)
)
(defun goto-previous-comment-line ()
(interactive)
(re-search-backward "^\\s<" nil 1 )
(re-search-backward "^\\S<" nil 1 )
(beginning-of-line)
(unless (bobp) (next-line))
)
(defun narrow-between-comments ()
(interactive)
(save-excursion
(next-line)
(goto-previous-comment-line)
(setq beginning (point)))
(save-excursion
(goto-next-comment-line)
(unless (bobp) (previous-line) (end-of-line))
(setq ending (point)))
(narrow-to-region beginning ending))
#+END_SRC
** helm
#+BEGIN_SRC emacs-lisp
(require 'helm-config)
(helm-mode 1)
(defun fix-helm-margins ()
(setq helm-left-margin-width left-margin-width))
(global-set-key-alist
'(("M-x" . helm-M-x)
("C-x C-f" . helm-find-files)
("C-x b" . helm-mini)
("C-x C-b" . helm-mini)
("M-y" . helm-show-kill-ring)))
(define-key helm-map (kbd "C-h") nil)
(define-key helm-find-files-map (kbd "C-h") nil)
(define-key helm-find-files-map (kbd "C-<backspace>") nil)
(helm-define-key-with-subkeys helm-find-files-map (kbd "DEL") ?\d 'helm-ff-delete-char-backward
'(([C-c DEL] . helm-ff-run-toggle-auto-update))
nil 'helm-ff-delete-char-backward--exit-fn)
(add-hook 'helm-after-initialize-hook 'fix-helm-margins)
#+END_SRC
** multiple-cursors
#+BEGIN_SRC emacs-lisp
(require 'multiple-cursors)
(define-key mc/keymap (kbd "<return>") nil)
(global-set-key-alist
'(("C->" . mc/mark-next-like-this)
("C-<" . mc/mark-previous-like-this)
("C-c C-<" . mc/mark-all-like-this)
("C-c C-#" . mc/insert-numbers)
("C-c C-\\" . mc/mark-all-dwim)
("C-c <f13>" . mc/mark-pop)
("C-c <f14>" . mc/mark-pop)))
#+END_SRC
** =avy= and =avy-zap=
These packages allow fast navigation and zapping
#+BEGIN_SRC emacs-lisp
(require 'avy-zap)
(avy-setup-default)
(global-set-key-alist
'(("C-c C-j" . avy-resume)
("M-z" . avy-zap-up-to-char-dwim)
("M-Z" . avy-zap-to-char-dwim)
("C-c SPC" . avy-goto-word-or-subword-1)
("M-s" . avy-goto-word-or-subword-1)
("M-g M-g" . avy-goto-line)
("M-g g" . avy-goto-line)))
(require 'ace-window)
(global-set-key (kbd "M-o") 'ace-window)
(setq aw-keys '(?f ?j ?d ?k ?s ?l ?a ?g ?h)
aw-scope 'frame
aw-ignore-current t)
(require 'ace-link)
; (defalias 'avy-process 'avy--process)
(ace-link-setup-default)
(setq avy-styles-alist nil
avy-background t)
; (add-to-list 'avy-styles-alist '(ace-link-org-agenda . at-full))
; (add-to-list 'avy-styles-alist '(ace-link-org . at-full))
(define-key org-mode-map (kbd "C-c M-o") 'ace-link-org)
(define-key org-agenda-mode-map (kbd "C-c M-o") 'ace-link-org)
#+END_SRC
** expand-region
This is an excellent package, although I do not use it that much
I should find a better binding
#+BEGIN_SRC emacs-lisp
(require 'expand-region)
(global-set-key (kbd "C-=") 'er/expand-region)
#+END_SRC
** ERC
Enable ~erc dcc~ files transfer
#+BEGIN_SRC emacs-lisp
(require 'erc-dcc)
#+END_SRC
** vterm
#+BEGIN_SRC emacs-lisp
(require 'vterm)
#+END_SRC
** TODO Phase out Package.el
Load package.el
#+BEGIN_SRC emacs-lisp
(require 'package)
(add-to-list 'package-archives
'("melpa-stable" . "http://stable.melpa.org/packages/") t)
#+END_SRC
* Tidy-up
** Save emacs-session files in appropriate directory
Save session files to the ~sessions~ directory so that they do not litter
the ~.emacs.d~ base directory.
#+BEGIN_SRC emacs-lisp
(defun emacs-session-filename (session-id)
"Construct a filename to save the session in based on SESSION-ID.
If the directory ~/.emacs.d exists, we make a filename in there, otherwise
a file in the home directory."
(let ((basename (concat "sessions/session." session-id))
(emacs-dir user-emacs-directory))
(expand-file-name (if (file-directory-p emacs-dir)
(concat emacs-dir basename)
(concat "~/.emacs-" basename)))))
#+END_SRC
* Finale
** Fixup faces
This is really a workaround as I do not like either bold or italic.
It needs to be at the end of the file since it sets the face for
packages that have loaded in the meantime; yet it does not work
perfectly as some packages are still to be loaded (most notably ~magit~)
#+BEGIN_SRC emacs-lisp
;; (set-face-font 'default "-xos4-hackminus-medium-r-normal--20-200-72-72-c-100-ISO10646-1")
(set-face-bold 'bold nil)
(wilder/fixup-faces)
(with-eval-after-load "info" (wilder/fixup-faces) nil)
(with-eval-after-load "vterm" (wilder/fixup-faces) nil)
#+END_SRC
** Start server
#+BEGIN_SRC emacs-lisp
; (server-start)
#+END_SRC