| @@ -0,0 +1,39 @@ | |||
| /url/cache | |||
| /.emacs.desktop | |||
| /auto-save-list | |||
| /.session | |||
| /custom.el | |||
| *.elc | |||
| CVS | |||
| .svn | |||
| *~ | |||
| .cvsignore | |||
| .*.lock | |||
| /tramp | |||
| /TODO | |||
| /anything-c-adaptive-history | |||
| /.org-id-locations | |||
| cookies | |||
| /newsticker | |||
| /ac-comphist.dat | |||
| \#* | |||
| /elpa | |||
| site-lisp/package/ | |||
| /swank | |||
| /.mc-lists.el | |||
| /var | |||
| /.sqli_history | |||
| /frame-restore-parameters | |||
| /.achievements | |||
| /.bookmarks.el | |||
| /history | |||
| /helm-adaptive-history | |||
| /thumbs/ | |||
| /emms/ | |||
| /.smex-items | |||
| /image-dired/ | |||
| /eshell | |||
| lisp/init-local.el | |||
| session* | |||
| .#.smex-items | |||
| @@ -0,0 +1,5 @@ | |||
| # My personal emacs config | |||
| Based on Steve Purcell's one: | |||
| https://github.com/purcell/emacs.d | |||
| @@ -0,0 +1,104 @@ | |||
| ;;'(("gnu" . "http://elpa.gnu.org/packages/") | |||
| ;;("marmalade" . "http://marmalade-repo.org/packages/") | |||
| ;;("melpa" . "http://melpa.milkbox.net/packages/")) | |||
| ;; sort apropos by rlevance | |||
| (setq apropos-sort-by-scores t) | |||
| ;; bind M-i to imenu | |||
| (global-set-key (kbd "M-i") 'imenu) | |||
| ;; Purcell | |||
| ;;; This file bootstraps the configuration, which is divided into | |||
| ;;; a number of other files. | |||
| (let ((minver 23)) | |||
| (unless (>= emacs-major-version minver) | |||
| (error "Your Emacs is too old -- this config requires v%s or higher" minver))) | |||
| (add-to-list 'load-path (expand-file-name "lisp" user-emacs-directory)) | |||
| (require 'init-benchmarking) ;; Measure startup time | |||
| (defconst *spell-check-support-enabled* nil) ;; Enable with t if you prefer | |||
| ;;---------------------------------------------------------------------------- | |||
| ;; Bootstrap config | |||
| ;;---------------------------------------------------------------------------- | |||
| (require 'init-utils) | |||
| (require 'init-site-lisp) ;; Must come before elpa, as it may provide package.el | |||
| (require 'init-elpa) ;; Machinery for installing required packages | |||
| ;;(require 'init-exec-path) ;; Set up $PATH | |||
| ;;---------------------------------------------------------------------------- | |||
| ;; Allow users to provide an optional "init-preload-local.el" | |||
| ;;---------------------------------------------------------------------------- | |||
| (require 'init-preload-local nil t) | |||
| ;;---------------------------------------------------------------------------- | |||
| ;; Load configs for specific features and modes | |||
| ;;---------------------------------------------------------------------------- | |||
| (require-package 'diminish) | |||
| (require 'init-themes) | |||
| (require 'init-dired) | |||
| (require 'init-isearch) | |||
| (require 'init-recentf) | |||
| (require 'init-ido) | |||
| (require 'init-auto-complete) | |||
| (require 'init-editing-utils) | |||
| (require 'init-crontab) | |||
| (require 'init-markdown) | |||
| (require 'init-csv) | |||
| (require 'init-javascript) | |||
| (require 'init-php) | |||
| (require 'init-org) | |||
| (require 'init-nxml) | |||
| (require 'init-html) | |||
| (require 'init-css) | |||
| (require 'init-python-mode) | |||
| (require 'init-sql) | |||
| (when *spell-check-support-enabled* | |||
| (require 'init-spelling)) | |||
| ;;(require 'init-marmalade) | |||
| ;;---------------------------------------------------------------------------- | |||
| ;; Variables configured via the interactive 'customize' interface | |||
| ;;---------------------------------------------------------------------------- | |||
| (setq custom-file (expand-file-name "custom.el" user-emacs-directory)) | |||
| (when (file-exists-p custom-file) | |||
| (load custom-file)) | |||
| ;;---------------------------------------------------------------------------- | |||
| ;; Allow access from emacsclient | |||
| ;;---------------------------------------------------------------------------- | |||
| (require 'server) | |||
| (unless (server-running-p) | |||
| (server-start)) | |||
| ;;---------------------------------------------------------------------------- | |||
| ;; Allow users to provide an optional "init-local" containing personal settings | |||
| ;;---------------------------------------------------------------------------- | |||
| (when (file-exists-p (expand-file-name "init-local.el" user-emacs-directory)) | |||
| (error "Please move init-local.el to ~/.emacs.d/lisp")) | |||
| (require 'init-local nil t) | |||
| (add-hook 'after-init-hook | |||
| (lambda () | |||
| (message "init completed in %.2fms" | |||
| (sanityinc/time-subtract-millis after-init-time before-init-time)))) | |||
| (provide 'init) | |||
| ;; Local Variables: | |||
| ;; coding: utf-8 | |||
| ;; no-byte-compile: t | |||
| ;; End: | |||
| @@ -0,0 +1,65 @@ | |||
| (require-package 'auto-complete) | |||
| (require 'auto-complete-config) | |||
| (global-auto-complete-mode t) | |||
| (setq-default ac-expand-on-auto-complete nil) | |||
| (setq-default ac-auto-start nil) | |||
| (setq-default ac-dwim nil) ; To get pop-ups with docs even if a word is uniquely completed | |||
| ;;---------------------------------------------------------------------------- | |||
| ;; Use Emacs' built-in TAB completion hooks to trigger AC (Emacs >= 23.2) | |||
| ;;---------------------------------------------------------------------------- | |||
| (setq tab-always-indent 'complete) ;; use 't when auto-complete is disabled | |||
| (add-to-list 'completion-styles 'initials t) | |||
| ;; Stop completion-at-point from popping up completion buffers so eagerly | |||
| (setq completion-cycle-threshold 5) | |||
| ;; TODO: find solution for php, haskell and other modes where TAB always does something | |||
| (setq c-tab-always-indent nil | |||
| c-insert-tab-function 'indent-for-tab-command) | |||
| ;; hook AC into completion-at-point | |||
| (defun sanityinc/auto-complete-at-point () | |||
| (when (and (not (minibufferp)) | |||
| (fboundp 'auto-complete-mode) | |||
| auto-complete-mode) | |||
| (auto-complete))) | |||
| (defun sanityinc/never-indent () | |||
| (set (make-local-variable 'indent-line-function) (lambda () 'noindent))) | |||
| (defun set-auto-complete-as-completion-at-point-function () | |||
| (setq completion-at-point-functions | |||
| (cons 'sanityinc/auto-complete-at-point | |||
| (remove 'sanityinc/auto-complete-at-point completion-at-point-functions)))) | |||
| (add-hook 'auto-complete-mode-hook 'set-auto-complete-as-completion-at-point-function) | |||
| (set-default 'ac-sources | |||
| '(ac-source-imenu | |||
| ac-source-dictionary | |||
| ac-source-words-in-buffer | |||
| ac-source-words-in-same-mode-buffers | |||
| ac-source-words-in-all-buffer)) | |||
| (dolist (mode '(magit-log-edit-mode | |||
| log-edit-mode org-mode text-mode haml-mode | |||
| git-commit-mode | |||
| sass-mode yaml-mode csv-mode espresso-mode haskell-mode | |||
| html-mode nxml-mode sh-mode smarty-mode clojure-mode | |||
| lisp-mode textile-mode markdown-mode tuareg-mode | |||
| js3-mode css-mode less-css-mode sql-mode | |||
| sql-interactive-mode | |||
| inferior-emacs-lisp-mode)) | |||
| (add-to-list 'ac-modes mode)) | |||
| ;; Exclude very large buffers from dabbrev | |||
| (defun sanityinc/dabbrev-friend-buffer (other-buffer) | |||
| (< (buffer-size other-buffer) (* 1 1024 1024))) | |||
| (setq dabbrev-friend-buffer-function 'sanityinc/dabbrev-friend-buffer) | |||
| (provide 'init-auto-complete) | |||
| @@ -0,0 +1,25 @@ | |||
| (defun sanityinc/time-subtract-millis (b a) | |||
| (* 1000.0 (float-time (time-subtract b a)))) | |||
| (defvar sanityinc/require-times nil | |||
| "A list of (FEATURE . LOAD-DURATION). | |||
| LOAD-DURATION is the time taken in milliseconds to load FEATURE.") | |||
| (defadvice require | |||
| (around build-require-times (feature &optional filename noerror) activate) | |||
| "Note in `sanityinc/require-times' the time taken to require each feature." | |||
| (let* ((already-loaded (memq feature features)) | |||
| (require-start-time (and (not already-loaded) (current-time)))) | |||
| (prog1 | |||
| ad-do-it | |||
| (when (and (not already-loaded) (memq feature features)) | |||
| (add-to-list 'sanityinc/require-times | |||
| (cons feature | |||
| (sanityinc/time-subtract-millis (current-time) | |||
| require-start-time)) | |||
| t))))) | |||
| (provide 'init-benchmarking) | |||
| @@ -0,0 +1,4 @@ | |||
| (require-package 'crontab-mode) | |||
| (add-auto-mode 'crontab-mode "\\.?cron\\(tab\\)?\\'") | |||
| (provide 'init-crontab) | |||
| @@ -0,0 +1,65 @@ | |||
| ;;; Colourise CSS colour literals | |||
| (when (eval-when-compile (>= emacs-major-version 24)) | |||
| ;; rainbow-mode needs color.el, bundled with Emacs >= 24. | |||
| (require-package 'rainbow-mode) | |||
| (dolist (hook '(css-mode-hook html-mode-hook sass-mode-hook)) | |||
| (add-hook hook 'rainbow-mode))) | |||
| ;;; Embedding in html | |||
| (require-package 'mmm-mode) | |||
| (after-load 'mmm-vars | |||
| (mmm-add-group | |||
| 'html-css | |||
| '((css-cdata | |||
| :submode css-mode | |||
| :face mmm-code-submode-face | |||
| :front "<style[^>]*>[ \t\n]*\\(//\\)?<!\\[CDATA\\[[ \t]*\n?" | |||
| :back "[ \t]*\\(//\\)?]]>[ \t\n]*</style>" | |||
| :insert ((?j js-tag nil @ "<style type=\"text/css\">" | |||
| @ "\n" _ "\n" @ "</style>" @))) | |||
| (css | |||
| :submode css-mode | |||
| :face mmm-code-submode-face | |||
| :front "<style[^>]*>[ \t]*\n?" | |||
| :back "[ \t]*</style>" | |||
| :insert ((?j js-tag nil @ "<style type=\"text/css\">" | |||
| @ "\n" _ "\n" @ "</style>" @))) | |||
| (css-inline | |||
| :submode css-mode | |||
| :face mmm-code-submode-face | |||
| :front "style=\"" | |||
| :back "\""))) | |||
| (dolist (mode (list 'html-mode 'nxml-mode)) | |||
| (mmm-add-mode-ext-class mode "\\.r?html\\(\\.erb\\)?\\'" 'html-css))) | |||
| ;;; SASS and SCSS | |||
| (require-package 'sass-mode) | |||
| (require-package 'scss-mode) | |||
| (setq-default scss-compile-at-save nil) | |||
| ;;; LESS | |||
| (require-package 'less-css-mode) | |||
| (when (featurep 'js2-mode) | |||
| (require-package 'skewer-less)) | |||
| ;;; Auto-complete CSS keywords | |||
| (after-load 'auto-complete | |||
| (dolist (hook '(css-mode-hook sass-mode-hook scss-mode-hook)) | |||
| (add-hook hook 'ac-css-mode-setup))) | |||
| ;;; Use eldoc for syntax hints | |||
| (require-package 'css-eldoc) | |||
| (autoload 'turn-on-css-eldoc "css-eldoc") | |||
| (add-hook 'css-mode-hook 'turn-on-css-eldoc) | |||
| (provide 'init-css) | |||
| @@ -0,0 +1,8 @@ | |||
| (require-package 'csv-mode) | |||
| (require-package 'csv-nav) | |||
| (add-auto-mode 'csv-mode "\\.[Cc][Ss][Vv]\\'") | |||
| (setq csv-separators '("," ";" "|" " ")) | |||
| (provide 'init-csv) | |||
| @@ -0,0 +1,18 @@ | |||
| (require-package 'dired+) | |||
| (require-package 'dired-sort) | |||
| (setq-default diredp-hide-details-initially-flag nil | |||
| dired-dwim-target t) | |||
| (after-load 'dired | |||
| (require 'dired+) | |||
| (require 'dired-sort) | |||
| (when (fboundp 'global-dired-hide-details-mode) | |||
| (global-dired-hide-details-mode -1)) | |||
| (setq dired-recursive-deletes 'top) | |||
| (define-key dired-mode-map [mouse-2] 'dired-find-file) | |||
| (add-hook 'dired-mode-hook | |||
| (lambda () (guide-key/add-local-guide-key-sequence "%")))) | |||
| (provide 'init-dired) | |||
| @@ -0,0 +1,337 @@ | |||
| (require-package 'unfill) | |||
| (when (fboundp 'electric-pair-mode) | |||
| (electric-pair-mode)) | |||
| (when (fboundp 'electric-indent-mode) | |||
| (electric-indent-mode)) | |||
| ;;---------------------------------------------------------------------------- | |||
| ;; Some basic preferences | |||
| ;;---------------------------------------------------------------------------- | |||
| (setq-default | |||
| blink-cursor-delay 0 | |||
| blink-cursor-interval 0.4 | |||
| bookmark-default-file (expand-file-name ".bookmarks.el" user-emacs-directory) | |||
| buffers-menu-max-size 30 | |||
| case-fold-search t | |||
| column-number-mode t | |||
| delete-selection-mode t | |||
| ediff-split-window-function 'split-window-horizontally | |||
| ediff-window-setup-function 'ediff-setup-windows-plain | |||
| indent-tabs-mode nil | |||
| make-backup-files nil | |||
| mouse-yank-at-point t | |||
| save-interprogram-paste-before-kill t | |||
| scroll-preserve-screen-position 'always | |||
| set-mark-command-repeat-pop t | |||
| show-trailing-whitespace t | |||
| tooltip-delay 1.5 | |||
| truncate-lines nil | |||
| truncate-partial-width-windows nil | |||
| visible-bell t) | |||
| (global-auto-revert-mode) | |||
| (setq global-auto-revert-non-file-buffers t | |||
| auto-revert-verbose nil) | |||
| (transient-mark-mode t) | |||
| ;;; Whitespace | |||
| (defun sanityinc/no-trailing-whitespace () | |||
| "Turn off display of trailing whitespace in this buffer." | |||
| (setq show-trailing-whitespace nil)) | |||
| ;; But don't show trailing whitespace in SQLi, inf-ruby etc. | |||
| (dolist (hook '(special-mode-hook | |||
| eww-mode-hook | |||
| term-mode-hook | |||
| comint-mode-hook | |||
| compilation-mode-hook | |||
| twittering-mode-hook | |||
| minibuffer-setup-hook)) | |||
| (add-hook hook #'sanityinc/no-trailing-whitespace)) | |||
| (require-package 'whitespace-cleanup-mode) | |||
| (global-whitespace-cleanup-mode t) | |||
| (when (eval-when-compile (string< "24.3.1" emacs-version)) | |||
| ;; https://github.com/purcell/emacs.d/issues/138 | |||
| (after-load 'subword | |||
| (diminish 'subword-mode))) | |||
| (when (fboundp 'global-prettify-symbols-mode) | |||
| (global-prettify-symbols-mode)) | |||
| (require-package 'undo-tree) | |||
| (global-undo-tree-mode) | |||
| (diminish 'undo-tree-mode) | |||
| (require-package 'highlight-symbol) | |||
| (dolist (hook '(prog-mode-hook html-mode-hook css-mode-hook)) | |||
| (add-hook hook 'highlight-symbol-mode) | |||
| (add-hook hook 'highlight-symbol-nav-mode)) | |||
| (eval-after-load 'highlight-symbol | |||
| '(diminish 'highlight-symbol-mode)) | |||
| ;;---------------------------------------------------------------------------- | |||
| ;; Zap *up* to char is a handy pair for zap-to-char | |||
| ;;---------------------------------------------------------------------------- | |||
| (autoload 'zap-up-to-char "misc" "Kill up to, but not including ARGth occurrence of CHAR.") | |||
| (global-set-key (kbd "M-Z") 'zap-up-to-char) | |||
| (require-package 'browse-kill-ring) | |||
| ;;---------------------------------------------------------------------------- | |||
| ;; Don't disable narrowing commands | |||
| ;;---------------------------------------------------------------------------- | |||
| (put 'narrow-to-region 'disabled nil) | |||
| (put 'narrow-to-page 'disabled nil) | |||
| (put 'narrow-to-defun 'disabled nil) | |||
| ;;---------------------------------------------------------------------------- | |||
| ;; Show matching parens | |||
| ;;---------------------------------------------------------------------------- | |||
| (show-paren-mode 1) | |||
| ;;---------------------------------------------------------------------------- | |||
| ;; Expand region | |||
| ;;---------------------------------------------------------------------------- | |||
| (require-package 'expand-region) | |||
| (global-set-key (kbd "C-=") 'er/expand-region) | |||
| ;;---------------------------------------------------------------------------- | |||
| ;; Don't disable case-change functions | |||
| ;;---------------------------------------------------------------------------- | |||
| (put 'upcase-region 'disabled nil) | |||
| (put 'downcase-region 'disabled nil) | |||
| ;;---------------------------------------------------------------------------- | |||
| ;; Rectangle selections, and overwrite text when the selection is active | |||
| ;;---------------------------------------------------------------------------- | |||
| (cua-selection-mode t) ; for rectangles, CUA is nice | |||
| ;;---------------------------------------------------------------------------- | |||
| ;; Handy key bindings | |||
| ;;---------------------------------------------------------------------------- | |||
| ;; To be able to M-x without meta | |||
| (global-set-key (kbd "C-x C-m") 'execute-extended-command) | |||
| ;; Vimmy alternatives to M-^ and C-u M-^ | |||
| (global-set-key (kbd "C-c j") 'join-line) | |||
| (global-set-key (kbd "C-c J") (lambda () (interactive) (join-line 1))) | |||
| (global-set-key (kbd "C-.") 'set-mark-command) | |||
| (global-set-key (kbd "C-x C-.") 'pop-global-mark) | |||
| (require-package 'ace-jump-mode) | |||
| (global-set-key (kbd "C-;") 'ace-jump-mode) | |||
| (global-set-key (kbd "C-:") 'ace-jump-word-mode) | |||
| (require-package 'multiple-cursors) | |||
| ;; multiple-cursors | |||
| (global-set-key (kbd "C-<") 'mc/mark-previous-like-this) | |||
| (global-set-key (kbd "C->") 'mc/mark-next-like-this) | |||
| (global-set-key (kbd "C-+") 'mc/mark-next-like-this) | |||
| (global-set-key (kbd "C-c C-<") 'mc/mark-all-like-this) | |||
| ;; From active region to multiple cursors: | |||
| (global-set-key (kbd "C-c c r") 'set-rectangular-region-anchor) | |||
| (global-set-key (kbd "C-c c c") 'mc/edit-lines) | |||
| (global-set-key (kbd "C-c c e") 'mc/edit-ends-of-lines) | |||
| (global-set-key (kbd "C-c c a") 'mc/edit-beginnings-of-lines) | |||
| ;; Train myself to use M-f and M-b instead | |||
| (global-unset-key [M-left]) | |||
| (global-unset-key [M-right]) | |||
| (defun kill-back-to-indentation () | |||
| "Kill from point back to the first non-whitespace character on the line." | |||
| (interactive) | |||
| (let ((prev-pos (point))) | |||
| (back-to-indentation) | |||
| (kill-region (point) prev-pos))) | |||
| (global-set-key (kbd "C-M-<backspace>") 'kill-back-to-indentation) | |||
| ;;---------------------------------------------------------------------------- | |||
| ;; Page break lines | |||
| ;;---------------------------------------------------------------------------- | |||
| (require-package 'page-break-lines) | |||
| (global-page-break-lines-mode) | |||
| (diminish 'page-break-lines-mode) | |||
| ;;---------------------------------------------------------------------------- | |||
| ;; Fill column indicator | |||
| ;;---------------------------------------------------------------------------- | |||
| (when (eval-when-compile (> emacs-major-version 23)) | |||
| (require-package 'fill-column-indicator) | |||
| (defun sanityinc/prog-mode-fci-settings () | |||
| (turn-on-fci-mode) | |||
| (when show-trailing-whitespace | |||
| (set (make-local-variable 'whitespace-style) '(face trailing)) | |||
| (whitespace-mode 1))) | |||
| ;;(add-hook 'prog-mode-hook 'sanityinc/prog-mode-fci-settings) | |||
| (defun sanityinc/fci-enabled-p () | |||
| (and (boundp 'fci-mode) fci-mode)) | |||
| (defvar sanityinc/fci-mode-suppressed nil) | |||
| (defadvice popup-create (before suppress-fci-mode activate) | |||
| "Suspend fci-mode while popups are visible" | |||
| (let ((fci-enabled (sanityinc/fci-enabled-p))) | |||
| (when fci-enabled | |||
| (set (make-local-variable 'sanityinc/fci-mode-suppressed) fci-enabled) | |||
| (turn-off-fci-mode)))) | |||
| (defadvice popup-delete (after restore-fci-mode activate) | |||
| "Restore fci-mode when all popups have closed" | |||
| (when (and sanityinc/fci-mode-suppressed | |||
| (null popup-instances)) | |||
| (setq sanityinc/fci-mode-suppressed nil) | |||
| (turn-on-fci-mode))) | |||
| ;; Regenerate fci-mode line images after switching themes | |||
| (defadvice enable-theme (after recompute-fci-face activate) | |||
| (dolist (buffer (buffer-list)) | |||
| (with-current-buffer buffer | |||
| (when (sanityinc/fci-enabled-p) | |||
| (turn-on-fci-mode)))))) | |||
| ;;---------------------------------------------------------------------------- | |||
| ;; Shift lines up and down with M-up and M-down. When paredit is enabled, | |||
| ;; it will use those keybindings. For this reason, you might prefer to | |||
| ;; use M-S-up and M-S-down, which will work even in lisp modes. | |||
| ;;---------------------------------------------------------------------------- | |||
| (require-package 'move-dup) | |||
| (global-set-key [M-up] 'md/move-lines-up) | |||
| (global-set-key [M-down] 'md/move-lines-down) | |||
| (global-set-key [M-S-up] 'md/move-lines-up) | |||
| (global-set-key [M-S-down] 'md/move-lines-down) | |||
| (global-set-key (kbd "C-c p") 'md/duplicate-down) | |||
| (global-set-key (kbd "C-c P") 'md/duplicate-up) | |||
| ;;---------------------------------------------------------------------------- | |||
| ;; Fix backward-up-list to understand quotes, see http://bit.ly/h7mdIL | |||
| ;;---------------------------------------------------------------------------- | |||
| (defun backward-up-sexp (arg) | |||
| "Jump up to the start of the ARG'th enclosing sexp." | |||
| (interactive "p") | |||
| (let ((ppss (syntax-ppss))) | |||
| (cond ((elt ppss 3) | |||
| (goto-char (elt ppss 8)) | |||
| (backward-up-sexp (1- arg))) | |||
| ((backward-up-list arg))))) | |||
| (global-set-key [remap backward-up-list] 'backward-up-sexp) ; C-M-u, C-M-up | |||
| ;;---------------------------------------------------------------------------- | |||
| ;; Cut/copy the current line if no region is active | |||
| ;;---------------------------------------------------------------------------- | |||
| (require-package 'whole-line-or-region) | |||
| (whole-line-or-region-mode t) | |||
| (diminish 'whole-line-or-region-mode) | |||
| (make-variable-buffer-local 'whole-line-or-region-mode) | |||
| (defun suspend-mode-during-cua-rect-selection (mode-name) | |||
| "Add an advice to suspend `MODE-NAME' while selecting a CUA rectangle." | |||
| (let ((flagvar (intern (format "%s-was-active-before-cua-rectangle" mode-name))) | |||
| (advice-name (intern (format "suspend-%s" mode-name)))) | |||
| (eval-after-load 'cua-rect | |||
| `(progn | |||
| (defvar ,flagvar nil) | |||
| (make-variable-buffer-local ',flagvar) | |||
| (defadvice cua--activate-rectangle (after ,advice-name activate) | |||
| (setq ,flagvar (and (boundp ',mode-name) ,mode-name)) | |||
| (when ,flagvar | |||
| (,mode-name 0))) | |||
| (defadvice cua--deactivate-rectangle (after ,advice-name activate) | |||
| (when ,flagvar | |||
| (,mode-name 1))))))) | |||
| (suspend-mode-during-cua-rect-selection 'whole-line-or-region-mode) | |||
| (defun sanityinc/open-line-with-reindent (n) | |||
| "A version of `open-line' which reindents the start and end positions. | |||
| If there is a fill prefix and/or a `left-margin', insert them | |||
| on the new line if the line would have been blank. | |||
| With arg N, insert N newlines." | |||
| (interactive "*p") | |||
| (let* ((do-fill-prefix (and fill-prefix (bolp))) | |||
| (do-left-margin (and (bolp) (> (current-left-margin) 0))) | |||
| (loc (point-marker)) | |||
| ;; Don't expand an abbrev before point. | |||
| (abbrev-mode nil)) | |||
| (delete-horizontal-space t) | |||
| (newline n) | |||
| (indent-according-to-mode) | |||
| (when (eolp) | |||
| (delete-horizontal-space t)) | |||
| (goto-char loc) | |||
| (while (> n 0) | |||
| (cond ((bolp) | |||
| (if do-left-margin (indent-to (current-left-margin))) | |||
| (if do-fill-prefix (insert-and-inherit fill-prefix)))) | |||
| (forward-line 1) | |||
| (setq n (1- n))) | |||
| (goto-char loc) | |||
| (end-of-line) | |||
| (indent-according-to-mode))) | |||
| (global-set-key (kbd "C-o") 'sanityinc/open-line-with-reindent) | |||
| ;;---------------------------------------------------------------------------- | |||
| ;; Random line sorting | |||
| ;;---------------------------------------------------------------------------- | |||
| (defun sort-lines-random (beg end) | |||
| "Sort lines in region randomly." | |||
| (interactive "r") | |||
| (save-excursion | |||
| (save-restriction | |||
| (narrow-to-region beg end) | |||
| (goto-char (point-min)) | |||
| (let ;; To make `end-of-line' and etc. to ignore fields. | |||
| ((inhibit-field-text-motion t)) | |||
| (sort-subr nil 'forward-line 'end-of-line nil nil | |||
| (lambda (s1 s2) (eq (random 2) 0))))))) | |||
| (require-package 'highlight-escape-sequences) | |||
| (hes-mode) | |||
| (require-package 'guide-key) | |||
| (setq guide-key/guide-key-sequence '("C-x r" "C-x 4" "C-x 5" "C-c ;" "C-c ; f" "C-c ' f" "C-x n")) | |||
| (guide-key-mode 1) | |||
| (diminish 'guide-key-mode) | |||
| (provide 'init-editing-utils) | |||
| @@ -0,0 +1,90 @@ | |||
| ;;; Find and load the correct package.el | |||
| ;; When switching between Emacs 23 and 24, we always use the bundled package.el in Emacs 24 | |||
| (let ((package-el-site-lisp-dir | |||
| (expand-file-name "site-lisp/package" user-emacs-directory))) | |||
| (when (and (file-directory-p package-el-site-lisp-dir) | |||
| (> emacs-major-version 23)) | |||
| (message "Removing local package.el from load-path to avoid shadowing bundled version") | |||
| (setq load-path (remove package-el-site-lisp-dir load-path)))) | |||
| (require 'package) | |||
| ;;; Standard package repositories | |||
| ;(add-to-list 'package-archives '("marmalade" . "http://marmalade-repo.org/packages/")) | |||
| ;; We include the org repository for completeness, but don't normally | |||
| ;; use it. | |||
| (add-to-list 'package-archives '("org" . "http://orgmode.org/elpa/")) | |||
| (when (< emacs-major-version 24) | |||
| (add-to-list 'package-archives '("gnu" . "http://elpa.gnu.org/packages/"))) | |||
| ;;; Also use Melpa for most packages | |||
| (add-to-list 'package-archives '("melpa" . "http://melpa.milkbox.net/packages/")) | |||
| (add-to-list 'package-archives '("melpa-stable" . "http://melpa-stable.milkbox.net/packages/")) | |||
| ;; If gpg cannot be found, signature checking will fail, so we | |||
| ;; conditionally enable it according to whether gpg is available. We | |||
| ;; re-run this check once $PATH has been configured | |||
| (defun sanityinc/package-maybe-enable-signatures () | |||
| (setq package-check-signature (when (executable-find "gpg") 'allow-unsigned))) | |||
| (sanityinc/package-maybe-enable-signatures) | |||
| ;;(after-load 'init-exec-path | |||
| ;; (sanityinc/package-maybe-enable-signatures)) | |||
| ;;; On-demand installation of packages | |||
| (defun require-package (package &optional min-version no-refresh) | |||
| "Install given PACKAGE, optionally requiring MIN-VERSION. | |||
| If NO-REFRESH is non-nil, the available package lists will not be | |||
| re-downloaded in order to locate PACKAGE." | |||
| (if (package-installed-p package min-version) | |||
| t | |||
| (if (or (assoc package package-archive-contents) no-refresh) | |||
| (package-install package) | |||
| (progn | |||
| (package-refresh-contents) | |||
| (require-package package min-version t))))) | |||
| ;;; Fire up package.el | |||
| (setq package-enable-at-startup nil) | |||
| (package-initialize) | |||
| (require-package 'fullframe) | |||
| (fullframe list-packages quit-window) | |||
| (require-package 'cl-lib) | |||
| (require 'cl-lib) | |||
| (defun sanityinc/set-tabulated-list-column-width (col-name width) | |||
| "Set any column with name COL-NAME to the given WIDTH." | |||
| (cl-loop for column across tabulated-list-format | |||
| when (string= col-name (car column)) | |||
| do (setf (elt column 1) width))) | |||
| (defun sanityinc/maybe-widen-package-menu-columns () | |||
| "Widen some columns of the package menu table to avoid truncation." | |||
| (when (boundp 'tabulated-list-format) | |||
| (sanityinc/set-tabulated-list-column-width "Version" 13) | |||
| (let ((longest-archive-name (apply 'max (mapcar 'length (mapcar 'car package-archives))))) | |||
| (sanityinc/set-tabulated-list-column-width "Archive" longest-archive-name)))) | |||
| (add-hook 'package-menu-mode-hook 'sanityinc/maybe-widen-package-menu-columns) | |||
| (provide 'init-elpa) | |||
| @@ -0,0 +1,11 @@ | |||
| (require-package 'exec-path-from-shell) | |||
| (after-load 'exec-path-from-shell | |||
| (dolist (var '("SSH_AUTH_SOCK" "SSH_AGENT_PID" "GPG_AGENT_INFO" "LANG" "LC_CTYPE")) | |||
| (add-to-list 'exec-path-from-shell-variables var))) | |||
| (when (memq window-system '(mac ns)) | |||
| (exec-path-from-shell-initialize)) | |||
| (provide 'init-exec-path) | |||
| @@ -0,0 +1,13 @@ | |||
| (require-package 'tidy) | |||
| (add-hook 'html-mode-hook (lambda () (tidy-build-menu html-mode-map))) | |||
| (require-package 'tagedit) | |||
| (after-load 'sgml-mode | |||
| (tagedit-add-paredit-like-keybindings) | |||
| (add-hook 'sgml-mode-hook (lambda () (tagedit-mode 1)))) | |||
| (add-auto-mode 'html-mode "\\.(jsp|tmpl)\\'") | |||
| ;; Note: ERB is configured in init-ruby-mode | |||
| (provide 'init-html) | |||
| @@ -0,0 +1,32 @@ | |||
| ;; Use C-f during file selection to switch to regular find-file | |||
| (require 'ido) | |||
| (ido-mode t) | |||
| (ido-everywhere t) | |||
| (setq ido-enable-flex-matching t) | |||
| (setq ido-use-filename-at-point nil) | |||
| (setq ido-auto-merge-work-directories-length 0) | |||
| (setq ido-use-virtual-buffers t) | |||
| (when (eval-when-compile (>= emacs-major-version 24)) | |||
| (require-package 'ido-ubiquitous) | |||
| (ido-ubiquitous-mode t)) | |||
| ;; Use smex to handle M-x | |||
| (when (eval-when-compile (>= emacs-major-version 24)) | |||
| (require-package 'smex) | |||
| ;; Change path for ~/.smex-items | |||
| (setq smex-save-file (expand-file-name ".smex-items" user-emacs-directory)) | |||
| (global-set-key [remap execute-extended-command] 'smex)) | |||
| (require-package 'idomenu) | |||
| ;; Allow the same buffer to be open in different frames | |||
| (setq ido-default-buffer-method 'selected-window) | |||
| ;; http://www.reddit.com/r/emacs/comments/21a4p9/use_recentf_and_ido_together/cgbprem | |||
| (add-hook 'ido-setup-hook (lambda () (define-key ido-completion-map [up] 'previous-history-element))) | |||
| (provide 'init-ido) | |||
| @@ -0,0 +1,75 @@ | |||
| ;; Show number of matches while searching | |||
| (when (>= emacs-major-version 24) | |||
| (require-package 'anzu) | |||
| (global-anzu-mode t) | |||
| (diminish 'anzu-mode) | |||
| (global-set-key [remap query-replace-regexp] 'anzu-query-replace-regexp) | |||
| (global-set-key [remap query-replace] 'anzu-query-replace)) | |||
| ;; Activate occur easily inside isearch | |||
| (define-key isearch-mode-map (kbd "C-o") 'isearch-occur) | |||
| ;; DEL during isearch should edit the search string, not jump back to the previous result | |||
| (define-key isearch-mode-map [remap isearch-delete-char] 'isearch-del-char) | |||
| ;; Search back/forth for the symbol at point | |||
| ;; See http://www.emacswiki.org/emacs/SearchAtPoint | |||
| (defun isearch-yank-symbol () | |||
| "*Put symbol at current point into search string." | |||
| (interactive) | |||
| (let ((sym (symbol-at-point))) | |||
| (if sym | |||
| (progn | |||
| (setq isearch-regexp t | |||
| isearch-string (concat "\\_<" (regexp-quote (symbol-name sym)) "\\_>") | |||
| isearch-message (mapconcat 'isearch-text-char-description isearch-string "") | |||
| isearch-yank-flag t)) | |||
| (ding))) | |||
| (isearch-search-and-update)) | |||
| (define-key isearch-mode-map "\C-\M-w" 'isearch-yank-symbol) | |||
| ;; http://www.emacswiki.org/emacs/ZapToISearch | |||
| (defun zap-to-isearch (rbeg rend) | |||
| "Kill the region between the mark and the closest portion of | |||
| the isearch match string. The behaviour is meant to be analogous | |||
| to zap-to-char; let's call it zap-to-isearch. The deleted region | |||
| does not include the isearch word. This is meant to be bound only | |||
| in isearch mode. The point of this function is that oftentimes | |||
| you want to delete some portion of text, one end of which happens | |||
| to be an active isearch word. The observation to make is that if | |||
| you use isearch a lot to move the cursor around (as you should, | |||
| it is much more efficient than using the arrows), it happens a | |||
| lot that you could just delete the active region between the mark | |||
| and the point, not include the isearch word." | |||
| (interactive "r") | |||
| (when (not mark-active) | |||
| (error "Mark is not active")) | |||
| (let* ((isearch-bounds (list isearch-other-end (point))) | |||
| (ismin (apply 'min isearch-bounds)) | |||
| (ismax (apply 'max isearch-bounds)) | |||
| ) | |||
| (if (< (mark) ismin) | |||
| (kill-region (mark) ismin) | |||
| (if (> (mark) ismax) | |||
| (kill-region ismax (mark)) | |||
| (error "Internal error in isearch kill function."))) | |||
| (isearch-exit) | |||
| )) | |||
| (define-key isearch-mode-map [(meta z)] 'zap-to-isearch) | |||
| ;; http://www.emacswiki.org/emacs/ZapToISearch | |||
| (defun isearch-exit-other-end (rbeg rend) | |||
| "Exit isearch, but at the other end of the search string. | |||
| This is useful when followed by an immediate kill." | |||
| (interactive "r") | |||
| (isearch-exit) | |||
| (goto-char isearch-other-end)) | |||
| (define-key isearch-mode-map [(control return)] 'isearch-exit-other-end) | |||
| (provide 'init-isearch) | |||
| @@ -0,0 +1,102 @@ | |||
| (require-package 'json-mode) | |||
| (when (>= emacs-major-version 24) | |||
| (require-package 'js2-mode) | |||
| (require-package 'ac-js2) | |||
| (require-package 'coffee-mode)) | |||
| (require-package 'js-comint) | |||
| (defcustom preferred-javascript-mode | |||
| (first (remove-if-not #'fboundp '(js2-mode js-mode))) | |||
| "Javascript mode to use for .js files." | |||
| :type 'symbol | |||
| :group 'programming | |||
| :options '(js2-mode js-mode)) | |||
| (defvar preferred-javascript-indent-level 4) | |||
| ;; Need to first remove from list if present, since elpa adds entries too, which | |||
| ;; may be in an arbitrary order | |||
| (eval-when-compile (require 'cl)) | |||
| (setq auto-mode-alist (cons `("\\.js\\(\\.erb\\)?\\'" . ,preferred-javascript-mode) | |||
| (loop for entry in auto-mode-alist | |||
| unless (eq preferred-javascript-mode (cdr entry)) | |||
| collect entry))) | |||
| ;; js2-mode | |||
| (after-load 'js2-mode | |||
| ;; Disable js2 mode's syntax error highlighting by default... | |||
| (setq-default js2-mode-show-parse-errors nil | |||
| js2-mode-show-strict-warnings nil) | |||
| ;; ... but enable it if flycheck can't handle javascript | |||
| (autoload 'flycheck-get-checker-for-buffer "flycheck") | |||
| (defun sanityinc/disable-js2-checks-if-flycheck-active () | |||
| (unless (flycheck-get-checker-for-buffer) | |||
| (set (make-local-variable 'js2-mode-show-parse-errors) t) | |||
| (set (make-local-variable 'js2-mode-show-strict-warnings) t))) | |||
| (add-hook 'js2-mode-hook 'sanityinc/disable-js2-checks-if-flycheck-active) | |||
| (add-hook 'js2-mode-hook '(lambda () (setq mode-name "JS2"))) | |||
| (setq-default | |||
| js2-basic-offset preferred-javascript-indent-level | |||
| js2-bounce-indent-p nil) | |||
| (after-load 'js2-mode | |||
| (js2-imenu-extras-setup))) | |||
| ;; js-mode | |||
| (setq-default js-indent-level preferred-javascript-indent-level) | |||
| (add-to-list 'interpreter-mode-alist (cons "node" preferred-javascript-mode)) | |||
| ;; Javascript nests {} and () a lot, so I find this helpful | |||
| (require-package 'rainbow-delimiters) | |||
| (dolist (hook '(js2-mode-hook js-mode-hook json-mode-hook)) | |||
| (add-hook hook 'rainbow-delimiters-mode)) | |||
| ;;; Coffeescript | |||
| (after-load 'coffee-mode | |||
| (setq coffee-js-mode preferred-javascript-mode | |||
| coffee-tab-width preferred-javascript-indent-level)) | |||
| (when (fboundp 'coffee-mode) | |||
| (add-to-list 'auto-mode-alist '("\\.coffee\\.erb\\'" . coffee-mode))) | |||
| ;; --------------------------------------------------------------------------- | |||
| ;; Run and interact with an inferior JS via js-comint.el | |||
| ;; --------------------------------------------------------------------------- | |||
| (setq inferior-js-program-command "js") | |||
| (defvar inferior-js-minor-mode-map (make-sparse-keymap)) | |||
| (define-key inferior-js-minor-mode-map "\C-x\C-e" 'js-send-last-sexp) | |||
| (define-key inferior-js-minor-mode-map "\C-\M-x" 'js-send-last-sexp-and-go) | |||
| (define-key inferior-js-minor-mode-map "\C-cb" 'js-send-buffer) | |||
| (define-key inferior-js-minor-mode-map "\C-c\C-b" 'js-send-buffer-and-go) | |||
| (define-key inferior-js-minor-mode-map "\C-cl" 'js-load-file-and-go) | |||
| (define-minor-mode inferior-js-keys-mode | |||
| "Bindings for communicating with an inferior js interpreter." | |||
| nil " InfJS" inferior-js-minor-mode-map) | |||
| (dolist (hook '(js2-mode-hook js-mode-hook)) | |||
| (add-hook hook 'inferior-js-keys-mode)) | |||
| ;; --------------------------------------------------------------------------- | |||
| ;; Alternatively, use skewer-mode | |||
| ;; --------------------------------------------------------------------------- | |||
| (when (and (>= emacs-major-version 24) (featurep 'js2-mode)) | |||
| (require-package 'skewer-mode) | |||
| (after-load 'skewer-mode | |||
| (add-hook 'skewer-mode-hook | |||
| (lambda () (inferior-js-keys-mode -1))))) | |||
| (provide 'init-javascript) | |||
| @@ -0,0 +1,22 @@ | |||
| (defun sanityinc/utf8-locale-p (v) | |||
| "Return whether locale string V relates to a UTF-8 locale." | |||
| (and v (string-match "UTF-8" v))) | |||
| (defun locale-is-utf8-p () | |||
| "Return t iff the \"locale\" command or environment variables prefer UTF-8." | |||
| (or (sanityinc/utf8-locale-p (and (executable-find "locale") (shell-command-to-string "locale"))) | |||
| (sanityinc/utf8-locale-p (getenv "LC_ALL")) | |||
| (sanityinc/utf8-locale-p (getenv "LC_CTYPE")) | |||
| (sanityinc/utf8-locale-p (getenv "LANG")))) | |||
| (when (or window-system (locale-is-utf8-p)) | |||
| (setq utf-translate-cjk-mode nil) ; disable CJK coding/encoding (Chinese/Japanese/Korean characters) | |||
| (set-language-environment 'utf-8) | |||
| (setq locale-coding-system 'utf-8) | |||
| (set-default-coding-systems 'utf-8) | |||
| (set-terminal-coding-system 'utf-8) | |||
| (unless (eq system-type 'windows-nt) | |||
| (set-selection-coding-system 'utf-8)) | |||
| (prefer-coding-system 'utf-8)) | |||
| (provide 'init-locales) | |||
| @@ -0,0 +1,6 @@ | |||
| (require-package 'markdown-mode) | |||
| (setq auto-mode-alist | |||
| (cons '("\\.\\(md\\|markdown\\)\\'" . markdown-mode) auto-mode-alist)) | |||
| (provide 'init-markdown) | |||
| @@ -0,0 +1,68 @@ | |||
| (require-package 'marmalade) | |||
| ;;; Handy code for uploading new versions of my own packages to marmalade | |||
| (autoload 'marmalade-upload-buffer "marmalade") | |||
| (defun sanityinc/parse-git-version (s) | |||
| "Return numeric version array parsed from S, or nil." | |||
| (ignore-errors (version-to-list s))) | |||
| (defun latest-version-from-git-tag () | |||
| (let ((versions | |||
| (remove-if #'null | |||
| (mapcar #'sanityinc/parse-git-version | |||
| (split-string (shell-command-to-string "git tag")))))) | |||
| (sort versions #'version-list-<) | |||
| (package-version-join (car (last versions))))) | |||
| (defun update-version-header (val) | |||
| (save-excursion | |||
| (goto-char (point-min)) | |||
| (re-search-forward "^;;;? ?Version:") | |||
| (kill-line) | |||
| (insert " " val))) | |||
| (defun submit-tar-to-marmalade (buf) | |||
| (interactive "bSubmit buffer library as tar: ") | |||
| (with-current-buffer buf | |||
| (let* ((tag (or (latest-version-from-git-tag) (error "Not tagged"))) | |||
| (library-name (file-name-nondirectory (file-name-sans-extension buffer-file-name))) | |||
| (package-dir-name (concat library-name "-" tag)) | |||
| (temp-working-dir (make-temp-file "emacs-marmalade" t)) | |||
| (dest (expand-file-name package-dir-name temp-working-dir)) | |||
| (tar-cmd (or (executable-find "gtar") | |||
| (executable-find "tar"))) | |||
| (tar (concat dest ".tar"))) | |||
| (message "Building package in %s" dest) | |||
| (make-directory dest) | |||
| (let ((command-line (format "cp *.el %s && (cd %s && perl -spi -e 's/\\{\\{VERSION\\}\\}/%s/' *.el) && (cd %s && %s cvf %s %s)" dest dest tag temp-working-dir tar-cmd tar package-dir-name))) | |||
| (shell-command command-line)) | |||
| (save-excursion | |||
| (shell-command (format "open %s" temp-working-dir)) | |||
| ;; (find-file tar) | |||
| ;; (marmalade-upload-buffer (current-buffer)) | |||
| ;; (delete-directory temp-working-dir t) | |||
| )))) | |||
| (defun submit-to-marmalade (buf) | |||
| "Submit the elisp library in BUF to Marmalade." | |||
| (interactive | |||
| (list | |||
| (let ((buffers (loop for b in (mapcar 'buffer-name (buffer-list)) | |||
| when (with-current-buffer b | |||
| (and buffer-file-name | |||
| (eq major-mode 'emacs-lisp-mode))) | |||
| collect b))) | |||
| (completing-read "Submit buffer: " buffers nil t nil nil (car buffers))))) | |||
| (with-current-buffer buf | |||
| (let ((tag (latest-version-from-git-tag))) | |||
| (unless tag | |||
| (error "Not tagged")) | |||
| (update-version-header tag) | |||
| (marmalade-upload-buffer buf) | |||
| (revert-buffer t t) | |||
| (message "Submitted version %s to marmalade" tag)))) | |||
| (provide 'init-marmalade) | |||
| @@ -0,0 +1,36 @@ | |||
| (add-auto-mode | |||
| 'nxml-mode | |||
| (concat "\\." | |||
| (regexp-opt | |||
| '("xml" "xsd" "sch" "rng" "xslt" "svg" "rss" | |||
| "gpx" "tcx" "plist")) | |||
| "\\'")) | |||
| (setq magic-mode-alist (cons '("<\\?xml " . nxml-mode) magic-mode-alist)) | |||
| (fset 'xml-mode 'nxml-mode) | |||
| (add-hook 'nxml-mode-hook (lambda () | |||
| (set (make-local-variable 'ido-use-filename-at-point) nil))) | |||
| (setq nxml-slash-auto-complete-flag t) | |||
| ;; See: http://sinewalker.wordpress.com/2008/06/26/pretty-printing-xml-with-emacs-nxml-mode/ | |||
| (defun sanityinc/pp-xml-region (begin end) | |||
| "Pretty format XML markup in region. The function inserts | |||
| linebreaks to separate tags that have nothing but whitespace | |||
| between them. It then indents the markup by using nxml's | |||
| indentation rules." | |||
| (interactive "r") | |||
| (save-excursion | |||
| (nxml-mode) | |||
| (goto-char begin) | |||
| (while (search-forward-regexp "\>[ \\t]*\<" nil t) | |||
| (backward-char) (insert "\n")) | |||
| (indent-region begin end))) | |||
| ;;---------------------------------------------------------------------------- | |||
| ;; Integration with tidy for html + xml | |||
| ;;---------------------------------------------------------------------------- | |||
| (require-package 'tidy) | |||
| (add-hook 'nxml-mode-hook (lambda () (tidy-build-menu nxml-mode-map))) | |||
| (provide 'init-nxml) | |||
| @@ -0,0 +1,131 @@ | |||
| (when (< emacs-major-version 24) | |||
| (require-package 'org)) | |||
| (require-package 'org-fstree) | |||
| ;(when *is-a-mac* | |||
| ; (require-package 'org-mac-link) | |||
| ; (autoload 'org-mac-grab-link "org-mac-link" nil t) | |||
| ; (require-package 'org-mac-iCal)) | |||
| (define-key global-map (kbd "C-c l") 'org-store-link) | |||
| (define-key global-map (kbd "C-c a") 'org-agenda) | |||
| ;; Various preferences | |||
| (setq org-log-done t | |||
| org-completion-use-ido t | |||
| org-edit-timestamp-down-means-later t | |||
| org-agenda-start-on-weekday nil | |||
| org-agenda-span 14 | |||
| org-agenda-include-diary t | |||
| org-agenda-window-setup 'current-window | |||
| org-fast-tag-selection-single-key 'expert | |||
| org-html-validation-link nil | |||
| org-export-kill-product-buffer-when-displayed t | |||
| org-tags-column 80) | |||
| ; Refile targets include this file and any file contributing to the agenda - up to 5 levels deep | |||
| (setq org-refile-targets (quote ((nil :maxlevel . 5) (org-agenda-files :maxlevel . 5)))) | |||
| ; Targets start with the file name - allows creating level 1 tasks | |||
| (setq org-refile-use-outline-path (quote file)) | |||
| ; Targets complete in steps so we start with filename, TAB shows the next level of targets etc | |||
| (setq org-outline-path-complete-in-steps t) | |||
| (setq org-todo-keywords | |||
| (quote ((sequence "TODO(t)" "STARTED(s)" "|" "DONE(d!/!)") | |||
| (sequence "WAITING(w@/!)" "SOMEDAY(S)" "|" "CANCELLED(c@/!)")))) | |||
| ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
| ;; Org clock | |||
| ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |||
| ;; Save the running clock and all clock history when exiting Emacs, load it on startup | |||
| (setq org-clock-persistence-insinuate t) | |||
| (setq org-clock-persist t) | |||
| (setq org-clock-in-resume t) | |||
| ;; Change task state to STARTED when clocking in | |||
| (setq org-clock-in-switch-to-state "STARTED") | |||
| ;; Save clock data and notes in the LOGBOOK drawer | |||
| (setq org-clock-into-drawer t) | |||
| ;; Removes clocked tasks with 0:00 duration | |||
| (setq org-clock-out-remove-zero-time-clocks t) | |||
| ;; Show clock sums as hours and minutes, not "n days" etc. | |||
| (setq org-time-clocksum-format | |||
| '(:hours "%d" :require-hours t :minutes ":%02d" :require-minutes t)) | |||
| ;; Show the clocked-in task - if any - in the header line | |||
| (defun sanityinc/show-org-clock-in-header-line () | |||
| (setq-default header-line-format '((" " org-mode-line-string " ")))) | |||
| (defun sanityinc/hide-org-clock-from-header-line () | |||
| (setq-default header-line-format nil)) | |||
| (add-hook 'org-clock-in-hook 'sanityinc/show-org-clock-in-header-line) | |||
| (add-hook 'org-clock-out-hook 'sanityinc/hide-org-clock-from-header-line) | |||
| (add-hook 'org-clock-cancel-hook 'sanityinc/hide-org-clock-from-header-line) | |||
| (after-load 'org-clock | |||
| (define-key org-clock-mode-line-map [header-line mouse-2] 'org-clock-goto) | |||
| (define-key org-clock-mode-line-map [header-line mouse-1] 'org-clock-menu)) | |||
| (require-package 'org-pomodoro) | |||
| (after-load 'org-agenda | |||
| (define-key org-agenda-mode-map (kbd "P") 'org-pomodoro)) | |||
| ;; ;; Show iCal calendars in the org agenda | |||
| ;; (when (and *is-a-mac* (require 'org-mac-iCal nil t)) | |||
| ;; (setq org-agenda-include-diary t | |||
| ;; org-agenda-custom-commands | |||
| ;; '(("I" "Import diary from iCal" agenda "" | |||
| ;; ((org-agenda-mode-hook #'org-mac-iCal))))) | |||
| ;; (add-hook 'org-agenda-cleanup-fancy-diary-hook | |||
| ;; (lambda () | |||
| ;; (goto-char (point-min)) | |||
| ;; (save-excursion | |||
| ;; (while (re-search-forward "^[a-z]" nil t) | |||
| ;; (goto-char (match-beginning 0)) | |||
| ;; (insert "0:00-24:00 "))) | |||
| ;; (while (re-search-forward "^ [a-z]" nil t) | |||
| ;; (goto-char (match-beginning 0)) | |||
| ;; (save-excursion | |||
| ;; (re-search-backward "^[0-9]+:[0-9]+-[0-9]+:[0-9]+ " nil t)) | |||
| ;; (insert (match-string 0)))))) | |||
| (after-load 'org | |||
| (define-key org-mode-map (kbd "C-M-<up>") 'org-up-element) | |||
| ; (when *is-a-mac* | |||
| ; (define-key org-mode-map (kbd "M-h") nil)) | |||
| (define-key org-mode-map (kbd "C-M-<up>") 'org-up-element) | |||
| ; (when *is-a-mac* | |||
| ; (define-key org-mode-map (kbd "C-c g") 'org-mac-grab-link))) | |||
| ) | |||
| (after-load 'org | |||
| (org-babel-do-load-languages | |||
| 'org-babel-load-languages | |||
| '((R . t) | |||
| (ditaa . t) | |||
| (dot . t) | |||
| (emacs-lisp . t) | |||
| (gnuplot . t) | |||
| (haskell . nil) | |||
| (latex . t) | |||
| (ledger . t) | |||
| (ocaml . nil) | |||
| (octave . t) | |||
| (python . t) | |||
| (ruby . t) | |||
| (screen . nil) | |||
| (sh . t) | |||
| (sql . nil) | |||
| (sqlite . t)))) | |||
| (provide 'init-org) | |||
| @@ -0,0 +1,4 @@ | |||
| (require-package 'php-mode) | |||
| (require-package 'smarty-mode) | |||
| (provide 'init-php) | |||
| @@ -0,0 +1,9 @@ | |||
| (setq auto-mode-alist | |||
| (append '(("SConstruct\\'" . python-mode) | |||
| ("SConscript\\'" . python-mode)) | |||
| auto-mode-alist)) | |||
| (require-package 'pip-requirements) | |||
| (provide 'init-python-mode) | |||
| @@ -0,0 +1,6 @@ | |||
| (recentf-mode 1) | |||
| (setq recentf-max-saved-items 1000 | |||
| recentf-exclude '("/tmp/" "/ssh:")) | |||
| (provide 'init-recentf) | |||
| @@ -0,0 +1,56 @@ | |||
| ;;; Set load path | |||
| (eval-when-compile (require 'cl)) | |||
| (defun sanityinc/add-subdirs-to-load-path (parent-dir) | |||
| "Adds every non-hidden subdir of PARENT-DIR to `load-path'." | |||
| (let* ((default-directory parent-dir)) | |||
| (progn | |||
| (setq load-path | |||
| (append | |||
| (loop for dir in (directory-files parent-dir) | |||
| unless (string-match "^\\." dir) | |||
| collecting (expand-file-name dir)) | |||
| load-path))))) | |||
| (sanityinc/add-subdirs-to-load-path | |||
| (expand-file-name "site-lisp/" user-emacs-directory)) | |||
| ;;; Utilities for grabbing upstream libs | |||
| (defun site-lisp-dir-for (name) | |||
| (expand-file-name (format "site-lisp/%s" name) user-emacs-directory)) | |||
| (defun site-lisp-library-el-path (name) | |||
| (expand-file-name (format "%s.el" name) (site-lisp-dir-for name))) | |||
| (defun download-site-lisp-module (name url) | |||
| (let ((dir (site-lisp-dir-for name))) | |||
| (message "Downloading %s from %s" name url) | |||
| (unless (file-directory-p dir) | |||
| (make-directory dir t)) | |||
| (add-to-list 'load-path dir) | |||
| (let ((el-file (site-lisp-library-el-path name))) | |||
| (url-copy-file url el-file t nil) | |||
| el-file))) | |||
| (defun ensure-lib-from-url (name url) | |||
| (unless (site-lisp-library-loadable-p name) | |||
| (byte-compile-file (download-site-lisp-module name url)))) | |||
| (defun site-lisp-library-loadable-p (name) | |||
| "Return whether or not the library `name' can be loaded from a | |||
| source file under ~/.emacs.d/site-lisp/name/" | |||
| (let ((f (locate-library (symbol-name name)))) | |||
| (and f (string-prefix-p (file-name-as-directory (site-lisp-dir-for name)) f)))) | |||
| ;; Download these upstream libs | |||
| (unless (> emacs-major-version 23) | |||
| (ensure-lib-from-url | |||
| 'package | |||
| "http://repo.or.cz/w/emacs.git/blob_plain/1a0a666f941c99882093d7bd08ced15033bc3f0c:/lisp/emacs-lisp/package.el")) | |||
| (provide 'init-site-lisp) | |||
| @@ -0,0 +1,6 @@ | |||
| (require 'ispell) | |||
| (when (executable-find ispell-program-name) | |||
| (require 'init-flyspell)) | |||
| (provide 'init-spelling) | |||
| @@ -0,0 +1,42 @@ | |||
| (require-package 'sql-indent) | |||
| (after-load 'sql | |||
| (require 'sql-indent)) | |||
| (defun sanityinc/pop-to-sqli-buffer () | |||
| "Switch to the corresponding sqli buffer." | |||
| (interactive) | |||
| (if sql-buffer | |||
| (progn | |||
| (pop-to-buffer sql-buffer) | |||
| (goto-char (point-max))) | |||
| (sql-set-sqli-buffer) | |||
| (when sql-buffer | |||
| (sanityinc/pop-to-sqli-buffer)))) | |||
| (after-load 'sql | |||
| (define-key sql-mode-map (kbd "C-c C-z") 'sanityinc/pop-to-sqli-buffer) | |||
| (add-hook 'sql-interactive-mode-hook 'sanityinc/never-indent) | |||
| (when (package-installed-p 'dash-at-point) | |||
| (defun sanityinc/maybe-set-dash-db-docset () | |||
| (when (eq sql-product 'postgres) | |||
| (setq dash-at-point-docset "psql"))) | |||
| (add-hook 'sql-mode-hook 'sanityinc/maybe-set-dash-db-docset) | |||
| (add-hook 'sql-interactive-mode-hook 'sanityinc/maybe-set-dash-db-docset) | |||
| (defadvice sql-set-product (after set-dash-docset activate) | |||
| (sanityinc/maybe-set-dash-db-docset)))) | |||
| (setq-default sql-input-ring-file-name | |||
| (expand-file-name ".sqli_history" user-emacs-directory)) | |||
| ;; See my answer to https://emacs.stackexchange.com/questions/657/why-do-sql-mode-and-sql-interactive-mode-not-highlight-strings-the-same-way/673 | |||
| (defun sanityinc/font-lock-everything-in-sql-interactive-mode () | |||
| (unless (eq 'oracle sql-product) | |||
| (sql-product-font-lock nil nil))) | |||
| (add-hook 'sql-interactive-mode-hook 'sanityinc/font-lock-everything-in-sql-interactive-mode) | |||
| (after-load 'page-break-lines | |||
| (push 'sql-mode page-break-lines-modes)) | |||
| (provide 'init-sql) | |||
| @@ -0,0 +1,75 @@ | |||
| (when (< emacs-major-version 24) | |||
| (require-package 'color-theme)) | |||
| (require-package 'color-theme-sanityinc-solarized) | |||
| (require-package 'color-theme-sanityinc-tomorrow) | |||
| ;;------------------------------------------------------------------------------ | |||
| ;; Old-style color theming support (via color-theme.el) | |||
| ;;------------------------------------------------------------------------------ | |||
| (defcustom window-system-color-theme 'color-theme-sanityinc-solarized-dark | |||
| "Color theme to use in window-system frames. | |||
| If Emacs' native theme support is available, this setting is | |||
| ignored: use `custom-enabled-themes' instead." | |||
| :type 'symbol) | |||
| (defcustom tty-color-theme 'color-theme-terminal | |||
| "Color theme to use in TTY frames. | |||
| If Emacs' native theme support is available, this setting is | |||
| ignored: use `custom-enabled-themes' instead." | |||
| :type 'symbol) | |||
| (unless (boundp 'custom-enabled-themes) | |||
| (defun color-theme-terminal () | |||
| (interactive) | |||
| (color-theme-sanityinc-solarized-dark)) | |||
| (defun apply-best-color-theme-for-frame-type (frame) | |||
| (with-selected-frame frame | |||
| (funcall (if window-system | |||
| window-system-color-theme | |||
| tty-color-theme)))) | |||
| (defun reapply-color-themes () | |||
| (interactive) | |||
| (mapcar 'apply-best-color-theme-for-frame-type (frame-list))) | |||
| (set-variable 'color-theme-is-global nil) | |||
| (add-hook 'after-make-frame-functions 'apply-best-color-theme-for-frame-type) | |||
| (add-hook 'after-init-hook 'reapply-color-themes) | |||
| (apply-best-color-theme-for-frame-type (selected-frame))) | |||
| ;;------------------------------------------------------------------------------ | |||
| ;; New-style theme support, in which per-frame theming is not possible | |||
| ;;------------------------------------------------------------------------------ | |||
| ;; If you don't customize it, this is the theme you get. | |||
| (setq-default custom-enabled-themes '(sanityinc-solarized-light)) | |||
| ;; Ensure that themes will be applied even if they have not been customized | |||
| (defun reapply-themes () | |||
| "Forcibly load the themes listed in `custom-enabled-themes'." | |||
| (dolist (theme custom-enabled-themes) | |||
| (unless (custom-theme-p theme) | |||
| (load-theme theme))) | |||
| (custom-set-variables `(custom-enabled-themes (quote ,custom-enabled-themes)))) | |||
| (add-hook 'after-init-hook 'reapply-themes) | |||
| ;;------------------------------------------------------------------------------ | |||
| ;; Toggle between light and dark | |||
| ;;------------------------------------------------------------------------------ | |||
| (defun light () | |||
| "Activate a light color theme." | |||
| (interactive) | |||
| (color-theme-sanityinc-solarized-light)) | |||
| (defun dark () | |||
| "Activate a dark color theme." | |||
| (interactive) | |||
| (color-theme-sanityinc-solarized-dark)) | |||
| (provide 'init-themes) | |||
| @@ -0,0 +1,87 @@ | |||
| (defmacro after-load (feature &rest body) | |||
| "After FEATURE is loaded, evaluate BODY." | |||
| (declare (indent defun)) | |||
| `(eval-after-load ,feature | |||
| '(progn ,@body))) | |||
| ;;---------------------------------------------------------------------------- | |||
| ;; Handier way to add modes to auto-mode-alist | |||
| ;;---------------------------------------------------------------------------- | |||
| (defun add-auto-mode (mode &rest patterns) | |||
| "Add entries to `auto-mode-alist' to use `MODE' for all given file `PATTERNS'." | |||
| (dolist (pattern patterns) | |||
| (add-to-list 'auto-mode-alist (cons pattern mode)))) | |||
| ;;---------------------------------------------------------------------------- | |||
| ;; String utilities missing from core emacs | |||
| ;;---------------------------------------------------------------------------- | |||
| (defun sanityinc/string-all-matches (regex str &optional group) | |||
| "Find all matches for `REGEX' within `STR', returning the full match string or group `GROUP'." | |||
| (let ((result nil) | |||
| (pos 0) | |||
| (group (or group 0))) | |||
| (while (string-match regex str pos) | |||
| (push (match-string group str) result) | |||
| (setq pos (match-end group))) | |||
| result)) | |||
| (defun sanityinc/string-rtrim (str) | |||
| "Remove trailing whitespace from `STR'." | |||
| (replace-regexp-in-string "[ \t\n]*$" "" str)) | |||
| ;;---------------------------------------------------------------------------- | |||
| ;; Find the directory containing a given library | |||
| ;;---------------------------------------------------------------------------- | |||
| (autoload 'find-library-name "find-func") | |||
| (defun sanityinc/directory-of-library (library-name) | |||
| "Return the directory in which the `LIBRARY-NAME' load file is found." | |||
| (file-name-as-directory (file-name-directory (find-library-name library-name)))) | |||
| ;;---------------------------------------------------------------------------- | |||
| ;; Delete the current file | |||
| ;;---------------------------------------------------------------------------- | |||
| (defun delete-this-file () | |||
| "Delete the current file, and kill the buffer." | |||
| (interactive) | |||
| (or (buffer-file-name) (error "No file is currently being edited")) | |||
| (when (yes-or-no-p (format "Really delete '%s'?" | |||
| (file-name-nondirectory buffer-file-name))) | |||
| (delete-file (buffer-file-name)) | |||
| (kill-this-buffer))) | |||
| ;;---------------------------------------------------------------------------- | |||
| ;; Rename the current file | |||
| ;;---------------------------------------------------------------------------- | |||
| (defun rename-this-file-and-buffer (new-name) | |||
| "Renames both current buffer and file it's visiting to NEW-NAME." | |||
| (interactive "sNew name: ") | |||
| (let ((name (buffer-name)) | |||
| (filename (buffer-file-name))) | |||
| (unless filename | |||
| (error "Buffer '%s' is not visiting a file!" name)) | |||
| (if (get-buffer new-name) | |||
| (message "A buffer named '%s' already exists!" new-name) | |||
| (progn | |||
| (when (file-exists-p filename) | |||
| (rename-file filename new-name 1)) | |||
| (rename-buffer new-name) | |||
| (set-visited-file-name new-name))))) | |||
| ;;---------------------------------------------------------------------------- | |||
| ;; Browse current HTML file | |||
| ;;---------------------------------------------------------------------------- | |||
| (defun browse-current-file () | |||
| "Open the current file as a URL using `browse-url'." | |||
| (interactive) | |||
| (let ((file-name (buffer-file-name))) | |||
| (if (tramp-tramp-file-p file-name) | |||
| (error "Cannot open tramp file") | |||
| (browse-url (concat "file://" file-name))))) | |||
| (provide 'init-utils) | |||