From 74e7e843c2e734a62716722339bf41af488cfcb0 Mon Sep 17 00:00:00 2001 From: David Thompson Date: Sat, 23 May 2015 20:23:25 -0400 Subject: emacs: Add config. --- dotfiles/.emacs.d/erc.el | 113 ++++++++++++ dotfiles/.emacs.d/init.el | 447 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 560 insertions(+) create mode 100644 dotfiles/.emacs.d/erc.el create mode 100644 dotfiles/.emacs.d/init.el diff --git a/dotfiles/.emacs.d/erc.el b/dotfiles/.emacs.d/erc.el new file mode 100644 index 0000000..3709f55 --- /dev/null +++ b/dotfiles/.emacs.d/erc.el @@ -0,0 +1,113 @@ +(require 'erc) +(require 'erc-log) +(require 'erc-notify) +(require 'erc-spelling) +(require 'erc-autoaway) +(require 'erc-services) +(require 'notifications) + +;; Notify the user of private messages +(defun erc-private-message-notify (proc parsed) + (let ((nick (car (erc-parse-user (erc-response.sender parsed)))) + (target (car (erc-response.command-args parsed))) + (msg (erc-response.contents parsed))) + (notifications-notify :title nick :body msg))) + +;; (add-hook 'erc-server-PRIVMSG-functions 'erc-private-message-notify) + +;; Notify the user when their nick is mentioned +(defun erc-nick-mentioned-notify (match-type nick message) + "Shows a notification when user's nick is mentioned." + (when (and (not (posix-string-match "^\\** *Users on #" message)) + (eq math-type 'current-nick)) + (notifications-notify + :title nick + :body message + :app-icon "/usr/share/notify-osd/icons/gnome/scalable/status/notification-message-im.svg" + :urgency 'low))) + +;; (add-hook 'erc-text-matched-hook 'erc-nick-mentioned-notify) + +;; Nickname +(setq erc-nick "davexunit") + +;; Interpret mIRC-style color commands in IRC chats +(setq erc-interpret-mirc-color t) + +;; The following are commented out by default, but users of other +;; non-Emacs IRC clients might find them useful. +;; Kill buffers for channels after /part +(setq erc-kill-buffer-on-part t) +;; Kill buffers for private queries after quitting the server +(setq erc-kill-queries-on-quit t) +;; Kill buffers for server messages after quitting the server +(setq erc-kill-server-buffer-on-quit t) + +;; open query buffers in the current window +(setq erc-query-display 'buffer) + +;; exclude boring stuff from tracking +(erc-track-mode t) +(setq erc-track-exclude-types '("JOIN" "NICK" "PART" "QUIT" "MODE" + "324" "329" "332" "333" "353" "477")) + +;; logging +(setq erc-log-channels-directory "~/.erc/logs/") + +(if (not (file-exists-p erc-log-channels-directory)) + (mkdir erc-log-channels-directory t)) + +(setq erc-save-buffer-on-part t) + +;; truncate long irc buffers +(erc-truncate-mode 1) + +;; enable spell checking +(erc-spelling-mode 0) + +;; utf-8 always and forever +(setq erc-server-coding-system '(utf-8 . utf-8)) + +;; Auto-join channels +(erc-autojoin-mode t) +(setq erc-autojoin-channels-alist + '(("freenode.net" "#libre.fm" "#guile" "#guix" "#gnu" + "#gnu-webmasters" "#emacs" "#scheme" "#lispgames" "#fsf" + "#fsfsys" "#fsf-office" "#fsf-campaigns" "#fsf-licensing" + "#libreplanet" "##wizards" "#tox" "#tox-dev" "#sly"))) +;; Don't open channel buffers in place of the current buffer because +;; that drives me fucking crazy. +(setq erc-join-buffer 'bury) + +;; Secret password file +(load "~/.emacs.d/.ercpasswords") + +;; Stuff to make authenticating with Rizon work +(erc-services-mode t) +(setq erc-prompt-for-nickserv-password nil) +(setq erc-nickserv-identify-mode 'autodetect) +(setq erc-nickserv-passwords + `((Rizon (("davexunit" . ,rizon-password))))) + +;; Start and stop erc +(defun start-irc () + "Connect to IRC." + (interactive) + (erc :server "irc.freenode.net" + :port 6667 + :nick erc-nick + :password freenode-password)) + +(defun filter-erc-server-buffers () + (delq nil + (mapcar + (lambda (x) (and (erc-server-buffer-p x) x)) + (buffer-list)))) + +(defun stop-irc () + "Disconnects from all irc servers" + (interactive) + (dolist (buffer (filter-erc-server-buffers)) + (message "Server buffer: %s" (buffer-name buffer)) + (with-current-buffer buffer + (erc-quit-server "Later")))) diff --git a/dotfiles/.emacs.d/init.el b/dotfiles/.emacs.d/init.el new file mode 100644 index 0000000..bdfcd9c --- /dev/null +++ b/dotfiles/.emacs.d/init.el @@ -0,0 +1,447 @@ +;; Turn off mouse interface early in startup to avoid momentary display +(if (fboundp 'tool-bar-mode) (tool-bar-mode -1)) +(if (fboundp 'menu-bar-mode) (menu-bar-mode -1)) +(if (fboundp 'scroll-bar-mode) (scroll-bar-mode -1)) + +;; No splash screen. +(setq inhibit-startup-message t) + +;; Use /bin/sh for shell. +;; +;; I like to use fish shell as my login shell, but there are +;; incompatibilities with its scripting language. +(setq shell-file-name "/bin/bash") + +;; Use screen in ansi-term and co. +(setq explicit-shell-file-name "/usr/bin/screen") + +;;; +;;; Packages +;;; + +(require 'package) +(add-to-list 'package-archives + '("melpa" . "http://melpa.milkbox.net/packages/") t) +(package-initialize) + +;; Additional packages that I use. +(setq required-packages + '(better-defaults + elfeed + emms + geiser + ido-ubiquitous + js2-mode + magit + notmuch + notmuch-unread + paredit + rainbow-delimiters + smex + web-mode + flx-ido + projectile + notmuch-unread)) + +(defun install-missing-packages () + "Install all required packages that haven't been installed." + (interactive) + (mapc (lambda (package) + (unless (package-installed-p package) + (package-install package))) + required-packages) + (message "Installed all missing packages!")) + +;;; +;;; Look and Feel +;;; + +(set-default-font "Inconsolata-11") +(load-theme 'wombat t) +(column-number-mode t) +(which-function-mode t) + +(defun change-theme (theme) + "Disable all active themes and load THEME." + (interactive + (lexical-let ((themes (mapcar 'symbol-name (custom-available-themes)))) + (list (intern (completing-read "Load custom theme: " themes))))) + (mapc 'disable-theme custom-enabled-themes) + (load-theme theme t)) + +;;; +;;; Dired +;;; + +(require 'dired-x) + +;;; +;;; Battery +;;; + +(require 'battery) + +;; Display battery level in modeline only if a battery is present, +;; otherwise display-battery-mode will throw an error. +(when (and (boundp 'battery-status-function) + (not (null battery-status-function)) + (not (string-match-p + "N/A" + (battery-format + "%B" + (funcall battery-status-function))))) + (display-battery-mode t)) + +;;; +;;; Buffers +;;; + +;; ido is awesome for the minibuffer. +(setq ido-everywhere t) +(setq ido-enable-flex-matching t) +(ido-mode t) +(ido-ubiquitous-mode t) +(flx-ido-mode t) + +;; Ignore compiled Guile files. This has the side-effect of looking +;; like I hate GoLang. +(setq ido-ignore-files (cons "\\.go$" ido-ignore-files)) + +(projectile-global-mode) + +;; Remember open buffers for next session. +(desktop-save-mode t) + +;; Kill buffers that haven't been modified in awhile. +(require 'midnight) + +;; Save point position between sessions +(require 'saveplace) +(setq-default save-place t) +(setq save-place-file (expand-file-name ".places" user-emacs-directory)) + +(defun cleanup-buffer-safe () + "Perform a bunch of safe operations on the whitespace content of a buffer. +Does not indent buffer, because it is used for a before-save-hook, and that +might be bad." + (interactive) + (delete-trailing-whitespace) + (set-buffer-file-coding-system 'utf-8)) + +;; Various superfluous white-space. Just say no. +(add-hook 'before-save-hook 'cleanup-buffer-safe) + +;; Snippets. +(auto-insert-mode t) + +(setq ibuffer-saved-filter-groups + '(("default" + ("guile-2d" (filename . "Code/guile-2d/")) + ("dired" (mode . dired-mode)) + ("org" (mode . org-mode)) + ("erc" (mode . erc-mode))))) + +(add-hook 'ibuffer-mode-hook + (lambda () + (ibuffer-switch-to-saved-filter-groups "default"))) + +;;; +;;; Tabs and Newlines +;;; + +(setq-default indent-tabs-mode nil) +(setq indent-tabs-mode nil) +(setq tab-width 2) +(electric-indent-mode t) +(setq require-final-newline t) + +;;; +;;; Version Control +;;; + +;; I don't like magit's default local tracking branch naming strategy. +(setq magit-default-tracking-name-function + 'magit-default-tracking-name-branch-only) + +;;; +;;; Ediff +;;; + +;; Don't break out a separate frame for ediff. +(setq ediff-window-setup-function 'ediff-setup-windows-plain) + +(setq ediff-split-window-function 'split-window-horizontally) + +;;; +;;; C +;;; + +(setq c-default-style "k&r") +(setq-default c-basic-offset 2) +(setq-default c-basic-indent 2) + +;;; +;;; Javascript +;;; + +(setq js-indent-level 2) +(setq js2-basic-offset 2) +(add-to-list 'auto-mode-alist '("\\.js$" . js2-mode)) + +;;; +;;; Web +;;; + +(add-to-list 'auto-mode-alist '("\\.html$" . web-mode)) +(add-to-list 'auto-mode-alist '("\\.tpl$" . web-mode)) + +;;; +;;; PHP +;;; + +(add-hook 'php-mode-hook (lambda () (setq c-basic-offset 2))) + +;;; +;;; Lisp +;;; + +;; Highlight matching parens, automatically insert pairs, use rainbow +;; delimiters and use paredit for Lisp buffers. +(require 'rainbow-delimiters) +(require 'paredit) +(global-rainbow-delimiters-mode t) +(show-paren-mode t) +(add-hook 'emacs-lisp-mode-hook (lambda () (paredit-mode t))) +(add-hook 'lisp-mode-hook (lambda () (paredit-mode t))) +(add-hook 'lisp-interaction-mode-hook (lambda () (paredit-mode t))) +(add-hook 'scheme-mode-hook (lambda () (paredit-mode t))) + +(setq geiser-active-implementations '(guile)) + +(put 'and-let* 'scheme-indent-function 1) +(put 'syntax-parameterize 'scheme-indent-function 1) +(put 'colambda 'scheme-indent-function 1) +(put 'codefine 'scheme-indent-function 1) +(put 'with-agenda 'scheme-indent-function 1) +(put 'gl-begin 'scheme-indent-function 1) +(put 'with-gl-push-matrix 'scheme-indent-function 0) +(put 'with-gl-bind-texture 'scheme-indent-function 2) +(put 'with-gl-client-state 'scheme-indent-function 1) +(put 'with-gl-enable 'scheme-indent-function 1) +(put 'with-mesh 'scheme-indent-function 1) +(put 'with-vertex-buffer 'scheme-indent-function 1) +(put 'with-texture 'scheme-indent-function 1) +(put 'with-texture-maybe 'scheme-indent-function 1) +(put 'with-shader-program 'scheme-indent-function 1) +(put 'uniforms 'scheme-indent-function 1) +(put 'with-sprite-batch 'scheme-indent-function 1) +(put 'with-window 'scheme-indent-function 1) +(put 'with-test-prefix 'scheme-indent-function 0) +(put 'with-mutex 'scheme-indent-function 1) +(put 'bind-key-commands 'scheme-indent-function 2) +(put 'signal-let 'scheme-indent-function 1) +(put 'signal-let* 'scheme-indent-function 1) +(put 'test-group 'scheme-indent-function 1) +(put 'mock 'scheme-indent-function 1) +(put 'with-framebuffer 'scheme-indent-function 1) +(put 'with-render-context 'scheme-indent-function 1) +(put 'with-push-context 'scheme-indent-function 1) +(put 'with-temp-transform 'scheme-indent-function 2) +(put 'chain 'scheme-indent-function 1) +(put 'call-with-port-or-input-file 'scheme-indent-function 1) +(put 'call-with-port-or-output-file 'scheme-indent-function 1) + +(defun connect-to-guile-wm () + "Connect to guile-wm's REPL server." + (interactive) + (geiser-connect 'guile "localhost" "37147")) + +;;; +;;; Ruby +;;; + +;; Rake files are ruby, too, as are gemspecs, rackup files, etc. +(add-to-list 'auto-mode-alist '("\\.rake$" . ruby-mode)) +(add-to-list 'auto-mode-alist '("\\.gemspec$" . ruby-mode)) +(add-to-list 'auto-mode-alist '("\\.ru$" . ruby-mode)) +(add-to-list 'auto-mode-alist '("Rakefile$" . ruby-mode)) +(add-to-list 'auto-mode-alist '("Gemfile$" . ruby-mode)) + +;; Use ruby-test-mode +(add-hook 'ruby-mode-hook 'ruby-test-mode) + +;;; +;;; SQL +;;; + +;; Don't wrap lines so that table listings with a lot of columns +;; remain readable. +(add-hook 'sql-interactive-mode-hook + (lambda () (setq truncate-lines t))) + +;;; +;;; RSS +;;; + +(setq elfeed-feeds + '("http://planet.gnu.org/rss20.xml" + "http://cs.worcester.edu/blog/feed/" + "https://hacks.mozilla.org/feed/" + "http://ebb.org/bkuhn/blog/rss.xml")) + +;;; +;;; GPG +;;; + d +(setf epg-gpg-program "gpg2") + +;;; +;;; Mail +;;; + +(require 'notmuch) +(require 'notmuch-unread) + +(notmuch-unread-mode 1) + +(setq notmuch-fcc-dirs + '(("dthompson2@worcester.edu" . "WSU/Sent") + ("davet@fsf.org" . "FSF/INBOX.Sent") + ("davet@gnu.org" . "FSF/INBOX.Sent") + (".*" . "sent"))) +(setq send-mail-function 'smtpmail-send-it) +(setq smtpmail-smtp-server "mail.fsf.org") +(setq smtpmail-smtp-service 587) +(setq smtpmail-stream-type 'starttls) +;; (setq smtpmail-smtp-server "smtp.gmail.com") +;; (setq smtpmail-smtp-service 465) +;; (setq smtpmail-stream-type 'ssl) + +(setq notmuch-saved-searches + '((:name "unread" :query "tag:unread") + (:name "inbox" :query "tag:inbox") + (:name "important" :query "tag:important") + (:name "fsfsys" :query "tag:fsfsys"))) + +(define-key notmuch-search-mode-map "u" + (lambda () + "Remove 'unread' tag from message." + (interactive) + (notmuch-search-tag '("-unread")) + (notmuch-search-next-thread))) + +(define-key notmuch-search-mode-map "a" + (lambda () + "Remove 'unread' and 'inbox' tags from message." + (interactive) + (notmuch-search-tag '("-unread" "-inbox")) + (notmuch-search-next-thread))) + +(define-key notmuch-search-mode-map "d" + (lambda () + "Add 'deleted' tag to message." + (interactive) + (notmuch-search-tag '("+deleted")) + (notmuch-search-next-thread))) + +(define-key notmuch-search-mode-map "i" + (lambda () + "Remove 'unread' and 'inbox' tags from message, and add the +'important' tag." + (interactive) + (notmuch-search-tag '("-unread" "-inbox" "+important")) + (notmuch-search-next-thread))) + +(define-key notmuch-search-mode-map "s" + (lambda () + "Remove 'unread' and 'inbox' tags from message, and add the +'spam' tag." + (interactive) + (notmuch-search-tag '("-unread" "-inbox" "+spam")) + (notmuch-search-next-thread))) + +;;; +;;; Calendar +;;; + +(require 'org-caldav) + +(setq org-caldav-url + "https://my.owndrive.com/remote.php/caldav/calendars/davexunit") +(setq org-caldav-calendar-id "defaultcalendar") +(setq org-caldav-inbox "~/Documents/calendar.org") +(setq org-caldav-files '()) +(setq org-icalendar-timezone "America/New_York") + +;;; +;;; Music +;;; + +(require 'emms-player-mpd) +(require 'emms-mode-line) +(require 'emms-browser) + +(emms-standard) +(emms-mode-line 1) +(setq emms-player-mpd-server-name "localhost" + emms-player-mpd-server-port "6600" + emms-volume-change-function 'emms-volume-mpd-change) +(add-to-list 'emms-info-functions 'emms-info-mpd) +(add-to-list 'emms-player-list 'emms-player-mpd) + +;;; +;;; Other +;;; + +;; Load machine specific emacs configuration +(defvar local-config-filename "~/.emacs.d/local.el") +(if (file-exists-p local-config-filename) + (load local-config-filename)) + +;; IRC configuration +(load "~/.emacs.d/erc.el") + +;;; +;;; Keybindings +;;; + +;; Handy functions courtesy of whattheemacs.d +(defun open-line-below () + (interactive) + (if (eolp) + (newline) + (end-of-line) + (newline)) + (indent-for-tab-command)) + +(defun open-line-above () + (interactive) + (beginning-of-line) + (newline) + (forward-line -1) + (indent-for-tab-command)) + +;; Easy window movement. +(require 'windmove) +(windmove-default-keybindings 'meta) + +(global-set-key (kbd "M-x") 'smex) +(global-set-key (kbd "RET") 'newline-and-indent) +(global-set-key (kbd "") 'open-line-below) +(global-set-key (kbd "") 'open-line-above) +(global-set-key (kbd "C-c g") 'magit-status) +(global-set-key (kbd "C-c i") 'start-irc) +(global-set-key (kbd "C-c p") 'package-list-packages) +(global-set-key (kbd "C-c C-f") 'ff-find-other-file) +(global-set-key (kbd "C-c s") 'connect-to-guile) +(global-set-key (kbd "C-c e e") 'emms) +(global-set-key (kbd "C-c e b") 'emms-browser) +(global-set-key (kbd "C-c f") 'elfeed) +(global-set-key (kbd "C-c m") 'notmuch) +(global-set-key (kbd "M-%") 'query-replace-regexp) +;; No more minimizing Emacs by accident. +(global-unset-key (kbd "C-z")) + +;; Enable some disabled-by-default functions +(put 'upcase-region 'disabled nil) +(put 'downcase-region 'disabled nil) -- cgit v1.2.3