Start cleaning up basic structure
This commit is contained in:
parent
dea9949d4b
commit
85fe9b1ab3
1 changed files with 436 additions and 415 deletions
|
@ -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:<kbd>$1</kbd>@@@@ascii:`$1'@@
|
||||
#+HTML_HEAD: <link href="https://ryuslash.org/org.css" rel="stylesheet" type="text/css">
|
||||
|
@ -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 @@
|
|||
<<default-frame-scroll-bar>>))
|
||||
#+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-<backspace>") (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-<backspace>") (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 @@
|
|||
<<flycheck-display>>)
|
||||
#+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 @@
|
|||
<<magit-auto-revert-mode>>)
|
||||
#+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
|
||||
|
||||
|
|
Loading…
Reference in a new issue