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