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