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