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