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