From 6b38c0bb4470a51f8b1f70ff9dcbf37f18a19429 Mon Sep 17 00:00:00 2001 From: Ian Kelling Date: Sun, 23 Jun 2019 22:47:33 -0400 Subject: [PATCH] consolidate --- .gitignore | 1 + ian-notes.org | 19 + init.el | 3592 ++++++++++++++++++++++++++++++++++++++++++++++++- myinit.el | 3568 ------------------------------------------------ 4 files changed, 3596 insertions(+), 3584 deletions(-) delete mode 100644 myinit.el diff --git a/.gitignore b/.gitignore index ae7be91..edb646b 100644 --- a/.gitignore +++ b/.gitignore @@ -27,6 +27,7 @@ /session.* *.elc /games +/transient # artifacts I create /my-init.el diff --git a/ian-notes.org b/ian-notes.org index e976bac..347b3db 100644 --- a/ian-notes.org +++ b/ian-notes.org @@ -1249,6 +1249,25 @@ clicking on info links speedbar-hide-button-brackets-flag nil) #+end_src +* TODO investigate modes i had installed, but removed due to not using: +inf-ruby +jedi +key-chord +paredit +python-info +rust-mode +python-mode +tabulated-list +python-environment +popup +transient +lv +outorg +ac-haskell-process +ghc + +* TODO in init.el, use (expand-file-name "myinit.el" init-dir) instead of ~/.emacs.d +so it could be relocated * TODO fix auto save to be reliable and not rely on idle time sometimes emacs or computer stays busy and idle never comes * TODO try out which key mode diff --git a/init.el b/init.el index 43384fe..f6f68de 100644 --- a/init.el +++ b/init.el @@ -1,4 +1,4 @@ -;; Copyright (C) 2014 Ian Kelling +;; Copyright (C) 2019 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 @@ -35,10 +35,20 @@ ;; seems its changed now. no harm in keeping this though. (global-unset-key (kbd "C-z")) +;; speed up init https://www.reddit.com/r/emacs/comments/3kqt6e/2_easy_little_known_steps_to_speed_up_emacs_start/ +(setq gc-cons-threshold 100000000) + + ;; these need to be done before the hook in order to satisfy the byte compiler or batch mode -(add-to-list 'load-path "~/.emacs.d/emacs/site-lisp/org") + +;; this is the builtin org mode +;;(add-to-list 'load-path "~/.emacs.d/emacs/site-lisp/org") + (add-to-list 'load-path "~/.emacs.d/src/readline-complete") -(add-to-list 'load-path "~/.emacs.d/src/bbdb-csv-import") + +;; disabled since not used. +;;(add-to-list 'load-path "~/.emacs.d/src/bbdb-csv-import") + (add-to-list 'load-path "~/.emacs.d/src/ghci-completion") (add-to-list 'load-path "~/.emacs.d/src/mediawiki-el") (add-to-list 'load-path "~/.emacs.d/src/spray") @@ -59,24 +69,3574 @@ ;;(require 'bbdb-loaddefs "~/.emacs.d/src/bbdb/lisp/bbdb-loaddefs.el") ;;(setq bbdb-print-tex-path "~/.emacs.d/src/bbdb/tex") + +;; iank: dunno what this was about ;;(add-hook 'server-visit-hook 'raise-frame) +(setq init-dir (file-name-directory load-file-name)) +;; 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))) -;; load init in `after-init-hook' so all packages are loaded +;; load init in `after-init-hook' so all packages are loaded. However, disabled because +;; there seems to be no need. ;; 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)) - ;; 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 (concat init-dir "myinit.el"))) +;; (add-hook 'after-init-hook +;; `(lambda () +;; (load-file (expand-file-name "myinit.el" init-dir)) +;; )) + + +;;; Weird package bug workaround + + +;; without this, when installing a package, this message happens +;; +;; custom-handle-keyword: Unknown keyword :group +;; +;; but when i lookup the function, i get the following, and if +;; I evaluate it, the error goes away. so I think the real +;; definition is happening somewhere else + +(defun custom-handle-keyword (symbol keyword value type) + "For customization option SYMBOL, handle KEYWORD with VALUE. +Fourth argument TYPE is the custom option type." + (if purify-flag + (setq value (purecopy value))) + (cond ((eq keyword :group) + (custom-add-to-group value symbol type)) + ((eq keyword :version) + (custom-add-version symbol value)) + ((eq keyword :package-version) + (custom-add-package-version symbol value)) + ((eq keyword :link) + (custom-add-link symbol value)) + ((eq keyword :load) + (custom-add-load symbol value)) + ((eq keyword :tag) + (put symbol 'custom-tag value)) + ((eq keyword :set-after) + (custom-add-dependencies symbol value)) + (t + (error "Unknown keyword %s" keyword)))) + + +;;; 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 ~/.dribble (or something) + + +;;;;; 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 +;; todo, evaluating this manually disables debug on error instead of toggling it +(toggle-debug-on-error) ;uncomment to help debug and catch errors + +;; packages installed from package manager: i pretty much prioritize repos this way: gnu, then melpa, then marmalade. + +;; package-activated-list: +;; ac-dabbrev ac-haskell-process ack-and-a-half alect-themes auctex bash-completion bbdb csv-mode cyberpunk-theme dot-mode expand-region f find-file-in-project flycheck foreign-regexp ggtags ghc gnuplot-mode goto-chg haskell-mode heroku-theme highlight-indentation highlight-symbol htmlize inf-ruby info+ inkpot-theme jedi auto-complete jedi-core epc ctable concurrent key-chord leuven-theme logstash-conf magit git-commit magit-popup misc-fns mouse+ naquadah-theme nginx-mode occidental-theme org paredit pcsv php-mode pkg-info epl popup py-autopep8 python-environment deferred python-info python-mode rainbow-mode rust-mode rw-hunspell s smartparens smex smooth-scroll sr-speedbar strings swiper ivy tabulated-list tangotango-theme thingatpt+ undo-tree vimrc-mode volatile-highlights web-mode with-editor dash async ws-butler yasnippet + +;;;; alternate keyboards +;; todo, figure out an easy way to disable this when using external keyboard +(if (display-graphic-p) + (setq + enter-key (kbd "") + s-enter-key (kbd "") + c-m-enter-key (kbd "") + m-enter (kbd "") + c-enter (kbd "")) + (setq + enter-key (kbd "C-m") + s-enter-key (kbd "C-8") + c-m-enter-key (kbd "C-M-8") + m-enter (kbd "M-m") + c-enter (kbd "C-8"))) + +(setq tp (string= (system-name) "tp")) +(setq x200 (string= (system-name) "x2")) +(setq laptop-keyboard (or tp x200)) + +;; Ubiquitous Packages which should be loaded on startup rather than +;; autoloaded on demand since they are likely to be used in every +;; session. +(require 'saveplace) +(require 'ffap) +(require 'uniquify) +(require 'ansi-color) +(require 'recentf) + +;; Better to have a list of packages in here vs installed manually. +;; However, I install manually because sometimes there are two +;; versions and it is not necessarily easy to reconcile that. +;; based on marmalage website front page. +(require 'package) + +;; little kit to help remove a down server +;; (setq package-archives nil) + +;;(add-to-list 'package-archives +;; '("marmalade" . +;; "http://marmalade-repo.org/packages/")) + +(add-to-list 'package-archives + '("melpa" . "http://melpa.milkbox.net/packages/") t) +(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 "~/.emacs.d/custom.el") +(load custom-file 'noerror) + + + +;;; abreviations +;; turn on abbrev mode globally +(setq-default abbrev-mode t) + +;; default abbreviation mode file is .emacs.d/abbrev_defs. +;; add-global-abbrev, add-mode-abbrev for expansion at point +;; if all else fails, edit the abbrev file + + + + +;;; auto-complete + +;; auto-completion in minibuffer +;; disabled while I look for another alternative +;;(icomplete-mode) + +(require 'auto-complete-config) +(ac-config-default) + + +;; complete after 1 char instead of default 2 +(setq ac-auto-start 1) +(setq ac-delay 0.001) + +(add-to-list 'ac-modes 'org-mode 'sql-mode) + +(defun ac-common-setup () + (add-to-list 'ac-sources 'ac-source-yasnippet)) + +;; 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) + + + +;;; 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))) + + +;;; readline complete fix + +;; I need this function here, where INSIDE_EMACS is replaced with RLC_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 "RLC_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 & backup +(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 +(setq 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 (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 on)) + +;; 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) + +;; 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) (* 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 + +;;; bbdb +;; based on bbdb manual +;; also has instructions to integrate with gnus, + +(bbdb-initialize 'message) + +;; recommended by gnus, +;; but seems like it could be good to have set for other stuff +(setq user-full-name "Ian Kelling") +;; general email setting? recommended by mu4e +(setq message-kill-buffer-on-exit t) + + + +;; use d instead +(add-hook 'bbdb-mode-hook + (lambda () (define-key bbdb-mode-map (kbd "C-k") nil)) + ;; based on emacs24-starter-kit + (setq bbdb-offer-save 'auto + bbdb-notice-auto-save-file t + bbdb-expand-mail-aliases t + bbdb-canonicalize-redundant-nets-p t + bbdb-complete-name-allow-cycling t) + ) + +;;(require 'bbdb-csv-import) + +;;; bookmark settings + ; save bookmarks whenever they are changed instead of just when emacs quits +(setq bookmark-save-flag 1) + ; increase bookmark context size for better functionality +(setq bookmark-search-size 2000) + +;;; c-like settings +;; change last thing from gnu. +;; notably this avoids brace indent after if, and 4 space indent +(setq c-default-style '((java-mode . "java") + (awk-mode . "awk") + (other . "stroustrup"))) +;; for emacs itself, use +;; (setq c-default-style '((java-mode . "java") +;; (awk-mode . "awk") +;; (other . "gnu"))) +;; (setq-default c-basic-offset 2) + +;;; 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. + + +;; interesting light themes + + +(defun override-theme (arg) + (interactive) + (while custom-enabled-themes + (disable-theme (car custom-enabled-themes))) + (load-theme arg t)) +(setq color-theme-is-global t) + +(defun toggle-night () + (interactive) + (cond ((equal (car custom-enabled-themes) 'naquadah) + (override-theme 'leuven)) + (t + (override-theme 'naquadah)))) + + +;; 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")))) +(override-theme 'leuven) + + +;; 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) + + + + +;;; yasnippet + +;; cd ~/.emacs.d/src +;; git clone --recursive https://github.com/capitaomorte/yasnippet +;; touch snippets/.yas-make-groups + +;; This all makes it so I can look through the default snippets +;; in the menu bar, but they don't show up elsewhere, because they are +;; mostly things I don't want. + + +(require 'yasnippet) +;; this needs to be before yas-global-mode +(setq yas-snippet-dirs (list "~/.emacs.d/snippets")) +(yas-global-mode 1) + +(setq + yas-also-auto-indent-first-line t + yas-choose-tables-first t + yas-use-menu (quote full) + ;; this sets ido-prompt as first function + yas-prompt-functions + '(yas-ido-prompt yas-dropdown-prompt yas-x-prompt yas-completing-prompt yas-no-prompt)) + +;; todo, explore this option for wrapping region +;; '(yas/wrap-around-region t)) + +;;; cross session settings + +;; Save a list of recent files visited. +(recentf-mode 1) +(setq recentf-max-saved-items 200 + recentf-max-menu-items 15) + + +(setq save-place t + save-place-version-control 'nospecial + save-place-limit 40000 + save-place-file "~/.emacs.d/places") + + + +;; savehist keeps track of some history +;; search entries +(setq savehist-additional-variables '(kill-ring search-ring regexp-search-ring) + ;; save every minute + savehist-autosave-interval 60 + ;; keep the home clean + savehist-file "~/.emacs.d/.savehist") +(savehist-mode 1) + + +;;; ediff +;; ediff-buffers is the main command to use + +;; ediff - 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 +(setq ediff-window-setup-function 'ediff-setup-windows-plain) +;;(setq ediff-window-setup-function 'ediff-setup-windows-default) + +;; do side by side diffs +(setq ediff-split-window-function 'split-window-horizontally) + + + +;; 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. + +;;; dired + +;; dired - reuse current buffer by pressing 'a' +(put 'dired-find-alternate-file 'disabled nil) + +;;; mu4e + +;; alsot tried notmuch, it had some glitches, and it's config has a list +;; of folders which i'd rather not publish, so it's config is archived. + +;;(add-to-list 'load-path "/usr/local/share/emacs/site-lisp/mu4e") +;;(add-to-list 'load-path "/usr/share/emacs/site-lisp/mu4e") +(require 'mu4e) + +;; (setq mu4e-headers-results-limit 2000) + +(setq + ;; common to gnus. default sendmail-query-once asks us, then sets this via customize. + send-mail-function (quote sendmail-send-it) + ;; use the standard imap folders + mu4e-sent-folder "/Sent" + mu4e-drafts-folder "/Drafts" + mu4e-trash-folder "/Trash" + ;; reindex new mail this often in seconds + ;; show addresses instead of just names + mu4e-view-show-addresses t + mu4e-use-fancy-chars t + mu4e-confirm-quit nil + mu4e-headers-leave-behavior 'apply ;; dont ask, do whatever was marked + mu4e-headers-fields (delq (assoc :mailing-list mu4e-headers-fields) mu4e-headers-fields) + ;; default 500. + mu4e-headers-results-limit 1000 + ;; tell exim to use from: as envelope from. + ;; exim's default is use outgoing_msg_localpart@hostname. + mail-specify-envelope-from t + + ;; looking up the list of maildirs when doing jo from summary + ;; can take a few seconds if we have a ton of messages. + ;; Only take that time for the first lookup. + ;; if we add a new maildir, just restart mu4e for it to be in that list. + mu4e-cache-maildir-list t + ;; default is 8, way too small for my big monitors + mu4e-headers-visible-lines 50 + ) + +;; fucks up reading unread bookmark. when that is fixed, enable it +;; (setq mu4e-update-interval 60) + + +;; 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. +(load "/p/c/mu4e.el") + +(defun my-decrypt () + ;; use for decrypting in mu4e + (interactive) + (beginning-of-buffer) + (when (search-forward "-----BEGIN PGP MESSAGE-----" nil t) + (read-only-mode 0) + (let ((start (match-beginning 0)) + (end (search-forward "-----END PGP MESSAGE-----" nil t))) + (shell-command-on-region start end "gpg2 -dq" nil t shell-command-default-error-buffer t) + ))) +(add-hook 'mu4e-view-mode-hook 'my-decrypt) + +(defun mu-set-from-name (regexes) + "If we find an address matching regex, then set that address as the to, +and whatever was used" + (when mu4e-compose-parent-message + (let ((found nil)) + (while (and regexes (not found)) + (setq re (car regexes) + regexes (cdr regexes) + found (mu4e-message-contact-field-matches + mu4e-compose-parent-message :to re))) + (when found (setq user-mail-address (cdr found) + user-full-name (car found))) + found))) +(defun mu-set-from (regexes) + "If we find an address matching regex, then set that address as the to, +and Ian Kelling as the name" + (when mu4e-compose-parent-message + (let ((found nil)) + (while (and regexes (not found)) + (setq re (car regexes) + regexes (cdr regexes) + found (cdr (mu4e-message-contact-field-matches + mu4e-compose-parent-message :to re)))) + (when found (setq user-mail-address found + user-full-name "Ian Kelling")) + found))) + + +(defun my-mu4e-to-fsf () + "inspired by mu4e info manual, search for mu4e-compose-pre-hook." + (cond + ((mu-set-from '("iank@fsf.org" + "iank@gnu.org"))) + ((setq user-mail-address "iank@fsf.org" + user-full-name "Ian Kelling")))) + + +;; on first run mkdir -p /nocow/user/.mufsf; mu index --maildir=/nocow/user/fsfmd +(defun mu-exit-wait () + (interactive) + ;; taken from the mu source + (let* ((buf (get-buffer mu4e~proc-name)) + (proc (and (buffer-live-p buf) (get-buffer-process buf)))) + (mu4e-quit) + ;; without sleep, we get database locked by another process error when hitting u + ;; if another mu was running. + (if proc (sleep-for 0 1000)))) + +(defun fsf-mu4e () + (interactive) + (unless (equal mu4e-maildir "/nocow/user/fsfmd") (mu-exit-wait)) + (setq + ;; fsf monitor is smaller + mu4e-headers-visible-lines 15 + mu4e-maildir "/nocow/user/fsfmd" + mu4e-refile-folder "/Spam" + mu4e-index-lazy-check nil + mu4e-get-mail-command "true" + user-mail-address "iank@fsf.org" + ;; WARNING: be careful editing this, there needs to be a space after --, and my editor + ;; and git will automatically remove it unless i manually disable it. + mail-signature " + +-- +Ian Kelling | Senior Systems Administrator, Free Software Foundation +GPG Key: B125 F60B 7B28 7FF6 A2B7 DF8F 170A F0E2 9542 95DF +https://fsf.org | https://gnu.org +" + + mu4e-user-mail-address-list '("iank@fsf.org" + "iank@gnu.org") + mu4e-maildir-shortcuts + '( ("/INBOX" . ?i) + ("/sysadmin" . ?a) + ("/sec" . ?x) + ("/rtcc" . ?c) + ("/Drafts" . ?d) + ("/Sent" . ?s) + ) + ) ;; end setq + (call-process "/a/exe/lnf" nil nil nil "-T" "/nocow/user/.mufsf" (concat (getenv "HOME") "/.mu")) + (add-hook 'mu4e-compose-pre-hook 'my-mu4e-to-fsf) + (remove-hook 'mu4e-compose-pre-hook 'my-mu4e-to) + (mu4e)) ;; end defun fsf-mu4e + + +;; it's implemented in mu4e, but not in the actions list for +;; some reason. +(add-to-list 'mu4e-view-actions + '("browser view" . mu4e-action-view-in-browser) t) + +;; normally, you would add to this, but we want to +;; modify unread messages. the first 4 are defined by default. +(setq mu4e-bookmarks + `( ,(make-mu4e-bookmark + :name "Unread messages" + ;; old less restrictive unread, for adapting in the future: + ;; flag:unread AND NOT flag:trashed AND NOT maildir:/Junk AND NOT maildir:/fwfw AND NOT maildir:/log + :query "flag:unread maildir:/INBOX" + :key ?u) + ,(make-mu4e-bookmark + :name "Today's messages" + :query "date:today..now" + :key ?t) + ,(make-mu4e-bookmark + :name "Last 7 days" + :query "date:7d..now" + :key ?w) + ,(make-mu4e-bookmark + :name "Messages with images" + :query "mime:image/*" + :key ?p)) + ) + + +(defun mu4e-action-msgs-by-this-sender (msg) + "In header view, view messages by the sender of the message under point." + (let ((from (mu4e-message-field msg :from))) + (unless from + (mu4e-error "No from header for this message")) + ;; from is structured like: (("Anacron" . "root@x2.lan")) + (mu4e-headers-search (concat "f:" (cdar from))))) + +(add-to-list 'mu4e-headers-actions + '("from this sender" . mu4e-action-msgs-by-this-sender) t) +(add-to-list 'mu4e-view-actions + '("from this sender" . mu4e-action-msgs-by-this-sender) t) + + +;;; elisp settings + ; when manually evaluating lisp, go into debugger on error +(setq eval-expression-debug-on-error t) + ;reminder of useful var: debug-on-error + + +;;; haskell + +;; useful comint-shell mode commands. If not prefaced with *, it means it is not in the haskell custom repl +;; *todo: setup haskell c-t toggle arrow keys +;; tab completion +;; C-q insert prev arg +;; C-( history search +;; c-m-left/right move to next/prev prompts +;; *c-enter, multi-line input +;; *s-delete, send input across windows. (i can implement this) +;; *c-m-l clear screen +;; *haskell-process-interrupt, c-cc terminate job (i can implement this maybe) + +;; nice bash/readline functions missing in comint: +;; yank-nth-arg +;; operate-get-next +;; menu-complete + +;; usefull comint commands: +;; c-cl : list historic command in temp buffer +;; C-c C-o comint-delete-output +;; comint-restore-input, todo: put this on a randomish c-c key + + + +;; todo: +;; checkout haskell repl functions: +;; c-cv haskell-check, hlint +;; C-M-q prog-indent-sexp +;; c-c. haskell-mode-format-imports +;; C-c M-/ haskell-doc-check-active +;; haskell-process-generate-tags +;; haskell-process-cabal-build +;; haskell-cabal-command.. or something +;; haskell-process-restart +;; C-h v haskell-process-log +;; C-h v haskell-process-show-debug-tips + +;; various not immediately useful functions: +;; haskell-process-add-dependency +;; haskell-process-touch-buffer +;; haskell-process-cd +;; haskell-process-unignore +;; haskell-process-reload-devel-main + + +;; rebind +;; home: C-a haskell-interactive-mode-beginning +;; c-return: C-j haskell-interactive-mode-newline-indent +;; up/down: haskell-interactive-mode-history-next + +;; todo haskell mode better binds for: +;; 'haskell-process-load-file +;; 'haskell-process-do-type +;; 'haskell-process-do-info +;; 'inferior-haskell-send-decl + + +;; commands which don't work in haskell-interactive-mode(hi) vs inferior-haskell-mode(ih, default) +;; functions not in hi: +;; inferior-haskell-find-definition, use tags instead +;; inferior-haskell-find-haddock, todo, test if this works + +;; redefined ih to hi +;; switch-to-haskell -> 'haskell-interactive-switch +;; haskell-process-load-file -> inferior-haskell-load-file +;; haskell-process-do-type -> inferior-haskell-type +;; switch-to-haskell -> haskell-interactive-switch +;; inferior-haskell-load-file -> 'haskell-process-load-file + + +;; haskell-mode installation from source, based on its readme +;; in the git directory, +;; make all + + + + +;; remove default option to not link the file +(setq haskell-compile-command "ghc -Wall -ferror-spans -fforce-recomp %s") +(add-hook 'haskell-indentation-mode-hook + (lambda () + (define-key haskell-indentation-mode-map [?\C-d] nil) + (define-key haskell-indentation-mode-map + (kbd "") + 'haskell-indentation-delete-char))) + +;;copied from haskell-mode docs in order to use the new, better, nondefault +;;interactive mode. +(eval-after-load "haskell-mode" + '(progn + (define-key haskell-mode-map (kbd "C-x C-d") nil) + (define-key haskell-mode-map (kbd "C-c C-z") 'haskell-interactive-switch) + (define-key haskell-mode-map (kbd "C-c C-l") 'haskell-process-load-file) + (define-key haskell-mode-map (kbd "C-c C-b") 'haskell-interactive-switch) + (define-key haskell-mode-map (kbd "C-c C-t") 'haskell-process-do-type) + (define-key haskell-mode-map (kbd "C-c C-i") 'haskell-process-do-info) + (define-key haskell-mode-map (kbd "C-c M-.") nil) + (define-key haskell-mode-map (kbd "C-c C-d") nil))) + +;; ghc-mod install http://www.mew.org/~kazu/proj/ghc-mod/en/emacs.html +;; todo, try this out +;; (autoload 'ghc-init "ghc" nil t) +;;(add-hook 'haskell-mode-hook (lambda () (ghc-init) (flymake-mode))) + + + +;; from the package readme for ghci-completion +(require 'ghci-completion) +(add-hook 'inferior-haskell-mode-hook 'turn-on-ghci-completion) + + +;; disable some rebinds. they are set to appropriate keys in the keybinds section +(eval-after-load "haskell-mode" + '(progn + (define-key haskell-mode-map (kbd "C-a") 'nil) + (define-key haskell-mode-map (kbd "C-j") 'nil))) + +(eval-after-load "python-mode" + '(progn + (define-key python-mode-map (kbd "C-j") nil))) + +(defun pretty-lambdas-haskell () + (font-lock-add-keywords + nil `((,(concat "(?\\(" (regexp-quote "\\") "\\)") + (0 (progn (compose-region (match-beginning 1) (match-end 1) + ,(make-char 'greek-iso8859-7 107)) + nil)))))) +;; from haskell-mode manual +(add-hook 'haskell-mode-hook 'turn-on-haskell-decl-scan) +(when (window-system) + (add-hook 'haskell-mode-hook 'pretty-lambdas-haskell)) + +;; added from haskell-mode website install instructions + ;(load "/usr/share/emacs/site-lisp/haskell-mode/haskell-site-file") +(add-hook 'haskell-mode-hook 'turn-on-haskell-doc-mode) +;;the three indentation modules are mutually exclusive - add at most one. Trying out the "most advanced" +(add-hook 'haskell-mode-hook 'turn-on-haskell-indentation) +;;(add-hook 'haskell-mode-hook 'turn-on-haskell-indent) +;;(add-hook 'haskell-mode-hook 'turn-on-haskell-simple-indent) + + +;; todo, set this to some other key +;; (local-set-key (kbd "C-e") 'my-haskell-load-and-run) + +(defun my-haskell-load-and-run () + "Loads and runs the current Haskell file." + (interactive) + (let ((start-buffer (current-buffer))) + (inferior-haskell-load-and-run inferior-haskell-run-command) + (sleep-for 0 100) + (end-of-buffer) + (pop-to-buffer start-buffer))) + +;; show haskell function in mode line +;; todo, this broke after updating emacs +;;(eval-after-load "which-func" +;; '(add-to-list 'which-func-modes 'haskell-mode)) + + + +(add-hook 'interactive-haskell-mode-hook 'ac-haskell-process-setup) +(add-hook 'haskell-interactive-mode-hook 'ac-haskell-process-setup) +(eval-after-load "auto-complete" + '(add-to-list 'ac-modes 'haskell-interactive-mode)) + +(add-hook 'haskell-mode-hook + (lambda () (define-key haskell-mode-map (kbd "C-(") + (lambda () (interactive) + (basic-save-buffer) + (haskell-compile) + (run-with-timer .3 nil 'repeat-shell))))) +(add-hook 'haskell-cabal-mode-hook + (lambda () (define-key haskell-cabal-mode-map (kbd "C-(") 'haskell-compile))) + + + +(add-hook 'haskell-interactive-mode-hook + (lambda () + (define-key haskell-interactive-mode-map "\r" nil) + (define-key haskell-interactive-mode-map (kbd "") 'haskell-interactive-mode-return))) +(add-hook 'haskell-indentation-mode-hook (lambda () (define-key haskell-indentation-mode-map "\r" nil))) + + + +(add-hook 'haskell-interactive-mode-hook + (lambda () + (define-key haskell-interactive-mode-map (kbd "") 'haskell-interactive-mode-newline-indent))) + +;;; 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))) + + + + ; lets look through emacs starter kit before we throw this out. + + + ; 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)) +(setq prelude-interactive-lisp-coding-hook 'prelude-interactive-lisp-coding-defaults) + + +;; ielm is an interactive Emacs Lisp shell +(defun ielm-mode-defaults () + (run-hooks 'prelude-interactive-lisp-coding-hook) + (turn-on-eldoc-mode)) +(add-hook 'ielm-mode-hook 'ielm-mode-defaults) + +;;; mediawiki + +(eval-after-load "mediawiki" + '(progn + (remove-hook 'outline-minor-mode-hook 'mediawiki-outline-magic-keys) + (add-hook 'mediawiki-mode-hook + (lambda () (define-key mediawiki-mode-map (kbd "C-(") 'mediawiki-save-reload))) + + ;; mediawiki mode has a bug that it will claim an edit conflict unless you reload after saving. + ;; I also like to save with no edit summary for previewing on my local mw instance + (defun mediawiki-save-reload () + (interactive) + (and (mediawiki-save "") (mediawiki-reload))))) +;;; modes with little configuration needed +;; busted: +;;(require 'csv-mode) +;;(add-to-list 'auto-mode-alist '("\\.[Cc][Ss][Vv]\\'" . csv-mode)) + +(require 'outshine) +(add-hook 'outline-minor-mode-hook 'outshine-mode) +(add-hook 'emacs-lisp-mode-hook 'outline-minor-mode) +(add-hook 'sh-mode-hook 'outline-minor-mode) + + + +(setq org-caldav-url "https://cal.iankelling.org" + org-caldav-calendar-id "ian" + org-caldav-inbox "/p/cal.org") +;;(org-caldav-sync) + + +;;(require 'dtrt-indent) +;;(setq dtrt-indent-mode t) + +(setq css-indent-offset 2) + +(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 +(add-to-list 'ws-butler-global-exempt-modes 'message-mode) + +(ws-butler-global-mode) + + + +(require '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) + +(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)))) +(defun tail-colorize () + (ansi-color-apply-on-region prev-auto-revert-max (point-max)) + (setq-local prev-auto-revert-max (point-max))) + + +;; gnu global +(require 'ggtags) +(add-hook 'c-mode-common-hook + (lambda () (ggtags-mode 1) + (setq c-label-minimum-indentation 0))) + +;; specific to my unusual keybind setup, you may want to +;; pick different keys +(define-key ggtags-mode-map (kbd "C-M-o") 'ggtags-find-tag-dwim) +(define-key ggtags-mode-map (kbd "C-M-m") 'ggtags-grep) + +(defun gtags-update-single(filename) + "Update Gtags database for changes in a single file" + (interactive) + (start-process "update-gtags" "update-gtags" "bash" "-c" (concat "cd " ggtags-project-root " ; gtags --single-update " filename ))) + +(defun gtags-update-current-file() + (interactive) + (let ((rel-filename (replace-regexp-in-string + ggtags-project-root "." + (buffer-file-name (current-buffer))))) + (gtags-update-single rel-filename))) + +(defun gtags-update-hook() + "Update GTAGS file incrementally upon saving a file" + (when (and ggtags-mode ggtags-project-root) + (gtags-update-current-file))) + +(add-hook 'after-save-hook 'gtags-update-hook) + +;; i'd like to make some elisp which modifies a keymap to remove +;; all binds which don't match a predicate. +;; I tried setting a keymap to a new keymap, +;; but that didn't register as functional. +;; so I'd need to modify the list in place. + +(require 'magit) + + +;; colorize hex colors: use rainbow mode + + +;; message mode prompted me on first message. +;; a function which describes options then sets this +;; the other options were to use smtp directly or pass to another mail client +;; here we use the standard sendmail interface, which I use postfix for +(setq send-mail-function (quote sendmail-send-it)) + +(require 'spray) +(global-set-key (kbd "C-M-w") 'spray-mode) +;; remember, h/l = move. f/s = faster/slower, space = pause, all others quit + +;; delete active selection with self-insert commands +(delete-selection-mode t) + +;; Transparently open compressed files +(auto-compression-mode t) + +;; Highlight matching parenthesesq when the pointq is on them. +;; not needed since smart paren mode? +;; (show-paren-mode 1) + + +;; 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. +(setq TeX-command-force "LaTeX") + +;; dot mode, repeats last action +(require 'dot-mode) +(add-hook 'find-file-hooks 'dot-mode-on) + + +;; clean up obsolete buffers automatically at midnight +(require 'midnight) + + +;; disabled because it takes 400ms on startup +;; ;; emacs regexes are too limited. +;; (require 'foreign-regexp) +;; ;; perl is most powerful, but javascript is pretty close and +;; ;; I'd rather know javascript stuff than perl +;; (custom-set-variables +;; '(foreign-regexp/regexp-type 'javascript) ;; Choose by your preference. +;; '(reb-re-syntax 'foreign-regexp)) ;; Tell re-builder to use foreign regexp. +;; ;; it would be nice to add documentation to do this for more commands to that package +;; ;; disabled because it's too slow. but I'd still m-x it for advanced replacements +;; ;;(define-key global-map [remap isearch-forward-regexp] 'foreign-regexp/isearch-forward) + + +;; saner regex syntax +(require 're-builder) +(setq reb-re-syntax 'string) + + +;; use shift + arrow keys to switch between visible buffers +;; todo, set these keys to something else +(require 'windmove) +(windmove-default-keybindings) + + +;; show the name of the current function definition in the modeline +(require 'which-func) +(setq which-func-modes t) +(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) +(add-hook 'text-mode-hook 'turn-on-flyspell) + + +;; auto indent shell script comments +(setq sh-indent-comment t) + +;; random extra highlights +(require 'volatile-highlights) +(volatile-highlights-mode t) + + +;; make help buffers smaller when it makes sense +(temp-buffer-resize-mode 1) + + +(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) + + +(require 'smooth-scroll) +;; long gnus summary buffers lags too much with this, +;; but I like it enough to leave it enabled by default +;; and crank up the step size to be faster +;; and it doesn't have a way to enable it only for certain modes etc. +;; todo sometime, make it work for certain modes only +(smooth-scroll-mode t) +;; its too slow with the default of 2 +(setq smooth-scroll/vscroll-step-size 7) +;; sublimity doesn't work as good going fast by default +;; smooth-scrolling.el, does not do smooth scrolling. its about cursor location + + +(setq sh-here-document-word "'EOF'") + +(setq tramp-default-method "ssh") +;;; misc general settings + +(ivy-mode 1) +(add-hook 'text-mode-hook (lambda () (auto-fill-mode t))) +(setq counsel-find-file-at-point t) + +;; easier to read with just spaces as separator +(setf (nth 2 ido-decorations) " ") + + +;; https://www.emacswiki.org/emacs/FillParagraph +;; make list items start paragraphs. +(setq paragraph-start "\f\\|[ \t]*$\\|[ \t]*[-+*] ") + +(setq sh-basic-offset 2) +(setq vc-follow-symlinks t) + +;; give us a shell to start instead of scratch +;;(setq initial-buffer-choice (lambda () (new-shell))) + +;; disable this nasty function, as I always use a gui +(defun suspend-frame() (interactive)) + +;; 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) +(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) + +;; i don't use frame titles, but if I ever do +;; this starter kit setting is probably good +(if window-system (setq frame-title-format '(buffer-file-name "%f" ("%b")))) + + +;;(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 + delete-by-moving-to-trash t + shift-select-mode nil + truncate-partial-width-windows nil + uniquify-buffer-name-style 'forward + oddmuse-directory "~/.emacs.d/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 '(".*") + ;; don't pause display code on input. + ;; smoother display performance at slight cost of input performance + redisplay-dont-pause t + 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 '(-4)) +(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 + compilation-read-command nil ;; just don't compile with unsafe file local vars + 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 + (beginning-of-buffer) + (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 "%b") + + ; ----------------------------- + ; fixing up the mode line + ; modified from mastering emacs blog + ; ---------------------------- + +(defvar mode-line-cleaner-alist + `((auto-complete-mode . "") + (yas/minor-mode . "") + (paredit-mode . "") + (auto-fill-function . "") + (eldoc-mode . "") + (abbrev-mode . "") + (flyspell-mode . "") + (glasses-mode . "") + (dot-mode . "") + (yas-global-mode . "") + (yas-minor-mode . "") + (volatile-highlights-mode . "") + (highlight-symbol-mode . "") + ;; Major modes + (lisp-interaction-mode . "λ") + (hi-lock-mode . "") + (python-mode . "Py") + (emacs-lisp-mode . "EL") + (nxhtml-mode . "nx")) + "Alist for `clean-mode-line'. + + When you add a new element to the alist, keep in mind that you + must pass the correct minor/major mode symbol and a string you + want to use in the modeline *in lieu of* the original.") + + +(defun clean-mode-line () + (interactive) + (loop for cleaner in mode-line-cleaner-alist + do (let* ((mode (car cleaner)) + (mode-str (cdr cleaner)) + (old-mode-str (cdr (assq mode minor-mode-alist)))) + (when old-mode-str + (setcar old-mode-str mode-str)) + ;; major mode + (when (eq mode major-mode) + (setq mode-name mode-str))))) + + ; disabled + ; (add-hook 'after-change-major-mode-hook 'clean-mode-line) + + + ;;; alias the new `flymake-report-status-slim' to + ;;; `flymake-report-status' +(defalias 'flymake-report-status 'flymake-report-status-slim) +(defun flymake-report-status-slim (e-w &optional status) + "Show \"slim\" flymake status in mode line." + (when e-w + (setq flymake-mode-line-e-w e-w)) + (when status + (setq flymake-mode-line-status status)) + (let* ((mode-line " Φ")) + (when (> (length flymake-mode-line-e-w) 0) + (setq mode-line (concat mode-line ":" flymake-mode-line-e-w))) + (setq mode-line (concat mode-line flymake-mode-line-status)) + (setq flymake-mode-line mode-line) + (force-mode-line-update))) + + +(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))) + +;;;; keybinds for wow mouse + +(global-set-key (kbd "") 'move-mouse-to-point) +(global-set-key (kbd "") 'indent-region) +(global-set-key (kbd "") 'mark-defun) +(global-set-key (kbd "") 'ibuffer) +(global-set-key (kbd "") 'delete-horizontal-space) + +;;; org mode + +;; todo work on org-cycle-emulate-tab + +;; 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-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 + org-catch-invisible-edits 'smart) + +;; non universally recommended settings +(setq + org-default-notes-file (concat org-directory "/a/t.org") + org-agenda-files (quote ("/a/t.org")) + org-mobile-directory "/p/org-mobile" + org-mobile-inbox-for-pull "/p/from-mobile.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) +;; + +(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") + (string= (buffer-file-name) "/home/iank/.emacs.d/my-init.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)) + +(defun ian-org-work-time () + (interactive) + (save-excursion + (set-buffer "t.org") + (goto-char (org-find-entry-with-id "ian-identifier-1")) + (org-clock-in))) + +(defun ian-org-idle-time () + (interactive) + (save-excursion + (goto-char (org-find-entry-with-id "ian-identifier-2")) + (set-buffer "t.org") + (org-clock-in))) + + + +;; 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) + + +(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)) + + +(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) + ;; 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) + (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) + +;; enable flyspell in prog mode. text mode is handled +(add-hook 'prog-mode-hook 'flyspell-prog-mode) + + + +;;; 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 +;; 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) +;;; smartparens +;; the melpa git version had a catastrophic bug I reported. +;; downgraded to marmalade version and everything is working fine. +(require 'smartparens-config) +(show-smartparens-global-mode t) + + +(defun gp/sp/pair-on-newline-and-indent (id action context) + "Open a new brace or bracket expression, with relevant newlines and indent. " + (save-excursion + (newline) + (indent-according-to-mode)) + (indent-according-to-mode)) + +;; when opening a pair, and then inserting a newline, push the closing pair to another newline +(sp-pair "{" nil :post-handlers + '(:add ((lambda (id action context) + (gp/sp/pair-on-newline-and-indent id action context)) (kbd "")))) +(sp-pair "[" nil :post-handlers + '(:add ((lambda (id action context) + (gp/sp/pair-on-newline-and-indent id action context)) (kbd "")))) + + +;; in my version, this is not a pairing. +;; not sure if it is in a future version since I reverted to marmalade +;; Don't need c-comments in strings -- they frustrate filename globs +;; (sp-pair "/*" nil :unless '(sp-in-string-p)) + +;; Don't need quotes to pair next to words +(sp-pair "\"" nil :unless '(sp-point-before-word-p sp-point-after-word-p)) +(sp-pair "'" nil :unless '(sp-point-before-word-p sp-point-after-word-p)) + + +;; todo, testout these mode specific settings from graphene. +;; Ruby-specific pairs and handlers +(require 'smartparens-ruby) + +;; Markdown +(sp-local-pair '(markdown-mode gfm-mode) "*" "*" + :unless '(sp-in-string-p) + :actions '(insert wrap)) + +;; Except in HTML +(sp-local-pair 'html-mode "\"" nil :unless '(:rem sp-point-after-word-p)) + + +;;; smex +;; todo; check out smex-show-unbound-commands shows frequently used commands that have no key bindings. + ; these must be before smex-initialize +(setq + smex-save-file "~/.emacs.d/.smex-items") + +(smex-initialize) +;;; spell correction +(setq + ispell-program-name "hunspell" + ispell-silently-savep t) ; don't prompt to save personal dictionary + +(require 'rw-hunspell) +;; rw-hunspell sets up hunspell dictionary automagically. + + +;; 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 +(setq-default TeX-PDF-mode t) ; use pdf + + ; more sensible defaults based on info manual quickstart +(setq TeX-auto-save t) +(setq TeX-parse-self t) + + + +;;; 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)) +(setq visible-mark-forward-faces '(visible-mark-forward-face1)) + + + ; highlight the last 2 marks +(setq visible-mark-max 2) + ; highlight 1 forward mark +(setq 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 + + +;;; zrc +(require 'znc) +(setq erc-fill-prefix "") +(defun chirp() + (interactive) + (setq vol 50) + (when (string= (system-name) "tp") (setq vol 40)) + (start-process-shell-command "ignoreme" nil (format "mpv --no-terminal --vo=null --volume=%d /a/bin/data/bird.mp3" vol))) +;; from https://www.emacswiki.org/emacs/ErcSound + +(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))) + +(add-hook 'erc-server-PRIVMSG-functions + 'erc-my-privmsg-sound) + +(defun erc-sound-if-not-server (match-type nickuserhost msg) + (unless (string-match "Server:[0-9]+" nickuserhost) + (chirp))) +(add-hook 'erc-text-matched-hook 'erc-sound-if-not-server) + +(erc-track-mode 1) +(setq + ;; 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) + + +;;; 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 . ,"~/.emacs.d/my-init.org")) + (?t (file . ,"/a/t.org")) + (?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 + +;;; keybinds + +;;;; misc +(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 +(define-key isearch-mode-map (kbd "") '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 "\t" nil) +(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 +(global-set-key (kbd "") 'indent-buffer) +;;;;; 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 - shell +(global-set-key (kbd "") 'shell-wrap) +(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 + ; 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 "") '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-down 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 + +;;;;; C-2 copy-symbol + +(global-unset-key (kbd "C-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-2") 'copy-symbol) + +;;;;; 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 --- + ; todo. whats going on here? +(global-unset-key (kbd "C-M-2")) + +;;;;; C-3 dot-mode-execute + +(global-set-key (kbd "C-3") 'dot-mode-execute) + +;;;;; C-M-3 recenter-top-bottom + +(global-set-key (kbd "C-M-3") 'recenter-top-bottom) + +;;;;; C-q org-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-archive-to-archive-sibling + +(global-set-key (kbd "M-q") 'org-archive-to-archive-sibling) + +;;;;; C-M-q quoted-insert + +(global-set-key (kbd "C-M-q") 'quoted-insert) + +;;;;; C-w --- +;; in terminal, it's ctrl-backspace, duplicate keybind. +;;;;; M-w org-clock-in + +(global-set-key (kbd "M-w") 'org-clock-in) + +;;;;; 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 org-clock-in-last + +(global-set-key (kbd "M-e") 'org-clock-in-last) + +;;;;; 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 org-clock-out + +(global-set-key (kbd "M-r") 'org-clock-out) + +;;;;; 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 +;;;;; C-M-d - swap buffer across windows +;; from http://www.emacswiki.org/emacs/TransposeWindows + +(setq swapping-buffer nil) +(setq swapping-window nil) +(defun swap-buffers-in-windows () + "Swap buffers between two windows" + (interactive) + (if (and swapping-window + swapping-buffer) + (let ((this-buffer (current-buffer)) + (this-window (selected-window))) + (if (and (window-live-p swapping-window) + (buffer-live-p swapping-buffer)) + (progn (switch-to-buffer swapping-buffer) + (select-window swapping-window) + (switch-to-buffer this-buffer) + (select-window this-window) + (message "Swapped buffers.")) + (message "Old buffer/window killed. Aborting.")) + (setq swapping-buffer nil) + (setq swapping-window nil)) + (progn + (setq swapping-buffer (current-buffer)) + (setq swapping-window (selected-window)) + (message "Buffer and window marked for swapping.")))) + +(global-set-key (kbd "C-M-d") 'swap-buffers-in-windows) + +;;;;; 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 - cancel / other window + +(global-set-key (kbd "C-g") 'other-window) + +;;;;; M-g - abort-recursive-edit + +(global-set-key (kbd "M-g") 'abort-recursive-edit) + +;;;;; C-M-g - gnus + +(global-set-key (kbd "C-M-g") 'mu4e) + +;;;;; C-z - undo-only + +(global-set-key (kbd "C-z") 'undo-only) + +;;;;; C-x - kill-region + +(global-set-key (kbd "C-s") 'kill-region) + +;;;;; M-x - smex + +(global-set-key (kbd "M-x") 'smex) + +;;;;; 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-hook + (lambda () (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 - org-capture + +(define-key global-map "\M-c" 'org-capture) + +;;;;; 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) + + + +(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 - delete-other-windows + +(global-set-key (kbd "C-b") 'delete-other-windows) + +;;;;; 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 + +(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 +;;;;; C-* - split-window-horizontally + +(global-set-key (kbd "C-*") 'split-window-horizontally) + +;;;;; C-M-* - calc-dispatch + +(global-set-key (kbd "C-M-*") 'calc-dispatch) + +;;;;; C-9 - delete-window-or-exit + +(global-set-key (kbd "C-9") '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)))) + +;;;;; 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 - ----- +;;;;; 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) + (define-key ido-common-completion-map (kbd "C-j") 'ido-select-text) + (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-m - recursive grep + + (define-key global-map (kbd "C-M-m") 'rgrep) + +;;;;; C-, - ounsel-find-file + + (global-set-key (kbd "C-,") 'counsel-find-file) + (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 +;; Taken from starter kit. + + (defun recentf-ido-find-file () + "Find a recent file using Ido." + (interactive) + (let* ((file-assoc-list + (mapcar (lambda (x) + (cons (file-name-nondirectory x) + x)) + recentf-list)) + (filename-list + (remove-duplicates (mapcar #'car file-assoc-list) + :test #'string=)) + (filename (ido-completing-read "Choose recent file: " + filename-list + nil + t))) + (when filename + (find-file (cdr (assoc filename + file-assoc-list)))))) + + (add-hook 'flyspell-mode-hook + (lambda () (define-key flyspell-mode-map (kbd "C-.") nil))) + (define-key dot-mode-map (kbd "C-.") nil) + (global-set-key (kbd "C-.") 'recentf-ido-find-file) + (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))) + (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-8 - calc-embedded-word + + (global-set-key (kbd "C-8") 'calc-embedded-word) + +;;;;; 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 + + (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)) + (global-set-key (kbd "") 'newline-anywhere) + + +;;;;; M-return - plain newline + + (defun plain-newline () + (interactive) + (insert "\n")) + (global-set-key (kbd "") 'plain-newline) + + +;;;;; C-M-return - newline-anywhere-previous +(defun newline-anywhere-previous () + "Add a newline from anywhere in the line." + (interactive) + (forward-line -1) + (end-of-line) + (newline-and-indent)) +(global-set-key (kbd "") 'newline-anywhere-previous) + +;;;;; 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-6 - save-buffers-kill-emacs + +(global-set-key (kbd "C-6") 'save-buffers-kill-emacs) + +;;;;; C-M-6 - insert-small-copyright + +(defun insert-small-copyright () + (interactive) + (beginning-of-line) + (let ((beg (point))) + (insert "Copyright (C) 2017 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) + +;;;;; C-M-7 - insert-full-copyright + +(defun insert-full-copyright () + (interactive) + (beginning-of-line) + (let ((beg (point))) + (insert "Copyright (C) 2017 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) +(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 - (load-file (expand-file-name "myinit.el" init-dir)) +(global-set-key (kbd "C-M-n") 'narrow-to-region) - )) +;;;;; C-escape - find-tag -;;init.el ends here +(global-set-key (kbd "") 'find-tag) diff --git a/myinit.el b/myinit.el deleted file mode 100644 index 5c5d102..0000000 --- a/myinit.el +++ /dev/null @@ -1,3568 +0,0 @@ -;;; copyright - -;; Copyright (C) 2019 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 -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with this program. If not, see . - -;;; Weird package bug workaround - - -;; without this, when installing a package, this message happens -;; -;; custom-handle-keyword: Unknown keyword :group -;; -;; but when i lookup the function, i get the following, and if -;; I evaluate it, the error goes away. so I think the real -;; definition is happening somewhere else - -(defun custom-handle-keyword (symbol keyword value type) - "For customization option SYMBOL, handle KEYWORD with VALUE. -Fourth argument TYPE is the custom option type." - (if purify-flag - (setq value (purecopy value))) - (cond ((eq keyword :group) - (custom-add-to-group value symbol type)) - ((eq keyword :version) - (custom-add-version symbol value)) - ((eq keyword :package-version) - (custom-add-package-version symbol value)) - ((eq keyword :link) - (custom-add-link symbol value)) - ((eq keyword :load) - (custom-add-load symbol value)) - ((eq keyword :tag) - (put symbol 'custom-tag value)) - ((eq keyword :set-after) - (custom-add-dependencies symbol value)) - (t - (error "Unknown keyword %s" keyword)))) - - -;;; 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 ~/.dribble (or something) - - -;;;;; 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 -;; todo, evaluating this manually disables debug on error instead of toggling it -(toggle-debug-on-error) ;uncomment to help debug and catch errors - -;; packages installed from package manager: i pretty much prioritize repos this way: gnu, then melpa, then marmalade. - -;; package-activated-list: -;; ac-dabbrev ac-haskell-process ack-and-a-half alect-themes auctex bash-completion bbdb csv-mode cyberpunk-theme dot-mode expand-region f find-file-in-project flycheck foreign-regexp ggtags ghc gnuplot-mode goto-chg haskell-mode heroku-theme highlight-indentation highlight-symbol htmlize inf-ruby info+ inkpot-theme jedi auto-complete jedi-core epc ctable concurrent key-chord leuven-theme logstash-conf magit git-commit magit-popup misc-fns mouse+ naquadah-theme nginx-mode occidental-theme org paredit pcsv php-mode pkg-info epl popup py-autopep8 python-environment deferred python-info python-mode rainbow-mode rust-mode rw-hunspell s smartparens smex smooth-scroll sr-speedbar strings swiper ivy tabulated-list tangotango-theme thingatpt+ undo-tree vimrc-mode volatile-highlights web-mode with-editor dash async ws-butler yasnippet - -;;;; alternate keyboards -;; todo, figure out an easy way to disable this when using external keyboard -(if (display-graphic-p) - (setq - enter-key (kbd "") - s-enter-key (kbd "") - c-m-enter-key (kbd "") - m-enter (kbd "") - c-enter (kbd "")) - (setq - enter-key (kbd "C-m") - s-enter-key (kbd "C-8") - c-m-enter-key (kbd "C-M-8") - m-enter (kbd "M-m") - c-enter (kbd "C-8"))) - -(setq tp (string= (system-name) "tp")) -(setq x200 (string= (system-name) "x2")) -(setq laptop-keyboard (or tp x200)) - -;; Ubiquitous Packages which should be loaded on startup rather than -;; autoloaded on demand since they are likely to be used in every -;; session. -(require 'saveplace) -(require 'ffap) -(require 'uniquify) -(require 'ansi-color) -(require 'recentf) - -;; Better to have a list of packages in here vs installed manually. -;; However, I install manually because sometimes there are two -;; versions and it is not necessarily easy to reconcile that. -;; based on marmalage website front page. -(require 'package) - -;; little kit to help remove a down server -;; (setq package-archives nil) - -;;(add-to-list 'package-archives -;; '("marmalade" . -;; "http://marmalade-repo.org/packages/")) - -(add-to-list 'package-archives - '("melpa" . "http://melpa.milkbox.net/packages/") t) -(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 "~/.emacs.d/custom.el") -(load custom-file 'noerror) - - - -;;; abreviations -;; turn on abbrev mode globally -(setq-default abbrev-mode t) - -;; default abbreviation mode file is .emacs.d/abbrev_defs. -;; add-global-abbrev, add-mode-abbrev for expansion at point -;; if all else fails, edit the abbrev file - - - - -;;; auto-complete - -;; auto-completion in minibuffer -;; disabled while I look for another alternative -;;(icomplete-mode) - -(require 'auto-complete-config) -(ac-config-default) - - -;; complete after 1 char instead of default 2 -(setq ac-auto-start 1) -(setq ac-delay 0.001) - -(add-to-list 'ac-modes 'org-mode 'sql-mode) - -(defun ac-common-setup () - (add-to-list 'ac-sources 'ac-source-yasnippet)) - -;; 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) - - - -;;; 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))) - - -;;; readline complete fix - -;; I need this function here, where INSIDE_EMACS is replaced with RLC_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 "RLC_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 & backup -(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 -(setq 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 (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 on)) - -;; 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) - -;; 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) (* 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 - -;;; bbdb -;; based on bbdb manual -;; also has instructions to integrate with gnus, - -(bbdb-initialize 'message) - -;; recommended by gnus, -;; but seems like it could be good to have set for other stuff -(setq user-full-name "Ian Kelling") -;; general email setting? recommended by mu4e -(setq message-kill-buffer-on-exit t) - - - -;; use d instead -(add-hook 'bbdb-mode-hook - (lambda () (define-key bbdb-mode-map (kbd "C-k") nil)) - ;; based on emacs24-starter-kit - (setq bbdb-offer-save 'auto - bbdb-notice-auto-save-file t - bbdb-expand-mail-aliases t - bbdb-canonicalize-redundant-nets-p t - bbdb-complete-name-allow-cycling t) - ) - -;;(require 'bbdb-csv-import) - -;;; bookmark settings - ; save bookmarks whenever they are changed instead of just when emacs quits -(setq bookmark-save-flag 1) - ; increase bookmark context size for better functionality -(setq bookmark-search-size 2000) - -;;; c-like settings -;; change last thing from gnu. -;; notably this avoids brace indent after if, and 4 space indent -(setq c-default-style '((java-mode . "java") - (awk-mode . "awk") - (other . "stroustrup"))) -;; for emacs itself, use -;; (setq c-default-style '((java-mode . "java") -;; (awk-mode . "awk") -;; (other . "gnu"))) -;; (setq-default c-basic-offset 2) - -;;; 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. - - -;; interesting light themes - - -(defun override-theme (arg) - (interactive) - (while custom-enabled-themes - (disable-theme (car custom-enabled-themes))) - (load-theme arg t)) -(setq color-theme-is-global t) - -(defun toggle-night () - (interactive) - (cond ((equal (car custom-enabled-themes) 'naquadah) - (override-theme 'leuven)) - (t - (override-theme 'naquadah)))) - - -;; 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")))) -(override-theme 'leuven) - - -;; 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) - - - - -;;; yasnippet - -;; cd ~/.emacs.d/src -;; git clone --recursive https://github.com/capitaomorte/yasnippet -;; touch snippets/.yas-make-groups - -;; This all makes it so I can look through the default snippets -;; in the menu bar, but they don't show up elsewhere, because they are -;; mostly things I don't want. - - -(require 'yasnippet) -;; this needs to be before yas-global-mode -(setq yas-snippet-dirs (list "~/.emacs.d/snippets")) -(yas-global-mode 1) - -(setq - yas-also-auto-indent-first-line t - yas-choose-tables-first t - yas-use-menu (quote full) - ;; this sets ido-prompt as first function - yas-prompt-functions - '(yas-ido-prompt yas-dropdown-prompt yas-x-prompt yas-completing-prompt yas-no-prompt)) - -;; todo, explore this option for wrapping region -;; '(yas/wrap-around-region t)) - -;;; cross session settings - -;; Save a list of recent files visited. -(recentf-mode 1) -(setq recentf-max-saved-items 200 - recentf-max-menu-items 15) - - -(setq save-place t - save-place-version-control 'nospecial - save-place-limit 40000 - save-place-file "~/.emacs.d/places") - - - -;; savehist keeps track of some history -;; search entries -(setq savehist-additional-variables '(kill-ring search-ring regexp-search-ring) - ;; save every minute - savehist-autosave-interval 60 - ;; keep the home clean - savehist-file "~/.emacs.d/.savehist") -(savehist-mode 1) - - -;;; ediff -;; ediff-buffers is the main command to use - -;; ediff - 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 -(setq ediff-window-setup-function 'ediff-setup-windows-plain) -;;(setq ediff-window-setup-function 'ediff-setup-windows-default) - -;; do side by side diffs -(setq ediff-split-window-function 'split-window-horizontally) - - - -;; 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. - -;;; dired - -;; dired - reuse current buffer by pressing 'a' -(put 'dired-find-alternate-file 'disabled nil) - -;;; mu4e - -;; alsot tried notmuch, it had some glitches, and it's config has a list -;; of folders which i'd rather not publish, so it's config is archived. - -;;(add-to-list 'load-path "/usr/local/share/emacs/site-lisp/mu4e") -;;(add-to-list 'load-path "/usr/share/emacs/site-lisp/mu4e") -(require 'mu4e) - -;; (setq mu4e-headers-results-limit 2000) - -(setq - ;; common to gnus. default sendmail-query-once asks us, then sets this via customize. - send-mail-function (quote sendmail-send-it) - ;; use the standard imap folders - mu4e-sent-folder "/Sent" - mu4e-drafts-folder "/Drafts" - mu4e-trash-folder "/Trash" - ;; reindex new mail this often in seconds - ;; show addresses instead of just names - mu4e-view-show-addresses t - mu4e-use-fancy-chars t - mu4e-confirm-quit nil - mu4e-headers-leave-behavior 'apply ;; dont ask, do whatever was marked - mu4e-headers-fields (delq (assoc :mailing-list mu4e-headers-fields) mu4e-headers-fields) - ;; default 500. - mu4e-headers-results-limit 1000 - ;; tell exim to use from: as envelope from. - ;; exim's default is use outgoing_msg_localpart@hostname. - mail-specify-envelope-from t - - ;; looking up the list of maildirs when doing jo from summary - ;; can take a few seconds if we have a ton of messages. - ;; Only take that time for the first lookup. - ;; if we add a new maildir, just restart mu4e for it to be in that list. - mu4e-cache-maildir-list t - ;; default is 8, way too small for my big monitors - mu4e-headers-visible-lines 50 - ) - -;; fucks up reading unread bookmark. when that is fixed, enable it -;; (setq mu4e-update-interval 60) - - -;; 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. -(load "/p/c/mu4e.el") - -(defun my-decrypt () - ;; use for decrypting in mu4e - (interactive) - (beginning-of-buffer) - (when (search-forward "-----BEGIN PGP MESSAGE-----" nil t) - (read-only-mode 0) - (let ((start (match-beginning 0)) - (end (search-forward "-----END PGP MESSAGE-----" nil t))) - (shell-command-on-region start end "gpg2 -dq" nil t shell-command-default-error-buffer t) - ))) -(add-hook 'mu4e-view-mode-hook 'my-decrypt) - -(defun mu-set-from-name (regexes) - "If we find an address matching regex, then set that address as the to, -and whatever was used" - (when mu4e-compose-parent-message - (let ((found nil)) - (while (and regexes (not found)) - (setq re (car regexes) - regexes (cdr regexes) - found (mu4e-message-contact-field-matches - mu4e-compose-parent-message :to re))) - (when found (setq user-mail-address (cdr found) - user-full-name (car found))) - found))) -(defun mu-set-from (regexes) - "If we find an address matching regex, then set that address as the to, -and Ian Kelling as the name" - (when mu4e-compose-parent-message - (let ((found nil)) - (while (and regexes (not found)) - (setq re (car regexes) - regexes (cdr regexes) - found (cdr (mu4e-message-contact-field-matches - mu4e-compose-parent-message :to re)))) - (when found (setq user-mail-address found - user-full-name "Ian Kelling")) - found))) - - -(defun my-mu4e-to-fsf () - "inspired by mu4e info manual, search for mu4e-compose-pre-hook." - (cond - ((mu-set-from '("iank@fsf.org" - "iank@gnu.org"))) - ((setq user-mail-address "iank@fsf.org" - user-full-name "Ian Kelling")))) - - -;; on first run mkdir -p /nocow/user/.mufsf; mu index --maildir=/nocow/user/fsfmd -(defun mu-exit-wait () - (interactive) - ;; taken from the mu source - (let* ((buf (get-buffer mu4e~proc-name)) - (proc (and (buffer-live-p buf) (get-buffer-process buf)))) - (mu4e-quit) - ;; without sleep, we get database locked by another process error when hitting u - ;; if another mu was running. - (if proc (sleep-for 0 1000)))) - -(defun fsf-mu4e () - (interactive) - (unless (equal mu4e-maildir "/nocow/user/fsfmd") (mu-exit-wait)) - (setq - ;; fsf monitor is smaller - mu4e-headers-visible-lines 15 - mu4e-maildir "/nocow/user/fsfmd" - mu4e-refile-folder "/Spam" - mu4e-index-lazy-check nil - mu4e-get-mail-command "true" - user-mail-address "iank@fsf.org" - ;; WARNING: be careful editing this, there needs to be a space after --, and my editor - ;; and git will automatically remove it unless i manually disable it. - mail-signature " - --- -Ian Kelling | Senior Systems Administrator, Free Software Foundation -GPG Key: B125 F60B 7B28 7FF6 A2B7 DF8F 170A F0E2 9542 95DF -https://fsf.org | https://gnu.org -" - - mu4e-user-mail-address-list '("iank@fsf.org" - "iank@gnu.org") - mu4e-maildir-shortcuts - '( ("/INBOX" . ?i) - ("/sysadmin" . ?a) - ("/sec" . ?x) - ("/rtcc" . ?c) - ("/Drafts" . ?d) - ("/Sent" . ?s) - ) - ) ;; end setq - (call-process "/a/exe/lnf" nil nil nil "-T" "/nocow/user/.mufsf" (concat (getenv "HOME") "/.mu")) - (add-hook 'mu4e-compose-pre-hook 'my-mu4e-to-fsf) - (remove-hook 'mu4e-compose-pre-hook 'my-mu4e-to) - (mu4e)) ;; end defun fsf-mu4e - - -;; it's implemented in mu4e, but not in the actions list for -;; some reason. -(add-to-list 'mu4e-view-actions - '("browser view" . mu4e-action-view-in-browser) t) - -;; normally, you would add to this, but we want to -;; modify unread messages. the first 4 are defined by default. -(setq mu4e-bookmarks - `( ,(make-mu4e-bookmark - :name "Unread messages" - ;; old less restrictive unread, for adapting in the future: - ;; flag:unread AND NOT flag:trashed AND NOT maildir:/Junk AND NOT maildir:/fwfw AND NOT maildir:/log - :query "flag:unread maildir:/INBOX" - :key ?u) - ,(make-mu4e-bookmark - :name "Today's messages" - :query "date:today..now" - :key ?t) - ,(make-mu4e-bookmark - :name "Last 7 days" - :query "date:7d..now" - :key ?w) - ,(make-mu4e-bookmark - :name "Messages with images" - :query "mime:image/*" - :key ?p)) - ) - - -(defun mu4e-action-msgs-by-this-sender (msg) - "In header view, view messages by the sender of the message under point." - (let ((from (mu4e-message-field msg :from))) - (unless from - (mu4e-error "No from header for this message")) - ;; from is structured like: (("Anacron" . "root@x2.lan")) - (mu4e-headers-search (concat "f:" (cdar from))))) - -(add-to-list 'mu4e-headers-actions - '("from this sender" . mu4e-action-msgs-by-this-sender) t) -(add-to-list 'mu4e-view-actions - '("from this sender" . mu4e-action-msgs-by-this-sender) t) - - -;;; elisp settings - ; when manually evaluating lisp, go into debugger on error -(setq eval-expression-debug-on-error t) - ;reminder of useful var: debug-on-error - - -;;; haskell - -;; useful comint-shell mode commands. If not prefaced with *, it means it is not in the haskell custom repl -;; *todo: setup haskell c-t toggle arrow keys -;; tab completion -;; C-q insert prev arg -;; C-( history search -;; c-m-left/right move to next/prev prompts -;; *c-enter, multi-line input -;; *s-delete, send input across windows. (i can implement this) -;; *c-m-l clear screen -;; *haskell-process-interrupt, c-cc terminate job (i can implement this maybe) - -;; nice bash/readline functions missing in comint: -;; yank-nth-arg -;; operate-get-next -;; menu-complete - -;; usefull comint commands: -;; c-cl : list historic command in temp buffer -;; C-c C-o comint-delete-output -;; comint-restore-input, todo: put this on a randomish c-c key - - - -;; todo: -;; checkout haskell repl functions: -;; c-cv haskell-check, hlint -;; C-M-q prog-indent-sexp -;; c-c. haskell-mode-format-imports -;; C-c M-/ haskell-doc-check-active -;; haskell-process-generate-tags -;; haskell-process-cabal-build -;; haskell-cabal-command.. or something -;; haskell-process-restart -;; C-h v haskell-process-log -;; C-h v haskell-process-show-debug-tips - -;; various not immediately useful functions: -;; haskell-process-add-dependency -;; haskell-process-touch-buffer -;; haskell-process-cd -;; haskell-process-unignore -;; haskell-process-reload-devel-main - - -;; rebind -;; home: C-a haskell-interactive-mode-beginning -;; c-return: C-j haskell-interactive-mode-newline-indent -;; up/down: haskell-interactive-mode-history-next - -;; todo haskell mode better binds for: -;; 'haskell-process-load-file -;; 'haskell-process-do-type -;; 'haskell-process-do-info -;; 'inferior-haskell-send-decl - - -;; commands which don't work in haskell-interactive-mode(hi) vs inferior-haskell-mode(ih, default) -;; functions not in hi: -;; inferior-haskell-find-definition, use tags instead -;; inferior-haskell-find-haddock, todo, test if this works - -;; redefined ih to hi -;; switch-to-haskell -> 'haskell-interactive-switch -;; haskell-process-load-file -> inferior-haskell-load-file -;; haskell-process-do-type -> inferior-haskell-type -;; switch-to-haskell -> haskell-interactive-switch -;; inferior-haskell-load-file -> 'haskell-process-load-file - - -;; haskell-mode installation from source, based on its readme -;; in the git directory, -;; make all - - - - -;; remove default option to not link the file -(setq haskell-compile-command "ghc -Wall -ferror-spans -fforce-recomp %s") -(add-hook 'haskell-indentation-mode-hook - (lambda () - (define-key haskell-indentation-mode-map [?\C-d] nil) - (define-key haskell-indentation-mode-map - (kbd "") - 'haskell-indentation-delete-char))) - -;;copied from haskell-mode docs in order to use the new, better, nondefault -;;interactive mode. -(eval-after-load "haskell-mode" - '(progn - (define-key haskell-mode-map (kbd "C-x C-d") nil) - (define-key haskell-mode-map (kbd "C-c C-z") 'haskell-interactive-switch) - (define-key haskell-mode-map (kbd "C-c C-l") 'haskell-process-load-file) - (define-key haskell-mode-map (kbd "C-c C-b") 'haskell-interactive-switch) - (define-key haskell-mode-map (kbd "C-c C-t") 'haskell-process-do-type) - (define-key haskell-mode-map (kbd "C-c C-i") 'haskell-process-do-info) - (define-key haskell-mode-map (kbd "C-c M-.") nil) - (define-key haskell-mode-map (kbd "C-c C-d") nil))) - -;; ghc-mod install http://www.mew.org/~kazu/proj/ghc-mod/en/emacs.html -;; todo, try this out -;; (autoload 'ghc-init "ghc" nil t) -;;(add-hook 'haskell-mode-hook (lambda () (ghc-init) (flymake-mode))) - - - -;; from the package readme for ghci-completion -(require 'ghci-completion) -(add-hook 'inferior-haskell-mode-hook 'turn-on-ghci-completion) - - -;; disable some rebinds. they are set to appropriate keys in the keybinds section -(eval-after-load "haskell-mode" - '(progn - (define-key haskell-mode-map (kbd "C-a") 'nil) - (define-key haskell-mode-map (kbd "C-j") 'nil))) - -(eval-after-load "python-mode" - '(progn - (define-key python-mode-map (kbd "C-j") nil))) - -(defun pretty-lambdas-haskell () - (font-lock-add-keywords - nil `((,(concat "(?\\(" (regexp-quote "\\") "\\)") - (0 (progn (compose-region (match-beginning 1) (match-end 1) - ,(make-char 'greek-iso8859-7 107)) - nil)))))) -;; from haskell-mode manual -(add-hook 'haskell-mode-hook 'turn-on-haskell-decl-scan) -(when (window-system) - (add-hook 'haskell-mode-hook 'pretty-lambdas-haskell)) - -;; added from haskell-mode website install instructions - ;(load "/usr/share/emacs/site-lisp/haskell-mode/haskell-site-file") -(add-hook 'haskell-mode-hook 'turn-on-haskell-doc-mode) -;;the three indentation modules are mutually exclusive - add at most one. Trying out the "most advanced" -(add-hook 'haskell-mode-hook 'turn-on-haskell-indentation) -;;(add-hook 'haskell-mode-hook 'turn-on-haskell-indent) -;;(add-hook 'haskell-mode-hook 'turn-on-haskell-simple-indent) - - -;; todo, set this to some other key -;; (local-set-key (kbd "C-e") 'my-haskell-load-and-run) - -(defun my-haskell-load-and-run () - "Loads and runs the current Haskell file." - (interactive) - (let ((start-buffer (current-buffer))) - (inferior-haskell-load-and-run inferior-haskell-run-command) - (sleep-for 0 100) - (end-of-buffer) - (pop-to-buffer start-buffer))) - -;; show haskell function in mode line -;; todo, this broke after updating emacs -;;(eval-after-load "which-func" -;; '(add-to-list 'which-func-modes 'haskell-mode)) - - - -(add-hook 'interactive-haskell-mode-hook 'ac-haskell-process-setup) -(add-hook 'haskell-interactive-mode-hook 'ac-haskell-process-setup) -(eval-after-load "auto-complete" - '(add-to-list 'ac-modes 'haskell-interactive-mode)) - -(add-hook 'haskell-mode-hook - (lambda () (define-key haskell-mode-map (kbd "C-(") - (lambda () (interactive) - (basic-save-buffer) - (haskell-compile) - (run-with-timer .3 nil 'repeat-shell))))) -(add-hook 'haskell-cabal-mode-hook - (lambda () (define-key haskell-cabal-mode-map (kbd "C-(") 'haskell-compile))) - - - -(add-hook 'haskell-interactive-mode-hook - (lambda () - (define-key haskell-interactive-mode-map "\r" nil) - (define-key haskell-interactive-mode-map (kbd "") 'haskell-interactive-mode-return))) -(add-hook 'haskell-indentation-mode-hook (lambda () (define-key haskell-indentation-mode-map "\r" nil))) - - - -(add-hook 'haskell-interactive-mode-hook - (lambda () - (define-key haskell-interactive-mode-map (kbd "") 'haskell-interactive-mode-newline-indent))) - -;;; 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))) - - - - ; lets look through emacs starter kit before we throw this out. - - - ; 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)) -(setq prelude-interactive-lisp-coding-hook 'prelude-interactive-lisp-coding-defaults) - - -;; ielm is an interactive Emacs Lisp shell -(defun ielm-mode-defaults () - (run-hooks 'prelude-interactive-lisp-coding-hook) - (turn-on-eldoc-mode)) -(add-hook 'ielm-mode-hook 'ielm-mode-defaults) - -;;; mediawiki - -(eval-after-load "mediawiki" - '(progn - (remove-hook 'outline-minor-mode-hook 'mediawiki-outline-magic-keys) - (add-hook 'mediawiki-mode-hook - (lambda () (define-key mediawiki-mode-map (kbd "C-(") 'mediawiki-save-reload))) - - ;; mediawiki mode has a bug that it will claim an edit conflict unless you reload after saving. - ;; I also like to save with no edit summary for previewing on my local mw instance - (defun mediawiki-save-reload () - (interactive) - (and (mediawiki-save "") (mediawiki-reload))))) -;;; modes with little configuration needed -;; busted: -;;(require 'csv-mode) -;;(add-to-list 'auto-mode-alist '("\\.[Cc][Ss][Vv]\\'" . csv-mode)) - -(require 'outshine) -(add-hook 'outline-minor-mode-hook 'outshine-mode) -(add-hook 'emacs-lisp-mode-hook 'outline-minor-mode) -(add-hook 'sh-mode-hook 'outline-minor-mode) - - - -(setq org-caldav-url "https://cal.iankelling.org" - org-caldav-calendar-id "ian" - org-caldav-inbox "/p/cal.org") -;;(org-caldav-sync) - - -;;(require 'dtrt-indent) -;;(setq dtrt-indent-mode t) - -(setq css-indent-offset 2) - -(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 -(add-to-list 'ws-butler-global-exempt-modes 'message-mode) - -(ws-butler-global-mode) - - - -(require '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) - -(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)))) -(defun tail-colorize () - (ansi-color-apply-on-region prev-auto-revert-max (point-max)) - (setq-local prev-auto-revert-max (point-max))) - - -;; gnu global -(require 'ggtags) -(add-hook 'c-mode-common-hook - (lambda () (ggtags-mode 1) - (setq c-label-minimum-indentation 0))) - -;; specific to my unusual keybind setup, you may want to -;; pick different keys -(define-key ggtags-mode-map (kbd "C-M-o") 'ggtags-find-tag-dwim) -(define-key ggtags-mode-map (kbd "C-M-m") 'ggtags-grep) - -(defun gtags-update-single(filename) - "Update Gtags database for changes in a single file" - (interactive) - (start-process "update-gtags" "update-gtags" "bash" "-c" (concat "cd " ggtags-project-root " ; gtags --single-update " filename ))) - -(defun gtags-update-current-file() - (interactive) - (let ((rel-filename (replace-regexp-in-string - ggtags-project-root "." - (buffer-file-name (current-buffer))))) - (gtags-update-single rel-filename))) - -(defun gtags-update-hook() - "Update GTAGS file incrementally upon saving a file" - (when (and ggtags-mode ggtags-project-root) - (gtags-update-current-file))) - -(add-hook 'after-save-hook 'gtags-update-hook) - -;; i'd like to make some elisp which modifies a keymap to remove -;; all binds which don't match a predicate. -;; I tried setting a keymap to a new keymap, -;; but that didn't register as functional. -;; so I'd need to modify the list in place. - -(require 'magit) - - -;; colorize hex colors: use rainbow mode - - -;; message mode prompted me on first message. -;; a function which describes options then sets this -;; the other options were to use smtp directly or pass to another mail client -;; here we use the standard sendmail interface, which I use postfix for -(setq send-mail-function (quote sendmail-send-it)) - -(require 'spray) -(global-set-key (kbd "C-M-w") 'spray-mode) -;; remember, h/l = move. f/s = faster/slower, space = pause, all others quit - -;; delete active selection with self-insert commands -(delete-selection-mode t) - -;; Transparently open compressed files -(auto-compression-mode t) - -;; Highlight matching parenthesesq when the pointq is on them. -;; not needed since smart paren mode? -;; (show-paren-mode 1) - - -;; 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. -(setq TeX-command-force "LaTeX") - -;; dot mode, repeats last action -(require 'dot-mode) -(add-hook 'find-file-hooks 'dot-mode-on) - - -;; clean up obsolete buffers automatically at midnight -(require 'midnight) - - -;; disabled because it takes 400ms on startup -;; ;; emacs regexes are too limited. -;; (require 'foreign-regexp) -;; ;; perl is most powerful, but javascript is pretty close and -;; ;; I'd rather know javascript stuff than perl -;; (custom-set-variables -;; '(foreign-regexp/regexp-type 'javascript) ;; Choose by your preference. -;; '(reb-re-syntax 'foreign-regexp)) ;; Tell re-builder to use foreign regexp. -;; ;; it would be nice to add documentation to do this for more commands to that package -;; ;; disabled because it's too slow. but I'd still m-x it for advanced replacements -;; ;;(define-key global-map [remap isearch-forward-regexp] 'foreign-regexp/isearch-forward) - - -;; saner regex syntax -(require 're-builder) -(setq reb-re-syntax 'string) - - -;; use shift + arrow keys to switch between visible buffers -;; todo, set these keys to something else -(require 'windmove) -(windmove-default-keybindings) - - -;; show the name of the current function definition in the modeline -(require 'which-func) -(setq which-func-modes t) -(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) -(add-hook 'text-mode-hook 'turn-on-flyspell) - - -;; auto indent shell script comments -(setq sh-indent-comment t) - -;; random extra highlights -(require 'volatile-highlights) -(volatile-highlights-mode t) - - -;; make help buffers smaller when it makes sense -(temp-buffer-resize-mode 1) - - -(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) - - -(require 'smooth-scroll) -;; long gnus summary buffers lags too much with this, -;; but I like it enough to leave it enabled by default -;; and crank up the step size to be faster -;; and it doesn't have a way to enable it only for certain modes etc. -;; todo sometime, make it work for certain modes only -(smooth-scroll-mode t) -;; its too slow with the default of 2 -(setq smooth-scroll/vscroll-step-size 7) -;; sublimity doesn't work as good going fast by default -;; smooth-scrolling.el, does not do smooth scrolling. its about cursor location - - -(setq sh-here-document-word "'EOF'") - -(setq tramp-default-method "ssh") -;;; misc general settings - -(ivy-mode 1) -(add-hook 'text-mode-hook (lambda () (auto-fill-mode t))) -(setq counsel-find-file-at-point t) - -;; easier to read with just spaces as separator -(setf (nth 2 ido-decorations) " ") - - -;; https://www.emacswiki.org/emacs/FillParagraph -;; make list items start paragraphs. -(setq paragraph-start "\f\\|[ \t]*$\\|[ \t]*[-+*] ") - -(setq sh-basic-offset 2) -(setq vc-follow-symlinks t) - -;; give us a shell to start instead of scratch -;;(setq initial-buffer-choice (lambda () (new-shell))) - -;; disable this nasty function, as I always use a gui -(defun suspend-frame() (interactive)) - -;; 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) -(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) - -;; i don't use frame titles, but if I ever do -;; this starter kit setting is probably good -(if window-system (setq frame-title-format '(buffer-file-name "%f" ("%b")))) - - -;;(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 - delete-by-moving-to-trash t - shift-select-mode nil - truncate-partial-width-windows nil - uniquify-buffer-name-style 'forward - oddmuse-directory "~/.emacs.d/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 '(".*") - ;; don't pause display code on input. - ;; smoother display performance at slight cost of input performance - redisplay-dont-pause t - 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 '(-4)) -(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 - compilation-read-command nil ;; just don't compile with unsafe file local vars - 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 - (beginning-of-buffer) - (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 "%b") - - ; ----------------------------- - ; fixing up the mode line - ; modified from mastering emacs blog - ; ---------------------------- - -(defvar mode-line-cleaner-alist - `((auto-complete-mode . "") - (yas/minor-mode . "") - (paredit-mode . "") - (auto-fill-function . "") - (eldoc-mode . "") - (abbrev-mode . "") - (flyspell-mode . "") - (glasses-mode . "") - (dot-mode . "") - (yas-global-mode . "") - (yas-minor-mode . "") - (volatile-highlights-mode . "") - (highlight-symbol-mode . "") - ;; Major modes - (lisp-interaction-mode . "λ") - (hi-lock-mode . "") - (python-mode . "Py") - (emacs-lisp-mode . "EL") - (nxhtml-mode . "nx")) - "Alist for `clean-mode-line'. - - When you add a new element to the alist, keep in mind that you - must pass the correct minor/major mode symbol and a string you - want to use in the modeline *in lieu of* the original.") - - -(defun clean-mode-line () - (interactive) - (loop for cleaner in mode-line-cleaner-alist - do (let* ((mode (car cleaner)) - (mode-str (cdr cleaner)) - (old-mode-str (cdr (assq mode minor-mode-alist)))) - (when old-mode-str - (setcar old-mode-str mode-str)) - ;; major mode - (when (eq mode major-mode) - (setq mode-name mode-str))))) - - ; disabled - ; (add-hook 'after-change-major-mode-hook 'clean-mode-line) - - - ;;; alias the new `flymake-report-status-slim' to - ;;; `flymake-report-status' -(defalias 'flymake-report-status 'flymake-report-status-slim) -(defun flymake-report-status-slim (e-w &optional status) - "Show \"slim\" flymake status in mode line." - (when e-w - (setq flymake-mode-line-e-w e-w)) - (when status - (setq flymake-mode-line-status status)) - (let* ((mode-line " Φ")) - (when (> (length flymake-mode-line-e-w) 0) - (setq mode-line (concat mode-line ":" flymake-mode-line-e-w))) - (setq mode-line (concat mode-line flymake-mode-line-status)) - (setq flymake-mode-line mode-line) - (force-mode-line-update))) - - -(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))) - -;;;; keybinds for wow mouse - -(global-set-key (kbd "") 'move-mouse-to-point) -(global-set-key (kbd "") 'indent-region) -(global-set-key (kbd "") 'mark-defun) -(global-set-key (kbd "") 'ibuffer) -(global-set-key (kbd "") 'delete-horizontal-space) - -;;; org mode - -;; todo work on org-cycle-emulate-tab - -;; 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-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 - org-catch-invisible-edits 'smart) - -;; non universally recommended settings -(setq - org-default-notes-file (concat org-directory "/a/t.org") - org-agenda-files (quote ("/a/t.org")) - org-mobile-directory "/p/org-mobile" - org-mobile-inbox-for-pull "/p/from-mobile.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) -;; - -(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") - (string= (buffer-file-name) "/home/iank/.emacs.d/my-init.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)) - -(defun ian-org-work-time () - (interactive) - (save-excursion - (set-buffer "t.org") - (goto-char (org-find-entry-with-id "ian-identifier-1")) - (org-clock-in))) - -(defun ian-org-idle-time () - (interactive) - (save-excursion - (goto-char (org-find-entry-with-id "ian-identifier-2")) - (set-buffer "t.org") - (org-clock-in))) - - - -;; 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) - - -(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)) - - -(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) - ;; 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) - (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) - -;; enable flyspell in prog mode. text mode is handled -(add-hook 'prog-mode-hook 'flyspell-prog-mode) - - - -;;; 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 -;; 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) -;;; smartparens -;; the melpa git version had a catastrophic bug I reported. -;; downgraded to marmalade version and everything is working fine. -(require 'smartparens-config) -(show-smartparens-global-mode t) - - -(defun gp/sp/pair-on-newline-and-indent (id action context) - "Open a new brace or bracket expression, with relevant newlines and indent. " - (save-excursion - (newline) - (indent-according-to-mode)) - (indent-according-to-mode)) - -;; when opening a pair, and then inserting a newline, push the closing pair to another newline -(sp-pair "{" nil :post-handlers - '(:add ((lambda (id action context) - (gp/sp/pair-on-newline-and-indent id action context)) (kbd "")))) -(sp-pair "[" nil :post-handlers - '(:add ((lambda (id action context) - (gp/sp/pair-on-newline-and-indent id action context)) (kbd "")))) - - -;; in my version, this is not a pairing. -;; not sure if it is in a future version since I reverted to marmalade -;; Don't need c-comments in strings -- they frustrate filename globs -;; (sp-pair "/*" nil :unless '(sp-in-string-p)) - -;; Don't need quotes to pair next to words -(sp-pair "\"" nil :unless '(sp-point-before-word-p sp-point-after-word-p)) -(sp-pair "'" nil :unless '(sp-point-before-word-p sp-point-after-word-p)) - - -;; todo, testout these mode specific settings from graphene. -;; Ruby-specific pairs and handlers -(require 'smartparens-ruby) - -;; Markdown -(sp-local-pair '(markdown-mode gfm-mode) "*" "*" - :unless '(sp-in-string-p) - :actions '(insert wrap)) - -;; Except in HTML -(sp-local-pair 'html-mode "\"" nil :unless '(:rem sp-point-after-word-p)) - - -;;; smex -;; todo; check out smex-show-unbound-commands shows frequently used commands that have no key bindings. - ; these must be before smex-initialize -(setq - smex-save-file "~/.emacs.d/.smex-items") - -(smex-initialize) -;;; spell correction -(setq - ispell-program-name "hunspell" - ispell-silently-savep t) ; don't prompt to save personal dictionary - -(require 'rw-hunspell) -;; rw-hunspell sets up hunspell dictionary automagically. - - -;; 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 -(setq-default TeX-PDF-mode t) ; use pdf - - ; more sensible defaults based on info manual quickstart -(setq TeX-auto-save t) -(setq TeX-parse-self t) - - - -;;; 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)) -(setq visible-mark-forward-faces '(visible-mark-forward-face1)) - - - ; highlight the last 2 marks -(setq visible-mark-max 2) - ; highlight 1 forward mark -(setq 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 - - -;;; zrc -(require 'znc) -(setq erc-fill-prefix "") -(defun chirp() - (interactive) - (setq vol 50) - (when (string= (system-name) "tp") (setq vol 40)) - (start-process-shell-command "ignoreme" nil (format "mpv --no-terminal --vo=null --volume=%d /a/bin/data/bird.mp3" vol))) -;; from https://www.emacswiki.org/emacs/ErcSound - -(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))) - -(add-hook 'erc-server-PRIVMSG-functions - 'erc-my-privmsg-sound) - -(defun erc-sound-if-not-server (match-type nickuserhost msg) - (unless (string-match "Server:[0-9]+" nickuserhost) - (chirp))) -(add-hook 'erc-text-matched-hook 'erc-sound-if-not-server) - -(erc-track-mode 1) -(setq - ;; 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) - - -;;; 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 . ,"~/.emacs.d/my-init.org")) - (?t (file . ,"/a/t.org")) - (?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 - -;;; keybinds - -;;;; misc -(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 -(define-key isearch-mode-map (kbd "") '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 "\t" nil) -(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 -(global-set-key (kbd "") 'indent-buffer) -;;;;; 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 - shell -(global-set-key (kbd "") 'shell-wrap) -(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 - ; 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 "") '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-down 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 - -;;;;; C-2 copy-symbol - -(global-unset-key (kbd "C-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-2") 'copy-symbol) - -;;;;; 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 --- - ; todo. whats going on here? -(global-unset-key (kbd "C-M-2")) - -;;;;; C-3 dot-mode-execute - -(global-set-key (kbd "C-3") 'dot-mode-execute) - -;;;;; C-M-3 recenter-top-bottom - -(global-set-key (kbd "C-M-3") 'recenter-top-bottom) - -;;;;; C-q org-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-archive-to-archive-sibling - -(global-set-key (kbd "M-q") 'org-archive-to-archive-sibling) - -;;;;; C-M-q quoted-insert - -(global-set-key (kbd "C-M-q") 'quoted-insert) - -;;;;; C-w --- -;; in terminal, it's ctrl-backspace, duplicate keybind. -;;;;; M-w org-clock-in - -(global-set-key (kbd "M-w") 'org-clock-in) - -;;;;; 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 org-clock-in-last - -(global-set-key (kbd "M-e") 'org-clock-in-last) - -;;;;; 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 org-clock-out - -(global-set-key (kbd "M-r") 'org-clock-out) - -;;;;; 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 -;;;;; C-M-d - swap buffer across windows -;; from http://www.emacswiki.org/emacs/TransposeWindows - -(setq swapping-buffer nil) -(setq swapping-window nil) -(defun swap-buffers-in-windows () - "Swap buffers between two windows" - (interactive) - (if (and swapping-window - swapping-buffer) - (let ((this-buffer (current-buffer)) - (this-window (selected-window))) - (if (and (window-live-p swapping-window) - (buffer-live-p swapping-buffer)) - (progn (switch-to-buffer swapping-buffer) - (select-window swapping-window) - (switch-to-buffer this-buffer) - (select-window this-window) - (message "Swapped buffers.")) - (message "Old buffer/window killed. Aborting.")) - (setq swapping-buffer nil) - (setq swapping-window nil)) - (progn - (setq swapping-buffer (current-buffer)) - (setq swapping-window (selected-window)) - (message "Buffer and window marked for swapping.")))) - -(global-set-key (kbd "C-M-d") 'swap-buffers-in-windows) - -;;;;; 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 - cancel / other window - -(global-set-key (kbd "C-g") 'other-window) - -;;;;; M-g - abort-recursive-edit - -(global-set-key (kbd "M-g") 'abort-recursive-edit) - -;;;;; C-M-g - gnus - -(global-set-key (kbd "C-M-g") 'mu4e) - -;;;;; C-z - undo-only - -(global-set-key (kbd "C-z") 'undo-only) - -;;;;; C-x - kill-region - -(global-set-key (kbd "C-s") 'kill-region) - -;;;;; M-x - smex - -(global-set-key (kbd "M-x") 'smex) - -;;;;; 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-hook - (lambda () (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 - org-capture - -(define-key global-map "\M-c" 'org-capture) - -;;;;; 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) - - - -(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 - delete-other-windows - -(global-set-key (kbd "C-b") 'delete-other-windows) - -;;;;; 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 - -(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 -;;;;; C-* - split-window-horizontally - -(global-set-key (kbd "C-*") 'split-window-horizontally) - -;;;;; C-M-* - calc-dispatch - -(global-set-key (kbd "C-M-*") 'calc-dispatch) - -;;;;; C-9 - delete-window-or-exit - -(global-set-key (kbd "C-9") '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)))) - -;;;;; 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 - ----- -;;;;; 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) - (define-key ido-common-completion-map (kbd "C-j") 'ido-select-text) - (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-m - recursive grep - - (define-key global-map (kbd "C-M-m") 'rgrep) - -;;;;; C-, - ounsel-find-file - - (global-set-key (kbd "C-,") 'counsel-find-file) - (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 -;; Taken from starter kit. - - (defun recentf-ido-find-file () - "Find a recent file using Ido." - (interactive) - (let* ((file-assoc-list - (mapcar (lambda (x) - (cons (file-name-nondirectory x) - x)) - recentf-list)) - (filename-list - (remove-duplicates (mapcar #'car file-assoc-list) - :test #'string=)) - (filename (ido-completing-read "Choose recent file: " - filename-list - nil - t))) - (when filename - (find-file (cdr (assoc filename - file-assoc-list)))))) - - (add-hook 'flyspell-mode-hook - (lambda () (define-key flyspell-mode-map (kbd "C-.") nil))) - (define-key dot-mode-map (kbd "C-.") nil) - (global-set-key (kbd "C-.") 'recentf-ido-find-file) - (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))) - (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-8 - calc-embedded-word - - (global-set-key (kbd "C-8") 'calc-embedded-word) - -;;;;; 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 - - (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)) - (global-set-key (kbd "") 'newline-anywhere) - - -;;;;; M-return - plain newline - - (defun plain-newline () - (interactive) - (insert "\n")) - (global-set-key (kbd "") 'plain-newline) - - -;;;;; C-M-return - newline-anywhere-previous -(defun newline-anywhere-previous () - "Add a newline from anywhere in the line." - (interactive) - (forward-line -1) - (end-of-line) - (newline-and-indent)) -(global-set-key (kbd "") 'newline-anywhere-previous) - -;;;;; 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-6 - save-buffers-kill-emacs - -(global-set-key (kbd "C-6") 'save-buffers-kill-emacs) - -;;;;; C-M-6 - insert-small-copyright - -(defun insert-small-copyright () - (interactive) - (beginning-of-line) - (let ((beg (point))) - (insert "Copyright (C) 2017 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) - -;;;;; C-M-7 - insert-full-copyright - -(defun insert-full-copyright () - (interactive) - (beginning-of-line) - (let ((beg (point))) - (insert "Copyright (C) 2017 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) -(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) -- 2.30.2