summaryrefslogtreecommitdiffstats
path: root/.emacs.d/init.org
blob: 1f37c7be92ce5633ea2b015219038b4504eae8b8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
# -*- ispell-local-dictionary: "en"; -*-
#+TITLE: Emacs init
#+HTML_HEAD: <link href="http://ryuslash.org/org.css" type="text/css" rel="stylesheet" />
#+OPTIONS: num:nil toc:nil
#+PROPERTY: tangle init2.el
#+STARTUP: showall

* First things first: Lexical binding

  To make sure that the code in this file follows the correct rules,
  make sure it uses lexical binding.

  #+BEGIN_SRC emacs-lisp :padline no
    ;;; -*- lexical-binding: t -*-
  #+END_SRC

* Improved eval-after-load

  A lot of the options and functionality isn't necessary until a
  certain package has been loaded. So in order to keep start-up as
  fast as possible, while still taking advantage of byte-compiling
  everything, I wrap most settings in the following macro, which is
  explained [[http://lunaryorn.com/2013/05/31/byte-compiling-eval-after-load/][here]].

  #+BEGIN_SRC emacs-lisp
    (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))
      ;; Byte compile the body. If the feature is not available, ignore
      ;; warnings. Taken from
      ;; http://lists.gnu.org/archive/html/bug-gnu-emacs/2012-11/msg01262.html
      (let ((loaded (if (symbolp feature)
                        (require feature nil :no-error)
                      (load feature :no-error :no-message))))
        `(,(if loaded
               'progn
             (message "stante-after: cannot find %s" feature)
             'with-no-warnings)
          (eval-after-load ',feature
            `(funcall (function ,(lambda () ,@forms)))))))
  #+END_SRC

* Executing things after initialization has finished

  Some functionality, for example everything loaded with ~package.el~,
  is only available after the initialization process has finished. So
  code that requires ~package.el~ packages to be available or other
  things that the initialization process does to be done should only
  be executed after initialization has finished. The
  =emacs-startup-hook= is good for this. This also seems more efficient
  than using =(package-initialize)=.

  #+BEGIN_SRC emacs-lisp
    (defmacro 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

* Preparing the load-path

  For anything that isn't loaded with ~package.el~ (like a manually
  installed ~org-mode~) its directory should be in =load-path=. If there
  happens to be a ~loaddefs.el~ in that same directory, load it so that
  it can add some autoloads. These directories contain manually
  installed packages, my local ~site-lisp~ directory and any project
  directories for projects which I (occasionally) work on.

  All of it is put in an =eval-and-compile= block so it is run both at
  compile-time and run-time, since it is necessary to properly compile
  my init file as well.

  #+BEGIN_SRC emacs-lisp
    (eval-and-compile
      (defun 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))))

      (mapc #'loadpath-add-and-autoload
            '("~/.emacs.d/site-lisp" "~/projects/emacs/pony-mode/src"
              "~/.emacs.d/vendor-lisp/org/lisp"
              "~/.emacs.d/vendor-lisp/org/contrib/lisp"
              "~/.emacs.d/vendor-lisp/mozrepl"
              "~/.emacs.d/vendor-lisp/eap" "/usr/share/emacs/site-lisp")))
  #+END_SRC

* Speeding up yes/no questions

  Typing ~yes~ or ~no~ when just ~y~ or ~n~ would suffice seems unnecessary.
  I've been using it almost as long as Emacs and I haven't had any
  accidents yet.

  #+BEGIN_SRC emacs-lisp
    (defalias 'yes-or-no-p 'y-or-n-p)
  #+END_SRC

* Getting a more feature-full buffer list

  ~ibuffer~ has a lot more features than regular =list-buffers=, plus does
  everything =list-buffers= does.

  #+BEGIN_SRC emacs-lisp
    (defalias 'list-buffers 'ibuffer)
  #+END_SRC

* Getting more feature-full text-completion

  One of the completion mechanisms of =hippie-expand= is a ~dabbrev~ based
  expansion, so it should do everything =dabbrev-expand= does, plus
  more. It also doesn't use =dabbrev-expand= directly, so it shouldn't
  be a problem to switch them.

  #+BEGIN_SRC emacs-lisp
    (defalias 'dabbrev-expand 'hippie-expand)
  #+END_SRC

