weigley inspired improvements
[dot-emacs] / init.el
1 ;; Copyright (C) 2019 Ian Kelling
2
3 ;; This program is free software: you can redistribute it and/or modify
4 ;; it under the terms of the GNU General Public License as published by
5 ;; the Free Software Foundation, either version 3 of the License, or
6 ;; (at your option) any later version.
7
8 ;; This program is distributed in the hope that it will be useful,
9 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
10 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 ;; GNU General Public License for more details.
12
13 ;; You should have received a copy of the GNU General Public License
14 ;; along with this program. If not, see <http://www.gnu.org/licenses/>.
15
16 ;; do m-x benchmark-init to see some benchmark stats
17 ;;(add-to-list 'load-path "~/.emacs.d/src/benchmark-init-el/")
18 ;;(require 'benchmark-init-loaddefs)
19 ;;(benchmark-init/activate)
20
21 ;;; init.el --- the start of customization
22
23 ;; (toggle-debug-on-error) ;uncomment to help debug
24
25
26 ;; stop from minimizing & freezing the gui
27 ;; used to freeze emacs and was really annoying,
28 ;; seems its changed now. no harm in keeping this though.
29 (global-unset-key (kbd "C-z"))
30
31 ;; speed up init https://www.reddit.com/r/emacs/comments/3kqt6e/2_easy_little_known_steps_to_speed_up_emacs_start/
32 ;; https://github.com/jwiegley/dot-emacs/blob/master/init.el
33 (defvar file-name-handler-alist-old file-name-handler-alist)
34 (setq package-enable-at-startup nil
35 file-name-handler-alist nil
36 message-log-max 16384
37 gc-cons-threshold 402653184
38 gc-cons-percentage 0.6
39 auto-window-vscroll nil)
40
41 (add-hook 'after-init-hook
42 `(lambda ()
43 (setq file-name-handler-alist file-name-handler-alist-old
44 gc-cons-threshold 800000
45 gc-cons-percentage 0.1)
46 (garbage-collect)) t)
47
48 ;; 2019-6-26, 1.26s
49 ;;; to profile init:
50 ;;; uncomment the following block
51 ;; (require 'benchmark-init)
52 ;; (add-hook 'after-init-hook 'benchmark-init/deactivate)
53 ;;; Then run:
54 ;;; emacs -f benchmark-init/show-durations-tabulated
55 ;;; emacs -f benchmark-init/show-durations-tree
56 ;;; to catch things post-init
57 ;;; emacs -f benchmark-init/deactivate
58
59
60 ;; these need to be done before the hook in order to satisfy the byte compiler or batch mode
61
62 ;; this is the builtin org mode
63 ;;(add-to-list 'load-path "~/.emacs.d/emacs/site-lisp/org")
64
65 (add-to-list 'load-path "~/.emacs.d/src/readline-complete")
66
67 ;; disabled since not used.
68 ;;(add-to-list 'load-path "~/.emacs.d/src/bbdb-csv-import")
69 ;;(add-to-list 'load-path "~/.emacs.d/src/ghci-completion")
70 ;;(add-to-list 'load-path "~/.emacs.d/src/mediawiki-el")
71 ;;(add-to-list 'load-path "~/.emacs.d/src/spray")
72
73 (add-to-list 'load-path "~/.emacs.d/src/visible-mark")
74
75
76
77 (setq init-dir (file-name-directory load-file-name))
78 ;; previously, i was doing byte-recompile-directory, but
79 ;; now i just have one init file
80 (unless (equal (user-uid) 0) ; don't make root owned files
81 (byte-recompile-file (expand-file-name "init.el" init-dir) nil 0)
82 (when (file-exists-p "/p/c/mymu4e.el")
83 (byte-recompile-file "/p/c/mymu4e.el" nil 0))
84 )
85
86 ;;; misc emacs documentation
87
88 ;;;; how to find auto-saved files that need recovering
89 ;; find a recently dated file in ~/.emacs.d/auto-save-list/, and see the files listed in it.
90 ;; #file# is an auto-save file. It may or may not be different than the file is corresponds to.
91 ;; If it is different, emacs will give a message about recovering it when you open it.
92
93 ;;;; misc org functions
94
95 ;; ;; these are usefull with (goto-char)
96 ;; ;; find named entity, other than headline
97 ;; (org-find-entry-with-id "string-number-or-symbol")
98
99 ;; (org-find-exact-headline-in-buffer "heading" nil t)
100
101 ;; ;; remove any indent level which is throughout the buffer
102 ;; (org-do-remove-indentation)
103
104
105 ;;;; gnus
106
107 ;; good info http://www.emacswiki.org/emacs/GnusTutorial
108 ;; good info http://www.emacs.uniyar.ac.ru/doc/em24h/emacs183.htm
109
110
111 ;; After downloading mailing list archives, once you have an mbox file,
112 ;; there are rather straightforward ways to get it into any mail program,
113 ;; but I will cover gnus, which I use and is a bit tricky.
114
115 ;; gnus has a native search (limited, too slow for body text searches), and external search engine integration.
116 ;; gnus manual recommends converting to maildir for searching local mail, but importing lots of maildir messages to gnus
117 ;; takes 10+ minutes, so scratch that option. it suggests 2 alternate options
118 ;; mairix. for mbox, it doesn't integrate 100% with gnus, it copies the search results to a mbox
119 ;; and tells gnus to make a group of that mbox and display it. This means the read state won't be persistent, but otherwise
120 ;; works great.
121
122 ;; local imap server which will use the mbox and provide search.
123 ;; dovecot is modular, theres a dovecot-common which uses recommends to install i guess it's most used modules. Its
124 ;; description is completely not useful. Anyways, I'm not sure if there is any benefit to installing this over just the
125 ;; module we need.
126 ;; pi dovecot-imapd
127
128 ;; dovecot by default also makes a an inbox folder based on the normal local mail location /var/mail/<username>
129 ;; those locations are adjustable and well documented via the var mail_location in
130 ;; /etc/dovecot/conf.d/10-mail.conf
131 ;; 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
132 ;; is. you could make the var be empty, which apparently has the same effect.
133
134 ;; Originally just linked the default location ~/.mail, but I changed to altering the config since ~/.mail since it seems
135 ;; other things like postfix use that location
136
137 ;; based on http://roland.entierement.nu/blog/2010/09/08/gnus-dovecot-offlineimap-search-a-howto.html
138 ;; other links that poped up contained outdated, innacurate information
139 ;; http://sachachua.com/blog/2008/05/geek-how-to-use-offlineimap-and-the-dovecot-mail-server-to-read-your-gmail-in-emacs-efficiently/
140 ;; http://www.emacswiki.org/emacs/JamesFerguson
141 ;; http://www.sanityinc.com/articles/read-mailing-lists-in-emacs-over-imap/
142
143 ;; Within emacs you can move messages between mbox and maildir etc, which is a nice flexibility.
144
145
146
147 ;; doc group for mbox:
148 ;; in gnus, do gnus-group-make-doc-group (G f in groups buffer) and point to the file
149
150 ;; info about groups created within gnus is stored in ~/.newsrc.eld
151 ;; also stored is a duplication of what email messages are read/unread,
152 ;; what newsgroups are subsribed to and read/unread,
153 ;; probably more stuff, everything that gnus saves.
154
155
156 ;; searching the body of the messages, i cut off after a few minutes.
157 ;; i can grep the file in just a couple seconds
158
159
160 ;; random side note
161 ;; we can also get mbox from gmane
162 ;; http://notmuchmail.org/howto/#index7h2
163
164
165 ;; gnus can't search mboxes except with its builtin search which is extremely slow. mairix can do mbox files from the command
166 ;; line, but not from within gnus, but from mairix.el, which can then open the results in gnus
167
168 ;; mbox can be converted to maildir easily, but gnus loads lots of maildir messages extremely slow. it parses all the
169 ;; headers and generates a nov file for each.
170
171 ;; nnfolder-generate-active-file
172
173 ;; to reset things, when changing mail group. I duno all the proper way, but it works to delete
174 ;; ~/Mail ~/.newsrc.eld ~/.newsrc-dribble
175
176
177 ;;;;; mail sources vs select methods background
178 ;; I found this very confusing when first reading through the manual. "mail sources" is a term that does not simply mean
179 ;; sources of mail, it is much narrower for gnus. sources of mail can be either "mail sources" or select methods. Mail
180 ;; sources will move mail to ~/Mail (not sure what format), and split it into groups according to variables. You can use
181 ;; "mail sources" for maildir / imap, but those can also be read via select methods, which do not move the mail from their
182 ;; location, but use them in their native format. This is what I want to do, and I can simply ignore mail
183 ;; sources. Confusing terminology is that "fetching mail" "scanning mail", lots of things mail doesn't mean all mail, it
184 ;; means specifically from "mail sources". The words "articles" and "news" is used in connection with select methods, aka my actual mail.
185
186
187
188 ;;;;; caching background
189
190 ;; caching:
191 ;; there is also ~/News/cache, filled with a bunch of articles, like 300 megs. can't figure out why.
192 ;; Grepped for caching in the manual, found 2 main things.
193 ;; cache is for 2 purposes. to cache locally, and to keep articles from expiring, called persistence
194 ;; gnus-use-cache, which puts things if they are
195 ;; gnus-cache-enter-articles
196 ;; things go in cache when they are marked certain ways by default, ticked and dormant
197 ;; and read articles are moved out of the cache
198 ;; still no idea why i have a bunch in the cache, but I set a var so that my mail won't get cached
199 ;; I'm gonna delete the cache, and check on it later see what exactly is going in there
200 ;; And of course, I moved ~/News to my encrypted drive and symlinked it
201
202
203
204 ;;; things that should be at the beginning
205
206 ;; from its README.md
207 (eval-when-compile
208 (require 'use-package))
209
210
211 ;; Ubiquitous Packages. these could go anywhere actually
212 (use-package saveplace
213 :unless noninteractive
214 :config
215 (save-place-mode 1))
216 (use-package ffap)
217
218 ;; from jwiegley
219 (use-package recentf
220 :defer 10
221 :commands (recentf-mode
222 recentf-add-file
223 recentf-apply-filename-handlers)
224 :config
225 (recentf-mode 1))
226
227 (setq package-archives
228 (quote
229 (("gnu" . "https://elpa.gnu.org/packages/")
230 ("MELPA" . "https://melpa.org/packages/"))))
231
232 ;;(add-to-list 'package-archives
233 ;; '("marmalade" .
234 ;; "http://marmalade-repo.org/packages/"))
235
236 ;; down atm 2020-08-30
237 ;;(add-to-list 'package-archives '("org" . "http://orgmode.org/elpa/") t)
238
239
240 ;; keep our init.el clean, by moving customization elisp to it's own file
241 (setq custom-file "~/.emacs.d/custom.el")
242 (load custom-file 'noerror)
243
244
245 ;;; auto-complete
246
247 ;; auto-completion in minibuffer
248 ;; disabled while I look for another alternative
249 ;;(icomplete-mode)
250
251 (require 'auto-complete-config)
252 (ac-config-default)
253
254
255 ;; complete after 1 char instead of default 2
256 (setq ac-auto-start 1)
257 (setq ac-delay 0.001)
258
259 (add-to-list 'ac-modes 'org-mode 'sql-mode)
260
261 (defun ac-common-setup ()
262 (add-to-list 'ac-sources 'ac-source-yasnippet))
263
264 ;; for org mode completion source taken from wiki.
265 ;; it did not work. no idea why. todo, investigate
266 ;; the ac-sources code is at http://www.emacswiki.org/emacs/AutoCompleteSources
267 ;; i've deleted it here so as to save space and not spam this file
268 ;;(defun my-ac-org-mode ()
269 ;; (setq ac-sources (append ac-sources '(ac-source-org))))
270
271
272 ;; this makes the org-self-insert command not do a flyspell spell check.
273 ;; low priority thing to look into sometime
274 (ac-flyspell-workaround)
275
276
277 (define-key ac-completing-map (kbd "<up>") nil)
278 (define-key ac-completing-map (kbd "<down>") nil)
279 (define-key ac-completing-map (kbd "<S-return>") 'ac-expand)
280 (define-key ac-completing-map "\t" 'ac-complete)
281 ;;(define-key ac-completing-map (kbd "<tab>") 'ac-complete)
282 (define-key ac-completing-map (kbd "TAB") 'ac-complete)
283
284
285
286 ;;; auto-complete readline-complete
287
288 (require 'readline-complete)
289 ;; not sure how I made these, but I deleted, and
290 ;; it would be nice to make them again sometime
291 ;;(require 'src-loaddefs)
292
293 ;; disabled cuz broken
294 ;; redefining function in readline-complete so ac-complete only uses readline as a source
295 (defun ac-rlc-setup-sources ()
296 "Add me to shell-mode-hook!"
297 (setq ac-sources '(ac-source-shell)))
298 (add-hook 'shell-mode-hook 'ac-rlc-setup-sources)
299
300 ;; generally unnecessary, but why not
301 (setq explicit-shell-file-name "bash")
302
303 ;; readline-complete says to add this line.
304 ;; however, it up my procfs directory tracking hook
305 ;; because get-process doesn't notice the child shell.
306 ;; instead, I've removed export EMACS=t from
307 ;; comint-exec-1 (the function which initially sets it)
308 ;; by finding it in emacs sources and redefinind it here
309 ;; and done stty echo in my bashrc
310 ;;(setq explicit-bash-args '("-c" "export EMACS=; stty echo; bash"))
311
312 (setenv "EMACS" "")
313 (setq explicit-bash-args nil)
314 (setq comint-process-echoes t)
315 ;; default of 30 is way too slow. todo, consider pushing this upstream
316 (setq rlc-attempts 5)
317
318 (add-to-list 'ac-modes 'shell-mode)
319
320 ;; readline-complete recommends this (i assume this format),
321 ;; but greping finds no reference in emacs or my .emacs.d
322 ;; so I'm assuming it is for an older emacs
323 ;;(setq explicit-ssh-args '("-t"))
324
325 (add-hook 'shell-mode-hook
326 (lambda ()
327 ;;(define-key shell-mode-map (kbd "<tab>") 'auto-complete)
328 (define-key shell-mode-map (kbd "TAB") 'auto-complete)
329 ))
330
331
332 ;;; readline complete fix
333
334 ;; I need this function here, where INSIDE_EMACS is replaced with LC_INSIDE_EMACS.
335 ;; ian: last update 2017-1-7. update this periodically from upstream
336 ;; like when we do a major emacs update
337 (defun comint-exec-1 (name buffer command switches)
338 (let ((process-environment
339 (nconc
340 ;; If using termcap, we specify `emacs' as the terminal type
341 ;; because that lets us specify a width.
342 ;; If using terminfo, we specify `dumb' because that is
343 ;; a defined terminal type. `emacs' is not a defined terminal type
344 ;; and there is no way for us to define it here.
345 ;; Some programs that use terminfo get very confused
346 ;; if TERM is not a valid terminal type.
347 ;; ;; There is similar code in compile.el.
348 (if (and (boundp 'system-uses-terminfo) system-uses-terminfo)
349 (list "TERM=dumb" "TERMCAP="
350 (format "COLUMNS=%d" (window-width)))
351 (list "TERM=emacs"
352 (format "TERMCAP=emacs:co#%d:tc=unknown:" (window-width))))
353 (list (format "LC_INSIDE_EMACS=%s,comint" emacs-version))
354 process-environment))
355 (default-directory
356 (if (file-accessible-directory-p default-directory)
357 default-directory
358 "/"))
359 proc decoding encoding changed)
360 (let ((exec-path (if (and command (file-name-directory command))
361 ;; If the command has slashes, make sure we
362 ;; first look relative to the current directory.
363 (cons default-directory exec-path) exec-path)))
364 (setq proc (apply 'start-file-process name buffer command switches)))
365 ;; Some file name handler cannot start a process, fe ange-ftp.
366 (unless (processp proc) (error "No process started"))
367 (let ((coding-systems (process-coding-system proc)))
368 (setq decoding (car coding-systems)
369 encoding (cdr coding-systems)))
370 ;; Even if start-file-process left the coding system for encoding data
371 ;; sent from the process undecided, we had better use the same one
372 ;; as what we use for decoding. But, we should suppress EOL
373 ;; conversion.
374 (if (and decoding (not encoding))
375 (setq encoding (coding-system-change-eol-conversion decoding 'unix)
376 changed t))
377 (if changed
378 (set-process-coding-system proc decoding encoding))
379 proc))
380
381 ;;; auto save & backup
382 (setq auto-save-timeout 1) ; idle time before auto-save.
383
384 ;; main hook for my auto save
385 (add-hook 'auto-save-hook 'my-auto-save)
386 ;; additional hook to try to deal with emacs not auto-saving when a buffer isn't active
387 (add-hook 'window-configuration-change-hook 'my-auto-save-win)
388
389 ;; this function from mu4e really does not like buffer saving
390 (advice-add 'message-send-and-exit :before 'my-as-off)
391 (advice-add 'message-send-and-exit :after 'my-as-on)
392
393 ;; avoid window config hook saving too much, it can
394 ;; get into loops in some random situations
395 (setq my-auto-save-last nil)
396 (defun my-auto-save-win ()
397 (unless (eq (current-buffer) my-auto-save-last)
398 (my-auto-save (current-buffer))))
399
400 (defun my-auto-save (&optional last)
401 (when (and
402 my-as
403 (buffer-file-name)
404 ;; mu4e has a bug right now, undo breaks when saving drafts
405 (not (string= (buffer-file-name) "*draft*"))
406 (buffer-modified-p)
407 (not (and (boundp 'org-src-edit-buffer-p) (org-src-edit-buffer-p))))
408 ;; serial is incremented on each save, so let's do a bit less of them
409 (not (derived-mode-p 'dns-mode))
410 (setq my-auto-save-last last)
411 (let (message-log-max)
412 ;; a bit of a hack to partially suppress the constant saving in the echo area
413 (with-temp-message ""
414 (basic-save-buffer)))))
415
416 ;; in the message-send-and-exit advice, got an error because it passed an arg.
417 ;; didn't look into why, just add ignored args.
418 (defun my-as-off (&rest ignore)
419 (interactive)
420 (setq my-as nil))
421
422 (defun my-as-off-local (&rest ignore)
423 (interactive)
424 (setq-local my-as nil))
425
426 (defun my-as-on (&rest ignore)
427 (interactive)
428 (setq my-as t))
429
430 (defun my-as-on-local (&rest ignore)
431 (interactive)
432 (setq-local my-as on))
433
434 ;; based on suggestion in the emacs docs, redefine these 2 functions
435 ;; to avoid prompt spamming the user when we do auto-save
436 (defun ask-user-about-supersession-threat (fn)
437 (discard-input)
438 (message
439 "File for %s has changed on disk outside of emacs. Auto-save is overwriting it, however
440 a backup is being created in case that is not what you intended." buffer-file-name)
441 (setq buffer-backed-up nil))
442
443 (defadvice ask-user-about-lock (before lock-deactivate-as activate)
444 (make-local-variable 'my-as)
445 (setq my-as nil)
446 (message "proper autosave has been turned off for this buffer because of lock file problem.
447 In this buffer, do M-x my-as-on to reenable"))
448
449 ;; todo, this doesn't work consistently to override the auto-save message
450 (defalias 'do-auto-save-original (symbol-function 'do-auto-save))
451 (defun do-auto-save (&optional no-message current-only)
452 "This function has been modified to wrap the original so that NO-MESSAGE
453 is always set to t, since we auto-save a lot, it spams otherwise.
454 The original doc string is as follows:
455
456 Auto-save all buffers that need it.
457 This is all buffers that have auto-saving enabled
458 and are changed since last auto-saved.
459 Auto-saving writes the buffer into a file
460 so that your editing is not lost if the system crashes.
461 This file is not the file you visited; that changes only when you save.
462 Normally we run the normal hook `auto-save-hook' before saving.
463
464
465 A non-nil NO-MESSAGE argument means do not print any message if successful.
466 A non-nil CURRENT-ONLY argument means save only current buffer."
467 (interactive)
468 (do-auto-save-original t current-only))
469
470 ;; enable MY auto-save
471 (my-as-on)
472
473 ;;; backups, separate from auto-save
474
475
476 ;; set backup file location
477 (setq backup-directory-alist '(("." . "~/.editor-backups")))
478 (setq auto-save-file-name-transforms
479 '((".*" "~/.editor-backups/" t)))
480
481 (setq version-control t ;; Use version numbers for backups
482 kept-new-versions 100
483 kept-old-versions 2
484 delete-old-versions t ;; delete old versions silently
485 ;; assume hard linked files are done on purpose, don't screw them up
486 backup-by-copying-when-linked t)
487
488 ;; todo, the time needs to be an integer, not a vector type thing
489 (defun constant-backup ()
490 "Backup conditioned on some time passing since last one.
491 Hooked into 'before-save-hook."
492 (cl-flet ((b-time (minutes)
493 (< last-backup-time
494 (- (current-time) (* 60 minutes)))))
495 (when (or (not (boundp 'last-backup-time)) (and (< (buffer-size) 10000000) (b-time 5)) (b-time 30))
496 (setq buffer-backed-up nil)
497 (setq-local last-backup-time (current-time)))))
498
499 ;; make a backup on auto-save, because the backup feature is not
500 ;; utilized with my-auto-save, only normal interactive save.
501 ;; todo, enable when fixed
502 ;;(add-hook 'before-save-hook 'constant-backup)
503
504 (add-hook 'auto-save-hook 'auto-save-size-limit)
505
506 (defun auto-save-size-limit ()
507 (when (and (not backup-inhibited) (> (buffer-size) 2000000))
508 (message "Backups disabled for this buffer due to size > 2 megs")
509 (make-local-variable 'backup-inhibited)
510 (setq backup-inhibited t)))
511
512
513 ;; ;; background:
514 ;; ;; the faq suggests to auto-save using
515 ;; (setq auto-save-visited-file-name t)
516 ;; and to toggle auto-saving in the current buffer, type `M-x auto-save-mode'
517
518 ;; however, this is buggy.
519 ;; it leaves around lock files, which can be disabled with
520 ;; (setq create-lockfiles nil)
521 ;; but it is also buggy on other things that appear to hook onto file saving
522 ;; so i created my own function, which originally had bugs,
523 ;; but new emacs version fixed all that, yay!.
524
525
526 ; not using, but here for documentation,
527 ; alternate way to enable and specify how long between autosaves.
528 ; number of input events between autosave.
529 ; lowest bound of functionality is actually about 15 input events
530 ;(setq auto-save-interval
531
532 ;;; bbdb
533 ;; based on bbdb manual
534 ;; also has instructions to integrate with gnus,
535
536 (bbdb-initialize 'message)
537
538 ;; recommended by gnus,
539 ;; but seems like it could be good to have set for other stuff
540 (setq user-full-name "Ian Kelling")
541 ;; general email setting? recommended by mu4e
542 (setq message-kill-buffer-on-exit t)
543
544
545
546 ;; use d instead
547 (add-hook 'bbdb-mode-hook
548 (lambda () (define-key bbdb-mode-map (kbd "C-k") nil))
549 ;; based on emacs24-starter-kit
550 (setq bbdb-offer-save 'auto
551 bbdb-notice-auto-save-file t
552 bbdb-expand-mail-aliases t
553 bbdb-canonicalize-redundant-nets-p t
554 bbdb-complete-name-allow-cycling t)
555 )
556
557 ;;(require 'bbdb-csv-import)
558
559 ;;; bookmark settings
560 ; save bookmarks whenever they are changed instead of just when emacs quits
561 (setq bookmark-save-flag 1)
562 ; increase bookmark context size for better functionality
563 (setq bookmark-search-size 2000)
564
565 ;;; c-like settings
566 ;; change last thing from gnu.
567 ;; notably this avoids brace indent after if, and 4 space indent
568 (setq c-default-style '((java-mode . "java")
569 (awk-mode . "awk")
570 (other . "stroustrup")))
571 ;; for emacs itself, use
572 ;; (setq c-default-style '((java-mode . "java")
573 ;; (awk-mode . "awk")
574 ;; (other . "gnu")))
575 ;; (setq-default c-basic-offset 2)
576
577 ;;; color theme
578
579 ;; A Theme builder is available at http://elpa.gnu.org/themes/ along with
580 ;; a list of pre-built themes at http://elpa.gnu.org/themes/view.html and
581 ;; themes are available through ELPA.
582
583
584 ;; interesting light themes
585
586
587 (defun override-theme (arg)
588 (interactive)
589 (while custom-enabled-themes
590 (disable-theme (car custom-enabled-themes)))
591 (load-theme arg t))
592 (setq color-theme-is-global t)
593
594 ;; temporary, make night be default
595
596 (defun toggle-night ()
597 (interactive)
598 (cond ((equal (car custom-enabled-themes) 'naquadah)
599 (override-theme 'leuven))
600 (t
601 (override-theme 'naquadah))))
602
603
604 ;; in the leuven theme file, i made this change. will need to remake it
605 ;; on package updates. I could fork, but its a pretty simple change
606 ;; < `(default ((,class (:foreground "#333333" :background "#FFFFFF"))))
607 ;; > `(default ((,class (:foreground "#333333" :background "#F6F6F0"))))
608 (override-theme 'leuven)
609
610
611 ;; disable color thing with this:
612 ;;(disable-theme (car custom-enabled-themes))
613
614 ;; decent dark themes
615
616 ;;(override-theme 'tangotango)
617 ;;(override-theme 'deeper-blue)
618 ;;(override-theme 'tango-dark)
619 ;;(override-theme 'tsdh-dark)
620
621 ;;(override-theme 'heroku)
622 ;;(override-theme 'inkpot) ;; part of inkpot-theme package
623 ;;(override-theme 'naquadah) ; org mode features, part of naquadah-theme package
624 ;;(override-theme 'spolsky) ;; part of sublime-themes package
625 ;;(override-theme 'twilight-anti-bright) ;; from twilight-anti-bright-theme package
626
627 ;; interesting but not usable colors
628 ;;(override-theme 'cyberpunk) ; cool org mode features, from cyberpunk-theme package
629 ;;(override-theme 'wombat) ; cursor not visible enough. from a wombat package, not sure which
630 ;;(override-theme 'misterioso) ; cursor not visible enough
631
632
633
634 ;;decent light themes
635 ;;(override-theme 'alect-light) ; theres a -alt version, don't see a dif. could use this without dimming. from alect-something package
636 ;;(override-theme 'occidental) ; from occidental-theme package
637
638
639 ;;color-theme is deprecated in emacs 24.
640
641 ;; theme packages i tried then removed:
642 ;; ignored ones that didn't use the new theme engine
643
644 ;;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)
645
646
647
648
649 ;;; yasnippet
650
651 ;; cd ~/.emacs.d/src
652 ;; git clone --recursive https://github.com/capitaomorte/yasnippet
653 ;; touch snippets/.yas-make-groups
654
655 ;; This all makes it so I can look through the default snippets
656 ;; in the menu bar, but they don't show up elsewhere, because they are
657 ;; mostly things I don't want.
658
659
660 (require 'yasnippet)
661 ;; this needs to be before yas-global-mode
662 (setq yas-snippet-dirs (list "~/.emacs.d/snippets"))
663 (yas-global-mode 1)
664
665 (setq
666 yas-also-auto-indent-first-line t
667 yas-choose-tables-first t
668 yas-use-menu (quote full)
669 ;; this sets ido-prompt as first function
670 yas-prompt-functions
671 '(yas-ido-prompt yas-dropdown-prompt yas-x-prompt yas-completing-prompt yas-no-prompt))
672
673 ;; todo, explore this option for wrapping region
674 ;; '(yas/wrap-around-region t))
675
676 ;;; cross session settings
677
678 ;; Save a list of recent files visited.
679 (recentf-mode 1)
680 (setq recentf-max-saved-items 400
681 recentf-max-menu-items 15)
682
683
684 (setq save-place t
685 save-place-version-control 'nospecial
686 save-place-limit 40000
687 save-place-file "~/.emacs.d/places")
688
689
690
691 ;; savehist keeps track of some history
692 ;; search entries
693 (setq savehist-additional-variables '(kill-ring search-ring regexp-search-ring)
694 ;; save every minute
695 savehist-autosave-interval 60
696 ;; keep the home clean
697 savehist-file "~/.emacs.d/.savehist")
698 (savehist-mode 1)
699
700
701 ;;; ediff
702 ;; ediff-buffers is the main command to use
703
704 ;; ediff - don't start another frame for the control panel
705 ;; unfortunately, this doesn't allow me to use 2 frames for the diff buffers
706 ;; so disable this temporarily with the next line if you want that
707 ;; sometime I should setup 2 functions to explicitly do each type
708 (setq ediff-window-setup-function 'ediff-setup-windows-plain)
709 ;;(setq ediff-window-setup-function 'ediff-setup-windows-default)
710
711 ;; do side by side diffs
712 (setq ediff-split-window-function 'split-window-horizontally)
713
714
715
716 ;; Things I tried which didn't work, which intuitively I think should
717 ;; work better: I can open the second diff buffer in a new frame, and
718 ;; close it's window in the first frame after starting ediff, but when I
719 ;; hit n to go to the next diff, it restores the window in the first
720 ;; frame. Another thing I tried is to open 2 new frames and set them up
721 ;; as I want. However, if I try to open the *Ediff Control Panel* buffer
722 ;; in a different window from its original one, my mouse jumps to one of
723 ;; the diff frames, or if that isn't visible, the buffer just hangs
724 ;; until I select the original ediff control panel window. This seems
725 ;; like a bug to me. I am using a very recent development version of
726 ;; emacs.
727
728 ;;; dired
729
730 ;; dired - reuse current buffer by pressing 'a'
731 (put 'dired-find-alternate-file 'disabled nil)
732
733 ;;; mu4e
734
735 ;; alsot tried notmuch, it had some glitches, and it's config has a list
736 ;; of folders which i'd rather not publish, so it's config is archived.
737
738 ;;(add-to-list 'load-path "/usr/local/share/emacs/site-lisp/mu4e")
739 ;;(add-to-list 'load-path "/usr/share/emacs/site-lisp/mu4e")
740 ;; (require 'mu4e)
741
742 ;; (setq mu4e-headers-results-limit 2000)
743
744
745 (defun my-mu4e-init ()
746 (setq mu4e-headers-fields (delq (assoc :mailing-list mu4e-headers-fields) mu4e-headers-fields))
747 ;; it's implemented in mu4e, but not in the actions list for
748 ;; some reason.
749 (add-to-list 'mu4e-view-actions
750 '("browser view" . mu4e-action-view-in-browser) t)
751
752 (add-to-list 'mu4e-headers-actions
753 '("from this sender" . mu4e-action-msgs-by-this-sender) t)
754 (add-to-list 'mu4e-view-actions
755 '("from this sender" . mu4e-action-msgs-by-this-sender) t)
756 ;; normally, you would add to this, but we want to
757 ;; modify unread messages. the first 4 are defined by default.
758 (setq mu4e-bookmarks
759 `( ,(make-mu4e-bookmark
760 :name "Unread messages"
761 ;; old less restrictive unread, for adapting in the future:
762 ;; flag:unread AND NOT flag:trashed AND NOT maildir:/Junk AND NOT maildir:/fwfw AND NOT maildir:/log
763 :query "flag:unread maildir:/INBOX"
764 :key ?u)
765 ,(make-mu4e-bookmark
766 :name "Today's messages"
767 :query "date:today..now"
768 :key ?t)
769 ,(make-mu4e-bookmark
770 :name "Last 7 days"
771 :query "date:7d..now"
772 :key ?w)
773 ,(make-mu4e-bookmark
774 :name "Messages with images"
775 :query "mime:image/*"
776 :key ?p))
777 )
778 )
779
780 (eval-after-load "mu4e" '(my-mu4e-init))
781
782 (setq
783 ;; https://github.com/djcb/mu/issues/1025
784 mail-user-agent 'mu4e-user-agent
785 ;; common to gnus. default sendmail-query-once asks us, then sets this via customize.
786 send-mail-function (quote sendmail-send-it)
787 ;; use the standard imap folders
788 mu4e-sent-folder "/Sent"
789 mu4e-drafts-folder "/Drafts"
790 mu4e-trash-folder "/Trash"
791 ;; reindex new mail this often in seconds
792 ;; show addresses instead of just names
793 mu4e-view-show-addresses t
794 mu4e-use-fancy-chars t
795 mu4e-confirm-quit nil
796 mu4e-headers-leave-behavior 'apply ;; dont ask, do whatever was marked
797 ;; default 500.
798 mu4e-headers-results-limit 1000
799 ;; tell exim to use from: as envelope from.
800 ;; exim's default is use outgoing_msg_localpart@hostname.
801 mail-specify-envelope-from t
802
803 ;; looking up the list of maildirs when doing jo from summary
804 ;; can take a few seconds if we have a ton of messages.
805 ;; Only take that time for the first lookup.
806 ;; if we add a new maildir, just restart mu4e for it to be in that list.
807 mu4e-cache-maildir-list t
808 ;; default is 8, way too small for my big monitors
809 mu4e-headers-visible-lines 50
810 message-sendmail-envelope-from 'header
811 ;; trying this out
812 ;;mu4e-view-use-gnus t
813 ;; had problems where mu4e and gnus would hang verifying signatures, gnus man
814 ;; said this should help, but it didnt work. they still got verified.
815 ;; mm-verify-option 'never
816 )
817
818 ;; fucks up reading unread bookmark. when that is fixed, enable it
819 ;; (setq mu4e-update-interval 60)
820
821
822 ;; this file includes setting up my email addresses, which are not public,
823 ;; including
824 ;; mu4e-user-mail-address-list
825 ;; and a function
826 ;; inspired by mu4e info manual, search for mu4e-compose-pre-hook.
827 (when (file-exists-p "/p/c/mymu4e.el")
828 (load "/p/c/mymu4e.el"))
829
830 (defun my-decrypt ()
831 ;; use for decrypting in mu4e
832 (interactive)
833 (beginning-of-buffer)
834 (when (search-forward "-----BEGIN PGP MESSAGE-----" nil t)
835 (read-only-mode 0)
836 (let ((start (match-beginning 0))
837 (end (search-forward "-----END PGP MESSAGE-----" nil t)))
838 (shell-command-on-region start end "gpg2 -dq" nil t shell-command-default-error-buffer t)
839 )))
840 (add-hook 'mu4e-view-mode-hook 'my-decrypt)
841
842 (defun iank-set-from-name (regexes)
843 "If we find an address matching regex, then set that address as the to,
844 and whatever was used"
845 (when mu4e-compose-parent-message
846 (let ((found nil))
847 (while (and regexes (not found))
848 (setq re (car regexes)
849 regexes (cdr regexes)
850 found (mu4e-message-contact-field-matches
851 mu4e-compose-parent-message :to re)))
852 (when found
853 (setq user-full-name (car found))
854 ;; we get an error unless we do this. that is a bug. I could
855 ;; send a patch... also a bug: setting message-from-style nil
856 ;; doesnt work in mu4e unless user-full-name is also nil.
857 (unless user-full-name
858 (setq message-from-style nil))
859 (setq user-mail-address (cdr found)
860 mail-signature nil))
861 found)))
862 (defun iank-set-from (regexes)
863 "If we find an address matching regex, then set that address as the to,
864 and Ian Kelling as the name"
865 (when mu4e-compose-parent-message
866 (let ((found nil))
867 (while (and regexes (not found))
868 (setq re (car regexes)
869 sig (cadr regexes)
870 regexes (cddr regexes)
871 found (cdr (mu4e-message-contact-field-matches
872 mu4e-compose-parent-message :to re))))
873 (when found (setq user-mail-address found
874 user-full-name "Ian Kelling"))
875 found)))
876
877
878 (defun mu-exit-wait ()
879 (interactive)
880 ;; taken from the mu source
881 (let* ((buf (get-buffer mu4e~proc-name))
882 (proc (and (buffer-live-p buf) (get-buffer-process buf))))
883 (mu4e-quit)
884 ;; without sleep, we get database locked by another process error when hitting u
885 ;; if another mu was running.
886 (if proc (sleep-for 0 1000))))
887
888 (defun fsf-mu4e ()
889 (interactive)
890 (my-mu4e-commmon)
891 (setq
892 user-mail-address "iank@fsf.org"
893 iank-user-mail-address user-mail-address
894 ;; WARNING: be careful editing this, there needs to be a space after --, and my editor
895 ;; and git will automatically remove it unless i manually disable it.
896 mail-signature fsf-sig
897 ) ;; end setq
898 (add-hook 'mu4e-compose-pre-hook 'my-mu4e-to)
899 (mu4e))
900
901
902
903
904 (defun mu4e-action-msgs-by-this-sender (msg)
905 "In header view, view messages by the sender of the message under point."
906 (let ((from (mu4e-message-field msg :from)))
907 (unless from
908 (mu4e-error "No from header for this message"))
909 ;; from is structured like: (("Anacron" . "root@x2.lan"))
910 (mu4e-headers-search (concat "f:" (cdar from)))))
911
912
913
914 ;;; elisp settings
915 ; when manually evaluating lisp, go into debugger on error
916 (setq eval-expression-debug-on-error t)
917 ;reminder of useful var: debug-on-error
918
919
920 ;;; haskell
921
922 ;; useful comint-shell mode commands. If not prefaced with *, it means it is not in the haskell custom repl
923 ;; *todo: setup haskell c-t toggle arrow keys
924 ;; tab completion
925 ;; C-q insert prev arg
926 ;; C-( history search
927 ;; c-m-left/right move to next/prev prompts
928 ;; *c-enter, multi-line input
929 ;; *s-delete, send input across windows. (i can implement this)
930 ;; *c-m-l clear screen
931 ;; *haskell-process-interrupt, c-cc terminate job (i can implement this maybe)
932
933 ;; nice bash/readline functions missing in comint:
934 ;; yank-nth-arg
935 ;; operate-get-next
936 ;; menu-complete
937
938 ;; usefull comint commands:
939 ;; c-cl : list historic command in temp buffer
940 ;; C-c C-o comint-delete-output
941 ;; comint-restore-input, todo: put this on a randomish c-c key
942
943
944
945 ;; todo:
946 ;; checkout haskell repl functions:
947 ;; c-cv haskell-check, hlint
948 ;; C-M-q prog-indent-sexp
949 ;; c-c. haskell-mode-format-imports
950 ;; C-c M-/ haskell-doc-check-active
951 ;; haskell-process-generate-tags
952 ;; haskell-process-cabal-build
953 ;; haskell-cabal-command.. or something
954 ;; haskell-process-restart
955 ;; C-h v haskell-process-log
956 ;; C-h v haskell-process-show-debug-tips
957
958 ;; various not immediately useful functions:
959 ;; haskell-process-add-dependency
960 ;; haskell-process-touch-buffer
961 ;; haskell-process-cd
962 ;; haskell-process-unignore
963 ;; haskell-process-reload-devel-main
964
965
966 ;; rebind
967 ;; home: C-a haskell-interactive-mode-beginning
968 ;; c-return: C-j haskell-interactive-mode-newline-indent
969 ;; up/down: <C-down> haskell-interactive-mode-history-next
970
971 ;; todo haskell mode better binds for:
972 ;; 'haskell-process-load-file
973 ;; 'haskell-process-do-type
974 ;; 'haskell-process-do-info
975 ;; 'inferior-haskell-send-decl
976
977
978 ;; commands which don't work in haskell-interactive-mode(hi) vs inferior-haskell-mode(ih, default)
979 ;; functions not in hi:
980 ;; inferior-haskell-find-definition, use tags instead
981 ;; inferior-haskell-find-haddock, todo, test if this works
982
983 ;; redefined ih to hi
984 ;; switch-to-haskell -> 'haskell-interactive-switch
985 ;; haskell-process-load-file -> inferior-haskell-load-file
986 ;; haskell-process-do-type -> inferior-haskell-type
987 ;; switch-to-haskell -> haskell-interactive-switch
988 ;; inferior-haskell-load-file -> 'haskell-process-load-file
989
990
991 ;; haskell-mode installation from source, based on its readme
992 ;; in the git directory,
993 ;; make all
994
995
996
997
998 ;; remove default option to not link the file
999 (setq haskell-compile-command "ghc -Wall -ferror-spans -fforce-recomp %s")
1000 (add-hook 'haskell-indentation-mode-hook
1001 (lambda ()
1002 (define-key haskell-indentation-mode-map [?\C-d] nil)
1003 (define-key haskell-indentation-mode-map
1004 (kbd "<deletechar>")
1005 'haskell-indentation-delete-char)))
1006
1007 ;;copied from haskell-mode docs in order to use the new, better, nondefault
1008 ;;interactive mode.
1009 (eval-after-load "haskell-mode"
1010 '(progn
1011 (define-key haskell-mode-map (kbd "C-x C-d") nil)
1012 (define-key haskell-mode-map (kbd "C-c C-z") 'haskell-interactive-switch)
1013 (define-key haskell-mode-map (kbd "C-c C-l") 'haskell-process-load-file)
1014 (define-key haskell-mode-map (kbd "C-c C-b") 'haskell-interactive-switch)
1015 (define-key haskell-mode-map (kbd "C-c C-t") 'haskell-process-do-type)
1016 (define-key haskell-mode-map (kbd "C-c C-i") 'haskell-process-do-info)
1017 (define-key haskell-mode-map (kbd "C-c M-.") nil)
1018 (define-key haskell-mode-map (kbd "C-c C-d") nil)))
1019
1020 ;; ghc-mod install http://www.mew.org/~kazu/proj/ghc-mod/en/emacs.html
1021 ;; todo, try this out
1022 ;; (autoload 'ghc-init "ghc" nil t)
1023 ;;(add-hook 'haskell-mode-hook (lambda () (ghc-init) (flymake-mode)))
1024
1025
1026
1027 ;; from the package readme for ghci-completion
1028 (add-hook 'inferior-haskell-mode-hook 'turn-on-ghci-completion)
1029
1030
1031 ;; disable some rebinds. they are set to appropriate keys in the keybinds section
1032 (eval-after-load "haskell-mode"
1033 '(progn
1034 (define-key haskell-mode-map (kbd "C-a") 'nil)
1035 (define-key haskell-mode-map (kbd "C-j") 'nil)))
1036
1037 (eval-after-load "python-mode"
1038 '(progn
1039 (define-key python-mode-map (kbd "C-j") nil)))
1040
1041 (defun pretty-lambdas-haskell ()
1042 (font-lock-add-keywords
1043 nil `((,(concat "(?\\(" (regexp-quote "\\") "\\)")
1044 (0 (progn (compose-region (match-beginning 1) (match-end 1)
1045 ,(make-char 'greek-iso8859-7 107))
1046 nil))))))
1047 ;; from haskell-mode manual
1048 (add-hook 'haskell-mode-hook 'turn-on-haskell-decl-scan)
1049 (when (window-system)
1050 (add-hook 'haskell-mode-hook 'pretty-lambdas-haskell))
1051
1052 ;; added from haskell-mode website install instructions
1053 ;(load "/usr/share/emacs/site-lisp/haskell-mode/haskell-site-file")
1054 (add-hook 'haskell-mode-hook 'turn-on-haskell-doc-mode)
1055 ;;the three indentation modules are mutually exclusive - add at most one. Trying out the "most advanced"
1056 (add-hook 'haskell-mode-hook 'turn-on-haskell-indentation)
1057 ;;(add-hook 'haskell-mode-hook 'turn-on-haskell-indent)
1058 ;;(add-hook 'haskell-mode-hook 'turn-on-haskell-simple-indent)
1059
1060
1061 ;; todo, set this to some other key
1062 ;; (local-set-key (kbd "C-e") 'my-haskell-load-and-run)
1063
1064 (defun my-haskell-load-and-run ()
1065 "Loads and runs the current Haskell file."
1066 (interactive)
1067 (let ((start-buffer (current-buffer)))
1068 (inferior-haskell-load-and-run inferior-haskell-run-command)
1069 (sleep-for 0 100)
1070 (end-of-buffer)
1071 (pop-to-buffer start-buffer)))
1072
1073 ;; show haskell function in mode line
1074 ;; todo, this broke after updating emacs
1075 ;;(eval-after-load "which-func"
1076 ;; '(add-to-list 'which-func-modes 'haskell-mode))
1077
1078
1079
1080 (add-hook 'interactive-haskell-mode-hook 'ac-haskell-process-setup)
1081 (add-hook 'haskell-interactive-mode-hook 'ac-haskell-process-setup)
1082 (eval-after-load "auto-complete"
1083 '(add-to-list 'ac-modes 'haskell-interactive-mode))
1084
1085 (add-hook 'haskell-mode-hook
1086 (lambda () (define-key haskell-mode-map (kbd "C-(")
1087 (lambda () (interactive)
1088 (basic-save-buffer)
1089 (haskell-compile)
1090 (run-with-timer .3 nil 'repeat-shell)))))
1091 (add-hook 'haskell-cabal-mode-hook
1092 (lambda () (define-key haskell-cabal-mode-map (kbd "C-(") 'haskell-compile)))
1093
1094
1095
1096 (add-hook 'haskell-interactive-mode-hook
1097 (lambda ()
1098 (define-key haskell-interactive-mode-map "\r" nil)
1099 (define-key haskell-interactive-mode-map (kbd "RET")
1100 'haskell-interactive-mode-return)))
1101 (add-hook 'haskell-indentation-mode-hook (lambda () (define-key haskell-indentation-mode-map "\r" nil)))
1102
1103
1104
1105 (add-hook 'haskell-interactive-mode-hook
1106 (lambda ()
1107 (define-key haskell-interactive-mode-map (kbd "<C-M-return>") 'haskell-interactive-mode-newline-indent)))
1108
1109 ;;; isearch
1110 (setq
1111 isearch-allow-scroll t
1112 search-ring-update t) ;; dont start an edit when going to previous search
1113
1114 (defun isearch-yank-regexp (regexp)
1115 "Pull REGEXP into search regexp."
1116 (let ((isearch-regexp nil)) ;; Dynamic binding of global.
1117 (isearch-yank-string regexp))
1118 (isearch-search-and-update))
1119
1120 (defun isearch-yank-symbol (&optional partialp backward)
1121 "Put symbol at current point into search string.
1122
1123 If PARTIALP is non-nil, find all partial matches."
1124 (interactive "P")
1125
1126 (let (from to bound sym)
1127 (setq sym
1128 ; this block taken directly from find-tag-default
1129 ; we couldn't use the function because we need the internal from and to values
1130 (when (or (progn
1131 ;; Look at text around `point'.
1132 (save-excursion
1133 (skip-syntax-backward "w_") (setq from (point)))
1134 (save-excursion
1135 (skip-syntax-forward "w_") (setq to (point)))
1136 (> to from))
1137 ;; Look between `line-beginning-position' and `point'.
1138 (save-excursion
1139 (and (setq bound (line-beginning-position))
1140 (skip-syntax-backward "^w_" bound)
1141 (> (setq to (point)) bound)
1142 (skip-syntax-backward "w_")
1143 (setq from (point))))
1144 ;; Look between `point' and `line-end-position'.
1145 (save-excursion
1146 (and (setq bound (line-end-position))
1147 (skip-syntax-forward "^w_" bound)
1148 (< (setq from (point)) bound)
1149 (skip-syntax-forward "w_")
1150 (setq to (point)))))
1151 (buffer-substring-no-properties from to)))
1152 (cond ((null sym)
1153 (message "No symbol at point"))
1154 ((null backward)
1155 (goto-char (1+ from)))
1156 (t
1157 (goto-char (1- to))))
1158 (isearch-search)
1159 (if partialp
1160 (isearch-yank-string sym)
1161 (isearch-yank-regexp
1162 (concat "\\_<" (regexp-quote sym) "\\_>")))))
1163
1164 (defun isearch-current-symbol (&optional partialp)
1165 "Incremental search forward with symbol under point.
1166
1167 Prefixed with \\[universal-argument] will find all partial
1168 matches."
1169 (interactive "P")
1170 (let ((start (point)))
1171 (isearch-forward-regexp nil 1)
1172 (isearch-yank-symbol partialp)))
1173 ;; todo, make this
1174
1175 (defun isearch-backward-current-symbol (&optional partialp)
1176 "Incremental search backward with symbol under point.
1177
1178 Prefixed with \\[universal-argument] will find all partial
1179 matches."
1180 (interactive "P")
1181 (let ((start (point)))
1182 (isearch-backward-regexp nil 1)
1183 (isearch-yank-symbol partialp)))
1184
1185
1186
1187 ; lets look through emacs starter kit before we throw this out.
1188
1189
1190 ; automatically wrap to the top of the buffer when isearch fails
1191 (defadvice isearch-search (after isearch-no-fail activate)
1192 (unless isearch-success
1193 (ad-disable-advice 'isearch-search 'after 'isearch-no-fail)
1194 (ad-activate 'isearch-search)
1195 (isearch-repeat (if isearch-forward 'forward))
1196 (ad-enable-advice 'isearch-search 'after 'isearch-no-fail)
1197 (ad-activate 'isearch-search)))
1198
1199 ;; Activate occur easily inside isearch
1200 (define-key isearch-mode-map (kbd "C-o")
1201 (lambda () (interactive)
1202 (let ((case-fold-search isearch-case-fold-search))
1203 (occur (if isearch-regexp
1204 isearch-string
1205 (regexp-quote isearch-string))))))
1206 ;;; lisp / elisp mode setings
1207
1208 (add-hook 'emacs-lisp-mode-hook 'starter-kit-remove-elc-on-save)
1209 (defun starter-kit-remove-elc-on-save ()
1210 "If you're saving an elisp file, likely the .elc is no longer valid."
1211 (make-local-variable 'after-save-hook)
1212 (add-hook 'after-save-hook
1213 (lambda ()
1214 (if (file-exists-p (concat buffer-file-name "c"))
1215 (delete-file (concat buffer-file-name "c"))))))
1216
1217
1218 (defun emacs-lisp-mode-defaults ()
1219 ;; checkdoc has an annoying feature that wants a header and footer
1220 ;; in every elisp buffer as if they all were packages
1221 ;; todo, see if there is a way
1222 ;; to make checkdoc usable instead of just disabling it as I do here
1223 (if (boundp 'flycheck-checkers)
1224 (setq flycheck-checkers (remove 'emacs-lisp-checkdoc flycheck-checkers)))
1225 (eldoc-mode 1))
1226 (add-hook 'emacs-lisp-mode-hook 'emacs-lisp-mode-defaults)
1227
1228 (define-key lisp-mode-map (kbd "<M-up>") 'backward-up-list)
1229 (define-key lisp-mode-map (kbd "<M-down>") 'down-list)
1230 (define-key emacs-lisp-mode-map (kbd "<M-up>") 'backward-up-list)
1231 (define-key emacs-lisp-mode-map (kbd "<M-down>") 'down-list)
1232 (define-key emacs-lisp-mode-map (kbd "<M-escape>") 'find-function-at-point)
1233
1234 ;; interactive modes don't need whitespace checks
1235 (defun interactive-lisp-coding-defaults ()
1236 (whitespace-mode -1))
1237 (setq prelude-interactive-lisp-coding-hook 'prelude-interactive-lisp-coding-defaults)
1238
1239
1240 ;; ielm is an interactive Emacs Lisp shell
1241 (defun ielm-mode-defaults ()
1242 (run-hooks 'prelude-interactive-lisp-coding-hook)
1243 (turn-on-eldoc-mode))
1244 (add-hook 'ielm-mode-hook 'ielm-mode-defaults)
1245
1246 ;;; mediawiki
1247
1248 (eval-after-load "mediawiki"
1249 '(progn
1250 (remove-hook 'outline-minor-mode-hook 'mediawiki-outline-magic-keys)
1251 (add-hook 'mediawiki-mode-hook
1252 (lambda () (define-key mediawiki-mode-map (kbd "C-(") 'mediawiki-save-reload)))
1253
1254 ;; mediawiki mode has a bug that it will claim an edit conflict unless you reload after saving.
1255 ;; I also like to save with no edit summary for previewing on my local mw instance
1256 (defun mediawiki-save-reload ()
1257 (interactive)
1258 (and (mediawiki-save "") (mediawiki-reload)))))
1259 ;;; modes with little configuration needed
1260 ;; busted:
1261 ;;(require 'csv-mode)
1262 ;;(add-to-list 'auto-mode-alist '("\\.[Cc][Ss][Vv]\\'" . csv-mode))
1263
1264 ;; disabled temporarily
1265 ;;(add-hook 'outline-minor-mode-hook 'outshine-mode)
1266
1267 (setq org-caldav-url "https://cal.iankelling.org"
1268 org-caldav-calendar-id "ian"
1269 org-caldav-inbox "/p/cal.org")
1270 ;;(org-caldav-sync)
1271
1272
1273 ;;(require 'dtrt-indent)
1274 ;;(setq dtrt-indent-mode t)
1275
1276 (setq css-indent-offset 2)
1277
1278 (when (file-exists-p "/a/h/iank-mod.el")
1279 (load-file "/a/h/iank-mod.el"))
1280
1281 ;; from when i was running my own patches
1282 ;;(add-to-list 'load-path "/a/opt/ws-butler")
1283
1284 (require 'ws-butler)
1285 ;; todo: I think this is broken, it keeps collapsing the last line
1286 ;; for empty messages.
1287
1288 ;; the main problem is when it deletes the blank line at the end
1289 ;; of a message with an empty body. but I might also
1290 ;; be pasting whitespace significant things in here, so
1291 ;; just don't do anything.
1292 ;; todo: propose this upstream
1293 (add-to-list 'ws-butler-global-exempt-modes 'message-mode)
1294
1295 (ws-butler-global-mode)
1296
1297
1298
1299 (require 'nginx-mode)
1300 ;;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:
1301 ;;(add-to-list 'auto-mode-alist '("/etc/nginx/sites-available/.*" . nginx-mode))
1302
1303 ;; todo, put this on a hook with prog mode
1304 ;;(highlight-indentation-mode 1)
1305
1306 (add-hook 'auto-revert-tail-mode-hook
1307 (lambda ()
1308 (when (string=
1309 buffer-file-name
1310 "/var/log/cloudman/development/cm-service.log")
1311 (setq-local prev-auto-revert-max 0)
1312 ;; set buffer-local hook
1313 (add-hook 'after-revert-hook 'tail-colorize nil t))))
1314 (defun tail-colorize ()
1315 (ansi-color-apply-on-region prev-auto-revert-max (point-max))
1316 (setq-local prev-auto-revert-max (point-max)))
1317
1318
1319 ;; gnu global
1320 (add-hook 'c-mode-common-hook
1321 (lambda () (ggtags-mode 1)
1322 (setq c-label-minimum-indentation 0)))
1323
1324 (defun my-ggtags-init()
1325 ;; specific to my unusual keybind setup, you may want to
1326 ;; pick different keys
1327 (define-key ggtags-mode-map (kbd "C-M-o") 'ggtags-find-tag-dwim)
1328 (define-key ggtags-mode-map (kbd "C-M-m") 'ggtags-grep))
1329 (eval-after-load "ggtags" '(my-ggtags-init))
1330
1331
1332 (defun gtags-update-single(filename)
1333 "Update Gtags database for changes in a single file"
1334 (interactive)
1335 (start-process "update-gtags" "update-gtags" "bash" "-c" (concat "cd " ggtags-project-root " ; gtags --single-update " filename )))
1336
1337 (defun gtags-update-current-file()
1338 (interactive)
1339 (let ((rel-filename (replace-regexp-in-string
1340 ggtags-project-root "."
1341 (buffer-file-name (current-buffer)))))
1342 (gtags-update-single rel-filename)))
1343
1344 (defun gtags-update-hook()
1345 "Update GTAGS file incrementally upon saving a file"
1346 (when (and (boundp 'ggtags-mode) ggtags-mode ggtags-project-root)
1347 (gtags-update-current-file)))
1348
1349 (add-hook 'after-save-hook 'gtags-update-hook)
1350
1351 ;; i'd like to make some elisp which modifies a keymap to remove
1352 ;; all binds which don't match a predicate.
1353 ;; I tried setting a keymap to a new keymap,
1354 ;; but that didn't register as functional.
1355 ;; so I'd need to modify the list in place.
1356
1357 ;; colorize hex colors: use rainbow mode
1358
1359
1360 ;; message mode prompted me on first message.
1361 ;; a function which describes options then sets this
1362 ;; the other options were to use smtp directly or pass to another mail client
1363 ;; here we use the standard sendmail interface, which I use postfix for
1364 (setq send-mail-function (quote sendmail-send-it))
1365
1366 (global-set-key (kbd "C-M-w") 'spray-mode)
1367 ;; remember, h/l = move. f/s = faster/slower, space = pause, all others quit
1368
1369 ;; delete active selection with self-insert commands
1370 (delete-selection-mode t)
1371
1372 ;; Transparently open compressed files
1373 (auto-compression-mode t)
1374
1375 ;; Highlight matching parenthesesq when the pointq is on them.
1376 ;; not needed since smart paren mode?
1377 ;; (show-paren-mode 1)
1378
1379
1380 ;; not documented, but looking at the source, I find this
1381 ;; stops me from being asked what command on every C-c-c
1382 ;; when doing a latex document.
1383 (setq TeX-command-force "LaTeX")
1384
1385 ;; dot mode, repeats last action
1386 (require 'dot-mode)
1387 (add-hook 'find-file-hooks 'dot-mode-on)
1388
1389
1390 ;; clean up obsolete buffers automatically at midnight
1391 (require 'midnight)
1392
1393
1394 ;; disabled because it takes 400ms on startup
1395 ;; ;; emacs regexes are too limited.
1396 ;; (require 'foreign-regexp)
1397 ;; ;; perl is most powerful, but javascript is pretty close and
1398 ;; ;; I'd rather know javascript stuff than perl
1399 ;; (custom-set-variables
1400 ;; '(foreign-regexp/regexp-type 'javascript) ;; Choose by your preference.
1401 ;; '(reb-re-syntax 'foreign-regexp)) ;; Tell re-builder to use foreign regexp.
1402 ;; ;; it would be nice to add documentation to do this for more commands to that package
1403 ;; ;; disabled because it's too slow. but I'd still m-x it for advanced replacements
1404 ;; ;;(define-key global-map [remap isearch-forward-regexp] 'foreign-regexp/isearch-forward)
1405
1406
1407 ;; saner regex syntax
1408 (require 're-builder)
1409 (setq reb-re-syntax 'string)
1410
1411
1412 ;; use shift + arrow keys to switch between visible buffers
1413 ;; todo, set these keys to something else
1414 ;; (require 'windmove)
1415 ;; (windmove-default-keybindings)
1416
1417
1418 ;; show the name of the current function definition in the modeline
1419 ;;(require 'which-func)
1420 (setq which-func-modes t)
1421 (which-function-mode 1)
1422
1423
1424 ;; enable winner-mode to manage window configurations
1425 (winner-mode +1)
1426
1427 ;; meaningful names for buffers with the same name
1428 (require 'uniquify)
1429 (setq uniquify-buffer-name-style 'forward
1430 uniquify-separator "/"
1431 ;; for sdx work. until I figure out a better way.
1432 ;; maybe something like projectile can do it,
1433 ;; or hacking around the status bar
1434 uniquify-min-dir-content 2
1435 uniquify-after-kill-buffer-p t ; rename after killing uniquified
1436 uniquify-ignore-buffers-re "^\\*") ; don't muck with special buffers
1437
1438
1439 ;; makefiles require tabs
1440 ;; todo: find a makefile indent function that works,
1441 ;; best I could find is this one which means don't indent at all
1442 ;;
1443 (add-hook 'makefile-mode-hook
1444 (lambda ()
1445 (setq indent-tabs-mode t)
1446 (setq indent-line-function (lambda () 'no-indent))))
1447
1448
1449 ;; todo, turn on auto-fill just for txt files
1450 ;;(add-hook 'text-mode-hook 'turn-on-auto-fill)
1451 (add-hook 'text-mode-hook 'turn-on-flyspell)
1452
1453
1454 ;; auto indent shell script comments
1455 (setq sh-indent-comment t)
1456
1457 ;; random extra highlights
1458 (require 'volatile-highlights)
1459 (volatile-highlights-mode t)
1460
1461
1462 ;; make help buffers smaller when it makes sense
1463 (temp-buffer-resize-mode 1)
1464
1465
1466 (defun my-info-init()
1467 (require 'info+)
1468 ;; based on suggestions in info+.el, I also installed misc-fns, strings, and thingatpt+
1469 ;; remove some bad keybinds from info+
1470 (define-key Info-mode-map [mouse-4] nil)
1471 (define-key Info-mode-map [mouse-5] nil))
1472
1473 (add-hook 'info-mode-hook 'my-info-init)
1474
1475
1476 (setq sh-here-document-word "'EOF'")
1477
1478 (setq tramp-default-method "ssh")
1479 ;;; misc general settings
1480
1481 ;; from tramp manual, use the same ssh controlmaster. I was having problems with
1482 ;; tramp prompting me for a username and pass.
1483 (customize-set-variable 'tramp-use-ssh-controlmaster-options nil)
1484
1485 (setq
1486 auto-revert-interval 2
1487 ;; fix eof end of file newline
1488 mode-require-final-newline t
1489 require-final-newline t
1490 auto-revert-verbose nil
1491 auto-revert-remote-files t)
1492
1493 (ivy-mode 1)
1494 (add-hook 'text-mode-hook (lambda () (auto-fill-mode t)))
1495 (setq counsel-find-file-at-point t)
1496
1497 (eval-after-load "ido"
1498 ;; easier to read with just spaces as separator
1499 (quote (setf (nth 2 ido-decorations) " ")))
1500
1501
1502 ;; https://www.emacswiki.org/emacs/FillParagraph
1503 ;; make list items start paragraphs.
1504 (setq paragraph-start "\f\\|[ \t]*$\\|[ \t]*[-+*] ")
1505
1506 (setq sh-basic-offset 2)
1507 (setq vc-follow-symlinks t)
1508
1509 ;; give us a shell to start instead of scratch
1510 ;;(setq initial-buffer-choice (lambda () (new-shell)))
1511
1512
1513 ;; Seed the random-number generator
1514 (random t)
1515
1516 ;; easier to remember than keybinds
1517 (defalias 'scrypt 'mml-secure-message-encrypt-pgpmime)
1518 (defalias 'sign 'mml-secure-message-sign-pgpmime)
1519 ;; otherwise we get error on sending:
1520 ;; mml-secure-epg-sign: Couldn’t find any signer names; try setting `mml-secure-smime-sign-with-sender'.
1521 ;; i dunno why sign+encrypt doesnt cause this, seems kinda dumb,
1522 ;;
1523 (setq mml-secure-openpgp-sign-with-sender t)
1524 ;; i dun use smime, the smime signing fails complaining it doesnt have
1525 ;; my key. todo: learn about smime
1526 (setq mml-secure-smime-sign-with-sender t)
1527 (defun encrypt ()
1528 (interactive)
1529 (mml-secure-message-encrypt-pgpmime 'dontsign))
1530
1531 ;; don't highlight the region.
1532 (set-face-background 'region nil)
1533
1534 ;; this fixes save error for python example code
1535 (define-coding-system-alias 'UTF-8 'utf-8)
1536
1537 ;; i don't use frame titles, but if I ever do
1538 ;; this starter kit setting is probably good
1539 (if window-system (setq frame-title-format '(buffer-file-name "%f" ("%b"))))
1540
1541
1542 ;;(prefer-coding-system 'utf-8-unix)
1543
1544 ;; remove ugly 3d box feature
1545 (set-face-attribute 'mode-line nil :box nil)
1546
1547 (add-to-list 'default-frame-alist
1548 '(font . "DejaVu Sans Mono-11"))
1549 ; the default will jump 2 sizes.
1550 (setq text-scale-mode-step 1.1)
1551 (setq font-lock-maximum-decoration t
1552 inhibit-startup-message t
1553 transient-mark-mode t
1554 delete-by-moving-to-trash t
1555 shift-select-mode nil
1556 truncate-partial-width-windows nil
1557 uniquify-buffer-name-style 'forward
1558 oddmuse-directory "~/.emacs.d/oddmuse"
1559 echo-keystrokes 0.1
1560 mark-ring-max 160
1561 sort-fold-case t ; case insensitive line sorting
1562 global-mark-ring-max 1000
1563 ;; the visible bell seems to lag the ui
1564 ;;visible-bell t
1565 ;; turn off audible bell
1566 ;; https://www.emacswiki.org/emacs/AlarmBell
1567 ring-bell-function 'ignore
1568 case-replace nil
1569 revert-without-query '(".*")
1570 ;; don't pause display code on input.
1571 ;; smoother display performance at slight cost of input performance
1572 redisplay-dont-pause t
1573 font-lock-maximum-decoration t) ; probably default and not necesary
1574
1575
1576 (setq-default indent-tabs-mode nil ;; don't use tabs to indent
1577 cursor-type 'box
1578 fill-column 72
1579
1580 ;; wrap at word boundaries instead of mid-word
1581 word-wrap t
1582 imenu-auto-rescan t
1583 indicate-empty-lines t) ; mark end of buffer
1584
1585 (require 'smooth-scroll)
1586 ;; long gnus summary buffers lags too much with this,
1587 ;; but I like it enough to leave it enabled by default
1588 ;; and crank up the step size to be faster
1589 ;; and it doesn't have a way to enable it only for certain modes etc.
1590 ;; todo sometime, make it work for certain modes only
1591 (smooth-scroll-mode t)
1592 ;; its too slow with the default of 2
1593 (setq smooth-scroll/vscroll-step-size 7)
1594 ;; sublimity doesn't work as good going fast by default
1595 ;; smooth-scrolling.el, does not do smooth scrolling. its about cursor location
1596
1597
1598 (blink-cursor-mode '(-4))
1599 (menu-bar-mode -1)
1600 (tool-bar-mode -1)
1601
1602
1603 ;; enable various commands
1604 (put 'narrow-to-region 'disabled nil)
1605 (put 'narrow-to-page 'disabled nil)
1606 (put 'narrow-to-defun 'disabled nil)
1607 (put 'upcase-region 'disabled nil)
1608 (put 'downcase-region 'disabled nil)
1609 (put 'scroll-left 'disabled nil)
1610 ;; these from graphene, haven't read about them yet
1611 (put 'ido-complete 'disabled nil)
1612 (put 'ido-exit-minibuffer 'disabled nil)
1613 (put 'dired-find-alternate-file 'disabled nil)
1614 (put 'autopair-newline 'disabled nil)
1615
1616
1617
1618 ;;disable and minimize various prompts/messages
1619 (fset 'yes-or-no-p 'y-or-n-p)
1620 (setq confirm-nonexistent-file-or-buffer nil
1621 inhibit-startup-message t
1622 inhibit-startup-echo-area-message t
1623 inhibit-startup-screen t
1624 kill-buffer-query-functions (remq 'process-kill-buffer-query-function
1625 kill-buffer-query-functions))
1626
1627
1628 ;; exit without bothering me
1629 ;; http://stackoverflow.com/questions/2706527/make-emacs-stop-asking-active-processes-exist-kill-them-and-exit-anyway/2708042#2708042
1630 (add-hook 'comint-exec-hook
1631 (lambda () (set-process-query-on-exit-flag (get-buffer-process (current-buffer)) nil)))
1632 ;; based on save-buffers-kill-emacs help string, don't ask about clients when exiting
1633 ;; apparently this would need to be in some later hook. dunno where is best, but this works
1634 (defadvice save-buffers-kill-emacs (before no-client-prompt-advice activate)
1635 (setq kill-emacs-query-functions (delq 'server-kill-emacs-query-function kill-emacs-query-functions)))
1636
1637
1638
1639 ;; (custom-set-faces
1640 ;; ;; setting header-line-format to " " as a hack for a top margin the oly thning I could find to do a top margin
1641 ;; '(header-line ((t (:background "default" :foreground "default" :overline nil :underline nil))))
1642 ;; ;; don't highlight the region
1643 ;; '(region ((t nil))))
1644 (setq-default header-line-format " ")
1645
1646
1647 (setq initial-scratch-message nil)
1648
1649
1650 ;; vertical margin background.
1651 ;; google turned up: http://lists.gnu.org/archive/html/help-gnu-emacs/2014-03/msg00544.html
1652 ;; the xresource doesn't work for me, probably an xmonad thing.
1653
1654 ;; figured out I needed to customize the header line face. To find the face, M-x list-faces-display or just google / search
1655 ;; info,
1656 ;; then M-x customize-face
1657 ;; header-line
1658 ;; unchecked some stuff so that it inherits from default.
1659
1660 ;;; misc function definitions
1661
1662
1663 (defun fill-buffer ()
1664 (interactive)
1665 (save-mark-and-excursion
1666 (beginning-of-buffer)
1667 (while (= (forward-line) 0)
1668 (fill-paragraph))))
1669
1670
1671 (defun next-backup-dir ()
1672 "In a directory listing from rsync -n,
1673 Go to the next directory based on where the cursor is."
1674 (interactive)
1675 (let* ((start-col (current-column))
1676 (end-col (progn (skip-chars-forward "^/\n") (current-column)))
1677 (dir (progn
1678 (beginning-of-line 1)
1679 (buffer-substring-no-properties (point) (+ (point) end-col)))))
1680 (message dir)
1681 (forward-line 1)
1682 (while (and (not (eobp))
1683 (string= dir (buffer-substring-no-properties (point) (+ (point) end-col))))
1684 (forward-line 1))
1685 (forward-char-same-line start-col)))
1686 ;; copy paste this for fast keybind
1687 ;;(local-set-key (kbd "<kp-enter>"))
1688
1689
1690 (defun goto-buffer-or-find-file (file-name)
1691 "If buffer is with FILE-NAME exists, go to it, else open the file using full path."
1692 (interactive)
1693 (let ((b (get-buffer (file-name-nondirectory file-name))))
1694 (if b
1695 (switch-to-buffer b)
1696 (find-file file-name))))
1697
1698
1699
1700
1701 ;; todo, i think this is broken. perhaps the last goto-char is not accounting for buffer or something
1702 (defun unpop-global-mark ()
1703 "Unpop off global mark ring. Does nothing if mark ring is empty."
1704 (interactive)
1705 (when global-mark-ring
1706 (setq global-mark-ring (cons (copy-marker (mark-marker)) global-mark-ring))
1707 (let ((lm (car (last global-mark-ring))))
1708 (set-marker (mark-marker) (marker-position lm) (marker-buffer lm)))
1709 (when (null (mark t)) (ding))
1710 (setq global-mark-ring (nbutlast global-mark-ring))
1711 (goto-char (marker-position (mark-marker)))))
1712
1713 (defun indent-buffer ()
1714 "Indents the entire buffer."
1715 (interactive)
1716 (cond ((derived-mode-p 'org-mode)
1717 (org-indent-region (point-min) (point-max)))
1718 ((derived-mode-p 'python-mode)
1719 (py-autopep8))
1720 (t
1721 (indent-region (point-min) (point-max)))))
1722
1723
1724 ;; TODO doesn't work with uniquify
1725 (defun rename-file-and-buffer ()
1726 "Renames current buffer and file it is visiting."
1727 (interactive)
1728 (let ((name (buffer-name))
1729 (filename (buffer-file-name)))
1730 (if (not (and filename (file-exists-p filename)))
1731 (message "Buffer '%s' is not visiting a file!" name)
1732 (let ((new-name (read-file-name "New name: " filename)))
1733 (cond ((get-buffer new-name)
1734 (message "A buffer named '%s' already exists!" new-name))
1735 (t
1736 (rename-file name new-name 1)
1737 (rename-buffer new-name)
1738 (set-visited-file-name new-name)
1739 (set-buffer-modified-p nil)))))))
1740
1741
1742
1743 (defun sudo-edit (&optional arg)
1744 (interactive "P")
1745 (if (or arg (not buffer-file-name))
1746 (find-file (concat "/sudo::" (ido-read-file-name "File: ")))
1747 (find-alternate-file (concat "/sudo::" buffer-file-name))))
1748
1749
1750
1751 (defun backward-symbol (arg)
1752 (interactive "p")
1753 (forward-symbol (- arg)))
1754
1755 ;;; mode line
1756 ;; make window title be the buffer name
1757 (setq frame-title-format "%b")
1758
1759 ; -----------------------------
1760 ; fixing up the mode line
1761 ; modified from mastering emacs blog
1762 ; ----------------------------
1763
1764 (defvar mode-line-cleaner-alist
1765 `((auto-complete-mode . "")
1766 (yas/minor-mode . "")
1767 (paredit-mode . "")
1768 (auto-fill-function . "")
1769 (eldoc-mode . "")
1770 (abbrev-mode . "")
1771 (flyspell-mode . "")
1772 (glasses-mode . "")
1773 (dot-mode . "")
1774 (yas-global-mode . "")
1775 (yas-minor-mode . "")
1776 (undo-tree-mode . "")
1777 (volatile-highlights-mode . "")
1778 (highlight-symbol-mode . "")
1779 ;; Major modes
1780 (lisp-interaction-mode . "λ")
1781 (hi-lock-mode . "")
1782 (python-mode . "Py")
1783 (emacs-lisp-mode . "EL")
1784 (nxhtml-mode . "nx"))
1785 "Alist for `clean-mode-line'.
1786
1787 When you add a new element to the alist, keep in mind that you
1788 must pass the correct minor/major mode symbol and a string you
1789 want to use in the modeline *in lieu of* the original.")
1790
1791
1792 (defun clean-mode-line ()
1793 (interactive)
1794 (loop for cleaner in mode-line-cleaner-alist
1795 do (let* ((mode (car cleaner))
1796 (mode-str (cdr cleaner))
1797 (old-mode-str (cdr (assq mode minor-mode-alist))))
1798 (when old-mode-str
1799 (setcar old-mode-str mode-str))
1800 ;; major mode
1801 (when (eq mode major-mode)
1802 (setq mode-name mode-str)))))
1803
1804 ; disabled
1805 ; (add-hook 'after-change-major-mode-hook 'clean-mode-line)
1806
1807
1808 ;;; alias the new `flymake-report-status-slim' to
1809 ;;; `flymake-report-status'
1810 (defalias 'flymake-report-status 'flymake-report-status-slim)
1811 (defun flymake-report-status-slim (e-w &optional status)
1812 "Show \"slim\" flymake status in mode line."
1813 (when e-w
1814 (setq flymake-mode-line-e-w e-w))
1815 (when status
1816 (setq flymake-mode-line-status status))
1817 (let* ((mode-line " Φ"))
1818 (when (> (length flymake-mode-line-e-w) 0)
1819 (setq mode-line (concat mode-line ":" flymake-mode-line-e-w)))
1820 (setq mode-line (concat mode-line flymake-mode-line-status))
1821 (setq flymake-mode-line mode-line)
1822 (force-mode-line-update)))
1823
1824
1825 (defun my-after-change-major-mode-hook ()
1826 (setq mode-line-mule-info nil
1827 minor-mode-alist nil
1828 mode-line-position nil)) ; todo, make only flymake status show up
1829
1830 (add-hook 'after-change-major-mode-hook 'my-after-change-major-mode-hook)
1831
1832 ;;; mouse related
1833 ;;;; settings
1834 (setq focus-follows-mouse t
1835 mouse-autoselect-window t
1836 xterm-mouse-mode t)
1837 ;;;; move-mouse-to-point
1838 ;; todo, this is buggy with multiple windows open.
1839 (defun move-mouse-to-point ()
1840 (interactive)
1841 (let* ((pos (posn-col-row (posn-at-point)))
1842 (x (+ (car pos) 2)) ; no idea why this is off by 1-2
1843 (y (cdr pos)))
1844 (set-mouse-position (selected-frame) x y)))
1845
1846 ;;;; keybinds for wow mouse
1847
1848 (global-set-key (kbd "<mouse-6>") 'move-mouse-to-point)
1849 (global-set-key (kbd "<kp-left>") 'indent-region)
1850 (global-set-key (kbd "<kp-begin>") 'mark-defun)
1851 (global-set-key (kbd "<kp-right>") 'ibuffer)
1852 (global-set-key (kbd "<kp-prior>") 'delete-horizontal-space)
1853
1854 ;;; org mode
1855
1856 ;; todo work on org-cycle-emulate-tab
1857
1858 ;; todo, this doesn't work for a non-standard keybind
1859 ;;(setq org-special-ctrl-k t)
1860
1861 ;; todo, generally fix org mode keys
1862 ;; todo, org-mark-element, unbdind from M-h, bind to mark defun key
1863
1864 ;(org-babel-do-load-languages
1865 ; 'org-babel-load-languages
1866 ; '((emacs-lisp . t)
1867 ; (sh . t)))
1868
1869
1870
1871 ;; make shell work like interactive bash shell
1872 (setq org-babel-default-header-args:sh
1873 '((:results . "output") (:shebang . "#!/bin/bash -l")))
1874
1875 ;; my patch to output stderr
1876 (setq org-babel-use-error-buffer nil)
1877
1878 ;
1879 ;; org-mode manual suggests these, but I haven't used them.
1880 ;;(global-set-key "\C-cl" 'org-store-link)
1881 ;;(global-set-key "\C-ca" 'org-agenda)
1882 ;; this got in the way of a haskell mode command
1883 ;;(global-set-key "\C-cb" 'org-iswitchb)
1884
1885
1886
1887 ;; org-src-tab-acts-natively t ; broken option. using next instead, todo fix
1888
1889 (setq org-src-fontify-natively t ; make babel blocks nice
1890 org-adapt-indentation nil
1891 org-src-preserve-indentation t
1892 ;; The most basic logging is to keep track of when a TODO item was finished.
1893 org-log-done 'time
1894 ;; use a drawer to keep the logs tidy
1895 org-log-into-drawer t
1896 org-extend-today-until 0
1897 org-startup-truncated nil
1898 org-clock-persist t
1899 org-use-sub-superscripts "{}"
1900 org-export-with-sub-superscripts nil
1901 org-clock-mode-line-total 'today
1902 ;; global STYLE property values for completion
1903 org-global-properties (quote (("STYLE_ALL" . "habit")))
1904 org-special-ctrl-a/e t ;; home and end work special in headlines
1905 org-completion-use-ido t
1906 org-catch-invisible-edits 'smart)
1907
1908 ;; non universally recommended settings
1909 (setq
1910 org-default-notes-file "/a/t.org"
1911 org-agenda-files (quote ("/a/t.org"))
1912 org-mobile-directory "/p/org-mobile"
1913 org-mobile-inbox-for-pull "/p/from-mobile.org"
1914 org-directory "/p")
1915
1916 ;; modeilne populated from (org-clock-get-clocked-time)
1917 ;; which is populated from the var org-clock-total-time
1918 ;; which is populated by a function which starts from (org-clock-get-sum-start)
1919 ;;
1920
1921 (eval-after-load "org"
1922 '(org-clock-persistence-insinuate))
1923
1924
1925 (defun time-to-org-day (time)
1926 (round (time-to-number-of-days
1927 (time-subtract time (list 0 (* 3600 org-extend-today-until) 0)))))
1928
1929
1930 (defun my-org-confirm-babel-evaluate (lang body)
1931 (not (or (string= (buffer-file-name) "/a/t.org")
1932 (string= (buffer-file-name) "/home/iank/.emacs.d/my-init.org")
1933 )))
1934 (setq org-confirm-babel-evaluate 'my-org-confirm-babel-evaluate)
1935
1936
1937 (defun org-time-stamp-with-time (arg)
1938 (interactive "P")
1939 ;; '(4) is the argument passed by universal prefix
1940 (org-time-stamp (if arg arg '(4)) t))
1941
1942 (defun ian-org-work-time ()
1943 (interactive)
1944 (save-excursion
1945 (set-buffer "t.org")
1946 (goto-char (org-find-entry-with-id "ian-identifier-1"))
1947 (org-clock-in)))
1948
1949 (defun ian-org-idle-time ()
1950 (interactive)
1951 (save-excursion
1952 (goto-char (org-find-entry-with-id "ian-identifier-2"))
1953 (set-buffer "t.org")
1954 (org-clock-in)))
1955
1956
1957
1958 ;; based on http://stackoverflow.com/questions/3758139/variable-pitch-for-org-mode-fixed-pitch-for-tables
1959 ;; keywords: proportional font, monospace
1960
1961 (defun variable-pitch-on ()
1962 (variable-pitch-mode 1))
1963 (add-hook 'fundamental-mode-hook 'variable-pitch-on)
1964 (add-hook 'org-mode-hook 'variable-pitch-on)
1965 (add-hook 'text-mode-hook 'variable-pitch-on)
1966 (defun variable-pitch-off ()
1967 (variable-pitch-mode 0))
1968 (add-hook 'yaml-mode-hook 'variable-pitch-off)
1969
1970 (eval-after-load "org" '(my-org-face-init))
1971
1972 (defun my-org-face-init()
1973 (set-face-attribute 'org-table nil :family (face-attribute 'fixed-pitch :family))
1974 (set-face-attribute 'org-code nil :family (face-attribute 'fixed-pitch :family))
1975 (set-face-attribute 'org-formula nil :family (face-attribute 'fixed-pitch :family))
1976 (set-face-attribute 'org-link nil :family (face-attribute 'fixed-pitch :family))
1977 (set-face-attribute 'org-block nil :family (face-attribute 'fixed-pitch :family))
1978 (set-face-attribute 'org-date nil :family (face-attribute 'fixed-pitch :family))
1979 )
1980
1981 (defun remove-org-binds ()
1982 (define-key org-mode-map (kbd "<M-return>") nil)
1983 (define-key org-mode-map (kbd "C-'") nil)
1984 (define-key org-mode-map (kbd "C-y") nil)
1985 (define-key org-mode-map (kbd "<C-return>") nil)
1986 (define-key org-mode-map (kbd "<C-M-kp-enter>") nil)
1987 (define-key org-mode-map (kbd "C-,") nil)
1988 (define-key org-mode-map (kbd "C-M-m") nil)
1989 (define-key org-mode-map (kbd "C-k") nil)
1990 (define-key org-mode-map (kbd "C-j") nil)
1991 (define-key org-mode-map (kbd "C-M-i") nil)
1992 (define-key org-mode-map (kbd "C-M-t") nil)
1993 (define-key org-mode-map (kbd "M-a") 'nil)
1994 (define-key org-mode-map (kbd "C-a") nil)
1995 (define-key org-mode-map (kbd "M-e") nil)
1996 (define-key org-mode-map (kbd "C-e") nil)
1997 (define-key org-mode-map (kbd "C-3") nil)
1998 (define-key org-mode-map (kbd "<M-left>") nil)
1999 (define-key org-mode-map (kbd "<M-right>") nil)
2000 (define-key org-mode-map (kbd "<S-return>") nil)
2001 (define-key org-mode-map (kbd "<tab>") nil)
2002 (define-key org-mode-map (kbd "<C-S-down>") nil)
2003 (define-key org-mode-map (kbd "<C-S-up>") nil)
2004 (define-key org-mode-map (kbd "<S-down>") nil)
2005 (define-key org-mode-map (kbd "<S-up>") nil)
2006 (define-key org-mode-map "\t" nil))
2007 (add-hook 'org-mode-hook 'remove-org-binds)
2008
2009 ;;; prog-mode-defaults
2010
2011
2012 (defun prog-mode-defaults ()
2013 "Default coding hook, useful with any programming language."
2014 ;; so that I can do completion before the dialog pops up
2015 ;;(local-set-key (kbd "<tab>") 'auto-complete)
2016 (local-set-key (kbd "TAB") 'auto-complete)
2017 ;; todo, this is causing error message on loading file, prolly not working
2018 ;;(flycheck-mode +1)
2019 (setq ac-sources (delq 'ac-source-dictionary ac-sources))
2020 (highlight-symbol-mode)
2021 (make-local-variable 'column-number-mode)
2022 ;; this says do autofilling using newcomment.el. The "only" is a misnomer.
2023 (set (make-local-variable 'comment-auto-fill-only-comments) t)
2024 (column-number-mode t)
2025 (turn-on-smartparens-mode)
2026
2027 ;; prettify lambdas
2028 (font-lock-add-keywords
2029 nil `(("(\\(lambda\\>\\)"
2030 (0 (progn (compose-region (match-beginning 1) (match-end 1)
2031 ,(make-char 'greek-iso8859-7 107))
2032 nil))))))
2033 (add-hook 'prog-mode-hook 'prog-mode-defaults)
2034
2035 ;; enable flyspell in prog mode. text mode is handled
2036 (add-hook 'prog-mode-hook 'flyspell-prog-mode)
2037
2038
2039
2040 ;;; yank auto-indent
2041 ;; automatically indenting yanked text if in programming-modes
2042 (defvar yank-indent-modes
2043 '(LaTeX-mode TeX-mode)
2044 "Modes in which to indent regions that are yanked (or yank-popped).
2045 Only modes that don't derive from `prog-mode' should be listed here.")
2046
2047 (defvar yank-indent-blacklisted-modes
2048 '(python-mode slim-mode haml-mode)
2049 "Modes for which auto-indenting is suppressed.")
2050
2051 (defvar yank-advised-indent-threshold 2000
2052 "Threshold (# chars) over which indentation does not automatically occur.")
2053
2054 (defun yank-advised-indent-function (beg end)
2055 "Do indentation, as long as the region isn't too large."
2056 (if (<= (- end beg) yank-advised-indent-threshold)
2057 (indent-region beg end nil)))
2058
2059 (defadvice yank (after yank-indent activate)
2060 "If current mode is one of 'yank-indent-modes,
2061 indent yanked text (with prefix arg don't indent)."
2062 (if (and (not (ad-get-arg 0))
2063 (not (member major-mode yank-indent-blacklisted-modes))
2064 (or (derived-mode-p 'prog-mode)
2065 (member major-mode yank-indent-modes)))
2066 (let ((transient-mark-mode nil))
2067 (yank-advised-indent-function (region-beginning) (region-end)))))
2068
2069 (defadvice yank-pop (after yank-pop-indent activate)
2070 "If current mode is one of 'yank-indent-modes,
2071 indent yanked text (with prefix arg don't indent)."
2072 (if (and (not (ad-get-arg 0))
2073 (not (member major-mode yank-indent-blacklisted-modes))
2074 (or (derived-mode-p 'prog-mode)
2075 (member major-mode yank-indent-modes)))
2076 (let ((transient-mark-mode nil))
2077 (yank-advised-indent-function (region-beginning) (region-end)))))
2078
2079
2080 ;;; shell mode
2081
2082
2083 ;; # eval: (outline-minor-mode)
2084 ;; # outline-regexp: "\\( *\\)# [*]\\{1,8\\} "
2085
2086
2087 ;; avoid stupid git crap like "warning, terminal not fully functional"
2088 (setenv "PAGER" "cat")
2089 ;; don't store successive duplicates in comint command history
2090 (setq comint-input-ignoredups t)
2091
2092 (defun add-mode-line-dirtrack ()
2093 (add-to-list 'mode-line-buffer-identification
2094 '(:propertize (" " default-directory " ") face dired-directory)))
2095 (add-hook 'shell-mode-hook 'add-mode-line-dirtrack)
2096
2097
2098 ;; don't fully understand it, but it works.
2099 ;; http://www.emacswiki.org/emacs/ShellDirtrackByProcfs
2100 (defun track-shell-directory/procfs ()
2101 (shell-dirtrack-mode 0)
2102 (add-hook 'comint-preoutput-filter-functions
2103 (lambda (str)
2104 (prog1 str
2105 (when (string-match comint-prompt-regexp str)
2106 (cd (file-symlink-p
2107 (format "/proc/%s/cwd" (process-id
2108 (get-buffer-process
2109 (current-buffer)))))))))
2110 nil t))
2111 (setq comint-buffer-maximum-size 100000)
2112 (add-to-list 'comint-output-filter-functions 'comint-truncate-buffer)
2113 (defun new-shell ()
2114 (interactive)
2115 (shell (generate-new-buffer-name "*shell*")))
2116 ;;
2117 (defun shell-wrap (prefix)
2118 "wrap the shell function, automatically generate a new name for a prefix arg"
2119 (interactive "P")
2120 (if prefix
2121 (new-shell)
2122 (shell)))
2123
2124 (add-hook 'shell-mode-hook 'track-shell-directory/procfs)
2125 ;;; smartparens
2126 ;; the melpa git version had a catastrophic bug I reported.
2127 ;; downgraded to marmalade version and everything is working fine.
2128 (require 'smartparens-config)
2129 (show-smartparens-global-mode t)
2130
2131
2132 (defun gp/sp/pair-on-newline-and-indent (id action context)
2133 "Open a new brace or bracket expression, with relevant newlines and indent. "
2134 (save-excursion
2135 (newline)
2136 (indent-according-to-mode))
2137 (indent-according-to-mode))
2138
2139 ;; when opening a pair, and then inserting a newline, push the closing pair to another newline
2140 (sp-pair "{" nil :post-handlers
2141 '(:add ((lambda (id action context)
2142 (gp/sp/pair-on-newline-and-indent id action context)) (kbd "RET"))))
2143 (sp-pair "[" nil :post-handlers
2144 '(:add ((lambda (id action context)
2145 (gp/sp/pair-on-newline-and-indent id action context)) (kbd "RET"))))
2146
2147
2148 ;; in my version, this is not a pairing.
2149 ;; not sure if it is in a future version since I reverted to marmalade
2150 ;; Don't need c-comments in strings -- they frustrate filename globs
2151 ;; (sp-pair "/*" nil :unless '(sp-in-string-p))
2152
2153 ;; Don't need quotes to pair next to words
2154 (sp-pair "\"" nil :unless '(sp-point-before-word-p sp-point-after-word-p))
2155 (sp-pair "'" nil :unless '(sp-point-before-word-p sp-point-after-word-p))
2156
2157
2158 ;; todo, testout these mode specific settings from graphene.
2159 ;; Ruby-specific pairs and handlers
2160
2161 (eval-after-load "ruby"
2162 '(require 'smartparens-ruby))
2163
2164 ;; Markdown
2165 (sp-local-pair '(markdown-mode gfm-mode) "*" "*"
2166 :unless '(sp-in-string-p)
2167 :actions '(insert wrap))
2168
2169 ;; Except in HTML
2170 (sp-local-pair 'html-mode "\"" nil :unless '(:rem sp-point-after-word-p))
2171
2172
2173
2174
2175 ;;; spell correction
2176 (setq
2177 ispell-program-name "hunspell"
2178 ispell-silently-savep t) ; don't prompt to save personal dictionary
2179
2180 (require 'rw-hunspell)
2181 ;; rw-hunspell sets up hunspell dictionary automagically.
2182
2183
2184 ;; Rant: Hunspell SHOULD be standard. its used by firefox and openoffice and
2185 ;; osx. In contrast, the first few words I added to aspell dictionary were
2186 ;; "emacs" "customizable" and "timestamp". Hunspell already has those,
2187 ;; thank god.
2188
2189 ;; ispell-personal-dictionary does not document where the hunspell
2190 ;; dictionary goes by default, but it is ~/.hunspell_en_US for me
2191
2192
2193 ;;; tex
2194 (setq-default TeX-PDF-mode t) ; use pdf
2195
2196 ; more sensible defaults based on info manual quickstart
2197 (setq TeX-auto-save t)
2198 (setq TeX-parse-self t)
2199
2200
2201
2202 ;;; visible mark mode
2203
2204 ;; since it is not easy to change the mark overlay priority, I change this one.
2205 (setq show-paren-priority 999)
2206
2207
2208 (defface visible-mark-active
2209 '((((type tty) (class mono)))
2210 (t (:background "magenta"))) "")
2211
2212
2213
2214 (defface mouse-cursor-face
2215 '((((type tty) (class mono)))
2216 (t (:background "DeepPink1"))) "")
2217
2218
2219 (require 'visible-mark)
2220
2221 (setq visible-mark-faces '(visible-mark-face1 visible-mark-face2))
2222 (setq visible-mark-forward-faces '(visible-mark-forward-face1))
2223
2224
2225 ; highlight the last 2 marks
2226 (setq visible-mark-max 2)
2227 ; highlight 1 forward mark
2228 (setq visible-mark-forward-max 1)
2229 ; globally activate visible-mark-mode
2230 (global-visible-mark-mode +1)
2231
2232
2233 ;; todo, it doesn't seem to be exposed in elisp, but it would be nice
2234 ;; if I could define overlay faces to use inverse foreground color
2235
2236
2237 ;;; znc
2238
2239
2240 (setq erc-fill-prefix "")
2241 (defun chirp()
2242 (interactive)
2243 (setq vol 50)
2244 (when (string= (system-name) "kd") (setq vol 80))
2245 ;; speed is there so i can adjust and make it go slow so it plays long enough to adjust in pavucontrol
2246 (start-process-shell-command "ignoreme" nil (format "mpv --speed=1 --no-terminal --vo=null --volume=%d /a/bin/data/bird.mp3" vol)))
2247 ;; from https://www.emacswiki.org/emacs/ErcSound
2248 (defun chirp-slow()
2249 (interactive)
2250 (setq vol 50)
2251 (when (string= (system-name) "tp") (setq vol 80))
2252 ;; speed is there so i can adjust and make it go slow so it plays long enough to adjust in pavucontrol
2253 (start-process-shell-command "ignoreme" nil (format "mpv --speed=.2 --no-terminal --vo=null --volume=%d /a/bin/data/bird.mp3" vol)))
2254
2255 (defun erc-my-privmsg-sound (proc parsed)
2256 (let* ((tgt (car (erc-response.command-args parsed)))
2257 (privp (erc-current-nick-p tgt)))
2258 (and
2259 privp (chirp)
2260 ;; We must return nil. See help for `erc-server-PRIVMSG-functions'
2261 nil)))
2262
2263 (add-hook 'erc-server-PRIVMSG-functions
2264 'erc-my-privmsg-sound)
2265
2266 (defun erc-sound-if-not-server (match-type nickuserhost msg)
2267 (unless (string-match "Server:[0-9]+" nickuserhost)
2268 (chirp)))
2269 (add-hook 'erc-text-matched-hook 'erc-sound-if-not-server)
2270
2271 (eval-after-load "erc"
2272 '(erc-track-mode 1))
2273 (setq
2274 ;; consider invisible frames to be unseen. seems like an obvious default
2275 erc-track-visibility 'visible
2276 ;; switch to buffer where i've been mentioned, etc instead of oldest
2277 erc-track-switch-direction 'importance
2278 ;; defaults minus fill. todo: modify the list instead of specifying it explicitly in case the defaults change
2279 erc-modules
2280 '(autojoin button completion irccontrols list match menu move-to-prompt netsplit networks noncommands readonly ring stamp track)
2281 )
2282
2283
2284 ;;; named commands
2285 (defun rm-file-and-buffer ()
2286 "Removes file connected to current buffer and kills buffer."
2287 (interactive)
2288 (let ((filename (buffer-file-name))
2289 (buffer (current-buffer))
2290 (name (buffer-name)))
2291 (if (not (and filename (file-exists-p filename)))
2292 (error "Buffer '%s' is not visiting a file!" name)
2293 (delete-file filename)
2294 (kill-buffer buffer)
2295 (message "File '%s' successfully removed" filename))))
2296
2297 ;;; persistent registers
2298 ;; This needs to be at the end, because I visit a file, thus setting a
2299 ;; mode, and the mode hook needs to be setup before that.
2300
2301 ;; I'm using persistent registers instead of bookmarks. I dun use them
2302 ;; much, so the added hassle of having to set it within this file is
2303 ;; worth the benefit of only having one concept in my mind.
2304 (dolist
2305 (r `(
2306 (?i (file . ,"~/.emacs.d/init.el"))
2307 (?o (file . ,"/a/work.org"))
2308 (?t (file . ,"/a/t.org"))
2309 (?s (file . ,"/usr/share/doc/exim4-base/spec.txt.gz"))
2310 (?w (file . ,"/p/w.org"))
2311 (?k (file . ,"/a/bin/ds/Arduino/Model01-Firmware/Model01-Firmware.ino"))
2312 (?x (file . ,"/a/x.txt"))
2313 ))
2314 (set-register (car r) (cadr r)))
2315
2316 (setq undo-outer-limit 100000000 ; per undo command
2317 undo-limit 500000000 ; undo history limit
2318 undo-strong-limit 600000000) ; undo history limit plus some extra
2319
2320
2321 ;;; undo tree mode
2322
2323 ;; note, this has weird errors when it was before recentf-mode
2324
2325 ;; more resilient undo-tree-history if we have its location set up front.
2326 (setq undo-tree-history-directory-alist '(("." . "~/.undo-tree-history")))
2327
2328
2329 ;; todo, send patch undo-tree-visualize should scroll with the scroll key, instead of just pgup pgdn (aka next/prior)
2330 (global-undo-tree-mode)
2331 ;; disabled due to bug, something like unknown entry in undo tree canary
2332 ;; (setq undo-tree-auto-save-history t)
2333 (setq undo-outer-limit 100000000 ; per undo command
2334 undo-limit 500000000 ; undo history limit
2335 undo-strong-limit 600000000) ; undo history limit plus some extra
2336 ;; Undo in region just happens accidentally, and throws me off
2337 (setq undo-tree-enable-undo-in-region nil)
2338
2339 ;;; keybinds
2340
2341 ;;;; misc
2342
2343 (define-prefix-command 'terminal-key-map)
2344 (global-set-key (kbd "\e[") 'terminal-key-map)
2345
2346
2347
2348 (global-set-key (kbd "C-x C-b") 'ibuffer)
2349
2350
2351 ;; isearch-occur
2352 ;; Activate occur easily inside isearch
2353 ;; from starter-kit
2354
2355 (define-key isearch-mode-map (kbd "C-o")
2356 (lambda () (interactive)
2357 (let ((case-fold-search isearch-case-fold-search))
2358 (occur (if isearch-regexp
2359 isearch-string
2360 (regexp-quote isearch-string))))))
2361
2362
2363 (defun my-isearch-toggle-regexp ()
2364 (interactive)
2365 (isearch-toggle-regexp)
2366 (cond (isearch-regexp
2367 (global-set-key (kbd "C-r") 'isearch-backward-regexp)
2368 (define-key global-map (kbd "<f12>") 'isearch-forward-regexp))
2369 (t
2370 (global-set-key (kbd "C-r") 'isearch-backward)
2371 (define-key global-map (kbd "<f12>") 'isearch-forward))))
2372 (define-key isearch-mode-map (kbd "M-r") 'my-isearch-toggle-regexp)
2373
2374
2375 (define-key Info-mode-map "x" 'Info-follow-nearest-node)
2376
2377
2378 ;;;; single/special keys
2379 ;;;;; tab - isearch
2380 ;; todo: this doesnt work. needs <tab>, which doesnt work in terminal. fix that.
2381 ;; (define-key isearch-mode-map (kbd "TAB") 'isearch-query-replace)
2382 (define-key isearch-mode-map (kbd "M-f") 'isearch-query-replace)
2383
2384 ;;;;; f12 - isearch-forward
2385 ;; explained in http://stackoverflow.com/questions/7411920/how-to-bind-search-and-search-repeat-to-c-f-in-emacs
2386 (global-set-key (kbd "<kp-add>") 'isearch-forward)
2387 (global-set-key (kbd "<f12>") 'isearch-forward)
2388 (define-key isearch-mode-map "\t" nil)
2389 (define-key isearch-mode-map (kbd "<kp-add>") 'isearch-repeat-forward)
2390 (define-key isearch-mode-map (kbd "<f12>") 'isearch-repeat-forward)
2391 ;; get rid of the standard completion binding, always use auto-complete
2392 ;; this didn't work very well
2393 ;;(global-set-key (kbd "TAB") 'auto-complete)
2394 (define-key global-map [remap completion-at-point] 'auto-complete)
2395
2396 ;;;;; end - move-end-of-line
2397 ;; taken from emacs wiki, along with home function
2398 ;; http://www.emacswiki.org/emacs/BackToIndentationOrBeginning
2399 (defun point-in-comment ()
2400 "Determine if the point is inside a comment"
2401 (interactive)
2402 (let ((syn (syntax-ppss)))
2403 (and (nth 8 syn)
2404 (not (nth 3 syn)))))
2405 (defun end-of-code-or-line (arg)
2406 "Move to end of line, or before start of comments depending on situation.
2407 Toggle back and forth positions if we are already at one.
2408 Comments are recognized in any mode that sets syntax-ppss
2409 properly."
2410 (interactive "P")
2411 (when (catch 'bol
2412 (let ((start (point))
2413 (bol (save-excursion
2414 (beginning-of-line)
2415 (point)))
2416 (eol (progn (move-end-of-line arg) (point))))
2417 (while (point-in-comment)
2418 (backward-char)
2419 (when (= (point) bol)
2420 (throw 'bol t)))
2421 (throw 'bol (and (not (= eol start)) (>= start (point))))))
2422 (move-end-of-line arg)))
2423
2424 (global-set-key (kbd "<end>") 'end-of-code-or-line)(add-hook 'org-mode-hook (lambda () (define-key org-mode-map (kbd "<end>") 'org-end-of-line)))
2425
2426 ;;;;; home - back-to-indentation
2427 (defun back-to-indentation-or-beginning ()
2428 (interactive)
2429 (if (= (point) (progn (back-to-indentation) (point)))
2430 (if (derived-mode-p 'org-mode)
2431 (org-beginning-of-line)
2432 (beginning-of-line))))
2433 (global-set-key (kbd "<home>") 'back-to-indentation-or-beginning)
2434
2435 ;;;;; s-tab - indent-buffer
2436 ;; graphical
2437 (global-set-key (kbd "<S-iso-lefttab>") 'indent-buffer)
2438 ;; terminal
2439 (global-set-key (kbd "<backtab>") 'indent-buffer)
2440 ;;;;; s-delete - send-shell
2441
2442 (global-set-key (kbd "<S-delete>") 'send-shell)
2443
2444 ;; optional variables used by send-shell
2445 (setq shell-send-yank-key nil)
2446
2447 (defun repeat-shell ()
2448 (interactive)
2449 "Repeat the last command in shell-mode, displaying the window if needed."
2450 (let ((shell-buffer (get-buffer "*shell*")))
2451 (if shell-buffer
2452 (buffer-window-show shell-buffer)
2453 (let ((original-buffer (current-buffer)))
2454 (funcall 'shell)
2455 (setq shell-buffer (current-buffer))
2456 (switch-to-buffer original-buffer)))
2457 (with-current-buffer shell-buffer
2458 (goto-char (point-max))
2459 (call-interactively 'comint-previous-input)
2460 ;; the t flag makes the buffer advance
2461 (comint-send-input nil t))))
2462
2463 (setq compilation-filenames '("Makefile" "makefile"))
2464
2465 (defun get-nearest-compilation-file ()
2466 "Search for the compilation file traversing up the directory tree."
2467 (interactive)
2468 (let ((dir default-directory)
2469 (parent-dir (file-name-directory (directory-file-name default-directory)))
2470 (nearest-compilation-file 'nil))
2471 (while (and (not (string= dir parent-dir))
2472 (not nearest-compilation-file))
2473 (dolist (filename compilation-filenames)
2474 (setq file-path (concat dir filename))
2475 (when (file-readable-p file-path)
2476 (setq nearest-compilation-file file-path)))
2477 (setq dir parent-dir
2478 parent-dir (file-name-directory (directory-file-name parent-dir))))
2479 nearest-compilation-file))
2480 (defun run ()
2481 (interactive)
2482 "call run-fun if it is set, else run make if there is a makefile,
2483 else save and repeat last shell command.
2484 run-fun is meant to store file local variables, which show how to
2485 do the main thing we want on this file, generally compile and
2486 run.
2487
2488 example of setting it in a file:
2489 ;; Local Variables:
2490 ;; run-fun: merge-test
2491 ;; End: "
2492 (basic-save-buffer)
2493 (if (and (boundp 'run-fun) run-fun)
2494 (funcall run-fun)
2495 (let ((makefile (get-nearest-compilation-file)))
2496 (if (and makefile (stringp mode-name) (string= mode-name "C/l"))
2497 (compile (format
2498 "make -f %s" (get-nearest-compilation-file)))
2499 (repeat-shell)))))
2500
2501
2502 (defun send-shell ()
2503 (interactive)
2504 (send-shell-buffer "*shell*" 'shell (kbd "C-v")))
2505
2506 (defun send-python ()
2507 (interactive)
2508 (send-shell-buffer "*Python*" 'py-shell (kbd "C-v")))
2509
2510
2511 (defun send-shell-buffer (buffer-name &optional init shell-send-yank-key)
2512 "Send current line or region to shell-mode buffer.
2513 When in shell-mode, copy the current line to the
2514 most recently visited visible window.
2515
2516 SHELL-SEND-YANK-KEY: key to use instead
2517 of yank to paste into recent window. This allows compatibility with
2518 modes like org-mode which have their own yank function."
2519 (if (string= (buffer-name) buffer-name)
2520 ;; this section is copied out of comint-send-input
2521 (progn
2522 (let ((proc (get-buffer-process (current-buffer))))
2523 (if (not proc) (user-error "Current buffer has no process")
2524 (widen)
2525
2526 (let* ((pmark (process-mark proc))
2527 (intxt (if (>= (point) (marker-position pmark))
2528 (progn (if comint-eol-on-send (end-of-line))
2529 (buffer-substring pmark (point)))
2530 (let ((copy (funcall comint-get-old-input)))
2531 (goto-char pmark)
2532 (insert copy)
2533 copy))))
2534
2535 (if (= (length intxt) 0)
2536 (kill-new (comint-previous-matching-input-string "." 1))
2537 (kill-new intxt)))))
2538 (kill-append "\n" nil)
2539 (select-window (previous-window nil nil 'visible))
2540 (if (and (boundp 'shell-send-yank-key) shell-send-yank-key)
2541 (call-interactively (global-key-binding shell-send-yank-key))
2542 (yank))
2543 (select-window (next-window nil nil 'visible)))
2544 (let (start end)
2545 (if mark-active
2546 (setq start (mark)
2547 end (point))
2548 (setq start (save-excursion (beginning-of-line) (point))
2549 end (save-excursion (end-of-line) (point)))
2550 (let (line-move-visual)
2551 (call-interactively 'next-line)))
2552 (send-comint-input buffer-name start end init))))
2553
2554 ;; supporting functions
2555 (defun send-comint-input (buffer-name start end &optional init)
2556 "Input the region to BUFFER-NAME, assuming it is a comint-derived buffer.
2557 Show BUFFER-NAME if it is not show.
2558 Call INIT if BUFFER-NAME does not exist."
2559 (let ((input (filter-buffer-substring start end)))
2560 (send-comint-string buffer-name input init)))
2561
2562 (defun send-comint-string (buffer-name string &optional init)
2563 "Input the string to BUFFER-NAME, assuming it is a comint-derived buffer.
2564 Show BUFFER-NAME if it is not show.
2565 Call INIT if BUFFER-NAME does not exist."
2566 (let ((buffer (get-buffer buffer-name)))
2567 (unless buffer
2568 (message "nobuffer")
2569 ;; save-excursion etc. don't work for (shell), so I do this instead
2570 (if init (let ((original-buffer (current-buffer)))
2571 (funcall init (and (boundp 'send-shell-buffer-name) send-shell-buffer-name))
2572 (switch-to-buffer original-buffer)
2573 (setq buffer (get-buffer buffer-name)))
2574 (error "No existing buffer found and no init function argument. ")))
2575 (buffer-window-show buffer)
2576 (with-current-buffer buffer
2577 (let ((proc (get-buffer-process buffer)))
2578 (goto-char (process-mark proc))
2579 (insert string)
2580 (comint-send-input nil t)))))
2581
2582 (defun buffer-window-show (&optional buffer action)
2583 "Like temp-buffer-window-show, but removed stuff
2584 relevant to it being temp or help."
2585 (let (window frame)
2586 (with-current-buffer buffer
2587 (when (let ((window-combination-limit
2588 ;; When `window-combination-limit' equals
2589 ;; `temp-buffer' or `temp-buffer-resize' and
2590 ;; `temp-buffer-resize-mode' is enabled in this
2591 ;; buffer bind it to t so resizing steals space
2592 ;; preferably from the window that was split.
2593 (if (or (eq window-combination-limit 'temp-buffer)
2594 (and (eq window-combination-limit
2595 'temp-buffer-resize)
2596 temp-buffer-resize-mode))
2597 t
2598 window-combination-limit)))
2599 ;; debug
2600 ;;(message "window-combination-limit")
2601 ;;(print window-combination-limit)
2602 (setq window (display-buffer buffer action)))
2603 (setq frame (window-frame window))
2604 (unless (eq frame (selected-frame))
2605 (raise-frame frame))
2606 (setq minibuffer-scroll-window window)
2607 (set-window-hscroll window 0)
2608 ;; Return the window.
2609 window))))
2610
2611
2612 ;; when poping help, etc, allow reusing a window in a different frame if it is visible
2613 ;; figured this out after spending quite a while reading doc string for display-buffer
2614 ;; which is the main function which uses this.
2615 ;; it will use other vars or its arg to override this,
2616 ;; but those things are often nil.
2617 ;; aha moments in reading it: ACTION = (FUNCTION-or-FUNCTIONLIST ALIST)
2618 ;; FRAME adds an association to ACTION's alist, but it's not used if ACTION arg is nil.
2619 (setq display-buffer-fallback-action `(,(car display-buffer-fallback-action) . '(reusable-frames . visible)))
2620 ;; stop splitting windows verticallly when I open a buffer or shell
2621 (setq split-height-threshold nil)
2622
2623 ;;;;; s-left arrow - ---
2624 ;; cant be used in terminal
2625 ;; When I had a binding, i did this so org-mode wouldnt clobber it
2626 ;; (add-hook 'org-mode-hook
2627 ;; (lambda ()
2628 ;; (define-key org-mode-map (kbd "<S-left>") nil)))
2629
2630 ;;;;; s-right arrow - keyboard-yank-primary
2631 (defun keyboard-yank-primary ()
2632 (interactive)
2633 (let ((mouse-yank-at-point t))
2634 (mouse-yank-primary nil)))
2635 ;; paste selection
2636 (global-set-key (kbd "<S-right>") 'keyboard-yank-primary)
2637 (add-hook 'org-mode-hook
2638 (lambda ()
2639 (define-key org-mode-map (kbd "<S-right>") nil)))
2640 ;;;;; esc
2641 ; todo, test out if this can be used
2642 ;;;;; return - new line
2643
2644 ;; todo, this doesn't set the keybind for the help minibuffer
2645
2646
2647 (global-set-key (kbd "\r") 'indent-new-comment-line)
2648
2649 ;; don't use enter for autocomplete, we use tab or something
2650 (define-key ac-completing-map (kbd "<return>") nil)
2651 (define-key ac-completing-map "\r" nil)
2652
2653 (add-hook 'org-mode-hook
2654 (lambda ()
2655 ;; copied from org-mode, replace org-enter with org-enter-indent
2656 (org-defkey org-mode-map "\C-m" 'org-return-indent)))
2657
2658
2659 (add-hook 'comint-mode-hook
2660 (lambda ()
2661 (define-key comint-mode-map "\r" nil)
2662 (define-key comint-mode-map (kbd "RET") 'comint-send-input)))
2663
2664 (add-hook 'comint-mode-hook
2665 (lambda ()
2666 (define-key comint-mode-map "\C-m" nil)
2667 (define-key comint-mode-map "\C-d" nil)))
2668
2669 ;;;;; s-return - auto-correct-prev-word
2670 (global-set-key (kbd "<S-return>") 'flyspell-auto-correct-previous-word)
2671 ;; kp-enter is shift return in terminal
2672 (global-set-key (kbd "<kp-enter>") 'flyspell-auto-correct-previous-word)
2673
2674 ;;;;; s-up arrow - my-contract-region
2675 (global-set-key (kbd "<S-up>") 'my-contract-region)
2676 ;;;;; c-up/down move 8 lines
2677
2678 ;; compiling warns that next-line should be called interactively,
2679 ;; but we would have to do something dumb, like give it a
2680 ;; vector of keys in order to supply the 8 argument
2681 (defun down-fast ()
2682 (interactive)
2683 (next-line 8))
2684 (defun up-fast ()
2685 (interactive)
2686 (next-line -8))
2687
2688 (global-set-key (kbd "<C-up>") 'up-fast)
2689 (global-set-key (kbd "<C-down>") 'down-fast)
2690
2691 ;;;;; c-scroll comint prev/next prompt
2692
2693 (add-hook 'comint-mode-hook
2694 (lambda ()
2695 (define-key comint-mode-map (kbd "<C-mouse-4>") 'comint-previous-prompt)
2696 (define-key comint-mode-map (kbd "<C-mouse-5>") 'comint-next-prompt)))
2697 ;;;;; m-scroll prev/next sexp
2698 (global-set-key (kbd "<M-mouse-4>") 'backward-sexp)
2699 (global-set-key (kbd "<M-mouse-5>") 'forward-sexp)
2700 ;;;;; S-scroll expand/contract region
2701 (global-set-key (kbd "<S-mouse-13>") 'my-contract-region)
2702 (global-set-key (kbd "<S-mouse-14>") 'er/expand-region)
2703 (global-set-key (kbd "<S-mouse-4>") 'my-contract-region)
2704 (global-set-key (kbd "<S-mouse-5>") 'er/expand-region)
2705
2706 (defun my-contract-region (arg)
2707 (interactive "p")
2708 (let ((current-prefix-arg '-))
2709 (call-interactively 'er/expand-region)))
2710
2711 ;; todo: define c-m scroll. i manually set to normal scrolling, i dunno why
2712
2713
2714 ;;;;; c-s-scroll scale text
2715
2716 (global-set-key (kbd "<C-S-mouse-4>") 'text-scale-increase)
2717 (global-set-key (kbd "<C-S-mouse-5>") 'text-scale-decrease)
2718 (global-set-key (kbd "<C-S-mouse-13>") 'text-scale-increase)
2719 (global-set-key (kbd "<C-S-mouse-14>") 'text-scale-decrease)
2720 (global-set-key (kbd "<C-S-down>") 'text-scale-increase)
2721 (global-set-key (kbd "<C-S-up>") 'text-scale-decrease)
2722
2723
2724 ;;;;; s-up arrow er/expand-region
2725 (global-set-key (kbd "<S-down>") 'er/expand-region)
2726 ;;;;; c-left/right move symbol
2727
2728 (global-set-key (kbd "<C-left>") 'backward-symbol)
2729 (global-set-key (kbd "<C-right>") 'forward-symbol)
2730
2731 ;;;; left primary
2732
2733 ;;;;; M-2 shell-cd-to-file
2734
2735
2736 (defun shell-cd-to-file ()
2737 (interactive)
2738 (let ((file (buffer-file-name)))
2739 (if file
2740 (send-comint-string "*shell*"
2741 (concat "c " (file-name-directory file))
2742 'shell)
2743 (message "%s" "shell-cd-to-file: buffer has no file name"))))
2744 (global-set-key (kbd "M-2") 'shell-cd-to-file)
2745
2746 ;;;;; C-M-2 copy-symbol
2747 (global-unset-key (kbd "C-M-2"))
2748 (defun copy-symbol (&optional arg)
2749 "Copy symbol at point into kill-ring"
2750 (interactive "P")
2751 (kill-new (thing-at-point 'symbol)))
2752
2753 (global-set-key (kbd "C-M-2") 'copy-symbol)
2754
2755 ;;;;; M-3 dot-mode-execute
2756
2757 (global-set-key (kbd "M-3") 'dot-mode-execute)
2758
2759 ;;;;; C-M-3 recenter-top-bottom
2760
2761 (global-set-key (kbd "C-M-3") 'recenter-top-bottom)
2762
2763 ;;;;; C-q org-cycle, comint previous arg
2764
2765 (global-set-key (kbd "C-q") 'bicycle-cycle)
2766 (add-hook 'org-mode-hook
2767 (lambda () (define-key org-mode-map (kbd "C-q") 'org-cycle)))
2768 (define-key widget-keymap (kbd "C-q") 'widget-forward)
2769 (add-hook 'comint-mode-hook
2770 (lambda () (define-key comint-mode-map (kbd "C-q") 'comint-insert-previous-argument)))
2771
2772 ;;;;; M-q org-archive-to-archive-sibling
2773
2774 (global-set-key (kbd "M-q") 'org-archive-to-archive-sibling)
2775
2776 ;;;;; C-M-q quoted-insert
2777
2778 (global-set-key (kbd "C-M-q") 'quoted-insert)
2779
2780 ;;;;; C-w counsel-find-file
2781
2782 (global-set-key (kbd "C-w") 'counsel-find-file)
2783
2784 ;;;;; M-w shell
2785
2786 (global-set-key (kbd "M-w") 'shell-wrap)
2787
2788 ;;;;; C-e copy-line
2789
2790 ;; todo, make repeated calls to this append the kills
2791 (defun copy-line (&optional arg)
2792 "Copy lines (as many as prefix argument) in the kill ring.
2793 Ease of use features:
2794 - Move to start of next line.
2795 - Appends the copy on sequential calls.
2796 - Use newline as last char even on the last line of the buffer.
2797 - If region is active, copy its lines."
2798 (interactive "p")
2799 (let ((beg (line-beginning-position))
2800 (end (line-end-position (or arg 1))))
2801 (when mark-active
2802 (if (> (point) (mark))
2803 (setq beg (save-excursion (goto-char (mark)) (line-beginning-position)))
2804 (setq end (save-excursion (goto-char (mark)) (line-end-position)))))
2805 (if (eq last-command 'copy-line)
2806 (kill-append (buffer-substring beg end) (< end beg))
2807 (kill-ring-save beg end)))
2808 (kill-append "\n" nil)
2809 ;; dun need cuz I have yank-better
2810 ;;(beginning-of-line (or (and arg (1+ arg)) 2))
2811 (if (and arg (not (= 1 arg))) (message "%d lines copied" arg)))
2812
2813 (global-set-key (kbd "C-e") 'copy-line)
2814
2815 ;;;;; M-e org-clock-in-last
2816
2817 (global-set-key (kbd "M-e") 'org-clock-in-last)
2818
2819 ;;;;; C-r isearch-backward
2820
2821 (global-set-key (kbd "C-r") 'isearch-backward)
2822 (add-hook 'comint-mode-hook
2823 (lambda ()
2824 (define-key comint-mode-map (kbd "C-r") 'comint-history-isearch-backward-regexp)))
2825
2826 ;;;;; M-r org-clock-out
2827
2828 (global-set-key (kbd "M-r") 'org-clock-out)
2829
2830 ;;;;; C-a copy buffer
2831
2832 (defun copy-all ()
2833 "Copy entire buffer to clipboard"
2834 (interactive)
2835 (clipboard-kill-ring-save (point-min) (point-max)))
2836 (global-set-key (kbd "C-a") 'copy-all)
2837
2838 ;;;;; C-s - c-x prefix
2839 ; prefix key binds.
2840 ; good info http://www.masteringemacs.org/articles/2011/02/08/mastering-key-bindings-emacs/
2841 ; rebinding the prefix keys are tricky. apparently, some modes ignore any redefinition of a prefix key and use it explicitly,
2842 ; so you have to dig into their key maps and redo things.
2843 ; There are 2 simpler alternatives which have their own downsides.
2844 ; One is cua mode, which I do not like because it smashes 2 keybinds onto 1 and limits what you can do.
2845 ; The other is keyboard-translate, which translates the key presses before anything else.
2846 ; The downside is that it translates them when you aren't using them as a prefix.
2847 ; Since the swaps I'm using are all very accessible, the only downside is some mental jugling when reading docs etc about these keybinds.
2848
2849 ; I've seen this as an another suggestion, it was a total fail. The prefix command took over both keys.
2850 ; (define-key key-translation-map [f12] "\C-c")
2851 ; (define-key key-translation-map "\C-c" [left])
2852
2853
2854 ;idea to remove the hook later since it is only needed at startup.
2855 ; did not work however, and there is not a real need to fix it, so I did not investigate
2856 ;(defun removeSwapHook ()
2857 ; (remove-hook 'buffer-list-update-hook 'myKeySwap)
2858 ; (remove-hook 'change-major-mode-hook 'removeSwapHook))
2859 ;(add-hook 'change-major-mode-hook 'removeSwapHook)
2860
2861
2862 ; went through almost all the relevant standard hooks,
2863 ; this overcomes a known bug that (keyboard-translate) does not get applied when running emacs daemon
2864 (add-hook 'buffer-list-update-hook (lambda () (interactive)
2865 (keyboard-translate ?\C-x ?\C-s)
2866 (keyboard-translate ?\C-s ?\C-x)
2867 (keyboard-translate ?\C-c ?\C-d)
2868 (keyboard-translate ?\C-d ?\C-c)))
2869
2870
2871
2872 ; these all don't work
2873 ; don't know why this doesn't error but reversing the keys does
2874 ;(keyboard-translate ?\t ?\M-\t)
2875 ;(keyboard-translate [M-tab] [tab])
2876 ; from what i can tell, it wants to use a keyboard-translate-table,
2877 ; which is a char table, which is a vector indexed by chars,
2878 ; and mod+tab is not a char (it has too many bits), it is an integer
2879 ; it actually says it can hold vectors or strings, but that it is obsolete to do so
2880 ;(characterp ?\M-a)
2881 ;(characterp ?\C-a)
2882
2883 ;;;;; C-M-s - split-window-vertically
2884
2885 (global-set-key (kbd "C-M-s") 'split-window-vertically)
2886
2887 ;;;;; C-d - C-c prefix
2888
2889 ;;;;; M-d - run
2890
2891 (global-set-key (kbd "M-d") 'run)
2892
2893 ;;;;; C-M-d - swap buffer across windows
2894 ;; from http://www.emacswiki.org/emacs/TransposeWindows
2895
2896 (setq swapping-buffer nil)
2897 (setq swapping-window nil)
2898 (defun swap-buffers-in-windows ()
2899 "Swap buffers between two windows"
2900 (interactive)
2901 (if (and swapping-window
2902 swapping-buffer)
2903 (let ((this-buffer (current-buffer))
2904 (this-window (selected-window)))
2905 (if (and (window-live-p swapping-window)
2906 (buffer-live-p swapping-buffer))
2907 (progn (switch-to-buffer swapping-buffer)
2908 (select-window swapping-window)
2909 (switch-to-buffer this-buffer)
2910 (select-window this-window)
2911 (message "Swapped buffers."))
2912 (message "Old buffer/window killed. Aborting."))
2913 (setq swapping-buffer nil)
2914 (setq swapping-window nil))
2915 (progn
2916 (setq swapping-buffer (current-buffer))
2917 (setq swapping-window (selected-window))
2918 (message "Buffer and window marked for swapping."))))
2919
2920 (global-set-key (kbd "C-M-d") 'swap-buffers-in-windows)
2921
2922 ;;;;; C-f - kill-whole-line
2923
2924 (global-set-key (kbd "C-f") 'kill-whole-line-wrapper)
2925 (defun kill-whole-line-wrapper (&optional arg)
2926 "If we are at the end of the file, kill backwards instead of doing nothing."
2927 (interactive "P")
2928 (if (= (point) (point-max))
2929 (kill-whole-line -1)
2930 (kill-whole-line arg)))
2931
2932 ;;;;; M-f - print-var-at-point
2933
2934 (defun print-var-at-point ()
2935 (interactive)
2936 (let ((v (variable-at-point)))
2937 (if (symbolp v)
2938 (message "%s: %s" v (symbol-value v))
2939 (message "no symbol found at point"))))
2940 (global-set-key (kbd "M-f") 'print-var-at-point)
2941
2942
2943 ;;;;; C-M-f - kill rest of line
2944
2945
2946 (add-hook 'org-mode-hook
2947 (lambda ()
2948 (define-key org-mode-map (kbd "C-M-f") 'org-kill-line)))
2949
2950 (global-set-key (kbd "C-M-f") 'kill-line)
2951 ;;;;; C-g - keyboard-quit
2952 ;;;;; M-g - abort-recursive-edit
2953
2954 (global-set-key (kbd "M-g") 'abort-recursive-edit)
2955
2956 ;;;;; C-M-g - gnus
2957
2958 (global-set-key (kbd "C-M-g") 'mu4e)
2959
2960 ;;;;; C-z - undo-only
2961 (global-set-key (kbd "C-z") 'undo-tree-undo)
2962 ;;;;; C-M-z - suspend-frame
2963 (global-set-key (kbd "C-M-z") 'suspend-frame)
2964 ;; this is never good in a gui
2965 (when (window-system)
2966 (defun suspend-frame() (interactive)))
2967
2968 ;;;;; C-x - kill-region
2969
2970 (global-set-key (kbd "C-s") 'kill-region)
2971
2972 ;;;;; M-x - counsel-m-x
2973
2974
2975 ;; todo; check out smex-show-unbound-commands shows frequently used commands that have no key bindings.
2976 ;; this must be before smex-initialize
2977 (setq
2978 smex-save-file "~/.emacs.d/.smex-items")
2979
2980 ;; this uses smex
2981 (global-set-key (kbd "M-x") 'counsel-M-x)
2982
2983 ;;;;; C-M-x - cut-to-register
2984
2985 ;; same args as copy-to-register
2986 (defun cut-to-register (register start end &optional delete-flag region)
2987 (interactive (list (register-read-with-preview "Cut to register: ")
2988 (region-beginning)
2989 (region-end)
2990 current-prefix-arg
2991 t))
2992 (copy-to-register register start end t region))
2993
2994 (global-set-key (kbd "C-M-x") 'cut-to-register)
2995
2996 ;;;;; C-c - copy
2997
2998 (global-set-key (kbd "C-d") 'kill-ring-save)
2999 (add-hook 'c-mode-hook
3000 (lambda () (define-key c-mode-map (kbd "C-d") nil)))
3001 (add-hook 'comint-mode-hook
3002 (lambda ()
3003 (define-key comint-mode-map (kbd "C-d") nil)))
3004 ;; the base map is shared by many c-modes, like java
3005 (add-hook 'c-mode-hook
3006 (lambda ()
3007 (define-key c-mode-base-map "\C-d" nil)
3008 (define-key c-mode-base-map (kbd "<deletechar>") 'c-electric-delete-forward)))
3009
3010
3011 ;;;;; M-c - delete-other-windows
3012
3013 ;; todo, consider binding/using org-capture
3014 (define-key global-map "\M-c" 'delete-other-windows)
3015
3016 ;;;;; C-M-c - copy-to-register
3017
3018 (global-set-key (kbd "C-M-c") 'copy-to-register)
3019
3020 ;;;;; C-v - yank
3021
3022 (global-set-key (kbd "C-v") 'yank-better)
3023
3024
3025
3026 (defun yank-better (arg)
3027 "Paste, linewise if our kill ends with a newline.
3028 I change the behavior of plain prefix. It makes it not do linewise paste,
3029 because sometimes you want to yank pop and a linewise paste screws that up.
3030 c-u with no number normally makes the point go before the yank.
3031 That is pointless for me, as it would be just as easier and less
3032 thought to pop the mark after yanking cuz it is set to before the mark."
3033 (interactive "*P")
3034 (if (and (not (equal arg '(4))) (string-suffix-p "\n" (current-kill 0 t)))
3035 (beginning-of-line))
3036 (if (and (stringp mode-name) (string= mode-name "Org"))
3037 (call-interactively 'org-yank)
3038 (setq this-command 'yank)
3039 (call-interactively 'yank (and (not (equal arg '(4)))))))
3040
3041 (put 'yank-better 'delete-selection 'yank)
3042
3043 ;;;;; M-v - insert-register
3044
3045 (global-set-key (kbd "M-v") 'insert-register)
3046
3047 ;;;;; C-M-v - yank-pop
3048
3049 (global-set-key (kbd "C-M-v") 'yank-pop)
3050
3051 ;;;;; C-b - other-window
3052
3053 (global-set-key (kbd "C-b") 'other-window)
3054
3055 ;;;;; M-b - isearch-backward-current-symbol
3056
3057 (global-set-key (kbd "M-b") 'isearch-backward-current-symbol)
3058
3059 ;;;;; C-M-b - isearch-current-symbol
3060
3061 (global-set-key (kbd "C-M-b") 'isearch-current-symbol)
3062
3063 ;;;;; C-tab - ---
3064 ;; in terminal, it's just TAB, duplicate keybind.
3065 ;;;;; M-tab - ---
3066 ;; in terminal it's duplicated of C-M-i
3067 ;;;;; C-delete - kill-symbol
3068
3069 (global-set-key (kbd "<C-delete>") 'kill-symbol)
3070 (defun kill-symbol (arg)
3071 (interactive "p")
3072 (kill-region (point) (save-excursion (forward-symbol arg) (point))))
3073
3074
3075 ;;;;; C-M-delete - kill-sexp
3076
3077 (global-set-key (kbd "<C-M-delete>") 'kill-sexp)
3078
3079 ;;;;; C-left-arrow - compile / comint search
3080
3081 (defun set-p (var)
3082 (and (bound-and-true-p var)
3083 (not (eq var 'unset))))
3084 (global-set-key (kbd "C-(") 'run)
3085
3086 ;; make compile work from the gtags root dir
3087 (defadvice compile (before pre-compile-advice activate)
3088 (basic-save-buffer)
3089 (when (set-p ggtags-project-root)
3090 (setq-local compile-saved-dir default-directory)
3091 (setq default-directory ggtags-project-root)))
3092 (defadvice compile (after post-compile-advice activate)
3093 (when (bound-and-true-p compile-saved-dir)
3094 (setq default-directory compile-saved-dir)))
3095
3096
3097 (add-hook 'c-mode-hook (lambda () (define-key c-mode-map (kbd "C-(") 'compile)))
3098 (add-hook 'comint-mode-hook
3099 (lambda ()
3100 (define-key isearch-mode-map (kbd "C-(") 'isearch-repeat-backward)
3101 (define-key comint-mode-map (kbd "C-(") 'isearch-backward)))
3102
3103
3104 ;;;;; C-M-left-arrow - org-shiftup
3105
3106 (add-hook 'org-mode-hook
3107 (lambda () (define-key org-mode-map (kbd "C-M-(") 'org-shiftup)))
3108
3109 ;;;;; C-right-arrow - forward-symbol
3110 ;;;;; C-M-right-arrow - org-shiftdown
3111 (add-hook 'org-mode-hook
3112 (lambda () (define-key org-mode-map (kbd "C-M-)") 'org-shiftdown)))
3113
3114 ;;;;; C-backspace - backward-kill-symbol
3115
3116 (define-key terminal-key-map (kbd "4b") 'backward-kill-symbol) ;c-backspace in my konsole
3117
3118 ;; c-w is duplicate in terminal
3119 (global-set-key (kbd "<C-backspace>") 'backward-kill-symbol)
3120 (add-hook 'comint-mode-hook
3121 (lambda ()
3122 (define-key comint-mode-map (kbd "<C-backspace>") 'backward-kill-word)))
3123 (defun backward-kill-symbol (arg)
3124 (interactive "p")
3125 (kill-region (point) (save-excursion (backward-symbol arg) (point))))
3126
3127 ;;;;; C-M-backspace - backward-kill-sexp
3128
3129 (global-set-key (kbd "<C-M-backspace>") 'backward-kill-sexp)
3130
3131 ;;;; right primary
3132 ;;;;; M-8 - delete-window-or-exit
3133
3134 (global-set-key (kbd "M-8") 'delete-window-or-exit)
3135
3136 (defun delete-window-or-exit ()
3137 "Delete window or exit emacs."
3138 (interactive)
3139 (if (condition-case nil (delete-window) (error t))
3140 (if (or (boundp 'server-process) (> (length (frame-list)) 1))
3141 (progn (basic-save-buffer) (delete-frame))
3142 (save-buffers-kill-terminal t))))
3143
3144 ;;;;; C-* - split-window-horizontally
3145 (global-set-key (kbd "C-*") 'split-window-horizontally)
3146 ;;;;; C-M-* - calc-dispatch
3147
3148 (global-set-key (kbd "C-M-*") 'calc-dispatch)
3149
3150 ;;;;; M-9 - kill-buffer
3151
3152 (defun kill-buffer-no-ido ()
3153 "kill-buffer, avoid the ido remapping"
3154 (interactive)
3155 (kill-buffer))
3156 (global-set-key (kbd "M-9") 'kill-buffer-no-ido)
3157
3158 ;; strangely, in simple mode, this is overridden.
3159 ;; I found this map to override, but it didn't work, so it seems its being bound some other way.
3160 ;; I did a grep of the emacs sources, but couldn't find anything.
3161 ;; (define-key universal-argument-map [?9 nil)
3162
3163 ;;;;; C-M-9 - end server edit
3164 ;; save & kill buffer if it was opened externally via emacsclient
3165
3166
3167 (defun server-edit-save ()
3168 (interactive)
3169 (save-buffer)
3170 (server-edit))
3171 (global-set-key (kbd "C-M-9") 'server-edit-save)
3172
3173 ;;;;; C-u - universal-argument
3174 ;;;;; C-M-u - search-keybind
3175
3176 (global-set-key (kbd "C-M-u") 'search-keybind)
3177
3178 (defun search-keybind (regexp &optional nlines)
3179 (interactive (occur-read-primary-args))
3180 (save-excursion
3181 (describe-bindings)
3182 (set-buffer "*Help*")
3183 (occur regexp)
3184 (delete-windows-on "*Help*")
3185 ))
3186
3187 ;;;;; C-i -
3188 ;; todo: try making use
3189 ;; this is the key in terminal
3190 ;;M-[ 4 d is undefined
3191
3192 ;; previously had this for enhancing graphical keybinds,
3193 ;; but afaik its no help since i want terminal to work
3194 ;; the same.
3195 ;; (define-key input-decode-map [?\C-i] [C-i])
3196
3197 ;;;;; C-M-i - query-replace-regexp
3198
3199 (global-set-key (kbd "C-M-i") 'query-replace-regexp)
3200 (add-hook 'flyspell-mode-hook
3201 (lambda () (define-key flyspell-mode-map (kbd "C-M-i") nil)))
3202 (add-hook 'text-mode-hook
3203 (lambda () (define-key text-mode-map (kbd "C-M-i") nil)))
3204
3205
3206 ;;;;; C-o - occur
3207
3208 (global-set-key (kbd "C-o") 'occur)
3209
3210 ;;;;; C-M-o - counsel-imenu
3211
3212 (global-set-key (kbd "C-M-o") 'counsel-imenu)
3213
3214 ;;;;; C-p - move-mouse-to-point
3215
3216 (global-set-key (kbd "C-p") 'move-mouse-to-point)
3217
3218 ;;;;; C-M-p - delete-horizontal-space
3219
3220 (global-set-key (kbd "C-M-p") 'delete-horizontal-space)
3221
3222 ;;;;; C-j - pop-to-mark
3223
3224 (defun my-pop-to-mark-command ()
3225 "Jump to mark, and pop a new position for mark off the ring.
3226 \(Does not affect global mark ring\)."
3227 (interactive)
3228 (pop-to-mark-command)
3229 (if (and (derived-mode-p 'org-mode) (outline-invisible-p))
3230 (org-show-context 'mark-goto)))
3231
3232 (global-set-key (kbd "C-j") 'my-pop-to-mark-command)
3233 (add-hook 'ido-setup-hook
3234 (lambda ()
3235 (define-key ido-common-completion-map (kbd "C-j") 'ido-select-text)
3236 ))
3237 (add-hook 'lisp-interaction-mode-hook
3238 (lambda ()
3239 (define-key lisp-interaction-mode-map (kbd "C-j") nil)))
3240
3241
3242 ;;;;; M-j - previous-error
3243
3244 (global-set-key (kbd "M-j") 'previous-error)
3245
3246 ;;;;; C-M-j - register prefix
3247
3248 (define-key global-map (kbd "C-M-j") ctl-x-r-map)
3249 (define-key ctl-x-r-map "m" 'kmacro-to-register)
3250
3251
3252 ;;;;; C-k - jump-to-register
3253
3254
3255 (global-set-key (kbd "C-k") 'jump-to-register)
3256
3257 ;;;;; M-k - next-error
3258
3259 (global-set-key (kbd "M-k") 'next-error)
3260
3261 ;;;;; C-M-k - man
3262
3263 (global-set-key (kbd "C-M-k") 'man)
3264
3265 ;;;;; C-l - ivy-switch-buffer
3266
3267 (global-set-key (kbd "C-l") 'ivy-switch-buffer)
3268
3269 ;;;;; C-M-l - move cursor top bottom mid, comint clear screen
3270
3271 (global-set-key (kbd "C-M-l") 'move-to-window-line-top-bottom)
3272
3273 ;;;;; C-; - used in flyspell, not sure what for, otherwise unbound
3274 ;;;;; M-; - comment-dwim
3275 ;;;;; C-M-; - comment-current-line-dwim
3276
3277 (defun comment-current-line-dwim ()
3278 "Comment or uncomment the current line."
3279 (interactive)
3280 (save-excursion
3281 (push-mark (beginning-of-line) t t)
3282 (end-of-line)
3283 (comment-dwim nil))
3284 (move-beginning-of-line 2))
3285 (global-set-key (kbd "C-M-;") 'comment-current-line-dwim)
3286
3287 ;;;;; C-m - ---
3288 ;; terminal/console needs this. otherwise, we could do this
3289 ;; to make C-m be a valid key in graphical mode.
3290 ;; (define-key input-decode-map [?\C-m] [C-m])
3291 ;;;;; C-M-m - recursive grep
3292
3293 (define-key global-map (kbd "C-M-m") 'rgrep)
3294
3295 ;;;;; C-, - ---
3296 ;; not recognized by terminal, can't get konsole keydef file to recognize comma,
3297 ;; todo: dig into konsole sources, or try newer version than t8
3298
3299 (add-hook 'flyspell-mode-hook
3300 (lambda () (define-key flyspell-mode-map (kbd "C-,") nil)))
3301
3302 ;;;;; C-M-, - ind-file-in-project
3303
3304 (global-set-key (kbd "C-M-,") 'find-file-in-project)
3305
3306 ;;;;; C-. - find recent file
3307
3308 (add-hook 'flyspell-mode-hook
3309 (lambda () (define-key flyspell-mode-map (kbd "C-.") nil)))
3310 (define-key dot-mode-map (kbd "C-.") nil)
3311 (define-key terminal-key-map (kbd "4c") 'counsel-recentf)
3312 (global-set-key (kbd "C-.") 'counsel-recentf)
3313 (add-hook 'php-mode-hook
3314 (lambda () (define-key php-mode-map (kbd "C-.") nil)))
3315
3316 ;;;;; C-M-. - -
3317
3318 (define-key dot-mode-map (kbd "C-M-.") nil)
3319 ;; (global-set-key (kbd "C-M-.") 'execute-extended-command)
3320
3321 ;;;;; C-/ - join lines
3322
3323 (defun vim-style-join-line ()
3324 (interactive)
3325 (join-line '(4)))
3326 (global-set-key (kbd "C-/") 'vim-style-join-line)
3327 (define-key undo-tree-map (kbd "C-/") nil)
3328
3329 ;;;;; C-M-/ - copy-buffer-file-name
3330
3331 ;; haven't bound this atm, todo, maybe someday?
3332 (defun copy-variable (variable)
3333 (interactive
3334 (let ((v (variable-at-point))
3335 (enable-recursive-minibuffers t)
3336 val)
3337 (setq val (completing-read (if (symbolp v)
3338 (format
3339 "Describe variable (default %s): " v)
3340 "Describe variable: ")
3341 obarray
3342 (lambda (vv)
3343 (or (get vv 'variable-documentation)
3344 (and (boundp vv) (not (keywordp vv)))))
3345 t nil nil
3346 (if (symbolp v) (symbol-name v))))
3347 (list (if (equal val "")
3348 v (intern val)))))
3349 (kill-new (symbol-value variable)))
3350
3351 (defun copy-buffer-file-name ()
3352 (interactive)
3353 (let ((name (cond
3354 ((derived-mode-p 'mu4e-view-mode) (mu4e-message-field-at-point :path))
3355 (t buffer-file-name))
3356 ))
3357 (kill-new name)
3358 (message name)))
3359
3360
3361 (global-set-key (kbd "C-M-/") 'copy-buffer-file-name)
3362
3363
3364
3365 ;;;;; C-up-arrow - org prev headline
3366
3367 ;; disabled just because i don't want to accidentally hit it
3368 (define-key global-map "\C-_" nil)
3369 (global-set-key (kbd "<C-_>") 'beginning-of-defun)
3370
3371 (add-hook 'org-mode-hook
3372 (lambda ()
3373 (define-key org-mode-map (kbd "\C-_") 'outline-previous-visible-heading)))
3374
3375
3376
3377
3378 ;;;;; C-S-up-arrow - winner undo
3379
3380 (global-set-key (kbd "<C-S-_>") 'winner-undo)
3381
3382 ;;;;; C-down-arrow - org next headline
3383
3384 (global-set-key (kbd "<C-kp-enter>") 'end-of-defun)
3385
3386 (add-hook 'org-mode-hook
3387 (lambda ()
3388 (define-key org-mode-map (kbd "<C-kp-enter>") 'outline-next-visible-heading)))
3389
3390
3391
3392
3393 ;;;;; C-M-down-arrow - toggle-mark-activation
3394
3395 (defun toggle-mark-activation ()
3396 (interactive)
3397 (if mark-active
3398 (deactivate-mark t)
3399 (activate-mark)))
3400
3401 (global-set-key (kbd "<C-M-kp-enter>") 'toggle-mark-activation)
3402
3403 ;;;;; C-S-down-arrow winner redo
3404
3405 (global-set-key (kbd "<C-S-kp-enter>") 'winner-redo)
3406
3407
3408 ;;;;; C-S-down-arrow - m-x for major mode
3409
3410 ;; todo, update this for ivy
3411 (global-set-key (kbd "<C-S-kp-enter>") 'smex-major-mode-commands)
3412
3413 ;;;;; C-lbracket - ----
3414 ;;;;; C-M-lbracket - scroll-right
3415
3416 (global-set-key (kbd "C-M-[") 'scroll-right)
3417
3418 ;;;;; C-rbracket - fill-paragraph
3419
3420 (global-set-key (kbd "C-]") 'fill-paragraph)
3421
3422 ;;;;; C-M-rbracket - scroll-left
3423
3424 (global-set-key (kbd "C-M-]") 'scroll-left)
3425
3426 ;;;;; C-return - newline-anywhere
3427
3428 (defun newline-anywhere ()
3429 "Add a newline from anywhere in the line."
3430 (interactive)
3431 (end-of-line)
3432 (newline-and-indent))
3433 ;; todo use alternate keybind make this work for terminal
3434 (global-set-key (kbd "<C-return>") 'newline-anywhere)
3435
3436
3437 ;;;;; M-return - plain newline
3438
3439 (defun plain-newline ()
3440 (interactive)
3441 (insert "\n"))
3442 (global-set-key (kbd "M-RET") 'plain-newline)
3443
3444
3445 ;;;;; C-space - org-edit-special
3446
3447 ;; commented due to new keyboard needing ctrl-space for mark
3448 ;; (kbd "<C-space>") does not work, (kbd "C-SPC") should work
3449 ;; (add-hook 'org-mode-hook
3450 ;; (lambda ()
3451 ;; (define-key org-mode-map (kbd "C-SPC") 'org-edit-special)
3452 ;; ;; org-src-mode-map is broken in git version of emacs.
3453 ;; ;; temporarily use this for exiting edit-special mode.
3454 ;; (global-set-key (kbd "C-M--") 'org-edit-src-exit)
3455 ;; (define-key org-src-mode-map (kbd "C-SPC") 'org-edit-src-exit)))
3456
3457 ;;;;; C-M-space - before or under cursor
3458
3459 (global-set-key (kbd "C-M-SPC") 'ispell-word)
3460 ;;;; left secondary
3461 ;;;;; C-M-4 - widen
3462
3463 (global-set-key (kbd "C-M-4") 'widen)
3464
3465 ;;;;; C-tab-key - query-replace
3466
3467
3468 (global-set-key (kbd "<C-kp-add>") 'query-replace)
3469
3470 ;;;;; C-t - org cycle todo / toggle comint motion
3471
3472 (add-hook 'org-mode-hook
3473 (lambda ()
3474 (define-key org-mode-map (kbd "C-t") 'org-todo)))
3475
3476 (defun my-comint-previous-input (arg)
3477 (interactive "*p")
3478 (if (comint-after-pmark-p)
3479 (comint-previous-input arg)
3480 (forward-line -1)))
3481
3482 (defun my-comint-next-input (arg)
3483 (interactive "*p")
3484 (if (comint-after-pmark-p)
3485 (comint-next-input arg)
3486 (forward-line)))
3487
3488 (add-hook 'comint-mode-hook
3489 (lambda ()
3490 (define-key comint-mode-map (kbd "C-t") 'comint-toggle-arrow-keys)
3491 (define-key comint-mode-map (kbd "<up>") 'my-comint-previous-input)
3492 (define-key comint-mode-map (kbd "<down>") 'my-comint-next-input)))
3493
3494
3495 (defun comint-toggle-arrow-keys ()
3496 (interactive)
3497 (toggle-arrow-keys comint-mode-map))
3498
3499 (setq-default comint-arrow-movement nil)
3500 (defun toggle-arrow-keys (map)
3501 (cond ((lookup-key map (kbd "<up>"))
3502 (setq-local comint-arrow-movement t)
3503 (define-key map (kbd "<up>") nil)
3504 (define-key map (kbd "<down>") nil))
3505 (t
3506 (setq-local comint-arrow-movement nil)
3507 (define-key map (kbd "<up>") 'my-comint-previous-input)
3508 (define-key map (kbd "<down>") 'my-comint-next-input)
3509 (goto-char (point-max)))))
3510
3511 (eval-after-load "message"
3512 '(define-key message-mode-map (kbd "C-t") 'mail-signature))
3513
3514
3515 ;;;;; C-M-t - org timestamp
3516
3517 (global-set-key (kbd "C-M-t") 'org-time-stamp-with-time)
3518
3519 ;;;;; C-home - start of buffer
3520 ;;;;; C-end - end of buffer
3521 ;;;; right secondary
3522 ;;;;; C-^ - save-buffers-kill-emacs
3523
3524 (global-set-key (kbd "C-^") 'save-buffers-kill-emacs)
3525
3526 ;;;;; C-M-6 - insert-small-copyright
3527
3528 (defun insert-small-copyright ()
3529 (interactive)
3530 (beginning-of-line)
3531 (let ((beg (point)))
3532 (insert "Copyright (C) 2019 Ian Kelling\nThis program is under GPL v. 3 or later, see <http://www.gnu.org/licenses/>")
3533 (comment-region beg (point))))
3534
3535 (global-set-key (kbd "C-M-6") 'insert-small-copyright)
3536
3537 ;;;;; M-7 - calc-embedded-word
3538
3539 (global-set-key (kbd "M-7") 'calc-embedded-word)
3540
3541 ;;;;; C-M-7 - insert-full-copyright
3542
3543 (defun insert-full-copyright ()
3544 (interactive)
3545 (beginning-of-line)
3546 (let ((beg (point)))
3547 (insert "Copyright (C) 2019 Ian Kelling\n")
3548 (insert "\n")
3549 (insert "This program is free software: you can redistribute it and/or modify\n")
3550 (insert "it under the terms of the GNU General Public License as published by\n")
3551 (insert "the Free Software Foundation, either version 3 of the License, or\n")
3552 (insert "(at your option) any later version.\n")
3553 (insert "\n")
3554 (insert "This program is distributed in the hope that it will be useful,\n")
3555 (insert "but WITHOUT ANY WARRANTY; without even the implied warranty of\n")
3556 (insert "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n")
3557 (insert "GNU General Public License for more details.\n")
3558 (insert "\n")
3559 (insert "You should have received a copy of the GNU General Public License\n")
3560 (insert "along with this program. If not, see <http://www.gnu.org/licenses/>.\n")
3561 (comment-region beg (point))))
3562
3563 (global-set-key (kbd "C-M-7") 'insert-full-copyright)
3564
3565
3566 ;;;;; C-0 - text-scale-reset
3567
3568 (defun text-scale-reset ()
3569 (interactive)
3570 (text-scale-set 0))
3571 (global-set-key (kbd "C-0") 'text-scale-reset)
3572
3573 ;;;;; C-M-0 - insert-apache
3574
3575 (defun insert-apache ()
3576 (interactive)
3577 (beginning-of-line)
3578 (let ((beg (point)))
3579 (insert "Copyright (C) 2017 Ian Kelling\n")
3580 (insert "\n")
3581 (insert "Licensed under the Apache License, Version 2.0 (the \"License\");\n")
3582 (insert "you may not use this file except in compliance with the License.\n")
3583 (insert "You may obtain a copy of the License at\n")
3584 (insert "\n")
3585 (insert " http://www.apache.org/licenses/LICENSE-2.0\n")
3586 (insert "\n")
3587 (insert "Unless required by applicable law or agreed to in writing, software\n")
3588 (insert "distributed under the License is distributed on an \"AS IS\" BASIS,\n")
3589 (insert "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n")
3590 (insert "See the License for the specific language governing permissions and\n")
3591 (insert "limitations under the License.\n")
3592 (comment-region beg (point))))
3593 (global-set-key (kbd "C-M-0") 'insert-apache)
3594
3595
3596 ;;;;; C-M-- - org-edit-src-exit
3597 ;;;;; C-y - undo
3598
3599 (global-set-key (kbd "C-y") 'undo-tree-redo)
3600 (add-hook 'org-mode-hook
3601 (lambda () (define-key org-mode-map (kbd "C-y") nil)))
3602
3603
3604 ;;;;; C-\ - sr-speedbar-toggle
3605 (global-set-key (kbd "C-\\") 'sr-speedbar-toggle)
3606
3607 ;;;;; C-M-\ - mark-defun
3608
3609 (global-set-key (kbd "C-M-\\") 'mark-defun)
3610
3611 ;;;;; C-h - help-prefix
3612
3613 ;;;;; C-' - val-expression
3614
3615 (global-set-key (kbd "C-'") 'eval-expression)
3616
3617 ;;;;; C-n - unpop to mark
3618
3619 (defun unpop-to-mark-command ()
3620 "Unpop off mark ring. Does nothing if mark ring is empty."
3621 (interactive)
3622 (when mark-ring
3623 (let ((pos (marker-position (car (last mark-ring)))))
3624 (if (not (= (point) pos))
3625 (goto-char pos)
3626 (setq mark-ring (cons (copy-marker (mark-marker)) mark-ring))
3627 (set-marker (mark-marker) pos)
3628 (setq mark-ring (nbutlast mark-ring))
3629 (goto-char (marker-position (car (last mark-ring))))))))
3630
3631 (global-set-key (kbd "C-n") 'unpop-to-mark-command)
3632
3633 ;;;;; C-M-n - narrow-to-region
3634
3635 (global-set-key (kbd "C-M-n") 'narrow-to-region)
3636
3637 ;;;;; C-escape - find-tag
3638
3639 (global-set-key (kbd "<C-escape>") 'find-tag)
3640
3641
3642 ;; Local Variables:
3643 ;; eval: (outline-minor-mode)
3644 ;; End: