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