* Making buffer names unique and understandable

  The problem with the default way of making buffer names unique is
  that it doesn't tell me anything about what makes them unique. I
  don't know what makes ~init.el<1>~ different from ~init.el<2>~. However,
  seeing it as, for example, ~init.el|.emacs.d~ and ~init.el|dotemacs~
  tells me a lot more.

  #+BEGIN_SRC emacs-lisp
    (require 'uniquify)

    (stante-after uniquify
      (setq uniquify-buffer-name-style 'post-forward))
  #+END_SRC

* Telling gnus where to look for its initialization file

  I prefer to keep everything in my =~/.emacs.d/= directory, so =~/.gnus=
  wouldn't work with that. To silence a compiler warning I define a
  "vacuous" variable first, so Emacs knows the name is defined. I
  don't specify an ~init-value~ with the =defvar= so that if it happens to
  already be defined, =setq= will still change it (=defvar= won't).

  #+BEGIN_SRC emacs-lisp
    (defvar gnus-init-file)
    (setq gnus-init-file "~/.emacs.d/site-lisp/gnus-init")
  #+END_SRC

* Clean up the UI

  There are things, like a blinking cursor, a menu bar, etc. that I
  just don't need, so I want to turn them off. Since they all have the
  same API, just loop through the symbols and turn each off.

  #+BEGIN_SRC emacs-lisp
    (defmacro turn-off (&rest modes)
      "Turn off each mode in MODES."
      `(progn ,@(mapcar (lambda (m) `(,m -1)) modes)))

    (turn-off menu-bar-mode scroll-bar-mode tool-bar-mode blink-cursor-mode
              column-number-mode line-number-mode tooltip-mode)
  #+END_SRC

* Loading a theme at the correct time

  A problem with loading some themes immediately at start-up, while
  using the ~--daemon~ switch is that there is no guarantee that it will
  ever use a window system, so it's like starting from the terminal.
  This may affect the colors of some themes.

  To get around this I use =lexical-binding= (because I'm not sure
  dynamic binding will work here) and create a closure that tracks if
  I've set the theme, so it doesn't reset it every time a new frame is
  created. Then I have this executed one tenth of a second after a
  frame is created, at which point there should be a window system and
  colors should be correct.

  One more problem is that when starting Emacs without the ~--daemon~
  switch the =after-make-frame-functions= aren't run, so if we're not
  running a daemon, just set the theme.

  #+BEGIN_SRC emacs-lisp
    (let ((theme (if (equal system-name "drd")
                     'yoshi
                   'leuven)))
      (let ((setp (not (daemonp))))
        (defun init-set-theme (frame)
          "Try to set the theme for the current (first) frame."
          (ignore frame)
          (unless setp
            (run-at-time .1 nil (lambda () (setq setp (load-theme theme t)))))))
      
      (if (daemonp)
          (add-hook 'after-make-frame-functions #'init-set-theme)
        (eval-after-init (load-theme theme t))))
  #+END_SRC

* Browsing with eww

  =eww= is a very cool project, but I don't like where it downloads things.

  #+BEGIN_SRC emacs-lisp
    (setq eww-download-path "~/downloads/")
  #+END_SRC

* Double space to end a sentence in Emacs Lisp

  The Emacs Lisp syntax checker is hell-bent on forcing me to use a
  double space at the end of sentences in comments and docstrings.
  Fine, then I will use double spaces in Emacs Lisp.

  #+BEGIN_SRC emacs-lisp
    (defun init-locally-enable-double-spaces ()
      (setq-local sentence-end-double-space t))

    (add-hook 'emacs-lisp-mode-hook #'init-locally-enable-double-spaces)
  #+END_SRC

* Show pretty symbols

  Emacs lisp has the default of showing ~lambda~ as ~λ~. I also want to
  show ~<=~ as ~≤~, ~>=~ as ~≥~ and ~sqrt~ as ~√~.

  #+BEGIN_SRC emacs-lisp
    (defun init-set-emacs-lisp-symbols ()
      (when (boundp 'prettify-symbols-alist)
        (setq prettify-symbols-alist
              (append prettify-symbols-alist
                      '(("<=" . ?≤)
                        (">=" . ?≥)
                        ("sqrt" . ?√))))))
    
    (add-hook 'emacs-lisp-mode-hook #'init-set-emacs-lisp-symbols)
  #+END_SRC

  Aside from Emacs lisp, I would also like to show most of these in
  Python. Though the ~sqrt~ doesn't seem applicable, I do want to show
  ~!=~ as ~≠~ here.

  #+BEGIN_SRC emacs-lisp
    (defun init-set-python-symbols ()
      (when (boundp 'prettify-symbols-alist)
        (setq prettify-symbols-alist
              '(("lambda" . ?λ)
                ("<=" . ?≤)
                (">=" . ?≥)
                ("!=" . ?≠)))))
    
    (add-hook 'python-mode-hook #'init-set-python-symbols)
  #+END_SRC

  Now just turn it on for =prog-mode=.

  #+BEGIN_SRC emacs-lisp
    (when (and (>= emacs-major-version 24)
               (> emacs-minor-version 3))
      (add-hook 'prog-mode-hook 'prettify-symbols-mode))
  #+END_SRC

* Slime implementations

  I usually use [[http://sbcl.org][SBCL]], but sometimes also [[http://www.clisp.org/][GNU CLISP]].

  #+BEGIN_SRC emacs-lisp
    (stante-after slime
      (setq slime-lisp-implementations
            '((sbcl ("sbcl" "--noinform") :coding-system utf-8-unix)
              (clisp ("clisp") :coding-system utf-8-unix))
            slime-default-lisp 'sbcl))
  #+END_SRC

* Use Liberation Mono font for unicode

  [[http://paratype.com/public/][PT Mono]] is a very nice font, but is misses some unicode characters I
  would like to use. [[https://www.redhat.com/promo/fonts/][Liberation Mono]] on the other hand does seem to
  contain these characters, so I use that for any unicode fonts.

  #+BEGIN_SRC emacs-lisp
    (set-fontset-font "fontset-default" 'unicode
                      (font-spec :family "Liberation Mono"
                                 :width 'normal
                                 :size 12.4
                                 :weight 'normal))
  #+END_SRC

* A command to sort python includes

  At work I use Python. Our project is getting bigger and bigger,
  import statements are growing. We use the following style:

  #+BEGIN_SRC python :tangle no
    from somemodule import (
        Class1,
        Class2,
        Class3,
    )
  #+END_SRC

  Which we found to be one of the better-looking ways to handle
  multi-line import statements. To sort these lines I wrote a very
  simplistic (and error-prone, but I'll handle it when I get to it)
  command.

  All it does is save the current point, searches backwards for a ~(~,
  then forwards for a ~)~ and sorts the region in between (not
  including) the ~()~.

  #+BEGIN_SRC emacs-lisp
    (defun sort-imports ()
      (interactive)
      (save-excursion
        (sort-lines nil (1+ (search-backward "("))
                    (1- (search-forward ")")))))
  #+END_SRC

* Bring back the z!

  One or two versions of Emacs ago it was decided that the ~z~ character
  was too easy to press accidentally, killing the current buffer if it
  was based on =special-mode=. I disagree. I don't like the fact that
  using ~q~ leaves the buffers open, usually I want to kill the buffers
  when I'm done with them, though not always. So I want back my ~z~!

  I don't, however, want to overwrite the ~z~ key in, say, =magit=, so I
  define it in the =special-mode-map= so it only gets redefined if modes
  based on =special-mode= don't rebind it themselves.

  #+BEGIN_SRC emacs-lisp
    (stante-after simple
      (define-key special-mode-map "z" #'kill-this-buffer))
  #+END_SRC

* Falling back to WM to switch windows

  Emacs and any window manager have a difference op opinion on what
  windows are. It doesn't have to matter, Emacs can manage its windows
  and stumpwm can do the rest. When moving around with ~windmove~ and it
  finds that there's no way to move in that direction, let stumpwm do
  it.

  First we have to know where the stumpish program is. SLIME could
  also be used, but calling stumpish might be easier for now.

  #+BEGIN_SRC emacs-lisp
    (defvar init-stumpish-program
      (expand-file-name
       "~/.local/share/quicklisp/local-projects/stumpwm/contrib/stumpish")
      "The location of the stumpish executable.")
  #+END_SRC

  Now that we know that, we should have an easy way to send stuff to
  it.

  #+BEGIN_SRC emacs-lisp
    (defun stumpwm-command (cmd)
      "Execute CMD in stumpwm."
      (call-process init-stumpish-program nil nil nil cmd))
  #+END_SRC

  And then we can advise =windmove-do-window-select=, so that when it
  finds there are no more windows to move to, it asks stumpwm to move
  in the same direction.

  #+BEGIN_SRC emacs-lisp
    (defadvice windmove-do-window-select
      (around init-windmove-stumpwm activate)
      "If no window can be moved to, move stumpwm."
      (condition-case err
          ad-do-it
        (error (stumpwm-command (format "move-focus %s" (ad-get-arg 0))))))
  #+END_SRC

  Now, whenever I try to move out of my Emacs windows, it just moves
  to the next X11 window, whatever it might be. My stumpwm config has
  a matching command that checks to see if the current window is
  Emacs, and if so sends the ~S-<direction>~ key to Emacs, which in turn
  calls stumpwm when it can't (getting a little crazy here).

  I also wrote a simplistic macro to execute some stumpwm lisp in
  Emacs.

  #+BEGIN_SRC emacs-lisp
    (defmacro stumpwm (&rest body)
      "Execute BODY in stumpwm."
      (declare (indent 0))
      `(call-process init-stumpish-program nil nil nil
                     ,(format "eval '%S'" `(progn ,@body))))
  #+END_SRC

  Which is pretty much the same as my =elisp= macro in my stumpwm
  config.

* Simplify window management in Emacs

  stumpwm uses ~<PREFIX> S~, ~<PREFIX> s~, ~<PREFIX> Q~ and ~<PREFIX> R~ to
  split horizontally, split vertically, remove all but the focused
  frame and remove the current frame. Somehow that seems easier than
  Emacs' ~C-x 3~, ~C-x 2~, ~C-x 1~ and ~C-x 0~. Just because ~S~, ~s~, ~Q~ and ~R~ are
  easier to reach, even though three of the four need a modifier key.

  #+BEGIN_SRC emacs-lisp
    (global-set-key (kbd "C-c S") #'split-window-right)
    (global-set-key (kbd "C-c s") #'split-window-below)
    (global-set-key (kbd "C-c Q") #'delete-other-windows)
    (global-set-key (kbd "C-c R") #'delete-window)
  #+END_SRC

* Use ternjs for javascript development

  Ternjs seems like an interesting project. Add its location to the
  =load-path=, autoload it and after it loads setup the auto-complete
  functionality.

  #+BEGIN_SRC emacs-lisp
    (add-to-list 'load-path "/usr/lib/node_modules/tern/emacs/")
    (autoload 'tern-mode "tern" nil t)

    (stante-after tern
      (require 'tern-auto-complete)
      (tern-ac-setup))
  #+END_SRC

* Turn on tern for javascript

  Torn on tern when working in =js2-mode=. It adds eldoc-like
  functionality and autocompletion.

  #+BEGIN_SRC emacs-lisp
    (add-hook 'js2-mode-hook #'tern-mode)
  #+END_SRC

* Switch to most recent buffer

  Like GNU Screen has the =C-a C-a= (at least with a =C-a= prefix)
  combination and stumpwm has =C-z C-z= (at least with a =C-z= prefix) I
  really need to be able to switch between the two most recently
  viewed buffers easily.

  #+BEGIN_SRC emacs-lisp
    (defun init-switch-to-other-buffer ()
      "Switch to the most recently viewed buffer."
      (interactive)
      (switch-to-buffer (other-buffer)))

    (global-set-key (kbd "C-. C-.") #'init-switch-to-other-buffer)
  #+END_SRC

* Fill lines to 72 columns when using woman

  It's a little bit nicer to read that way, 65 characters on a line is
  a little small.

  #+BEGIN_SRC emacs-lisp
    (stante-after woman
      (setq woman-fill-column 72))
  #+END_SRC

* Turn on smartparens for C coding

  C is not as well-structured as Lisp, but it still has a lot of
  braces, brackets and other things.

  #+BEGIN_SRC emacs-lisp
    (add-hook 'c-mode-hook #'smartparens-strict-mode)
  #+END_SRC

* Autoload and start moz-minor-mode

  When using javascript, mozrepl is awesome.

  #+BEGIN_SRC emacs-lisp
    (autoload 'moz-minor-mode "moz" nil t)
    (add-hook 'javascript-mode-hook 'moz-minor-mode)
  #+END_SRC

* Change numbers at point

  Sometimes you just want to increase or decrease the number under the
  cursor, no fuss.

  #+BEGIN_SRC emacs-lisp
    (defun change-number-at-point (change-func)
      "Use CHANGE-FUNC to change the number at `point'."
      (let ((num (number-to-string (funcall change-func (number-at-point))))
            (bounds (bounds-of-thing-at-point 'word)))
        (save-excursion
          (delete-region (car bounds) (cdr bounds))
          (insert num))))

    (defun decrease-number-at-point ()
      "Take the number at `point' and replace it with it decreased by 1."
      (interactive)
      (change-number-at-point #'1-))

    (defun increase-number-at-point ()
      "Take the number at `point' and replace it with it increased by 1."
      (interactive)
      (change-number-at-point #'1+))

    (global-set-key (kbd "C-c -") #'decrease-number-at-point)
    (global-set-key (kbd "C-c +") #'increase-number-at-point)
  #+END_SRC