1 ;; Copyright (C) 2019 Ian Kelling
3 ;; This program is free software: you can redistribute it and/or modify
4 ;; it under the terms of the GNU General Public License as published by
5 ;; the Free Software Foundation, either version 3 of the License, or
6 ;; (at your option) any later version.
8 ;; This program is distributed in the hope that it will be useful,
9 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
10 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 ;; GNU General Public License for more details.
13 ;; You should have received a copy of the GNU General Public License
14 ;; along with this program. If not, see <http://www.gnu.org/licenses/>.
16 ;; do m-x benchmark-init to see some benchmark stats
17 ;;(add-to-list 'load-path "~/.emacs.d/src/benchmark-init-el/")
18 ;;(require 'benchmark-init-loaddefs)
19 ;;(benchmark-init/activate)
21 ;;; init.el --- the start of customization
23 ;; (toggle-debug-on-error) ;uncomment to help debug
26 ;; stop from minimizing & freezing the gui
27 ;; used to freeze emacs and was really annoying,
28 ;; seems its changed now. no harm in keeping this though.
29 (global-unset-key (kbd "C-z"))
31 ;; speed up init https://www.reddit.com/r/emacs/comments/3kqt6e/2_easy_little_known_steps_to_speed_up_emacs_start/
32 ;; comment out this let for more accurate stack trace for init errors
33 (let ((file-name-handler-alist nil))
34 (setq gc-cons-threshold 100000000)
38 ;; emacs -f benchmark-init/show-durations-tabulated
39 ;; emacs -f benchmark-init/show-durations-tree
40 ;; to catch things post-init
41 ;; emacs -f benchmark-init/deactivate
42 (require 'benchmark-init)
43 (add-hook 'after-init-hook 'benchmark-init/deactivate)
46 ;; these need to be done before the hook in order to satisfy the byte compiler or batch mode
48 ;; this is the builtin org mode
49 ;;(add-to-list 'load-path "~/.emacs.d/emacs/site-lisp/org")
51 (add-to-list 'load-path "~/.emacs.d/src/readline-complete")
53 ;; disabled since not used.
54 ;;(add-to-list 'load-path "~/.emacs.d/src/bbdb-csv-import")
55 ;;(add-to-list 'load-path "~/.emacs.d/src/ghci-completion")
56 ;;(add-to-list 'load-path "~/.emacs.d/src/mediawiki-el")
57 ;;(add-to-list 'load-path "~/.emacs.d/src/spray")
59 (add-to-list 'load-path "~/.emacs.d/src/visible-mark")
62 ;; git version of gnus
63 ;; (add-to-list 'load-path "~/.emacs.d/src/gnus/lisp")
64 ;; (eval-after-load "info"
65 ;; (quote (add-to-list 'Info-default-directory-list "~/.emacs.d/src/gnus/texi")))
68 ;; needed for git version
69 ;;(add-to-list 'load-path "~/.emacs.d/src/haskell-mode")
70 ;;(require 'haskell-mode-autoloads)
71 ;;(add-to-list 'Info-default-directory-list "~/.emacs.d/src/haskell-mode")
73 ;; for using custom/upstream bbdb
74 ;;(require 'bbdb-loaddefs "~/.emacs.d/src/bbdb/lisp/bbdb-loaddefs.el")
75 ;;(setq bbdb-print-tex-path "~/.emacs.d/src/bbdb/tex")
78 ;; iank: dunno what this was about
79 ;;(add-hook 'server-visit-hook 'raise-frame)
81 (setq init-dir (file-name-directory load-file-name))
82 ;; previously, i was doing byte-recompile-directory, but
83 ;; now i just have one init file
84 (unless (equal (user-uid) 0) ; don't make root owned files
85 (byte-recompile-file (expand-file-name "init.el" init-dir) nil 0)
86 (byte-recompile-file "/p/c/mymu4e.el" nil 0)
89 ;; load init in `after-init-hook' so all packages are loaded. However, disabled because
90 ;; there seems to be no need.
91 ;; todo, learn about the weird evaluation order of this hook that requires the quoting.
92 ;; adapted from starter-kit
93 ;; (add-hook 'after-init-hook
95 ;; (load-file (expand-file-name "myinit.el" init-dir))
99 ;;; Weird package bug workaround
102 ;; without this, when installing a package, this message happens
104 ;; custom-handle-keyword: Unknown keyword :group
106 ;; but when i lookup the function, i get the following, and if
107 ;; I evaluate it, the error goes away. so I think the real
108 ;; definition is happening somewhere else
110 (defun custom-handle-keyword (symbol keyword value type)
111 "For customization option SYMBOL, handle KEYWORD with VALUE.
112 Fourth argument TYPE is the custom option type."
114 (setq value (purecopy value)))
115 (cond ((eq keyword :group)
116 (custom-add-to-group value symbol type))
117 ((eq keyword :version)
118 (custom-add-version symbol value))
119 ((eq keyword :package-version)
120 (custom-add-package-version symbol value))
122 (custom-add-link symbol value))
124 (custom-add-load symbol value))
126 (put symbol 'custom-tag value))
127 ((eq keyword :set-after)
128 (custom-add-dependencies symbol value))
130 (error "Unknown keyword %s" keyword))))
133 ;;; misc emacs documentation
135 ;;;; how to find auto-saved files that need recovering
136 ;; find a recently dated file in ~/.emacs.d/auto-save-list/, and see the files listed in it.
137 ;; #file# is an auto-save file. It may or may not be different than the file is corresponds to.
138 ;; If it is different, emacs will give a message about recovering it when you open it.
140 ;;;; misc org functions
142 ;; ;; these are usefull with (goto-char)
143 ;; ;; find named entity, other than headline
144 ;; (org-find-entry-with-id "string-number-or-symbol")
146 ;; (org-find-exact-headline-in-buffer "heading" nil t)
148 ;; ;; remove any indent level which is throughout the buffer
149 ;; (org-do-remove-indentation)
154 ;; good info http://www.emacswiki.org/emacs/GnusTutorial
155 ;; good info http://www.emacs.uniyar.ac.ru/doc/em24h/emacs183.htm
158 ;; After downloading mailing list archives, once you have an mbox file,
159 ;; there are rather straightforward ways to get it into any mail program,
160 ;; but I will cover gnus, which I use and is a bit tricky.
162 ;; gnus has a native search (limited, too slow for body text searches), and external search engine integration.
163 ;; gnus manual recommends converting to maildir for searching local mail, but importing lots of maildir messages to gnus
164 ;; takes 10+ minutes, so scratch that option. it suggests 2 alternate options
165 ;; mairix. for mbox, it doesn't integrate 100% with gnus, it copies the search results to a mbox
166 ;; and tells gnus to make a group of that mbox and display it. This means the read state won't be persistent, but otherwise
169 ;; local imap server which will use the mbox and provide search.
170 ;; dovecot is modular, theres a dovecot-common which uses recommends to install i guess it's most used modules. Its
171 ;; description is completely not useful. Anyways, I'm not sure if there is any benefit to installing this over just the
175 ;; dovecot by default also makes a an inbox folder based on the normal local mail location /var/mail/<username>
176 ;; those locations are adjustable and well documented via the var mail_location in
177 ;; /etc/dovecot/conf.d/10-mail.conf
178 ;; 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
179 ;; is. you could make the var be empty, which apparently has the same effect.
181 ;; Originally just linked the default location ~/.mail, but I changed to altering the config since ~/.mail since it seems
182 ;; other things like postfix use that location
184 ;; based on http://roland.entierement.nu/blog/2010/09/08/gnus-dovecot-offlineimap-search-a-howto.html
185 ;; other links that poped up contained outdated, innacurate information
186 ;; http://sachachua.com/blog/2008/05/geek-how-to-use-offlineimap-and-the-dovecot-mail-server-to-read-your-gmail-in-emacs-efficiently/
187 ;; http://www.emacswiki.org/emacs/JamesFerguson
188 ;; http://www.sanityinc.com/articles/read-mailing-lists-in-emacs-over-imap/
190 ;; Within emacs you can move messages between mbox and maildir etc, which is a nice flexibility.
194 ;; doc group for mbox:
195 ;; in gnus, do gnus-group-make-doc-group (G f in groups buffer) and point to the file
197 ;; info about groups created within gnus is stored in ~/.newsrc.eld
198 ;; also stored is a duplication of what email messages are read/unread,
199 ;; what newsgroups are subsribed to and read/unread,
200 ;; probably more stuff, everything that gnus saves.
203 ;; searching the body of the messages, i cut off after a few minutes.
204 ;; i can grep the file in just a couple seconds
208 ;; we can also get mbox from gmane
209 ;; http://notmuchmail.org/howto/#index7h2
212 ;; gnus can't search mboxes except with its builtin search which is extremely slow. mairix can do mbox files from the command
213 ;; line, but not from within gnus, but from mairix.el, which can then open the results in gnus
215 ;; mbox can be converted to maildir easily, but gnus loads lots of maildir messages extremely slow. it parses all the
216 ;; headers and generates a nov file for each.
218 ;; nnfolder-generate-active-file
220 ;; to reset things, when changing mail group. I duno all the proper way, but it works to delete
221 ;; ~/Mail ~/.newsrc.eld ~/.newsrc-dribble
224 ;;;;; mail sources vs select methods background
225 ;; I found this very confusing when first reading through the manual. "mail sources" is a term that does not simply mean
226 ;; sources of mail, it is much narrower for gnus. sources of mail can be either "mail sources" or select methods. Mail
227 ;; sources will move mail to ~/Mail (not sure what format), and split it into groups according to variables. You can use
228 ;; "mail sources" for maildir / imap, but those can also be read via select methods, which do not move the mail from their
229 ;; location, but use them in their native format. This is what I want to do, and I can simply ignore mail
230 ;; sources. Confusing terminology is that "fetching mail" "scanning mail", lots of things mail doesn't mean all mail, it
231 ;; means specifically from "mail sources". The words "articles" and "news" is used in connection with select methods, aka my actual mail.
235 ;;;;; caching background
238 ;; there is also ~/News/cache, filled with a bunch of articles, like 300 megs. can't figure out why.
239 ;; Grepped for caching in the manual, found 2 main things.
240 ;; cache is for 2 purposes. to cache locally, and to keep articles from expiring, called persistence
241 ;; gnus-use-cache, which puts things if they are
242 ;; gnus-cache-enter-articles
243 ;; things go in cache when they are marked certain ways by default, ticked and dormant
244 ;; and read articles are moved out of the cache
245 ;; still no idea why i have a bunch in the cache, but I set a var so that my mail won't get cached
246 ;; I'm gonna delete the cache, and check on it later see what exactly is going in there
247 ;; And of course, I moved ~/News to my encrypted drive and symlinked it
251 ;;; things that should be at the beginning
253 ;; packages installed from package manager: i pretty much prioritize repos this way: gnu, then melpa, then marmalade.
255 ;; package-activated-list:
256 ;; 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
258 ;;;; alternate keyboards
259 ;; todo, figure out an easy way to disable this when using external keyboard
260 (if (display-graphic-p)
262 enter-key (kbd "<return>")
263 s-enter-key (kbd "<S-return>")
264 c-m-enter-key (kbd "<C-M-return>")
265 m-enter (kbd "<M-return>")
266 c-enter (kbd "<C-return>"))
268 enter-key (kbd "C-m")
269 s-enter-key (kbd "C-8")
270 c-m-enter-key (kbd "C-M-8")
272 c-enter (kbd "C-8")))
274 (setq tp (string= (system-name) "tp"))
275 (setq x200 (string= (system-name) "x2"))
276 (setq laptop-keyboard (or tp x200))
278 ;; Ubiquitous Packages which should be loaded on startup rather than
279 ;; autoloaded on demand since they are likely to be used in every
284 ;; iank: dunno why this was here
285 ;;(require 'ansi-color)
288 ;; Better to have a list of packages in here vs installed manually.
289 ;; However, I install manually because sometimes there are two
290 ;; versions and it is not necessarily easy to reconcile that.
291 ;; based on marmalage website front page.
294 ;; little kit to help remove a down server
295 ;; (setq package-archives nil)
297 ;;(add-to-list 'package-archives
299 ;; "http://marmalade-repo.org/packages/"))
301 (add-to-list 'package-archives
302 '("melpa" . "http://melpa.milkbox.net/packages/") t)
303 (add-to-list 'package-archives '("org" . "http://orgmode.org/elpa/") t)
306 ;; keep our init.el clean, by moving customization elisp to it's own file
307 (setq custom-file "~/.emacs.d/custom.el")
308 (load custom-file 'noerror)
314 ;; turn on abbrev mode globally
315 (setq-default abbrev-mode t)
317 ;; default abbreviation mode file is .emacs.d/abbrev_defs.
318 ;; add-global-abbrev, add-mode-abbrev for expansion at point
319 ;; if all else fails, edit the abbrev file
326 ;; auto-completion in minibuffer
327 ;; disabled while I look for another alternative
330 (require 'auto-complete-config)
334 ;; complete after 1 char instead of default 2
335 (setq ac-auto-start 1)
336 (setq ac-delay 0.001)
338 (add-to-list 'ac-modes 'org-mode 'sql-mode)
340 (defun ac-common-setup ()
341 (add-to-list 'ac-sources 'ac-source-yasnippet))
343 ;; for org mode completion source taken from wiki.
344 ;; it did not work. no idea why. todo, investigate
345 ;; the ac-sources code is at http://www.emacswiki.org/emacs/AutoCompleteSources
346 ;; i've deleted it here so as to save space and not spam this file
347 ;;(defun my-ac-org-mode ()
348 ;; (setq ac-sources (append ac-sources '(ac-source-org))))
351 ;; this makes the org-self-insert command not do a flyspell spell check.
352 ;; low priority thing to look into sometime
353 (ac-flyspell-workaround)
356 (define-key ac-completing-map (kbd "<up>") nil)
357 (define-key ac-completing-map (kbd "<down>") nil)
358 (define-key ac-completing-map (kbd "<S-return>") 'ac-expand)
359 (define-key ac-completing-map "\t" 'ac-complete)
360 (define-key ac-completing-map (kbd "<tab>") 'ac-complete)
364 ;;; auto-complete readline-complete
366 (require 'readline-complete)
367 ;; not sure how I made these, but I deleted, and
368 ;; it would be nice to make them again sometime
369 ;;(require 'src-loaddefs)
371 ;; disabled cuz broken
372 ;; redefining function in readline-complete so ac-complete only uses readline as a source
373 (defun ac-rlc-setup-sources ()
374 "Add me to shell-mode-hook!"
375 (setq ac-sources '(ac-source-shell)))
376 (add-hook 'shell-mode-hook 'ac-rlc-setup-sources)
378 ;; generally unnecessary, but why not
379 (setq explicit-shell-file-name "bash")
381 ;; readline-complete says to add this line.
382 ;; however, it up my procfs directory tracking hook
383 ;; because get-process doesn't notice the child shell.
384 ;; instead, I've removed export EMACS=t from
385 ;; comint-exec-1 (the function which initially sets it)
386 ;; by finding it in emacs sources and redefinind it here
387 ;; and done stty echo in my bashrc
388 ;;(setq explicit-bash-args '("-c" "export EMACS=; stty echo; bash"))
391 (setq explicit-bash-args nil)
392 (setq comint-process-echoes t)
393 ;; default of 30 is way too slow. todo, consider pushing this upstream
394 (setq rlc-attempts 5)
396 (add-to-list 'ac-modes 'shell-mode)
398 ;; readline-complete recommends this (i assume this format),
399 ;; but greping finds no reference in emacs or my .emacs.d
400 ;; so I'm assuming it is for an older emacs
401 ;;(setq explicit-ssh-args '("-t"))
403 (add-hook 'shell-mode-hook
405 (define-key shell-mode-map (kbd "<tab>") 'auto-complete)))
408 ;;; readline complete fix
410 ;; I need this function here, where INSIDE_EMACS is replaced with LC_INSIDE_EMACS.
411 ;; ian: last update 2017-1-7. update this periodically from upstream
412 ;; like when we do a major emacs update
413 (defun comint-exec-1 (name buffer command switches)
414 (let ((process-environment
416 ;; If using termcap, we specify `emacs' as the terminal type
417 ;; because that lets us specify a width.
418 ;; If using terminfo, we specify `dumb' because that is
419 ;; a defined terminal type. `emacs' is not a defined terminal type
420 ;; and there is no way for us to define it here.
421 ;; Some programs that use terminfo get very confused
422 ;; if TERM is not a valid terminal type.
423 ;; ;; There is similar code in compile.el.
424 (if (and (boundp 'system-uses-terminfo) system-uses-terminfo)
425 (list "TERM=dumb" "TERMCAP="
426 (format "COLUMNS=%d" (window-width)))
428 (format "TERMCAP=emacs:co#%d:tc=unknown:" (window-width))))
429 (list (format "LC_INSIDE_EMACS=%s,comint" emacs-version))
430 process-environment))
432 (if (file-accessible-directory-p default-directory)
435 proc decoding encoding changed)
436 (let ((exec-path (if (and command (file-name-directory command))
437 ;; If the command has slashes, make sure we
438 ;; first look relative to the current directory.
439 (cons default-directory exec-path) exec-path)))
440 (setq proc (apply 'start-file-process name buffer command switches)))
441 ;; Some file name handler cannot start a process, fe ange-ftp.
442 (unless (processp proc) (error "No process started"))
443 (let ((coding-systems (process-coding-system proc)))
444 (setq decoding (car coding-systems)
445 encoding (cdr coding-systems)))
446 ;; Even if start-file-process left the coding system for encoding data
447 ;; sent from the process undecided, we had better use the same one
448 ;; as what we use for decoding. But, we should suppress EOL
450 (if (and decoding (not encoding))
451 (setq encoding (coding-system-change-eol-conversion decoding 'unix)
454 (set-process-coding-system proc decoding encoding))
457 ;;; auto save & backup
458 (setq auto-save-timeout 1) ; idle time before auto-save.
460 ;; main hook for my auto save
461 (add-hook 'auto-save-hook 'my-auto-save)
462 ;; additional hook to try to deal with emacs not auto-saving when a buffer isn't active
463 (add-hook 'window-configuration-change-hook 'my-auto-save-win)
465 ;; this function from mu4e really does not like buffer saving
466 (advice-add 'message-send-and-exit :before 'my-as-off)
467 (advice-add 'message-send-and-exit :after 'my-as-on)
469 ;; avoid window config hook saving too much, it can
470 ;; get into loops in some random situations
471 (setq my-auto-save-last nil)
472 (defun my-auto-save-win ()
473 (unless (eq (current-buffer) my-auto-save-last)
474 (my-auto-save (current-buffer))))
476 (defun my-auto-save (&optional last)
480 ;; mu4e has a bug right now, undo breaks when saving drafts
481 (not (string= (buffer-file-name) "*draft*"))
483 (not (and (boundp 'org-src-edit-buffer-p) (org-src-edit-buffer-p))))
484 ;; serial is incremented on each save, so let's do a bit less of them
485 (not (derived-mode-p 'dns-mode))
486 (setq my-auto-save-last last)
487 (let (message-log-max)
488 ;; a bit of a hack to partially suppress the constant saving in the echo area
489 (with-temp-message ""
490 (basic-save-buffer)))))
492 ;; in the message-send-and-exit advice, got an error because it passed an arg.
493 ;; didn't look into why, just add ignored args.
494 (defun my-as-off (&rest ignore)
498 (defun my-as-off-local (&rest ignore)
500 (setq-local my-as nil))
502 (defun my-as-on (&rest ignore)
506 (defun my-as-on-local (&rest ignore)
508 (setq-local my-as on))
510 ;; based on suggestion in the emacs docs, redefine these 2 functions
511 ;; to avoid prompt spamming the user when we do auto-save
512 (defun ask-user-about-supersession-threat (fn)
515 "File for %s has changed on disk outside of emacs. Auto-save is overwriting it, however
516 a backup is being created in case that is not what you intended." buffer-file-name)
517 (setq buffer-backed-up nil))
519 (defadvice ask-user-about-lock (before lock-deactivate-as activate)
520 (make-local-variable 'my-as)
522 (message "proper autosave has been turned off for this buffer because of lock file problem.
523 In this buffer, do M-x my-as-on to reenable"))
525 ;; todo, this doesn't work consistently to override the auto-save message
526 (defalias 'do-auto-save-original (symbol-function 'do-auto-save))
527 (defun do-auto-save (&optional no-message current-only)
528 "This function has been modified to wrap the original so that NO-MESSAGE
529 is always set to t, since we auto-save a lot, it spams otherwise.
530 The original doc string is as follows:
532 Auto-save all buffers that need it.
533 This is all buffers that have auto-saving enabled
534 and are changed since last auto-saved.
535 Auto-saving writes the buffer into a file
536 so that your editing is not lost if the system crashes.
537 This file is not the file you visited; that changes only when you save.
538 Normally we run the normal hook `auto-save-hook' before saving.
541 A non-nil NO-MESSAGE argument means do not print any message if successful.
542 A non-nil CURRENT-ONLY argument means save only current buffer."
544 (do-auto-save-original t current-only))
546 ;; enable MY auto-save
549 ;;; backups, separate from auto-save
552 ;; set backup file location
553 (setq backup-directory-alist '(("." . "~/.editor-backups")))
554 (setq auto-save-file-name-transforms
555 '((".*" "~/.editor-backups/" t)))
557 (setq version-control t ;; Use version numbers for backups
558 kept-new-versions 100
560 delete-old-versions t ;; delete old versions silently
561 ;; assume hard linked files are done on purpose, don't screw them up
562 backup-by-copying-when-linked t)
564 ;; todo, the time needs to be an integer, not a vector type thing
565 (defun constant-backup ()
566 "Backup conditioned on some time passing since last one.
567 Hooked into 'before-save-hook."
568 (cl-flet ((b-time (minutes)
570 (- (current-time) (* 60 minutes)))))
571 (when (or (not (boundp 'last-backup-time)) (and (< (buffer-size) 10000000) (b-time 5)) (b-time 30))
572 (setq buffer-backed-up nil)
573 (setq-local last-backup-time (current-time)))))
575 ;; make a backup on auto-save, because the backup feature is not
576 ;; utilized with my-auto-save, only normal interactive save.
577 ;; todo, enable when fixed
578 ;;(add-hook 'before-save-hook 'constant-backup)
580 (add-hook 'auto-save-hook 'auto-save-size-limit)
582 (defun auto-save-size-limit ()
583 (when (and (not backup-inhibited) (> (buffer-size) 2000000))
584 (message "Backups disabled for this buffer due to size > 2 megs")
585 (make-local-variable 'backup-inhibited)
586 (setq backup-inhibited t)))
590 ;; ;; the faq suggests to auto-save using
591 ;; (setq auto-save-visited-file-name t)
592 ;; and to toggle auto-saving in the current buffer, type `M-x auto-save-mode'
594 ;; however, this is buggy.
595 ;; it leaves around lock files, which can be disabled with
596 ;; (setq create-lockfiles nil)
597 ;; but it is also buggy on other things that appear to hook onto file saving
598 ;; so i created my own function, which originally had bugs,
599 ;; but new emacs version fixed all that, yay!.
602 ; not using, but here for documentation,
603 ; alternate way to enable and specify how long between autosaves.
604 ; number of input events between autosave.
605 ; lowest bound of functionality is actually about 15 input events
606 ;(setq auto-save-interval
609 ;; based on bbdb manual
610 ;; also has instructions to integrate with gnus,
612 (bbdb-initialize 'message)
614 ;; recommended by gnus,
615 ;; but seems like it could be good to have set for other stuff
616 (setq user-full-name "Ian Kelling")
617 ;; general email setting? recommended by mu4e
618 (setq message-kill-buffer-on-exit t)
623 (add-hook 'bbdb-mode-hook
624 (lambda () (define-key bbdb-mode-map (kbd "C-k") nil))
625 ;; based on emacs24-starter-kit
626 (setq bbdb-offer-save 'auto
627 bbdb-notice-auto-save-file t
628 bbdb-expand-mail-aliases t
629 bbdb-canonicalize-redundant-nets-p t
630 bbdb-complete-name-allow-cycling t)
633 ;;(require 'bbdb-csv-import)
635 ;;; bookmark settings
636 ; save bookmarks whenever they are changed instead of just when emacs quits
637 (setq bookmark-save-flag 1)
638 ; increase bookmark context size for better functionality
639 (setq bookmark-search-size 2000)
642 ;; change last thing from gnu.
643 ;; notably this avoids brace indent after if, and 4 space indent
644 (setq c-default-style '((java-mode . "java")
646 (other . "stroustrup")))
647 ;; for emacs itself, use
648 ;; (setq c-default-style '((java-mode . "java")
649 ;; (awk-mode . "awk")
651 ;; (setq-default c-basic-offset 2)
655 ;; A Theme builder is available at http://elpa.gnu.org/themes/ along with
656 ;; a list of pre-built themes at http://elpa.gnu.org/themes/view.html and
657 ;; themes are available through ELPA.
660 ;; interesting light themes
663 (defun override-theme (arg)
665 (while custom-enabled-themes
666 (disable-theme (car custom-enabled-themes)))
668 (setq color-theme-is-global t)
670 ;; temporary, make night be default
672 (defun toggle-night ()
674 (cond ((equal (car custom-enabled-themes) 'naquadah)
675 (override-theme 'leuven))
677 (override-theme 'naquadah))))
680 ;; in the leuven theme file, i made this change. will need to remake it
681 ;; on package updates. I could fork, but its a pretty simple change
682 ;; < `(default ((,class (:foreground "#333333" :background "#FFFFFF"))))
683 ;; > `(default ((,class (:foreground "#333333" :background "#F6F6F0"))))
684 (override-theme 'leuven)
687 ;; disable color thing with this:
688 ;;(disable-theme (car custom-enabled-themes))
690 ;; decent dark themes
692 ;;(override-theme 'tangotango)
693 ;;(override-theme 'deeper-blue)
694 ;;(override-theme 'tango-dark)
695 ;;(override-theme 'tsdh-dark)
697 ;;(override-theme 'heroku)
698 ;;(override-theme 'inkpot) ;; part of inkpot-theme package
699 ;;(override-theme 'naquadah) ; org mode features, part of naquadah-theme package
700 ;;(override-theme 'spolsky) ;; part of sublime-themes package
701 ;;(override-theme 'twilight-anti-bright) ;; from twilight-anti-bright-theme package
703 ;; interesting but not usable colors
704 ;;(override-theme 'cyberpunk) ; cool org mode features, from cyberpunk-theme package
705 ;;(override-theme 'wombat) ; cursor not visible enough. from a wombat package, not sure which
706 ;;(override-theme 'misterioso) ; cursor not visible enough
710 ;;decent light themes
711 ;;(override-theme 'alect-light) ; theres a -alt version, don't see a dif. could use this without dimming. from alect-something package
712 ;;(override-theme 'occidental) ; from occidental-theme package
715 ;;color-theme is deprecated in emacs 24.
717 ;; theme packages i tried then removed:
718 ;; ignored ones that didn't use the new theme engine
720 ;;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)
728 ;; git clone --recursive https://github.com/capitaomorte/yasnippet
729 ;; touch snippets/.yas-make-groups
731 ;; This all makes it so I can look through the default snippets
732 ;; in the menu bar, but they don't show up elsewhere, because they are
733 ;; mostly things I don't want.
737 ;; this needs to be before yas-global-mode
738 (setq yas-snippet-dirs (list "~/.emacs.d/snippets"))
742 yas-also-auto-indent-first-line t
743 yas-choose-tables-first t
744 yas-use-menu (quote full)
745 ;; this sets ido-prompt as first function
747 '(yas-ido-prompt yas-dropdown-prompt yas-x-prompt yas-completing-prompt yas-no-prompt))
749 ;; todo, explore this option for wrapping region
750 ;; '(yas/wrap-around-region t))
752 ;;; cross session settings
754 ;; Save a list of recent files visited.
756 (setq recentf-max-saved-items 400
757 recentf-max-menu-items 15)
761 save-place-version-control 'nospecial
762 save-place-limit 40000
763 save-place-file "~/.emacs.d/places")
767 ;; savehist keeps track of some history
769 (setq savehist-additional-variables '(kill-ring search-ring regexp-search-ring)
771 savehist-autosave-interval 60
772 ;; keep the home clean
773 savehist-file "~/.emacs.d/.savehist")
778 ;; ediff-buffers is the main command to use
780 ;; ediff - don't start another frame for the control panel
781 ;; unfortunately, this doesn't allow me to use 2 frames for the diff buffers
782 ;; so disable this temporarily with the next line if you want that
783 ;; sometime I should setup 2 functions to explicitly do each type
784 (setq ediff-window-setup-function 'ediff-setup-windows-plain)
785 ;;(setq ediff-window-setup-function 'ediff-setup-windows-default)
787 ;; do side by side diffs
788 (setq ediff-split-window-function 'split-window-horizontally)
792 ;; Things I tried which didn't work, which intuitively I think should
793 ;; work better: I can open the second diff buffer in a new frame, and
794 ;; close it's window in the first frame after starting ediff, but when I
795 ;; hit n to go to the next diff, it restores the window in the first
796 ;; frame. Another thing I tried is to open 2 new frames and set them up
797 ;; as I want. However, if I try to open the *Ediff Control Panel* buffer
798 ;; in a different window from its original one, my mouse jumps to one of
799 ;; the diff frames, or if that isn't visible, the buffer just hangs
800 ;; until I select the original ediff control panel window. This seems
801 ;; like a bug to me. I am using a very recent development version of
806 ;; dired - reuse current buffer by pressing 'a'
807 (put 'dired-find-alternate-file 'disabled nil)
811 ;; alsot tried notmuch, it had some glitches, and it's config has a list
812 ;; of folders which i'd rather not publish, so it's config is archived.
814 ;;(add-to-list 'load-path "/usr/local/share/emacs/site-lisp/mu4e")
815 ;;(add-to-list 'load-path "/usr/share/emacs/site-lisp/mu4e")
818 ;; (setq mu4e-headers-results-limit 2000)
821 (defun my-mu4e-init ()
822 (setq mu4e-headers-fields (delq (assoc :mailing-list mu4e-headers-fields) mu4e-headers-fields))
823 ;; it's implemented in mu4e, but not in the actions list for
825 (add-to-list 'mu4e-view-actions
826 '("browser view" . mu4e-action-view-in-browser) t)
828 (add-to-list 'mu4e-headers-actions
829 '("from this sender" . mu4e-action-msgs-by-this-sender) t)
830 (add-to-list 'mu4e-view-actions
831 '("from this sender" . mu4e-action-msgs-by-this-sender) t)
832 ;; normally, you would add to this, but we want to
833 ;; modify unread messages. the first 4 are defined by default.
835 `( ,(make-mu4e-bookmark
836 :name "Unread messages"
837 ;; old less restrictive unread, for adapting in the future:
838 ;; flag:unread AND NOT flag:trashed AND NOT maildir:/Junk AND NOT maildir:/fwfw AND NOT maildir:/log
839 :query "flag:unread maildir:/INBOX"
842 :name "Today's messages"
843 :query "date:today..now"
847 :query "date:7d..now"
850 :name "Messages with images"
851 :query "mime:image/*"
856 (eval-after-load "mu4e" '(my-mu4e-init))
859 ;; https://github.com/djcb/mu/issues/1025
860 mail-user-agent 'mu4e-user-agent
861 ;; common to gnus. default sendmail-query-once asks us, then sets this via customize.
862 send-mail-function (quote sendmail-send-it)
863 ;; use the standard imap folders
864 mu4e-sent-folder "/Sent"
865 mu4e-drafts-folder "/Drafts"
866 mu4e-trash-folder "/Trash"
867 ;; reindex new mail this often in seconds
868 ;; show addresses instead of just names
869 mu4e-view-show-addresses t
870 mu4e-use-fancy-chars t
871 mu4e-confirm-quit nil
872 mu4e-headers-leave-behavior 'apply ;; dont ask, do whatever was marked
874 mu4e-headers-results-limit 1000
875 ;; tell exim to use from: as envelope from.
876 ;; exim's default is use outgoing_msg_localpart@hostname.
877 mail-specify-envelope-from t
879 ;; looking up the list of maildirs when doing jo from summary
880 ;; can take a few seconds if we have a ton of messages.
881 ;; Only take that time for the first lookup.
882 ;; if we add a new maildir, just restart mu4e for it to be in that list.
883 mu4e-cache-maildir-list t
884 ;; default is 8, way too small for my big monitors
885 mu4e-headers-visible-lines 50
886 message-sendmail-envelope-from 'header
888 ;;mu4e-view-use-gnus t
889 ;; had problems where mu4e and gnus would hang verifying signatures, gnus man
890 ;; said this should help, but it didnt work. they still got verified.
891 ;; mm-verify-option 'never
894 ;; fucks up reading unread bookmark. when that is fixed, enable it
895 ;; (setq mu4e-update-interval 60)
898 ;; this file includes setting up my email addresses, which are not public,
900 ;; mu4e-user-mail-address-list
902 ;; inspired by mu4e info manual, search for mu4e-compose-pre-hook.
903 (load "/p/c/mymu4e.el")
906 ;; use for decrypting in mu4e
908 (beginning-of-buffer)
909 (when (search-forward "-----BEGIN PGP MESSAGE-----" nil t)
911 (let ((start (match-beginning 0))
912 (end (search-forward "-----END PGP MESSAGE-----" nil t)))
913 (shell-command-on-region start end "gpg2 -dq" nil t shell-command-default-error-buffer t)
915 (add-hook 'mu4e-view-mode-hook 'my-decrypt)
917 (defun iank-set-from-name (regexes)
918 "If we find an address matching regex, then set that address as the to,
919 and whatever was used"
920 (when mu4e-compose-parent-message
922 (while (and regexes (not found))
923 (setq re (car regexes)
924 regexes (cdr regexes)
925 found (mu4e-message-contact-field-matches
926 mu4e-compose-parent-message :to re)))
928 (setq user-full-name (car found))
929 ;; we get an error unless we do this. that is a bug. I could
930 ;; send a patch... also a bug: setting message-from-style nil
931 ;; doesnt work in mu4e unless user-full-name is also nil.
932 (unless user-full-name
933 (setq message-from-style nil))
934 (setq user-mail-address (cdr found)
937 (defun iank-set-from (regexes)
938 "If we find an address matching regex, then set that address as the to,
939 and Ian Kelling as the name"
940 (when mu4e-compose-parent-message
942 (while (and regexes (not found))
943 (setq re (car regexes)
945 regexes (cddr regexes)
946 found (cdr (mu4e-message-contact-field-matches
947 mu4e-compose-parent-message :to re))))
948 (when found (setq user-mail-address found
949 user-full-name "Ian Kelling"))
953 (defun mu-exit-wait ()
955 ;; taken from the mu source
956 (let* ((buf (get-buffer mu4e~proc-name))
957 (proc (and (buffer-live-p buf) (get-buffer-process buf))))
959 ;; without sleep, we get database locked by another process error when hitting u
960 ;; if another mu was running.
961 (if proc (sleep-for 0 1000))))
967 user-mail-address "iank@fsf.org"
968 iank-user-mail-address user-mail-address
969 ;; WARNING: be careful editing this, there needs to be a space after --, and my editor
970 ;; and git will automatically remove it unless i manually disable it.
971 mail-signature fsf-sig
973 (add-hook 'mu4e-compose-pre-hook 'my-mu4e-to)
979 (defun mu4e-action-msgs-by-this-sender (msg)
980 "In header view, view messages by the sender of the message under point."
981 (let ((from (mu4e-message-field msg :from)))
983 (mu4e-error "No from header for this message"))
984 ;; from is structured like: (("Anacron" . "root@x2.lan"))
985 (mu4e-headers-search (concat "f:" (cdar from)))))
990 ; when manually evaluating lisp, go into debugger on error
991 (setq eval-expression-debug-on-error t)
992 ;reminder of useful var: debug-on-error
997 ;; useful comint-shell mode commands. If not prefaced with *, it means it is not in the haskell custom repl
998 ;; *todo: setup haskell c-t toggle arrow keys
1000 ;; C-q insert prev arg
1001 ;; C-( history search
1002 ;; c-m-left/right move to next/prev prompts
1003 ;; *c-enter, multi-line input
1004 ;; *s-delete, send input across windows. (i can implement this)
1005 ;; *c-m-l clear screen
1006 ;; *haskell-process-interrupt, c-cc terminate job (i can implement this maybe)
1008 ;; nice bash/readline functions missing in comint:
1013 ;; usefull comint commands:
1014 ;; c-cl : list historic command in temp buffer
1015 ;; C-c C-o comint-delete-output
1016 ;; comint-restore-input, todo: put this on a randomish c-c key
1021 ;; checkout haskell repl functions:
1022 ;; c-cv haskell-check, hlint
1023 ;; C-M-q prog-indent-sexp
1024 ;; c-c. haskell-mode-format-imports
1025 ;; C-c M-/ haskell-doc-check-active
1026 ;; haskell-process-generate-tags
1027 ;; haskell-process-cabal-build
1028 ;; haskell-cabal-command.. or something
1029 ;; haskell-process-restart
1030 ;; C-h v haskell-process-log
1031 ;; C-h v haskell-process-show-debug-tips
1033 ;; various not immediately useful functions:
1034 ;; haskell-process-add-dependency
1035 ;; haskell-process-touch-buffer
1036 ;; haskell-process-cd
1037 ;; haskell-process-unignore
1038 ;; haskell-process-reload-devel-main
1042 ;; home: C-a haskell-interactive-mode-beginning
1043 ;; c-return: C-j haskell-interactive-mode-newline-indent
1044 ;; up/down: <C-down> haskell-interactive-mode-history-next
1046 ;; todo haskell mode better binds for:
1047 ;; 'haskell-process-load-file
1048 ;; 'haskell-process-do-type
1049 ;; 'haskell-process-do-info
1050 ;; 'inferior-haskell-send-decl
1053 ;; commands which don't work in haskell-interactive-mode(hi) vs inferior-haskell-mode(ih, default)
1054 ;; functions not in hi:
1055 ;; inferior-haskell-find-definition, use tags instead
1056 ;; inferior-haskell-find-haddock, todo, test if this works
1058 ;; redefined ih to hi
1059 ;; switch-to-haskell -> 'haskell-interactive-switch
1060 ;; haskell-process-load-file -> inferior-haskell-load-file
1061 ;; haskell-process-do-type -> inferior-haskell-type
1062 ;; switch-to-haskell -> haskell-interactive-switch
1063 ;; inferior-haskell-load-file -> 'haskell-process-load-file
1066 ;; haskell-mode installation from source, based on its readme
1067 ;; in the git directory,
1073 ;; remove default option to not link the file
1074 (setq haskell-compile-command "ghc -Wall -ferror-spans -fforce-recomp %s")
1075 (add-hook 'haskell-indentation-mode-hook
1077 (define-key haskell-indentation-mode-map [?\C-d] nil)
1078 (define-key haskell-indentation-mode-map
1079 (kbd "<deletechar>")
1080 'haskell-indentation-delete-char)))
1082 ;;copied from haskell-mode docs in order to use the new, better, nondefault
1084 (eval-after-load "haskell-mode"
1086 (define-key haskell-mode-map (kbd "C-x C-d") nil)
1087 (define-key haskell-mode-map (kbd "C-c C-z") 'haskell-interactive-switch)
1088 (define-key haskell-mode-map (kbd "C-c C-l") 'haskell-process-load-file)
1089 (define-key haskell-mode-map (kbd "C-c C-b") 'haskell-interactive-switch)
1090 (define-key haskell-mode-map (kbd "C-c C-t") 'haskell-process-do-type)
1091 (define-key haskell-mode-map (kbd "C-c C-i") 'haskell-process-do-info)
1092 (define-key haskell-mode-map (kbd "C-c M-.") nil)
1093 (define-key haskell-mode-map (kbd "C-c C-d") nil)))
1095 ;; ghc-mod install http://www.mew.org/~kazu/proj/ghc-mod/en/emacs.html
1096 ;; todo, try this out
1097 ;; (autoload 'ghc-init "ghc" nil t)
1098 ;;(add-hook 'haskell-mode-hook (lambda () (ghc-init) (flymake-mode)))
1102 ;; from the package readme for ghci-completion
1103 (add-hook 'inferior-haskell-mode-hook 'turn-on-ghci-completion)
1106 ;; disable some rebinds. they are set to appropriate keys in the keybinds section
1107 (eval-after-load "haskell-mode"
1109 (define-key haskell-mode-map (kbd "C-a") 'nil)
1110 (define-key haskell-mode-map (kbd "C-j") 'nil)))
1112 (eval-after-load "python-mode"
1114 (define-key python-mode-map (kbd "C-j") nil)))
1116 (defun pretty-lambdas-haskell ()
1117 (font-lock-add-keywords
1118 nil `((,(concat "(?\\(" (regexp-quote "\\") "\\)")
1119 (0 (progn (compose-region (match-beginning 1) (match-end 1)
1120 ,(make-char 'greek-iso8859-7 107))
1122 ;; from haskell-mode manual
1123 (add-hook 'haskell-mode-hook 'turn-on-haskell-decl-scan)
1124 (when (window-system)
1125 (add-hook 'haskell-mode-hook 'pretty-lambdas-haskell))
1127 ;; added from haskell-mode website install instructions
1128 ;(load "/usr/share/emacs/site-lisp/haskell-mode/haskell-site-file")
1129 (add-hook 'haskell-mode-hook 'turn-on-haskell-doc-mode)
1130 ;;the three indentation modules are mutually exclusive - add at most one. Trying out the "most advanced"
1131 (add-hook 'haskell-mode-hook 'turn-on-haskell-indentation)
1132 ;;(add-hook 'haskell-mode-hook 'turn-on-haskell-indent)
1133 ;;(add-hook 'haskell-mode-hook 'turn-on-haskell-simple-indent)
1136 ;; todo, set this to some other key
1137 ;; (local-set-key (kbd "C-e") 'my-haskell-load-and-run)
1139 (defun my-haskell-load-and-run ()
1140 "Loads and runs the current Haskell file."
1142 (let ((start-buffer (current-buffer)))
1143 (inferior-haskell-load-and-run inferior-haskell-run-command)
1146 (pop-to-buffer start-buffer)))
1148 ;; show haskell function in mode line
1149 ;; todo, this broke after updating emacs
1150 ;;(eval-after-load "which-func"
1151 ;; '(add-to-list 'which-func-modes 'haskell-mode))
1155 (add-hook 'interactive-haskell-mode-hook 'ac-haskell-process-setup)
1156 (add-hook 'haskell-interactive-mode-hook 'ac-haskell-process-setup)
1157 (eval-after-load "auto-complete"
1158 '(add-to-list 'ac-modes 'haskell-interactive-mode))
1160 (add-hook 'haskell-mode-hook
1161 (lambda () (define-key haskell-mode-map (kbd "C-(")
1162 (lambda () (interactive)
1165 (run-with-timer .3 nil 'repeat-shell)))))
1166 (add-hook 'haskell-cabal-mode-hook
1167 (lambda () (define-key haskell-cabal-mode-map (kbd "C-(") 'haskell-compile)))
1171 (add-hook 'haskell-interactive-mode-hook
1173 (define-key haskell-interactive-mode-map "\r" nil)
1174 (define-key haskell-interactive-mode-map (kbd "<return>") 'haskell-interactive-mode-return)))
1175 (add-hook 'haskell-indentation-mode-hook (lambda () (define-key haskell-indentation-mode-map "\r" nil)))
1179 (add-hook 'haskell-interactive-mode-hook
1181 (define-key haskell-interactive-mode-map (kbd "<C-M-return>") 'haskell-interactive-mode-newline-indent)))
1185 isearch-allow-scroll t
1186 search-ring-update t) ;; dont start an edit when going to previous search
1188 (defun isearch-yank-regexp (regexp)
1189 "Pull REGEXP into search regexp."
1190 (let ((isearch-regexp nil)) ;; Dynamic binding of global.
1191 (isearch-yank-string regexp))
1192 (isearch-search-and-update))
1194 (defun isearch-yank-symbol (&optional partialp backward)
1195 "Put symbol at current point into search string.
1197 If PARTIALP is non-nil, find all partial matches."
1200 (let (from to bound sym)
1202 ; this block taken directly from find-tag-default
1203 ; we couldn't use the function because we need the internal from and to values
1205 ;; Look at text around `point'.
1207 (skip-syntax-backward "w_") (setq from (point)))
1209 (skip-syntax-forward "w_") (setq to (point)))
1211 ;; Look between `line-beginning-position' and `point'.
1213 (and (setq bound (line-beginning-position))
1214 (skip-syntax-backward "^w_" bound)
1215 (> (setq to (point)) bound)
1216 (skip-syntax-backward "w_")
1217 (setq from (point))))
1218 ;; Look between `point' and `line-end-position'.
1220 (and (setq bound (line-end-position))
1221 (skip-syntax-forward "^w_" bound)
1222 (< (setq from (point)) bound)
1223 (skip-syntax-forward "w_")
1224 (setq to (point)))))
1225 (buffer-substring-no-properties from to)))
1227 (message "No symbol at point"))
1229 (goto-char (1+ from)))
1231 (goto-char (1- to))))
1234 (isearch-yank-string sym)
1235 (isearch-yank-regexp
1236 (concat "\\_<" (regexp-quote sym) "\\_>")))))
1238 (defun isearch-current-symbol (&optional partialp)
1239 "Incremental search forward with symbol under point.
1241 Prefixed with \\[universal-argument] will find all partial
1244 (let ((start (point)))
1245 (isearch-forward-regexp nil 1)
1246 (isearch-yank-symbol partialp)))
1249 (defun isearch-backward-current-symbol (&optional partialp)
1250 "Incremental search backward with symbol under point.
1252 Prefixed with \\[universal-argument] will find all partial
1255 (let ((start (point)))
1256 (isearch-backward-regexp nil 1)
1257 (isearch-yank-symbol partialp)))
1261 ; lets look through emacs starter kit before we throw this out.
1264 ; automatically wrap to the top of the buffer when isearch fails
1265 (defadvice isearch-search (after isearch-no-fail activate)
1266 (unless isearch-success
1267 (ad-disable-advice 'isearch-search 'after 'isearch-no-fail)
1268 (ad-activate 'isearch-search)
1269 (isearch-repeat (if isearch-forward 'forward))
1270 (ad-enable-advice 'isearch-search 'after 'isearch-no-fail)
1271 (ad-activate 'isearch-search)))
1273 ;; Activate occur easily inside isearch
1274 (define-key isearch-mode-map (kbd "C-o")
1275 (lambda () (interactive)
1276 (let ((case-fold-search isearch-case-fold-search))
1277 (occur (if isearch-regexp
1279 (regexp-quote isearch-string))))))
1280 ;;; lisp / elisp mode setings
1282 (add-hook 'emacs-lisp-mode-hook 'starter-kit-remove-elc-on-save)
1283 (defun starter-kit-remove-elc-on-save ()
1284 "If you're saving an elisp file, likely the .elc is no longer valid."
1285 (make-local-variable 'after-save-hook)
1286 (add-hook 'after-save-hook
1288 (if (file-exists-p (concat buffer-file-name "c"))
1289 (delete-file (concat buffer-file-name "c"))))))
1292 (defun emacs-lisp-mode-defaults ()
1293 ;; checkdoc has an annoying feature that wants a header and footer
1294 ;; in every elisp buffer as if they all were packages
1295 ;; todo, see if there is a way
1296 ;; to make checkdoc usable instead of just disabling it as I do here
1297 (if (boundp 'flycheck-checkers)
1298 (setq flycheck-checkers (remove 'emacs-lisp-checkdoc flycheck-checkers)))
1300 (add-hook 'emacs-lisp-mode-hook 'emacs-lisp-mode-defaults)
1302 (define-key lisp-mode-map (kbd "<M-up>") 'backward-up-list)
1303 (define-key lisp-mode-map (kbd "<M-down>") 'down-list)
1304 (define-key emacs-lisp-mode-map (kbd "<M-up>") 'backward-up-list)
1305 (define-key emacs-lisp-mode-map (kbd "<M-down>") 'down-list)
1306 (define-key emacs-lisp-mode-map (kbd "<M-escape>") 'find-function-at-point)
1308 ;; interactive modes don't need whitespace checks
1309 (defun interactive-lisp-coding-defaults ()
1310 (whitespace-mode -1))
1311 (setq prelude-interactive-lisp-coding-hook 'prelude-interactive-lisp-coding-defaults)
1314 ;; ielm is an interactive Emacs Lisp shell
1315 (defun ielm-mode-defaults ()
1316 (run-hooks 'prelude-interactive-lisp-coding-hook)
1317 (turn-on-eldoc-mode))
1318 (add-hook 'ielm-mode-hook 'ielm-mode-defaults)
1322 (eval-after-load "mediawiki"
1324 (remove-hook 'outline-minor-mode-hook 'mediawiki-outline-magic-keys)
1325 (add-hook 'mediawiki-mode-hook
1326 (lambda () (define-key mediawiki-mode-map (kbd "C-(") 'mediawiki-save-reload)))
1328 ;; mediawiki mode has a bug that it will claim an edit conflict unless you reload after saving.
1329 ;; I also like to save with no edit summary for previewing on my local mw instance
1330 (defun mediawiki-save-reload ()
1332 (and (mediawiki-save "") (mediawiki-reload)))))
1333 ;;; modes with little configuration needed
1335 ;;(require 'csv-mode)
1336 ;;(add-to-list 'auto-mode-alist '("\\.[Cc][Ss][Vv]\\'" . csv-mode))
1338 ;; disabled temporarily
1339 ;;(add-hook 'outline-minor-mode-hook 'outshine-mode)
1341 (setq org-caldav-url "https://cal.iankelling.org"
1342 org-caldav-calendar-id "ian"
1343 org-caldav-inbox "/p/cal.org")
1347 ;;(require 'dtrt-indent)
1348 ;;(setq dtrt-indent-mode t)
1350 (setq css-indent-offset 2)
1352 (load-file "/a/h/iank-mod.el")
1354 ;; from when i was running my own patches
1355 ;;(add-to-list 'load-path "/a/opt/ws-butler")
1357 (require 'ws-butler)
1358 ;; todo: I think this is broken, it keeps collapsing the last line
1359 ;; for empty messages.
1361 ;; the main problem is when it deletes the blank line at the end
1362 ;; of a message with an empty body. but I might also
1363 ;; be pasting whitespace significant things in here, so
1364 ;; just don't do anything.
1365 ;; todo: propose this upstream
1366 (add-to-list 'ws-butler-global-exempt-modes 'message-mode)
1368 (ws-butler-global-mode)
1372 (require 'nginx-mode)
1373 ;;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:
1374 ;;(add-to-list 'auto-mode-alist '("/etc/nginx/sites-available/.*" . nginx-mode))
1376 ;; todo, put this on a hook with prog mode
1377 ;;(highlight-indentation-mode 1)
1379 (add-hook 'auto-revert-tail-mode-hook
1383 "/var/log/cloudman/development/cm-service.log")
1384 (setq-local prev-auto-revert-max 0)
1385 ;; set buffer-local hook
1386 (add-hook 'after-revert-hook 'tail-colorize nil t))))
1387 (defun tail-colorize ()
1388 (ansi-color-apply-on-region prev-auto-revert-max (point-max))
1389 (setq-local prev-auto-revert-max (point-max)))
1393 (add-hook 'c-mode-common-hook
1394 (lambda () (ggtags-mode 1)
1395 (setq c-label-minimum-indentation 0)))
1397 (defun my-ggtags-init()
1398 ;; specific to my unusual keybind setup, you may want to
1399 ;; pick different keys
1400 (define-key ggtags-mode-map (kbd "C-M-o") 'ggtags-find-tag-dwim)
1401 (define-key ggtags-mode-map (kbd "C-M-m") 'ggtags-grep))
1402 (eval-after-load "ggtags" '(my-ggtags-init))
1405 (defun gtags-update-single(filename)
1406 "Update Gtags database for changes in a single file"
1408 (start-process "update-gtags" "update-gtags" "bash" "-c" (concat "cd " ggtags-project-root " ; gtags --single-update " filename )))
1410 (defun gtags-update-current-file()
1412 (let ((rel-filename (replace-regexp-in-string
1413 ggtags-project-root "."
1414 (buffer-file-name (current-buffer)))))
1415 (gtags-update-single rel-filename)))
1417 (defun gtags-update-hook()
1418 "Update GTAGS file incrementally upon saving a file"
1419 (when (and (boundp 'ggtags-mode) ggtags-mode ggtags-project-root)
1420 (gtags-update-current-file)))
1422 (add-hook 'after-save-hook 'gtags-update-hook)
1424 ;; i'd like to make some elisp which modifies a keymap to remove
1425 ;; all binds which don't match a predicate.
1426 ;; I tried setting a keymap to a new keymap,
1427 ;; but that didn't register as functional.
1428 ;; so I'd need to modify the list in place.
1430 ;; colorize hex colors: use rainbow mode
1433 ;; message mode prompted me on first message.
1434 ;; a function which describes options then sets this
1435 ;; the other options were to use smtp directly or pass to another mail client
1436 ;; here we use the standard sendmail interface, which I use postfix for
1437 (setq send-mail-function (quote sendmail-send-it))
1439 (global-set-key (kbd "C-M-w") 'spray-mode)
1440 ;; remember, h/l = move. f/s = faster/slower, space = pause, all others quit
1442 ;; delete active selection with self-insert commands
1443 (delete-selection-mode t)
1445 ;; Transparently open compressed files
1446 (auto-compression-mode t)
1448 ;; Highlight matching parenthesesq when the pointq is on them.
1449 ;; not needed since smart paren mode?
1450 ;; (show-paren-mode 1)
1453 ;; not documented, but looking at the source, I find this
1454 ;; stops me from being asked what command on every C-c-c
1455 ;; when doing a latex document.
1456 (setq TeX-command-force "LaTeX")
1458 ;; dot mode, repeats last action
1460 (add-hook 'find-file-hooks 'dot-mode-on)
1463 ;; clean up obsolete buffers automatically at midnight
1467 ;; disabled because it takes 400ms on startup
1468 ;; ;; emacs regexes are too limited.
1469 ;; (require 'foreign-regexp)
1470 ;; ;; perl is most powerful, but javascript is pretty close and
1471 ;; ;; I'd rather know javascript stuff than perl
1472 ;; (custom-set-variables
1473 ;; '(foreign-regexp/regexp-type 'javascript) ;; Choose by your preference.
1474 ;; '(reb-re-syntax 'foreign-regexp)) ;; Tell re-builder to use foreign regexp.
1475 ;; ;; it would be nice to add documentation to do this for more commands to that package
1476 ;; ;; disabled because it's too slow. but I'd still m-x it for advanced replacements
1477 ;; ;;(define-key global-map [remap isearch-forward-regexp] 'foreign-regexp/isearch-forward)
1480 ;; saner regex syntax
1481 (require 're-builder)
1482 (setq reb-re-syntax 'string)
1485 ;; use shift + arrow keys to switch between visible buffers
1486 ;; todo, set these keys to something else
1487 ;; (require 'windmove)
1488 ;; (windmove-default-keybindings)
1491 ;; show the name of the current function definition in the modeline
1492 ;;(require 'which-func)
1493 (setq which-func-modes t)
1494 (which-function-mode 1)
1497 ;; enable winner-mode to manage window configurations
1500 ;; meaningful names for buffers with the same name
1502 (setq uniquify-buffer-name-style 'forward
1503 uniquify-separator "/"
1504 ;; for sdx work. until I figure out a better way.
1505 ;; maybe something like projectile can do it,
1506 ;; or hacking around the status bar
1507 uniquify-min-dir-content 2
1508 uniquify-after-kill-buffer-p t ; rename after killing uniquified
1509 uniquify-ignore-buffers-re "^\\*") ; don't muck with special buffers
1512 ;; makefiles require tabs
1513 ;; todo: find a makefile indent function that works,
1514 ;; best I could find is this one which means don't indent at all
1516 (add-hook 'makefile-mode-hook
1518 (setq indent-tabs-mode t)
1519 (setq indent-line-function (lambda () 'no-indent))))
1522 ;; todo, turn on auto-fill just for txt files
1523 ;;(add-hook 'text-mode-hook 'turn-on-auto-fill)
1524 (add-hook 'text-mode-hook 'turn-on-flyspell)
1527 ;; auto indent shell script comments
1528 (setq sh-indent-comment t)
1530 ;; random extra highlights
1531 (require 'volatile-highlights)
1532 (volatile-highlights-mode t)
1535 ;; make help buffers smaller when it makes sense
1536 (temp-buffer-resize-mode 1)
1539 (defun my-info-init()
1541 ;; based on suggestions in info+.el, I also installed misc-fns, strings, and thingatpt+
1542 ;; remove some bad keybinds from info+
1543 (define-key Info-mode-map [mouse-4] nil)
1544 (define-key Info-mode-map [mouse-5] nil))
1546 (add-hook 'info-mode-hook 'my-info-init)
1549 (setq sh-here-document-word "'EOF'")
1551 (setq tramp-default-method "ssh")
1552 ;;; misc general settings
1554 ;; from tramp manual, use the same ssh controlmaster. I was having problems with
1555 ;; tramp prompting me for a username and pass.
1556 (customize-set-variable 'tramp-use-ssh-controlmaster-options nil)
1559 auto-revert-interval 2
1560 ;; fix eof end of file newline
1561 mode-require-final-newline t
1562 require-final-newline t
1563 auto-revert-verbose nil
1564 auto-revert-remote-files t)
1567 (add-hook 'text-mode-hook (lambda () (auto-fill-mode t)))
1568 (setq counsel-find-file-at-point t)
1570 (eval-after-load "ido"
1571 ;; easier to read with just spaces as separator
1572 (quote (setf (nth 2 ido-decorations) " ")))
1575 ;; https://www.emacswiki.org/emacs/FillParagraph
1576 ;; make list items start paragraphs.
1577 (setq paragraph-start "\f\\|[ \t]*$\\|[ \t]*[-+*] ")
1579 (setq sh-basic-offset 2)
1580 (setq vc-follow-symlinks t)
1582 ;; give us a shell to start instead of scratch
1583 ;;(setq initial-buffer-choice (lambda () (new-shell)))
1586 ;; Seed the random-number generator
1589 ;; easier to remember than keybinds
1590 (defalias 'scrypt 'mml-secure-message-encrypt-pgpmime)
1591 (defalias 'sign 'mml-secure-message-sign-pgpmime)
1592 ;; otherwise we get error on sending:
1593 ;; mml-secure-epg-sign: Couldn’t find any signer names; try setting `mml-secure-smime-sign-with-sender'.
1594 ;; i dunno why sign+encrypt doesnt cause this, seems kinda dumb,
1596 (setq mml-secure-openpgp-sign-with-sender t)
1597 ;; i dun use smime, the smime signing fails complaining it doesnt have
1598 ;; my key. todo: learn about smime
1599 (setq mml-secure-smime-sign-with-sender t)
1602 (mml-secure-message-encrypt-pgpmime 'dontsign))
1604 ;; don't highlight the region.
1605 (set-face-background 'region nil)
1607 ;; this fixes save error for python example code
1608 (define-coding-system-alias 'UTF-8 'utf-8)
1610 ;; i don't use frame titles, but if I ever do
1611 ;; this starter kit setting is probably good
1612 (if window-system (setq frame-title-format '(buffer-file-name "%f" ("%b"))))
1615 ;;(prefer-coding-system 'utf-8-unix)
1617 ;; remove ugly 3d box feature
1618 (set-face-attribute 'mode-line nil :box nil)
1620 (add-to-list 'default-frame-alist
1621 '(font . "DejaVu Sans Mono-11"))
1622 ; the default will jump 2 sizes.
1623 (setq text-scale-mode-step 1.1)
1624 (setq font-lock-maximum-decoration t
1625 inhibit-startup-message t
1626 transient-mark-mode t
1627 delete-by-moving-to-trash t
1628 shift-select-mode nil
1629 truncate-partial-width-windows nil
1630 uniquify-buffer-name-style 'forward
1631 oddmuse-directory "~/.emacs.d/oddmuse"
1634 sort-fold-case t ; case insensitive line sorting
1635 global-mark-ring-max 1000
1636 ;; the visible bell seems to lag the ui
1638 ;; turn off audible bell
1639 ;; https://www.emacswiki.org/emacs/AlarmBell
1640 ring-bell-function 'ignore
1642 revert-without-query '(".*")
1643 ;; don't pause display code on input.
1644 ;; smoother display performance at slight cost of input performance
1645 redisplay-dont-pause t
1646 font-lock-maximum-decoration t) ; probably default and not necesary
1649 (setq-default indent-tabs-mode nil ;; don't use tabs to indent
1653 ;; wrap at word boundaries instead of mid-word
1656 indicate-empty-lines t) ; mark end of buffer
1658 (require 'smooth-scroll)
1659 ;; long gnus summary buffers lags too much with this,
1660 ;; but I like it enough to leave it enabled by default
1661 ;; and crank up the step size to be faster
1662 ;; and it doesn't have a way to enable it only for certain modes etc.
1663 ;; todo sometime, make it work for certain modes only
1664 (smooth-scroll-mode t)
1665 ;; its too slow with the default of 2
1666 (setq smooth-scroll/vscroll-step-size 7)
1667 ;; sublimity doesn't work as good going fast by default
1668 ;; smooth-scrolling.el, does not do smooth scrolling. its about cursor location
1671 (blink-cursor-mode '(-4))
1676 ;; enable various commands
1677 (put 'narrow-to-region 'disabled nil)
1678 (put 'narrow-to-page 'disabled nil)
1679 (put 'narrow-to-defun 'disabled nil)
1680 (put 'upcase-region 'disabled nil)
1681 (put 'downcase-region 'disabled nil)
1682 (put 'scroll-left 'disabled nil)
1683 ;; these from graphene, haven't read about them yet
1684 (put 'ido-complete 'disabled nil)
1685 (put 'ido-exit-minibuffer 'disabled nil)
1686 (put 'dired-find-alternate-file 'disabled nil)
1687 (put 'autopair-newline 'disabled nil)
1691 ;;disable and minimize various prompts/messages
1692 (fset 'yes-or-no-p 'y-or-n-p)
1693 (setq confirm-nonexistent-file-or-buffer nil
1694 inhibit-startup-message t
1695 inhibit-startup-echo-area-message t
1696 inhibit-startup-screen t
1697 kill-buffer-query-functions (remq 'process-kill-buffer-query-function
1698 kill-buffer-query-functions))
1701 ;; exit without bothering me
1702 ;; http://stackoverflow.com/questions/2706527/make-emacs-stop-asking-active-processes-exist-kill-them-and-exit-anyway/2708042#2708042
1703 (add-hook 'comint-exec-hook
1704 (lambda () (set-process-query-on-exit-flag (get-buffer-process (current-buffer)) nil)))
1705 ;; based on save-buffers-kill-emacs help string, don't ask about clients when exiting
1706 ;; apparently this would need to be in some later hook. dunno where is best, but this works
1707 (defadvice save-buffers-kill-emacs (before no-client-prompt-advice activate)
1708 (setq kill-emacs-query-functions (delq 'server-kill-emacs-query-function kill-emacs-query-functions)))
1712 ;; (custom-set-faces
1713 ;; ;; setting header-line-format to " " as a hack for a top margin the oly thning I could find to do a top margin
1714 ;; '(header-line ((t (:background "default" :foreground "default" :overline nil :underline nil))))
1715 ;; ;; don't highlight the region
1716 ;; '(region ((t nil))))
1717 (setq-default header-line-format " ")
1720 (setq initial-scratch-message nil)
1723 ;; vertical margin background.
1724 ;; google turned up: http://lists.gnu.org/archive/html/help-gnu-emacs/2014-03/msg00544.html
1725 ;; the xresource doesn't work for me, probably an xmonad thing.
1727 ;; figured out I needed to customize the header line face. To find the face, M-x list-faces-display or just google / search
1729 ;; then M-x customize-face
1731 ;; unchecked some stuff so that it inherits from default.
1733 ;;; misc function definitions
1736 (defun fill-buffer ()
1738 (save-mark-and-excursion
1739 (beginning-of-buffer)
1740 (while (= (forward-line) 0)
1744 (defun next-backup-dir ()
1745 "In a directory listing from rsync -n,
1746 Go to the next directory based on where the cursor is."
1748 (let* ((start-col (current-column))
1749 (end-col (progn (skip-chars-forward "^/\n") (current-column)))
1751 (beginning-of-line 1)
1752 (buffer-substring-no-properties (point) (+ (point) end-col)))))
1755 (while (and (not (eobp))
1756 (string= dir (buffer-substring-no-properties (point) (+ (point) end-col))))
1758 (forward-char-same-line start-col)))
1759 ;; copy paste this for fast keybind
1760 ;;(local-set-key (kbd "<kp-enter>"))
1763 (defun goto-buffer-or-find-file (file-name)
1764 "If buffer is with FILE-NAME exists, go to it, else open the file using full path."
1766 (let ((b (get-buffer (file-name-nondirectory file-name))))
1768 (switch-to-buffer b)
1769 (find-file file-name))))
1774 ;; todo, i think this is broken. perhaps the last goto-char is not accounting for buffer or something
1775 (defun unpop-global-mark ()
1776 "Unpop off global mark ring. Does nothing if mark ring is empty."
1778 (when global-mark-ring
1779 (setq global-mark-ring (cons (copy-marker (mark-marker)) global-mark-ring))
1780 (let ((lm (car (last global-mark-ring))))
1781 (set-marker (mark-marker) (marker-position lm) (marker-buffer lm)))
1782 (when (null (mark t)) (ding))
1783 (setq global-mark-ring (nbutlast global-mark-ring))
1784 (goto-char (marker-position (mark-marker)))))
1786 (defun indent-buffer ()
1787 "Indents the entire buffer."
1789 (cond ((derived-mode-p 'org-mode)
1790 (org-indent-region (point-min) (point-max)))
1791 ((derived-mode-p 'python-mode)
1794 (indent-region (point-min) (point-max)))))
1797 ;; TODO doesn't work with uniquify
1798 (defun rename-file-and-buffer ()
1799 "Renames current buffer and file it is visiting."
1801 (let ((name (buffer-name))
1802 (filename (buffer-file-name)))
1803 (if (not (and filename (file-exists-p filename)))
1804 (message "Buffer '%s' is not visiting a file!" name)
1805 (let ((new-name (read-file-name "New name: " filename)))
1806 (cond ((get-buffer new-name)
1807 (message "A buffer named '%s' already exists!" new-name))
1809 (rename-file name new-name 1)
1810 (rename-buffer new-name)
1811 (set-visited-file-name new-name)
1812 (set-buffer-modified-p nil)))))))
1816 (defun sudo-edit (&optional arg)
1818 (if (or arg (not buffer-file-name))
1819 (find-file (concat "/sudo::" (ido-read-file-name "File: ")))
1820 (find-alternate-file (concat "/sudo::" buffer-file-name))))
1824 (defun backward-symbol (arg)
1826 (forward-symbol (- arg)))
1829 ;; make window title be the buffer name
1830 (setq frame-title-format "%b")
1832 ; -----------------------------
1833 ; fixing up the mode line
1834 ; modified from mastering emacs blog
1835 ; ----------------------------
1837 (defvar mode-line-cleaner-alist
1838 `((auto-complete-mode . "")
1839 (yas/minor-mode . "")
1841 (auto-fill-function . "")
1844 (flyspell-mode . "")
1847 (yas-global-mode . "")
1848 (yas-minor-mode . "")
1849 (undo-tree-mode . "")
1850 (volatile-highlights-mode . "")
1851 (highlight-symbol-mode . "")
1853 (lisp-interaction-mode . "λ")
1855 (python-mode . "Py")
1856 (emacs-lisp-mode . "EL")
1857 (nxhtml-mode . "nx"))
1858 "Alist for `clean-mode-line'.
1860 When you add a new element to the alist, keep in mind that you
1861 must pass the correct minor/major mode symbol and a string you
1862 want to use in the modeline *in lieu of* the original.")
1865 (defun clean-mode-line ()
1867 (loop for cleaner in mode-line-cleaner-alist
1868 do (let* ((mode (car cleaner))
1869 (mode-str (cdr cleaner))
1870 (old-mode-str (cdr (assq mode minor-mode-alist))))
1872 (setcar old-mode-str mode-str))
1874 (when (eq mode major-mode)
1875 (setq mode-name mode-str)))))
1878 ; (add-hook 'after-change-major-mode-hook 'clean-mode-line)
1881 ;;; alias the new `flymake-report-status-slim' to
1882 ;;; `flymake-report-status'
1883 (defalias 'flymake-report-status 'flymake-report-status-slim)
1884 (defun flymake-report-status-slim (e-w &optional status)
1885 "Show \"slim\" flymake status in mode line."
1887 (setq flymake-mode-line-e-w e-w))
1889 (setq flymake-mode-line-status status))
1890 (let* ((mode-line " Φ"))
1891 (when (> (length flymake-mode-line-e-w) 0)
1892 (setq mode-line (concat mode-line ":" flymake-mode-line-e-w)))
1893 (setq mode-line (concat mode-line flymake-mode-line-status))
1894 (setq flymake-mode-line mode-line)
1895 (force-mode-line-update)))
1898 (defun my-after-change-major-mode-hook ()
1899 (setq mode-line-mule-info nil
1900 minor-mode-alist nil
1901 mode-line-position nil)) ; todo, make only flymake status show up
1903 (add-hook 'after-change-major-mode-hook 'my-after-change-major-mode-hook)
1907 (setq focus-follows-mouse t
1908 mouse-autoselect-window t
1910 ;;;; move-mouse-to-point
1911 ;; todo, this is buggy with multiple windows open.
1912 (defun move-mouse-to-point ()
1914 (let* ((pos (posn-col-row (posn-at-point)))
1915 (x (+ (car pos) 2)) ; no idea why this is off by 1-2
1917 (set-mouse-position (selected-frame) x y)))
1919 ;;;; keybinds for wow mouse
1921 (global-set-key (kbd "<mouse-6>") 'move-mouse-to-point)
1922 (global-set-key (kbd "<kp-left>") 'indent-region)
1923 (global-set-key (kbd "<kp-begin>") 'mark-defun)
1924 (global-set-key (kbd "<kp-right>") 'ibuffer)
1925 (global-set-key (kbd "<kp-prior>") 'delete-horizontal-space)
1929 ;; todo work on org-cycle-emulate-tab
1931 ;; todo, this doesn't work for a non-standard keybind
1932 ;;(setq org-special-ctrl-k t)
1934 ;; todo, generally fix org mode keys
1935 ;; todo, org-mark-element, unbdind from M-h, bind to mark defun key
1937 ;(org-babel-do-load-languages
1938 ; 'org-babel-load-languages
1939 ; '((emacs-lisp . t)
1944 ;; make shell work like interactive bash shell
1945 (setq org-babel-default-header-args:sh
1946 '((:results . "output") (:shebang . "#!/bin/bash -l")))
1948 ;; my patch to output stderr
1949 (setq org-babel-use-error-buffer nil)
1952 ;; org-mode manual suggests these, but I haven't used them.
1953 ;;(global-set-key "\C-cl" 'org-store-link)
1954 ;;(global-set-key "\C-ca" 'org-agenda)
1955 ;; this got in the way of a haskell mode command
1956 ;;(global-set-key "\C-cb" 'org-iswitchb)
1960 ;; org-src-tab-acts-natively t ; broken option. using next instead, todo fix
1962 (setq org-src-fontify-natively t ; make babel blocks nice
1963 org-adapt-indentation nil
1964 org-src-preserve-indentation t
1965 ;; The most basic logging is to keep track of when a TODO item was finished.
1967 ;; use a drawer to keep the logs tidy
1968 org-log-into-drawer t
1969 org-extend-today-until 0
1970 org-startup-truncated nil
1972 org-use-sub-superscripts "{}"
1973 org-export-with-sub-superscripts nil
1974 org-clock-mode-line-total 'today
1975 ;; global STYLE property values for completion
1976 org-global-properties (quote (("STYLE_ALL" . "habit")))
1977 org-special-ctrl-a/e t ;; home and end work special in headlines
1978 org-completion-use-ido t
1979 org-catch-invisible-edits 'smart)
1981 ;; non universally recommended settings
1983 org-default-notes-file "/a/t.org"
1984 org-agenda-files (quote ("/a/t.org"))
1985 org-mobile-directory "/p/org-mobile"
1986 org-mobile-inbox-for-pull "/p/from-mobile.org"
1989 ;; modeilne populated from (org-clock-get-clocked-time)
1990 ;; which is populated from the var org-clock-total-time
1991 ;; which is populated by a function which starts from (org-clock-get-sum-start)
1994 (eval-after-load "org"
1995 '(org-clock-persistence-insinuate))
1998 (defun time-to-org-day (time)
1999 (round (time-to-number-of-days
2000 (time-subtract time (list 0 (* 3600 org-extend-today-until) 0)))))
2003 (defun my-org-confirm-babel-evaluate (lang body)
2004 (not (or (string= (buffer-file-name) "/a/t.org")
2005 (string= (buffer-file-name) "/home/iank/.emacs.d/my-init.org")
2007 (setq org-confirm-babel-evaluate 'my-org-confirm-babel-evaluate)
2010 (defun org-time-stamp-with-time (arg)
2012 ;; '(4) is the argument passed by universal prefix
2013 (org-time-stamp (if arg arg '(4)) t))
2015 (defun ian-org-work-time ()
2018 (set-buffer "t.org")
2019 (goto-char (org-find-entry-with-id "ian-identifier-1"))
2022 (defun ian-org-idle-time ()
2025 (goto-char (org-find-entry-with-id "ian-identifier-2"))
2026 (set-buffer "t.org")
2031 ;; based on http://stackoverflow.com/questions/3758139/variable-pitch-for-org-mode-fixed-pitch-for-tables
2032 ;; keywords: proportional font, monospace
2034 (defun variable-pitch-on ()
2035 (variable-pitch-mode 1))
2036 (add-hook 'fundamental-mode-hook 'variable-pitch-on)
2037 (add-hook 'org-mode-hook 'variable-pitch-on)
2038 (add-hook 'text-mode-hook 'variable-pitch-on)
2039 (defun variable-pitch-off ()
2040 (variable-pitch-mode 0))
2041 (add-hook 'yaml-mode-hook 'variable-pitch-off)
2043 (eval-after-load "org" '(my-org-face-init))
2045 (defun my-org-face-init()
2046 (set-face-attribute 'org-table nil :family (face-attribute 'fixed-pitch :family))
2047 (set-face-attribute 'org-code nil :family (face-attribute 'fixed-pitch :family))
2048 (set-face-attribute 'org-formula nil :family (face-attribute 'fixed-pitch :family))
2049 (set-face-attribute 'org-link nil :family (face-attribute 'fixed-pitch :family))
2050 (set-face-attribute 'org-block nil :family (face-attribute 'fixed-pitch :family))
2051 (set-face-attribute 'org-date nil :family (face-attribute 'fixed-pitch :family))
2054 (defun remove-org-binds ()
2055 (define-key org-mode-map (kbd "<M-return>") nil)
2056 (define-key org-mode-map (kbd "C-'") nil)
2057 (define-key org-mode-map (kbd "C-y") nil)
2058 (define-key org-mode-map (kbd "<C-return>") nil)
2059 (define-key org-mode-map (kbd "<C-M-kp-enter>") nil)
2060 (define-key org-mode-map (kbd "C-,") nil)
2061 (define-key org-mode-map (kbd "C-M-m") nil)
2062 (define-key org-mode-map (kbd "C-k") nil)
2063 (define-key org-mode-map (kbd "C-j") nil)
2064 (define-key org-mode-map (kbd "C-M-i") nil)
2065 (define-key org-mode-map (kbd "C-M-t") nil)
2066 (define-key org-mode-map (kbd "M-a") 'nil)
2067 (define-key org-mode-map (kbd "C-a") nil)
2068 (define-key org-mode-map (kbd "M-e") nil)
2069 (define-key org-mode-map (kbd "C-e") nil)
2070 (define-key org-mode-map (kbd "C-3") nil)
2071 (define-key org-mode-map (kbd "<M-left>") nil)
2072 (define-key org-mode-map (kbd "<M-right>") nil)
2073 (define-key org-mode-map (kbd "<S-return>") nil)
2074 (define-key org-mode-map (kbd "<tab>") nil)
2075 (define-key org-mode-map (kbd "<C-S-down>") nil)
2076 (define-key org-mode-map (kbd "<C-S-up>") nil)
2077 (define-key org-mode-map (kbd "<S-down>") nil)
2078 (define-key org-mode-map (kbd "<S-up>") nil)
2079 (define-key org-mode-map "\t" nil))
2080 (add-hook 'org-mode-hook 'remove-org-binds)
2082 ;;; prog-mode-defaults
2085 (defun prog-mode-defaults ()
2086 "Default coding hook, useful with any programming language."
2087 ;; so that I can do completion before the dialog pops up
2088 (local-set-key (kbd "<tab>") 'auto-complete)
2089 ;; todo, this is causing error message on loading file, prolly not working
2090 ;;(flycheck-mode +1)
2091 (setq ac-sources (delq 'ac-source-dictionary ac-sources))
2092 (highlight-symbol-mode)
2093 (make-local-variable 'column-number-mode)
2094 ;; this says do autofilling using newcomment.el. The "only" is a misnomer.
2095 (set (make-local-variable 'comment-auto-fill-only-comments) t)
2096 (column-number-mode t)
2097 (turn-on-smartparens-mode)
2100 (font-lock-add-keywords
2101 nil `(("(\\(lambda\\>\\)"
2102 (0 (progn (compose-region (match-beginning 1) (match-end 1)
2103 ,(make-char 'greek-iso8859-7 107))
2105 (add-hook 'prog-mode-hook 'prog-mode-defaults)
2107 ;; enable flyspell in prog mode. text mode is handled
2108 (add-hook 'prog-mode-hook 'flyspell-prog-mode)
2112 ;;; yank auto-indent
2113 ;; automatically indenting yanked text if in programming-modes
2114 (defvar yank-indent-modes
2115 '(LaTeX-mode TeX-mode)
2116 "Modes in which to indent regions that are yanked (or yank-popped).
2117 Only modes that don't derive from `prog-mode' should be listed here.")
2119 (defvar yank-indent-blacklisted-modes
2120 '(python-mode slim-mode haml-mode)
2121 "Modes for which auto-indenting is suppressed.")
2123 (defvar yank-advised-indent-threshold 2000
2124 "Threshold (# chars) over which indentation does not automatically occur.")
2126 (defun yank-advised-indent-function (beg end)
2127 "Do indentation, as long as the region isn't too large."
2128 (if (<= (- end beg) yank-advised-indent-threshold)
2129 (indent-region beg end nil)))
2131 (defadvice yank (after yank-indent activate)
2132 "If current mode is one of 'yank-indent-modes,
2133 indent yanked text (with prefix arg don't indent)."
2134 (if (and (not (ad-get-arg 0))
2135 (not (member major-mode yank-indent-blacklisted-modes))
2136 (or (derived-mode-p 'prog-mode)
2137 (member major-mode yank-indent-modes)))
2138 (let ((transient-mark-mode nil))
2139 (yank-advised-indent-function (region-beginning) (region-end)))))
2141 (defadvice yank-pop (after yank-pop-indent activate)
2142 "If current mode is one of 'yank-indent-modes,
2143 indent yanked text (with prefix arg don't indent)."
2144 (if (and (not (ad-get-arg 0))
2145 (not (member major-mode yank-indent-blacklisted-modes))
2146 (or (derived-mode-p 'prog-mode)
2147 (member major-mode yank-indent-modes)))
2148 (let ((transient-mark-mode nil))
2149 (yank-advised-indent-function (region-beginning) (region-end)))))
2155 ;; # eval: (outline-minor-mode)
2156 ;; # outline-regexp: "\\( *\\)# [*]\\{1,8\\} "
2159 ;; avoid stupid git crap like "warning, terminal not fully functional"
2160 (setenv "PAGER" "cat")
2161 ;; don't store successive duplicates in comint command history
2162 (setq comint-input-ignoredups t)
2164 (defun add-mode-line-dirtrack ()
2165 (add-to-list 'mode-line-buffer-identification
2166 '(:propertize (" " default-directory " ") face dired-directory)))
2167 (add-hook 'shell-mode-hook 'add-mode-line-dirtrack)
2170 ;; don't fully understand it, but it works.
2171 ;; http://www.emacswiki.org/emacs/ShellDirtrackByProcfs
2172 (defun track-shell-directory/procfs ()
2173 (shell-dirtrack-mode 0)
2174 (add-hook 'comint-preoutput-filter-functions
2177 (when (string-match comint-prompt-regexp str)
2179 (format "/proc/%s/cwd" (process-id
2181 (current-buffer)))))))))
2183 (setq comint-buffer-maximum-size 100000)
2184 (add-to-list 'comint-output-filter-functions 'comint-truncate-buffer)
2187 (shell (generate-new-buffer-name "*shell*")))
2189 (defun shell-wrap (prefix)
2190 "wrap the shell function, automatically generate a new name for a prefix arg"
2196 (add-hook 'shell-mode-hook 'track-shell-directory/procfs)
2198 ;; the melpa git version had a catastrophic bug I reported.
2199 ;; downgraded to marmalade version and everything is working fine.
2200 (require 'smartparens-config)
2201 (show-smartparens-global-mode t)
2204 (defun gp/sp/pair-on-newline-and-indent (id action context)
2205 "Open a new brace or bracket expression, with relevant newlines and indent. "
2208 (indent-according-to-mode))
2209 (indent-according-to-mode))
2211 ;; when opening a pair, and then inserting a newline, push the closing pair to another newline
2212 (sp-pair "{" nil :post-handlers
2213 '(:add ((lambda (id action context)
2214 (gp/sp/pair-on-newline-and-indent id action context)) (kbd "<return>"))))
2215 (sp-pair "[" nil :post-handlers
2216 '(:add ((lambda (id action context)
2217 (gp/sp/pair-on-newline-and-indent id action context)) (kbd "<return>"))))
2220 ;; in my version, this is not a pairing.
2221 ;; not sure if it is in a future version since I reverted to marmalade
2222 ;; Don't need c-comments in strings -- they frustrate filename globs
2223 ;; (sp-pair "/*" nil :unless '(sp-in-string-p))
2225 ;; Don't need quotes to pair next to words
2226 (sp-pair "\"" nil :unless '(sp-point-before-word-p sp-point-after-word-p))
2227 (sp-pair "'" nil :unless '(sp-point-before-word-p sp-point-after-word-p))
2230 ;; todo, testout these mode specific settings from graphene.
2231 ;; Ruby-specific pairs and handlers
2233 (eval-after-load "ruby"
2234 '(require 'smartparens-ruby))
2237 (sp-local-pair '(markdown-mode gfm-mode) "*" "*"
2238 :unless '(sp-in-string-p)
2239 :actions '(insert wrap))
2242 (sp-local-pair 'html-mode "\"" nil :unless '(:rem sp-point-after-word-p))
2247 ;;; spell correction
2249 ispell-program-name "hunspell"
2250 ispell-silently-savep t) ; don't prompt to save personal dictionary
2252 (require 'rw-hunspell)
2253 ;; rw-hunspell sets up hunspell dictionary automagically.
2256 ;; Rant: Hunspell SHOULD be standard. its used by firefox and openoffice and
2257 ;; osx. In contrast, the first few words I added to aspell dictionary were
2258 ;; "emacs" "customizable" and "timestamp". Hunspell already has those,
2261 ;; ispell-personal-dictionary does not document where the hunspell
2262 ;; dictionary goes by default, but it is ~/.hunspell_en_US for me
2266 (setq-default TeX-PDF-mode t) ; use pdf
2268 ; more sensible defaults based on info manual quickstart
2269 (setq TeX-auto-save t)
2270 (setq TeX-parse-self t)
2274 ;;; visible mark mode
2276 ;; since it is not easy to change the mark overlay priority, I change this one.
2277 (setq show-paren-priority 999)
2280 (defface visible-mark-active
2281 '((((type tty) (class mono)))
2282 (t (:background "magenta"))) "")
2286 (defface mouse-cursor-face
2287 '((((type tty) (class mono)))
2288 (t (:background "DeepPink1"))) "")
2291 (require 'visible-mark)
2293 (setq visible-mark-faces '(visible-mark-face1 visible-mark-face2))
2294 (setq visible-mark-forward-faces '(visible-mark-forward-face1))
2297 ; highlight the last 2 marks
2298 (setq visible-mark-max 2)
2299 ; highlight 1 forward mark
2300 (setq visible-mark-forward-max 1)
2301 ; globally activate visible-mark-mode
2302 (global-visible-mark-mode +1)
2305 ;; todo, it doesn't seem to be exposed in elisp, but it would be nice
2306 ;; if I could define overlay faces to use inverse foreground color
2312 (setq erc-fill-prefix "")
2316 (when (string= (system-name) "kd") (setq vol 80))
2317 ;; speed is there so i can adjust and make it go slow so it plays long enough to adjust in pavucontrol
2318 (start-process-shell-command "ignoreme" nil (format "mpv --speed=1 --no-terminal --vo=null --volume=%d /a/bin/data/bird.mp3" vol)))
2319 ;; from https://www.emacswiki.org/emacs/ErcSound
2323 (when (string= (system-name) "tp") (setq vol 80))
2324 ;; speed is there so i can adjust and make it go slow so it plays long enough to adjust in pavucontrol
2325 (start-process-shell-command "ignoreme" nil (format "mpv --speed=.2 --no-terminal --vo=null --volume=%d /a/bin/data/bird.mp3" vol)))
2327 (defun erc-my-privmsg-sound (proc parsed)
2328 (let* ((tgt (car (erc-response.command-args parsed)))
2329 (privp (erc-current-nick-p tgt)))
2332 ;; We must return nil. See help for `erc-server-PRIVMSG-functions'
2335 (add-hook 'erc-server-PRIVMSG-functions
2336 'erc-my-privmsg-sound)
2338 (defun erc-sound-if-not-server (match-type nickuserhost msg)
2339 (unless (string-match "Server:[0-9]+" nickuserhost)
2341 (add-hook 'erc-text-matched-hook 'erc-sound-if-not-server)
2343 (eval-after-load "erc"
2344 '(erc-track-mode 1))
2346 ;; consider invisible frames to be unseen. seems like an obvious default
2347 erc-track-visibility 'visible
2348 ;; switch to buffer where i've been mentioned, etc instead of oldest
2349 erc-track-switch-direction 'importance
2350 ;; defaults minus fill. todo: modify the list instead of specifying it explicitly in case the defaults change
2352 '(autojoin button completion irccontrols list match menu move-to-prompt netsplit networks noncommands readonly ring stamp track)
2357 (defun rm-file-and-buffer ()
2358 "Removes file connected to current buffer and kills buffer."
2360 (let ((filename (buffer-file-name))
2361 (buffer (current-buffer))
2362 (name (buffer-name)))
2363 (if (not (and filename (file-exists-p filename)))
2364 (error "Buffer '%s' is not visiting a file!" name)
2365 (delete-file filename)
2366 (kill-buffer buffer)
2367 (message "File '%s' successfully removed" filename))))
2369 ;;; persistent registers
2370 ;; This needs to be at the end, because I visit a file, thus setting a
2371 ;; mode, and the mode hook needs to be setup before that.
2373 ;; I'm using persistent registers instead of bookmarks. I dun use them
2374 ;; much, so the added hassle of having to set it within this file is
2375 ;; worth the benefit of only having one concept in my mind.
2378 (?i (file . ,"~/.emacs.d/init.el"))
2379 (?o (file . ,"/a/work.org"))
2380 (?t (file . ,"/a/t.org"))
2381 (?s (file . ,"/usr/share/doc/exim4-base/spec.txt.gz"))
2382 (?w (file . ,"/p/w.org"))
2383 (?k (file . ,"/a/bin/ds/Arduino/Model01-Firmware/Model01-Firmware.ino"))
2384 (?x (file . ,"/a/x.txt"))
2386 (set-register (car r) (cadr r)))
2388 (setq undo-outer-limit 100000000 ; per undo command
2389 undo-limit 500000000 ; undo history limit
2390 undo-strong-limit 600000000) ; undo history limit plus some extra
2395 ;; note, this has weird errors when it was before recentf-mode
2397 ;; more resilient undo-tree-history if we have its location set up front.
2398 (setq undo-tree-history-directory-alist '(("." . "~/.undo-tree-history")))
2401 ;; todo, send patch undo-tree-visualize should scroll with the scroll key, instead of just pgup pgdn (aka next/prior)
2402 (global-undo-tree-mode)
2403 ;; disabled due to bug, something like unknown entry in undo tree canary
2404 ;; (setq undo-tree-auto-save-history t)
2405 (setq undo-outer-limit 100000000 ; per undo command
2406 undo-limit 500000000 ; undo history limit
2407 undo-strong-limit 600000000) ; undo history limit plus some extra
2408 ;; Undo in region just happens accidentally, and throws me off
2409 (setq undo-tree-enable-undo-in-region nil)
2415 (define-prefix-command 'terminal-key-map)
2416 (global-set-key (kbd "\e[") 'terminal-key-map)
2420 (global-set-key (kbd "C-x C-b") 'ibuffer)
2424 ;; Activate occur easily inside isearch
2427 (define-key isearch-mode-map (kbd "C-o")
2428 (lambda () (interactive)
2429 (let ((case-fold-search isearch-case-fold-search))
2430 (occur (if isearch-regexp
2432 (regexp-quote isearch-string))))))
2435 (defun my-isearch-toggle-regexp ()
2437 (isearch-toggle-regexp)
2438 (cond (isearch-regexp
2439 (global-set-key (kbd "C-r") 'isearch-backward-regexp)
2440 (define-key global-map (kbd "<f12>") 'isearch-forward-regexp))
2442 (global-set-key (kbd "C-r") 'isearch-backward)
2443 (define-key global-map (kbd "<f12>") 'isearch-forward))))
2444 (define-key isearch-mode-map (kbd "M-r") 'my-isearch-toggle-regexp)
2447 (define-key Info-mode-map "x" 'Info-follow-nearest-node)
2450 ;;;; single/special keys
2452 (define-key isearch-mode-map (kbd "TAB") 'isearch-query-replace)
2454 ;;;;; f12 - isearch-forward
2455 ;; explained in http://stackoverflow.com/questions/7411920/how-to-bind-search-and-search-repeat-to-c-f-in-emacs
2456 (global-set-key (kbd "<kp-add>") 'isearch-forward)
2457 (global-set-key (kbd "<f12>") 'isearch-forward)
2458 (define-key isearch-mode-map "\t" nil)
2459 (define-key isearch-mode-map (kbd "<kp-add>") 'isearch-repeat-forward)
2460 (define-key isearch-mode-map (kbd "<f12>") 'isearch-repeat-forward)
2461 ;; get rid of the standard completion binding, always use auto-complete
2462 ;; this didn't work very well
2463 ;;(global-set-key (kbd "TAB") 'auto-complete)
2464 (define-key global-map [remap completion-at-point] 'auto-complete)
2466 ;;;;; end - move-end-of-line
2467 ;; taken from emacs wiki, along with home function
2468 ;; http://www.emacswiki.org/emacs/BackToIndentationOrBeginning
2469 (defun point-in-comment ()
2470 "Determine if the point is inside a comment"
2472 (let ((syn (syntax-ppss)))
2474 (not (nth 3 syn)))))
2475 (defun end-of-code-or-line (arg)
2476 "Move to end of line, or before start of comments depending on situation.
2477 Toggle back and forth positions if we are already at one.
2478 Comments are recognized in any mode that sets syntax-ppss
2482 (let ((start (point))
2483 (bol (save-excursion
2486 (eol (progn (move-end-of-line arg) (point))))
2487 (while (point-in-comment)
2489 (when (= (point) bol)
2491 (throw 'bol (and (not (= eol start)) (>= start (point))))))
2492 (move-end-of-line arg)))
2494 (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)))
2496 ;;;;; home - back-to-indentation
2497 (defun back-to-indentation-or-beginning ()
2499 (if (= (point) (progn (back-to-indentation) (point)))
2500 (if (derived-mode-p 'org-mode)
2501 (org-beginning-of-line)
2502 (beginning-of-line))))
2503 (global-set-key (kbd "<home>") 'back-to-indentation-or-beginning)
2505 ;;;;; s-tab - indent-buffer
2507 (global-set-key (kbd "<S-iso-lefttab>") 'indent-buffer)
2509 (global-set-key (kbd "<backtab>") 'indent-buffer)
2510 ;;;;; s-delete - send-shell
2512 (global-set-key (kbd "<S-delete>") 'send-shell)
2514 ;; optional variables used by send-shell
2515 (setq shell-send-yank-key nil)
2517 (defun repeat-shell ()
2519 "Repeat the last command in shell-mode, displaying the window if needed."
2520 (let ((shell-buffer (get-buffer "*shell*")))
2522 (buffer-window-show shell-buffer)
2523 (let ((original-buffer (current-buffer)))
2525 (setq shell-buffer (current-buffer))
2526 (switch-to-buffer original-buffer)))
2527 (with-current-buffer shell-buffer
2528 (goto-char (point-max))
2529 (call-interactively 'comint-previous-input)
2530 ;; the t flag makes the buffer advance
2531 (comint-send-input nil t))))
2533 (setq compilation-filenames '("Makefile" "makefile"))
2535 (defun get-nearest-compilation-file ()
2536 "Search for the compilation file traversing up the directory tree."
2538 (let ((dir default-directory)
2539 (parent-dir (file-name-directory (directory-file-name default-directory)))
2540 (nearest-compilation-file 'nil))
2541 (while (and (not (string= dir parent-dir))
2542 (not nearest-compilation-file))
2543 (dolist (filename compilation-filenames)
2544 (setq file-path (concat dir filename))
2545 (when (file-readable-p file-path)
2546 (setq nearest-compilation-file file-path)))
2547 (setq dir parent-dir
2548 parent-dir (file-name-directory (directory-file-name parent-dir))))
2549 nearest-compilation-file))
2552 "call run-fun if it is set, else run make if there is a makefile,
2553 else save and repeat last shell command.
2554 run-fun is meant to store file local variables, which show how to
2555 do the main thing we want on this file, generally compile and
2558 example of setting it in a file:
2560 ;; run-fun: merge-test
2563 (if (and (boundp 'run-fun) run-fun)
2565 (let ((makefile (get-nearest-compilation-file)))
2566 (if (and makefile (stringp mode-name) (string= mode-name "C/l"))
2568 "make -f %s" (get-nearest-compilation-file)))
2572 (defun send-shell ()
2574 (send-shell-buffer "*shell*" 'shell (kbd "C-v")))
2576 (defun send-python ()
2578 (send-shell-buffer "*Python*" 'py-shell (kbd "C-v")))
2581 (defun send-shell-buffer (buffer-name &optional init shell-send-yank-key)
2582 "Send current line or region to shell-mode buffer.
2583 When in shell-mode, copy the current line to the
2584 most recently visited visible window.
2586 SHELL-SEND-YANK-KEY: key to use instead
2587 of yank to paste into recent window. This allows compatibility with
2588 modes like org-mode which have their own yank function."
2589 (if (string= (buffer-name) buffer-name)
2590 ;; this section is copied out of comint-send-input
2592 (let ((proc (get-buffer-process (current-buffer))))
2593 (if (not proc) (user-error "Current buffer has no process")
2596 (let* ((pmark (process-mark proc))
2597 (intxt (if (>= (point) (marker-position pmark))
2598 (progn (if comint-eol-on-send (end-of-line))
2599 (buffer-substring pmark (point)))
2600 (let ((copy (funcall comint-get-old-input)))
2605 (if (= (length intxt) 0)
2606 (kill-new (comint-previous-matching-input-string "." 1))
2607 (kill-new intxt)))))
2608 (kill-append "\n" nil)
2609 (select-window (previous-window nil nil 'visible))
2610 (if (and (boundp 'shell-send-yank-key) shell-send-yank-key)
2611 (call-interactively (global-key-binding shell-send-yank-key))
2613 (select-window (next-window nil nil 'visible)))
2618 (setq start (save-excursion (beginning-of-line) (point))
2619 end (save-excursion (end-of-line) (point)))
2620 (let (line-move-visual)
2621 (call-interactively 'next-line)))
2622 (send-comint-input buffer-name start end init))))
2624 ;; supporting functions
2625 (defun send-comint-input (buffer-name start end &optional init)
2626 "Input the region to BUFFER-NAME, assuming it is a comint-derived buffer.
2627 Show BUFFER-NAME if it is not show.
2628 Call INIT if BUFFER-NAME does not exist."
2629 (let ((input (filter-buffer-substring start end)))
2630 (send-comint-string buffer-name input init)))
2632 (defun send-comint-string (buffer-name string &optional init)
2633 "Input the string to BUFFER-NAME, assuming it is a comint-derived buffer.
2634 Show BUFFER-NAME if it is not show.
2635 Call INIT if BUFFER-NAME does not exist."
2636 (let ((buffer (get-buffer buffer-name)))
2638 (message "nobuffer")
2639 ;; save-excursion etc. don't work for (shell), so I do this instead
2640 (if init (let ((original-buffer (current-buffer)))
2641 (funcall init (and (boundp 'send-shell-buffer-name) send-shell-buffer-name))
2642 (switch-to-buffer original-buffer)
2643 (setq buffer (get-buffer buffer-name)))
2644 (error "No existing buffer found and no init function argument. ")))
2645 (buffer-window-show buffer)
2646 (with-current-buffer buffer
2647 (let ((proc (get-buffer-process buffer)))
2648 (goto-char (process-mark proc))
2650 (comint-send-input nil t)))))
2652 (defun buffer-window-show (&optional buffer action)
2653 "Like temp-buffer-window-show, but removed stuff
2654 relevant to it being temp or help."
2656 (with-current-buffer buffer
2657 (when (let ((window-combination-limit
2658 ;; When `window-combination-limit' equals
2659 ;; `temp-buffer' or `temp-buffer-resize' and
2660 ;; `temp-buffer-resize-mode' is enabled in this
2661 ;; buffer bind it to t so resizing steals space
2662 ;; preferably from the window that was split.
2663 (if (or (eq window-combination-limit 'temp-buffer)
2664 (and (eq window-combination-limit
2665 'temp-buffer-resize)
2666 temp-buffer-resize-mode))
2668 window-combination-limit)))
2670 ;;(message "window-combination-limit")
2671 ;;(print window-combination-limit)
2672 (setq window (display-buffer buffer action)))
2673 (setq frame (window-frame window))
2674 (unless (eq frame (selected-frame))
2675 (raise-frame frame))
2676 (setq minibuffer-scroll-window window)
2677 (set-window-hscroll window 0)
2678 ;; Return the window.
2682 ;; when poping help, etc, allow reusing a window in a different frame if it is visible
2683 ;; figured this out after spending quite a while reading doc string for display-buffer
2684 ;; which is the main function which uses this.
2685 ;; it will use other vars or its arg to override this,
2686 ;; but those things are often nil.
2687 ;; aha moments in reading it: ACTION = (FUNCTION-or-FUNCTIONLIST ALIST)
2688 ;; FRAME adds an association to ACTION's alist, but it's not used if ACTION arg is nil.
2689 (setq display-buffer-fallback-action `(,(car display-buffer-fallback-action) . '(reusable-frames . visible)))
2690 ;; stop splitting windows verticallly when I open a buffer or shell
2691 (setq split-height-threshold nil)
2693 ;;;;; s-left arrow - ---
2694 ;; cant be used in terminal
2695 ;; When I had a binding, i did this so org-mode wouldnt clobber it
2696 ;; (add-hook 'org-mode-hook
2698 ;; (define-key org-mode-map (kbd "<S-left>") nil)))
2700 ;;;;; s-right arrow - keyboard-yank-primary
2701 (defun keyboard-yank-primary ()
2703 (let ((mouse-yank-at-point t))
2704 (mouse-yank-primary nil)))
2706 (global-set-key (kbd "<S-right>") 'keyboard-yank-primary)
2707 (add-hook 'org-mode-hook
2709 (define-key org-mode-map (kbd "<S-right>") nil)))
2711 ; todo, test out if this can be used
2712 ;;;;; return - new line
2714 ;; todo, this doesn't set the keybind for the help minibuffer
2717 (global-set-key (kbd "\r") 'indent-new-comment-line)
2719 ;; don't use enter for autocomplete, we use tab or something
2720 (define-key ac-completing-map (kbd "<return>") nil)
2721 (define-key ac-completing-map "\r" nil)
2723 (add-hook 'org-mode-hook
2725 ;; copied from org-mode, replace org-enter with org-enter-indent
2726 (org-defkey org-mode-map "\C-m" 'org-return-indent)))
2729 (add-hook 'comint-mode-hook
2731 (define-key comint-mode-map "\r" nil)
2732 (define-key comint-mode-map (kbd "<return>") 'comint-send-input)))
2734 (add-hook 'comint-mode-hook
2736 (define-key comint-mode-map "\C-m" nil)
2737 (define-key comint-mode-map "\C-d" nil)))
2739 ;;;;; s-return - auto-correct-prev-word
2740 (global-set-key (kbd "<S-return>") 'flyspell-auto-correct-previous-word)
2741 ;; kp-enter is shift return in terminal
2742 (global-set-key (kbd "<kp-enter>") 'flyspell-auto-correct-previous-word)
2744 ;;;;; s-up arrow - my-contract-region
2745 (global-set-key (kbd "<S-up>") 'my-contract-region)
2746 ;;;;; c-up/down move 8 lines
2748 ;; compiling warns that next-line should be called interactively,
2749 ;; but we would have to do something dumb, like give it a
2750 ;; vector of keys in order to supply the 8 argument
2758 (global-set-key (kbd "<C-up>") 'up-fast)
2759 (global-set-key (kbd "<C-down>") 'down-fast)
2761 ;;;;; c-scroll comint prev/next prompt
2763 (add-hook 'comint-mode-hook
2765 (define-key comint-mode-map (kbd "<C-mouse-4>") 'comint-previous-prompt)
2766 (define-key comint-mode-map (kbd "<C-mouse-5>") 'comint-next-prompt)))
2767 ;;;;; m-scroll prev/next sexp
2768 (global-set-key (kbd "<M-mouse-4>") 'backward-sexp)
2769 (global-set-key (kbd "<M-mouse-5>") 'forward-sexp)
2770 ;;;;; S-scroll expand/contract region
2771 (global-set-key (kbd "<S-mouse-13>") 'my-contract-region)
2772 (global-set-key (kbd "<S-mouse-14>") 'er/expand-region)
2773 (global-set-key (kbd "<S-mouse-4>") 'my-contract-region)
2774 (global-set-key (kbd "<S-mouse-5>") 'er/expand-region)
2776 (defun my-contract-region (arg)
2778 (let ((current-prefix-arg '-))
2779 (call-interactively 'er/expand-region)))
2781 ;; todo: define c-m scroll. i manually set to normal scrolling, i dunno why
2784 ;;;;; c-s-scroll scale text
2786 (global-set-key (kbd "<C-S-mouse-4>") 'text-scale-increase)
2787 (global-set-key (kbd "<C-S-mouse-5>") 'text-scale-decrease)
2788 (global-set-key (kbd "<C-S-mouse-13>") 'text-scale-increase)
2789 (global-set-key (kbd "<C-S-mouse-14>") 'text-scale-decrease)
2790 (global-set-key (kbd "<C-S-down>") 'text-scale-increase)
2791 (global-set-key (kbd "<C-S-up>") 'text-scale-decrease)
2794 ;;;;; s-up arrow er/expand-region
2795 (global-set-key (kbd "<S-down>") 'er/expand-region)
2796 ;;;;; c-left/right move symbol
2798 (global-set-key (kbd "<C-left>") 'backward-symbol)
2799 (global-set-key (kbd "<C-right>") 'forward-symbol)
2803 ;;;;; M-2 shell-cd-to-file
2806 (defun shell-cd-to-file ()
2808 (let ((file (buffer-file-name)))
2810 (send-comint-string "*shell*"
2811 (concat "c " (file-name-directory file))
2813 (message "%s" "shell-cd-to-file: buffer has no file name"))))
2814 (global-set-key (kbd "M-2") 'shell-cd-to-file)
2816 ;;;;; C-M-2 copy-symbol
2817 (global-unset-key (kbd "C-M-2"))
2818 (defun copy-symbol (&optional arg)
2819 "Copy symbol at point into kill-ring"
2821 (kill-new (thing-at-point 'symbol)))
2823 (global-set-key (kbd "C-M-2") 'copy-symbol)
2825 ;;;;; M-3 dot-mode-execute
2827 (global-set-key (kbd "M-3") 'dot-mode-execute)
2829 ;;;;; C-M-3 recenter-top-bottom
2831 (global-set-key (kbd "C-M-3") 'recenter-top-bottom)
2833 ;;;;; C-q org-cycle, comint previous arg
2835 (global-set-key (kbd "C-q") 'bicycle-cycle)
2836 (add-hook 'org-mode-hook
2837 (lambda () (define-key org-mode-map (kbd "C-q") 'org-cycle)))
2838 (define-key widget-keymap (kbd "C-q") 'widget-forward)
2839 (add-hook 'comint-mode-hook
2840 (lambda () (define-key comint-mode-map (kbd "C-q") 'comint-insert-previous-argument)))
2842 ;;;;; M-q org-archive-to-archive-sibling
2844 (global-set-key (kbd "M-q") 'org-archive-to-archive-sibling)
2846 ;;;;; C-M-q quoted-insert
2848 (global-set-key (kbd "C-M-q") 'quoted-insert)
2850 ;;;;; C-w counsel-find-file
2852 (global-set-key (kbd "C-w") 'counsel-find-file)
2856 (global-set-key (kbd "M-w") 'shell-wrap)
2860 ;; todo, make repeated calls to this append the kills
2861 (defun copy-line (&optional arg)
2862 "Copy lines (as many as prefix argument) in the kill ring.
2863 Ease of use features:
2864 - Move to start of next line.
2865 - Appends the copy on sequential calls.
2866 - Use newline as last char even on the last line of the buffer.
2867 - If region is active, copy its lines."
2869 (let ((beg (line-beginning-position))
2870 (end (line-end-position (or arg 1))))
2872 (if (> (point) (mark))
2873 (setq beg (save-excursion (goto-char (mark)) (line-beginning-position)))
2874 (setq end (save-excursion (goto-char (mark)) (line-end-position)))))
2875 (if (eq last-command 'copy-line)
2876 (kill-append (buffer-substring beg end) (< end beg))
2877 (kill-ring-save beg end)))
2878 (kill-append "\n" nil)
2879 ;; dun need cuz I have yank-better
2880 ;;(beginning-of-line (or (and arg (1+ arg)) 2))
2881 (if (and arg (not (= 1 arg))) (message "%d lines copied" arg)))
2883 (global-set-key (kbd "C-e") 'copy-line)
2885 ;;;;; M-e org-clock-in-last
2887 (global-set-key (kbd "M-e") 'org-clock-in-last)
2889 ;;;;; C-r isearch-backward
2891 (global-set-key (kbd "C-r") 'isearch-backward)
2892 (add-hook 'comint-mode-hook
2894 (define-key comint-mode-map (kbd "C-r") 'comint-history-isearch-backward-regexp)))
2896 ;;;;; M-r org-clock-out
2898 (global-set-key (kbd "M-r") 'org-clock-out)
2900 ;;;;; C-a copy buffer
2903 "Copy entire buffer to clipboard"
2905 (clipboard-kill-ring-save (point-min) (point-max)))
2906 (global-set-key (kbd "C-a") 'copy-all)
2908 ;;;;; C-s - c-x prefix
2910 ; good info http://www.masteringemacs.org/articles/2011/02/08/mastering-key-bindings-emacs/
2911 ; rebinding the prefix keys are tricky. apparently, some modes ignore any redefinition of a prefix key and use it explicitly,
2912 ; so you have to dig into their key maps and redo things.
2913 ; There are 2 simpler alternatives which have their own downsides.
2914 ; One is cua mode, which I do not like because it smashes 2 keybinds onto 1 and limits what you can do.
2915 ; The other is keyboard-translate, which translates the key presses before anything else.
2916 ; The downside is that it translates them when you aren't using them as a prefix.
2917 ; Since the swaps I'm using are all very accessible, the only downside is some mental jugling when reading docs etc about these keybinds.
2919 ; I've seen this as an another suggestion, it was a total fail. The prefix command took over both keys.
2920 ; (define-key key-translation-map [f12] "\C-c")
2921 ; (define-key key-translation-map "\C-c" [left])
2924 ;idea to remove the hook later since it is only needed at startup.
2925 ; did not work however, and there is not a real need to fix it, so I did not investigate
2926 ;(defun removeSwapHook ()
2927 ; (remove-hook 'buffer-list-update-hook 'myKeySwap)
2928 ; (remove-hook 'change-major-mode-hook 'removeSwapHook))
2929 ;(add-hook 'change-major-mode-hook 'removeSwapHook)
2932 ; went through almost all the relevant standard hooks,
2933 ; this overcomes a known bug that (keyboard-translate) does not get applied when running emacs daemon
2934 (add-hook 'buffer-list-update-hook (lambda () (interactive)
2935 (keyboard-translate ?\C-x ?\C-s)
2936 (keyboard-translate ?\C-s ?\C-x)
2937 (keyboard-translate ?\C-c ?\C-d)
2938 (keyboard-translate ?\C-d ?\C-c)))
2942 ; these all don't work
2943 ; don't know why this doesn't error but reversing the keys does
2944 ;(keyboard-translate ?\t ?\M-\t)
2945 ;(keyboard-translate [M-tab] [tab])
2946 ; from what i can tell, it wants to use a keyboard-translate-table,
2947 ; which is a char table, which is a vector indexed by chars,
2948 ; and mod+tab is not a char (it has too many bits), it is an integer
2949 ; it actually says it can hold vectors or strings, but that it is obsolete to do so
2953 ;;;;; C-M-s - split-window-vertically
2955 (global-set-key (kbd "C-M-s") 'split-window-vertically)
2957 ;;;;; C-d - C-c prefix
2961 (global-set-key (kbd "M-d") 'run)
2963 ;;;;; C-M-d - swap buffer across windows
2964 ;; from http://www.emacswiki.org/emacs/TransposeWindows
2966 (setq swapping-buffer nil)
2967 (setq swapping-window nil)
2968 (defun swap-buffers-in-windows ()
2969 "Swap buffers between two windows"
2971 (if (and swapping-window
2973 (let ((this-buffer (current-buffer))
2974 (this-window (selected-window)))
2975 (if (and (window-live-p swapping-window)
2976 (buffer-live-p swapping-buffer))
2977 (progn (switch-to-buffer swapping-buffer)
2978 (select-window swapping-window)
2979 (switch-to-buffer this-buffer)
2980 (select-window this-window)
2981 (message "Swapped buffers."))
2982 (message "Old buffer/window killed. Aborting."))
2983 (setq swapping-buffer nil)
2984 (setq swapping-window nil))
2986 (setq swapping-buffer (current-buffer))
2987 (setq swapping-window (selected-window))
2988 (message "Buffer and window marked for swapping."))))
2990 (global-set-key (kbd "C-M-d") 'swap-buffers-in-windows)
2992 ;;;;; C-f - kill-whole-line
2994 (global-set-key (kbd "C-f") 'kill-whole-line-wrapper)
2995 (defun kill-whole-line-wrapper (&optional arg)
2996 "If we are at the end of the file, kill backwards instead of doing nothing."
2998 (if (= (point) (point-max))
2999 (kill-whole-line -1)
3000 (kill-whole-line arg)))
3002 ;;;;; M-f - print-var-at-point
3004 (defun print-var-at-point ()
3006 (let ((v (variable-at-point)))
3008 (message "%s: %s" v (symbol-value v))
3009 (message "no symbol found at point"))))
3010 (global-set-key (kbd "M-f") 'print-var-at-point)
3013 ;;;;; C-M-f - kill rest of line
3016 (add-hook 'org-mode-hook
3018 (define-key org-mode-map (kbd "C-M-f") 'org-kill-line)))
3020 (global-set-key (kbd "C-M-f") 'kill-line)
3021 ;;;;; C-g - keyboard-quit
3022 ;;;;; M-g - abort-recursive-edit
3024 (global-set-key (kbd "M-g") 'abort-recursive-edit)
3028 (global-set-key (kbd "C-M-g") 'mu4e)
3030 ;;;;; C-z - undo-only
3031 (global-set-key (kbd "C-z") 'undo-tree-undo)
3032 ;;;;; C-M-z - suspend-frame
3033 (global-set-key (kbd "C-z") 'suspend-frame)
3034 ;; previously, i meant to only use gui and ran this to
3035 ;; be sure it never got ran
3036 ;;(defun suspend-frame() (interactive))
3038 ;;;;; C-x - kill-region
3040 (global-set-key (kbd "C-s") 'kill-region)
3042 ;;;;; M-x - counsel-m-x
3045 ;; todo; check out smex-show-unbound-commands shows frequently used commands that have no key bindings.
3046 ;; this must be before smex-initialize
3048 smex-save-file "~/.emacs.d/.smex-items")
3051 (global-set-key (kbd "M-x") 'counsel-M-x)
3053 ;;;;; C-M-x - cut-to-register
3055 ;; same args as copy-to-register
3056 (defun cut-to-register (register start end &optional delete-flag region)
3057 (interactive (list (register-read-with-preview "Cut to register: ")
3062 (copy-to-register register start end t region))
3064 (global-set-key (kbd "C-M-x") 'cut-to-register)
3068 (global-set-key (kbd "C-d") 'kill-ring-save)
3069 (add-hook 'c-mode-hook
3070 (lambda () (define-key c-mode-map (kbd "C-d") nil)))
3071 (add-hook 'comint-mode-hook
3073 (define-key comint-mode-map (kbd "C-d") nil)))
3074 ;; the base map is shared by many c-modes, like java
3075 (add-hook 'c-mode-hook
3077 (define-key c-mode-base-map "\C-d" nil)
3078 (define-key c-mode-base-map (kbd "<deletechar>") 'c-electric-delete-forward)))
3081 ;;;;; M-c - delete-other-windows
3083 ;; todo, consider binding/using org-capture
3084 (define-key global-map "\M-c" 'delete-other-windows)
3086 ;;;;; C-M-c - copy-to-register
3088 (global-set-key (kbd "C-M-c") 'copy-to-register)
3092 (global-set-key (kbd "C-v") 'yank-better)
3096 (defun yank-better (arg)
3097 "Paste, linewise if our kill ends with a newline.
3098 I change the behavior of plain prefix. It makes it not do linewise paste,
3099 because sometimes you want to yank pop and a linewise paste screws that up.
3100 c-u with no number normally makes the point go before the yank.
3101 That is pointless for me, as it would be just as easier and less
3102 thought to pop the mark after yanking cuz it is set to before the mark."
3104 (if (and (not (equal arg '(4))) (string-suffix-p "\n" (current-kill 0 t)))
3105 (beginning-of-line))
3106 (if (and (stringp mode-name) (string= mode-name "Org"))
3107 (call-interactively 'org-yank)
3108 (setq this-command 'yank)
3109 (call-interactively 'yank (and (not (equal arg '(4)))))))
3111 (put 'yank-better 'delete-selection 'yank)
3113 ;;;;; M-v - insert-register
3115 (global-set-key (kbd "M-v") 'insert-register)
3117 ;;;;; C-M-v - yank-pop
3119 (global-set-key (kbd "C-M-v") 'yank-pop)
3121 ;;;;; C-b - other-window
3123 (global-set-key (kbd "C-b") 'other-window)
3125 ;;;;; M-b - isearch-backward-current-symbol
3127 (global-set-key (kbd "M-b") 'isearch-backward-current-symbol)
3129 ;;;;; C-M-b - isearch-current-symbol
3131 (global-set-key (kbd "C-M-b") 'isearch-current-symbol)
3134 ;; in terminal, it's just TAB, duplicate keybind.
3136 ;; in terminal it's duplicated of C-M-i
3137 ;;;;; C-delete - kill-symbol
3139 (global-set-key (kbd "<C-delete>") 'kill-symbol)
3140 (defun kill-symbol (arg)
3142 (kill-region (point) (save-excursion (forward-symbol arg) (point))))
3145 ;;;;; C-M-delete - kill-sexp
3147 (global-set-key (kbd "<C-M-delete>") 'kill-sexp)
3149 ;;;;; C-left-arrow - compile / comint search
3152 (and (bound-and-true-p var)
3153 (not (eq var 'unset))))
3154 (global-set-key (kbd "C-(") 'run)
3156 ;; make compile work from the gtags root dir
3157 (defadvice compile (before pre-compile-advice activate)
3159 (when (set-p ggtags-project-root)
3160 (setq-local compile-saved-dir default-directory)
3161 (setq default-directory ggtags-project-root)))
3162 (defadvice compile (after post-compile-advice activate)
3163 (when (bound-and-true-p compile-saved-dir)
3164 (setq default-directory compile-saved-dir)))
3167 (add-hook 'c-mode-hook (lambda () (define-key c-mode-map (kbd "C-(") 'compile)))
3168 (add-hook 'comint-mode-hook
3170 (define-key isearch-mode-map (kbd "C-(") 'isearch-repeat-backward)
3171 (define-key comint-mode-map (kbd "C-(") 'isearch-backward)))
3174 ;;;;; C-M-left-arrow - org-shiftup
3176 (add-hook 'org-mode-hook
3177 (lambda () (define-key org-mode-map (kbd "C-M-(") 'org-shiftup)))
3179 ;;;;; C-right-arrow - forward-symbol
3180 ;;;;; C-M-right-arrow - org-shiftdown
3181 (add-hook 'org-mode-hook
3182 (lambda () (define-key org-mode-map (kbd "C-M-)") 'org-shiftdown)))
3184 ;;;;; C-backspace - backward-kill-symbol
3186 (define-key terminal-key-map (kbd "4b") 'backward-kill-symbol) ;c-backspace in my konsole
3188 ;; c-w is duplicate in terminal
3189 (global-set-key (kbd "<C-backspace>") 'backward-kill-symbol)
3190 (add-hook 'comint-mode-hook
3192 (define-key comint-mode-map (kbd "<C-backspace>") 'backward-kill-word)))
3193 (defun backward-kill-symbol (arg)
3195 (kill-region (point) (save-excursion (backward-symbol arg) (point))))
3197 ;;;;; C-M-backspace - backward-kill-sexp
3199 (global-set-key (kbd "<C-M-backspace>") 'backward-kill-sexp)
3202 ;;;;; M-8 - delete-window-or-exit
3204 (global-set-key (kbd "M-8") 'delete-window-or-exit)
3206 (defun delete-window-or-exit ()
3207 "Delete window or exit emacs."
3209 (if (condition-case nil (delete-window) (error t))
3210 (if (or (boundp 'server-process) (> (length (frame-list)) 1))
3211 (progn (basic-save-buffer) (delete-frame))
3212 (save-buffers-kill-terminal t))))
3214 ;;;;; C-* - split-window-horizontally
3215 (global-set-key (kbd "C-*") 'split-window-horizontally)
3216 ;;;;; C-M-* - calc-dispatch
3218 (global-set-key (kbd "C-M-*") 'calc-dispatch)
3220 ;;;;; M-9 - kill-buffer
3222 (defun kill-buffer-no-ido ()
3223 "kill-buffer, avoid the ido remapping"
3226 (global-set-key (kbd "M-9") 'kill-buffer-no-ido)
3228 ;; strangely, in simple mode, this is overridden.
3229 ;; I found this map to override, but it didn't work, so it seems its being bound some other way.
3230 ;; I did a grep of the emacs sources, but couldn't find anything.
3231 ;; (define-key universal-argument-map [?9 nil)
3233 ;;;;; C-M-9 - end server edit
3234 ;; save & kill buffer if it was opened externally via emacsclient
3237 (defun server-edit-save ()
3241 (global-set-key (kbd "C-M-9") 'server-edit-save)
3243 ;;;;; C-u - universal-argument
3244 ;;;;; C-M-u - search-keybind
3246 (global-set-key (kbd "C-M-u") 'search-keybind)
3248 (defun search-keybind (regexp &optional nlines)
3249 (interactive (occur-read-primary-args))
3252 (set-buffer "*Help*")
3254 (delete-windows-on "*Help*")
3258 ;; todo: try making use
3259 ;; this is the key in terminal
3260 ;;M-[ 4 d is undefined
3262 ;; previously had this for enhancing graphical keybinds,
3263 ;; but afaik its no help since i want terminal to work
3265 ;; (define-key input-decode-map [?\C-i] [C-i])
3267 ;;;;; C-M-i - query-replace-regexp
3269 (global-set-key (kbd "C-M-i") 'query-replace-regexp)
3270 (add-hook 'flyspell-mode-hook
3271 (lambda () (define-key flyspell-mode-map (kbd "C-M-i") nil)))
3272 (add-hook 'text-mode-hook
3273 (lambda () (define-key text-mode-map (kbd "C-M-i") nil)))
3278 (global-set-key (kbd "C-o") 'occur)
3280 ;;;;; C-M-o - counsel-imenu
3282 (global-set-key (kbd "C-M-o") 'counsel-imenu)
3284 ;;;;; C-p - move-mouse-to-point
3286 (global-set-key (kbd "C-p") 'move-mouse-to-point)
3288 ;;;;; C-M-p - delete-horizontal-space
3290 (global-set-key (kbd "C-M-p") 'delete-horizontal-space)
3292 ;;;;; C-j - pop-to-mark
3294 (defun my-pop-to-mark-command ()
3295 "Jump to mark, and pop a new position for mark off the ring.
3296 \(Does not affect global mark ring\)."
3298 (pop-to-mark-command)
3299 (if (and (derived-mode-p 'org-mode) (outline-invisible-p))
3300 (org-show-context 'mark-goto)))
3302 (global-set-key (kbd "C-j") 'my-pop-to-mark-command)
3303 (add-hook 'ido-setup-hook
3305 (define-key ido-common-completion-map (kbd "C-j") 'ido-select-text)
3307 (add-hook 'lisp-interaction-mode-hook
3309 (define-key lisp-interaction-mode-map (kbd "C-j") nil)))
3312 ;;;;; M-j - previous-error
3314 (global-set-key (kbd "M-j") 'previous-error)
3316 ;;;;; C-M-j - register prefix
3318 (define-key global-map (kbd "C-M-j") ctl-x-r-map)
3319 (define-key ctl-x-r-map "m" 'kmacro-to-register)
3322 ;;;;; C-k - jump-to-register
3325 (global-set-key (kbd "C-k") 'jump-to-register)
3327 ;;;;; M-k - next-error
3329 (global-set-key (kbd "M-k") 'next-error)
3333 (global-set-key (kbd "C-M-k") 'man)
3335 ;;;;; C-l - ivy-switch-buffer
3337 (global-set-key (kbd "C-l") 'ivy-switch-buffer)
3339 ;;;;; C-M-l - move cursor top bottom mid, comint clear screen
3341 (global-set-key (kbd "C-M-l") 'move-to-window-line-top-bottom)
3343 ;;;;; C-; - used in flyspell, not sure what for, otherwise unbound
3344 ;;;;; M-; - comment-dwim
3345 ;;;;; C-M-; - comment-current-line-dwim
3347 (defun comment-current-line-dwim ()
3348 "Comment or uncomment the current line."
3351 (push-mark (beginning-of-line) t t)
3354 (move-beginning-of-line 2))
3355 (global-set-key (kbd "C-M-;") 'comment-current-line-dwim)
3358 ;; terminal/console needs this. otherwise, we could do this
3359 ;; to make C-m be a valid key in graphical mode.
3360 ;; (define-key input-decode-map [?\C-m] [C-m])
3361 ;;;;; C-M-m - recursive grep
3363 (define-key global-map (kbd "C-M-m") 'rgrep)
3366 ;; not recognized by terminal, can't get konsole keydef file to recognize comma,
3367 ;; todo: dig into konsole sources, or try newer version than t8
3369 (add-hook 'flyspell-mode-hook
3370 (lambda () (define-key flyspell-mode-map (kbd "C-,") nil)))
3372 ;;;;; C-M-, - ind-file-in-project
3374 (global-set-key (kbd "C-M-,") 'find-file-in-project)
3376 ;;;;; C-. - find recent file
3378 (add-hook 'flyspell-mode-hook
3379 (lambda () (define-key flyspell-mode-map (kbd "C-.") nil)))
3380 (define-key dot-mode-map (kbd "C-.") nil)
3381 (define-key terminal-key-map (kbd "4c") 'counsel-recentf)
3382 (global-set-key (kbd "C-.") 'counsel-recentf)
3383 (add-hook 'php-mode-hook
3384 (lambda () (define-key php-mode-map (kbd "C-.") nil)))
3388 (define-key dot-mode-map (kbd "C-M-.") nil)
3389 ;; (global-set-key (kbd "C-M-.") 'execute-extended-command)
3391 ;;;;; C-/ - join lines
3393 (defun vim-style-join-line ()
3396 (global-set-key (kbd "C-/") 'vim-style-join-line)
3397 (define-key undo-tree-map (kbd "C-/") nil)
3399 ;;;;; C-M-/ - copy-buffer-file-name
3401 ;; haven't bound this atm, todo, maybe someday?
3402 (defun copy-variable (variable)
3404 (let ((v (variable-at-point))
3405 (enable-recursive-minibuffers t)
3407 (setq val (completing-read (if (symbolp v)
3409 "Describe variable (default %s): " v)
3410 "Describe variable: ")
3413 (or (get vv 'variable-documentation)
3414 (and (boundp vv) (not (keywordp vv)))))
3416 (if (symbolp v) (symbol-name v))))
3417 (list (if (equal val "")
3419 (kill-new (symbol-value variable)))
3421 (defun copy-buffer-file-name ()
3424 ((derived-mode-p 'mu4e-view-mode) (mu4e-message-field-at-point :path))
3425 (t buffer-file-name))
3431 (global-set-key (kbd "C-M-/") 'copy-buffer-file-name)
3435 ;;;;; C-up-arrow - org prev headline
3437 ;; disabled just because i don't want to accidentally hit it
3438 (define-key global-map "\C-_" nil)
3439 (global-set-key (kbd "<C-_>") 'beginning-of-defun)
3441 (add-hook 'org-mode-hook
3443 (define-key org-mode-map (kbd "\C-_") 'outline-previous-visible-heading)))
3448 ;;;;; C-S-up-arrow - winner undo
3450 (global-set-key (kbd "<C-S-_>") 'winner-undo)
3452 ;;;;; C-down-arrow - org next headline
3454 (global-set-key (kbd "<C-kp-enter>") 'end-of-defun)
3456 (add-hook 'org-mode-hook
3458 (define-key org-mode-map (kbd "<C-kp-enter>") 'outline-next-visible-heading)))
3463 ;;;;; C-M-down-arrow - toggle-mark-activation
3465 (defun toggle-mark-activation ()
3471 (global-set-key (kbd "<C-M-kp-enter>") 'toggle-mark-activation)
3473 ;;;;; C-S-down-arrow winner redo
3475 (global-set-key (kbd "<C-S-kp-enter>") 'winner-redo)
3478 ;;;;; C-S-down-arrow - m-x for major mode
3480 ;; todo, update this for ivy
3481 (global-set-key (kbd "<C-S-kp-enter>") 'smex-major-mode-commands)
3483 ;;;;; C-lbracket - ----
3484 ;;;;; C-M-lbracket - scroll-right
3486 (global-set-key (kbd "C-M-[") 'scroll-right)
3488 ;;;;; C-rbracket - fill-paragraph
3490 (global-set-key (kbd "C-]") 'fill-paragraph)
3492 ;;;;; C-M-rbracket - scroll-left
3494 (global-set-key (kbd "C-M-]") 'scroll-left)
3496 ;;;;; C-return - newline-anywhere
3498 (defun newline-anywhere ()
3499 "Add a newline from anywhere in the line."
3502 (newline-and-indent))
3503 (global-set-key (kbd "<C-return>") 'newline-anywhere)
3506 ;;;;; M-return - plain newline
3508 (defun plain-newline ()
3511 (global-set-key (kbd "<M-return>") 'plain-newline)
3514 ;;;;; C-space - org-edit-special
3516 ;; commented due to new keyboard needing ctrl-space for mark
3517 ;; (kbd "<C-space>") does not work, (kbd "C-SPC") should work
3518 ;; (add-hook 'org-mode-hook
3520 ;; (define-key org-mode-map (kbd "C-SPC") 'org-edit-special)
3521 ;; ;; org-src-mode-map is broken in git version of emacs.
3522 ;; ;; temporarily use this for exiting edit-special mode.
3523 ;; (global-set-key (kbd "C-M--") 'org-edit-src-exit)
3524 ;; (define-key org-src-mode-map (kbd "C-SPC") 'org-edit-src-exit)))
3526 ;;;;; C-M-space - before or under cursor
3528 (global-set-key (kbd "C-M-SPC") 'ispell-word)
3532 (global-set-key (kbd "C-M-4") 'widen)
3534 ;;;;; C-tab-key - query-replace
3537 (global-set-key (kbd "<C-kp-add>") 'query-replace)
3539 ;;;;; C-t - org cycle todo / toggle comint motion
3541 (add-hook 'org-mode-hook
3543 (define-key org-mode-map (kbd "C-t") 'org-todo)))
3545 (defun my-comint-previous-input (arg)
3547 (if (comint-after-pmark-p)
3548 (comint-previous-input arg)
3551 (defun my-comint-next-input (arg)
3553 (if (comint-after-pmark-p)
3554 (comint-next-input arg)
3557 (add-hook 'comint-mode-hook
3559 (define-key comint-mode-map (kbd "C-t") 'comint-toggle-arrow-keys)
3560 (define-key comint-mode-map (kbd "<up>") 'my-comint-previous-input)
3561 (define-key comint-mode-map (kbd "<down>") 'my-comint-next-input)))
3564 (defun comint-toggle-arrow-keys ()
3566 (toggle-arrow-keys comint-mode-map))
3568 (setq-default comint-arrow-movement nil)
3569 (defun toggle-arrow-keys (map)
3570 (cond ((lookup-key map (kbd "<up>"))
3571 (setq-local comint-arrow-movement t)
3572 (define-key map (kbd "<up>") nil)
3573 (define-key map (kbd "<down>") nil))
3575 (setq-local comint-arrow-movement nil)
3576 (define-key map (kbd "<up>") 'my-comint-previous-input)
3577 (define-key map (kbd "<down>") 'my-comint-next-input)
3578 (goto-char (point-max)))))
3580 (eval-after-load "message"
3581 '(define-key message-mode-map (kbd "C-t") 'mail-signature))
3584 ;;;;; C-M-t - org timestamp
3586 (global-set-key (kbd "C-M-t") 'org-time-stamp-with-time)
3588 ;;;;; C-home - start of buffer
3589 ;;;;; C-end - end of buffer
3590 ;;;; right secondary
3591 ;;;;; C-^ - save-buffers-kill-emacs
3593 (global-set-key (kbd "C-^") 'save-buffers-kill-emacs)
3595 ;;;;; C-M-6 - insert-small-copyright
3597 (defun insert-small-copyright ()
3600 (let ((beg (point)))
3601 (insert "Copyright (C) 2019 Ian Kelling\nThis program is under GPL v. 3 or later, see <http://www.gnu.org/licenses/>")
3602 (comment-region beg (point))))
3604 (global-set-key (kbd "C-M-6") 'insert-small-copyright)
3606 ;;;;; M-7 - calc-embedded-word
3608 (global-set-key (kbd "M-7") 'calc-embedded-word)
3610 ;;;;; C-M-7 - insert-full-copyright
3612 (defun insert-full-copyright ()
3615 (let ((beg (point)))
3616 (insert "Copyright (C) 2019 Ian Kelling\n")
3618 (insert "This program is free software: you can redistribute it and/or modify\n")
3619 (insert "it under the terms of the GNU General Public License as published by\n")
3620 (insert "the Free Software Foundation, either version 3 of the License, or\n")
3621 (insert "(at your option) any later version.\n")
3623 (insert "This program is distributed in the hope that it will be useful,\n")
3624 (insert "but WITHOUT ANY WARRANTY; without even the implied warranty of\n")
3625 (insert "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n")
3626 (insert "GNU General Public License for more details.\n")
3628 (insert "You should have received a copy of the GNU General Public License\n")
3629 (insert "along with this program. If not, see <http://www.gnu.org/licenses/>.\n")
3630 (comment-region beg (point))))
3632 (global-set-key (kbd "C-M-7") 'insert-full-copyright)
3635 ;;;;; C-0 - text-scale-reset
3637 (defun text-scale-reset ()
3640 (global-set-key (kbd "C-0") 'text-scale-reset)
3642 ;;;;; C-M-0 - insert-apache
3644 (defun insert-apache ()
3647 (let ((beg (point)))
3648 (insert "Copyright (C) 2017 Ian Kelling\n")
3650 (insert "Licensed under the Apache License, Version 2.0 (the \"License\");\n")
3651 (insert "you may not use this file except in compliance with the License.\n")
3652 (insert "You may obtain a copy of the License at\n")
3654 (insert " http://www.apache.org/licenses/LICENSE-2.0\n")
3656 (insert "Unless required by applicable law or agreed to in writing, software\n")
3657 (insert "distributed under the License is distributed on an \"AS IS\" BASIS,\n")
3658 (insert "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n")
3659 (insert "See the License for the specific language governing permissions and\n")
3660 (insert "limitations under the License.\n")
3661 (comment-region beg (point))))
3662 (global-set-key (kbd "C-M-0") 'insert-apache)
3665 ;;;;; C-M-- - org-edit-src-exit
3668 (global-set-key (kbd "C-y") 'undo-tree-redo)
3669 (add-hook 'org-mode-hook
3670 (lambda () (define-key org-mode-map (kbd "C-y") nil)))
3673 ;;;;; C-\ - sr-speedbar-toggle
3674 (global-set-key (kbd "C-\\") 'sr-speedbar-toggle)
3676 ;;;;; C-M-\ - mark-defun
3678 (global-set-key (kbd "C-M-\\") 'mark-defun)
3680 ;;;;; C-h - help-prefix
3682 ;;;;; C-' - val-expression
3684 (global-set-key (kbd "C-'") 'eval-expression)
3686 ;;;;; C-n - unpop to mark
3688 (defun unpop-to-mark-command ()
3689 "Unpop off mark ring. Does nothing if mark ring is empty."
3692 (let ((pos (marker-position (car (last mark-ring)))))
3693 (if (not (= (point) pos))
3695 (setq mark-ring (cons (copy-marker (mark-marker)) mark-ring))
3696 (set-marker (mark-marker) pos)
3697 (setq mark-ring (nbutlast mark-ring))
3698 (goto-char (marker-position (car (last mark-ring))))))))
3700 (global-set-key (kbd "C-n") 'unpop-to-mark-command)
3702 ;;;;; C-M-n - narrow-to-region
3704 (global-set-key (kbd "C-M-n") 'narrow-to-region)
3706 ;;;;; C-escape - find-tag
3708 (global-set-key (kbd "<C-escape>") 'find-tag)
3710 ;;; end let from start of file
3714 ;; eval: (outline-minor-mode)