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