From 85fe9b1ab390c86e86be24173844b5e6853f60da Mon Sep 17 00:00:00 2001 From: Tom Willemse Date: Wed, 23 Sep 2015 14:24:02 +0200 Subject: [PATCH] Start cleaning up basic structure --- emacs/.emacs.d/init.org | 851 ++++++++++++++++++++-------------------- 1 file changed, 436 insertions(+), 415 deletions(-) diff --git a/emacs/.emacs.d/init.org b/emacs/.emacs.d/init.org index f8b213d..7ac205c 100644 --- a/emacs/.emacs.d/init.org +++ b/emacs/.emacs.d/init.org @@ -1,6 +1,6 @@ #+TITLE: Emacs init #+PROPERTY: tangle init2.el -#+STARTUP: showall +#+STARTUP: content #+OPTIONS: author:nil num:nil toc:nil #+MACRO: key @@html:$1@@@@ascii:`$1'@@ #+HTML_HEAD: @@ -122,79 +122,51 @@ (cask-initialize)) #+END_SRC -* Some general-purpose functions and macros +** Some helper functions - A configuration as big as mine is bound to have some functions and - macros that are used in many places. + Certain functions make life a lot easier when configuring Emacs. + These don't generally belong to any one specific customization, but + make things look a lot prettier. -** Turn off +*** Optimized ~with-eval-after-load~ - This macro creates a function that will turn off a minor mode that - passed to it. + First offered [[http://www.lunaryorn.com/2013/05/01/byte-compiling-eval-after-load.html][here]] and then later updated [[http://www.lunaryorn.com/2013/06/25/introducing-with-eval-after-load.html][here]] (when + ~with-eval-after-load~ was added). Makes for very nice on-demand + settings loading. + + #+BEGIN_SRC emacs-lisp + ;; http://www.lunaryorn.com/2013/06/25/introducing-with-eval-after-load/ + (defmacro stante-after (feature &rest forms) + "After FEATURE is loaded, evaluate FORMS. + + FEATURE may be an unquoted feature symbol or a file name, see + `eval-after-load'." + (declare (indent 1) (debug t)) + `(,(if (or (not byte-compile-current-file) + (if (symbolp feature) + (require feature nil :noerror) + (load feature :no-message :no-error))) + `progn + (message "stante-after: cannot find %s" feature) + 'with-no-warnings) + (with-eval-after-load ',feature ,@forms))) + #+END_SRC + +* General customization + + These customizations don't belong with any specific mode. + +** Set some personal information + + This information is used by some emacs commands and modules to make + your life easier. #+BEGIN_SRC emacs-lisp - (defmacro turn-off (func) - "Create a function that will turn off FUNC when called." - `(lambda () (eval (,func -1)))) + (setq user-full-name "Tom Willemse" + user-mail-address "tom@ryuslash.org") #+END_SRC -** Change setting - - Sometimes a mode just needs to change a certain setting to a - specific value. - - #+BEGIN_SRC emacs-lisp - (defmacro change-settings (&rest settings) - "Create a function that changes the value of NAME to VALUE." - `(lambda () (setq ,@settings))) - #+END_SRC - -** Whitespace only with tabs - - In some modes I want to see the tabs in a buffer. Though I don't - want to be overwhelmed by seeing all spaces and line endings. - - #+BEGIN_SRC emacs-lisp - (defvar whitespace-style) - - (defun oni:whitespace-only-tabs () - (setq-local whitespace-style '(face tabs)) - (whitespace-mode)) - #+END_SRC - -** Eval after init - - Some things can only really work after all other initialization - functions have completed. For example, any functions that require - any ELPA packages to be loaded, unless you want to load it in your - init manually (and have it loaded again later on after your config - has run). - - #+BEGIN_SRC emacs-lisp - (defmacro oni:eval-after-init (&rest body) - "Defer execution of BODY until after Emacs init." - (declare (indent 0)) - `(add-hook 'emacs-startup-hook #'(lambda () ,@body))) - #+END_SRC - -* Set some personal information - - This information is used by some emacs commands and modules to make - your life easier. - - #+BEGIN_SRC emacs-lisp - (setq user-full-name "Tom Willemse" - user-mail-address "tom@ryuslash.org") - #+END_SRC - -* Clean up some UI elements - - Some elements are only really useful if you use the mouse. Which I - don't, not if I can help it. Only when browsing the web or using the - odd graphical application do I touch the mouse, and even then as - little as I can. - -** Menu bar +** Turn-off menu bar The menu bar is one of the UI elements which work best with mouses. Sure you can change your toolkit's key bindings to allow you to @@ -206,7 +178,7 @@ (menu-bar-mode -1) #+END_SRC -** Tool bar +** Turn-off tool bar The toolbar is another such thing, and it takes up quite a bit more space too. Icons can look pretty cool, but in the end if you're not @@ -217,7 +189,7 @@ (tool-bar-mode -1) #+END_SRC -** Blinking cursor +** Turn-off blinking cursor I suppose a blinking cursor doesn't get lost very easily. But on the other hand, it can induce quite a few more headaches. @@ -230,17 +202,17 @@ (blink-cursor-mode -1) #+END_SRC -** Line numbers +** Turn-off line numbers - As I'm currently using svg-mode-line-themes[fn:2] for my ~mode-line~ I - don't need to show these. Also I didn't really use them much, I + As I'm currently using svg-mode-line-themes[fn:2] for my ~mode-line~ + I don't need to show these. Also I didn't really use them much, I don't often need to know what line I'm on. #+BEGIN_SRC emacs-lisp (line-number-mode -1) #+END_SRC -** Tooltips +** Turn-off tooltips Tooltips are another one of those UI elements that aren't quite keyboard-friendly. As usually this information is shown just as well @@ -250,7 +222,7 @@ (tooltip-mode -1) #+END_SRC -** Cursor type +** Change cursor type I prefer using a bar as a cursor, as opposed to a box. Using a bar is a better way of representing the location of the cursor, in my @@ -260,18 +232,16 @@ (setq-default cursor-type 'bar) #+END_SRC -** Cursors in inactive windows - I use a bar cursor that's already pretty thin, so having an even - thinner one in inactive windows is not very clear. Even when I - was using a box cursor I didn't like seeing a hollow box everywhere - my focus /wasn't/. + thinner one in inactive windows is not very clear. Even when I was + using a box cursor I didn't like seeing a hollow box everywhere my + focus /wasn't/. #+BEGIN_SRC emacs-lisp (setq-default cursor-in-non-selected-windows nil) #+END_SRC -** Long lines +** Truncate long lines Sometimes, very long lines can't help but show up in code. The default of wrapping lines around to the next line and showing an @@ -282,7 +252,7 @@ (setq-default truncate-lines t) #+END_SRC -** The default frame +** Change default frame settings Usually, most of these settings would be done with functions like =set-frame-font= or =scroll-bar-mode=, but working with the Emacs @@ -290,7 +260,7 @@ start a graphical environment at some point (I usually do immediately), but the startup process isn't. -*** Internal border +*** Remove internal border Set the internal border width to 0. This makes a small difference, with my current setup it causes my window's width to increase from @@ -302,7 +272,7 @@ (internal-border-width . 0) #+END_SRC -*** A fantastic font +*** Use a fantastic font I've tried several fonts, and all of them were nice, but came up short on some way. Some didn't have italic variants, some had @@ -329,7 +299,7 @@ (font . "Fantasque Sans Mono-13") #+END_SRC -*** Scroll bar +*** Hide the scroll bar The scroll-bar is almost just as informative as the current line number and buffer position information shown in the (my) mode @@ -352,7 +322,7 @@ (vertical-scroll-bars . nil) #+END_SRC -*** Setting the option +*** Bringing it all together So I've explained the reasons for each individual setting, but to get them to work they have to be put in the =default-frame-alist=. @@ -365,7 +335,7 @@ <>)) #+END_SRC -** Frame title +** Set the frame title Show the buffer name in the frame title to make multiple frames identifiable by the buffer they're showing. @@ -435,316 +405,113 @@ (setq frame-resize-pixelwise t) #+END_SRC -* Add org-mode appointments to the diary +** Don't just quit Emacs with {{{key(C-x C-c)}}} in the daemon - Diary offers reminders, which can be useful when scheduling - appointments. - - #+BEGIN_SRC emacs-lisp - (defadvice org-agenda-redo (after ext:org-agenda-redo-add-appts) - "Pressing `r' on the agenda will also add appointments." - (setq appt-time-msg-list nil) - (org-agenda-to-appt)) - #+END_SRC - -* Close ansi-term buffer after exit - - After the ansi-term process ends it leaves a buffer. I don't use - ansi term in such a way that this has ever been useful, so just kill - the ansi-term buffer after the process quits, no matter the exit - status. Usually this comes about when I press {{{kbd(C-d)}}} at the - command prompt. - - #+BEGIN_SRC emacs-lisp - (defadvice term-handle-exit (after oni:kill-buffer-after-exit activate) - "Kill the term buffer if the process finished." - (kill-buffer (current-buffer))) - #+END_SRC - -* Stumpwm integration - - This variable, macro and function help with integrating Emacs and - Stumpwm. They are used by some other functions to make the two seem - extra connected. - - #+BEGIN_SRC emacs-lisp - (defvar oni:stumpish-program - (expand-file-name - "~/.local/share/quicklisp/local-projects/stumpwm/contrib/util/stumpish/stumpish") - "The location of the stumpish executable.") - - (defmacro oni:stumpwm (&rest body) - "Execute BODY in stumpwm." - (declare (indent 0)) - `(call-process oni:stumpish-program nil nil nil - ,(format "eval '%S'" `(progn ,@body)))) - - (defun oni:stumpwm-command (cmd) - "Execute CMD in stumpwm." - (call-process oni:stumpish-program nil nil nil cmd)) - - (defun oni:stumpwm-echo (message) - (call-process oni:stumpish-program nil nil nil (format "echo %s" message))) - #+END_SRC - -** Fall back on stumpwm when moving around - - Using the function specified in [[Stumpwm integration]] wrap the - =windmove-do-window-select= function and catch any error produced, - hoping it's the error that there's no more window to move to and - then request that stumpwm move the focus in the same direction as - windmove would have. + When working with Emacs as a daemon, which I do almost all of the + time, I prefer using {{{key(C-x C-c)}}} to close the current frame + instead of the entire session. Before this change I would + occasionally close my session by mistake. #+BEGIN_SRC emacs-lisp - (defadvice windmove-do-window-select - (around oni:windmove-stumpwm activate) - "If no window can be moved to, move stumpwm." - (condition-case err - ad-do-it - (error (oni:stumpwm-command - (format "move-focus %s" (ad-get-arg 0)))))) + (defun oni:close-client-window () + "Close a client's frames." + (interactive) + (server-save-buffers-kill-terminal nil)) + + (when (daemonp) + (global-set-key (kbd "C-x C-c") 'oni:close-client-window)) #+END_SRC -* Don't just quit Emacs with {{{key(C-x C-c)}}} in the daemon +** Don't minimize the frame with {{{key(C-z)}}} - When working with Emacs as a daemon, which I do almost all of the - time, I prefer using {{{key(C-x C-c)}}} to close the current frame - instead of the entire session. Before this change I would - occasionally close my session by mistake. + One of the more annoying things that can happen is accidentally + minimizing the frame you're working with. This doesn't really matter + if you're working on a normal stacking window manager, but with a + tiling window manager and no task bar this just causes the Emacs + frame to hang until it is refocused or disappear with no way to get + it back. - #+BEGIN_SRC emacs-lisp - (defun oni:close-client-window () - "Close a client's frames." - (interactive) - (server-save-buffers-kill-terminal nil)) + #+BEGIN_SRC emacs-lisp + (when (or window-system (daemonp)) + (global-unset-key (kbd "C-z"))) + #+END_SRC - (when (daemonp) - (global-set-key (kbd "C-x C-c") 'oni:close-client-window)) - #+END_SRC +** Lazily load some buffers -* Don't minimize the frame with {{{key(C-z)}}} - - One of the more annoying things that can happen is accidentally - minimizing the frame you're working with. This doesn't really matter - if you're working on a normal stacking window manager, but with a - tiling window manager and no task bar this just causes the Emacs - frame to hang until it is refocused or disappear with no way to get - it back. - - #+BEGIN_SRC emacs-lisp - (when (or window-system (daemonp)) - (global-unset-key (kbd "C-z"))) - #+END_SRC - -* Use the right dictionary - - One of the caveats of using two (or more) languages in a single - installation of Gnus is that ispell sometimes gets confused. Having - come across a stackoverflow question[fn:7] about just this subject - it was easy to modify the source code posted there to come up with - this. - - *Note:* See my [[Function declarations][note]] on function declarations about the use of - =declare-function=. - - #+BEGIN_SRC emacs-lisp - (declare-function message-narrow-to-headers-or-head "message") - (declare-function message-fetch-field "message") - - (defun oni:switch-ispell-dictionary () - (save-excursion - (message-narrow-to-headers-or-head) - (when (string-match (rx (and "@" (or "aethon" "picturefix") ".nl>") eol) - (message-fetch-field "From")) - (ispell-change-dictionary "nl_NL")))) - - (add-hook 'message-setup-hook 'oni:switch-ispell-dictionary) - #+END_SRC - -* Don't let shr use background color - - Reading mail in Gnus is very nice, but shr has become a little too - good at its job. Add to this the many occasions when a background is - specified without specifying a foreground, plus a color theme that - is the inverse of what is usually expected, and you can get - hard-to-read HTML messages, gray foreground and gray background. - - I've looked at the other possible renderers, but they don't look - very nice compared to shr. So just remove its ability to add - background colors. - - *Note:* See my [[Function declarations][note]] on function declarations about the use of - =declare-function=. - - #+BEGIN_SRC emacs-lisp - (declare-function shr-colorize-region "shr") - - (defun oni:shr-colorize-remove-last-arg (args) - "If ARGS has more than 3 items, remove the last one." - (if (> (length args) 3) - (butlast args) - args)) - - (with-eval-after-load 'shr - (advice-add #'shr-colorize-region :filter-args - #'oni:shr-colorize-remove-last-arg)) - #+END_SRC - -* Optimized ~with-eval-after-load~ - - First offered [[http://www.lunaryorn.com/2013/05/01/byte-compiling-eval-after-load.html][here]] and then later updated [[http://www.lunaryorn.com/2013/06/25/introducing-with-eval-after-load.html][here]] (when - ~with-eval-after-load~ was added). Makes for very nice on-demand - settings loading. - - #+BEGIN_SRC emacs-lisp - ;; http://www.lunaryorn.com/2013/06/25/introducing-with-eval-after-load/ - (defmacro stante-after (feature &rest forms) - "After FEATURE is loaded, evaluate FORMS. - - FEATURE may be an unquoted feature symbol or a file name, see - `eval-after-load'." - (declare (indent 1) (debug t)) - `(,(if (or (not byte-compile-current-file) - (if (symbolp feature) - (require feature nil :noerror) - (load feature :no-message :no-error))) - `progn - (message "stante-after: cannot find %s" feature) - 'with-no-warnings) - (with-eval-after-load ',feature ,@forms))) - #+END_SRC - -* Remember SQL input - - Remembering input between sessions is a good thing. - - #+BEGIN_SRC emacs-lisp - (stante-after sql - (setf sql-input-ring-file-name - (expand-file-name "~/.emacs.d/sqliinput"))) - #+END_SRC - -* Lazily load some buffers - - Don't load all buffers right away. Having a lot of buffers and - switching between projects a lot can take up quite a bit of time. - - *Note:* See my [[Vacuous defvar][note]] on vacuous defvar for this use of =defvar=. - - #+BEGIN_SRC emacs-lisp - (defvar desktop-restore-eager) - (setq desktop-restore-eager 5) - #+END_SRC - -* Fix some term keybindings - - =ansi-term= passes along a lot of characters correctly, but things - like =forward-delete-word= are not, by default. This is confusing when - you see one thing and another is sent. Passing the correct keys - directly to the terminal fixes this problem. - - *Note:* See my [[Vacuous defvar][note]] on vacuous defvar for this use of =defvar=. - - *Note:* See my [[Function declarations][note]] on function declarations about the use of - =declare-function=. - - #+BEGIN_SRC emacs-lisp - (defvar term-raw-map) - (declare-function term-send-raw-string "term") - - (defun oni:set-term-keys () - (cl-flet ((zcommand (key) - (lambda () - (interactive) (term-send-raw-string key)))) - (define-key term-raw-map - (kbd "C-") (zcommand "\C-H")))) - - (add-hook 'term-mode-hook #'oni:set-term-keys) - #+END_SRC - -* Ask for a ~y~ or ~n~, not ~yes~ or ~no~. - - Emacs starts out asking for you to type ~yes~ or ~no~ with most - important questions. It is possible that this is used for such - important questions where accidentally saying ~yes~ when you meant ~no~ - would be catastrophic (or at least could be). However, I've never - (so far) had this problem, and I find it quite tedious to have to - write out ~yes~ or ~no~ and then press {{{kbd(RET)}}}, give me a simple - ~y~ or ~n~ with no {{{kdb(RET)}}} required and I'm quite happy. - - #+BEGIN_SRC emacs-lisp - (defalias 'yes-or-no-p 'y-or-n-p) - #+END_SRC - -* Use =hippie-expand=, not =dabbrev-expand= - - I've never actually used =dabbrev-expand=, and only rarely use - =hippie-expand= really, but since =hippie-expand= also includes a - =dabbrev= expander and a lot more than just that, it seems alright to - do this. - - #+BEGIN_SRC emacs-lisp - (defalias 'dabbrev-expand 'hippie-expand) - #+END_SRC - -* Setting up =load-path= - - First, to help, I create a function that takes a path, adds it to - =load-path= and then checks to see if there is a file named - ~loaddefs.el~ in the given path. If there is, it loads it. This - ~loaddefs.el~ file is something that is created from autoload cookies - in the files in some of these paths. - - Since the =load-path= is also important during byte-compilation, this - function should be defined both at run-time and compile-time. - - #+BEGIN_SRC emacs-lisp - (eval-and-compile - (defun oni:loadpath-add-and-autoload (path) - "Add PATH to `load-path' and load a `loaddefs.el' if it exists." - (add-to-list 'load-path path) - (let ((loaddefs (concat path "/loaddefs.el"))) - (when (file-exists-p loaddefs) - (load loaddefs))))) - #+END_SRC - - After that I add some directories to my =load-path= so I can use these - libraries when wanted. One of these is the ~site-lisp~ directory in my - ~.emacs.d~ directory, which is where I keep most of my personal - non-ELPA modules (like module-specific initialization files). There - are also some directories I include in ~vendor-lisp~, which is where I - keep modules that I didn't write myself and, for some reason, can't - or don't want to use ELPA for. Again it is important to realize that - this information is relevant both at run-time and compile-time, so - we wrap it with an =eval-and-compile=. - - #+BEGIN_SRC emacs-lisp - (eval-and-compile - (mapc #'oni:loadpath-add-and-autoload - '("~/.emacs.d/site-lisp" - "~/.emacs.d/vendor-lisp/mozrepl" - "~/.emacs.d/vendor-lisp/eap" "/usr/share/emacs/site-lisp" - "/usr/lib/node_modules/tern/emacs/" - "~/.emacs.d/vendor-lisp/habitrpg.el"))) - #+END_SRC - -* Some unconditional settings - - Here are some settings that either need to be changed before certain - modules load, or that don't belong in any specific module. - -** Gnus init file - - I put my gnus initialization file right where I put all my - module-specific initialization files. Gnus is special, though: It - loads the file every time you start it. That keeps it from using a - simple =(eval-after-load 'gnus '(load "gnus-init"))=. + Don't load all buffers right away. Having a lot of buffers and + switching between projects a lot can take up quite a bit of time. *Note:* See my [[Vacuous defvar][note]] on vacuous defvar for this use of =defvar=. #+BEGIN_SRC emacs-lisp - (defvar gnus-init-file) - (setq gnus-init-file "~/.emacs.d/site-lisp/gnus-init") + (defvar desktop-restore-eager) + (setq desktop-restore-eager 5) + #+END_SRC + +** Ask for a ~y~ or ~n~, not ~yes~ or ~no~. + + Emacs starts out asking for you to type ~yes~ or ~no~ with most + important questions. It is possible that this is used for such + important questions where accidentally saying ~yes~ when you meant ~no~ + would be catastrophic (or at least could be). However, I've never + (so far) had this problem, and I find it quite tedious to have to + write out ~yes~ or ~no~ and then press {{{kbd(RET)}}}, give me a simple + ~y~ or ~n~ with no {{{kdb(RET)}}} required and I'm quite happy. + + #+BEGIN_SRC emacs-lisp + (defalias 'yes-or-no-p 'y-or-n-p) + #+END_SRC + +** Use =hippie-expand=, not =dabbrev-expand= + + I've never actually used =dabbrev-expand=, and only rarely use + =hippie-expand= really, but since =hippie-expand= also includes a + =dabbrev= expander and a lot more than just that, it seems alright to + do this. + + #+BEGIN_SRC emacs-lisp + (defalias 'dabbrev-expand 'hippie-expand) + #+END_SRC + +** Setting up =load-path= + + First, to help, I create a function that takes a path, adds it to + =load-path= and then checks to see if there is a file named + ~loaddefs.el~ in the given path. If there is, it loads it. This + ~loaddefs.el~ file is something that is created from autoload cookies + in the files in some of these paths. + + Since the =load-path= is also important during byte-compilation, this + function should be defined both at run-time and compile-time. + + #+BEGIN_SRC emacs-lisp + (eval-and-compile + (defun oni:loadpath-add-and-autoload (path) + "Add PATH to `load-path' and load a `loaddefs.el' if it exists." + (add-to-list 'load-path path) + (let ((loaddefs (concat path "/loaddefs.el"))) + (when (file-exists-p loaddefs) + (load loaddefs))))) + #+END_SRC + + After that I add some directories to my =load-path= so I can use these + libraries when wanted. One of these is the ~site-lisp~ directory in my + ~.emacs.d~ directory, which is where I keep most of my personal + non-ELPA modules (like module-specific initialization files). There + are also some directories I include in ~vendor-lisp~, which is where I + keep modules that I didn't write myself and, for some reason, can't + or don't want to use ELPA for. Again it is important to realize that + this information is relevant both at run-time and compile-time, so + we wrap it with an =eval-and-compile=. + + #+BEGIN_SRC emacs-lisp + (eval-and-compile + (mapc #'oni:loadpath-add-and-autoload + '("~/.emacs.d/site-lisp" + "~/.emacs.d/vendor-lisp/mozrepl" + "~/.emacs.d/vendor-lisp/eap" "/usr/share/emacs/site-lisp" + "/usr/lib/node_modules/tern/emacs/" + "~/.emacs.d/vendor-lisp/habitrpg.el"))) #+END_SRC ** Turn off bidirectional text @@ -802,6 +569,276 @@ (setq message-log-max 1000) #+END_SRC +** Reject SSL/TLS certificates that don't check out + + You just can't trust the internet. And I'd prefer to know if + something goes wrong. + + #+BEGIN_SRC emacs-lisp + (defvar gnutls-verify-error) + + (setq gnutls-verify-error t) + #+END_SRC + +** Use Conkeror to browse URLs + + Use the generic browse-url function to open URLs in Conkeror. + + #+BEGIN_SRC emacs-lisp + (stante-after browse-url + (setq browse-url-browser-function 'browse-url-generic) + (setq browse-url-generic-program "conkeror")) + #+END_SRC + +* Major mode customization + + Many major modes offer and require some customization. + +** Org mode + + Org mode offers /a lot/ of customization options. Most of mine are in + a separate file. + +*** Add org-mode appointments to the diary + + Diary offers reminders, which can be useful when scheduling + appointments. + + #+BEGIN_SRC emacs-lisp + (defadvice org-agenda-redo (after ext:org-agenda-redo-add-appts) + "Pressing `r' on the agenda will also add appointments." + (setq appt-time-msg-list nil) + (org-agenda-to-appt)) + #+END_SRC + +** Ansi term + + I don't use ansi term much. Though I probably should do it more. + Eshell is much nicer for many reasons but it can't handle + everything. + +*** Close ansi-term buffer after exit + + After the ansi-term process ends it leaves a buffer. I don't use + ansi term in such a way that this has ever been useful, so just kill + the ansi-term buffer after the process quits, no matter the exit + status. Usually this comes about when I press {{{kbd(C-d)}}} at the + command prompt. + + #+BEGIN_SRC emacs-lisp + (defadvice term-handle-exit (after oni:kill-buffer-after-exit activate) + "Kill the term buffer if the process finished." + (kill-buffer (current-buffer))) + #+END_SRC + +* Some general-purpose functions and macros + + A configuration as big as mine is bound to have some functions and + macros that are used in many places. + +** Turn off + + This macro creates a function that will turn off a minor mode that + passed to it. + + #+BEGIN_SRC emacs-lisp + (defmacro turn-off (func) + "Create a function that will turn off FUNC when called." + `(lambda () (eval (,func -1)))) + #+END_SRC + +** Change setting + + Sometimes a mode just needs to change a certain setting to a + specific value. + + #+BEGIN_SRC emacs-lisp + (defmacro change-settings (&rest settings) + "Create a function that changes the value of NAME to VALUE." + `(lambda () (setq ,@settings))) + #+END_SRC + +** Whitespace only with tabs + + In some modes I want to see the tabs in a buffer. Though I don't + want to be overwhelmed by seeing all spaces and line endings. + + #+BEGIN_SRC emacs-lisp + (defvar whitespace-style) + + (defun oni:whitespace-only-tabs () + (setq-local whitespace-style '(face tabs)) + (whitespace-mode)) + #+END_SRC + +** Eval after init + + Some things can only really work after all other initialization + functions have completed. For example, any functions that require + any ELPA packages to be loaded, unless you want to load it in your + init manually (and have it loaded again later on after your config + has run). + + #+BEGIN_SRC emacs-lisp + (defmacro oni:eval-after-init (&rest body) + "Defer execution of BODY until after Emacs init." + (declare (indent 0)) + `(add-hook 'emacs-startup-hook #'(lambda () ,@body))) + #+END_SRC + +* Stumpwm integration + + This variable, macro and function help with integrating Emacs and + Stumpwm. They are used by some other functions to make the two seem + extra connected. + + #+BEGIN_SRC emacs-lisp + (defvar oni:stumpish-program + (expand-file-name + "~/.local/share/quicklisp/local-projects/stumpwm/contrib/util/stumpish/stumpish") + "The location of the stumpish executable.") + + (defmacro oni:stumpwm (&rest body) + "Execute BODY in stumpwm." + (declare (indent 0)) + `(call-process oni:stumpish-program nil nil nil + ,(format "eval '%S'" `(progn ,@body)))) + + (defun oni:stumpwm-command (cmd) + "Execute CMD in stumpwm." + (call-process oni:stumpish-program nil nil nil cmd)) + + (defun oni:stumpwm-echo (message) + (call-process oni:stumpish-program nil nil nil (format "echo %s" message))) + #+END_SRC + +** Fall back on stumpwm when moving around + + Using the function specified in [[Stumpwm integration]] wrap the + =windmove-do-window-select= function and catch any error produced, + hoping it's the error that there's no more window to move to and + then request that stumpwm move the focus in the same direction as + windmove would have. + + #+BEGIN_SRC emacs-lisp + (defadvice windmove-do-window-select + (around oni:windmove-stumpwm activate) + "If no window can be moved to, move stumpwm." + (condition-case err + ad-do-it + (error (oni:stumpwm-command + (format "move-focus %s" (ad-get-arg 0)))))) + #+END_SRC + +* Use the right dictionary + + One of the caveats of using two (or more) languages in a single + installation of Gnus is that ispell sometimes gets confused. Having + come across a stackoverflow question[fn:7] about just this subject + it was easy to modify the source code posted there to come up with + this. + + *Note:* See my [[Function declarations][note]] on function declarations about the use of + =declare-function=. + + #+BEGIN_SRC emacs-lisp + (declare-function message-narrow-to-headers-or-head "message") + (declare-function message-fetch-field "message") + + (defun oni:switch-ispell-dictionary () + (save-excursion + (message-narrow-to-headers-or-head) + (when (string-match (rx (and "@" (or "aethon" "picturefix") ".nl>") eol) + (message-fetch-field "From")) + (ispell-change-dictionary "nl_NL")))) + + (add-hook 'message-setup-hook 'oni:switch-ispell-dictionary) + #+END_SRC + +* Don't let shr use background color + + Reading mail in Gnus is very nice, but shr has become a little too + good at its job. Add to this the many occasions when a background is + specified without specifying a foreground, plus a color theme that + is the inverse of what is usually expected, and you can get + hard-to-read HTML messages, gray foreground and gray background. + + I've looked at the other possible renderers, but they don't look + very nice compared to shr. So just remove its ability to add + background colors. + + *Note:* See my [[Function declarations][note]] on function declarations about the use of + =declare-function=. + + #+BEGIN_SRC emacs-lisp + (declare-function shr-colorize-region "shr") + + (defun oni:shr-colorize-remove-last-arg (args) + "If ARGS has more than 3 items, remove the last one." + (if (> (length args) 3) + (butlast args) + args)) + + (with-eval-after-load 'shr + (advice-add #'shr-colorize-region :filter-args + #'oni:shr-colorize-remove-last-arg)) + #+END_SRC + +* Remember SQL input + + Remembering input between sessions is a good thing. + + #+BEGIN_SRC emacs-lisp + (stante-after sql + (setf sql-input-ring-file-name + (expand-file-name "~/.emacs.d/sqliinput"))) + #+END_SRC + +* Fix some term keybindings + + =ansi-term= passes along a lot of characters correctly, but things + like =forward-delete-word= are not, by default. This is confusing when + you see one thing and another is sent. Passing the correct keys + directly to the terminal fixes this problem. + + *Note:* See my [[Vacuous defvar][note]] on vacuous defvar for this use of =defvar=. + + *Note:* See my [[Function declarations][note]] on function declarations about the use of + =declare-function=. + + #+BEGIN_SRC emacs-lisp + (defvar term-raw-map) + (declare-function term-send-raw-string "term") + + (defun oni:set-term-keys () + (cl-flet ((zcommand (key) + (lambda () + (interactive) (term-send-raw-string key)))) + (define-key term-raw-map + (kbd "C-") (zcommand "\C-H")))) + + (add-hook 'term-mode-hook #'oni:set-term-keys) + #+END_SRC + +* Some unconditional settings + + Here are some settings that either need to be changed before certain + modules load, or that don't belong in any specific module. + +** Gnus init file + + I put my gnus initialization file right where I put all my + module-specific initialization files. Gnus is special, though: It + loads the file every time you start it. That keeps it from using a + simple =(eval-after-load 'gnus '(load "gnus-init"))=. + + *Note:* See my [[Vacuous defvar][note]] on vacuous defvar for this use of =defvar=. + + #+BEGIN_SRC emacs-lisp + (defvar gnus-init-file) + (setq gnus-init-file "~/.emacs.d/site-lisp/gnus-init") + #+END_SRC + ** Don't start =elnode= when Emacs starts Elnode is an awesome project and I'm still looking for a moment @@ -1093,17 +1130,6 @@ (setq electric-pair-skip-whitespace 'chomp) #+END_SRC -* Reject SSL/TLS certificates that don't check out - - You just can't trust the internet. And I'd prefer to know if - something goes wrong. - - #+BEGIN_SRC emacs-lisp - (defvar gnutls-verify-error) - - (setq gnutls-verify-error t) - #+END_SRC - * Programming Emacs is a real programmer's editor, especially so because it's so @@ -1495,16 +1521,6 @@ <>) #+END_SRC -* Use Conkeror to browse URLs - - Use the generic browse-url function to open URLs in Conkeror. - - #+BEGIN_SRC emacs-lisp - (stante-after browse-url - (setq browse-url-browser-function 'browse-url-generic) - (setq browse-url-generic-program "conkeror")) - #+END_SRC - * Magit Recently Magit gained the annoying habit of producing a /huge/ warning @@ -1568,19 +1584,24 @@ <>) #+END_SRC -* Load custom file +* Final touches - I don't really use the Emacs customization interface much, but I - have used it as a kind-of persistent datastore, specifically for - desktop-registry[fn:9]. I do very much like the idea of it, it's a - very cool thing to have. I also use ~custom.el~ for storing some - things that I really can't store in a public viewing location like - this file or the git repository it lives in. + These options and calls need to come last so they don't interfere + with the rest of the initialization process, or get interfered with. - #+BEGIN_SRC emacs-lisp - (setq custom-file "~/.emacs.d/custom.el") - (load custom-file) - #+END_SRC +** Load custom file + + I don't really use the Emacs customization interface much, but I + have used it as a kind-of persistent datastore, specifically for + desktop-registry[fn:9]. I do very much like the idea of it, it's a + very cool thing to have. I also use ~custom.el~ for storing some + things that I really can't store in a public viewing location like + this file or the git repository it lives in. + + #+BEGIN_SRC emacs-lisp + (setq custom-file "~/.emacs.d/custom.el") + (load custom-file) + #+END_SRC * Notes