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