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