move most of init into normal .el file
[dot-emacs] / myinit.el
1 ;;; copyright
2
3 ;; Copyright (C) 2019 Ian Kelling
4
5 ;; This program is free software: you can redistribute it and/or modify
6 ;; it under the terms of the GNU General Public License as published by
7 ;; the Free Software Foundation, either version 3 of the License, or
8 ;; (at your option) any later version.
9
10 ;; This program is distributed in the hope that it will be useful,
11 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ;; GNU General Public License for more details.
14
15 ;; You should have received a copy of the GNU General Public License
16 ;; along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 ;;; misc emacs documentation
19
20 ;;;; how to find auto-saved files that need recovering
21 ;; find a recently dated file in ~/.emacs.d/auto-save-list/, and see the files listed in it.
22 ;; #file# is an auto-save file. It may or may not be different than the file is corresponds to.
23 ;; If it is different, emacs will give a message about recovering it when you open it.
24
25 ;;;; misc org functions
26
27 ;; ;; these are usefull with (goto-char)
28 ;; ;; find named entity, other than headline
29 ;; (org-find-entry-with-id "string-number-or-symbol")
30
31 ;; (org-find-exact-headline-in-buffer "heading" nil t)
32
33 ;; ;; remove any indent level which is throughout the buffer
34 ;; (org-do-remove-indentation)
35
36
37 ;;;; gnus
38
39 ;; good info http://www.emacswiki.org/emacs/GnusTutorial
40 ;; good info http://www.emacs.uniyar.ac.ru/doc/em24h/emacs183.htm
41
42
43 ;; After downloading mailing list archives, once you have an mbox file,
44 ;; there are rather straightforward ways to get it into any mail program,
45 ;; but I will cover gnus, which I use and is a bit tricky.
46
47 ;; gnus has a native search (limited, too slow for body text searches), and external search engine integration.
48 ;; gnus manual recommends converting to maildir for searching local mail, but importing lots of maildir messages to gnus
49 ;; takes 10+ minutes, so scratch that option. it suggests 2 alternate options
50 ;; mairix. for mbox, it doesn't integrate 100% with gnus, it copies the search results to a mbox
51 ;; and tells gnus to make a group of that mbox and display it. This means the read state won't be persistent, but otherwise
52 ;; works great.
53
54 ;; local imap server which will use the mbox and provide search.
55 ;; dovecot is modular, theres a dovecot-common which uses recommends to install i guess it's most used modules. Its
56 ;; description is completely not useful. Anyways, I'm not sure if there is any benefit to installing this over just the
57 ;; module we need.
58 ;; pi dovecot-imapd
59
60 ;; dovecot by default also makes a an inbox folder based on the normal local mail location /var/mail/<username>
61 ;; those locations are adjustable and well documented via the var mail_location in
62 ;; /etc/dovecot/conf.d/10-mail.conf
63 ;; I forward my local mail, didn't see immediately how to turn off the inbox, but it will always be empty, so I left as
64 ;; is. you could make the var be empty, which apparently has the same effect.
65
66 ;; Originally just linked the default location ~/.mail, but I changed to altering the config since ~/.mail since it seems
67 ;; other things like postfix use that location
68
69 ;; based on http://roland.entierement.nu/blog/2010/09/08/gnus-dovecot-offlineimap-search-a-howto.html
70 ;; other links that poped up contained outdated, innacurate information
71 ;; http://sachachua.com/blog/2008/05/geek-how-to-use-offlineimap-and-the-dovecot-mail-server-to-read-your-gmail-in-emacs-efficiently/
72 ;; http://www.emacswiki.org/emacs/JamesFerguson
73 ;; http://www.sanityinc.com/articles/read-mailing-lists-in-emacs-over-imap/
74
75 ;; Within emacs you can move messages between mbox and maildir etc, which is a nice flexibility.
76
77
78
79 ;; doc group for mbox:
80 ;; in gnus, do gnus-group-make-doc-group (G f in groups buffer) and point to the file
81
82 ;; info about groups created within gnus is stored in ~/.newsrc.eld
83 ;; also stored is a duplication of what email messages are read/unread,
84 ;; what newsgroups are subsribed to and read/unread,
85 ;; probably more stuff, everything that gnus saves.
86
87
88 ;; searching the body of the messages, i cut off after a few minutes.
89 ;; i can grep the file in just a couple seconds
90
91
92 ;; random side note
93 ;; we can also get mbox from gmane
94 ;; http://notmuchmail.org/howto/#index7h2
95
96
97 ;; gnus can't search mboxes except with its builtin search which is extremely slow. mairix can do mbox files from the command
98 ;; line, but not from within gnus, but from mairix.el, which can then open the results in gnus
99
100 ;; mbox can be converted to maildir easily, but gnus loads lots of maildir messages extremely slow. it parses all the
101 ;; headers and generates a nov file for each.
102
103 ;; nnfolder-generate-active-file
104
105 ;; to reset things, when changing mail group. I duno all the proper way, but it works to delete
106 ;; ~/Mail ~/.newsrc.eld ~/.dribble (or something)
107
108
109 ;;;;; mail sources vs select methods background
110 ;; I found this very confusing when first reading through the manual. "mail sources" is a term that does not simply mean
111 ;; sources of mail, it is much narrower for gnus. sources of mail can be either "mail sources" or select methods. Mail
112 ;; sources will move mail to ~/Mail (not sure what format), and split it into groups according to variables. You can use
113 ;; "mail sources" for maildir / imap, but those can also be read via select methods, which do not move the mail from their
114 ;; location, but use them in their native format. This is what I want to do, and I can simply ignore mail
115 ;; sources. Confusing terminology is that "fetching mail" "scanning mail", lots of things mail doesn't mean all mail, it
116 ;; means specifically from "mail sources". The words "articles" and "news" is used in connection with select methods, aka my actual mail.
117
118
119
120 ;;;;; caching background
121
122 ;; caching:
123 ;; there is also ~/News/cache, filled with a bunch of articles, like 300 megs. can't figure out why.
124 ;; Grepped for caching in the manual, found 2 main things.
125 ;; cache is for 2 purposes. to cache locally, and to keep articles from expiring, called persistence
126 ;; gnus-use-cache, which puts things if they are
127 ;; gnus-cache-enter-articles
128 ;; things go in cache when they are marked certain ways by default, ticked and dormant
129 ;; and read articles are moved out of the cache
130 ;; still no idea why i have a bunch in the cache, but I set a var so that my mail won't get cached
131 ;; I'm gonna delete the cache, and check on it later see what exactly is going in there
132 ;; And of course, I moved ~/News to my encrypted drive and symlinked it
133
134
135
136 ;;; things that should be at the beginning
137 ;; todo, evaluating this manually disables debug on error instead of toggling it
138 ;;(toggle-debug-on-error) ;uncomment to help debug and catch errors
139
140 ;; packages installed from package manager: i pretty much prioritize repos this way: gnu, then melpa, then marmalade.
141
142 ;; package-activated-list:
143 ;; ac-dabbrev ac-haskell-process ack-and-a-half alect-themes auctex bash-completion bbdb csv-mode cyberpunk-theme dot-mode expand-region f find-file-in-project flycheck foreign-regexp ggtags ghc gnuplot-mode goto-chg haskell-mode heroku-theme highlight-indentation highlight-symbol htmlize inf-ruby info+ inkpot-theme jedi auto-complete jedi-core epc ctable concurrent key-chord leuven-theme logstash-conf magit git-commit magit-popup misc-fns mouse+ naquadah-theme nginx-mode occidental-theme org paredit pcsv php-mode pkg-info epl popup py-autopep8 python-environment deferred python-info python-mode rainbow-mode rust-mode rw-hunspell s smartparens smex smooth-scroll sr-speedbar strings swiper ivy tabulated-list tangotango-theme thingatpt+ undo-tree vimrc-mode volatile-highlights web-mode with-editor dash async ws-butler yasnippet
144
145 ;;;; alternate keyboards
146 ;; todo, figure out an easy way to disable this when using external keyboard
147 (if (display-graphic-p)
148 (setq
149 enter-key (kbd "<return>")
150 s-enter-key (kbd "<S-return>")
151 c-m-enter-key (kbd "<C-M-return>")
152 m-enter (kbd "<M-return>")
153 c-enter (kbd "<C-return>"))
154 (setq
155 enter-key (kbd "C-m")
156 s-enter-key (kbd "C-8")
157 c-m-enter-key (kbd "C-M-8")
158 m-enter (kbd "M-m")
159 c-enter (kbd "C-8")))
160
161 (setq tp (string= (system-name) "tp"))
162 (setq x200 (string= (system-name) "x2"))
163 (setq laptop-keyboard (or tp x200))
164
165 ;; Ubiquitous Packages which should be loaded on startup rather than
166 ;; autoloaded on demand since they are likely to be used in every
167 ;; session.
168 (require 'saveplace)
169 (require 'ffap)
170 (require 'uniquify)
171 (require 'ansi-color)
172 (require 'recentf)
173
174 ;; Better to have a list of packages in here vs installed manually.
175 ;; However, I install manually because sometimes there are two
176 ;; versions and it is not necessarily easy to reconcile that.
177 ;; based on marmalage website front page.
178 (require 'package)
179
180 ;; little kit to help remove a down server
181 ;; (setq package-archives nil)
182
183 ;;(add-to-list 'package-archives
184 ;; '("marmalade" .
185 ;; "http://marmalade-repo.org/packages/"))
186
187 (add-to-list 'package-archives
188 '("melpa" . "http://melpa.milkbox.net/packages/") t)
189 (add-to-list 'package-archives '("org" . "http://orgmode.org/elpa/") t)
190
191
192 ;; keep our init.el clean, by moving customization elisp to it's own file
193 (setq custom-file "~/.emacs.d/custom.el")
194 (load custom-file 'noerror)
195
196 ;; undo tree stuff
197 ;; more resilient undo-tree-history if we have their locations set up front.
198 (setq undo-tree-history-directory-alist '(("." . "~/.undo-tree-history")))
199 ;; Undo in region just happens accidentally, and throws me off, and it's been buggy in the past
200 (setq undo-tree-enable-undo-in-region nil)
201
202
203 ;;; abreviations
204 ;; turn on abbrev mode globally
205 (setq-default abbrev-mode t)
206
207 ;; default abbreviation mode file is .emacs.d/abbrev_defs.
208 ;; add-global-abbrev, add-mode-abbrev for expansion at point
209 ;; if all else fails, edit the abbrev file
210
211
212
213
214 ;;; auto-complete
215
216 ;; auto-completion in minibuffer
217 ;; disabled while I look for another alternative
218 ;;(icomplete-mode)
219
220 (require 'auto-complete-config)
221 (ac-config-default)
222
223
224 ;; complete after 1 char instead of default 2
225 (setq ac-auto-start 1)
226 (setq ac-delay 0.001)
227
228 (add-to-list 'ac-modes 'org-mode 'sql-mode)
229
230 (defun ac-common-setup ()
231 (add-to-list 'ac-sources 'ac-source-yasnippet))
232
233 ;; for org mode completion source taken from wiki.
234 ;; it did not work. no idea why. todo, investigate
235 ;; the ac-sources code is at http://www.emacswiki.org/emacs/AutoCompleteSources
236 ;; i've deleted it here so as to save space and not spam this file
237 ;;(defun my-ac-org-mode ()
238 ;; (setq ac-sources (append ac-sources '(ac-source-org))))
239
240
241 ;; this makes the org-self-insert command not do a flyspell spell check.
242 ;; low priority thing to look into sometime
243 (ac-flyspell-workaround)
244
245
246 (define-key ac-completing-map (kbd "<up>") nil)
247 (define-key ac-completing-map (kbd "<down>") nil)
248 (define-key ac-completing-map (kbd "<S-return>") 'ac-expand)
249 (define-key ac-completing-map "\t" 'ac-complete)
250 (define-key ac-completing-map (kbd "<tab>") 'ac-complete)
251
252
253
254 ;;; auto-complete readline-complete
255
256 (require 'readline-complete)
257 ;; not sure how I made these, but I deleted, and
258 ;; it would be nice to make them again sometime
259 ;;(require 'src-loaddefs)
260
261 ;; disabled cuz broken
262 ;; redefining function in readline-complete so ac-complete only uses readline as a source
263 (defun ac-rlc-setup-sources ()
264 "Add me to shell-mode-hook!"
265 (setq ac-sources '(ac-source-shell)))
266 (add-hook 'shell-mode-hook 'ac-rlc-setup-sources)
267
268 ;; generally unnecessary, but why not
269 (setq explicit-shell-file-name "bash")
270
271 ;; readline-complete says to add this line.
272 ;; however, it up my procfs directory tracking hook
273 ;; because get-process doesn't notice the child shell.
274 ;; instead, I've removed export EMACS=t from
275 ;; comint-exec-1 (the function which initially sets it)
276 ;; by finding it in emacs sources and redefinind it here
277 ;; and done stty echo in my bashrc
278 ;;(setq explicit-bash-args '("-c" "export EMACS=; stty echo; bash"))
279
280 (setenv "EMACS" "")
281 (setq explicit-bash-args nil)
282 (setq comint-process-echoes t)
283 ;; default of 30 is way too slow. todo, consider pushing this upstream
284 (setq rlc-attempts 5)
285
286 (add-to-list 'ac-modes 'shell-mode)
287
288 ;; readline-complete recommends this (i assume this format),
289 ;; but greping finds no reference in emacs or my .emacs.d
290 ;; so I'm assuming it is for an older emacs
291 ;;(setq explicit-ssh-args '("-t"))
292
293 (add-hook 'shell-mode-hook
294 (lambda ()
295 (define-key shell-mode-map (kbd "<tab>") 'auto-complete)))
296
297
298 ;;; readline complete fix
299
300 ;; I need this function here, where INSIDE_EMACS is replaced with RLC_INSIDE_EMACS.
301 ;; ian: last update 2017-1-7. update this periodically from upstream
302 ;; like when we do a major emacs update
303 (defun comint-exec-1 (name buffer command switches)
304 (let ((process-environment
305 (nconc
306 ;; If using termcap, we specify `emacs' as the terminal type
307 ;; because that lets us specify a width.
308 ;; If using terminfo, we specify `dumb' because that is
309 ;; a defined terminal type. `emacs' is not a defined terminal type
310 ;; and there is no way for us to define it here.
311 ;; Some programs that use terminfo get very confused
312 ;; if TERM is not a valid terminal type.
313 ;; ;; There is similar code in compile.el.
314 (if (and (boundp 'system-uses-terminfo) system-uses-terminfo)
315 (list "TERM=dumb" "TERMCAP="
316 (format "COLUMNS=%d" (window-width)))
317 (list "TERM=emacs"
318 (format "TERMCAP=emacs:co#%d:tc=unknown:" (window-width))))
319 (list (format "RLC_INSIDE_EMACS=%s,comint" emacs-version))
320 process-environment))
321 (default-directory
322 (if (file-accessible-directory-p default-directory)
323 default-directory
324 "/"))
325 proc decoding encoding changed)
326 (let ((exec-path (if (and command (file-name-directory command))
327 ;; If the command has slashes, make sure we
328 ;; first look relative to the current directory.
329 (cons default-directory exec-path) exec-path)))
330 (setq proc (apply 'start-file-process name buffer command switches)))
331 ;; Some file name handler cannot start a process, fe ange-ftp.
332 (unless (processp proc) (error "No process started"))
333 (let ((coding-systems (process-coding-system proc)))
334 (setq decoding (car coding-systems)
335 encoding (cdr coding-systems)))
336 ;; Even if start-file-process left the coding system for encoding data
337 ;; sent from the process undecided, we had better use the same one
338 ;; as what we use for decoding. But, we should suppress EOL
339 ;; conversion.
340 (if (and decoding (not encoding))
341 (setq encoding (coding-system-change-eol-conversion decoding 'unix)
342 changed t))
343 (if changed
344 (set-process-coding-system proc decoding encoding))
345 proc))
346
347 ;;; auto save & backup
348 (setq auto-save-timeout 1) ; idle time before auto-save.
349
350 ;; main hook for my auto save
351 (add-hook 'auto-save-hook 'my-auto-save)
352 ;; additional hook to try to deal with emacs not auto-saving when a buffer isn't active
353 (add-hook 'window-configuration-change-hook 'my-auto-save-win)
354
355 ;; this function from mu4e really does not like buffer saving
356 (advice-add 'message-send-and-exit :before 'my-as-off)
357 (advice-add 'message-send-and-exit :after 'my-as-on)
358
359 ;; avoid window config hook saving too much, it can
360 ;; get into loops in some random situations
361 (setq my-auto-save-last nil)
362 (defun my-auto-save-win ()
363 (unless (eq (current-buffer) my-auto-save-last)
364 (my-auto-save (current-buffer))))
365
366 (defun my-auto-save (&optional last)
367 (when (and
368 my-as
369 (buffer-file-name)
370 ;; mu4e has a bug right now, undo breaks when saving drafts
371 (not (string= (buffer-file-name) "*draft*"))
372 (buffer-modified-p)
373 (not (org-src-edit-buffer-p)))
374 ;; serial is incremented on each save, so let's do a bit less of them
375 (not (derived-mode-p 'dns-mode))
376 (setq my-auto-save-last last)
377 (let (message-log-max)
378 ;; a bit of a hack to partially suppress the constant saving in the echo area
379 (with-temp-message ""
380 (basic-save-buffer)))))
381
382 ;; in the message-send-and-exit advice, got an error because it passed an arg.
383 ;; didn't look into why, just add ignored args.
384 (defun my-as-off (&rest ignore)
385 (interactive)
386 (setq my-as nil))
387
388 (defun my-as-off-local (&rest ignore)
389 (interactive)
390 (setq-local my-as nil))
391
392 (defun my-as-on (&rest ignore)
393 (interactive)
394 (setq my-as t))
395
396 (defun my-as-on-local (&rest ignore)
397 (interactive)
398 (setq-local my-as on))
399
400 ;; based on suggestion in the emacs docs, redefine these 2 functions
401 ;; to avoid prompt spamming the user when we do auto-save
402 (defun ask-user-about-supersession-threat (fn)
403 (discard-input)
404 (message
405 "File for %s has changed on disk outside of emacs. Auto-save is overwriting it, however
406 a backup is being created in case that is not what you intended." buffer-file-name)
407 (setq buffer-backed-up nil))
408
409 (defadvice ask-user-about-lock (before lock-deactivate-as activate)
410 (make-local-variable 'my-as)
411 (setq my-as nil)
412 (message "proper autosave has been turned off for this buffer because of lock file problem.
413 In this buffer, do M-x my-as-on to reenable"))
414
415 ;; todo, this doesn't work consistently to override the auto-save message
416 (defalias 'do-auto-save-original (symbol-function 'do-auto-save))
417 (defun do-auto-save (&optional no-message current-only)
418 "This function has been modified to wrap the original so that NO-MESSAGE
419 is always set to t, since we auto-save a lot, it spams otherwise.
420 The original doc string is as follows:
421
422 Auto-save all buffers that need it.
423 This is all buffers that have auto-saving enabled
424 and are changed since last auto-saved.
425 Auto-saving writes the buffer into a file
426 so that your editing is not lost if the system crashes.
427 This file is not the file you visited; that changes only when you save.
428 Normally we run the normal hook `auto-save-hook' before saving.
429
430
431 A non-nil NO-MESSAGE argument means do not print any message if successful.
432 A non-nil CURRENT-ONLY argument means save only current buffer."
433 (interactive)
434 (do-auto-save-original t current-only))
435
436 ;; enable MY auto-save
437 (my-as-on)
438
439 ;;; backups, separate from auto-save
440
441
442 ;; set backup file location
443 (setq backup-directory-alist '(("." . "~/.editor-backups")))
444 (setq auto-save-file-name-transforms
445 '((".*" "~/.editor-backups/" t)))
446
447 (setq version-control t ;; Use version numbers for backups
448 kept-new-versions 100
449 kept-old-versions 2
450 delete-old-versions t ;; delete old versions silently
451 ;; assume hard linked files are done on purpose, don't screw them up
452 backup-by-copying-when-linked t)
453
454 ;; todo, the time needs to be an integer, not a vector type thing
455 (defun constant-backup ()
456 "Backup conditioned on some time passing since last one.
457 Hooked into 'before-save-hook."
458 (cl-flet ((b-time (minutes)
459 (< last-backup-time
460 (- (current-time) (* 60 minutes)))))
461 (when (or (not (boundp 'last-backup-time)) (and (< (buffer-size) 10000000) (b-time 5)) (b-time 30))
462 (setq buffer-backed-up nil)
463 (setq-local last-backup-time (current-time)))))
464
465 ;; make a backup on auto-save, because the backup feature is not
466 ;; utilized with my-auto-save, only normal interactive save.
467 ;; todo, enable when fixed
468 ;;(add-hook 'before-save-hook 'constant-backup)
469
470 (add-hook 'auto-save-hook 'auto-save-size-limit)
471
472 (defun auto-save-size-limit ()
473 (when (and (not backup-inhibited) (> (buffer-size) 2000000))
474 (message "Backups disabled for this buffer due to size > 2 megs")
475 (make-local-variable 'backup-inhibited)
476 (setq backup-inhibited t)))
477
478
479 ;; ;; background:
480 ;; ;; the faq suggests to auto-save using
481 ;; (setq auto-save-visited-file-name t)
482 ;; and to toggle auto-saving in the current buffer, type `M-x auto-save-mode'
483
484 ;; however, this is buggy.
485 ;; it leaves around lock files, which can be disabled with
486 ;; (setq create-lockfiles nil)
487 ;; but it is also buggy on other things that appear to hook onto file saving
488 ;; so i created my own function, which originally had bugs,
489 ;; but new emacs version fixed all that, yay!.
490
491
492 ; not using, but here for documentation,
493 ; alternate way to enable and specify how long between autosaves.
494 ; number of input events between autosave.
495 ; lowest bound of functionality is actually about 15 input events
496 ;(setq auto-save-interval
497
498 ;;; bbdb
499 ;; based on bbdb manual
500 ;; also has instructions to initialize upon launching gnus, etc
501 ;; but I figure try this to make sure everything works all the time first
502 (require 'bbdb)
503 (bbdb-initialize 'message)
504
505 ;; recommended by gnus,
506 ;; but seems like it could be good to have set for other stuff
507 (setq user-full-name "Ian Kelling")
508 ;; general email setting? recommended by mu4e
509 (setq message-kill-buffer-on-exit t)
510
511
512 ;; based on emacs24-starter-kit
513 (setq bbdb-offer-save 'auto
514 bbdb-notice-auto-save-file t
515 bbdb-expand-mail-aliases t
516 bbdb-canonicalize-redundant-nets-p t
517 bbdb-complete-name-allow-cycling t)
518
519 ;; use d instead
520 (add-hook 'bbdb-mode-hook
521 (lambda () (define-key bbdb-mode-map (kbd "C-k") nil)))
522
523 (require 'bbdb-csv-import)
524
525 ;;; bookmark settings
526 ; save bookmarks whenever they are changed instead of just when emacs quits
527 (setq bookmark-save-flag 1)
528 ; increase bookmark context size for better functionality
529 (setq bookmark-search-size 2000)
530
531 ;;; c-like settings
532 ;; change last thing from gnu.
533 ;; notably this avoids brace indent after if, and 4 space indent
534 (setq c-default-style '((java-mode . "java")
535 (awk-mode . "awk")
536 (other . "stroustrup")))
537 ;; for emacs itself, use
538 ;; (setq c-default-style '((java-mode . "java")
539 ;; (awk-mode . "awk")
540 ;; (other . "gnu")))
541 ;; (setq-default c-basic-offset 2)
542
543 ;;; color theme
544
545 ;; A Theme builder is available at http://elpa.gnu.org/themes/ along with
546 ;; a list of pre-built themes at http://elpa.gnu.org/themes/view.html and
547 ;; themes are available through ELPA.
548
549
550 ;; interesting light themes
551
552
553 (defun override-theme (arg)
554 (interactive)
555 (while custom-enabled-themes
556 (disable-theme (car custom-enabled-themes)))
557 (load-theme arg t))
558 (setq color-theme-is-global t)
559
560 (defun toggle-night ()
561 (interactive)
562 (cond ((equal (car custom-enabled-themes) 'naquadah)
563 (override-theme 'occidental))
564 (t
565 (override-theme 'naquadah))))
566 ;; for a long time i used leuven plus this, but it doesn't like dark terminal
567 ;;(custom-set-faces `(default ((t (:background "#F6F6F0")))))
568 (override-theme 'occidental)
569
570
571 ;; disable color thing with this:
572 ;;(disable-theme (car custom-enabled-themes))
573
574 ;; decent dark themes
575
576 ;;(override-theme 'tangotango)
577 ;;(override-theme 'deeper-blue)
578 ;;(override-theme 'tango-dark)
579 ;;(override-theme 'tsdh-dark)
580
581 ;;(override-theme 'heroku)
582 ;;(override-theme 'inkpot) ;; part of inkpot-theme package
583 ;;(override-theme 'naquadah) ; org mode features, part of naquadah-theme package
584 ;;(override-theme 'spolsky) ;; part of sublime-themes package
585 ;;(override-theme 'twilight-anti-bright) ;; from twilight-anti-bright-theme package
586
587 ;; interesting but not usable colors
588 ;;(override-theme 'cyberpunk) ; cool org mode features, from cyberpunk-theme package
589 ;;(override-theme 'wombat) ; cursor not visible enough. from a wombat package, not sure which
590 ;;(override-theme 'misterioso) ; cursor not visible enough
591
592
593
594 ;;decent light themes
595 ;;(override-theme 'alect-light) ; theres a -alt version, don't see a dif. could use this without dimming. from alect-something package
596 ;;(override-theme 'occidental) ; from occidental-theme package
597
598
599 ;;color-theme is deprecated in emacs 24.
600
601 ;; theme packages i tried then removed:
602 ;; ignored ones that didn't use the new theme engine
603
604 ;;66 packages (zenburn-theme-2.1, zen-and-art-theme-1.0.1, waher-theme-20130917.7, ujelly-theme-1.0.35, twilight-theme-1.0.0, twilight-bright-theme-20130605.143, twilight-anti-bright-theme-20120713.316, tronesque-theme-1.3, tron-theme-12, toxi-theme-0.1.0, tommyh-theme-1.2, tango-2-theme-1.0.0, sunny-day-theme-20131203.1250, sublime-themes-20140117.323, subatomic-theme-20131011.1048, soothe-theme-0.3.16, soft-morning-theme-20131211.1342, soft-charcoal-theme-20130924.1206, sea-before-storm-theme-0.3, purple-haze-theme-20130929.1751, phoenix-dark-pink-theme-20130905.941, phoenix-dark-mono-theme-20130306.1215, pastels-on-dark-theme-0.3, obsidian-theme-20130920.937, nzenburn-theme-20130513, noctilux-theme-20131019.31, mustang-theme-20130920.939, monokai-theme-0.0.10, molokai-theme-20130828.0, late-night-theme-0.0, jujube-theme-0.1, ir-black-theme-20130302.2355, gruvbox-theme-20131229.1458, gruber-darker-theme-0.6, grandshell-theme-20140118.1003, github-theme-0.0.3, gandalf-theme-0.1, flatland-theme-20131204.858, django-theme-20131022.202, deep-thought-theme-0.1.1, dakrone-theme-20131212.1159, colorsarenice-theme-20131128.1106, color-theme-wombat+-0.0.2, color-theme-wombat-0.0.1, color-theme-twilight-0.1, color-theme-tango-0.0.2, color-theme-solarized-20120301, color-theme-sanityinc-solarized-2.25, color-theme-railscasts-0.0.2, color-theme-monokai-0.0.5, color-theme-molokai-0.1, color-theme-ir-black-1.0.1, color-theme-heroku-1.0.0, color-theme-github-0.0.3, color-theme-eclipse-0.0.2, color-theme-dpaste-0.0.1, color-theme-dawn-night-1.0, color-theme-colorful-obsolescence-0.0.1, color-theme-cobalt-0.0.2, color-theme-20080305.34, clues-theme-20130908.801, busybee-theme-20130920.942, bubbleberry-theme-0.1.2, mblage-theme-20130715.621, anti-zenburn-theme-20140104.1542, ample-zen-theme-0.2)
605
606
607
608
609 ;;; yasnippet
610
611 ;; cd ~/.emacs.d/src
612 ;; git clone --recursive https://github.com/capitaomorte/yasnippet
613 ;; touch snippets/.yas-make-groups
614
615 ;; This all makes it so I can look through the default snippets
616 ;; in the menu bar, but they don't show up elsewhere, because they are
617 ;; mostly things I don't want.
618
619
620 (require 'yasnippet)
621 ;; this needs to be before yas-global-mode
622 (setq yas-snippet-dirs (list "~/.emacs.d/snippets"))
623 (yas-global-mode 1)
624
625 (setq
626 yas-also-auto-indent-first-line t
627 yas-choose-tables-first t
628 yas-use-menu (quote full)
629 ;; this sets ido-prompt as first function
630 yas-prompt-functions
631 '(yas-ido-prompt yas-dropdown-prompt yas-x-prompt yas-completing-prompt yas-no-prompt))
632
633 ;; todo, explore this option for wrapping region
634 ;; '(yas/wrap-around-region t))
635
636 ;;; cross session settings
637
638 ;; Save a list of recent files visited.
639 (recentf-mode 1)
640 (setq recentf-max-saved-items 200
641 recentf-max-menu-items 15)
642
643
644 (setq save-place t
645 save-place-version-control 'nospecial
646 save-place-limit 40000
647 save-place-file "~/.emacs.d/places")
648
649
650
651 ;; savehist keeps track of some history
652 ;; search entries
653 (setq savehist-additional-variables '(kill-ring search-ring regexp-search-ring)
654 ;; save every minute
655 savehist-autosave-interval 60
656 ;; keep the home clean
657 savehist-file "~/.emacs.d/.savehist")
658 (savehist-mode 1)
659
660
661 ;;; ediff
662 ;; ediff-buffers is the main command to use
663
664 ;; ediff - don't start another frame for the control panel
665 ;; unfortunately, this doesn't allow me to use 2 frames for the diff buffers
666 ;; so disable this temporarily with the next line if you want that
667 ;; sometime I should setup 2 functions to explicitly do each type
668 (setq ediff-window-setup-function 'ediff-setup-windows-plain)
669 ;;(setq ediff-window-setup-function 'ediff-setup-windows-default)
670
671 ;; do side by side diffs
672 (setq ediff-split-window-function 'split-window-horizontally)
673
674
675
676 ;; Things I tried which didn't work, which intuitively I think should
677 ;; work better: I can open the second diff buffer in a new frame, and
678 ;; close it's window in the first frame after starting ediff, but when I
679 ;; hit n to go to the next diff, it restores the window in the first
680 ;; frame. Another thing I tried is to open 2 new frames and set them up
681 ;; as I want. However, if I try to open the *Ediff Control Panel* buffer
682 ;; in a different window from its original one, my mouse jumps to one of
683 ;; the diff frames, or if that isn't visible, the buffer just hangs
684 ;; until I select the original ediff control panel window. This seems
685 ;; like a bug to me. I am using a very recent development version of
686 ;; emacs.
687
688 ;;; dired
689
690 ;; dired - reuse current buffer by pressing 'a'
691 (put 'dired-find-alternate-file 'disabled nil)
692
693 ;;; mu4e
694
695 ;; alsot tried notmuch, it had some glitches, and it's config has a list
696 ;; of folders which i'd rather not publish, so it's config is archived.
697
698 ;;(add-to-list 'load-path "/usr/local/share/emacs/site-lisp/mu4e")
699 ;;(add-to-list 'load-path "/usr/share/emacs/site-lisp/mu4e")
700 (require 'mu4e)
701
702 ;; (setq mu4e-headers-results-limit 2000)
703
704 (setq
705 ;; common to gnus. default sendmail-query-once asks us, then sets this via customize.
706 send-mail-function (quote sendmail-send-it)
707 ;; use the standard imap folders
708 mu4e-sent-folder "/Sent"
709 mu4e-drafts-folder "/Drafts"
710 mu4e-trash-folder "/Trash"
711 ;; reindex new mail this often in seconds
712 ;; show addresses instead of just names
713 mu4e-view-show-addresses t
714 mu4e-use-fancy-chars t
715 mu4e-confirm-quit nil
716 mu4e-headers-leave-behavior 'apply ;; dont ask, do whatever was marked
717 mu4e-headers-fields (delq (assoc :mailing-list mu4e-headers-fields) mu4e-headers-fields)
718 ;; default 500.
719 mu4e-headers-results-limit 1000
720 ;; tell exim to use from: as envelope from.
721 ;; exim's default is use outgoing_msg_localpart@hostname.
722 mail-specify-envelope-from t
723
724 ;; looking up the list of maildirs when doing jo from summary
725 ;; can take a few seconds if we have a ton of messages.
726 ;; Only take that time for the first lookup.
727 ;; if we add a new maildir, just restart mu4e for it to be in that list.
728 mu4e-cache-maildir-list t
729 ;; default is 8, way too small for my big monitors
730 mu4e-headers-visible-lines 50
731 )
732
733 ;; fucks up reading unread bookmark. when that is fixed, enable it
734 ;; (setq mu4e-update-interval 60)
735
736
737 ;; this file includes setting up my email addresses, which are not public,
738 ;; including
739 ;; mu4e-user-mail-address-list
740 ;; and a function
741 ;; inspired by mu4e info manual, search for mu4e-compose-pre-hook.
742 (load "/p/c/mu4e.el")
743
744 (defun my-decrypt ()
745 ;; use for decrypting in mu4e
746 (interactive)
747 (beginning-of-buffer)
748 (when (search-forward "-----BEGIN PGP MESSAGE-----" nil t)
749 (read-only-mode 0)
750 (let ((start (match-beginning 0))
751 (end (search-forward "-----END PGP MESSAGE-----" nil t)))
752 (shell-command-on-region start end "gpg2 -dq" nil t shell-command-default-error-buffer t)
753 )))
754 (add-hook 'mu4e-view-mode-hook 'my-decrypt)
755
756 (defun mu-set-from-name (regexes)
757 "If we find an address matching regex, then set that address as the to,
758 and whatever was used"
759 (when mu4e-compose-parent-message
760 (let ((found nil))
761 (while (and regexes (not found))
762 (setq re (car regexes)
763 regexes (cdr regexes)
764 found (mu4e-message-contact-field-matches
765 mu4e-compose-parent-message :to re)))
766 (when found (setq user-mail-address (cdr found)
767 user-full-name (car found)))
768 found)))
769 (defun mu-set-from (regexes)
770 "If we find an address matching regex, then set that address as the to,
771 and Ian Kelling as the name"
772 (when mu4e-compose-parent-message
773 (let ((found nil))
774 (while (and regexes (not found))
775 (setq re (car regexes)
776 regexes (cdr regexes)
777 found (cdr (mu4e-message-contact-field-matches
778 mu4e-compose-parent-message :to re))))
779 (when found (setq user-mail-address found
780 user-full-name "Ian Kelling"))
781 found)))
782
783
784 (defun my-mu4e-to-fsf ()
785 "inspired by mu4e info manual, search for mu4e-compose-pre-hook."
786 (cond
787 ((mu-set-from '("iank@fsf.org"
788 "iank@gnu.org")))
789 ((setq user-mail-address "iank@fsf.org"
790 user-full-name "Ian Kelling"))))
791
792
793 ;; on first run mkdir -p /nocow/user/.mufsf; mu index --maildir=/nocow/user/fsfmd
794 (defun mu-exit-wait ()
795 (interactive)
796 ;; taken from the mu source
797 (let* ((buf (get-buffer mu4e~proc-name))
798 (proc (and (buffer-live-p buf) (get-buffer-process buf))))
799 (mu4e-quit)
800 ;; without sleep, we get database locked by another process error when hitting u
801 ;; if another mu was running.
802 (if proc (sleep-for 0 1000))))
803
804 (defun fsf-mu4e ()
805 (interactive)
806 (unless (equal mu4e-maildir "/nocow/user/fsfmd") (mu-exit-wait))
807 (setq
808 ;; fsf monitor is smaller
809 mu4e-headers-visible-lines 15
810 mu4e-maildir "/nocow/user/fsfmd"
811 mu4e-refile-folder "/Spam"
812 mu4e-index-lazy-check nil
813 mu4e-get-mail-command "true"
814 user-mail-address "iank@fsf.org"
815 mail-signature "
816
817 --
818 Ian Kelling | Senior Systems Administrator, Free Software Foundation
819 GPG Key: B125 F60B 7B28 7FF6 A2B7 DF8F 170A F0E2 9542 95DF
820 https://fsf.org | https://gnu.org
821 "
822
823 mu4e-user-mail-address-list '("iank@fsf.org"
824 "iank@gnu.org")
825 mu4e-maildir-shortcuts
826 '( ("/INBOX" . ?i)
827 ("/sysadmin" . ?a)
828 ("/sec" . ?x)
829 ("/rtcc" . ?c)
830 ("/Drafts" . ?d)
831 ("/Sent" . ?s)
832 )
833 ) ;; end setq
834 (call-process "/a/exe/lnf" nil nil nil "-T" "/nocow/user/.mufsf" (concat (getenv "HOME") "/.mu"))
835 (add-hook 'mu4e-compose-pre-hook 'my-mu4e-to-fsf)
836 (remove-hook 'mu4e-compose-pre-hook 'my-mu4e-to)
837 (mu4e)) ;; end defun fsf-mu4e
838
839
840 ;; it's implemented in mu4e, but not in the actions list for
841 ;; some reason.
842 (add-to-list 'mu4e-view-actions
843 '("browser view" . mu4e-action-view-in-browser) t)
844
845 ;; normally, you would add to this, but we want to
846 ;; modify unread messages. the first 4 are defined by default.
847 (setq mu4e-bookmarks
848 `( ,(make-mu4e-bookmark
849 :name "Unread messages"
850 ;; old less restrictive unread, for adapting in the future:
851 ;; flag:unread AND NOT flag:trashed AND NOT maildir:/Junk AND NOT maildir:/fwfw AND NOT maildir:/log
852 :query "flag:unread maildir:/INBOX"
853 :key ?u)
854 ,(make-mu4e-bookmark
855 :name "Today's messages"
856 :query "date:today..now"
857 :key ?t)
858 ,(make-mu4e-bookmark
859 :name "Last 7 days"
860 :query "date:7d..now"
861 :key ?w)
862 ,(make-mu4e-bookmark
863 :name "Messages with images"
864 :query "mime:image/*"
865 :key ?p))
866 )
867
868
869 (defun mu4e-action-msgs-by-this-sender (msg)
870 "In header view, view messages by the sender of the message under point."
871 (let ((from (mu4e-message-field msg :from)))
872 (unless from
873 (mu4e-error "No from header for this message"))
874 ;; from is structured like: (("Anacron" . "root@x2.lan"))
875 (mu4e-headers-search (concat "f:" (cdar from)))))
876
877 (add-to-list 'mu4e-headers-actions
878 '("from this sender" . mu4e-action-msgs-by-this-sender) t)
879 (add-to-list 'mu4e-view-actions
880 '("from this sender" . mu4e-action-msgs-by-this-sender) t)
881
882
883 ;;; elisp settings
884 ; when manually evaluating lisp, go into debugger on error
885 (setq eval-expression-debug-on-error t)
886 ;reminder of useful var: debug-on-error
887
888
889 ;;; haskell
890
891 ;; useful comint-shell mode commands. If not prefaced with *, it means it is not in the haskell custom repl
892 ;; *todo: setup haskell c-t toggle arrow keys
893 ;; tab completion
894 ;; C-q insert prev arg
895 ;; C-( history search
896 ;; c-m-left/right move to next/prev prompts
897 ;; *c-enter, multi-line input
898 ;; *s-delete, send input across windows. (i can implement this)
899 ;; *c-m-l clear screen
900 ;; *haskell-process-interrupt, c-cc terminate job (i can implement this maybe)
901
902 ;; nice bash/readline functions missing in comint:
903 ;; yank-nth-arg
904 ;; operate-get-next
905 ;; menu-complete
906
907 ;; usefull comint commands:
908 ;; c-cl : list historic command in temp buffer
909 ;; C-c C-o comint-delete-output
910 ;; comint-restore-input, todo: put this on a randomish c-c key
911
912
913
914 ;; todo:
915 ;; checkout haskell repl functions:
916 ;; c-cv haskell-check, hlint
917 ;; C-M-q prog-indent-sexp
918 ;; c-c. haskell-mode-format-imports
919 ;; C-c M-/ haskell-doc-check-active
920 ;; haskell-process-generate-tags
921 ;; haskell-process-cabal-build
922 ;; haskell-cabal-command.. or something
923 ;; haskell-process-restart
924 ;; C-h v haskell-process-log
925 ;; C-h v haskell-process-show-debug-tips
926
927 ;; various not immediately useful functions:
928 ;; haskell-process-add-dependency
929 ;; haskell-process-touch-buffer
930 ;; haskell-process-cd
931 ;; haskell-process-unignore
932 ;; haskell-process-reload-devel-main
933
934
935 ;; rebind
936 ;; home: C-a haskell-interactive-mode-beginning
937 ;; c-return: C-j haskell-interactive-mode-newline-indent
938 ;; up/down: <C-down> haskell-interactive-mode-history-next
939
940 ;; todo haskell mode better binds for:
941 ;; 'haskell-process-load-file
942 ;; 'haskell-process-do-type
943 ;; 'haskell-process-do-info
944 ;; 'inferior-haskell-send-decl
945
946
947 ;; commands which don't work in haskell-interactive-mode(hi) vs inferior-haskell-mode(ih, default)
948 ;; functions not in hi:
949 ;; inferior-haskell-find-definition, use tags instead
950 ;; inferior-haskell-find-haddock, todo, test if this works
951
952 ;; redefined ih to hi
953 ;; switch-to-haskell -> 'haskell-interactive-switch
954 ;; haskell-process-load-file -> inferior-haskell-load-file
955 ;; haskell-process-do-type -> inferior-haskell-type
956 ;; switch-to-haskell -> haskell-interactive-switch
957 ;; inferior-haskell-load-file -> 'haskell-process-load-file
958
959
960 ;; haskell-mode installation from source, based on its readme
961 ;; in the git directory,
962 ;; make all
963
964
965
966
967 ;; remove default option to not link the file
968 (setq haskell-compile-command "ghc -Wall -ferror-spans -fforce-recomp %s")
969 (add-hook 'haskell-indentation-mode-hook
970 (lambda ()
971 (define-key haskell-indentation-mode-map [?\C-d] nil)
972 (define-key haskell-indentation-mode-map
973 (kbd "<deletechar>")
974 'haskell-indentation-delete-char)))
975
976 ;;copied from haskell-mode docs in order to use the new, better, nondefault
977 ;;interactive mode.
978 (eval-after-load "haskell-mode"
979 '(progn
980 (define-key haskell-mode-map (kbd "C-x C-d") nil)
981 (define-key haskell-mode-map (kbd "C-c C-z") 'haskell-interactive-switch)
982 (define-key haskell-mode-map (kbd "C-c C-l") 'haskell-process-load-file)
983 (define-key haskell-mode-map (kbd "C-c C-b") 'haskell-interactive-switch)
984 (define-key haskell-mode-map (kbd "C-c C-t") 'haskell-process-do-type)
985 (define-key haskell-mode-map (kbd "C-c C-i") 'haskell-process-do-info)
986 (define-key haskell-mode-map (kbd "C-c M-.") nil)
987 (define-key haskell-mode-map (kbd "C-c C-d") nil)))
988
989 ;; ghc-mod install http://www.mew.org/~kazu/proj/ghc-mod/en/emacs.html
990 ;; todo, try this out
991 ;; (autoload 'ghc-init "ghc" nil t)
992 ;;(add-hook 'haskell-mode-hook (lambda () (ghc-init) (flymake-mode)))
993
994
995
996 ;; from the package readme for ghci-completion
997 (require 'ghci-completion)
998 (add-hook 'inferior-haskell-mode-hook 'turn-on-ghci-completion)
999
1000
1001 ;; disable some rebinds. they are set to appropriate keys in the keybinds section
1002 (eval-after-load "haskell-mode"
1003 '(progn
1004 (define-key haskell-mode-map (kbd "C-a") 'nil)
1005 (define-key haskell-mode-map (kbd "C-j") 'nil)))
1006
1007 (eval-after-load "python-mode"
1008 '(progn
1009 (define-key python-mode-map (kbd "C-j") nil)))
1010
1011 (defun pretty-lambdas-haskell ()
1012 (font-lock-add-keywords
1013 nil `((,(concat "(?\\(" (regexp-quote "\\") "\\)")
1014 (0 (progn (compose-region (match-beginning 1) (match-end 1)
1015 ,(make-char 'greek-iso8859-7 107))
1016 nil))))))
1017 ;; from haskell-mode manual
1018 (add-hook 'haskell-mode-hook 'turn-on-haskell-decl-scan)
1019 (when (window-system)
1020 (add-hook 'haskell-mode-hook 'pretty-lambdas-haskell))
1021
1022 ;; added from haskell-mode website install instructions
1023 ;(load "/usr/share/emacs/site-lisp/haskell-mode/haskell-site-file")
1024 (add-hook 'haskell-mode-hook 'turn-on-haskell-doc-mode)
1025 ;;the three indentation modules are mutually exclusive - add at most one. Trying out the "most advanced"
1026 (add-hook 'haskell-mode-hook 'turn-on-haskell-indentation)
1027 ;;(add-hook 'haskell-mode-hook 'turn-on-haskell-indent)
1028 ;;(add-hook 'haskell-mode-hook 'turn-on-haskell-simple-indent)
1029
1030
1031 ;; todo, set this to some other key
1032 ;; (local-set-key (kbd "C-e") 'my-haskell-load-and-run)
1033
1034 (defun my-haskell-load-and-run ()
1035 "Loads and runs the current Haskell file."
1036 (interactive)
1037 (let ((start-buffer (current-buffer)))
1038 (inferior-haskell-load-and-run inferior-haskell-run-command)
1039 (sleep-for 0 100)
1040 (end-of-buffer)
1041 (pop-to-buffer start-buffer)))
1042
1043 ;; show haskell function in mode line
1044 ;; todo, this broke after updating emacs
1045 ;;(eval-after-load "which-func"
1046 ;; '(add-to-list 'which-func-modes 'haskell-mode))
1047
1048
1049
1050 (add-hook 'interactive-haskell-mode-hook 'ac-haskell-process-setup)
1051 (add-hook 'haskell-interactive-mode-hook 'ac-haskell-process-setup)
1052 (eval-after-load "auto-complete"
1053 '(add-to-list 'ac-modes 'haskell-interactive-mode))
1054
1055 (add-hook 'haskell-mode-hook
1056 (lambda () (define-key haskell-mode-map (kbd "C-(")
1057 (lambda () (interactive)
1058 (basic-save-buffer)
1059 (haskell-compile)
1060 (run-with-timer .3 nil 'repeat-shell)))))
1061 (add-hook 'haskell-cabal-mode-hook
1062 (lambda () (define-key haskell-cabal-mode-map (kbd "C-(") 'haskell-compile)))
1063
1064
1065
1066 (add-hook 'haskell-interactive-mode-hook
1067 (lambda ()
1068 (define-key haskell-interactive-mode-map "\r" nil)
1069 (define-key haskell-interactive-mode-map (kbd "<return>") 'haskell-interactive-mode-return)))
1070 (add-hook 'haskell-indentation-mode-hook (lambda () (define-key haskell-indentation-mode-map "\r" nil)))
1071
1072
1073
1074 (add-hook 'haskell-interactive-mode-hook
1075 (lambda ()
1076 (define-key haskell-interactive-mode-map (kbd "<C-M-return>") 'haskell-interactive-mode-newline-indent)))
1077
1078 ;;; isearch
1079 (setq
1080 isearch-allow-scroll t
1081 search-ring-update t) ;; dont start an edit when going to previous search
1082
1083 (defun isearch-yank-regexp (regexp)
1084 "Pull REGEXP into search regexp."
1085 (let ((isearch-regexp nil)) ;; Dynamic binding of global.
1086 (isearch-yank-string regexp))
1087 (isearch-search-and-update))
1088
1089 (defun isearch-yank-symbol (&optional partialp backward)
1090 "Put symbol at current point into search string.
1091
1092 If PARTIALP is non-nil, find all partial matches."
1093 (interactive "P")
1094
1095 (let (from to bound sym)
1096 (setq sym
1097 ; this block taken directly from find-tag-default
1098 ; we couldn't use the function because we need the internal from and to values
1099 (when (or (progn
1100 ;; Look at text around `point'.
1101 (save-excursion
1102 (skip-syntax-backward "w_") (setq from (point)))
1103 (save-excursion
1104 (skip-syntax-forward "w_") (setq to (point)))
1105 (> to from))
1106 ;; Look between `line-beginning-position' and `point'.
1107 (save-excursion
1108 (and (setq bound (line-beginning-position))
1109 (skip-syntax-backward "^w_" bound)
1110 (> (setq to (point)) bound)
1111 (skip-syntax-backward "w_")
1112 (setq from (point))))
1113 ;; Look between `point' and `line-end-position'.
1114 (save-excursion
1115 (and (setq bound (line-end-position))
1116 (skip-syntax-forward "^w_" bound)
1117 (< (setq from (point)) bound)
1118 (skip-syntax-forward "w_")
1119 (setq to (point)))))
1120 (buffer-substring-no-properties from to)))
1121 (cond ((null sym)
1122 (message "No symbol at point"))
1123 ((null backward)
1124 (goto-char (1+ from)))
1125 (t
1126 (goto-char (1- to))))
1127 (isearch-search)
1128 (if partialp
1129 (isearch-yank-string sym)
1130 (isearch-yank-regexp
1131 (concat "\\_<" (regexp-quote sym) "\\_>")))))
1132
1133 (defun isearch-current-symbol (&optional partialp)
1134 "Incremental search forward with symbol under point.
1135
1136 Prefixed with \\[universal-argument] will find all partial
1137 matches."
1138 (interactive "P")
1139 (let ((start (point)))
1140 (isearch-forward-regexp nil 1)
1141 (isearch-yank-symbol partialp)))
1142 ;; todo, make this
1143
1144 (defun isearch-backward-current-symbol (&optional partialp)
1145 "Incremental search backward with symbol under point.
1146
1147 Prefixed with \\[universal-argument] will find all partial
1148 matches."
1149 (interactive "P")
1150 (let ((start (point)))
1151 (isearch-backward-regexp nil 1)
1152 (isearch-yank-symbol partialp)))
1153
1154
1155
1156 ; lets look through emacs starter kit before we throw this out.
1157
1158
1159 ; automatically wrap to the top of the buffer when isearch fails
1160 (defadvice isearch-search (after isearch-no-fail activate)
1161 (unless isearch-success
1162 (ad-disable-advice 'isearch-search 'after 'isearch-no-fail)
1163 (ad-activate 'isearch-search)
1164 (isearch-repeat (if isearch-forward 'forward))
1165 (ad-enable-advice 'isearch-search 'after 'isearch-no-fail)
1166 (ad-activate 'isearch-search)))
1167
1168 ;; Activate occur easily inside isearch
1169 (define-key isearch-mode-map (kbd "C-o")
1170 (lambda () (interactive)
1171 (let ((case-fold-search isearch-case-fold-search))
1172 (occur (if isearch-regexp
1173 isearch-string
1174 (regexp-quote isearch-string))))))
1175 ;;; lisp / elisp mode setings
1176
1177 (add-hook 'emacs-lisp-mode-hook 'starter-kit-remove-elc-on-save)
1178 (defun starter-kit-remove-elc-on-save ()
1179 "If you're saving an elisp file, likely the .elc is no longer valid."
1180 (make-local-variable 'after-save-hook)
1181 (add-hook 'after-save-hook
1182 (lambda ()
1183 (if (file-exists-p (concat buffer-file-name "c"))
1184 (delete-file (concat buffer-file-name "c"))))))
1185
1186
1187 (defun emacs-lisp-mode-defaults ()
1188 ;; checkdoc has an annoying feature that wants a header and footer
1189 ;; in every elisp buffer as if they all were packages
1190 ;; todo, see if there is a way
1191 ;; to make checkdoc usable instead of just disabling it as I do here
1192 (if (boundp 'flycheck-checkers)
1193 (setq flycheck-checkers (remove 'emacs-lisp-checkdoc flycheck-checkers)))
1194 (eldoc-mode 1))
1195 (add-hook 'emacs-lisp-mode-hook 'emacs-lisp-mode-defaults)
1196
1197 (define-key lisp-mode-map (kbd "<M-up>") 'backward-up-list)
1198 (define-key lisp-mode-map (kbd "<M-down>") 'down-list)
1199 (define-key emacs-lisp-mode-map (kbd "<M-up>") 'backward-up-list)
1200 (define-key emacs-lisp-mode-map (kbd "<M-down>") 'down-list)
1201 (define-key emacs-lisp-mode-map (kbd "<M-escape>") 'find-function-at-point)
1202
1203 ;; interactive modes don't need whitespace checks
1204 (defun interactive-lisp-coding-defaults ()
1205 (whitespace-mode -1))
1206 (setq prelude-interactive-lisp-coding-hook 'prelude-interactive-lisp-coding-defaults)
1207
1208
1209 ;; ielm is an interactive Emacs Lisp shell
1210 (defun ielm-mode-defaults ()
1211 (run-hooks 'prelude-interactive-lisp-coding-hook)
1212 (turn-on-eldoc-mode))
1213 (add-hook 'ielm-mode-hook 'ielm-mode-defaults)
1214
1215 ;;; mediawiki
1216
1217 (eval-after-load "mediawiki"
1218 '(progn
1219 (remove-hook 'outline-minor-mode-hook 'mediawiki-outline-magic-keys)
1220 (add-hook 'mediawiki-mode-hook
1221 (lambda () (define-key mediawiki-mode-map (kbd "C-(") 'mediawiki-save-reload)))
1222
1223 ;; mediawiki mode has a bug that it will claim an edit conflict unless you reload after saving.
1224 ;; I also like to save with no edit summary for previewing on my local mw instance
1225 (defun mediawiki-save-reload ()
1226 (interactive)
1227 (and (mediawiki-save "") (mediawiki-reload)))))
1228 ;;; modes with little configuration needed
1229 ;; busted:
1230 ;;(require 'csv-mode)
1231 ;;(add-to-list 'auto-mode-alist '("\\.[Cc][Ss][Vv]\\'" . csv-mode))
1232
1233 (require 'outshine)
1234 (add-hook 'outline-minor-mode-hook 'outshine-hook-function)
1235 (add-hook 'emacs-lisp-mode-hook 'outline-minor-mode)
1236 (add-hook 'sh-mode-hook 'outline-minor-mode)
1237
1238
1239
1240 (setq org-caldav-url "https://cal.iankelling.org"
1241 org-caldav-calendar-id "ian"
1242 org-caldav-inbox "/p/cal.org")
1243 ;;(org-caldav-sync)
1244
1245
1246 ;;(require 'dtrt-indent)
1247 ;;(setq dtrt-indent-mode t)
1248
1249 (setq css-indent-offset 2)
1250
1251 (load-file "/a/h/iank-mod.el")
1252
1253 ;; from when i was running my own patches
1254 ;;(add-to-list 'load-path "/a/opt/ws-butler")
1255
1256 (require 'ws-butler)
1257 ;; todo: I think this is broken, it keeps collapsing the last line
1258 ;; for empty messages.
1259
1260 ;; the main problem is when it deletes the blank line at the end
1261 ;; of a message with an empty body. but I might also
1262 ;; be pasting whitespace significant things in here, so
1263 ;; just don't do anything.
1264 ;; todo: propose this upstream
1265 (add-to-list 'ws-butler-global-exempt-modes 'message-mode)
1266
1267 (ws-butler-global-mode)
1268
1269
1270
1271 (require 'nginx-mode)
1272 ;;The mode should automatically activate for files called nginx.conf and files under /etc/nginx - if not, you can add something like this to your init file:
1273 ;;(add-to-list 'auto-mode-alist '("/etc/nginx/sites-available/.*" . nginx-mode))
1274
1275 ;; todo, put this on a hook with prog mode
1276 ;;(highlight-indentation-mode 1)
1277
1278 (add-hook 'auto-revert-tail-mode-hook
1279 (lambda ()
1280 (when (string=
1281 buffer-file-name
1282 "/var/log/cloudman/development/cm-service.log")
1283 (setq-local prev-auto-revert-max 0)
1284 ;; set buffer-local hook
1285 (add-hook 'after-revert-hook 'tail-colorize nil t))))
1286 (defun tail-colorize ()
1287 (ansi-color-apply-on-region prev-auto-revert-max (point-max))
1288 (setq-local prev-auto-revert-max (point-max)))
1289
1290
1291 ;; gnu global
1292 (require 'ggtags)
1293 (add-hook 'c-mode-common-hook
1294 (lambda () (ggtags-mode 1)
1295 (setq c-label-minimum-indentation 0)))
1296
1297 ;; specific to my unusual keybind setup, you may want to
1298 ;; pick different keys
1299 (define-key ggtags-mode-map (kbd "C-M-o") 'ggtags-find-tag-dwim)
1300 (define-key ggtags-mode-map (kbd "C-M-m") 'ggtags-grep)
1301
1302 (defun gtags-update-single(filename)
1303 "Update Gtags database for changes in a single file"
1304 (interactive)
1305 (start-process "update-gtags" "update-gtags" "bash" "-c" (concat "cd " ggtags-project-root " ; gtags --single-update " filename )))
1306
1307 (defun gtags-update-current-file()
1308 (interactive)
1309 (let ((rel-filename (replace-regexp-in-string
1310 ggtags-project-root "."
1311 (buffer-file-name (current-buffer)))))
1312 (gtags-update-single rel-filename)))
1313
1314 (defun gtags-update-hook()
1315 "Update GTAGS file incrementally upon saving a file"
1316 (when (and ggtags-mode ggtags-project-root)
1317 (gtags-update-current-file)))
1318
1319 (add-hook 'after-save-hook 'gtags-update-hook)
1320
1321 ;; i'd like to make some elisp which modifies a keymap to remove
1322 ;; all binds which don't match a predicate.
1323 ;; I tried setting a keymap to a new keymap,
1324 ;; but that didn't register as functional.
1325 ;; so I'd need to modify the list in place.
1326
1327 (require 'magit)
1328
1329
1330 ;; colorize hex colors: use rainbow mode
1331
1332
1333 ;; message mode prompted me on first message.
1334 ;; a function which describes options then sets this
1335 ;; the other options were to use smtp directly or pass to another mail client
1336 ;; here we use the standard sendmail interface, which I use postfix for
1337 (setq send-mail-function (quote sendmail-send-it))
1338
1339 (require 'spray)
1340 (global-set-key (kbd "C-M-w") 'spray-mode)
1341 ;; remember, h/l = move. f/s = faster/slower, space = pause, all others quit
1342
1343 ;; delete active selection with self-insert commands
1344 (delete-selection-mode t)
1345
1346 ;; Transparently open compressed files
1347 (auto-compression-mode t)
1348
1349 ;; Highlight matching parenthesesq when the pointq is on them.
1350 ;; not needed since smart paren mode?
1351 ;; (show-paren-mode 1)
1352
1353
1354 ;; not documented, but looking at the source, I find this
1355 ;; stops me from being asked what command on every C-c-c
1356 ;; when doing a latex document.
1357 (setq TeX-command-force "LaTeX")
1358
1359 ;; dot mode, repeats last action
1360 (require 'dot-mode)
1361 (add-hook 'find-file-hooks 'dot-mode-on)
1362
1363
1364 ;; clean up obsolete buffers automatically at midnight
1365 (require 'midnight)
1366
1367
1368 ;; disabled because it takes 400ms on startup
1369 ;; ;; emacs regexes are too limited.
1370 ;; (require 'foreign-regexp)
1371 ;; ;; perl is most powerful, but javascript is pretty close and
1372 ;; ;; I'd rather know javascript stuff than perl
1373 ;; (custom-set-variables
1374 ;; '(foreign-regexp/regexp-type 'javascript) ;; Choose by your preference.
1375 ;; '(reb-re-syntax 'foreign-regexp)) ;; Tell re-builder to use foreign regexp.
1376 ;; ;; it would be nice to add documentation to do this for more commands to that package
1377 ;; ;; disabled because it's too slow. but I'd still m-x it for advanced replacements
1378 ;; ;;(define-key global-map [remap isearch-forward-regexp] 'foreign-regexp/isearch-forward)
1379
1380
1381 ;; saner regex syntax
1382 (require 're-builder)
1383 (setq reb-re-syntax 'string)
1384
1385
1386 ;; use shift + arrow keys to switch between visible buffers
1387 ;; todo, set these keys to something else
1388 (require 'windmove)
1389 (windmove-default-keybindings)
1390
1391
1392 ;; show the name of the current function definition in the modeline
1393 (require 'which-func)
1394 (setq which-func-modes t)
1395 (which-function-mode 1)
1396
1397
1398 ;; enable winner-mode to manage window configurations
1399 (winner-mode +1)
1400
1401 ;; meaningful names for buffers with the same name
1402 (require 'uniquify)
1403 (setq uniquify-buffer-name-style 'forward
1404 uniquify-separator "/"
1405 ;; for sdx work. until I figure out a better way.
1406 ;; maybe something like projectile can do it,
1407 ;; or hacking around the status bar
1408 uniquify-min-dir-content 2
1409 uniquify-after-kill-buffer-p t ; rename after killing uniquified
1410 uniquify-ignore-buffers-re "^\\*") ; don't muck with special buffers
1411
1412
1413 ;; makefiles require tabs
1414 ;; todo: find a makefile indent function that works,
1415 ;; best I could find is this one which means don't indent at all
1416 ;;
1417 (add-hook 'makefile-mode-hook
1418 (lambda ()
1419 (setq indent-tabs-mode t)
1420 (setq indent-line-function (lambda () 'no-indent))))
1421
1422
1423 ;; todo, turn on auto-fill just for txt files
1424 ;;(add-hook 'text-mode-hook 'turn-on-auto-fill)
1425 (add-hook 'text-mode-hook 'turn-on-flyspell)
1426
1427
1428 ;; auto indent shell script comments
1429 (setq sh-indent-comment t)
1430
1431 ;; random extra highlights
1432 (require 'volatile-highlights)
1433 (volatile-highlights-mode t)
1434
1435
1436 ;; make help buffers smaller when it makes sense
1437 (temp-buffer-resize-mode 1)
1438
1439
1440 (require 'info+)
1441 ;; based on suggestions in info+.el, I also installed misc-fns, strings, and thingatpt+
1442 ;; remove some bad keybinds from info+
1443 (define-key Info-mode-map [mouse-4] nil)
1444 (define-key Info-mode-map [mouse-5] nil)
1445
1446
1447 (require 'smooth-scroll)
1448 ;; long gnus summary buffers lags too much with this,
1449 ;; but I like it enough to leave it enabled by default
1450 ;; and crank up the step size to be faster
1451 ;; and it doesn't have a way to enable it only for certain modes etc.
1452 ;; todo sometime, make it work for certain modes only
1453 (smooth-scroll-mode t)
1454 ;; its too slow with the default of 2
1455 (setq smooth-scroll/vscroll-step-size 7)
1456 ;; sublimity doesn't work as good going fast by default
1457 ;; smooth-scrolling.el, does not do smooth scrolling. its about cursor location
1458
1459
1460 (setq sh-here-document-word "'EOF'")
1461
1462 (setq tramp-default-method "ssh")
1463 ;;; misc general settings
1464
1465 ;; https://www.emacswiki.org/emacs/FillParagraph
1466 ;; make list items start paragraphs.
1467 (setq paragraph-start "\f\\|[ \t]*$\\|[ \t]*[-+*] ")
1468
1469 (setq sh-basic-offset 2)
1470 (setq vc-follow-symlinks t)
1471
1472 ;; give us a shell to start instead of scratch
1473 ;;(setq initial-buffer-choice (lambda () (new-shell)))
1474
1475 ;; disable this nasty function, as I always use a gui
1476 (defun suspend-frame() (interactive))
1477
1478 ;; Seed the random-number generator
1479 (random t)
1480
1481 ;; easier to remember than keybinds
1482 (defalias 'scrypt 'mml-secure-message-encrypt-pgpmime)
1483 (defalias 'sign 'mml-secure-message-sign-pgpmime)
1484 (defun encrypt ()
1485 (interactive)
1486 (mml-secure-message-encrypt-pgpmime 'dontsign))
1487
1488 ;; don't highlight the region.
1489 (set-face-background 'region nil)
1490
1491 ;; this fixes save error for python example code
1492 (define-coding-system-alias 'UTF-8 'utf-8)
1493
1494 ;; i don't use frame titles, but if I ever do
1495 ;; this starter kit setting is probably good
1496 (if window-system (setq frame-title-format '(buffer-file-name "%f" ("%b"))))
1497
1498
1499 ;;(prefer-coding-system 'utf-8-unix)
1500
1501 ;; remove ugly 3d box feature
1502 (set-face-attribute 'mode-line nil :box nil)
1503
1504 (add-to-list 'default-frame-alist
1505 '(font . "DejaVu Sans Mono-11"))
1506 ; the default will jump 2 sizes.
1507 (setq text-scale-mode-step 1.1)
1508 (setq font-lock-maximum-decoration t
1509 inhibit-startup-message t
1510 transient-mark-mode t
1511 delete-by-moving-to-trash t
1512 shift-select-mode nil
1513 truncate-partial-width-windows nil
1514 uniquify-buffer-name-style 'forward
1515 oddmuse-directory "~/.emacs.d/oddmuse"
1516 echo-keystrokes 0.1
1517 mark-ring-max 160
1518 sort-fold-case t ; case insensitive line sorting
1519 global-mark-ring-max 1000
1520 ;; the visible bell seems to lag the ui
1521 ;;visible-bell t
1522 ;; turn off audible bell
1523 ;; https://www.emacswiki.org/emacs/AlarmBell
1524 ring-bell-function 'ignore
1525 case-replace nil
1526 revert-without-query '(".*")
1527 ;; don't pause display code on input.
1528 ;; smoother display performance at slight cost of input performance
1529 redisplay-dont-pause t
1530 font-lock-maximum-decoration t) ; probably default and not necesary
1531
1532
1533 (setq-default indent-tabs-mode nil ;; don't use tabs to indent
1534 cursor-type 'box
1535 fill-column 72
1536
1537 ;; wrap at word boundaries instead of mid-word
1538 word-wrap t
1539 imenu-auto-rescan t
1540 indicate-empty-lines t) ; mark end of buffer
1541
1542
1543 (blink-cursor-mode '(-4))
1544 (menu-bar-mode -1)
1545 (tool-bar-mode -1)
1546
1547
1548 ;; enable various commands
1549 (put 'narrow-to-region 'disabled nil)
1550 (put 'narrow-to-page 'disabled nil)
1551 (put 'narrow-to-defun 'disabled nil)
1552 (put 'upcase-region 'disabled nil)
1553 (put 'downcase-region 'disabled nil)
1554 (put 'scroll-left 'disabled nil)
1555 ;; these from graphene, haven't read about them yet
1556 (put 'ido-complete 'disabled nil)
1557 (put 'ido-exit-minibuffer 'disabled nil)
1558 (put 'dired-find-alternate-file 'disabled nil)
1559 (put 'autopair-newline 'disabled nil)
1560
1561
1562
1563 ;;disable and minimize various prompts/messages
1564 (fset 'yes-or-no-p 'y-or-n-p)
1565 (setq confirm-nonexistent-file-or-buffer nil
1566 inhibit-startup-message t
1567 inhibit-startup-echo-area-message t
1568 inhibit-startup-screen t
1569 compilation-read-command nil ;; just don't compile with unsafe file local vars
1570 kill-buffer-query-functions (remq 'process-kill-buffer-query-function
1571 kill-buffer-query-functions))
1572
1573
1574 ;; exit without bothering me
1575 ;; http://stackoverflow.com/questions/2706527/make-emacs-stop-asking-active-processes-exist-kill-them-and-exit-anyway/2708042#2708042
1576 (add-hook 'comint-exec-hook
1577 (lambda () (set-process-query-on-exit-flag (get-buffer-process (current-buffer)) nil)))
1578 ;; based on save-buffers-kill-emacs help string, don't ask about clients when exiting
1579 ;; apparently this would need to be in some later hook. dunno where is best, but this works
1580 (defadvice save-buffers-kill-emacs (before no-client-prompt-advice activate)
1581 (setq kill-emacs-query-functions (delq 'server-kill-emacs-query-function kill-emacs-query-functions)))
1582
1583
1584
1585 ;; (custom-set-faces
1586 ;; ;; setting header-line-format to " " as a hack for a top margin the oly thning I could find to do a top margin
1587 ;; '(header-line ((t (:background "default" :foreground "default" :overline nil :underline nil))))
1588 ;; ;; don't highlight the region
1589 ;; '(region ((t nil))))
1590 (setq-default header-line-format " ")
1591
1592
1593 (setq initial-scratch-message nil)
1594
1595
1596 ;; vertical margin background.
1597 ;; google turned up: http://lists.gnu.org/archive/html/help-gnu-emacs/2014-03/msg00544.html
1598 ;; the xresource doesn't work for me, probably an xmonad thing.
1599
1600 ;; figured out I needed to customize the header line face. To find the face, M-x list-faces-display or just google / search
1601 ;; info,
1602 ;; then M-x customize-face
1603 ;; header-line
1604 ;; unchecked some stuff so that it inherits from default.
1605
1606 ;;; misc function definitions
1607
1608
1609 (defun fill-buffer ()
1610 (interactive)
1611 (save-mark-and-excursion
1612 (beginning-of-buffer)
1613 (while (= (forward-line) 0)
1614 (fill-paragraph))))
1615
1616
1617 (defun next-backup-dir ()
1618 "In a directory listing from rsync -n,
1619 Go to the next directory based on where the cursor is."
1620 (interactive)
1621 (let* ((start-col (current-column))
1622 (end-col (progn (skip-chars-forward "^/\n") (current-column)))
1623 (dir (progn
1624 (beginning-of-line 1)
1625 (buffer-substring-no-properties (point) (+ (point) end-col)))))
1626 (message dir)
1627 (forward-line 1)
1628 (while (and (not (eobp))
1629 (string= dir (buffer-substring-no-properties (point) (+ (point) end-col))))
1630 (forward-line 1))
1631 (forward-char-same-line start-col)))
1632 ;; copy paste this for fast keybind
1633 ;;(local-set-key (kbd "<kp-enter>"))
1634
1635
1636 (defun goto-buffer-or-find-file (file-name)
1637 "If buffer is with FILE-NAME exists, go to it, else open the file using full path."
1638 (interactive)
1639 (let ((b (get-buffer (file-name-nondirectory file-name))))
1640 (if b
1641 (switch-to-buffer b)
1642 (find-file file-name))))
1643
1644
1645
1646
1647 ;; todo, i think this is broken. perhaps the last goto-char is not accounting for buffer or something
1648 (defun unpop-global-mark ()
1649 "Unpop off global mark ring. Does nothing if mark ring is empty."
1650 (interactive)
1651 (when global-mark-ring
1652 (setq global-mark-ring (cons (copy-marker (mark-marker)) global-mark-ring))
1653 (let ((lm (car (last global-mark-ring))))
1654 (set-marker (mark-marker) (marker-position lm) (marker-buffer lm)))
1655 (when (null (mark t)) (ding))
1656 (setq global-mark-ring (nbutlast global-mark-ring))
1657 (goto-char (marker-position (mark-marker)))))
1658
1659 (defun indent-buffer ()
1660 "Indents the entire buffer."
1661 (interactive)
1662 (cond ((derived-mode-p 'org-mode)
1663 (org-indent-region (point-min) (point-max)))
1664 ((derived-mode-p 'python-mode)
1665 (py-autopep8))
1666 (t
1667 (indent-region (point-min) (point-max)))))
1668
1669
1670 ;; TODO doesn't work with uniquify
1671 (defun rename-file-and-buffer ()
1672 "Renames current buffer and file it is visiting."
1673 (interactive)
1674 (let ((name (buffer-name))
1675 (filename (buffer-file-name)))
1676 (if (not (and filename (file-exists-p filename)))
1677 (message "Buffer '%s' is not visiting a file!" name)
1678 (let ((new-name (read-file-name "New name: " filename)))
1679 (cond ((get-buffer new-name)
1680 (message "A buffer named '%s' already exists!" new-name))
1681 (t
1682 (rename-file name new-name 1)
1683 (rename-buffer new-name)
1684 (set-visited-file-name new-name)
1685 (set-buffer-modified-p nil)))))))
1686
1687
1688
1689 (defun sudo-edit (&optional arg)
1690 (interactive "P")
1691 (if (or arg (not buffer-file-name))
1692 (find-file (concat "/sudo::" (ido-read-file-name "File: ")))
1693 (find-alternate-file (concat "/sudo::" buffer-file-name))))
1694
1695
1696
1697 (defun backward-symbol (arg)
1698 (interactive "p")
1699 (forward-symbol (- arg)))
1700
1701 ;;; mode line
1702 ;; make window title be the buffer name
1703 (setq frame-title-format "%b")
1704
1705 ; -----------------------------
1706 ; fixing up the mode line
1707 ; modified from mastering emacs blog
1708 ; ----------------------------
1709
1710 (defvar mode-line-cleaner-alist
1711 `((auto-complete-mode . "")
1712 (yas/minor-mode . "")
1713 (paredit-mode . "")
1714 (auto-fill-function . "")
1715 (eldoc-mode . "")
1716 (abbrev-mode . "")
1717 (flyspell-mode . "")
1718 (glasses-mode . "")
1719 (dot-mode . "")
1720 (yas-global-mode . "")
1721 (yas-minor-mode . "")
1722 (undo-tree-mode . "")
1723 (volatile-highlights-mode . "")
1724 (highlight-symbol-mode . "")
1725 ;; Major modes
1726 (lisp-interaction-mode . "λ")
1727 (hi-lock-mode . "")
1728 (python-mode . "Py")
1729 (emacs-lisp-mode . "EL")
1730 (nxhtml-mode . "nx"))
1731 "Alist for `clean-mode-line'.
1732
1733 When you add a new element to the alist, keep in mind that you
1734 must pass the correct minor/major mode symbol and a string you
1735 want to use in the modeline *in lieu of* the original.")
1736
1737
1738 (defun clean-mode-line ()
1739 (interactive)
1740 (loop for cleaner in mode-line-cleaner-alist
1741 do (let* ((mode (car cleaner))
1742 (mode-str (cdr cleaner))
1743 (old-mode-str (cdr (assq mode minor-mode-alist))))
1744 (when old-mode-str
1745 (setcar old-mode-str mode-str))
1746 ;; major mode
1747 (when (eq mode major-mode)
1748 (setq mode-name mode-str)))))
1749
1750 ; disabled
1751 ; (add-hook 'after-change-major-mode-hook 'clean-mode-line)
1752
1753
1754 ;;; alias the new `flymake-report-status-slim' to
1755 ;;; `flymake-report-status'
1756 (defalias 'flymake-report-status 'flymake-report-status-slim)
1757 (defun flymake-report-status-slim (e-w &optional status)
1758 "Show \"slim\" flymake status in mode line."
1759 (when e-w
1760 (setq flymake-mode-line-e-w e-w))
1761 (when status
1762 (setq flymake-mode-line-status status))
1763 (let* ((mode-line " Φ"))
1764 (when (> (length flymake-mode-line-e-w) 0)
1765 (setq mode-line (concat mode-line ":" flymake-mode-line-e-w)))
1766 (setq mode-line (concat mode-line flymake-mode-line-status))
1767 (setq flymake-mode-line mode-line)
1768 (force-mode-line-update)))
1769
1770
1771 (defun my-after-change-major-mode-hook ()
1772 (setq mode-line-mule-info nil
1773 minor-mode-alist nil
1774 mode-line-position nil)) ; todo, make only flymake status show up
1775
1776 (add-hook 'after-change-major-mode-hook 'my-after-change-major-mode-hook)
1777
1778 ;;; mouse related
1779 ;;;; settings
1780 (setq focus-follows-mouse t
1781 mouse-autoselect-window t
1782 xterm-mouse-mode t)
1783 ;;;; move-mouse-to-point
1784 ;; todo, this is buggy with multiple windows open.
1785 (defun move-mouse-to-point ()
1786 (interactive)
1787 (let* ((pos (posn-col-row (posn-at-point)))
1788 (x (+ (car pos) 2)) ; no idea why this is off by 1-2
1789 (y (cdr pos)))
1790 (set-mouse-position (selected-frame) x y)))
1791
1792 ;;; org mode
1793
1794 ;; todo work on org-cycle-emulate-tab
1795
1796 ;; todo, this doesn't work for a non-standard keybind
1797 ;;(setq org-special-ctrl-k t)
1798
1799 ;; todo, generally fix org mode keys
1800 ;; todo, org-mark-element, unbdind from M-h, bind to mark defun key
1801
1802 ;(org-babel-do-load-languages
1803 ; 'org-babel-load-languages
1804 ; '((emacs-lisp . t)
1805 ; (sh . t)))
1806
1807
1808
1809 ;; make shell work like interactive bash shell
1810 (setq org-babel-default-header-args:sh
1811 '((:results . "output") (:shebang . "#!/bin/bash -l")))
1812
1813 ;; my patch to output stderr
1814 (setq org-babel-use-error-buffer nil)
1815
1816 ;
1817 ;; org-mode manual suggests these, but I haven't used them.
1818 ;;(global-set-key "\C-cl" 'org-store-link)
1819 ;;(global-set-key "\C-ca" 'org-agenda)
1820 ;; this got in the way of a haskell mode command
1821 ;;(global-set-key "\C-cb" 'org-iswitchb)
1822
1823
1824
1825 ;; org-src-tab-acts-natively t ; broken option. using next instead, todo fix
1826
1827 (setq org-src-fontify-natively t ; make babel blocks nice
1828 org-adapt-indentation nil
1829 org-src-preserve-indentation t
1830 ;; The most basic logging is to keep track of when a TODO item was finished.
1831 org-log-done 'time
1832 ;; use a drawer to keep the logs tidy
1833 org-log-into-drawer t
1834 org-extend-today-until 0
1835 org-startup-truncated nil
1836 org-clock-persist t
1837 org-clock-mode-line-total 'today
1838 ;; global STYLE property values for completion
1839 org-global-properties (quote (("STYLE_ALL" . "habit")))
1840 org-special-ctrl-a/e t ;; home and end work special in headlines
1841 org-completion-use-ido t
1842 org-catch-invisible-edits 'smart)
1843
1844 ;; non universally recommended settings
1845 (setq
1846 org-default-notes-file (concat org-directory "/a/t.org")
1847 org-agenda-files (quote ("/a/t.org"))
1848 org-mobile-directory "/p/org-mobile"
1849 org-mobile-inbox-for-pull "/p/from-mobile.org"
1850 org-directory "/p")
1851
1852 ;; modeilne populated from (org-clock-get-clocked-time)
1853 ;; which is populated from the var org-clock-total-time
1854 ;; which is populated by a function which starts from (org-clock-get-sum-start)
1855 ;;
1856
1857 (org-clock-persistence-insinuate)
1858
1859
1860 (defun time-to-org-day (time)
1861 (round (time-to-number-of-days
1862 (time-subtract time (list 0 (* 3600 org-extend-today-until) 0)))))
1863
1864
1865 (defun my-org-confirm-babel-evaluate (lang body)
1866 (not (or (string= (buffer-file-name) "/a/t.org")
1867 (string= (buffer-file-name) "/home/iank/.emacs.d/my-init.org")
1868 )))
1869 (setq org-confirm-babel-evaluate 'my-org-confirm-babel-evaluate)
1870
1871
1872 (defun org-time-stamp-with-time (arg)
1873 (interactive "P")
1874 ;; '(4) is the argument passed by universal prefix
1875 (org-time-stamp (if arg arg '(4)) t))
1876
1877 (defun ian-org-work-time ()
1878 (interactive)
1879 (save-excursion
1880 (set-buffer "t.org")
1881 (goto-char (org-find-entry-with-id "ian-identifier-1"))
1882 (org-clock-in)))
1883
1884 (defun ian-org-idle-time ()
1885 (interactive)
1886 (save-excursion
1887 (goto-char (org-find-entry-with-id "ian-identifier-2"))
1888 (set-buffer "t.org")
1889 (org-clock-in)))
1890
1891
1892
1893 ;; based on http://stackoverflow.com/questions/3758139/variable-pitch-for-org-mode-fixed-pitch-for-tables
1894 ;; keywords: proportional font, monospace
1895
1896 (defun variable-pitch-on ()
1897 (variable-pitch-mode 1))
1898 (add-hook 'fundamental-mode-hook 'variable-pitch-on)
1899 (add-hook 'org-mode-hook 'variable-pitch-on)
1900 (add-hook 'text-mode-hook 'variable-pitch-on)
1901 (defun variable-pitch-off ()
1902 (variable-pitch-mode 0))
1903 (add-hook 'yaml-mode-hook 'variable-pitch-off)
1904
1905
1906 (set-face-attribute 'org-table nil :family (face-attribute 'fixed-pitch :family))
1907 (set-face-attribute 'org-code nil :family (face-attribute 'fixed-pitch :family))
1908 (set-face-attribute 'org-formula nil :family (face-attribute 'fixed-pitch :family))
1909 (set-face-attribute 'org-link nil :family (face-attribute 'fixed-pitch :family))
1910 (set-face-attribute 'org-block nil :family (face-attribute 'fixed-pitch :family))
1911 (set-face-attribute 'org-date nil :family (face-attribute 'fixed-pitch :family))
1912
1913
1914 (defun remove-org-binds ()
1915 (define-key org-mode-map (kbd "<M-return>") nil)
1916 (define-key org-mode-map (kbd "C-'") nil)
1917 (define-key org-mode-map (kbd "C-y") nil)
1918 (define-key org-mode-map (kbd "<C-return>") nil)
1919 (define-key org-mode-map (kbd "<C-M-kp-enter>") nil)
1920 (define-key org-mode-map (kbd "C-,") nil)
1921 (define-key org-mode-map (kbd "C-M-m") nil)
1922 (define-key org-mode-map (kbd "C-k") nil)
1923 (define-key org-mode-map (kbd "C-j") nil)
1924 (define-key org-mode-map (kbd "C-M-i") nil)
1925 (define-key org-mode-map (kbd "C-M-t") nil)
1926 (define-key org-mode-map (kbd "M-a") 'nil)
1927 (define-key org-mode-map (kbd "C-a") nil)
1928 (define-key org-mode-map (kbd "M-e") nil)
1929 (define-key org-mode-map (kbd "C-e") nil)
1930 (define-key org-mode-map (kbd "C-3") nil)
1931 (define-key org-mode-map (kbd "<M-left>") nil)
1932 (define-key org-mode-map (kbd "<M-right>") nil)
1933 (define-key org-mode-map (kbd "<S-return>") nil)
1934 (define-key org-mode-map (kbd "<tab>") nil)
1935 (define-key org-mode-map (kbd "<C-S-down>") nil)
1936 (define-key org-mode-map (kbd "<C-S-up>") nil)
1937 (define-key org-mode-map (kbd "<S-down>") nil)
1938 (define-key org-mode-map (kbd "<S-up>") nil)
1939 (define-key org-mode-map "\t" nil))
1940 (add-hook 'org-mode-hook 'remove-org-binds)
1941
1942 ;;; prog-mode-defaults
1943
1944
1945 (defun prog-mode-defaults ()
1946 "Default coding hook, useful with any programming language."
1947 ;; so that I can do completion before the dialog pops up
1948 (local-set-key (kbd "<tab>") 'auto-complete)
1949 ;; todo, this is causing error message on loading file, prolly not working
1950 ;;(flycheck-mode +1)
1951 (setq ac-sources (delq 'ac-source-dictionary ac-sources))
1952 (highlight-symbol-mode)
1953 (make-local-variable 'column-number-mode)
1954 ;; this says do autofilling using newcomment.el. The "only" is a misnomer.
1955 (set (make-local-variable 'comment-auto-fill-only-comments) t)
1956 (column-number-mode t)
1957 (turn-on-smartparens-mode)
1958
1959 ;; prettify lambdas
1960 (font-lock-add-keywords
1961 nil `(("(\\(lambda\\>\\)"
1962 (0 (progn (compose-region (match-beginning 1) (match-end 1)
1963 ,(make-char 'greek-iso8859-7 107))
1964 nil))))))
1965 (add-hook 'prog-mode-hook 'prog-mode-defaults)
1966
1967 ;; enable flyspell in prog mode. text mode is handled
1968 (add-hook 'prog-mode-hook 'flyspell-prog-mode)
1969
1970
1971
1972 ;;; yank auto-indent
1973 ;; automatically indenting yanked text if in programming-modes
1974 (defvar yank-indent-modes
1975 '(LaTeX-mode TeX-mode)
1976 "Modes in which to indent regions that are yanked (or yank-popped).
1977 Only modes that don't derive from `prog-mode' should be listed here.")
1978
1979 (defvar yank-indent-blacklisted-modes
1980 '(python-mode slim-mode haml-mode)
1981 "Modes for which auto-indenting is suppressed.")
1982
1983 (defvar yank-advised-indent-threshold 2000
1984 "Threshold (# chars) over which indentation does not automatically occur.")
1985
1986 (defun yank-advised-indent-function (beg end)
1987 "Do indentation, as long as the region isn't too large."
1988 (if (<= (- end beg) yank-advised-indent-threshold)
1989 (indent-region beg end nil)))
1990
1991 (defadvice yank (after yank-indent activate)
1992 "If current mode is one of 'yank-indent-modes,
1993 indent yanked text (with prefix arg don't indent)."
1994 (if (and (not (ad-get-arg 0))
1995 (not (member major-mode yank-indent-blacklisted-modes))
1996 (or (derived-mode-p 'prog-mode)
1997 (member major-mode yank-indent-modes)))
1998 (let ((transient-mark-mode nil))
1999 (yank-advised-indent-function (region-beginning) (region-end)))))
2000
2001 (defadvice yank-pop (after yank-pop-indent activate)
2002 "If current mode is one of 'yank-indent-modes,
2003 indent yanked text (with prefix arg don't indent)."
2004 (if (and (not (ad-get-arg 0))
2005 (not (member major-mode yank-indent-blacklisted-modes))
2006 (or (derived-mode-p 'prog-mode)
2007 (member major-mode yank-indent-modes)))
2008 (let ((transient-mark-mode nil))
2009 (yank-advised-indent-function (region-beginning) (region-end)))))
2010
2011
2012 ;;; shell mode
2013 ;; avoid stupid git crap like "warning, terminal not fully functional"
2014 (setenv "PAGER" "cat")
2015 ;; don't store successive duplicates in comint command history
2016 (setq comint-input-ignoredups t)
2017
2018 (defun add-mode-line-dirtrack ()
2019 (add-to-list 'mode-line-buffer-identification
2020 '(:propertize (" " default-directory " ") face dired-directory)))
2021 (add-hook 'shell-mode-hook 'add-mode-line-dirtrack)
2022
2023
2024 ;; don't fully understand it, but it works.
2025 ;; http://www.emacswiki.org/emacs/ShellDirtrackByProcfs
2026 (defun track-shell-directory/procfs ()
2027 (shell-dirtrack-mode 0)
2028 (add-hook 'comint-preoutput-filter-functions
2029 (lambda (str)
2030 (prog1 str
2031 (when (string-match comint-prompt-regexp str)
2032 (cd (file-symlink-p
2033 (format "/proc/%s/cwd" (process-id
2034 (get-buffer-process
2035 (current-buffer)))))))))
2036 nil t))
2037 (setq comint-buffer-maximum-size 100000)
2038 (add-to-list 'comint-output-filter-functions 'comint-truncate-buffer)
2039 (defun new-shell ()
2040 (interactive)
2041 (shell (generate-new-buffer-name "*shell*")))
2042 ;;
2043 (defun shell-wrap (prefix)
2044 "wrap the shell function, automatically generate a new name for a prefix arg"
2045 (interactive "P")
2046 (if prefix
2047 (new-shell)
2048 (shell)))
2049
2050 (add-hook 'shell-mode-hook 'track-shell-directory/procfs)
2051 ;;; smartparens
2052 ;; the melpa git version had a catastrophic bug I reported.
2053 ;; downgraded to marmalade version and everything is working fine.
2054 (require 'smartparens-config)
2055 (show-smartparens-global-mode t)
2056
2057
2058 (defun gp/sp/pair-on-newline-and-indent (id action context)
2059 "Open a new brace or bracket expression, with relevant newlines and indent. "
2060 (save-excursion
2061 (newline)
2062 (indent-according-to-mode))
2063 (indent-according-to-mode))
2064
2065 ;; when opening a pair, and then inserting a newline, push the closing pair to another newline
2066 (sp-pair "{" nil :post-handlers
2067 '(:add ((lambda (id action context)
2068 (gp/sp/pair-on-newline-and-indent id action context)) (kbd "<return>"))))
2069 (sp-pair "[" nil :post-handlers
2070 '(:add ((lambda (id action context)
2071 (gp/sp/pair-on-newline-and-indent id action context)) (kbd "<return>"))))
2072
2073
2074 ;; in my version, this is not a pairing.
2075 ;; not sure if it is in a future version since I reverted to marmalade
2076 ;; Don't need c-comments in strings -- they frustrate filename globs
2077 ;; (sp-pair "/*" nil :unless '(sp-in-string-p))
2078
2079 ;; Don't need quotes to pair next to words
2080 (sp-pair "\"" nil :unless '(sp-point-before-word-p sp-point-after-word-p))
2081 (sp-pair "'" nil :unless '(sp-point-before-word-p sp-point-after-word-p))
2082
2083
2084 ;; todo, testout these mode specific settings from graphene.
2085 ;; Ruby-specific pairs and handlers
2086 (require 'smartparens-ruby)
2087
2088 ;; Markdown
2089 (sp-local-pair '(markdown-mode gfm-mode) "*" "*"
2090 :unless '(sp-in-string-p)
2091 :actions '(insert wrap))
2092
2093 ;; Except in HTML
2094 (sp-local-pair 'html-mode "\"" nil :unless '(:rem sp-point-after-word-p))
2095
2096
2097 ;;; smex
2098 ;; todo; check out smex-show-unbound-commands shows frequently used commands that have no key bindings.
2099 ; these must be before smex-initialize
2100 (setq
2101 smex-save-file "~/.emacs.d/.smex-items")
2102
2103 (smex-initialize)
2104 ;;; spell correction
2105 (setq
2106 ispell-program-name "hunspell"
2107 ispell-silently-savep t) ; don't prompt to save personal dictionary
2108
2109 (require 'rw-hunspell)
2110 ;; rw-hunspell sets up hunspell dictionary automagically.
2111
2112
2113 ;; Rant: Hunspell SHOULD be standard. its used by firefox and openoffice and
2114 ;; osx. In contrast, the first few words I added to aspell dictionary were
2115 ;; "emacs" "customizable" and "timestamp". Hunspell already has those,
2116 ;; thank god.
2117
2118 ;; ispell-personal-dictionary does not document where the hunspell
2119 ;; dictionary goes by default, but it is ~/.hunspell_en_US for me
2120
2121
2122 ;;; tex
2123 (setq-default TeX-PDF-mode t) ; use pdf
2124
2125 ; more sensible defaults based on info manual quickstart
2126 (setq TeX-auto-save t)
2127 (setq TeX-parse-self t)
2128
2129
2130 ;;; undo tree
2131
2132 ;; undo-tree checks for minor modes which override
2133 ;; its minor mode keymap, and sets global keybinds if
2134 ;; that happens. this will prevent that, but I have no
2135 ;; reason to do that, so it is commented.
2136 ;; (defun undo-tree-overridden-undo-bindings-p () nil)
2137
2138 ;; todo, send patch undo-tree-visualize should scroll with the scroll key, instead of just pgup pgdn (aka next/prior)
2139 (global-undo-tree-mode)
2140 ;; disabled due to bug, something like unknown entry in undo tree canary
2141 ;; (setq undo-tree-auto-save-history t)
2142 (setq undo-outer-limit 100000000 ; per undo command
2143 undo-limit 500000000 ; undo history limit
2144 undo-strong-limit 600000000) ; undo history limit plus some extra
2145
2146
2147 ;;; visible mark mode
2148
2149 ;; since it is not easy to change the mark overlay priority, I change this one.
2150 (setq show-paren-priority 999)
2151
2152
2153 (defface visible-mark-active
2154 '((((type tty) (class mono)))
2155 (t (:background "magenta"))) "")
2156
2157
2158
2159 (defface mouse-cursor-face
2160 '((((type tty) (class mono)))
2161 (t (:background "DeepPink1"))) "")
2162
2163
2164 (require 'visible-mark)
2165
2166 (setq visible-mark-faces '(visible-mark-face1 visible-mark-face2))
2167 (setq visible-mark-forward-faces '(visible-mark-forward-face1))
2168
2169
2170 ; highlight the last 2 marks
2171 (setq visible-mark-max 2)
2172 ; highlight 1 forward mark
2173 (setq visible-mark-forward-max 1)
2174 ; globally activate visible-mark-mode
2175 (global-visible-mark-mode +1)
2176
2177
2178 ;; todo, it doesn't seem to be exposed in elisp, but it would be nice
2179 ;; if I could define overlay faces to use inverse foreground color
2180
2181
2182 ;;; zrc
2183 (require 'znc)
2184 (setq erc-fill-prefix "")
2185 (defun chirp()
2186 (interactive)
2187 (setq vol 50)
2188 (when (string= (system-name) "tp") (setq vol 40))
2189 (start-process-shell-command "ignoreme" nil (format "mpv --no-terminal --vo=null --volume=%d /a/bin/data/bird.mp3" vol)))
2190 ;; from https://www.emacswiki.org/emacs/ErcSound
2191
2192 (defun erc-my-privmsg-sound (proc parsed)
2193 (let* ((tgt (car (erc-response.command-args parsed)))
2194 (privp (erc-current-nick-p tgt)))
2195 (and
2196 privp (chirp)
2197 ;; We must return nil. See help for `erc-server-PRIVMSG-functions'
2198 nil)))
2199
2200 (add-hook 'erc-server-PRIVMSG-functions
2201 'erc-my-privmsg-sound)
2202
2203 (defun erc-sound-if-not-server (match-type nickuserhost msg)
2204 (unless (string-match "Server:[0-9]+" nickuserhost)
2205 (chirp)))
2206 (add-hook 'erc-text-matched-hook 'erc-sound-if-not-server)
2207
2208 (erc-track-mode 1)
2209 (setq
2210 ;; consider invisible frames to be unseen. seems like an obvious default
2211 erc-track-visibility 'visible
2212 ;; switch to buffer where i've been mentioned, etc instead of oldest
2213 erc-track-switch-direction 'importance)
2214
2215
2216 ;;; persistent registers
2217 ;; This needs to be at the end, because I visit a file, thus setting a
2218 ;; mode, and the mode hook needs to be setup before that.
2219
2220 ;; I'm using persistent registers instead of bookmarks. I dun use them
2221 ;; much, so the added hassle of having to set it within this file is
2222 ;; worth the benefit of only having one concept in my mind.
2223 (dolist
2224 (r `(
2225 (?i (file . ,"~/.emacs.d/my-init.org"))
2226 (?t (file . ,"/a/x.txt"))
2227 ))
2228 (set-register (car r) (cadr r)))