;;; 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 .
;;; 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)
;; undo tree stuff
;; more resilient undo-tree-history if we have their locations set up front.
(setq undo-tree-history-directory-alist '(("." . "~/.undo-tree-history")))
;; Undo in region just happens accidentally, and throws me off, and it's been buggy in the past
(setq undo-tree-enable-undo-in-region nil)
;;; 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 initialize upon launching gnus, etc
;; but I figure try this to make sure everything works all the time first
(require 'bbdb)
(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)
;; 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)
;; use d instead
(add-hook 'bbdb-mode-hook
(lambda () (define-key bbdb-mode-map (kbd "C-k") nil)))
(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 'occidental))
(t
(override-theme 'naquadah))))
;; for a long time i used leuven plus this, but it doesn't like dark terminal
;;(custom-set-faces `(default ((t (:background "#F6F6F0")))))
(override-theme 'occidental)
;; 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"
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-hook-function)
(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
;; 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 . "")
(undo-tree-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)))
;;; 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)
;;; undo tree
;; undo-tree checks for minor modes which override
;; its minor mode keymap, and sets global keybinds if
;; that happens. this will prevent that, but I have no
;; reason to do that, so it is commented.
;; (defun undo-tree-overridden-undo-bindings-p () nil)
;; todo, send patch undo-tree-visualize should scroll with the scroll key, instead of just pgup pgdn (aka next/prior)
(global-undo-tree-mode)
;; disabled due to bug, something like unknown entry in undo tree canary
;; (setq undo-tree-auto-save-history t)
(setq undo-outer-limit 100000000 ; per undo command
undo-limit 500000000 ; undo history limit
undo-strong-limit 600000000) ; undo history limit plus some extra
;;; 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)
;;; 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/x.txt"))
))
(set-register (car r) (cadr r)))