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