X-Git-Url: https://iankelling.org/git/?a=blobdiff_plain;ds=sidebyside;f=init.el;h=0553e7c17f7dcb8d4eb2b56847d052f528cea22a;hb=HEAD;hp=6b279cae0780a9d1c901dfdfe0e7bbf2a8319192;hpb=a5e731477f1535eb05c207de961c3fbf9a1037a8;p=dot-emacs
diff --git a/init.el b/init.el
index 6b279ca..0553e7c 100644
--- a/init.el
+++ b/init.el
@@ -1,4 +1,4 @@
-;; Copyright (C) 2014 Ian Kelling
+;; Copyright (C) 2020 Ian Kelling
;; This program is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
@@ -13,77 +13,3164 @@
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see .
-
;; do m-x benchmark-init to see some benchmark stats
-;;(add-to-list 'load-path "~/.emacs.d/src/benchmark-init-el/")
+;;(add-to-list 'load-path (concat user-emacs-directory "src/benchmark-init-el/")
;;(require 'benchmark-init-loaddefs)
;;(benchmark-init/activate)
-
;;; init.el --- the start of customization
-;; (toggle-debug-on-error) ;uncomment to help debug
+;;(toggle-debug-on-error) ;uncomment to help debug
-;; stop from minimizing & freezing the gui
-;; Added by Package.el. This must come before configurations of
-;; installed packages. Don't delete this line. If you don't want it,
-;; just comment it out by adding a semicolon to the start of the line.
-;; You may delete these explanatory comments.
-(package-initialize)
+;; stop from minimizing & freezing the gui
+;; used to freeze emacs and was really annoying,
+;; seems its changed now. no harm in keeping this though.
(global-unset-key (kbd "C-z"))
-;; these need to be done before the hook in order to satisfy the byte compiler
-;; (add-to-list 'load-path "~/.emacs.d/elpa/smartparens-20140328.809")
-;; (add-to-list 'load-path "~/.emacs.d/elpa/dash-20140308.656")
+;; speed up init https://www.reddit.com/r/emacs/comments/3kqt6e/2_easy_little_known_steps_to_speed_up_emacs_start/
+;; https://github.com/jwiegley/dot-emacs/blob/master/init.el
+(defvar file-name-handler-alist-old file-name-handler-alist)
+(setq package-enable-at-startup nil
+ file-name-handler-alist nil
+ message-log-max 16384
+ gc-cons-threshold 402653184
+ gc-cons-percentage 0.6
+ auto-window-vscroll nil)
-;;(add-to-list 'load-path "~/.emacs.d/src/ghci-completion")
-(add-to-list 'load-path "~/.emacs.d/emacs/site-lisp/org")
+(add-hook 'after-init-hook
+ `(lambda ()
+ (setq file-name-handler-alist file-name-handler-alist-old
+ ;; 100 mb
+ gc-cons-threshold 100000000))
+ ;; taken from wiegley, dunno why the t is there.
+ t)
-;; git version of gnus
-;; (add-to-list 'load-path "~/.emacs.d/src/gnus/lisp")
-(require 'info)
-(add-to-list 'Info-default-directory-list "~/.emacs.d/src/gnus/texi")
+;; 2019-6-26, 1.26s
+;; ; to profile init:
+;; ; uncomment the following block
+;;(require 'benchmark-init)
+;;(add-hook 'after-init-hook 'benchmark-init/deactivate)
+;; ; Then run:
+;; ; emacs -f benchmark-init/show-durations-tabulated
+;; ; emacs -f benchmark-init/show-durations-tree
+;; ; to catch things post-init
+;; ; emacs -f benchmark-init/deactivate
-;; needed for git version
-;;(add-to-list 'load-path "~/.emacs.d/src/haskell-mode")
-;;(require 'haskell-mode-autoloads)
-;;(add-to-list 'Info-default-directory-list "~/.emacs.d/src/haskell-mode")
-(require 'bbdb-loaddefs "~/.emacs.d/src/bbdb/lisp/bbdb-loaddefs.el")
-(setq bbdb-print-tex-path "~/.emacs.d/src/bbdb/tex")
+(setq init-dir (file-name-directory load-file-name))
-;;(add-hook 'server-visit-hook 'raise-frame)
+;; these need to be done before the hook in order to satisfy the byte compiler or batch mode
+(add-to-list 'load-path (concat user-emacs-directory "src/readline-complete"))
+;; disabled since not used.
+;;(add-to-list 'load-path (concat user-emacs-directory "src/bbdb-csv-import"))
+;;(add-to-list 'load-path (concat user-emacs-directory "src/spray"))
-;; load init in `after-init-hook' so all packages are loaded
-;; todo, learn about the weird evaluation order of this hook that requires the quoting.
-;; adapted from starter-kit
-(add-hook 'after-init-hook
- `(lambda ()
- ;; todo, set this var in my-init.org and use it instead
- ;; of .emacs.d
- (setq init-dir ,(file-name-directory load-file-name))
- (unless (equal (user-uid) 0) ; don't make root owned files
- (byte-recompile-directory init-dir))
- ;; (byte-recompile-directory init-dir 0) ; with the 0,
- ;; compile .el files that have no .elc file already
-
- ;; this must be loaded first to avoid an error: void-function(cl-member)
- (require 'cl)
- ;; added org-habit, org-drill, org-mobile from the defaults
- ;; disabled because I'm not using org-drill, and I see
- ;; this error on startup of emacs server,
- ;; which might be nothing but meh,
- ;; File mode specification error: (void-function org-drill-add-cloze-fontification)
-
- (require 'org)
- ;; (setq org-modules (quote (org-bbdb org-bibtex org-docview org-gnus
- ;; org-info org-jsinfo org-irc org-mew
- ;; org-mhe org-rmail org-vm org-wl org-w3m
- ;; org-habit org-drill org-mobile)))
- (org-babel-load-file (expand-file-name "my-init.org" init-dir))
- (org-babel-load-file (expand-file-name "dev.org" init-dir))))
-
-;;init.el ends here
+(add-to-list 'load-path (concat user-emacs-directory "src/visible-mark"))
+
+
+
+;; previously, i was doing byte-recompile-directory, but
+;; now i just have one init file
+(unless (equal (user-uid) 0) ; don't make root owned files
+ (byte-recompile-file (expand-file-name "init.el" init-dir) nil 0)
+ (when (file-exists-p "/p/c/mymu4e.el")
+ (byte-recompile-file "/p/c/mymu4e.el" nil 0))
+ )
+
+;;; misc emacs documentation
+
+;;;; how to find auto-saved files that need recovering
+;; find a recently dated file in ~/.emacs.d/auto-save-list/, and see the files listed in it.
+;; #file# is an auto-save file. It may or may not be different than the file is corresponds to.
+;; If it is different, emacs will give a message about recovering it when you open it.
+
+;;;; misc org functions
+
+;; ;; these are usefull with (goto-char)
+;; ;; find named entity, other than headline
+;; (org-find-entry-with-id "string-number-or-symbol")
+
+;; (org-find-exact-headline-in-buffer "heading" nil t)
+
+;; ;; remove any indent level which is throughout the buffer
+;; (org-do-remove-indentation)
+
+
+;;;; gnus
+
+;; good info http://www.emacswiki.org/emacs/GnusTutorial
+;; good info http://www.emacs.uniyar.ac.ru/doc/em24h/emacs183.htm
+
+
+;; After downloading mailing list archives, once you have an mbox file,
+;; there are rather straightforward ways to get it into any mail program,
+;; but I will cover gnus, which I use and is a bit tricky.
+
+;; gnus has a native search (limited, too slow for body text searches), and external search engine integration.
+;; gnus manual recommends converting to maildir for searching local mail, but importing lots of maildir messages to gnus
+;; takes 10+ minutes, so scratch that option. it suggests 2 alternate options
+;; mairix. for mbox, it doesn't integrate 100% with gnus, it copies the search results to a mbox
+;; and tells gnus to make a group of that mbox and display it. This means the read state won't be persistent, but otherwise
+;; works great.
+
+;; local imap server which will use the mbox and provide search.
+;; dovecot is modular, theres a dovecot-common which uses recommends to install i guess it's most used modules. Its
+;; description is completely not useful. Anyways, I'm not sure if there is any benefit to installing this over just the
+;; module we need.
+;; pi dovecot-imapd
+
+;; dovecot by default also makes a an inbox folder based on the normal local mail location /var/mail/
+;; those locations are adjustable and well documented via the var mail_location in
+;; /etc/dovecot/conf.d/10-mail.conf
+;; 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
+;; is. you could make the var be empty, which apparently has the same effect.
+
+;; Originally just linked the default location ~/.mail, but I changed to altering the config since ~/.mail since it seems
+;; other things like postfix use that location
+
+;; based on http://roland.entierement.nu/blog/2010/09/08/gnus-dovecot-offlineimap-search-a-howto.html
+;; other links that poped up contained outdated, innacurate information
+;; http://sachachua.com/blog/2008/05/geek-how-to-use-offlineimap-and-the-dovecot-mail-server-to-read-your-gmail-in-emacs-efficiently/
+;; http://www.emacswiki.org/emacs/JamesFerguson
+;; http://www.sanityinc.com/articles/read-mailing-lists-in-emacs-over-imap/
+
+;; Within emacs you can move messages between mbox and maildir etc, which is a nice flexibility.
+
+
+
+;; doc group for mbox:
+;; in gnus, do gnus-group-make-doc-group (G f in groups buffer) and point to the file
+
+;; info about groups created within gnus is stored in ~/.newsrc.eld
+;; also stored is a duplication of what email messages are read/unread,
+;; what newsgroups are subsribed to and read/unread,
+;; probably more stuff, everything that gnus saves.
+
+
+;; searching the body of the messages, i cut off after a few minutes.
+;; i can grep the file in just a couple seconds
+
+
+;; random side note
+;; we can also get mbox from gmane
+;; http://notmuchmail.org/howto/#index7h2
+
+
+;; gnus can't search mboxes except with its builtin search which is extremely slow. mairix can do mbox files from the command
+;; line, but not from within gnus, but from mairix.el, which can then open the results in gnus
+
+;; mbox can be converted to maildir easily, but gnus loads lots of maildir messages extremely slow. it parses all the
+;; headers and generates a nov file for each.
+
+;; nnfolder-generate-active-file
+
+;; to reset things, when changing mail group. I duno all the proper way, but it works to delete
+;; ~/Mail ~/.newsrc.eld ~/.newsrc-dribble
+
+
+;;;;; mail sources vs select methods background
+;; I found this very confusing when first reading through the manual. "mail sources" is a term that does not simply mean
+;; sources of mail, it is much narrower for gnus. sources of mail can be either "mail sources" or select methods. Mail
+;; sources will move mail to ~/Mail (not sure what format), and split it into groups according to variables. You can use
+;; "mail sources" for maildir / imap, but those can also be read via select methods, which do not move the mail from their
+;; location, but use them in their native format. This is what I want to do, and I can simply ignore mail
+;; sources. Confusing terminology is that "fetching mail" "scanning mail", lots of things mail doesn't mean all mail, it
+;; means specifically from "mail sources". The words "articles" and "news" is used in connection with select methods, aka my actual mail.
+
+
+
+;;;;; caching background
+
+;; caching:
+;; there is also ~/News/cache, filled with a bunch of articles, like 300 megs. can't figure out why.
+;; Grepped for caching in the manual, found 2 main things.
+;; cache is for 2 purposes. to cache locally, and to keep articles from expiring, called persistence
+;; gnus-use-cache, which puts things if they are
+;; gnus-cache-enter-articles
+;; things go in cache when they are marked certain ways by default, ticked and dormant
+;; and read articles are moved out of the cache
+;; still no idea why i have a bunch in the cache, but I set a var so that my mail won't get cached
+;; I'm gonna delete the cache, and check on it later see what exactly is going in there
+;; And of course, I moved ~/News to my encrypted drive and symlinked it
+
+
+
+;;; things that should be at the beginning
+
+;; from its README.md
+(eval-when-compile
+ (require 'use-package))
+(use-package use-package-ensure-system-package
+ :ensure t)
+
+;; Ubiquitous Packages. these could go anywhere actually
+
+;; find file at point
+(use-package ffap)
+
+
+
+
+(setq package-archives
+ (quote
+ (("gnu" . "https://elpa.gnu.org/packages/")
+ ("MELPA" . "https://melpa.org/packages/"))))
+
+;;(add-to-list 'package-archives
+;; '("marmalade" .
+;; "http://marmalade-repo.org/packages/"))
+
+;; down atm 2020-08-30
+;;(add-to-list 'package-archives '("org" . "http://orgmode.org/elpa/") t)
+
+
+;; keep our init.el clean, by moving customization elisp to it's own file
+(setq custom-file (concat user-emacs-directory "custom.el"))
+;; empty atm
+;;(load custom-file 'noerror)
+
+
+;;; auto-complete
+
+;; auto-completion in minibuffer
+;; disabled while I look for another alternative
+;;(icomplete-mode)
+
+(unless (string= (daemonp) "server")
+ (setq ac-use-comphist nil))
+(require 'auto-complete-config)
+(ac-config-default)
+
+
+;; complete after 1 char instead of default 2
+(setq ac-auto-start 1
+ ac-delay 0.001)
+
+(add-to-list 'ac-modes 'org-mode 'sql-mode)
+
+
+;; for org mode completion source taken from wiki.
+;; it did not work. no idea why. todo, investigate
+;; the ac-sources code is at http://www.emacswiki.org/emacs/AutoCompleteSources
+;; i've deleted it here so as to save space and not spam this file
+;;(defun my-ac-org-mode ()
+;; (setq ac-sources (append ac-sources '(ac-source-org))))
+
+
+;; this makes the org-self-insert command not do a flyspell spell check.
+;; low priority thing to look into sometime
+(ac-flyspell-workaround)
+
+
+(define-key ac-completing-map (kbd "") nil)
+(define-key ac-completing-map (kbd "") nil)
+(define-key ac-completing-map (kbd "") 'ac-expand)
+(define-key ac-completing-map "\t" 'ac-complete)
+;;(define-key ac-completing-map (kbd "") 'ac-complete)
+(define-key ac-completing-map (kbd "TAB") 'ac-complete)
+
+
+
+;;; auto-complete readline-complete
+
+(require 'readline-complete)
+;; not sure how I made these, but I deleted, and
+;; it would be nice to make them again sometime
+;;(require 'src-loaddefs)
+
+;; disabled cuz broken
+;; redefining function in readline-complete so ac-complete only uses readline as a source
+(defun ac-rlc-setup-sources ()
+ "Add me to shell-mode-hook!"
+ (setq ac-sources '(ac-source-shell)))
+(add-hook 'shell-mode-hook 'ac-rlc-setup-sources)
+
+;; generally unnecessary, but why not
+(setq explicit-shell-file-name "bash")
+
+;; readline-complete says to add this line.
+;; however, it up my procfs directory tracking hook
+;; because get-process doesn't notice the child shell.
+;; instead, I've removed export EMACS=t from
+;; comint-exec-1 (the function which initially sets it)
+;; by finding it in emacs sources and redefinind it here
+;; and done stty echo in my bashrc
+;;(setq explicit-bash-args '("-c" "export EMACS=; stty echo; bash"))
+
+(setenv "EMACS" "")
+(setq explicit-bash-args nil)
+(setq comint-process-echoes t)
+;; default of 30 is way too slow. todo, consider pushing this upstream
+(setq rlc-attempts 5)
+
+(add-to-list 'ac-modes 'shell-mode)
+
+;; readline-complete recommends this (i assume this format),
+;; but greping finds no reference in emacs or my .emacs.d
+;; so I'm assuming it is for an older emacs
+;;(setq explicit-ssh-args '("-t"))
+
+(add-hook 'shell-mode-hook
+ (lambda ()
+ ;;(define-key shell-mode-map (kbd "") 'auto-complete)
+ (define-key shell-mode-map (kbd "TAB") 'auto-complete)
+ ))
+
+
+;;; readline complete fix
+
+;; I need this function here, where INSIDE_EMACS is replaced with LC_INSIDE_EMACS.
+;; ian: last update 2017-1-7. update this periodically from upstream
+;; like when we do a major emacs update
+(defun comint-exec-1 (name buffer command switches)
+ (let ((process-environment
+ (nconc
+ ;; If using termcap, we specify `emacs' as the terminal type
+ ;; because that lets us specify a width.
+ ;; If using terminfo, we specify `dumb' because that is
+ ;; a defined terminal type. `emacs' is not a defined terminal type
+ ;; and there is no way for us to define it here.
+ ;; Some programs that use terminfo get very confused
+ ;; if TERM is not a valid terminal type.
+ ;; ;; There is similar code in compile.el.
+ (if (and (boundp 'system-uses-terminfo) system-uses-terminfo)
+ (list "TERM=dumb" "TERMCAP="
+ (format "COLUMNS=%d" (window-width)))
+ (list "TERM=emacs"
+ (format "TERMCAP=emacs:co#%d:tc=unknown:" (window-width))))
+ (list (format "LC_INSIDE_EMACS=%s,comint" emacs-version))
+ process-environment))
+ (default-directory
+ (if (file-accessible-directory-p default-directory)
+ default-directory
+ "/"))
+ proc decoding encoding changed)
+ (let ((exec-path (if (and command (file-name-directory command))
+ ;; If the command has slashes, make sure we
+ ;; first look relative to the current directory.
+ (cons default-directory exec-path) exec-path)))
+ (setq proc (apply 'start-file-process name buffer command switches)))
+ ;; Some file name handler cannot start a process, fe ange-ftp.
+ (unless (processp proc) (error "No process started"))
+ (let ((coding-systems (process-coding-system proc)))
+ (setq decoding (car coding-systems)
+ encoding (cdr coding-systems)))
+ ;; Even if start-file-process left the coding system for encoding data
+ ;; sent from the process undecided, we had better use the same one
+ ;; as what we use for decoding. But, we should suppress EOL
+ ;; conversion.
+ (if (and decoding (not encoding))
+ (setq encoding (coding-system-change-eol-conversion decoding 'unix)
+ changed t))
+ (if changed
+ (set-process-coding-system proc decoding encoding))
+ proc))
+
+;;; auto save
+
+;; todo: patch this so i can turn it off like my-as-off-local.
+;; then try it out and see if it can replace my autosave.
+;; Or maybe with the new auto-save-visited-mode.
+;; (use-package super-save
+;; :ensure t
+;; :config
+;; (setq super-save-exclude '("")
+;; super-save-triggers
+;; '(balance-windows
+;; next-buffer
+;; org-babel-execute-src-block
+;; other-window
+;; previous-buffer
+;; split-window-below
+;; split-window-horizontally
+;; start-process-shell-command
+;; switch-to-buffer
+;; windmove-down
+;; windmove-left
+;; windmove-right
+;; windmove-up)
+;; )
+;; (super-save-mode +1))
+
+
+
+(setq auto-save-timeout 1) ; idle time before auto-save.
+
+;; main hook for my auto save
+(add-hook 'auto-save-hook 'my-auto-save)
+;; additional hook to try to deal with emacs not auto-saving when a buffer isn't active
+(add-hook 'window-configuration-change-hook 'my-auto-save-win)
+
+;; this function from mu4e really does not like buffer saving
+(advice-add 'message-send-and-exit :before 'my-as-off)
+(advice-add 'message-send-and-exit :after 'my-as-on)
+
+;; avoid window config hook saving too much, it can
+;; get into loops in some random situations
+(defvar my-auto-save-last nil)
+(defvar my-as nil)
+(defvar my-auto-save-last nil)
+(defun my-auto-save-win ()
+ (unless (eq (current-buffer) my-auto-save-last)
+ (my-auto-save (current-buffer))))
+
+(defun my-auto-save (&optional last)
+ (when (and
+ my-as
+ (buffer-file-name)
+ ;; mu4e has a bug right now, undo breaks when saving drafts
+ (not (string= (buffer-file-name) "*draft*"))
+ (buffer-modified-p)
+ (not (and (boundp 'org-src-edit-buffer-p) (org-src-edit-buffer-p))))
+ ;; serial is incremented on each save, so let's do a bit less of them
+ (not (derived-mode-p 'dns-mode))
+ (setq my-auto-save-last last)
+ (let (message-log-max)
+ ;; a bit of a hack to partially suppress the constant saving in the echo area
+ (with-temp-message ""
+ (basic-save-buffer)))))
+
+;; in the message-send-and-exit advice, got an error because it passed an arg.
+;; didn't look into why, just add ignored args.
+(defun my-as-off (&rest ignore)
+ (interactive)
+ (setq my-as nil))
+
+(defun my-as-off-local (&rest ignore)
+ (interactive)
+ (setq-local my-as nil))
+
+(defun my-as-on (&rest ignore)
+ (interactive)
+ (setq my-as t))
+
+(defun my-as-on-local (&rest ignore)
+ (interactive)
+ (setq-local my-as t))
+
+;; based on suggestion in the emacs docs, redefine these 2 functions
+;; to avoid prompt spamming the user when we do auto-save
+(defun ask-user-about-supersession-threat (fn)
+ (discard-input)
+ (message
+ "File for %s has changed on disk outside of emacs. Auto-save is overwriting it, however
+a backup is being created in case that is not what you intended." buffer-file-name)
+ (setq buffer-backed-up nil))
+
+(defadvice ask-user-about-lock (before lock-deactivate-as activate)
+ (make-local-variable 'my-as)
+ (setq my-as nil)
+ (message "proper autosave has been turned off for this buffer because of lock file problem.
+ In this buffer, do M-x my-as-on to reenable"))
+
+;; todo, this doesn't work consistently to override the auto-save message
+(defalias 'do-auto-save-original (symbol-function 'do-auto-save))
+(defun do-auto-save (&optional no-message current-only)
+ "This function has been modified to wrap the original so that NO-MESSAGE
+is always set to t, since we auto-save a lot, it spams otherwise.
+The original doc string is as follows:
+
+Auto-save all buffers that need it.
+This is all buffers that have auto-saving enabled
+and are changed since last auto-saved.
+Auto-saving writes the buffer into a file
+so that your editing is not lost if the system crashes.
+This file is not the file you visited; that changes only when you save.
+Normally we run the normal hook `auto-save-hook' before saving.
+
+
+A non-nil NO-MESSAGE argument means do not print any message if successful.
+A non-nil CURRENT-ONLY argument means save only current buffer."
+ (interactive)
+ (do-auto-save-original t current-only))
+
+;; enable MY auto-save
+(my-as-on)
+
+;;; backups, separate from auto-save
+
+
+;; set backup file location
+(setq backup-directory-alist '(("." . "~/.editor-backups")))
+(setq auto-save-file-name-transforms
+ '((".*" "~/.editor-backups/" t)))
+
+(setq version-control t ;; Use version numbers for backups
+ kept-new-versions 100
+ kept-old-versions 2
+ delete-old-versions t ;; delete old versions silently
+ ;; assume hard linked files are done on purpose, don't screw them up
+ backup-by-copying-when-linked t)
+
+(defvar last-backup-time 0)
+;; todo, the time needs to be an integer, not a vector type thing
+(defun constant-backup ()
+ "Backup conditioned on some time passing since last one.
+ Hooked into 'before-save-hook."
+ (cl-flet ((b-time (minutes)
+ (< last-backup-time
+ ;; current-time is seconds, so convert minutes to seconds.
+ (- (current-time) (* 60 minutes)))))
+ (when (or (not (boundp 'last-backup-time)) (and (< (buffer-size) 10000000) (b-time 5)) (b-time 30))
+ (setq buffer-backed-up nil)
+ (setq-local last-backup-time (current-time)))))
+
+;; make a backup on auto-save, because the backup feature is not
+;; utilized with my-auto-save, only normal interactive save.
+;; todo, enable when fixed
+;;(add-hook 'before-save-hook 'constant-backup)
+
+(add-hook 'auto-save-hook 'auto-save-size-limit)
+
+(defun auto-save-size-limit ()
+ (when (and (not backup-inhibited) (> (buffer-size) 2000000))
+ (message "Backups disabled for this buffer due to size > 2 megs")
+ (make-local-variable 'backup-inhibited)
+ (setq backup-inhibited t)))
+
+
+;; ;; background:
+;; ;; the faq suggests to auto-save using
+;; (setq auto-save-visited-file-name t)
+;; and to toggle auto-saving in the current buffer, type `M-x auto-save-mode'
+
+;; however, this is buggy.
+;; it leaves around lock files, which can be disabled with
+;; (setq create-lockfiles nil)
+;; but it is also buggy on other things that appear to hook onto file saving
+;; so i created my own function, which originally had bugs,
+;; but new emacs version fixed all that, yay!.
+
+
+;; not using, but here for documentation,
+;; alternate way to enable and specify how long between autosaves.
+;; number of input events between autosave.
+;; lowest bound of functionality is actually about 15 input events
+;; (setq auto-save-interval ...)
+
+;;; color theme
+
+;; A Theme builder is available at http://elpa.gnu.org/themes/ along with
+;; a list of pre-built themes at http://elpa.gnu.org/themes/view.html and
+;; themes are available through ELPA.
+
+
+(defun override-theme (arg)
+ (interactive)
+ (while custom-enabled-themes
+ (disable-theme (car custom-enabled-themes)))
+ (load-theme arg t))
+
+;; not a real var? remove when I see this again
+;;(setq color-theme-is-global t)
+
+;; temporary, make night be default
+
+(defun toggle-night ()
+ (interactive)
+ (cond ((equal (car custom-enabled-themes) 'naquadah)
+ (override-theme 'ef-light))
+ (t
+ (override-theme 'naquadah))))
+
+(setq ef-themes-mixed-fonts t
+ ef-themes-variable-pitch-ui t)
+
+
+;; in the leuven theme file, i made this change. will need to remake it
+;; on package updates. I could fork, but its a pretty simple change
+;; < `(default ((,class (:foreground "#333333" :background "#FFFFFF"))))
+;; > `(default ((,class (:foreground "#333333" :background "#F6F6F0"))))
+;;
+;; < `(font-lock-comment-face ((,class (:slant italic :foreground "#8D8D84")))) ; #696969
+;; > `(font-lock-comment-face ((,class (:slant italic :foreground "#484848")))) ; #696969
+
+;;(override-theme 'leuven)
+
+;; based on ef-themes README.org
+(mapc #'disable-theme custom-enabled-themes)
+;; the default blue is too dark and messes with erc colors
+(setq ef-light-palette-overrides
+ '((bg-mode-line "#efefef")))
+(ef-themes-select 'ef-light)
+;;(load-theme 'ef-light)
+
+
+;; for learning about faces, see
+;; useful snippet
+;; (byte-recompile-file "/home/iank/.emacs.d/elpa/leuven-theme-20220203.947/leuven-theme.el" nil 0)
+
+;; disable color thing with this:
+;;(disable-theme (car custom-enabled-themes))
+
+;; decent dark themes
+
+;;(override-theme 'tangotango)
+;;(override-theme 'deeper-blue)
+;;(override-theme 'tango-dark)
+;;(override-theme 'tsdh-dark)
+
+;;(override-theme 'heroku)
+;;(override-theme 'inkpot) ;; part of inkpot-theme package
+;;(override-theme 'naquadah) ; org mode features, part of naquadah-theme package
+;;(override-theme 'spolsky) ;; part of sublime-themes package
+;;(override-theme 'twilight-anti-bright) ;; from twilight-anti-bright-theme package
+
+;; interesting but not usable colors
+;;(override-theme 'cyberpunk) ; cool org mode features, from cyberpunk-theme package
+;;(override-theme 'wombat) ; cursor not visible enough. from a wombat package, not sure which
+;;(override-theme 'misterioso) ; cursor not visible enough
+
+;;decent light themes
+;;(override-theme 'alect-light) ; theres a -alt version, don't see a dif. could use this without dimming. from alect-something package
+;;(override-theme 'occidental) ; from occidental-theme package
+
+
+;;color-theme is deprecated in emacs 24.
+
+;; theme packages i tried then removed:
+;; ignored ones that didn't use the new theme engine
+
+;;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)
+
+
+
+;;; cross session settings
+
+
+
+(use-package recentf
+ ;; defer & commands from jwiegley
+ :defer 10
+ :if (string= (daemonp) "server")
+ :commands (recentf-mode
+ recentf-add-file
+ recentf-apply-filename-handlers)
+ :config
+ (recentf-mode 1)
+ (setq recentf-max-saved-items 400
+ recentf-max-menu-items 15)
+ )
+
+(when (string= (daemonp) "server")
+ ;; save it every 5 minutes. https://www.emacswiki.org/emacs/RecentFiles
+ (run-at-time nil (* 5 60) 'recentf-save-list))
+
+;; less strong conditional: :unless noninteractive
+(use-package saveplace
+ :if (string= (daemonp) "server")
+ :config
+ (setq
+ save-place-version-control 'nospecial
+ save-place-limit 4000
+ save-place-file (concat user-emacs-directory "places"))
+ (save-place-mode 1))
+
+
+;; savehist keeps track of some history search entries
+(use-package savehist
+ :if (string= (daemonp) "server")
+ :config
+ (setq savehist-additional-variables '(kill-ring search-ring regexp-search-ring)
+ ;; save every minute
+ savehist-autosave-interval 60
+ ;; keep the home clean
+ savehist-file (concat user-emacs-directory ".savehist"))
+ (savehist-mode 1))
+
+;;; dired
+
+;; dired - reuse current buffer by pressing 'a'
+(put 'dired-find-alternate-file 'disabled nil)
+
+
+;; copied from dired-x info manual
+(with-eval-after-load 'dired
+ (require 'dired-x)
+ ;; use e instead for find file. i would like
+ ;; dired-do-async-shell-command, except it pops open some async
+ ;; shell buffer. i should figure out how to get rid of that.
+ (define-key dired-mode-map "f" 'dired-do-shell-command)
+ ;; Set dired-x global variables here. For example:
+ ;; (setq dired-guess-shell-gnutar "gtar")
+ ;; (setq dired-x-hands-off-my-keys nil)
+ )
+(add-hook 'dired-mode-hook
+ (lambda ()
+ ;; Set dired-x buffer-local variables here. For example:
+ ;; (dired-omit-mode 1)
+ ))
+
+;; the defaults are just some weird predefined list, like xpdf for pdf.
+(setq dired-guess-shell-alist-user
+ (list
+ (list ".*" "xdg-open")
+ ))
+
+
+;;; elisp settings
+;; when manually evaluating lisp, go into debugger on error
+(setq eval-expression-debug-on-error t)
+
+
+;;; isearch
+(setq
+ isearch-allow-scroll t
+ search-ring-update t) ;; dont start an edit when going to previous search
+
+(defun isearch-yank-regexp (regexp)
+ "Pull REGEXP into search regexp."
+ (let ((isearch-regexp nil)) ;; Dynamic binding of global.
+ (isearch-yank-string regexp))
+ (isearch-search-and-update))
+
+(defun isearch-yank-symbol (&optional partialp backward)
+ "Put symbol at current point into search string.
+
+ If PARTIALP is non-nil, find all partial matches."
+ (interactive "P")
+
+ (let (from to bound sym)
+ (setq sym
+ ; this block taken directly from find-tag-default
+ ; we couldn't use the function because we need the internal from and to values
+ (when (or (progn
+ ;; Look at text around `point'.
+ (save-excursion
+ (skip-syntax-backward "w_") (setq from (point)))
+ (save-excursion
+ (skip-syntax-forward "w_") (setq to (point)))
+ (> to from))
+ ;; Look between `line-beginning-position' and `point'.
+ (save-excursion
+ (and (setq bound (line-beginning-position))
+ (skip-syntax-backward "^w_" bound)
+ (> (setq to (point)) bound)
+ (skip-syntax-backward "w_")
+ (setq from (point))))
+ ;; Look between `point' and `line-end-position'.
+ (save-excursion
+ (and (setq bound (line-end-position))
+ (skip-syntax-forward "^w_" bound)
+ (< (setq from (point)) bound)
+ (skip-syntax-forward "w_")
+ (setq to (point)))))
+ (buffer-substring-no-properties from to)))
+ (cond ((null sym)
+ (message "No symbol at point"))
+ ((null backward)
+ (goto-char (1+ from)))
+ (t
+ (goto-char (1- to))))
+ (isearch-search)
+ (if partialp
+ (isearch-yank-string sym)
+ (isearch-yank-regexp
+ (concat "\\_<" (regexp-quote sym) "\\_>")))))
+
+(defun isearch-current-symbol (&optional partialp)
+ "Incremental search forward with symbol under point.
+
+ Prefixed with \\[universal-argument] will find all partial
+ matches."
+ (interactive "P")
+ (let ((start (point)))
+ (isearch-forward-regexp nil 1)
+ (isearch-yank-symbol partialp)))
+;; todo, make this
+
+(defun isearch-backward-current-symbol (&optional partialp)
+ "Incremental search backward with symbol under point.
+
+ Prefixed with \\[universal-argument] will find all partial
+ matches."
+ (interactive "P")
+ (let ((start (point)))
+ (isearch-backward-regexp nil 1)
+ (isearch-yank-symbol partialp)))
+
+
+;; automatically wrap to the top of the buffer when isearch fails
+(defadvice isearch-search (after isearch-no-fail activate)
+ (unless isearch-success
+ (ad-disable-advice 'isearch-search 'after 'isearch-no-fail)
+ (ad-activate 'isearch-search)
+ (isearch-repeat (if isearch-forward 'forward))
+ (ad-enable-advice 'isearch-search 'after 'isearch-no-fail)
+ (ad-activate 'isearch-search)))
+
+;; Activate occur easily inside isearch
+(define-key isearch-mode-map (kbd "C-o")
+ (lambda () (interactive)
+ (let ((case-fold-search isearch-case-fold-search))
+ (occur (if isearch-regexp
+ isearch-string
+ (regexp-quote isearch-string))))))
+;;; lisp / elisp mode setings
+
+(add-hook 'emacs-lisp-mode-hook 'starter-kit-remove-elc-on-save)
+(defun starter-kit-remove-elc-on-save ()
+ "If you're saving an elisp file, likely the .elc is no longer valid."
+ (make-local-variable 'after-save-hook)
+ (add-hook 'after-save-hook
+ (lambda ()
+ (if (file-exists-p (concat buffer-file-name "c"))
+ (delete-file (concat buffer-file-name "c"))))))
+
+
+(defun emacs-lisp-mode-defaults ()
+ ;; checkdoc has an annoying feature that wants a header and footer
+ ;; in every elisp buffer as if they all were packages
+ ;; todo, see if there is a way
+ ;; to make checkdoc usable instead of just disabling it as I do here
+ (if (boundp 'flycheck-checkers)
+ (setq flycheck-checkers (remove 'emacs-lisp-checkdoc flycheck-checkers)))
+ (eldoc-mode 1))
+(add-hook 'emacs-lisp-mode-hook 'emacs-lisp-mode-defaults)
+
+(define-key lisp-mode-map (kbd "") 'backward-up-list)
+(define-key lisp-mode-map (kbd "") 'down-list)
+(define-key emacs-lisp-mode-map (kbd "") 'backward-up-list)
+(define-key emacs-lisp-mode-map (kbd "") 'down-list)
+(define-key emacs-lisp-mode-map (kbd "") 'find-function-at-point)
+
+;; interactive modes don't need whitespace checks
+(defun interactive-lisp-coding-defaults ()
+ (whitespace-mode -1))
+
+;;; modes with little configuration needed
+
+
+
+(custom-set-variables
+ '(css-indent-offset 2)
+ '(sh-here-document-word "'EOF'")
+ '(outline-minor-mode-prefix "")
+ '(tramp-default-method "ssh")
+ ;; change last thing from gnu.
+ ;; notably this avoids brace indent after if, and 4 space indent
+ ;; for emacs itself, use
+ ;; (setq c-default-style '((java-mode . "java")
+ ;; (awk-mode . "awk")
+ ;; (other . "gnu")))
+ ;; (setq-default c-basic-offset 2)
+ '(c-default-style '((java-mode . "java")
+ (awk-mode . "awk")
+ (other . "stroustrup")))
+ )
+
+
+(setq
+ ;; ediff-buffers is the main command to use
+ ;; don't start another frame for the control panel
+ ;; unfortunately, this doesn't allow me to use 2 frames for the diff buffers
+ ;; so disable this temporarily with the next line if you want that
+ ;; sometime I should setup 2 functions to explicitly do each type
+ ediff-window-setup-function 'ediff-setup-windows-plain
+ ;;(setq ediff-window-setup-function 'ediff-setup-windows-default)
+ ;; do side by side diffs
+ ediff-split-window-function 'split-window-horizontally
+ ;; ediff things I tried which didn't work, which intuitively I think should
+ ;; work better: I can open the second diff buffer in a new frame, and
+ ;; close it's window in the first frame after starting ediff, but when I
+ ;; hit n to go to the next diff, it restores the window in the first
+ ;; frame. Another thing I tried is to open 2 new frames and set them up
+ ;; as I want. However, if I try to open the *Ediff Control Panel* buffer
+ ;; in a different window from its original one, my mouse jumps to one of
+ ;; the diff frames, or if that isn't visible, the buffer just hangs
+ ;; until I select the original ediff control panel window. This seems
+ ;; like a bug to me. I am using a very recent development version of
+ ;; emacs.
+
+ )
+
+;; disabled temporarily. todo, look into it
+;;(add-hook 'outline-minor-mode-hook 'outshine-mode)
+
+
+
+;; this file includes setting up my email addresses, which are not public,
+;; including
+;; mu4e-user-mail-address-list
+;; and a function
+;; inspired by mu4e info manual, search for mu4e-compose-pre-hook.
+(when (file-exists-p "/p/c/mymu4e.el")
+ (load "/p/c/mymu4e"))
+
+
+(when (file-exists-p "/a/h/iank-mod.el")
+ (load-file "/a/h/iank-mod.el"))
+
+;; from when i was running my own patches
+;;(add-to-list 'load-path "/a/opt/ws-butler")
+
+(require 'ws-butler)
+;; todo: I think this is broken, it keeps collapsing the last line
+;; for empty messages.
+
+;; the main problem is when it deletes the blank line at the end
+;; of a message with an empty body. but I might also
+;; be pasting whitespace significant things in here, so
+;; just don't do anything.
+;; todo: propose this upstream
+;; fundamental mode for files like .asc
+(add-to-list 'ws-butler-global-exempt-modes 'message-mode)
+(add-to-list 'ws-butler-global-exempt-modes 'dns-mode)
+(add-to-list 'ws-butler-global-exempt-modes 'fundamental-mode)
+
+(ws-butler-global-mode)
+
+;; disabled because i dont edit nginx files enough
+;; to have this loaded at startup
+;;(use-package nginx-mode)
+;;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:
+;;(add-to-list 'auto-mode-alist '("/etc/nginx/sites-available/.*" . nginx-mode))
+
+;; todo, put this on a hook with prog mode
+;;(highlight-indentation-mode 1)
+
+
+;; example of a syntax highlighted tail
+(use-package autorevert
+ :defer t
+ :config
+ (defvar prev-auto-revert-max)
+ (defun tail-colorize ()
+ (ansi-color-apply-on-region prev-auto-revert-max (point-max))
+ (setq-local prev-auto-revert-max (point-max)))
+ (add-hook 'auto-revert-tail-mode-hook
+ (lambda ()
+ (when (string=
+ buffer-file-name
+ "/var/log/cloudman/development/cm-service.log")
+ (setq-local prev-auto-revert-max 0)
+ ;; set buffer-local hook
+ (add-hook 'after-revert-hook 'tail-colorize nil t))))
+ )
+
+;; delete active selection with self-insert commands
+(delete-selection-mode t)
+
+;; Transparently open compressed files
+(auto-compression-mode t)
+
+;; dot mode, repeats last action
+(require 'dot-mode)
+(add-hook 'find-file-hook 'dot-mode-on)
+
+;; clean up obsolete buffers automatically at midnight
+(require 'midnight)
+
+;; saner regex syntax
+(require 're-builder)
+(setq reb-re-syntax 'string)
+
+
+;; show the name of the current function definition in the modeline
+(which-function-mode 1)
+
+;; enable winner-mode to manage window configurations
+(winner-mode +1)
+
+;; meaningful names for buffers with the same name
+(require 'uniquify)
+(setq uniquify-buffer-name-style 'forward
+ uniquify-separator "/"
+ ;; for sdx work. until I figure out a better way.
+ ;; maybe something like projectile can do it,
+ ;; or hacking around the status bar
+ uniquify-min-dir-content 2
+ uniquify-after-kill-buffer-p t ; rename after killing uniquified
+ uniquify-ignore-buffers-re "^\\*") ; don't muck with special buffers
+
+
+;; makefiles require tabs
+;; todo: find a makefile indent function that works,
+;; best I could find is this one which means don't indent at all
+;;
+(add-hook 'makefile-mode-hook
+ (lambda ()
+ (setq indent-tabs-mode t)
+ (setq indent-line-function (lambda () 'no-indent))))
+
+
+;; todo, turn on auto-fill just for txt files
+;;(add-hook 'text-mode-hook 'turn-on-auto-fill)
+
+;; random extra highlights
+(require 'volatile-highlights)
+(volatile-highlights-mode t)
+
+
+;; make help buffers smaller when it makes sense
+(temp-buffer-resize-mode 1)
+
+
+(defun my-info-init()
+ (require 'info+)
+ ;; based on suggestions in info+.el, I also installed misc-fns, strings, and thingatpt+
+ ;; remove some bad keybinds from info+
+ (define-key Info-mode-map [mouse-4] nil)
+ (define-key Info-mode-map [mouse-5] nil))
+
+(add-hook 'info-mode-hook 'my-info-init)
+
+
+;;; misc general settings
+
+
+;; I tried to look for a function that would set this that is
+;; not part of the emacs interactive customize stuff, but didn't see one
+;; in the faces documentation.
+
+(custom-set-faces
+ ;; custom-set-faces was added by Custom.
+ ;; If you edit it by hand, you could mess it up, so be careful.
+ ;; Your init file should contain only one such instance.
+ ;; If there is more than one, they won't work right.
+ '(header-line ((t (:background "default" :foreground "default" :overline nil :underline nil))))
+ '(region ((t nil))))
+
+
+;; from tramp manual, use the same ssh controlmaster. I was having problems with
+;; tramp prompting me for a username and pass.
+(customize-set-variable 'tramp-use-ssh-controlmaster-options nil)
+
+(setq
+ ;; avoid this stupid prompt when doing sudo-edit
+ ;; Save auth info to file ~/.authinfo? [y/n/N/e/?]
+ ;; which doesn't actually use the default N by pressing enter,
+ ;; and doesn't actually save the 'never' setting like it claims.
+ ;; todo: file a bug.
+ auth-source-save-behavior nil
+ auto-revert-interval 2
+ ;; fix eof end of file newline
+ mode-require-final-newline t
+ require-final-newline t
+ auto-revert-verbose nil
+ auto-revert-remote-files t
+ ;; save bookmarks whenever they are changed instead of just when emacs quits
+ bookmark-save-flag 1
+ ;; increase bookmark context size for better functionality
+ bookmark-search-size 2000
+ ;; https://www.emacswiki.org/emacs/FillParagraph
+ ;; make list items start paragraphs.
+ paragraph-start "\f\\|[ \t]*$\\|[ \t]*[-+*] "
+ sh-basic-offset 2
+ vc-follow-symlinks t
+ dired-confirm-shell-command nil
+ dired-deletion-confirmer '(lambda (x) t)
+ dired-listing-switches "-alh"
+ dired-recursive-deletes 'always
+ dired-clean-confirm-killing-deleted-buffers nil
+ undo-outer-limit 100000000 ; per undo command
+ undo-limit 500000000 ; undo history limit
+ undo-strong-limit 600000000 ; undo history limit plus some extra
+ )
+
+
+
+(ivy-mode 1)
+(add-hook 'text-mode-hook (lambda () (auto-fill-mode t)))
+(setq counsel-find-file-at-point t)
+
+(eval-after-load "ido"
+ ;; easier to read with just spaces as separator
+ (quote (setf (nth 2 ido-decorations) " ")))
+
+;; Seed the random-number generator
+(random t)
+
+;; easier to remember than keybinds
+(defalias 'scrypt 'mml-secure-message-encrypt-pgpmime)
+(defalias 'sign 'mml-secure-message-sign-pgpmime)
+;; otherwise we get error on sending:
+;; mml-secure-epg-sign: Couldnât find any signer names; try setting `mml-secure-smime-sign-with-sender'.
+;; i dunno why sign+encrypt doesnt cause this, seems kinda dumb,
+;;
+(setq mml-secure-openpgp-sign-with-sender t)
+;; i dun use smime, the smime signing fails complaining it doesnt have
+;; my key. todo: learn about smime
+(setq mml-secure-smime-sign-with-sender t)
+(defun encrypt ()
+ (interactive)
+ (mml-secure-message-encrypt-pgpmime 'dontsign))
+
+;; don't highlight the region.
+(set-face-background 'region nil)
+
+;; this fixes save error for python example code
+(define-coding-system-alias 'UTF-8 'utf-8)
+
+
+;;(prefer-coding-system 'utf-8-unix)
+
+;; remove ugly 3d box feature
+(set-face-attribute 'mode-line nil :box nil)
+
+(add-to-list 'default-frame-alist
+ '(font . "DejaVu Sans Mono-11"))
+ ; the default will jump 2 sizes.
+(setq text-scale-mode-step 1.1)
+(setq font-lock-maximum-decoration t
+ inhibit-startup-message t
+ transient-mark-mode t
+ shift-select-mode nil
+ truncate-partial-width-windows nil
+ uniquify-buffer-name-style 'forward
+ oddmuse-directory (concat user-emacs-directory "oddmuse")
+ echo-keystrokes 0.1
+ mark-ring-max 160
+ sort-fold-case t ; case insensitive line sorting
+ global-mark-ring-max 1000
+ ;; the visible bell seems to lag the ui
+ ;;visible-bell t
+ ;; turn off audible bell
+ ;; https://www.emacswiki.org/emacs/AlarmBell
+ ring-bell-function 'ignore
+ case-replace nil
+ revert-without-query '(".*")
+ font-lock-maximum-decoration t) ; probably default and not necesary
+
+
+(setq-default indent-tabs-mode nil ;; don't use tabs to indent
+ cursor-type 'box
+ fill-column 72
+
+ ;; wrap at word boundaries instead of mid-word
+ word-wrap t
+ imenu-auto-rescan t
+ indicate-empty-lines t) ; mark end of buffer
+
+
+(blink-cursor-mode 0)
+(menu-bar-mode -1)
+(tool-bar-mode -1)
+
+
+;; enable various commands
+(put 'narrow-to-region 'disabled nil)
+(put 'narrow-to-page 'disabled nil)
+(put 'narrow-to-defun 'disabled nil)
+(put 'upcase-region 'disabled nil)
+(put 'downcase-region 'disabled nil)
+(put 'scroll-left 'disabled nil)
+;; these from graphene, haven't read about them yet
+(put 'ido-complete 'disabled nil)
+(put 'ido-exit-minibuffer 'disabled nil)
+(put 'dired-find-alternate-file 'disabled nil)
+(put 'autopair-newline 'disabled nil)
+
+
+
+;;disable and minimize various prompts/messages
+(fset 'yes-or-no-p 'y-or-n-p)
+(setq confirm-nonexistent-file-or-buffer nil
+ inhibit-startup-message t
+ inhibit-startup-echo-area-message t
+ inhibit-startup-screen t
+ kill-buffer-query-functions (remq 'process-kill-buffer-query-function
+ kill-buffer-query-functions))
+
+
+;; exit without bothering me
+;; http://stackoverflow.com/questions/2706527/make-emacs-stop-asking-active-processes-exist-kill-them-and-exit-anyway/2708042#2708042
+(add-hook 'comint-exec-hook
+ (lambda () (set-process-query-on-exit-flag (get-buffer-process (current-buffer)) nil)))
+;; based on save-buffers-kill-emacs help string, don't ask about clients when exiting
+;; apparently this would need to be in some later hook. dunno where is best, but this works
+(defadvice save-buffers-kill-emacs (before no-client-prompt-advice activate)
+ (setq kill-emacs-query-functions (delq 'server-kill-emacs-query-function kill-emacs-query-functions)))
+
+
+
+;; (custom-set-faces
+;; ;; setting header-line-format to " " as a hack for a top margin the oly thning I could find to do a top margin
+;; '(header-line ((t (:background "default" :foreground "default" :overline nil :underline nil))))
+;; ;; don't highlight the region
+;; '(region ((t nil))))
+(setq-default header-line-format " ")
+
+
+(setq initial-scratch-message nil)
+
+
+;; vertical margin background.
+;; google turned up: http://lists.gnu.org/archive/html/help-gnu-emacs/2014-03/msg00544.html
+;; the xresource doesn't work for me, probably an xmonad thing.
+
+;; figured out I needed to customize the header line face. To find the face, M-x list-faces-display or just google / search
+;; info,
+;; then M-x customize-face
+;; header-line
+;; unchecked some stuff so that it inherits from default.
+
+;;; misc function definitions
+
+
+(defun fill-buffer ()
+ (interactive)
+ (save-mark-and-excursion
+ (goto-char (point-min))
+ (while (= (forward-line) 0)
+ (fill-paragraph))))
+
+
+(defun next-backup-dir ()
+ "In a directory listing from rsync -n,
+Go to the next directory based on where the cursor is."
+ (interactive)
+ (let* ((start-col (current-column))
+ (end-col (progn (skip-chars-forward "^/\n") (current-column)))
+ (dir (progn
+ (beginning-of-line 1)
+ (buffer-substring-no-properties (point) (+ (point) end-col)))))
+ (message dir)
+ (forward-line 1)
+ (while (and (not (eobp))
+ (string= dir (buffer-substring-no-properties (point) (+ (point) end-col))))
+ (forward-line 1))
+ (forward-char-same-line start-col)))
+;; copy paste this for fast keybind
+;;(local-set-key (kbd ""))
+
+
+(defun goto-buffer-or-find-file (file-name)
+ "If buffer is with FILE-NAME exists, go to it, else open the file using full path."
+ (interactive)
+ (let ((b (get-buffer (file-name-nondirectory file-name))))
+ (if b
+ (switch-to-buffer b)
+ (find-file file-name))))
+
+
+
+
+;; todo, i think this is broken. perhaps the last goto-char is not accounting for buffer or something
+(defun unpop-global-mark ()
+ "Unpop off global mark ring. Does nothing if mark ring is empty."
+ (interactive)
+ (when global-mark-ring
+ (setq global-mark-ring (cons (copy-marker (mark-marker)) global-mark-ring))
+ (let ((lm (car (last global-mark-ring))))
+ (set-marker (mark-marker) (marker-position lm) (marker-buffer lm)))
+ (when (null (mark t)) (ding))
+ (setq global-mark-ring (nbutlast global-mark-ring))
+ (goto-char (marker-position (mark-marker)))))
+
+(defun indent-buffer ()
+ "Indents the entire buffer."
+ (interactive)
+ (cond ((derived-mode-p 'org-mode)
+ (org-indent-region (point-min) (point-max)))
+ ((derived-mode-p 'python-mode)
+ (py-autopep8))
+ (t
+ (indent-region (point-min) (point-max)))))
+
+
+;; TODO doesn't work with uniquify
+(defun rename-file-and-buffer ()
+ "Renames current buffer and file it is visiting."
+ (interactive)
+ (let ((name (buffer-name))
+ (filename (buffer-file-name)))
+ (if (not (and filename (file-exists-p filename)))
+ (message "Buffer '%s' is not visiting a file!" name)
+ (let ((new-name (read-file-name "New name: " filename)))
+ (cond ((get-buffer new-name)
+ (message "A buffer named '%s' already exists!" new-name))
+ (t
+ (rename-file name new-name 1)
+ (rename-buffer new-name)
+ (set-visited-file-name new-name)
+ (set-buffer-modified-p nil)))))))
+
+
+
+(defun sudo-edit (&optional arg)
+ (interactive "P")
+ (if (or arg (not buffer-file-name))
+ (find-file (concat "/sudo::" (ido-read-file-name "File: ")))
+ (find-alternate-file (concat "/sudo::" buffer-file-name))))
+
+
+
+(defun backward-symbol (arg)
+ (interactive "p")
+ (forward-symbol (- arg)))
+
+;;; mode line
+;; make window title be the buffer name
+(setq
+ frame-title-format "e-iak %b"
+ icon-title-format "e-iak %b"
+ )
+
+(defun my-after-change-major-mode-hook ()
+ (setq mode-line-mule-info nil
+ minor-mode-alist nil
+ mode-line-position nil)) ; todo, make only flymake status show up
+
+(add-hook 'after-change-major-mode-hook 'my-after-change-major-mode-hook)
+
+;;; mouse related
+;;;; settings
+(setq focus-follows-mouse t
+ mouse-autoselect-window t
+ xterm-mouse-mode t)
+;;;; move-mouse-to-point
+;; todo, this is buggy with multiple windows open.
+(defun move-mouse-to-point ()
+ (interactive)
+ (let* ((pos (posn-col-row (posn-at-point)))
+ (x (+ (car pos) 2)) ; no idea why this is off by 1-2
+ (y (cdr pos)))
+ (set-mouse-position (selected-frame) x y)))
+
+;;; org mode
+
+
+
+;; todo, this doesn't work for a non-standard keybind
+;;(setq org-special-ctrl-k t)
+
+;; todo, generally fix org mode keys
+;; todo, org-mark-element, unbdind from M-h, bind to mark defun key
+
+ ;(org-babel-do-load-languages
+ ; 'org-babel-load-languages
+ ; '((emacs-lisp . t)
+ ; (sh . t)))
+
+
+
+;; make shell work like interactive bash shell
+(setq org-babel-default-header-args:sh
+ '((:results . "output") (:shebang . "#!/bin/bash -l")))
+
+;; my patch to output stderr
+(setq org-babel-use-error-buffer nil)
+
+ ;
+;; org-mode manual suggests these, but I haven't used them.
+;;(global-set-key "\C-cl" 'org-store-link)
+;;(global-set-key "\C-ca" 'org-agenda)
+;; this got in the way of a haskell mode command
+;;(global-set-key "\C-cb" 'org-iswitchb)
+
+
+
+;; org-src-tab-acts-natively t ; broken option. using next instead, todo fix
+
+(setq org-src-fontify-natively t ; make babel blocks nice
+ org-adapt-indentation nil
+ org-src-preserve-indentation t
+ ;; The most basic logging is to keep track of when a TODO item was finished.
+ org-log-done 'time
+ ;; use a drawer to keep the logs tidy
+ org-log-into-drawer t
+ org-extend-today-until 0
+ org-startup-truncated nil
+ org-clock-persist t
+ org-use-sub-superscripts "{}"
+ org-export-with-sub-superscripts nil
+ org-clock-mode-line-total 'today
+ ;; global STYLE property values for completion
+ org-global-properties (quote (("STYLE_ALL" . "habit")))
+ org-special-ctrl-a/e t ;; home and end work special in headlines
+ org-completion-use-ido t
+ ;; i had some problem with this in the past, but don't know what, so whatever.
+ org-cycle-emulate-tab nil
+ org-catch-invisible-edits 'smart)
+
+(setq
+ org-default-notes-file "/a/t.org"
+ org-directory "/p")
+
+;; modeilne populated from (org-clock-get-clocked-time)
+;; which is populated from the var org-clock-total-time
+;; which is populated by a function which starts from (org-clock-get-sum-start)
+;;
+
+(eval-after-load "org"
+ '(org-clock-persistence-insinuate))
+
+(defun time-to-org-day (time)
+ (round (time-to-number-of-days
+ (time-subtract time (list 0 (* 3600 org-extend-today-until) 0)))))
+
+(defun my-org-confirm-babel-evaluate (lang body)
+ (not (or (string= (buffer-file-name) "/a/t.org")
+ )))
+(setq org-confirm-babel-evaluate 'my-org-confirm-babel-evaluate)
+
+
+(defun org-time-stamp-with-time (arg)
+ (interactive "P")
+ ;; '(4) is the argument passed by universal prefix
+ (org-time-stamp (if arg arg '(4)) t))
+
+;; based on http://stackoverflow.com/questions/3758139/variable-pitch-for-org-mode-fixed-pitch-for-tables
+;; keywords: proportional font, monospace
+
+(defun variable-pitch-on ()
+ (variable-pitch-mode 1))
+(add-hook 'fundamental-mode-hook 'variable-pitch-on)
+(add-hook 'org-mode-hook 'variable-pitch-on)
+(add-hook 'text-mode-hook 'variable-pitch-on)
+(defun variable-pitch-off ()
+ (variable-pitch-mode 0))
+(add-hook 'yaml-mode-hook 'variable-pitch-off)
+(add-hook 'dns-mode-hook 'variable-pitch-off)
+
+
+(defun my-org-face-init()
+ (set-face-attribute 'org-table nil :family (face-attribute 'fixed-pitch :family))
+ (set-face-attribute 'org-code nil :family (face-attribute 'fixed-pitch :family))
+ (set-face-attribute 'org-formula nil :family (face-attribute 'fixed-pitch :family))
+ (set-face-attribute 'org-link nil :family (face-attribute 'fixed-pitch :family))
+ (set-face-attribute 'org-block nil :family (face-attribute 'fixed-pitch :family))
+ (set-face-attribute 'org-date nil :family (face-attribute 'fixed-pitch :family))
+ )
+
+(eval-after-load "org" '(my-org-face-init))
+
+(defun remove-org-binds ()
+ (define-key org-mode-map (kbd "") nil)
+ (define-key org-mode-map (kbd "C-'") nil)
+ (define-key org-mode-map (kbd "C-y") nil)
+ (define-key org-mode-map (kbd "") nil)
+ (define-key org-mode-map (kbd "") nil)
+ (define-key org-mode-map (kbd "C-,") nil)
+ (define-key org-mode-map (kbd "C-M-m") nil)
+ (define-key org-mode-map (kbd "C-k") nil)
+ (define-key org-mode-map (kbd "C-j") nil)
+ (define-key org-mode-map (kbd "C-M-i") nil)
+ (define-key org-mode-map (kbd "C-M-t") nil)
+ (define-key org-mode-map (kbd "M-a") 'nil)
+ (define-key org-mode-map (kbd "C-a") nil)
+ (define-key org-mode-map (kbd "M-e") nil)
+ (define-key org-mode-map (kbd "C-e") nil)
+ (define-key org-mode-map (kbd "C-3") nil)
+ (define-key org-mode-map (kbd "") nil)
+ (define-key org-mode-map (kbd "") nil)
+ (define-key org-mode-map (kbd "") nil)
+ (define-key org-mode-map (kbd "") nil)
+ (define-key org-mode-map (kbd "") nil)
+ (define-key org-mode-map (kbd "") nil)
+ (define-key org-mode-map (kbd "") nil)
+ (define-key org-mode-map (kbd "") nil)
+ (define-key org-mode-map "\t" nil))
+(add-hook 'org-mode-hook 'remove-org-binds)
+
+;;; prog-mode-defaults
+
+
+(defun prog-mode-defaults ()
+ "Default coding hook, useful with any programming language."
+ ;; so that I can do completion before the dialog pops up
+ ;;(local-set-key (kbd "") 'auto-complete)
+ (local-set-key (kbd "TAB") 'auto-complete)
+ (define-key emacs-lisp-mode-map (kbd "M-q") nil)
+
+ ;; todo, this is causing error message on loading file, prolly not working
+ ;;(flycheck-mode +1)
+ (setq ac-sources (delq 'ac-source-dictionary ac-sources))
+ (highlight-symbol-mode)
+ (make-local-variable 'column-number-mode)
+ ;; this says do autofilling using newcomment.el. The "only" is a misnomer.
+ (set (make-local-variable 'comment-auto-fill-only-comments) t)
+ (column-number-mode t)
+ ;; trying without
+ ;; (turn-on-smartparens-mode)
+
+ ;; prettify lambdas
+ (font-lock-add-keywords
+ nil `(("(\\(lambda\\>\\)"
+ (0 (progn (compose-region (match-beginning 1) (match-end 1)
+ ,(make-char 'greek-iso8859-7 107))
+ nil))))))
+(add-hook 'prog-mode-hook 'prog-mode-defaults)
+
+
+
+;;; yank auto-indent
+;; automatically indenting yanked text if in programming-modes
+(defvar yank-indent-modes
+ '(LaTeX-mode TeX-mode)
+ "Modes in which to indent regions that are yanked (or yank-popped).
+Only modes that don't derive from `prog-mode' should be listed here.")
+
+(defvar yank-indent-blacklisted-modes
+ '(python-mode slim-mode haml-mode)
+ "Modes for which auto-indenting is suppressed.")
+
+(defvar yank-advised-indent-threshold 2000
+ "Threshold (# chars) over which indentation does not automatically occur.")
+
+(defun yank-advised-indent-function (beg end)
+ "Do indentation, as long as the region isn't too large."
+ (if (<= (- end beg) yank-advised-indent-threshold)
+ (indent-region beg end nil)))
+
+(defadvice yank (after yank-indent activate)
+ "If current mode is one of 'yank-indent-modes,
+indent yanked text (with prefix arg don't indent)."
+ (if (and (not (ad-get-arg 0))
+ (not (member major-mode yank-indent-blacklisted-modes))
+ (or (derived-mode-p 'prog-mode)
+ (member major-mode yank-indent-modes)))
+ (let ((transient-mark-mode nil))
+ (yank-advised-indent-function (region-beginning) (region-end)))))
+
+(defadvice yank-pop (after yank-pop-indent activate)
+ "If current mode is one of 'yank-indent-modes,
+indent yanked text (with prefix arg don't indent)."
+ (if (and (not (ad-get-arg 0))
+ (not (member major-mode yank-indent-blacklisted-modes))
+ (or (derived-mode-p 'prog-mode)
+ (member major-mode yank-indent-modes)))
+ (let ((transient-mark-mode nil))
+ (yank-advised-indent-function (region-beginning) (region-end)))))
+
+
+;;; shell mode
+
+
+;; # eval: (outline-minor-mode)
+;; # outline-regexp: "\\( *\\)# [*]\\{1,8\\} "
+
+(defun outline-level ()
+ "Return the depth to which a statement is nested in the outline.
+Point must be at the beginning of a header line.
+This is actually either the level specified in `outline-heading-alist'
+or else the number of characters matched by `outline-regexp'."
+ (or (cdr (assoc (match-string 0) outline-heading-alist))
+ (let ((whitespace-end (match-end 1))
+ (match-begin (match-beginning 0)))
+ (if (= whitespace-end match-begin)
+ (- (match-end 0) match-begin)
+ (- (match-end 0) whitespace-end)
+ ))))
+;; originally:
+;;(or (cdr (assoc (match-string 0) outline-heading-alist))
+;; (- (match-end 0) (match-beginning 0))))
+
+
+
+;; avoid stupid git crap like "warning, terminal not fully functional"
+(setenv "PAGER" "cat")
+;; don't store successive duplicates in comint command history
+(setq comint-input-ignoredups t)
+
+(defun add-mode-line-dirtrack ()
+ (add-to-list 'mode-line-buffer-identification
+ '(:propertize (" " default-directory " ") face dired-directory)))
+(add-hook 'shell-mode-hook 'add-mode-line-dirtrack)
+
+
+;; don't fully understand it, but it works.
+;; http://www.emacswiki.org/emacs/ShellDirtrackByProcfs
+(defun track-shell-directory/procfs ()
+ (shell-dirtrack-mode 0)
+ (add-hook 'comint-preoutput-filter-functions
+ (lambda (str)
+ (prog1 str
+ (when (string-match comint-prompt-regexp str)
+ (cd (file-symlink-p
+ (format "/proc/%s/cwd" (process-id
+ (get-buffer-process
+ (current-buffer)))))))))
+ nil t))
+(setq comint-buffer-maximum-size 100000)
+(add-to-list 'comint-output-filter-functions 'comint-truncate-buffer)
+(defun new-shell ()
+ (interactive)
+ (shell (generate-new-buffer-name "*shell*")))
+;;
+(defun shell-wrap (prefix)
+ "wrap the shell function, automatically generate a new name for a prefix arg"
+ (interactive "P")
+ (if prefix
+ (new-shell)
+ (shell)))
+
+(add-hook 'shell-mode-hook 'track-shell-directory/procfs)
+;;; spell correction
+(setq
+ ispell-program-name "hunspell"
+ ispell-silently-savep t) ; don't prompt to save personal dictionary
+
+(use-package rw-hunspell
+ :defer t)
+;; rw-hunspell sets up hunspell dictionary automagically.
+
+(use-package flyspell
+ :ensure-system-package hunspell
+ :hook ((prog-mode . flyspell-prog-mode)
+ (text-mode . turn-on-flyspell)))
+
+;; Rant: Hunspell SHOULD be standard. its used by firefox and openoffice and
+;; osx. In contrast, the first few words I added to aspell dictionary were
+;; "emacs" "customizable" and "timestamp". Hunspell already has those,
+;; thank god.
+
+;; ispell-personal-dictionary does not document where the hunspell
+;; dictionary goes by default, but it is ~/.hunspell_en_US for me
+
+
+;;; tex
+
+(use-package latex-mode
+ :no-require t
+ :config
+ (setq-default TeX-PDF-mode t) ; use pdf
+ ;; more sensible defaults based on info manual quickstart
+ (setq TeX-auto-save t
+ TeX-parse-self t
+ ;; not documented, but looking at the source, I find this
+ ;; stops me from being asked what command on every C-c-c
+ ;; when doing a latex document.
+ TeX-command-force "LaTeX"
+ ))
+
+;;; visible mark mode
+
+;; since it is not easy to change the mark overlay priority, I change this one.
+(setq show-paren-priority 999)
+
+(defface visible-mark-active
+ '((((type tty) (class mono)))
+ (t (:background "magenta"))) "")
+
+(defface mouse-cursor-face
+ '((((type tty) (class mono)))
+ (t (:background "DeepPink1"))) "")
+
+
+(require 'visible-mark)
+
+(setq
+ visible-mark-faces '(visible-mark-face1 visible-mark-face2)
+ visible-mark-forward-faces '(visible-mark-forward-face1)
+ ;; highlight the last 2 marks
+ visible-mark-max 2
+ ;; highlight 1 forward mark
+ visible-mark-forward-max 1)
+;; globally activate visible-mark-mode
+(global-visible-mark-mode +1)
+
+
+;; todo, it doesn't seem to be exposed in elisp, but it would be nice
+;; if I could define overlay faces to use inverse foreground color
+
+
+;; (setq comment-start "
")
+ (setq comment-padding " ")
+ (setq fill-column 50)
+ ;; (setq fill-column 30)
+ (mark-paragraph)
+ ;; (call-interactively 'uncomment-region)
+ (fill-paragraph)
+ (call-interactively 'comment-region)
+ (deactivate-mark)
+ (save-excursion
+ (goto-char (region-beginning))
+ (next-line)
+ (comment-line 1)
+ )
+ )
+
+;; (chirp)
+(defun chirp()
+ (message "chirp nothing"))
+;;; znc/erc
+(defun chirp()
+ (interactive)
+ (setq vol 80)
+ (when (string= (system-name) "kd") (setq vol 60))
+ ;; speed is there so i can adjust and make it go slow so it plays long enough to adjust in pavucontrol
+ (start-process-shell-command "ignoreme" nil (format "mpv --speed=1 --no-terminal --vo=null --volume=%d /a/bin/data/d20.wav" vol)))
+;; from https://www.emacswiki.org/emacs/ErcSound
+(defun chirp-slow()
+ (interactive)
+ (setq vol 50)
+ (when (string= (system-name) "tp") (setq vol 80))
+ ;; speed is there so i can adjust and make it go slow so it plays long enough to adjust in pavucontrol
+ (start-process-shell-command "ignoreme" nil (format "mpv --speed=.2 --no-terminal --vo=null --volume=%d /a/bin/data/d20.wav" vol)))
+
+(defun erc-my-privmsg-sound (proc parsed)
+ (let* ((tgt (car (erc-response.command-args parsed)))
+ (privp (erc-current-nick-p tgt)))
+ (and
+ privp (chirp)
+ ;; We must return nil. See help for `erc-server-PRIVMSG-functions'
+ nil)))
+
+(defun erc-sound-if-not-server (match-type nickuserhost msg)
+ (unless (string-match "Server:[0-9]+" nickuserhost)
+ (chirp)))
+
+(defun erc-sound-if-not-server (match-type nickuserhost msg)
+ ;; (message "d1 %s" nickuserhost)
+ (unless (or (string-match-p "Server:[0-9]+" nickuserhost) (string-match-p "leah" nickuserhost))
+ (chirp)))
+
+(use-package erc
+ :defer t
+ :custom-face
+ (erc-current-nick-face ((t :weight bold :foreground "red")))
+ :init
+ (which-function-mode 0)
+ ;; fuck that default turquoise
+ (setq erc-fill-prefix ""
+ ;; consider invisible frames to be unseen. seems like an obvious default
+ erc-track-visibility 'visible
+ ;; switch to buffer where i've been mentioned, etc instead of oldest
+ erc-track-switch-direction 'importance
+ ;; when starting erc, open #fsfsys. otherwise it is super
+ ;; annoying to always have to manually switch buffers.
+ erc-join-hook (lambda () (when (string= (buffer-name(current-buffer)) "#fsfsys") (switch-to-buffer (current-buffer))))
+ ;; defaults minus fill. you can find defaults by searching for
+ ;; defcustom erc-modules in erc.el, or customize group erc.
+ erc-modules (remove 'fill erc-modules)
+ ;; expanded from https://www.emacswiki.org/emacs/ErcChannelTracking,
+ ;; ignore various messages
+ erc-track-exclude-types '("JOIN" "NICK" "PART" "QUIT" "MODE"
+ "324" "329" "332" "333" "353")
+ ;; seems good, i don't care about the server buffer generally
+ erc-track-exclude-server-buffer t
+ ;; dont highlight channels just cuz of new messages, except for pms or some new channel I haven't listed in my config.
+
+ erc-track-shorten-cutoff 40
+ ;; sed -rn 's/.*(#[^>]*).*/"\1"/p' /p/c/machine_specific/li/filesystem/var/lib/znc/configs/znc.conf
+ erc-track-priority-faces-only (list
+ "#conservancy"
+ "#fosdem"
+ "#fsf"
+ "#fsf-licensing"
+ "#fsfe"
+ "#fsfsys"
+ "#gnu"
+ "#librecmc"
+ "#libreplanet"
+ "#mnt-reform"
+ "#nouveau"
+ "#pump.io"
+ "#savannah"
+ "#seagl"
+ "#social"
+ "#spamassassin"
+ "#talos-workstation"
+ "#trisquel"
+ "#trisquel-dev"
+ "#overseers"
+ "#gdb"
+ "#gcc"
+ "#glibc"
+ "#binutils"
+ "#gnu-linux-libre"
+ "#parabola"
+ "#guix"
+ "#gnu-ops"
+ "#gcc"
+ )
+ ;; so that we don't show channels where i havent been mmentioned
+ erc-track-faces-priority-list '(erc-current-nick-face
+ erc-keyword-face
+ erc-pal-face
+ erc-nick-msg-face
+ erc-direct-msg-face
+ erc-fool-face)
+
+
+ ) ; end setq
+
+:config
+(add-hook 'erc-server-PRIVMSG-functions
+ 'erc-my-privmsg-sound)
+(add-hook 'erc-text-matched-hook 'erc-sound-if-not-server)
+(erc-track-mode 1)
+(defun erc-track--switch-buffer (fun arg)
+ (if (not erc-track-mode)
+ (message (concat "Enable the ERC track module if you want to use the"
+ " tracking minor mode"))
+ (cond (erc-modified-channels-alist
+ ;; if we're not in erc-mode, set this buffer to return to
+ (if-let ((buf (erc-track-get-active-buffer arg))
+ ((buffer-live-p buf)))
+ (funcall fun buf)
+ (erc-modified-channels-update)
+ (erc-track--switch-buffer fun arg)))
+ ;; if no active channels, switch back to what we were doing before
+ (t (switch-to-buffer "#fsfsys")))))
+)
+;;; named commands
+(defun rm-file-and-buffer ()
+ "Removes file connected to current buffer and kills buffer."
+ (interactive)
+ (let ((filename (buffer-file-name))
+ (buffer (current-buffer))
+ (name (buffer-name)))
+ (if (not (and filename (file-exists-p filename)))
+ (error "Buffer '%s' is not visiting a file!" name)
+ (delete-file filename)
+ (kill-buffer buffer)
+ (message "File '%s' successfully removed" filename))))
+
+;;; persistent registers
+;; This needs to be at the end, because I visit a file, thus setting a
+;; mode, and the mode hook needs to be setup before that.
+
+;; I'm using persistent registers instead of bookmarks. I dun use them
+;; much, so the added hassle of having to set it within this file is
+;; worth the benefit of only having one concept in my mind.
+(dolist
+ (r `(
+ (?i (file . ,(concat user-emacs-directory "init.el")))
+ (?o (file . ,"/b/w/work.org"))
+ (?t (file . ,"/a/t.org"))
+ (?s (file . ,"/usr/share/doc/exim4-base/spec.txt.gz"))
+ (?w (file . ,"/p/w.org"))
+ (?k (file . ,"/a/bin/ds/Arduino/Model01-Firmware/Model01-Firmware.ino"))
+ (?x (file . ,"/a/x.txt"))
+ ))
+ (set-register (car r) (cadr r)))
+
+(setq undo-outer-limit 100000000 ; per undo command
+ undo-limit 500000000 ; undo history limit
+ undo-strong-limit 600000000) ; undo history limit plus some extra
+
+
+;;; undo-fu mode
+
+;; thank god i'm done with undo-tree and the bug where my auto-saveing
+;; would cause it to lose all undo history, strangely especially in
+;; email buffers. it would claim the undo was outside the visible
+;; buffer.
+
+(use-package undo-fu
+ :config
+ (global-unset-key (kbd "C-z")))
+
+(use-package undo-fu-session
+ :if (string= (daemonp) "server")
+ :config
+ (setq undo-fu-session-incompatible-files '("/COMMIT_EDITMSG\\'" "/git-rebase-todo\\'")))
+
+(when (string= (daemonp) "server")
+ (unless (equal (user-uid) 0) ; don't make root owned files
+ (global-undo-fu-session-mode)
+ (when (file-exists-p "/p/c/undo-fu-session")
+ (setq undo-fu-session-directory "/p/c/undo-fu-session"))
+ ))
+
+
+;;; keybinds
+
+;;;; misc
+
+(define-prefix-command 'terminal-key-map)
+(global-set-key (kbd "\e[") 'terminal-key-map)
+
+(global-set-key (kbd "C-x C-b") 'ibuffer)
+
+
+;; isearch-occur
+;; Activate occur easily inside isearch
+;; from starter-kit
+
+(define-key isearch-mode-map (kbd "C-o")
+ (lambda () (interactive)
+ (let ((case-fold-search isearch-case-fold-search))
+ (occur (if isearch-regexp
+ isearch-string
+ (regexp-quote isearch-string))))))
+
+
+(defun my-isearch-toggle-regexp ()
+ (interactive)
+ (isearch-toggle-regexp)
+ (cond (isearch-regexp
+ (global-set-key (kbd "C-r") 'isearch-backward-regexp)
+ (define-key global-map (kbd "") 'isearch-forward-regexp))
+ (t
+ (global-set-key (kbd "C-r") 'isearch-backward)
+ (define-key global-map (kbd "") 'isearch-forward))))
+(define-key isearch-mode-map (kbd "M-r") 'my-isearch-toggle-regexp)
+
+
+(define-key Info-mode-map "x" 'Info-follow-nearest-node)
+
+
+;;;; single/special keys
+;;;;; tab - isearch
+;; todo: this doesnt work. needs , which doesnt work in terminal. fix that.
+(define-key isearch-mode-map (kbd "TAB") 'isearch-query-replace)
+
+;;;;; f12 - isearch-forward
+;; explained in http://stackoverflow.com/questions/7411920/how-to-bind-search-and-search-repeat-to-c-f-in-emacs
+(global-set-key (kbd "") 'isearch-forward)
+(global-set-key (kbd "") 'isearch-forward)
+(define-key isearch-mode-map (kbd "") 'isearch-repeat-forward)
+(define-key isearch-mode-map (kbd "") 'isearch-repeat-forward)
+;; get rid of the standard completion binding, always use auto-complete
+;; this didn't work very well
+;;(global-set-key (kbd "TAB") 'auto-complete)
+(define-key global-map [remap completion-at-point] 'auto-complete)
+
+;;;;; end - move-end-of-line
+;; taken from emacs wiki, along with home function
+;; http://www.emacswiki.org/emacs/BackToIndentationOrBeginning
+(defun point-in-comment ()
+ "Determine if the point is inside a comment"
+ (interactive)
+ (let ((syn (syntax-ppss)))
+ (and (nth 8 syn)
+ (not (nth 3 syn)))))
+(defun end-of-code-or-line (arg)
+ "Move to end of line, or before start of comments depending on situation.
+ Toggle back and forth positions if we are already at one.
+ Comments are recognized in any mode that sets syntax-ppss
+ properly."
+ (interactive "P")
+ (when (catch 'bol
+ (let ((start (point))
+ (bol (save-excursion
+ (beginning-of-line)
+ (point)))
+ (eol (progn (move-end-of-line arg) (point))))
+ (while (point-in-comment)
+ (backward-char)
+ (when (= (point) bol)
+ (throw 'bol t)))
+ (throw 'bol (and (not (= eol start)) (>= start (point))))))
+ (move-end-of-line arg)))
+
+(global-set-key (kbd "") 'end-of-code-or-line)(add-hook 'org-mode-hook (lambda () (define-key org-mode-map (kbd "") 'org-end-of-line)))
+
+;;;;; home - back-to-indentation
+(defun back-to-indentation-or-beginning ()
+ (interactive)
+ (if (= (point) (progn (back-to-indentation) (point)))
+ (if (derived-mode-p 'org-mode)
+ (org-beginning-of-line)
+ (beginning-of-line))))
+(global-set-key (kbd "") 'back-to-indentation-or-beginning)
+
+;;;;; s-tab - indent-buffer
+;; This is translated from S- in graphicsal mode. previously, I had
+;; also set (kbd ""),
+;; But I stopped because it overrides minor mode mappings, and i don't want to do that, at least not only in graphical mode.
+;;
+(global-set-key (kbd "") 'indent-buffer)
+
+(add-hook 'org-mode-hook
+ (lambda ()
+ (define-key org-mode-map (kbd "") nil)))
+
+;;;;; s-delete - send-shell
+
+(global-set-key (kbd "") 'send-shell)
+
+;; optional variables used by send-shell
+(setq shell-send-yank-key nil)
+
+(defun repeat-shell ()
+ (interactive)
+ "Repeat the last command in shell-mode, displaying the window if needed."
+ (let ((shell-buffer (get-buffer "*shell*")))
+ (if shell-buffer
+ (buffer-window-show shell-buffer)
+ (let ((original-buffer (current-buffer)))
+ (funcall 'shell)
+ (setq shell-buffer (current-buffer))
+ (switch-to-buffer original-buffer)))
+ (with-current-buffer shell-buffer
+ (goto-char (point-max))
+ (call-interactively 'comint-previous-input)
+ ;; the t flag makes the buffer advance
+ (comint-send-input nil t))))
+
+(setq compilation-filenames '("Makefile" "makefile"))
+
+(defun get-nearest-compilation-file ()
+ "Search for the compilation file traversing up the directory tree."
+ (interactive)
+ (let ((dir default-directory)
+ (parent-dir (file-name-directory (directory-file-name default-directory)))
+ (nearest-compilation-file 'nil))
+ (while (and (not (string= dir parent-dir))
+ (not nearest-compilation-file))
+ (dolist (filename compilation-filenames)
+ (setq file-path (concat dir filename))
+ (when (file-readable-p file-path)
+ (setq nearest-compilation-file file-path)))
+ (setq dir parent-dir
+ parent-dir (file-name-directory (directory-file-name parent-dir))))
+ nearest-compilation-file))
+(defun run ()
+ (interactive)
+ "call run-fun if it is set, else run make if there is a makefile,
+else save and repeat last shell command.
+run-fun is meant to store file local variables, which show how to
+do the main thing we want on this file, generally compile and
+run.
+
+example of setting it in a file:
+;; Local Variables:
+;; run-fun: merge-test
+;; End: "
+ (basic-save-buffer)
+ (if (and (boundp 'run-fun) run-fun)
+ (funcall run-fun)
+ (let ((makefile (get-nearest-compilation-file)))
+ (if (and makefile (stringp mode-name) (string= mode-name "C/l"))
+ (compile (format
+ "make -f %s" (get-nearest-compilation-file)))
+ (repeat-shell)))))
+
+
+(defun send-shell ()
+ (interactive)
+ (send-shell-buffer "*shell*" 'shell (kbd "C-v")))
+
+(defun send-python ()
+ (interactive)
+ (send-shell-buffer "*Python*" 'py-shell (kbd "C-v")))
+
+
+(defun send-shell-buffer (buffer-name &optional init shell-send-yank-key)
+ "Send current line or region to shell-mode buffer.
+When in shell-mode, copy the current line to the
+most recently visited visible window.
+
+SHELL-SEND-YANK-KEY: key to use instead
+of yank to paste into recent window. This allows compatibility with
+modes like org-mode which have their own yank function."
+ (if (string= (buffer-name) buffer-name)
+ ;; this section is copied out of comint-send-input
+ (progn
+ (let ((proc (get-buffer-process (current-buffer))))
+ (if (not proc) (user-error "Current buffer has no process")
+ (widen)
+
+ (let* ((pmark (process-mark proc))
+ (intxt (if (>= (point) (marker-position pmark))
+ (progn (if comint-eol-on-send (end-of-line))
+ (buffer-substring pmark (point)))
+ (let ((copy (funcall comint-get-old-input)))
+ (goto-char pmark)
+ (insert copy)
+ copy))))
+
+ (if (= (length intxt) 0)
+ (kill-new (comint-previous-matching-input-string "." 1))
+ (kill-new intxt)))))
+ (kill-append "\n" nil)
+ (select-window (previous-window nil nil 'visible))
+ (if (and (boundp 'shell-send-yank-key) shell-send-yank-key)
+ (call-interactively (global-key-binding shell-send-yank-key))
+ (yank))
+ (select-window (next-window nil nil 'visible)))
+ (let (start end)
+ (if mark-active
+ (setq start (mark)
+ end (point))
+ (setq start (save-excursion (beginning-of-line) (point))
+ end (save-excursion (end-of-line) (point)))
+ (let (line-move-visual)
+ (call-interactively 'next-line)))
+ (send-comint-input buffer-name start end init))))
+
+;; supporting functions
+(defun send-comint-input (buffer-name start end &optional init)
+ "Input the region to BUFFER-NAME, assuming it is a comint-derived buffer.
+ Show BUFFER-NAME if it is not show.
+ Call INIT if BUFFER-NAME does not exist."
+ (let ((input (filter-buffer-substring start end)))
+ (send-comint-string buffer-name input init)))
+
+(defun send-comint-string (buffer-name string &optional init)
+ "Input the string to BUFFER-NAME, assuming it is a comint-derived buffer.
+ Show BUFFER-NAME if it is not show.
+ Call INIT if BUFFER-NAME does not exist."
+ (let ((buffer (get-buffer buffer-name)))
+ (unless buffer
+ (message "nobuffer")
+ ;; save-excursion etc. don't work for (shell), so I do this instead
+ (if init (let ((original-buffer (current-buffer)))
+ (funcall init (and (boundp 'send-shell-buffer-name) send-shell-buffer-name))
+ (switch-to-buffer original-buffer)
+ (setq buffer (get-buffer buffer-name)))
+ (error "No existing buffer found and no init function argument. ")))
+ (buffer-window-show buffer)
+ (with-current-buffer buffer
+ (let ((proc (get-buffer-process buffer)))
+ (goto-char (process-mark proc))
+ (insert string)
+ (comint-send-input nil t)))))
+
+(defun buffer-window-show (&optional buffer action)
+ "Like temp-buffer-window-show, but removed stuff
+ relevant to it being temp or help."
+ (let (window frame)
+ (with-current-buffer buffer
+ (when (let ((window-combination-limit
+ ;; When `window-combination-limit' equals
+ ;; `temp-buffer' or `temp-buffer-resize' and
+ ;; `temp-buffer-resize-mode' is enabled in this
+ ;; buffer bind it to t so resizing steals space
+ ;; preferably from the window that was split.
+ (if (or (eq window-combination-limit 'temp-buffer)
+ (and (eq window-combination-limit
+ 'temp-buffer-resize)
+ temp-buffer-resize-mode))
+ t
+ window-combination-limit)))
+ ;; debug
+ ;;(message "window-combination-limit")
+ ;;(print window-combination-limit)
+ (setq window (display-buffer buffer action)))
+ (setq frame (window-frame window))
+ (unless (eq frame (selected-frame))
+ (raise-frame frame))
+ (setq minibuffer-scroll-window window)
+ (set-window-hscroll window 0)
+ ;; Return the window.
+ window))))
+
+
+;; when poping help, etc, allow reusing a window in a different frame if it is visible
+;; figured this out after spending quite a while reading doc string for display-buffer
+;; which is the main function which uses this.
+;; it will use other vars or its arg to override this,
+;; but those things are often nil.
+;; aha moments in reading it: ACTION = (FUNCTION-or-FUNCTIONLIST ALIST)
+;; FRAME adds an association to ACTION's alist, but it's not used if ACTION arg is nil.
+(setq display-buffer-fallback-action `(,(car display-buffer-fallback-action) . '(reusable-frames . visible)))
+;; stop splitting windows verticallly when I open a buffer or shell
+(setq split-height-threshold nil)
+
+;;;;; s-left arrow - ---
+;; cant be used in terminal
+;; When I had a binding, i did this so org-mode wouldnt clobber it
+;; (add-hook 'org-mode-hook
+;; (lambda ()
+;; (define-key org-mode-map (kbd "") nil)))
+
+;;;;; s-right arrow - keyboard-yank-primary
+(defun keyboard-yank-primary ()
+ (interactive)
+ (let ((mouse-yank-at-point t))
+ (mouse-yank-primary nil)))
+;; paste selection
+(global-set-key (kbd "") 'keyboard-yank-primary)
+(add-hook 'org-mode-hook
+ (lambda ()
+ (define-key org-mode-map (kbd "") nil)))
+;;;;; esc --- terminal dup
+;; todo, test out if this can be used
+;;;;; return - new line
+
+;; todo, this doesn't set the keybind for the help minibuffer
+
+
+(global-set-key (kbd "\r") 'indent-new-comment-line)
+
+;; don't use enter for autocomplete, we use tab or something
+(define-key ac-completing-map (kbd "") nil)
+(define-key ac-completing-map "\r" nil)
+
+(add-hook 'org-mode-hook
+ (lambda ()
+ ;; copied from org-mode, replace org-enter with org-enter-indent
+ (org-defkey org-mode-map "\C-m" 'org-return-indent)))
+
+
+(add-hook 'comint-mode-hook
+ (lambda ()
+ (define-key comint-mode-map "\r" nil)
+ (define-key comint-mode-map (kbd "RET") 'comint-send-input)))
+
+(add-hook 'comint-mode-hook
+ (lambda ()
+ (define-key comint-mode-map "\C-m" nil)
+ (define-key comint-mode-map "\C-d" nil)))
+
+;;;;; s-return - auto-correct-prev-word
+(global-set-key (kbd "") 'flyspell-auto-correct-previous-word)
+;; kp-enter is shift return in terminal
+(global-set-key (kbd "") 'flyspell-auto-correct-previous-word)
+
+;;;;; s-up arrow - my-contract-region
+(global-set-key (kbd "") 'my-contract-region)
+;;;;; c-up/down move 8 lines
+
+;; compiling warns that next-line should be called interactively,
+;; but we would have to do something dumb, like give it a
+;; vector of keys in order to supply the 8 argument
+(defun down-fast ()
+ (interactive)
+ (next-line 8))
+(defun up-fast ()
+ (interactive)
+ (next-line -8))
+
+(global-set-key (kbd "") 'up-fast)
+(global-set-key (kbd "") 'down-fast)
+
+;;;;; c-scroll comint prev/next prompt
+
+(add-hook 'comint-mode-hook
+ (lambda ()
+ (define-key comint-mode-map (kbd "") 'comint-previous-prompt)
+ (define-key comint-mode-map (kbd "") 'comint-next-prompt)))
+;;;;; m-scroll prev/next sexp
+(global-set-key (kbd "") 'backward-sexp)
+(global-set-key (kbd "") 'forward-sexp)
+;;;;; S-scroll expand/contract region
+(global-set-key (kbd "") 'my-contract-region)
+(global-set-key (kbd "") 'er/expand-region)
+(global-set-key (kbd "") 'my-contract-region)
+(global-set-key (kbd "") 'er/expand-region)
+
+(defun my-contract-region (arg)
+ (interactive "p")
+ (let ((current-prefix-arg '-))
+ (call-interactively 'er/expand-region)))
+
+;; todo: define c-m scroll. i manually set to normal scrolling, i dunno why
+
+
+;;;;; c-s-scroll scale text
+
+(global-set-key (kbd "") 'text-scale-increase)
+(global-set-key (kbd "") 'text-scale-decrease)
+(global-set-key (kbd "") 'text-scale-increase)
+(global-set-key (kbd "") 'text-scale-decrease)
+(global-set-key (kbd "") 'text-scale-increase)
+(global-set-key (kbd "") 'text-scale-decrease)
+
+
+;;;;; s-up arrow er/expand-region
+(global-set-key (kbd "") 'er/expand-region)
+;;;;; c-left/right move symbol
+
+(global-set-key (kbd "") 'backward-symbol)
+(global-set-key (kbd "") 'forward-symbol)
+
+;;;; left primary
+
+;;;;; M-2 shell-cd-to-file
+
+
+(defun shell-cd-to-file ()
+ (interactive)
+ (let ((file (buffer-file-name)))
+ (if file
+ (send-comint-string "*shell*"
+ (concat "c " (file-name-directory file))
+ 'shell)
+ (message "%s" "shell-cd-to-file: buffer has no file name"))))
+(global-set-key (kbd "M-2") 'shell-cd-to-file)
+
+;;;;; C-M-2 copy-symbol
+(global-unset-key (kbd "C-M-2"))
+(defun copy-symbol (&optional arg)
+ "Copy symbol at point into kill-ring"
+ (interactive "P")
+ (kill-new (thing-at-point 'symbol)))
+
+(global-set-key (kbd "C-M-2") 'copy-symbol)
+
+;;;;; M-3 dot-mode-execute
+
+(global-set-key (kbd "M-3") 'dot-mode-execute)
+
+;;;;; C-M-3 recenter-top-bottom
+
+(global-set-key (kbd "C-M-3") 'recenter-top-bottom)
+
+;;;;; C-q org/bicycle-cycle, comint previous arg
+
+(global-set-key (kbd "C-q") 'bicycle-cycle)
+(add-hook 'org-mode-hook
+ (lambda () (define-key org-mode-map (kbd "C-q") 'org-cycle)))
+(define-key widget-keymap (kbd "C-q") 'widget-forward)
+(add-hook 'comint-mode-hook
+ (lambda () (define-key comint-mode-map (kbd "C-q") 'comint-insert-previous-argument)))
+
+;;;;; M-q org/bicycle-cycle global
+
+(add-hook 'org-mode-hook
+ (lambda ()
+ (define-key org-mode-map (kbd "M-q") 'org-shifttab)))
+(global-set-key (kbd "M-q") 'bicycle-cycle-global)
+
+;;;;; C-M-q quoted-insert
+
+(global-set-key (kbd "C-M-q") 'quoted-insert)
+
+;;;;; C-w counsel-find-file
+
+(global-set-key (kbd "C-w") 'counsel-find-file)
+
+;;;;; M-w shell
+
+(global-set-key (kbd "M-w") 'shell-wrap)
+
+;;;;; C-e copy-line
+
+;; todo, make repeated calls to this append the kills
+(defun copy-line (&optional arg)
+ "Copy lines (as many as prefix argument) in the kill ring.
+ Ease of use features:
+ - Move to start of next line.
+ - Appends the copy on sequential calls.
+ - Use newline as last char even on the last line of the buffer.
+ - If region is active, copy its lines."
+ (interactive "p")
+ (let ((beg (line-beginning-position))
+ (end (line-end-position (or arg 1))))
+ (when mark-active
+ (if (> (point) (mark))
+ (setq beg (save-excursion (goto-char (mark)) (line-beginning-position)))
+ (setq end (save-excursion (goto-char (mark)) (line-end-position)))))
+ (if (eq last-command 'copy-line)
+ (kill-append (buffer-substring beg end) (< end beg))
+ (kill-ring-save beg end)))
+ (kill-append "\n" nil)
+ ;; dun need cuz I have yank-better
+ ;;(beginning-of-line (or (and arg (1+ arg)) 2))
+ (if (and arg (not (= 1 arg))) (message "%d lines copied" arg)))
+
+(global-set-key (kbd "C-e") 'copy-line)
+
+;;;;; M-e ?? unused
+
+;;;;; C-r isearch-backward
+
+(global-set-key (kbd "C-r") 'isearch-backward)
+(add-hook 'comint-mode-hook
+ (lambda ()
+ (define-key comint-mode-map (kbd "C-r") 'comint-history-isearch-backward-regexp)))
+
+;;;;; M-r ?? unused
+
+
+;;;;; C-a copy buffer
+
+(defun copy-all ()
+ "Copy entire buffer to clipboard"
+ (interactive)
+ (clipboard-kill-ring-save (point-min) (point-max)))
+(global-set-key (kbd "C-a") 'copy-all)
+
+;;;;; C-s - c-x prefix
+;; prefix key binds.
+;; good info http://www.masteringemacs.org/articles/2011/02/08/mastering-key-bindings-emacs/
+;; rebinding the prefix keys are tricky. apparently, some modes ignore any redefinition of a prefix key and use it explicitly,
+;; so you have to dig into their key maps and redo things.
+;; There are 2 simpler alternatives which have their own downsides.
+;; One is cua mode, which I do not like because it smashes 2 keybinds onto 1 and limits what you can do.
+;; The other is keyboard-translate, which translates the key presses before anything else.
+;; The downside is that it translates them when you aren't using them as a prefix.
+;; Since the swaps I'm using are all very accessible, the only downside is some mental jugling when reading docs etc about these keybinds.
+
+;; I've seen this as an another suggestion, it was a total fail. The prefix command took over both keys.
+;; (define-key key-translation-map [f12] "\C-c")
+;; (define-key key-translation-map "\C-c" [left])
+
+
+;;idea to remove the hook later since it is only needed at startup.
+;; did not work however, and there is not a real need to fix it, so I did not investigate
+;;(defun removeSwapHook ()
+;; (remove-hook 'buffer-list-update-hook 'myKeySwap)
+;; (remove-hook 'change-major-mode-hook 'removeSwapHook))
+;;(add-hook 'change-major-mode-hook 'removeSwapHook)
+
+
+;; went through almost all the relevant standard hooks,
+;; this overcomes a known bug that (keyboard-translate) does not get applied when running emacs daemon
+(add-hook 'buffer-list-update-hook (lambda () (interactive)
+ (keyboard-translate ?\C-x ?\C-s)
+ (keyboard-translate ?\C-s ?\C-x)
+ (keyboard-translate ?\C-c ?\C-d)
+ (keyboard-translate ?\C-d ?\C-c)))
+
+
+
+;; these all don't work
+;; don't know why this doesn't error but reversing the keys does
+;;(keyboard-translate ?\t ?\M-\t)
+;;(keyboard-translate [M-tab] [tab])
+;; from what i can tell, it wants to use a keyboard-translate-table,
+;; which is a char table, which is a vector indexed by chars,
+;; and mod+tab is not a char (it has too many bits), it is an integer
+;; it actually says it can hold vectors or strings, but that it is obsolete to do so
+;;(characterp ?\M-a)
+;;(characterp ?\C-a)
+
+;;;;; C-M-s - split-window-vertically
+
+(global-set-key (kbd "C-M-s") 'split-window-vertically)
+
+;;;;; C-d - C-c prefix
+
+;;;;; M-d - run
+
+(global-set-key (kbd "M-d") 'run)
+
+;;;;; C-M-d - split-window-horizontally
+
+(global-set-key (kbd "C-M-d") 'split-window-horizontally)
+
+
+;;;;; C-f - kill-whole-line
+
+(global-set-key (kbd "C-f") 'kill-whole-line-wrapper)
+(defun kill-whole-line-wrapper (&optional arg)
+ "If we are at the end of the file, kill backwards instead of doing nothing."
+ (interactive "P")
+ (if (= (point) (point-max))
+ (kill-whole-line -1)
+ (kill-whole-line arg)))
+
+;;;;; M-f - print-var-at-point
+
+(defun print-var-at-point ()
+ (interactive)
+ (let ((v (variable-at-point)))
+ (if (symbolp v)
+ (message "%s: %s" v (symbol-value v))
+ (message "no symbol found at point"))))
+(global-set-key (kbd "M-f") 'print-var-at-point)
+
+
+;;;;; C-M-f - kill rest of line
+
+
+(add-hook 'org-mode-hook
+ (lambda ()
+ (define-key org-mode-map (kbd "C-M-f") 'org-kill-line)))
+
+(global-set-key (kbd "C-M-f") 'kill-line)
+;;;;; C-g - keyboard-quit
+;;;;; M-g - abort-recursive-edit
+
+(global-set-key (kbd "M-g") 'abort-recursive-edit)
+
+;;;;; C-M-g - mu4e
+
+(global-set-key (kbd "C-M-g") 'mu4e)
+
+;;;;; C-z - undo-only
+;;(global-set-key (kbd "C-z") 'undo-tree-undo)
+(global-set-key (kbd "C-z") 'undo-fu-only-undo)
+;;;;; C-M-z - suspend-frame
+(global-set-key (kbd "C-M-z") 'suspend-frame)
+;; this is never good in a gui
+(when (window-system)
+ (defun suspend-frame() (interactive)))
+
+;;;;; C-x - kill-region
+
+(global-set-key (kbd "C-s") 'kill-region)
+
+;;;;; M-x - counsel-m-x
+
+
+;; todo; check out smex-show-unbound-commands shows frequently used commands that have no key bindings.
+;; this must be before smex-initialize
+(setq
+ smex-save-file (concat user-emacs-directory ".smex-items"))
+
+;; this uses smex
+(global-set-key (kbd "M-x") 'counsel-M-x)
+
+;;;;; C-M-x - cut-to-register
+
+;; same args as copy-to-register
+(defun cut-to-register (register start end &optional delete-flag region)
+ (interactive (list (register-read-with-preview "Cut to register: ")
+ (region-beginning)
+ (region-end)
+ current-prefix-arg
+ t))
+ (copy-to-register register start end t region))
+
+(global-set-key (kbd "C-M-x") 'cut-to-register)
+
+;;;;; C-c - copy
+
+(global-set-key (kbd "C-d") 'kill-ring-save)
+(add-hook 'c-mode-common-hook
+ (lambda ()
+ (define-key c-mode-map (kbd "C-d") nil)
+ (define-key c++-mode-map (kbd "C-d") nil)))
+(add-hook 'comint-mode-hook
+ (lambda ()
+ (define-key comint-mode-map (kbd "C-d") nil)))
+;; the base map is shared by many c-modes, like java
+(add-hook 'c-mode-hook
+ (lambda ()
+ (define-key c-mode-base-map "\C-d" nil)
+ (define-key c-mode-base-map (kbd "") 'c-electric-delete-forward)))
+
+
+;;;;; M-c - delete-other-windows
+
+(define-key global-map "\M-c" 'delete-other-windows)
+
+;;;;; C-M-c - copy-to-register
+
+(global-set-key (kbd "C-M-c") 'copy-to-register)
+
+;;;;; C-v - yank
+
+(global-set-key (kbd "C-v") 'yank-better)
+
+(add-hook 'ivy-mode-hook
+ (lambda ()
+ (define-key ivy-minibuffer-map (kbd "C-v") nil)))
+
+
+
+(defun yank-better (arg)
+ "Paste, linewise if our kill ends with a newline.
+ I change the behavior of plain prefix. It makes it not do linewise paste,
+ because sometimes you want to yank pop and a linewise paste screws that up.
+ c-u with no number normally makes the point go before the yank.
+ That is pointless for me, as it would be just as easier and less
+ thought to pop the mark after yanking cuz it is set to before the mark."
+ (interactive "*P")
+ (if (and (not (equal arg '(4))) (string-suffix-p "\n" (current-kill 0 t)))
+ (beginning-of-line))
+ (if (and (stringp mode-name) (string= mode-name "Org"))
+ (call-interactively 'org-yank)
+ (setq this-command 'yank)
+ (call-interactively 'yank (and (not (equal arg '(4)))))))
+
+(put 'yank-better 'delete-selection 'yank)
+
+;;;;; M-v - insert-register
+
+(global-set-key (kbd "M-v") 'insert-register)
+
+;;;;; C-M-v - yank-pop
+
+(global-set-key (kbd "C-M-v") 'yank-pop)
+
+;;;;; C-b - other-window
+
+(global-set-key (kbd "C-b") 'other-window)
+
+;;;;; M-b - isearch-backward-current-symbol
+
+(global-set-key (kbd "M-b") 'isearch-backward-current-symbol)
+
+;;;;; C-M-b - isearch-current-symbol
+
+(global-set-key (kbd "C-M-b") 'isearch-current-symbol)
+
+;;;;; C-tab - ---
+;; in terminal, it's just TAB, duplicate keybind.
+;;;;; M-tab - ---
+;; in terminal it's duplicated of C-M-i
+;;;;; C-delete - kill-symbol
+
+(global-set-key (kbd "") 'kill-symbol)
+(defun kill-symbol (arg)
+ (interactive "p")
+ (kill-region (point) (save-excursion (forward-symbol arg) (point))))
+
+
+;;;;; C-M-delete - kill-sexp
+
+(global-set-key (kbd "") 'kill-sexp)
+
+;;;;; C-left-arrow - compile / comint search
+
+(defun set-p (var)
+ (and (bound-and-true-p var)
+ (not (eq var 'unset))))
+(global-set-key (kbd "C-(") 'run)
+
+;; make compile work from the gtags root dir
+(defadvice compile (before pre-compile-advice activate)
+ (basic-save-buffer)
+ (when (set-p ggtags-project-root)
+ (setq-local compile-saved-dir default-directory)
+ (setq default-directory ggtags-project-root)))
+(defadvice compile (after post-compile-advice activate)
+ (when (bound-and-true-p compile-saved-dir)
+ (setq default-directory compile-saved-dir)))
+
+
+(add-hook 'c-mode-hook (lambda () (define-key c-mode-map (kbd "C-(") 'compile)))
+(add-hook 'comint-mode-hook
+ (lambda ()
+ (define-key isearch-mode-map (kbd "C-(") 'isearch-repeat-backward)
+ (define-key comint-mode-map (kbd "C-(") 'isearch-backward)))
+
+
+;;;;; C-M-left-arrow - org-shiftup
+
+(add-hook 'org-mode-hook
+ (lambda () (define-key org-mode-map (kbd "C-M-(") 'org-shiftup)))
+
+;;;;; C-right-arrow - forward-symbol
+;;;;; C-M-right-arrow - org-shiftdown
+(add-hook 'org-mode-hook
+ (lambda () (define-key org-mode-map (kbd "C-M-)") 'org-shiftdown)))
+
+;;;;; C-backspace - backward-kill-symbol
+
+(define-key terminal-key-map (kbd "4b") 'backward-kill-symbol) ;c-backspace in my konsole
+
+;; c-w is duplicate in terminal
+(global-set-key (kbd "") 'backward-kill-symbol)
+(add-hook 'comint-mode-hook
+ (lambda ()
+ (define-key comint-mode-map (kbd "") 'backward-kill-word)))
+(defun backward-kill-symbol (arg)
+ (interactive "p")
+ (kill-region (point) (save-excursion (backward-symbol arg) (point))))
+
+;;;;; C-M-backspace - backward-kill-sexp
+
+(global-set-key (kbd "") 'backward-kill-sexp)
+
+;;;; right primary
+;;;;; M-8 - delete-window-or-exit
+
+(global-set-key (kbd "M-8") 'delete-window-or-exit)
+
+(defun delete-window-or-exit ()
+ "Delete window or exit emacs."
+ (interactive)
+ (if (condition-case nil (delete-window) (error t))
+ (if (or (boundp 'server-process) (> (length (frame-list)) 1))
+ (progn (basic-save-buffer) (delete-frame))
+ (save-buffers-kill-terminal t))))
+
+;;;;; C-* - --- terminal
+;;;;; C-M-* - calc-dispatch
+
+(global-set-key (kbd "C-M-*") 'calc-dispatch)
+
+;;;;; M-9 - kill-buffer
+
+(defun kill-buffer-no-ido ()
+ "kill-buffer, avoid the ido remapping"
+ (interactive)
+ (kill-buffer))
+(global-set-key (kbd "M-9") 'kill-buffer-no-ido)
+
+;; strangely, in simple mode, this is overridden.
+;; I found this map to override, but it didn't work, so it seems its being bound some other way.
+;; I did a grep of the emacs sources, but couldn't find anything.
+;; (define-key universal-argument-map [?9 nil)
+
+;;;;; C-M-9 - end server edit
+;; save & kill buffer if it was opened externally via emacsclient
+
+
+(defun server-edit-save ()
+ (interactive)
+ (save-buffer)
+ (server-edit))
+(global-set-key (kbd "C-M-9") 'server-edit-save)
+
+;;;;; C-u - universal-argument
+;;;;; C-M-u - search-keybind
+
+(global-set-key (kbd "C-M-u") 'search-keybind)
+
+(defun search-keybind (regexp &optional nlines)
+ (interactive (occur-read-primary-args))
+ (save-excursion
+ (describe-bindings)
+ (set-buffer "*Help*")
+ (occur regexp)
+ (delete-windows-on "*Help*")
+ ))
+
+;;;;; C-i -
+;; todo: try making use
+;; this is the key in terminal
+;;M-[ 4 d is undefined
+
+;; previously had this for enhancing graphical keybinds,
+;; but afaik its no help since i want terminal to work
+;; the same.
+;; (define-key input-decode-map [?\C-i] [C-i])
+
+;;;;; C-M-i - query-replace-regexp
+
+(global-set-key (kbd "C-M-i") 'query-replace-regexp)
+(add-hook 'flyspell-mode-hook
+ (lambda () (define-key flyspell-mode-map (kbd "C-M-i") nil)))
+(add-hook 'text-mode-hook
+ (lambda () (define-key text-mode-map (kbd "C-M-i") nil)))
+
+
+;;;;; C-o - occur
+
+(global-set-key (kbd "C-o") 'occur)
+
+;;;;; C-M-o - counsel-imenu
+
+(global-set-key (kbd "C-M-o") 'counsel-imenu)
+
+;;;;; C-p - move-mouse-to-point
+
+(global-set-key (kbd "C-p") 'move-mouse-to-point)
+
+;;;;; C-M-p - delete-horizontal-space
+
+(global-set-key (kbd "C-M-p") 'delete-horizontal-space)
+
+;;;;; C-j - pop-to-mark
+
+(defun my-pop-to-mark-command ()
+ "Jump to mark, and pop a new position for mark off the ring.
+ \(Does not affect global mark ring\)."
+ (interactive)
+ (pop-to-mark-command)
+ (if (and (derived-mode-p 'org-mode) (outline-invisible-p))
+ (org-show-context 'mark-goto)))
+
+(global-set-key (kbd "C-j") 'my-pop-to-mark-command)
+(add-hook 'ido-setup-hook
+ (lambda ()
+ (define-key ido-common-completion-map (kbd "C-j") 'ido-select-text)
+ ))
+(add-hook 'lisp-interaction-mode-hook
+ (lambda ()
+ (define-key lisp-interaction-mode-map (kbd "C-j") nil)))
+
+
+;;;;; M-j - previous-error
+
+(global-set-key (kbd "M-j") 'previous-error)
+
+;;;;; C-M-j - register prefix
+
+(define-key global-map (kbd "C-M-j") ctl-x-r-map)
+(define-key ctl-x-r-map "m" 'kmacro-to-register)
+
+
+;;;;; C-k - jump-to-register
+
+
+(global-set-key (kbd "C-k") 'jump-to-register)
+
+;;;;; M-k - next-error
+
+(global-set-key (kbd "M-k") 'next-error)
+
+;;;;; C-M-k - man
+
+(global-set-key (kbd "C-M-k") 'man)
+
+;;;;; C-l - ivy-switch-buffer
+
+(global-set-key (kbd "C-l") 'ivy-switch-buffer)
+
+;;;;; C-M-l - move cursor top bottom mid, comint clear screen
+
+(global-set-key (kbd "C-M-l") 'move-to-window-line-top-bottom)
+
+;;;;; C-; - used in flyspell, not sure what for, otherwise unbound
+;;;;; M-; - comment-dwim
+;;;;; C-M-; - comment-current-line-dwim
+
+(defun comment-current-line-dwim ()
+ "Comment or uncomment the current line."
+ (interactive)
+ (save-excursion
+ (push-mark (beginning-of-line) t t)
+ (end-of-line)
+ (comment-dwim nil))
+ (move-beginning-of-line 2))
+(global-set-key (kbd "C-M-;") 'comment-current-line-dwim)
+
+;;;;; C-m - ---
+;; terminal/console needs this. otherwise, we could do this
+;; to make C-m be a valid key in graphical mode.
+;; (define-key input-decode-map [?\C-m] [C-m])
+;;;;; C-M-m - recursive grep
+
+(define-key global-map (kbd "C-M-m") 'rgrep)
+
+;;;;; C-, - ---
+;; not recognized by terminal, can't get konsole keydef file to recognize comma,
+;; todo: dig into konsole sources, or try newer version than t8
+
+(add-hook 'flyspell-mode-hook
+ (lambda () (define-key flyspell-mode-map (kbd "C-,") nil)))
+
+;;;;; C-M-, - ind-file-in-project
+
+(global-set-key (kbd "C-M-,") 'find-file-in-project)
+
+;;;;; C-. - find recent file
+
+(add-hook 'flyspell-mode-hook
+ (lambda () (define-key flyspell-mode-map (kbd "C-.") nil)))
+(define-key dot-mode-map (kbd "C-.") nil)
+(define-key terminal-key-map (kbd "4c") 'counsel-recentf)
+(global-set-key (kbd "C-.") 'counsel-recentf)
+(add-hook 'php-mode-hook
+ (lambda () (define-key php-mode-map (kbd "C-.") nil)))
+
+;;;;; C-M-. - -
+
+(define-key dot-mode-map (kbd "C-M-.") nil)
+;; (global-set-key (kbd "C-M-.") 'execute-extended-command)
+
+;;;;; C-/ - join lines
+
+(defun vim-style-join-line ()
+ (interactive)
+ (join-line '(4)))
+;; terminal
+(global-set-key (kbd "C-_") 'vim-style-join-line)
+;; gui
+(global-set-key (kbd "C-/") 'vim-style-join-line)
+
+;;;;; C-M-/ - copy-buffer-file-name
+
+;; haven't bound this atm, todo, maybe someday?
+(defun copy-variable (variable)
+ (interactive
+ (let ((v (variable-at-point))
+ (enable-recursive-minibuffers t)
+ val)
+ (setq val (completing-read (if (symbolp v)
+ (format
+ "Describe variable (default %s): " v)
+ "Describe variable: ")
+ obarray
+ (lambda (vv)
+ (or (get vv 'variable-documentation)
+ (and (boundp vv) (not (keywordp vv)))))
+ t nil nil
+ (if (symbolp v) (symbol-name v))))
+ (list (if (equal val "")
+ v (intern val)))))
+ (kill-new (symbol-value variable)))
+
+(defun copy-buffer-file-name ()
+ (interactive)
+ (let ((name (cond
+ ((derived-mode-p 'mu4e-view-mode) (mu4e-message-field-at-point :path))
+ (t buffer-file-name))
+ ))
+ (kill-new name)
+ (message name)))
+
+
+(global-set-key (kbd "C-M-/") 'copy-buffer-file-name)
+
+
+
+;;;;; C-up-arrow - org prev headline
+
+;; disabled just because i don't want to accidentally hit it
+(define-key global-map "\C-_" nil)
+(global-set-key (kbd "") 'beginning-of-defun)
+
+(add-hook 'org-mode-hook
+ (lambda ()
+ (define-key org-mode-map (kbd "\C-_") 'outline-previous-visible-heading)))
+
+
+
+
+;;;;; C-S-up-arrow - winner undo
+
+(global-set-key (kbd "") 'winner-undo)
+
+;;;;; C-down-arrow - org next headline
+
+(global-set-key (kbd "") 'end-of-defun)
+
+(add-hook 'org-mode-hook
+ (lambda ()
+ (define-key org-mode-map (kbd "") 'outline-next-visible-heading)))
+
+
+
+
+;;;;; C-M-down-arrow - toggle-mark-activation
+
+(defun toggle-mark-activation ()
+ (interactive)
+ (if mark-active
+ (deactivate-mark t)
+ (activate-mark)))
+
+(global-set-key (kbd "") 'toggle-mark-activation)
+
+;;;;; C-S-down-arrow winner redo
+
+(global-set-key (kbd "") 'winner-redo)
+
+
+;;;;; C-S-down-arrow - m-x for major mode
+
+;; todo, update this for ivy
+(global-set-key (kbd "") 'smex-major-mode-commands)
+
+;;;;; C-lbracket - ----
+;;;;; C-M-lbracket - scroll-right
+
+(global-set-key (kbd "C-M-[") 'scroll-right)
+
+;;;;; C-rbracket - fill-paragraph
+
+(global-set-key (kbd "C-]") 'fill-paragraph)
+
+;;;;; C-M-rbracket - scroll-left
+
+(global-set-key (kbd "C-M-]") 'scroll-left)
+
+;;;;; C-return - newline-anywhere
+
+(defun newline-anywhere ()
+ "Add a newline from anywhere in the line."
+ (interactive)
+ (end-of-line)
+ (newline-and-indent))
+;; todo use alternate keybind make this work for terminal
+(global-set-key (kbd "") 'newline-anywhere)
+
+
+;;;;; M-return - plain newline
+
+(defun plain-newline ()
+ (interactive)
+ (insert "\n"))
+(global-set-key (kbd "M-RET") 'plain-newline)
+
+
+;;;;; C-space - org-edit-special
+
+;; commented due to new keyboard needing ctrl-space for mark
+;; (kbd "") does not work, (kbd "C-SPC") should work
+;; (add-hook 'org-mode-hook
+;; (lambda ()
+;; (define-key org-mode-map (kbd "C-SPC") 'org-edit-special)
+;; ;; org-src-mode-map is broken in git version of emacs.
+;; ;; temporarily use this for exiting edit-special mode.
+;; (global-set-key (kbd "C-M--") 'org-edit-src-exit)
+;; (define-key org-src-mode-map (kbd "C-SPC") 'org-edit-src-exit)))
+
+;;;;; C-M-space - before or under cursor
+
+(global-set-key (kbd "C-M-SPC") 'ispell-word)
+;;;; left secondary
+;;;;; C-M-4 - widen
+
+(global-set-key (kbd "C-M-4") 'widen)
+
+;;;;; C-tab-key - query-replace
+
+
+(global-set-key (kbd "") 'query-replace)
+
+;;;;; C-t - org cycle todo / toggle comint motion
+
+(add-hook 'org-mode-hook
+ (lambda ()
+ (define-key org-mode-map (kbd "C-t") 'org-todo)))
+
+
+
+(defun my-comint-previous-input (arg)
+ (interactive "*p")
+ (if (comint-after-pmark-p)
+ (comint-previous-input arg)
+ (forward-line -1)))
+
+(defun my-comint-next-input (arg)
+ (interactive "*p")
+ (if (comint-after-pmark-p)
+ (comint-next-input arg)
+ (forward-line)))
+
+(add-hook 'comint-mode-hook
+ (lambda ()
+ (define-key comint-mode-map (kbd "C-t") 'comint-toggle-arrow-keys)
+ (define-key comint-mode-map (kbd "") 'my-comint-previous-input)
+ (define-key comint-mode-map (kbd "") 'my-comint-next-input)))
+
+
+(defun comint-toggle-arrow-keys ()
+ (interactive)
+ (toggle-arrow-keys comint-mode-map))
+
+(setq-default comint-arrow-movement nil)
+(defun toggle-arrow-keys (map)
+ (cond ((lookup-key map (kbd ""))
+ (setq-local comint-arrow-movement t)
+ (define-key map (kbd "") nil)
+ (define-key map (kbd "") nil))
+ (t
+ (setq-local comint-arrow-movement nil)
+ (define-key map (kbd "") 'my-comint-previous-input)
+ (define-key map (kbd "") 'my-comint-next-input)
+ (goto-char (point-max)))))
+
+(eval-after-load "message"
+ '(define-key message-mode-map (kbd "C-t") 'mail-signature))
+
+
+;;;;; C-M-t - org timestamp
+
+(global-set-key (kbd "C-M-t") 'org-time-stamp-with-time)
+
+;;;;; C-home - start of buffer
+;;;;; C-end - end of buffer
+;;;; right secondary
+;;;;; C-^ - save-buffers-kill-emacs exit quit
+
+(global-set-key (kbd "C-^") 'save-buffers-kill-emacs)
+
+;;;;; C-M-6 - insert-small-copyright
+
+(defun insert-small-copyright ()
+ (interactive)
+ (beginning-of-line)
+ (let ((beg (point)))
+ (insert "Copyright (C) 2019 Ian Kelling\nThis program is under GPL v. 3 or later, see ")
+ (comment-region beg (point))))
+
+(global-set-key (kbd "C-M-6") 'insert-small-copyright)
+
+;;;;; M-7 - calc-embedded-word
+
+(global-set-key (kbd "M-7") 'calc-embedded-word)
+
+;;;;; C-M-7 - insert-full-copyright
+
+(defun insert-full-copyright ()
+ (interactive)
+ (beginning-of-line)
+ (let ((beg (point)))
+ (insert "Copyright (C) 2019 Ian Kelling\n")
+ (insert "\n")
+ (insert "This program is free software: you can redistribute it and/or modify\n")
+ (insert "it under the terms of the GNU General Public License as published by\n")
+ (insert "the Free Software Foundation, either version 3 of the License, or\n")
+ (insert "(at your option) any later version.\n")
+ (insert "\n")
+ (insert "This program is distributed in the hope that it will be useful,\n")
+ (insert "but WITHOUT ANY WARRANTY; without even the implied warranty of\n")
+ (insert "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n")
+ (insert "GNU General Public License for more details.\n")
+ (insert "\n")
+ (insert "You should have received a copy of the GNU General Public License\n")
+ (insert "along with this program. If not, see .\n")
+ (comment-region beg (point))))
+
+(global-set-key (kbd "C-M-7") 'insert-full-copyright)
+
+
+;;;;; C-0 - text-scale-reset
+
+(defun text-scale-reset ()
+ (interactive)
+ (text-scale-set 0))
+(global-set-key (kbd "C-0") 'text-scale-reset)
+
+;;;;; C-M-0 - insert-apache
+
+(defun insert-apache ()
+ (interactive)
+ (beginning-of-line)
+ (let ((beg (point)))
+ (insert "Copyright (C) 2017 Ian Kelling\n")
+ (insert "\n")
+ (insert "Licensed under the Apache License, Version 2.0 (the \"License\");\n")
+ (insert "you may not use this file except in compliance with the License.\n")
+ (insert "You may obtain a copy of the License at\n")
+ (insert "\n")
+ (insert " http://www.apache.org/licenses/LICENSE-2.0\n")
+ (insert "\n")
+ (insert "Unless required by applicable law or agreed to in writing, software\n")
+ (insert "distributed under the License is distributed on an \"AS IS\" BASIS,\n")
+ (insert "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n")
+ (insert "See the License for the specific language governing permissions and\n")
+ (insert "limitations under the License.\n")
+ (comment-region beg (point))))
+(global-set-key (kbd "C-M-0") 'insert-apache)
+
+
+;;;;; C-M-- - org-edit-src-exit
+;;;;; C-y - undo
+
+;;(global-set-key (kbd "C-y") 'undo-tree-redo)
+(global-set-key (kbd "C-y") 'undo-fu-only-redo)
+(add-hook 'org-mode-hook
+ (lambda () (define-key org-mode-map (kbd "C-y") nil)))
+
+
+;;;;; C-\ - sr-speedbar-toggle
+(global-set-key (kbd "C-\\") 'sr-speedbar-toggle)
+
+;;;;; C-M-\ - mark-defun
+
+(global-set-key (kbd "C-M-\\") 'mark-defun)
+
+;;;;; C-h - help-prefix
+
+;;;;; C-' - val-expression
+
+(global-set-key (kbd "C-'") 'eval-expression)
+
+;;;;; C-n - unpop to mark
+
+(defun unpop-to-mark-command ()
+ "Unpop off mark ring. Does nothing if mark ring is empty."
+ (interactive)
+ (when mark-ring
+ (let ((pos (marker-position (car (last mark-ring)))))
+ (if (not (= (point) pos))
+ (goto-char pos)
+ (setq mark-ring (cons (copy-marker (mark-marker)) mark-ring))
+ (set-marker (mark-marker) pos)
+ (setq mark-ring (nbutlast mark-ring))
+ (goto-char (marker-position (car (last mark-ring))))))))
+
+(global-set-key (kbd "C-n") 'unpop-to-mark-command)
+
+;;;;; C-M-n - narrow-to-region
+
+(global-set-key (kbd "C-M-n") 'narrow-to-region)
+
+;;;;; C-escape - find-tag
+
+(global-set-key (kbd "") 'find-tag)
+
+
+;; Local Variables:
+;; eval: (outline-minor-mode)
+;; outline-regexp: "\\( *\\);;;\\{1,8\\} "
+;; End: