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