diff options
-rw-r--r-- | .gitignore | 3 | ||||
-rw-r--r-- | Makefile | 19 | ||||
-rw-r--r-- | init.el | 1854 | ||||
-rw-r--r-- | lisp/init-diminish.el | 39 | ||||
-rw-r--r-- | lisp/init-elisp.el | 46 | ||||
-rw-r--r-- | lisp/init-external.el | 350 | ||||
-rw-r--r-- | lisp/init-general.el | 110 | ||||
-rw-r--r-- | lisp/init-god.el | 68 | ||||
-rw-r--r-- | lisp/init-haskell.el | 40 | ||||
-rw-r--r-- | lisp/init-helm.el | 72 | ||||
-rw-r--r-- | lisp/init-mail.el | 274 | ||||
-rw-r--r-- | lisp/init-server.el | 46 | ||||
-rw-r--r-- | lisp/init-yas.el | 47 | ||||
-rw-r--r-- | lisp/km-abbrev.el (renamed from lisp/init-abbrev.el) | 19 | ||||
-rw-r--r-- | lisp/km-ace-link.el (renamed from lisp/init-ace.el) | 91 | ||||
-rw-r--r-- | lisp/km-avy.el | 70 | ||||
-rw-r--r-- | lisp/km-bib.el (renamed from lisp/init-bib.el) | 36 | ||||
-rw-r--r-- | lisp/km-buffer-cleanup.el | 52 | ||||
-rw-r--r-- | lisp/km-buffers.el (renamed from lisp/init-buffers.el) | 24 | ||||
-rw-r--r-- | lisp/km-compile.el | 94 | ||||
-rw-r--r-- | lisp/km-diff.el | 57 | ||||
-rw-r--r-- | lisp/km-dired.el (renamed from lisp/init-dired.el) | 107 | ||||
-rw-r--r-- | lisp/km-editing.el (renamed from lisp/init-editing.el) | 213 | ||||
-rw-r--r-- | lisp/km-ess.el (renamed from lisp/init-ess.el) | 35 | ||||
-rw-r--r-- | lisp/km-files.el (renamed from lisp/init-files.el) | 119 | ||||
-rw-r--r-- | lisp/km-framewin.el (renamed from lisp/init-framewin.el) | 34 | ||||
-rw-r--r-- | lisp/km-god.el (renamed from lisp/init-bog.el) | 25 | ||||
-rw-r--r-- | lisp/km-helm.el (renamed from lisp/init-view.el) | 39 | ||||
-rw-r--r-- | lisp/km-hydra.el | 203 | ||||
-rw-r--r-- | lisp/km-magit.el (renamed from lisp/init-git.el) | 268 | ||||
-rw-r--r-- | lisp/km-mail.el | 150 | ||||
-rw-r--r-- | lisp/km-org.el (renamed from lisp/init-org.el) | 318 | ||||
-rw-r--r-- | lisp/km-outline.el (renamed from lisp/init-outline.el) | 52 | ||||
-rw-r--r-- | lisp/km-projectile.el (renamed from lisp/init-projectile.el) | 166 | ||||
-rw-r--r-- | lisp/km-python.el (renamed from lisp/init-python.el) | 82 | ||||
-rw-r--r-- | lisp/km-shell.el | 117 | ||||
-rw-r--r-- | lisp/km-snakemake.el (renamed from lisp/init-snakemake.el) | 38 | ||||
-rw-r--r-- | lisp/km-tex.el (renamed from lisp/init-tex.el) | 22 | ||||
-rw-r--r-- | lisp/km-theme.el (renamed from lisp/init-appearance.el) | 20 | ||||
-rw-r--r-- | lisp/km-util.el (renamed from lisp/init-util.el) | 6 | ||||
-rw-r--r-- | lisp/km-webjump.el | 48 | ||||
-rw-r--r-- | lisp/setkey.el | 48 |
42 files changed, 2941 insertions, 2580 deletions
@@ -1,7 +1,7 @@ auto-save-list cache bookmarks -/lisp/init-untracked.el +/lisp/km-untracked.el /.mc-lists.el /projectile-bookmarks.eld /projectile.cache @@ -21,3 +21,4 @@ bookmarks /network-security.data /.pydoc-names /eww-bookmarks +/lisp/km-emacs-autoloads.el diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..54b6d92 --- /dev/null +++ b/Makefile @@ -0,0 +1,19 @@ + +LOAD_PATH ?= +BATCH = emacs -Q --batch $(LOAD_PATH) + +LOADDEFS_FNAME = km-emacs-autoloads.el +LOADDEFS = lisp/$(LOADDEFS_FNAME) + +ELS = $(shell find lisp -maxdepth 1 \ + -type f \( -name "*.el" -and ! -name "$(LOADDEFS_FNAME)" \) -print) + +$(LOADDEFS): $(ELS) + @$(BATCH) --eval "\ + (let* ((make-backup-files nil) \ + (default-directory \"$(CURDIR)\") \ + (generated-autoload-file (expand-file-name \"$(LOADDEFS)\"))) \ + (update-directory-autoloads \"lisp/\"))" + +%.elc: %.el + @$(BATCH) -f batch-byte-compile $< @@ -22,9 +22,6 @@ ;; (package-initialize) -(defvar km/init-lisp-dir (expand-file-name "lisp/" user-emacs-directory)) -(add-to-list 'load-path km/init-lisp-dir) - (require 'package) (add-to-list 'package-archives '("melpa" . "http://melpa.org/packages/")) (package-initialize) @@ -34,52 +31,1837 @@ (require 'pallet) (pallet-mode 1) -(require 'init-appearance) - (require 'cl-lib) (require 'dash) (require 's) -(require 'init-util) -(require 'init-general) -(require 'init-abbrev) -(require 'init-diminish) +(require 'bind-key) +(require 'use-package) +(require 'use-package-chords) +(key-chord-mode 1) + +(defvar km/init-lisp-dir (expand-file-name "lisp/" user-emacs-directory)) +(add-to-list 'load-path km/init-lisp-dir) + +(require 'km-util) +(require 'km-emacs-autoloads) + + +;;; Appearance + +(setq inhibit-splash-screen t + initial-scratch-message nil) + +(blink-cursor-mode -1) +(menu-bar-mode -1) +(scroll-bar-mode -1) +(tool-bar-mode -1) + +(column-number-mode) +(line-number-mode) +(size-indication-mode) + +(require 'km-theme) + + +;;; Custom prefix maps + +(pcase-dolist (`(,key ,map) '(("C-c c" km/compile-map) + ("C-c e" km/editing-map) + ("C-c f" km/file-map) + ("C-c g" km/git-map) + ("C-c k" km/kill-map) + ("C-x m" km/mail-map) + ("C-c o" km/global-org-map) + ("C-c z" km/external-map))) + (define-prefix-command map) + (global-set-key (kbd key) map)) + + +;;; Org + +(use-package org + :load-path "~/src/emacs/org-mode/lisp/" + :mode ("\\.org.txt\\'" . org-mode) + :init + (require 'org-loaddefs) + (add-to-list 'load-path "~/src/emacs/org-mode/contrib/lisp/" t) + (add-to-list 'Info-directory-list "~/src/emacs/org-mode/doc/") + (bind-keys :map km/global-org-map + ("b" . org-iswitchb) + ("l" . org-store-link) + ("o" . org-open-at-point) + ("s" . org-save-all-org-buffers) + ("w" . org-refile-goto-last-stored)) + (define-prefix-command 'km/org-prefix-map) + :config + (setq org-log-done t + org-log-into-drawer t + org-clock-into-drawer t + org-todo-keywords '((sequence "TODO(t)" "STARTED(s)" "WAITING(w@)" + "|" "DONE(d)" "NA(n@)"))) + (setq org-catch-invisible-edits 'error + org-special-ctrl-k t + org-insert-heading-respect-content t + org-M-RET-may-split-line nil + org-adapt-indentation nil + org-blank-before-new-entry '((heading . t) (plain-list-item . auto))) + (setq org-use-speed-commands t + org-use-extra-keys t + org-fast-tag-selection-single-key 'expert) + (setq org-outline-path-complete-in-steps nil + org-goto-interface 'outline-path-completionp + org-goto-max-level 3) + + (setq org-default-notes-file "~/notes/agenda/tasks.org") + (setq org-agenda-text-search-extra-files + (file-expand-wildcards "~/notes/extra/*.org")) + + (setq org-reverse-note-order t) + (setq org-refile-targets '((nil :maxlevel . 2)) + org-refile-cache nil) + + (setq org-link-search-must-match-exact-headline nil) + + (setq org-confirm-babel-evaluate nil + org-src-fontify-natively t) + + (org-babel-do-load-languages + 'org-babel-load-languages + '((shell . t) + (python . t) + (R . t) + (emacs-lisp . t) + (latex . t))) + + (defadvice org-open-file (after km/org-open-add-to-recentf activate) + (recentf-add-file path)) + + (put 'org-goto-max-level 'safe-local-variable #'integerp) + + (add-to-list 'org-latex-packages-alist '("" "amsmath" t)) + + (setq org-structure-template-alist + (append '(("p" "#+property: ") + ("o" "#+options: ") + ("d" "#+date: ") + ("t" "#+title: ") + ("S" "#+setupfile: ?") + ("n" "#+name: ") + ("w" "#+begin_note\n ?\n#+end_note") + ("C" "#+caption: ") + ("b" "#+label: ") + ("r" "#+attr_latex: ") + ("R" "#+attr_html: ")) + (mapcar (lambda (i) (list (car i) (downcase (cadr i)))) + org-structure-template-alist))) + + (add-hook 'next-error-hook (lambda () + (when (eq major-mode 'org-mode) + (org-show-context)))) + + (bind-keys :map org-mode-map + ("C-c l" . org-goto) + ("C-c m" . km/org-prefix-map) + ;; Don't let `org-cycle-agenda-files' binding override + ;; custom `backward-kill-word' binding + ;; (`org-cycle-agenda-files' is still bound to C-,). + ("C-'" . nil) + ("C-c C-x d" . org-metadown) + ("C-c C-x n" . org-next-item) + ("C-c C-x s" . org-set-property) + ("C-c C-x p" . org-previous-item) + ("C-c C-x w" . org-insert-drawer))) + +(use-package ox-latex + :defer t + :config + (add-to-list 'org-latex-classes + '("short" + "\\documentclass{short}" + ("\\section{%s}" . "\\section*{%s}") + ("\\subsection{%s}" . "\\subsection*{%s}") + ("\\subsubsection{%s}" . "\\subsubsection*{%s}") + ("\\paragraph{%s}" . "\\paragraph*{%s}") + ("\\subparagraph{%s}" . "\\subparagraph*{%s}")))) + +(use-package org-table + :defer t + :diminish (orgtbl-mode . "Ot")) + +(use-package org-capture + :defer t + :init (define-key km/global-org-map "c" #'org-capture) + :config + (setq org-capture-templates + '(("t" "task" entry (file+headline "~/notes/tasks.org" "Inbox") + "* TODO %?%i" :prepend t) + ("d" "date" entry (file+headline "~/notes/calendar.org" "Inbox") + "* %?%i" :prepend t) + ("b" "bookmark" entry (file+headline "~/notes/bookmarks.org" "Inbox") + "* %?%i" :prepend t) + ("v" "Visit" checkitem (file+headline "~/notes/tasks.org" "Visit") + "- [ ] %?%i\n" :prepend t) + ("r" "Revisit" checkitem (file+headline "~/notes/tasks.org" "Revisit") + "- [ ] %?%i\n" :prepend t) + ;; Link counterparts + ("T" "task link" entry (file+headline "~/notes/tasks.org" "Inbox") + "* TODO %?%i\n\n%a" :prepend t) + ("D" "date link" entry (file+headline "~/notes/calendar.org" "Inbox") + "* %?%i\n\n%a" :prepend t) + ("B" "bookmark link" entry + (file+headline "~/notes/bookmarks.org" "Inbox") + "* %?%i\n\n%a" :prepend t) + ;; Clipboard + ("x" "task clipboard" entry (file+headline "~/notes/tasks.org" "Inbox") + "* TODO %?%i\n\n%x" :prepend t) + ("X" "bookmark clipboard" entry + (file+headline "~/notes/bookmarks.org" "Inbox") + "* %?%i\n\n%x" :prepend t)))) + +(use-package org-agenda + :defer t + :init (define-key km/global-org-map "a" #'org-agenda) + :config + (setq org-agenda-restore-windows-after-quit t + org-agenda-window-setup 'only-window + org-agenda-sticky t) + (setq org-agenda-dim-blocked-tasks nil + org-agenda-show-all-dates t + org-agenda-skip-deadline-if-done t + org-agenda-skip-scheduled-if-done t + org-agenda-start-on-weekday nil + org-agenda-use-time-grid nil) + (setq org-agenda-sorting-strategy + '((agenda time-up deadline-up scheduled-up priority-down category-keep) + (todo priority-down category-keep) + (tags priority-down category-keep) + (search category-keep))) + (setq org-agenda-custom-commands + '(("d" todo "DONE" nil) + ("u" "Unschedule TODO entries" alltodo "" + ((org-agenda-skip-function + (lambda nil + (org-agenda-skip-entry-if 'scheduled 'deadline + 'regexp "\n]+>"))) + (org-agenda-overriding-header "Unscheduled TODO entries: "))) + ("p" "Past timestamps" tags "TIMESTAMP<=\"<now>\""))) + + ;; Bind `org-agenda-follow-mode' to same key as + ;; `next-error-follow-minor-mode'. + (define-key org-agenda-mode-map (kbd "C-c C-f") #'org-agenda-follow-mode) + ;; Free up 'j' for `km/org-agenda-avy-goto-subword-1'. + (define-key org-agenda-mode-map (kbd "C-j") #'org-agenda-goto-date)) + +(use-package org-contacts + :defer t + :after org + :init + (setq org-contacts-files '("~/notes/contacts.org")) + (after 'org-capture + (add-to-list 'org-capture-templates + '("a" "email address" entry + (file+headline "~/notes/contacts.org" "Inbox") + " +** %(org-contacts-template-name) +:PROPERTIES: +:EMAIL: %(org-contacts-template-email) +:END:")))) + +(use-package km-org + :defer t + :after org-agenda + :init + (bind-keys :map km/global-org-map + ("j" . km/org-goto-agenda-heading) + ("m" . km/org-open-default-notes-file-inbox) + ("n" . km/org-agenda-add-or-remove-file)) + (bind-keys :map km/org-prefix-map + ("c" . km/org-clone-and-shift-by-repeater) + ("d" . km/org-link-dired-jump) + ("D" . km/org-delete-checked-items) + ("i" . km/org-refile-list-item) + ("l" . km/org-remove-title-leader) + ("n" . km/org-normalize-spaces) + ("s" . km/org-sort-parent) + ("w" . km/org-refile-to-other-org-buffer)) + (bind-keys :map km/file-map + ("a" . km/org-open-annex-file) + ("o" . km/org-open-file) + ("p" . km/org-open-file-at-point) + ("r" . km/org-open-recent-file)) + + (define-key ctl-x-4-map "o" #'km/org-switch-to-buffer-other-window) + + (after 'org + (define-key org-mode-map (kbd "C-c C-x B") + #'km/org-tree-to-indirect-buffer-current-window) + (define-key org-mode-map [remap org-tree-to-indirect-buffer] + #'km/org-tree-to-indirect-buffer) + (define-key org-mode-map [remap org-refile] #'km/org-refile-dwim) + + (add-to-list 'org-speed-commands-user '("o" . km/org-open-at-point-stay)) + (add-to-list 'org-speed-commands-user '("w" . km/org-refile-dwim)) + + (setq org-refile-target-verify-function #'km/org-refile-verify-target) + (add-hook 'org-after-refile-insert-hook #'km/org-maybe-sort-parent) + + (org-add-link-type "pmid" #'km/org-pmid-open)) + (after 'org-agenda + (setq km/org-agenda-file-directory "~/notes/agenda/" + org-agenda-files (list km/org-agenda-file-directory)) + (add-hook 'org-agenda-mode-hook #'km/org-agenda-cd-and-read-dir-locals) + (add-hook 'org-agenda-finalize-hook #'km/org-agenda-store-current-span)) + (after 'ox-md + (advice-add 'org-md-paragraph :filter-return #'km/org-md--fill-string)) + :config + (add-to-list 'safe-local-variable-values + (cons 'org-refile-targets km/org-agenda-refile-targets))) + +(use-package poporg + :defer t + :init + (define-key km/global-org-map "p" #'poporg-dwim) + :config + (define-key poporg-mode-map (kbd "C-c C-c") #'poporg-edit-exit)) + +(use-package org-link-edit + :load-path "~/src/emacs/org-link-edit/" + :defer t + :init (require 'org-link-edit-autoloads)) + +(use-package bog + :load-path "~/src/emacs/bog/" + :defer t + :init + (require 'bog-autoloads) + (after 'org + (add-hook 'org-mode-hook #'bog-mode)) + (setq bog-keymap-prefix (kbd "C-c b")) + (global-set-key bog-keymap-prefix bog-command-map) + :config + (setq bog-subdirectory-group 2 + bog-combined-bib-ignore-not-found t + bog-use-citekey-cache t)) + + +;;; Editing, navigation, and search + +(setq set-mark-command-repeat-pop t) +(setq recenter-positions '(top middle bottom)) + +(setq-default indicate-empty-lines t + indent-tabs-mode nil) + +(electric-indent-mode -1) +(electric-pair-mode) +(show-paren-mode) + +(put 'upcase-region 'disabled nil) +(put 'downcase-region 'disabled nil) + +(put 'set-goal-column 'disabled nil) + +(bind-keys :map km/editing-map + ("C-i" . indent-relative) + ("l" . toggle-truncate-lines)) + +(bind-keys :map occur-mode-map + ("n" . next-line) + ("p" . previous-line)) +(bind-keys :map search-map + ("s" . query-replace) + ("S" . replace-string) + ("r" . query-replace-regexp) + ("R" . replace-regexp)) + +;; Avoid shift key for `backward-paragraph' and `forward-paragraph'. +(global-set-key (kbd "M-}") nil) +(global-set-key (kbd "M-]") #'forward-paragraph) +(global-set-key (kbd "M-{") nil) +(global-set-key (kbd "M-[") #'backward-paragraph) + +(global-set-key (kbd "C-z") #'zap-to-char) +(use-package misc + :bind ("M-z" . zap-up-to-char)) + +(global-set-key (kbd "C-'") #'backward-kill-word) + +(put 'fill-paragraph-function 'safe-local-variable + (lambda (v) (equal v (lambda (_) t)))) + +(key-chord-define-global "qp" #'fill-paragraph) + +(use-package align + :bind ("C-x \\" . align-regexp)) + +(use-package expand-region + :bind ("C-." . er/expand-region)) + +(use-package iedit + :defer t + :init (define-key km/editing-map "i" #'iedit-mode) + :config + (setq iedit-toggle-key-default nil)) + +(use-package easy-kill + :defer t + :init + (global-set-key [remap kill-ring-save] #'easy-kill)) + +(use-package whitespace + :defer 5 + :diminish global-whitespace-mode + :config + (setq whitespace-style '(face trailing indentation)) + (global-whitespace-mode)) + +(use-package km-editing + :defer t + :chords ("jx" . km/toggle-line-or-region-comment) + :init + (define-key search-map "o" #'km/occur) + (define-key narrow-map "c" #'km/narrow-to-comment-heading) + + (bind-keys :map km/editing-map + ("f" . km/fill-surrounding-indented) + ("u" . km/unfill-paragraph)) + :config + (bind-keys :map km/kill-map + ("." . km/kill-sentence-at-point) + ("j" . km/join-next-line-with-space) + ("l" . km/kill-line-at-point) + ("p" . km/kill-paragraph-at-point) + ("s" . km/kill-string-at-point) + ("w" . km/kill-word-at-point))) + +(use-package km-outline + :defer t) + +(put 'narrow-to-page 'disabled nil) +(put 'narrow-to-region 'disabled nil) + +(use-package narrow-indirect + :defer t + :init + (bind-keys :map ctl-x-4-map + ("nd" . ni-narrow-to-defun-indirect-other-window) + ("nn" . ni-narrow-to-region-indirect-other-window) + ("np" . ni-narrow-to-page-indirect-other-window))) + +(use-package avy + :defer t + :chords ("jf" . avy-goto-subword-1) + :init + (define-key isearch-mode-map (kbd "C-'") #'avy-isearch)) + +(use-package ace-link + :defer t + :init + (after 'org + (define-key org-mode-map (kbd "C-c m o") #'ace-link-org)) + (after 'info + (define-key Info-mode-map "o" #'ace-link-info)) + (after 'compile + (define-key compilation-mode-map "o" #'ace-link-compilation)) + (after 'help-mode + (define-key help-mode-map "o" #'ace-link-help)) + (after 'woman + (define-key woman-mode-map "o" #'ace-link-woman)) + (after 'eww + (define-key eww-link-keymap "o" #'ace-link-eww) + (define-key eww-mode-map "o" #'ace-link-eww))) + +(use-package km-ace-link + :defer t + :init + (after 'dired + ;; This overrides the binding for `dired-find-file-other-window'. + (define-key dired-mode-map "o" #'km/ace-link-dired) + (define-key dired-mode-map "r" #'dired-find-file-other-window)) + (after 'notmuch + (define-key notmuch-hello-mode-map "o" #'km/ace-link-widget)) + (after 'gnus-sum + (define-key gnus-summary-mode-map "o" #'km/ace-link-widget)) + (after 'gnus-art + (define-key gnus-article-mode-map "o" #'km/ace-link-widget))) + +(use-package km-avy + :defer t + :init + (after 'gnus-sum + (define-key gnus-summary-mode-map "j" + #'km/gnus-avy-goto-subword-and-select)) + (after 'grep + (define-key grep-mode-map "j" #'km/grep-avy-goto-subword-1)) + (after 'org-agenda + (define-key org-agenda-mode-map "j" #'km/org-agenda-avy-goto-subword-1)) + (after 'magit + (define-key magit-refs-mode-map "j" #'km/magit-avy-goto-subword-1)) + (after 'magit-log + (define-key magit-log-mode-map "j" #'km/magit-avy-goto-subword-1) + (define-key magit-cherry-mode-map "j" #'km/magit-avy-goto-subword-1)) + (after 'replace + (define-key occur-mode-map "j" #'km/occur-avy-goto-subword-1))) + + +;;; Buffers and files + +(setq require-final-newline t) + +;; Disable `suspend-frame' binding. +(global-set-key (kbd "C-x C-z") nil) + +(use-package uniquify + :config + (setq uniquify-buffer-name-style 'forward)) + +(use-package autorevert + :config + (setq auto-revert-use-notify nil) + (global-auto-revert-mode)) + +(use-package ibuffer + :bind ("C-x C-b" . ibuffer) + :init + (setq ibuffer-expert t + ibuffer-restore-window-config-on-quit t + ibuffer-show-empty-filter-groups nil)) + +(use-package km-buffer-cleanup + :config + (add-hook 'before-save-hook #'km/cleanup-buffer) + (define-key km/editing-map "t" #'km/toggle-prevent-cleanup)) + +(use-package km-buffers + :defer t + :chords ("js" . km/save-buffers) + :bind ("C-x k" . km/kill-buffer)) + +(use-package ffap + :defer t + :config + (setq ffap-machine-p-known 'reject)) + +(use-package tramp + :defer t + :config + (setq tramp-default-method "sshx")) + +(use-package recentf + :config + (setq recentf-max-menu-items 15 + recentf-max-saved-items 200 + recentf-save-file "~/.emacs.d/cache/recentf") + (recentf-mode)) + +(use-package nlines + :load-path "~/src/emacs/nlines/" + :defer t + :init + (require 'nlines-autoloads) + (define-key km/file-map "l" #'nlines-run-command)) + +(use-package view + :diminish (view-mode . "Vw") + :defer t + :chords ("hq" . view-mode) + :init + (define-key ctl-x-4-map "v" #'view-file-other-window) + :config + (bind-keys :map view-mode-map + ("l" . recenter-top-bottom) + ("f" . forward-word) + ("b" . backward-word) + ("]" . forward-paragraph) + ("[" . backward-paragraph) + ("j" . avy-goto-subword-1))) + +(use-package km-files + :bind (("C-c s" . km/scratch-find-file) + ("C-x C-w" . km/write-file)) + :init + (bind-keys :map km/file-map + ("j" . km/dired-jump-file-at-point) + ("n" . km/rename-current-buffer-file) + ("R" . km/find-file-as-root)) + (bind-keys :map ctl-x-4-map + ("r" . km/recentf-find-file-other-window) + ("s" . km/scratch-find-file-other-window))) + + +;;; Frames and windows + +(use-package winner + :defer 10 + :chords ("lq" . winner-undo) + :config + (winner-mode)) + +(use-package km-framewin + :defer t + :init + (define-key ctl-x-4-map "c" + #'km/clone-indirect-buffer-other-window-and-widen)) + +(use-package ace-window + :commands km/ace-window + :chords ("jw" . km/ace-window) + :init + (defun km/ace-window (arg) + "Run `ace-window', swapping single and double C-u's." + (interactive "p") + (cl-case arg + (4 (setq arg 16)) + (16 (setq arg 4))) + (ace-window arg)) + :config + (setq aw-keys '(?a ?s ?d ?f ?g ?h ?j ?k ?l) + aw-scope 'frame)) + + +;;; Projectile + +(use-package projectile + :defer t + :diminish projectile-mode + :chords ("jq" . projectile-commander) + :init + (define-prefix-command 'km/projectile-ctl-x-4-map) + (define-key ctl-x-4-map "p" 'km/projectile-ctl-x-4-map) + (bind-keys :map km/projectile-ctl-x-4-map + ("C-o" . projectile-display-buffer) + ("b" . projectile-switch-to-buffer-other-window) + ("d" . projectile-find-dir-other-window) + ("f" . projectile-find-file-other-window) + ("t" . projectile-find-implementation-or-test-other-window)) + :config + (setq projectile-find-dir-includes-top-level t + projectile-completion-system 'helm + projectile-use-git-grep t) + + (defun km/projectile-ignore-directory-p (name) + (or (file-remote-p name) + (string-prefix-p "/tmp/" name))) + (setq projectile-ignored-project-function #'km/projectile-ignore-directory-p) + + (projectile-register-project-type 'snakemake + '("Snakefile") "snakemake -p" "") + + (bind-keys :map projectile-command-map + ("g" . projectile-vc) + ("i" . projectile-ibuffer) + ("I" . projectile-invalidate-cache) + ("l" . projectile-project-buffers-other-buffer) + ("q" . projectile-replace) + ("s" . projectile-grep)) + + ;; I'm redefining a lot of bindings, so unset pre-defined methods + ;; and define everyting here. + (setq projectile-commander-methods nil) + + (def-projectile-commander-method ?c + "Run project compilation command." + (call-interactively 'projectile-compile-project)) + (def-projectile-commander-method ?D + "Find a project directory in other window." + (call-interactively 'projectile-find-dir-other-window)) + (def-projectile-commander-method ?F + "Find project file in other window." + (call-interactively 'projectile-find-file-other-window)) + (def-projectile-commander-method ?g + "Open project root in vc-dir or magit." + (projectile-vc)) + (def-projectile-commander-method ?i + "Open an IBuffer window showing all buffers in the current project." + (call-interactively 'projectile-ibuffer)) + (def-projectile-commander-method ?o + "Display a project buffer in other window." + (call-interactively 'projectile-display-buffer)) + (def-projectile-commander-method ?O + "Run multi-occur on project buffers." + (projectile-multi-occur)) + (def-projectile-commander-method ?r + "Find recently visited file in project." + (projectile-recentf)) + (def-projectile-commander-method ?s + "Run grep on project." + (call-interactively #'projectile-grep)) + + (projectile-global-mode)) + +(use-package helm-projectile + :after projectile + :config + (bind-keys :map projectile-command-map + ("b" . helm-projectile-switch-to-buffer) + ("d" . helm-projectile-find-dir) + ("f" . helm-projectile-find-file) + ("F" . helm-projectile-find-file-in-known-projects) + ("p" . helm-projectile-switch-project) + ("r" . helm-projectile-recentf)) + (def-projectile-commander-method ?b + "Find project buffer." + (call-interactively 'helm-projectile-switch-to-buffer)) + (def-projectile-commander-method ?d + "Find directory in project." + (helm-projectile-find-dir)) + (def-projectile-commander-method ?f + "Open project file." + (helm-projectile-find-file)) + (def-projectile-commander-method ?p + "Switch project." + (helm-projectile-switch-project))) + +(use-package km-projectile + :defer t + :chords ("gp" . km/projectile-switch-project) + :init + (define-key km/projectile-ctl-x-4-map "v" + #'km/projectile-view-file-other-window) + + (after 'projectile + (bind-keys :map projectile-command-map + ("4 v" . km/projectile-view-file-other-window) + ("." . km/projectile-copy-project-filename-as-kill) + ("e" . km/projectile-restore-thing) + ("k" . km/projectile-kill-buffers) + ("v" . km/projectile-view-file) + ("w" . km/projectile-save-thing)) + + (def-projectile-commander-method ?e + "Restore saved thing." + (km/projectile-restore-thing)) + (def-projectile-commander-method ?k + "Kill all project buffers." + (call-interactively #'km/projectile-kill-buffers)) + (def-projectile-commander-method ?v + "View project file." + (km/projectile-view-file)) + (def-projectile-commander-method ?V + "View project file in other window." + (km/projectile-view-file-other-window)) + (def-projectile-commander-method ?w + "Save thing." + (call-interactively #'km/projectile-save-thing)))) + + +;;; Version control + +(use-package vc + :defer t + :config + (setq vc-follow-symlinks t)) + +(use-package vc-git + :commands vc-git-grep) + +(use-package smerge-mode + :defer t + :config + (setq smerge-diff-switches '("-d" "-b" "-u"))) + +(use-package git-annex + :defer t + :after dired + :config + (setq git-annex-commit nil)) + +(use-package magit + :load-path "~/src/emacs/magit/lisp/" + :defer t + :chords ("jg" . magit-status) + :init + (load "magit-autoloads.el") + (bind-keys :map km/git-map + ("d" . magit-dispatch-popup) + ("l" . magit-log-buffer-file) + ("s" . magit-stage-file)) + (define-prefix-command 'km/magit-map) + (define-prefix-command 'km/magit-wip-map) + (define-key km/git-map "w" 'km/magit-wip-map) + :config + (setq magit-revert-buffers 'silent + magit-revert-buffers-only-for-tracked-files nil + magit-push-always-verify nil + magit-delete-by-moving-to-trash nil + magit-diff-auto-show-delay 0.1 + magit-revision-show-gravatars nil + magit-log-section-arguments nil + magit-log-show-margin nil) + (setq magit-uniquify-buffer-names nil + magit-buffer-name-format "*%M%v: %t*") + (setq magit-no-confirm '(stage-all-changes unstage-all-changes reverse)) + + (setq magit-popup-show-help-echo nil + magit-popup-show-common-commands nil + magit-popup-use-prefix-argument 'default) + (setq magit-branch-arguments + (delete "--track" magit-branch-arguments)) + (setq magit-patch-popup + (plist-put magit-patch-popup :use-prefix 'popup)) + + (remove-hook 'magit-refs-sections-hook #'magit-insert-tags) + + (add-hook 'magit-post-display-buffer-hook + (lambda () + (when (eq major-mode 'magit-status-mode) + (delete-other-windows)))) + + (define-key ctl-x-4-map "g" #'magit-find-file-other-window) + (define-key km/file-map "g" #'magit-find-file) + + (bind-keys :map magit-mode-map + ("o" . magit-push-popup) + ;; Remove `magit-add-change-log-entry-other-window', + ;; which overrides my binding for + ;; `km/zsh-ansi-term-other-window'. + ("P" . magit-submodule-popup) + ("C-x 4 a" . nil)) + + (define-key magit-file-section-map (kbd "C-j") + #'magit-diff-visit-file-worktree) + (define-key magit-hunk-section-map (kbd "C-j") + #'magit-diff-visit-file-worktree) + + (define-key magit-process-mode-map (kbd "C-c C-k") #'magit-process-kill) + + (define-key magit-mode-map "." 'km/magit-map) + (bind-keys :map km/magit-map + ("l" . magit-toggle-buffer-lock)) + + (bind-keys :map km/magit-wip-map + ("a" . magit-wip-after-apply-mode) + ("b" . magit-wip-before-change-mode) + ("c" . magit-wip-commit) + ("f" . magit-wip-commit-buffer-file) + ("l" . magit-wip-log-current) + ("o" . magit-wip-log) + ("s" . magit-wip-after-save-mode) + ("S" . magit-wip-after-save-local-mode)) + + (define-key magit-popup-mode-map (kbd "SPC <t>") + #'magit-invoke-popup-switch) + (define-key magit-popup-mode-map (kbd "SPC SPC <t>") + #'magit-invoke-popup-option) + + (magit-define-popup-action 'magit-diff-popup + ?e "Edit options" #'magit-diff-refresh-popup) + + (magit-change-popup-key 'magit-stash-popup :action + ?Z ?s) + + (magit-define-popup-switch 'magit-log-popup + ?p "First parent" "--first-parent") + (magit-define-popup-switch 'magit-log-popup + ?n "No merges" "--no-merges") + (magit-define-popup-switch 'magit-log-popup + ?t "Date order" "--date-order") + + (magit-define-popup-action 'magit-log-popup + ?e "Edit options" 'magit-log-refresh-popup) + (magit-define-popup-action 'magit-log-popup + ?w "Log current WIP" 'magit-wip-log-current) + (magit-define-popup-action 'magit-log-popup + ?W "Log other WIP" 'magit-wip-log) + + (magit-change-popup-key 'magit-branch-popup :action + ?c ?o) + (magit-change-popup-key 'magit-branch-popup :action + ?n ?C) + (magit-change-popup-key 'magit-branch-popup :action + ?m ?R) + (magit-change-popup-key 'magit-branch-popup :action + ?s ?v) + + (defadvice magit-merge-editmsg (around km/magit-merge-editmsg-no-ff activate) + "Set '--no-ff' flag when running `magit-merge-editmsg'." + (let ((args '("--no-ff"))) + ad-do-it))) + +(use-package km-magit + :defer t + :after magit + :init + (bind-keys :map km/git-map + ("." . km/magit-show-commit-at-point) + ("c" . km/magit-copy-commit-summary) + ("e" . km/magit-commit-extend-with-file) + ("f" . km/magit-reset-file) + ("i" . km/magit-insert-staged-file) + ("n" . km/magit-shorten-hash-at-point) + ("p" . km/magit-pin-file) + ("r" . km/magit-find-recently-changed-file) + ("u" . km/magit-auto-commit) + ("v" . km/magit-revfile-reset)) + :config + (bind-keys :map magit-mode-map + ("Q" . km/magit-mode-bury-all-windows) + ("C-w" . km/magit-copy-as-kill)) + + (define-key magit-file-section-map (kbd "C-o") + #'km/magit-diff-visit-file-other-window) + (define-key magit-hunk-section-map (kbd "C-o") + #'km/magit-diff-visit-file-other-window) + + (define-key magit-log-select-mode-map "." + #'km/magit-log-select-guess-fixup-commit) + + (define-key magit-refs-mode-map (kbd "C-c C-t") #'km/magit-refs-toggle-tags) + + (define-key magit-file-section-map [remap magit-visit-thing] + #'km/magit-diff-visit-file) + (define-key magit-hunk-section-map [remap magit-visit-thing] + #'km/magit-diff-visit-file) + + (define-key magit-refs-mode-map (kbd "C-c C-f") + #'km/magit-refs-filter-recent) + + (bind-keys :map km/magit-map + ("c" . km/magit-find-commit-file) + ("g" . km/git-map) + ("f" . km/magit-flip-revs)) + + (define-key km/magit-wip-map "w" #'km/magit-commit-wip-with-file) + + (magit-define-popup-action 'magit-commit-popup + ?u "Auto commit" #'km/magit-auto-commit) + + (magit-define-popup-action 'magit-push-popup + ?a "Push all" #'km/magit-push-all) + (magit-define-popup-action 'magit-push-popup + ?h "Push HEAD" #'km/magit-push-head) + + (magit-define-popup-action 'magit-merge-popup + ?u "Merge upstream" #'km/magit-ff-merge-upstream) + + (magit-define-popup-action 'magit-branch-popup + ?c "Create & checkout from current" + #'km/magit-branch-and-checkout-from-current) + + (magit-define-popup-action 'magit-branch-popup + ?K "Delete previous branch" #'km/magit-delete-previous-branch) + (magit-define-popup-action 'magit-branch-popup + ?m "Checkout master" #'km/magit-checkout-master) + (magit-define-popup-action 'magit-branch-popup + ?n "Checkout recent ref" #'km/magit-checkout-recent-ref) + (magit-define-popup-action 'magit-branch-popup + ?N "Track recent ref" #'km/magit-checkout-track-recent-ref) + (magit-define-popup-action 'magit-branch-popup + ?l "Checkout previous" #'km/magit-checkout-previous-branch) + (magit-define-popup-action 'magit-branch-popup + ?r "Rename branch" #'km/magit-branch-rename) + (magit-define-popup-action 'magit-branch-popup + ?s "Backup current branch" #'km/magit-backup-branch) + (magit-define-popup-action 'magit-branch-popup + ?t "Local tracking" #'km/magit-checkout-local-tracking)) + +(use-package magit-annex + :load-path "~/src/emacs/magit-annex/" + :defer t + :init (require 'magit-annex-autoloads) + :config + (setq magit-annex-unused-open-function #'org-open-file) + (setq magit-annex-all-action-arguments + (delete "--auto" magit-annex-all-action-arguments))) + +(use-package git-commit + :load-path "~/src/emacs/magit/lisp/" + :defer t + :config + (setq git-commit-finish-query-functions nil) + + (add-hook 'git-commit-setup-hook + (lambda () + (add-hook 'with-editor-pre-finish-hook + #'git-commit-save-message nil t))) + (add-hook 'git-commit-setup-hook #'git-commit-turn-on-flyspell)) + +(use-package orgit + :load-path "~/src/emacs/orgit/" + :defer t + :init (require 'orgit-autoloads)) + + +;;; Command interfaces + +(use-package setkey + :bind ("C-c v" . setkey-call)) + +(use-package god-mode + :bind (("C-c d" . god-local-mode) + ("C-x C-1" . delete-other-windows) + ("C-x C-2" . split-window-below) + ("C-x C-3" . split-window-right) + ("C-x C-0" . delete-window)) + :config + (add-hook 'view-mode-hook + (lambda () + (if view-mode (god-local-mode-pause) (god-local-mode-resume)))) + (add-hook 'org-capture-mode-hook + (lambda () (god-local-mode -1))) + + (add-hook 'god-mode-enabled-hook + (lambda () + (when view-mode + (view-mode -1)) + (when (derived-mode-p 'emacs-lisp-mode) + (lispy-mode -1)))) + (add-hook 'god-mode-disabled-hook + (lambda () + (when (derived-mode-p 'emacs-lisp-mode) + (lispy-mode 1)))) + (bind-keys :map god-local-mode-map + ("." . repeat) + ("i" . god-local-mode))) + +(use-package km-god + :defer t + :after god-mode + :config + (add-to-list 'god-exempt-predicates #'km/god-gnus-p) + (add-hook 'god-mode-enabled-hook #'km/god-update-cursor) + (add-hook 'god-mode-disabled-hook #'km/god-update-cursor)) + +(use-package km-hydra + :bind (("C-c n" . km/hydra-outline-mode) + ("C-c w" . hydra-window-map/body)) + :commands (hydra-file-search-map/body + hydra-kmacro/body + hydra-multiple-cursors/body + hydra-org-link-edit/body + hydra-smerge/body) + :init + (bind-keys :map km/editing-map + ("k" . hydra-kmacro/body) + ("o" . hydra-multiple-cursors/body)) + (define-key km/git-map "m" #'hydra-smerge/body) + (define-key km/file-map "s" #'hydra-file-search-map/body) + (after 'org + (define-key km/org-prefix-map "." #'hydra-org-link-edit/body))) + + +;;; Helm + +(use-package helm + :defer t + :config + (setq helm-move-to-line-cycle-in-source t)) + +(use-package helm-config + :defer t + :config + (global-set-key (kbd "C-x c") nil) + (customize-set-value 'helm-command-prefix-key "C-c h")) + +(use-package helm-buffers + :defer t + :chords ("jt" . helm-mini)) + +(use-package helm-files + :defer t + :chords ("jc" . helm-find-files) + :config + (setq helm-ff-newfile-prompt-p nil + helm-ff-file-name-history-use-recentf t + helm-ff-skip-boring-files t)) + +(use-package km-helm + :defer t + :after helm + :init + (after 'helm-files + (bind-keys :map helm-find-files-map + ("C-c x" . km/helm-ff-org-open-file) + ("C-c C-o" . km/helm-display-file))) + (after 'helm-locate + (bind-keys :map helm-generic-files-map + ("C-c x" . km/helm-ff-org-open-file) + ("C-c C-o" . km/helm-display-file))) + (after 'helm-buffers + (define-key helm-buffer-map (kbd "C-c C-o") #'km/helm-display-buffer))) + +(use-package helm-mode + :diminish helm-mode + :after helm + :config + (helm-mode 1)) + +(use-package helm-command + :defer t + :chords ("kx" . helm-M-x)) + +(use-package helm-swoop + :defer t + :init (define-key search-map "k" #'helm-swoop)) + +(use-package helm-apropos + :bind ("C-h a" . helm-apropos)) + +(use-package helm-imenu + :bind ("C-c l" . helm-imenu)) + +(use-package helm-man + :defer t + :init (define-key km/external-map "m" #'helm-man-woman)) + + +;;; Expansion + +(use-package abbrev + :commands abbrev-mode + :diminish (abbrev-mode . "Ab") + :init + (add-hook 'text-mode-hook #'abbrev-mode) + (add-hook 'prog-mode-hook #'abbrev-mode) + :config + (define-abbrev-table 'typo-abbrev-table nil) + (abbrev-table-put global-abbrev-table :parents + (cons typo-abbrev-table + (abbrev-table-get global-abbrev-table :parents)))) + +(use-package km-abbrev + :defer t + :init + (after 'abbrev + (bind-keys :map abbrev-map + ("c" . km/abbrev-add-case-global) + ("iu" . km/abbrev-inverse-add-uppercase-global)))) + +(use-package hippie-exp + :bind ("M-/" . hippie-expand) + :config + (setq hippie-expand-try-functions-list '(try-complete-file-name-partially + try-complete-file-name + try-expand-all-abbrevs + try-expand-dabbrev + try-expand-dabbrev-all-buffers + try-expand-dabbrev-from-kill + try-complete-lisp-symbol-partially + try-complete-lisp-symbol))) + +(use-package yasnippet + :diminish yas-minor-mode + :commands km/yas-dummy + :init + (global-set-key (kbd "C-c i") #'km/yas-dummy) + :config + (defun km/yas-dummy () + (interactive)) + (global-set-key (kbd "C-c i") nil) + (setq yas-fallback-behavior nil) + + (defun km/yas-with-comment (str) + (concat comment-start + (unless (s-ends-with? " " comment-start) " ") + str comment-end)) + + (defvar km/personal-snippets + (file-name-as-directory (expand-file-name "psnippets" + user-emacs-directory))) + (when (file-exists-p km/personal-snippets) + (add-to-list 'yas-snippet-dirs km/personal-snippets)) + + (bind-keys :map yas-minor-mode-map + ("C-c i" . yas-expand) + ;; Remove commands with 'C-c &' prefix, which conflicts + ;; with `org-mark-ring-goto' binding' + ("C-c &" . nil) + ("<tab>" . nil) + ("TAB" . nil)) + (yas-global-mode)) + + +;;; Dired + +(use-package dired + :defer t + :init + (define-prefix-command 'km/dired-prefix-map) + :config + (require 'dired-x) + ;; .git is present as part of `dired-omit-extensions', but this + ;; seems to only be taken into account if a non-exension part + ;; exists. + (setq dired-omit-files + (concat dired-omit-files + "\\|^\\.git$\\|^\\.gitignore$" + "\\|^__pycache__$\\|^\\.snakemake$")) + + (setq dired-omit-extensions + (append dired-omit-extensions + (list ".aux" ".fdb_latexmk" ".fls" + ".log" ".nav" ".out" ".snm"))) + + (setq-default dired-omit-mode t) + + (setq dired-dwim-target t + dired-listing-switches "-alht") + + (setq dired-guess-shell-alist-user '(("\\.pdf\\'" "zathura"))) + + (setq dired-recursive-copies t + dired-recursive-deletes t) + + (put 'dired-find-alternate-file 'disabled nil) + + (add-hook 'dired-mode-hook #'dired-hide-details-mode) + + (define-key dired-mode-map "c" #'dired-do-copy) + + (define-key dired-mode-map (kbd "C-c m") 'km/dired-prefix-map)) + +(use-package km-dired + :bind ("C-x C-d" . km/dired-switch-to-buffer) + :init + (define-prefix-command 'km/dired-copy-filename-map) + (after 'projectile + (define-key km/dired-copy-filename-map "p" + #'km/dired-copy-project-filename-as-kill)) + (define-key km/dired-copy-filename-map "o" + #'km/dired-copy-relative-filename-as-kill) + (define-key km/dired-copy-filename-map "w" + #'dired-copy-filename-as-kill) + + (after 'dired + ;; This overrides the default binding for `dired-copy-filename-as-kill'. + (define-key dired-mode-map "w" #'km/dired-copy-filename-map) + (bind-keys :map dired-mode-map + ("w" . km/dired-copy-filename-map) + ("C" . km/dired-copy-and-edit) + ("V" . km/dired-view-file-other-window))) + + (define-key ctl-x-4-map "D" #'km/dired-switch-to-buffer-other-window) + + (after 'org + ;; This overrides `dired-find-file', which is also bound to "f". + (define-key dired-mode-map "e" #'km/org-open-dired-marked-files))) + +(use-package dired-narrow + :defer t + :init + (after 'dired + (define-prefix-command 'km/dired-narrow-prefix-map) + (bind-keys :map km/dired-narrow-prefix-map + ("f" . dired-narrow-fuzzy) + ("n" . dired-narrow) + ("r" . dired-narrow-regexp)) + (define-key km/dired-prefix-map "n" 'km/dired-narrow-prefix-map) + (define-key dired-mode-map "/" #'dired-narrow))) + +(use-package dired-subtree + :defer t + :init + (after 'dired + (define-prefix-command 'km/dired-subtree-prefix-map) + (bind-keys :map km/dired-subtree-prefix-map + ("@" . dired-subtree-mark-subtree) + ("." . dired-subtree-unmark-subtree) + ("<" . dired-subtree-beginning) + (">" . dired-subtree-end) + ("g" . dired-subtree-revert) + ("d" . dired-subtree-down) + ("i" . dired-subtree-insert) + ("n" . dired-subtree-next-sibling) + ("p" . dired-subtree-previous-sibling) + ("r" . dired-subtree-remove) + ("s" . dired-subtree-narrow) + ("u" . dired-subtree-up)) + (define-key km/dired-prefix-map "s" 'km/dired-subtree-prefix-map))) + + +;;; Compilation and shells + +(setq shell-file-name "/bin/bash") +(setq shell-command-switch "-c") + +(bind-keys :map km/external-map + ("r" . shell-command-on-region) + ("s" . shell-command) + ("S" . shell)) + +(use-package grep + :defer t + :config + (defun km/grep-hide-header () + (narrow-to-region + (save-excursion (goto-char (point-min)) + (line-beginning-position 5)) + (point-max))) + + (add-hook 'grep-setup-hook #'km/grep-hide-header) + (add-hook 'grep-mode-hook #'toggle-truncate-lines)) + +(use-package compile + :defer t + :init + (bind-keys :map km/compile-map + ("c" . compile) + ("g" . recompile)) + :config + (defadvice compile (around prevent-duplicate-compilation-windows activate) + "Pop to compilation buffer only if it isn't visible. +This is useful for using multiple frames (e.g., with a two +monitor setup)." + (if (get-buffer-window (km/compilation-name-by-directory) + 'visible) + (save-window-excursion ad-do-it) + ad-do-it)) + + (defadvice recompile (around prevent-window-on-compilation activate) + "Prevent recompiling from spawning new windows." + (save-window-excursion ad-do-it))) + +(use-package km-compile + :after compile + :chords ("hv" . km/compilation-recompile) + :init + (bind-keys :map km/compile-map + ("h" . km/compile-in-home-dir) + ("o" . km/compilation-display-buffer)) + :config + (setq compilation-buffer-name-function #'km/compilation-name-by-directory)) + +(use-package km-shell + :chords ("kz" . km/zsh-toggle-ansi-term-home) + :init + (define-key ctl-x-4-map "a" #'km/zsh-ansi-term-other-window) + (bind-keys :map km/external-map + ("a" . km/zsh-ansi-term) + ("t" . km/open-external-terminal))) + + +;;; Other external programs + +(use-package browse-url + :defer t + :init + (define-key km/external-map "b" #'browse-url) + :config + (setq browse-url-browser-function 'browse-url-generic + browse-url-generic-program "firefox")) + +(use-package webjump + :defer t + :config + (setq webjump-sites + '(("Arch User Repository" . + [simple-query "https://aur.archlinux.org" + "https://aur.archlinux.org/packages/?K=" ""]) + ("DuckDuckGo" . + [simple-query "https://duckduckgo.com" + "https://duckduckgo.com/?q=" ""]) + ("Emacs Wiki" . + [simple-query "www.emacswiki.org" + "www.emacswiki.org/cgi-bin/wiki/" ""]) + ("GitHub" . "https://github.com") + ("GitHub search" . + [simple-query "https://github.com" + "https://github.com/search?q=" ""]) + ("Google" . + [simple-query "www.google.com" + "www.google.com/search?q=" ""]) + ("Google Scholar" . + [simple-query "http://scholar.google.com" + "http://scholar.google.com/scholar?&q=" ""]) + ("Wikipedia" . + [simple-query "wikipedia.org" + "wikipedia.org/wiki/" ""])))) + +(use-package km-webjump + :after webjump + :defer t + :init + (define-key km/external-map "j" #'km/webjump)) + +(use-package select + :defer t + :config + (setq x-select-enable-clipboard t + x-select-enable-primary t)) + +(use-package man + :defer t + :config + (setq Man-notify-method 'aggressive)) + +(use-package mailcap + :config + (mailcap-parse-mailcaps) + (pcase-dolist (`(_ . ,info) + (cdr (assoc-string "application" mailcap-mime-data))) + ;; Instead of deleting doc-view-mode entry, just make its test + ;; always fail. + (when (eq (cdr (assq 'viewer info)) 'doc-view-mode) + (setf (cdr (assq 'test info)) (lambda (&rest _) nil))))) + +(use-package diff + :defer t + :config + (setq diff-command "/bin/diff" + diff-switches "-u")) + +(use-package ediff + :defer t + :init + (define-key km/external-map "e" #'ediff) + :config + (setq ediff-window-setup-function #'ediff-setup-windows-plain)) + +(use-package km-diff + :defer t + :init + (bind-keys :map km/external-map + ("o" . km/ediff-with-other-window) + ("d" . km/diff)) + :config + (after 'diff-mode-map + (define-key diff-mode-map (kbd "C-c C-g") #'km/revert-buffer-and-view))) + + +;;; Text modes + +(add-hook 'text-mode-hook #'turn-on-auto-fill) + +(use-package footnote + :defer t + :config + (setq footnote-section-tag "")) + +(use-package ispell + :defer t + :init + (define-key km/external-map "i" #'ispell-buffer) + (define-key km/editing-map "w" #'ispell-word) + :config + (setq ispell-program-name "aspell")) + +(use-package flyspell + :defer t + :diminish (flyspell-mode . "Fy") + :config + (setq flyspell-auto-correct-binding (kbd "C-c e ;")) + (define-key flyspell-mode-map (kbd "C-.") nil)) + +(use-package tex-site + :mode ("\\.[tT]e[xX]\\'" . TeX-latex-mode) + :config + (setq font-latex-fontify-sectioning 'color) + (setq TeX-electric-math '("$" . "$")) + + (after 'latex + (put 'LaTeX-narrow-to-environment 'disabled nil) + (add-hook 'LaTeX-mode-hook #'turn-on-reftex) + (add-hook 'LaTeX-mode-hook #'flyspell-mode))) + +(use-package km-tex + :defer t + :after latex + :config + (add-hook 'LaTeX-mode-hook + (lambda () + (setq imenu-create-index-function + #'km/latex-imenu-create-index-function)))) + +(use-package reftex + :diminish (reftex-mode . "Rf") + :defer t + :config + (setq reftex-default-bibliography '("refs.bib"))) + +(use-package bibtex + :defer t + :config + ;; Make cite key have form <last author last name><year><first word>. + (setq bibtex-autokey-titlewords 1 + bibtex-autokey-titleword-ignore '("A" "An" "On" "The" "[0-9].*") + bibtex-autokey-titleword-length nil + bibtex-autokey-titlewords-stretch 0 + bibtex-autokey-year-length 4 + bibtex-autokey-year-title-separator "") + (setq bibtex-align-at-equal-sign t) ; Used by `bibtex-fill-entry'. + (setq bibtex-entry-format + (append '(realign whitespace last-comma delimiters sort-fields) + bibtex-entry-format))) + +(use-package km-bib + :after bibtex + :config + (dolist (h '(km/bibtex-delete-article-fields + km/bibtex-downcase-author-and + km/bibtex-downcase-entry + km/bibtex-downcase-keys + km/bibtex-pages-use-double-hyphen + km/bibtex-use-title-case + km/bibtex-remove-doi-leader + km/bibtex-remove-entry-space + km/bibtex-set-coding-system + km/bibtex-single-space-author-list)) + (add-hook 'bibtex-clean-entry-hook h))) + + +;;; Language modes + +(add-to-list 'auto-mode-alist '("\\.zsh\\'" . shell-script-mode)) +(add-to-list 'auto-mode-alist '("\\.*rc\\'" . conf-unix-mode)) + +(add-hook 'after-save-hook + #'executable-make-buffer-file-executable-if-script-p) + +(global-set-key (kbd "C-c x") #'eval-expression) + +(use-package haskell-mode + :defer t + :config + (setq haskell-process-show-debug-tips nil) + (add-hook 'haskell-mode-hook #'turn-on-haskell-indentation) + (add-hook 'haskell-mode-hook #'interactive-haskell-mode) + (add-hook 'haskell-mode-hook #'turn-on-haskell-doc) + (bind-keys :map haskell-mode-map + ("C-x C-d" . nil) + ("C-c C-z" . haskell-interactive-switch) + ("C-c C-l" . haskell-process-load-file) + ("C-c C-b" . haskell-interactive-switch) + ("C-c C-t" . haskell-process-do-type) + ("C-c C-i" . haskell-process-do-info) + ("C-c M-." . nil) + ("C-c C-d" . nil))) + +(use-package elisp-mode + :defer t + :config + (defun km/elisp-outline-level () + (and (looking-at (concat "^" outline-regexp)) + (- (match-end 0) (match-beginning 0) 3))) + + (defun km/elisp-set-outline-vars () + (setq outline-regexp ";;;;* ") + (setq outline-level #'km/elisp-outline-level)) + + (add-hook 'emacs-lisp-mode-hook #'km/elisp-set-outline-vars)) + +(use-package find-function + :bind (("C-h ;" . find-function) + ("C-h 4 ;" . find-function-other-window))) + +(use-package paredit + :defer t + :diminish (paredit-mode . "Pe")) + +(use-package lispy + :defer t + :init + (add-hook 'emacs-lisp-mode-hook #'lispy-mode) + :config + (setq lispy-no-permanent-semantic t) + (add-hook 'lispy-mode-hook #'km/elisp-set-outline-vars) + ;; This is ugly, but I haven't found another way to stop + ;; `imenu-create-index-function' from being set to + ;; `semantic-create-imenu-index'. Trying to set it in + ;; `emacs-lisp-mode-hook' or `lispy-mode-hook' doesn't work. + (defalias 'semantic-create-imenu-index 'imenu-default-create-index-function)) + +(use-package python + :defer t + :init + (add-to-list 'interpreter-mode-alist '("python2" . python-mode)) + (add-to-list 'interpreter-mode-alist '("python3" . python-mode)) + (define-prefix-command 'km/python-prefix-map) + :config + (setq python-fill-docstring-style 'pep-257-nn + python-indent-guess-indent-offset nil) + (setq python-shell-interpreter "ipython" + python-shell-prompt-detect-enabled nil) + + (defun km/python-outline-level () + (and (looking-at (concat "^" outline-regexp)) + (- (match-end 0) (match-beginning 0) 3))) + + (defun km/python-set-local-vars () + (setq outline-regexp "####* ") + (setq outline-level #'km/python-outline-level) + ;; Stop semantic from taking over imenu. + (setq imenu-create-index-function #'python-imenu-create-index) + (set (make-local-variable 'compile-command) "py.test")) + (add-hook 'python-mode-hook #'km/python-set-local-vars) + + (bind-keys :map python-mode-map + ("C-c C-b" . python-shell-send-buffer) + ("C-c C-f" . python-shell-send-defun) + ("C-M-x" . python-eldoc-at-point))) + +(use-package pydoc + :load-path "~/src/emacs/pydoc/" + :defer t + :config + (setq pydoc-make-method-buttons nil) + ;; Don't shadow my `ace-link' binding. + (define-key pydoc-mode-map "o" #'ace-link-help)) + +(use-package km-python + :after python + :bind ("C-h y" . km/pydoc) + :init + (bind-keys :map km/python-prefix-map + ("c" . km/python-copy-last-shell-line-as-comment) + ("t" . km/find-python-test-file-other-window)) + :config + (bind-keys :map python-mode-map + ("C-c C-." . km/python-shell-send-buffer-up-to-line) + ("C-c C-c" . km/python-shell-send-function-or-paragraph-and-step) + ("C-c C-d" . km/python-shell-send-set-string) + ("C-c m" . km/python-prefix-map)) + + (add-hook 'python-mode-hook + (lambda () + (add-hook + 'post-self-insert-hook + #'km/python-indent-post-self-insert-function 'append 'local))) + + (add-hook 'pydoc-after-finish-hook #'km/pydoc-store-name) + (when (file-exists-p km/pydoc-names-file) + (km/pydoc-read-names-file km/pydoc-names-file))) + +(use-package snakemake-mode + :load-path "~/src/emacs/snakemake-mode/" + :defer t + :init + (require 'snakemake-mode-autoloads) + (autoload 'snakemake-compile-command "snakemake-mode") + (setq snakemake-compile-command-options '("-p")) + :config + (defun km/snakemake-set-local-vars () + (set (make-local-variable 'compile-command) + (snakemake-compile-command)) + (set (make-local-variable 'imenu-create-index-function) + #'snakemake-imenu-create-index)) + + ;; Although `compile-command' and `imenu-create-index-function' are + ;; set when snakemake-mode is derived from Python mode, I need to + ;; define them again here because I have a Python mode hook + ;; overrides the Python versions. + (add-hook 'snakemake-mode-hook #'km/snakemake-set-local-vars)) + +(use-package km-snakemake + :defer t + :init + (bind-keys :map km/compile-map + ("b" . km/snakemake-compile-project-rule) + ("p" . km/snakemake-compile-project-file)) + (after 'dired + (define-key dired-mode-map "b" #'km/snakemake-compile-project-file))) + +(use-package ess-site + :mode ("\\.[rR]\\'" . R-mode) + :config + (setq ess-smart-S-assign-key ";") + (ess-toggle-S-assign nil) + (ess-toggle-S-assign nil) + (setq ess-use-ido nil) + + (define-abbrev-table 'ess-mode-abbrev-table + '(("true" "TRUE") + ("false" "FALSE")) + :system t) + (dolist (hook '(ess-mode-hook inferior-ess-mode-hook)) + (add-hook hook (lambda () + (setq local-abbrev-table ess-mode-abbrev-table))) + (add-hook hook #'abbrev-mode))) + +(use-package km-ess + :defer t + :config + (bind-keys :map ess-mode-map + ("C-c C-." . km/ess-eval-buffer-up-to-line) + ("|" . km/ess-insert-dplyr-pipe)) + (after 'ess-inf + (define-key inferior-ess-mode-map "|" #'km/ess-insert-dplyr-pipe))) + + +;;; Mail + +(use-package notmuch + :defer t + :init (define-key km/mail-map "n" #'notmuch) + :config + (setq notmuch-fcc-dirs nil + notmuch-search-oldest-first nil) + (add-to-list 'notmuch-saved-searches + '(:name "today" :query "date:today.." :key ".")) + (define-prefix-command 'km/notmuch-show-prefix-map) + (define-key notmuch-show-mode-map (kbd "C-c m") 'km/notmuch-show-prefix-map) + + (define-key km/notmuch-show-prefix-map "i" + #'km/notmuch-show-copy-message-id-as-kill)) + +(use-package message + :defer t + :config + (setq message-send-mail-function 'message-send-mail-with-sendmail + message-sendmail-envelope-from 'header + message-kill-buffer-on-exit t) + (add-hook 'message-mode-hook #'flyspell-mode)) + +(use-package mml + :defer t + :diminish (mml-mode . "ML")) + +(use-package mm-decode + :defer t + :config + (setq mm-discouraged-alternatives '("text/html" "text/richtext"))) + +(use-package gnus + :defer t + :init + (bind-keys :map km/mail-map + ("g" . gnus) + ("p" . gnus-plugged) + ("u" . gnus-unplugged)) + :config + (setq gnus-home-directory "~/.gnus.d/" + gnus-directory gnus-home-directory + gnus-article-save-directory (expand-file-name "saved/" gnus-directory) + gnus-kill-files-directory (expand-file-name "scores/" gnus-directory)) + (setq gnus-startup-file (expand-file-name "newsrc" gnus-home-directory) + gnus-init-file (expand-file-name "gnus" gnus-home-directory) + gnus-save-newsrc-file nil + gnus-read-newsrc-file nil + gnus-inhibit-startup-message t) + (setq gnus-summary-line-format "%U%R %&user-date;%-20= %-15,15f %B %S \n") + (setq gnus-gcc-mark-as-read t + gnus-visible-headers '("^From" "^Subject" "^Date" "^To" "^Cc" "^User-Agent") + gnus-confirm-mail-reply-to-news t) + (setq gnus-agent-go-online t + gnus-agent-synchronize-flags t) + (setq gnus-inhibit-images t) + (setq gnus-interactive-exit nil) + + (setq gnus-topic-display-empty-topics nil + gnus-group-line-format "%M\%S\%p\%P\%5y:%B%(%G%)\n" + gnus-group-list-inactive-groups nil) + + (setq gnus-group-use-permanent-levels t) + + (setq gnus-auto-select-next 'quietly) + + (setq gnus-thread-hide-subtree t + gnus-thread-sort-functions '(gnus-thread-sort-by-most-recent-number)) + (define-key gnus-group-mode-map "e" #'gnus-group-select-group)) + +(use-package gnus-sum + :defer t + :init + (define-prefix-command 'km/gnus-summary-prefix-map) + :config + (setq gnus-sum-thread-tree-indent " " + gnus-sum-thread-tree-root "." + gnus-sum-thread-tree-false-root "o " + gnus-sum-thread-tree-single-indent "" + gnus-sum-thread-tree-leaf-with-other "+-> " + gnus-sum-thread-tree-vertical "| " + gnus-sum-thread-tree-single-leaf "`-> ") + (bind-keys :map gnus-summary-mode-map + ("e" . gnus-summary-scroll-up) + ("v" . org-capture) + (";" . gnus-summary-universal-argument)) + (define-key gnus-summary-mode-map (kbd "C-c m") + 'km/gnus-summary-prefix-map)) + +(use-package gnus-art + :defer t + :init + (define-prefix-command 'km/gnus-article-prefix-map) + :config + (define-key gnus-article-mode-map "v" #'org-capture) + (define-key gnus-article-mode-map (kbd "C-c m") + 'km/gnus-article-prefix-map)) + +(use-package shr + :defer t + :config + (bind-keys :map shr-map + ;; Allow `km/ace-link-widget' binding to work even when + ;; on shr widget. + ("o" . nil) + ("O" . shr-save-contents) + ("v" . nil))) + +(use-package sendmail + :defer t + :config + (setq sendmail-program "/usr/bin/msmtp")) + +(use-package km-mail + :defer t + :after gnus + :config + (add-hook 'message-send-hook #'km/message-confirm-sender) + (add-hook 'kill-emacs-hook #'km/gnus-grace-exit-before-kill-emacs) + + (setq gnus-group-sort-function '(gnus-group-sort-by-alphabet + km/gnus-group-sort-by-topic + gnus-group-sort-by-level)) -(require 'init-org) -(require 'init-helm) + (after 'gnus-sum + (bind-keys :map gnus-summary-mode-map + ("c" . km/gnus-summary-catchup) + ("l" . km/gnus-copy-message-link) + ("o" . km/ace-link-widget))) + (after 'gnus-art + (bind-keys :map gnus-article-mode-map + ("C-c l" . km/gnus-follow-last-message-link) + ("e" . km/shr-browse-url-and-goto-next) + ("o" . km/ace-link-widget))) -(require 'init-files) -(require 'init-buffers) -(require 'init-framewin) -(require 'init-ace) -(require 'init-view) + (bind-keys :map km/gnus-summary-prefix-map + ("p" . km/gnus-open-github-patch) + ("l" . km/gnus-copy-gmane-link-as-kill)) + (bind-keys :map km/gnus-article-prefix-map + ("p" . km/gnus-open-github-patch) + ("l" . km/gnus-copy-gmane-link-as-kill))) -(require 'init-editing) -(require 'init-outline) -(require 'init-god) + +;;; Miscellaneous configuration -(require 'init-elisp) -(require 'init-haskell) -(require 'init-python) -(require 'init-ess) +(setq echo-keystrokes 0.1 + use-dialog-box nil + visible-bell t + enable-recursive-minibuffers t) -(require 'init-tex) -(require 'init-bib) -(require 'init-bog) +(setq bookmark-save-flag nil) -(require 'init-dired) -(require 'init-git) -(require 'init-projectile) -(require 'init-snakemake) +;; This is intentionally not loaded. +(setq custom-file "~/.emacs.d/.custom.el") -(require 'init-external) +(setq default-input-method "TeX") -(require 'init-yas) +(defalias 'yes-or-no-p 'y-or-n-p) -(when (file-exists-p (expand-file-name "init-untracked.el" km/init-lisp-dir)) - (require 'init-untracked)) +(when (file-exists-p (expand-file-name "km-untracked.el" km/init-lisp-dir)) + (require 'km-untracked)) -(require 'init-mail) -(require 'init-server) +(use-package server + :config + (setq server-use-tcp t) + (unless (server-running-p) + (server-start)) + (let ((server (daemonp))) + (cond + ((string= server "default") + ;; Remove all mail map bindings except notmuch. + (global-set-key (kbd "C-x m") nil) + (global-set-key (kbd "C-x m n") #'notmuch) + (after 'km-python + (add-hook 'kill-emacs-hook #'km/pydoc-save-names-file)) + (setq save-abbrevs 'silently + bookmark-save-flag 1)) + ((string= server "mail") + (setq mode-line-misc-info + (cons (propertize " [Mail] " 'face 'font-lock-doc-face) + mode-line-misc-info)) + (key-chord-define-global "jg" 'km/mail-map) + (setq recentf-save-file "~/.emacs.d/cache/recentf-mail") + (setq save-abbrevs nil))))) ;;; init.el ends here diff --git a/lisp/init-diminish.el b/lisp/init-diminish.el deleted file mode 100644 index 48baf5a..0000000 --- a/lisp/init-diminish.el +++ /dev/null @@ -1,39 +0,0 @@ -;;; init-diminish.el --- Diminish mode configuration - -;; Copyright (C) 2012-2016 Kyle Meyer <kyle@kyleam.com> - -;; Author: Kyle Meyer <kyle@kyleam.com> -;; URL: https://github.com/kyleam/emacs.d - -;; 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 <http://www.gnu.org/licenses/>. - -;;; Code: - -(require 'diminish) - -(diminish 'abbrev-mode "Ab") -(after 'helm-mode (diminish 'helm-mode)) -(after 'flyspell (diminish 'flyspell-mode "Fy")) -(after 'paredit (diminish 'paredit-mode " Pe")) -(after 'mml (diminish 'mml-mode "Ml")) -(after 'org (diminish 'orgstruct-mode "Os")) -(after 'org-table (diminish 'orgtbl-mode "Ot")) -(after 'projectile (diminish 'projectile-mode)) -(after 'reftex (diminish 'reftex-mode "Rf")) -(after 'view (diminish 'view-mode "Vw")) -(after 'whitespace (diminish 'global-whitespace-mode)) -(after 'yasnippet (diminish 'yas-minor-mode)) - -(provide 'init-diminish) -;;; init-diminish.el ends here diff --git a/lisp/init-elisp.el b/lisp/init-elisp.el deleted file mode 100644 index 987dab8..0000000 --- a/lisp/init-elisp.el +++ /dev/null @@ -1,46 +0,0 @@ -;;; init-elisp.el --- Elisp-related configuration - -;; Copyright (C) 2012-2016 Kyle Meyer <kyle@kyleam.com> - -;; Author: Kyle Meyer <kyle@kyleam.com> -;; URL: https://github.com/kyleam/emacs.d - -;; 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 <http://www.gnu.org/licenses/>. - -;;; Code: - -(setq lispy-no-permanent-semantic t) - -(add-hook 'emacs-lisp-mode-hook 'lispy-mode) -(add-hook 'emacs-lisp-mode-hook 'km/elisp-set-outline-vars) -;; This likely breaks lispy's outline functions, but I don't use them. -(add-hook 'lispy-mode-hook 'km/elisp-set-outline-vars) - -(after 'lispy - ;; This is ugly, but I haven't found another way to stop - ;; `imenu-create-index-function' from being set to - ;; `semantic-create-imenu-index'. Trying to set it in - ;; `emacs-lisp-mode-hook' or `lispy-mode-hook' doesn't work. - (defalias 'semantic-create-imenu-index 'imenu-default-create-index-function)) - -(defun km/elisp-outline-level () - (and (looking-at (concat "^" outline-regexp)) - (- (match-end 0) (match-beginning 0) 3))) - -(defun km/elisp-set-outline-vars () - (setq outline-regexp ";;;;* ") - (setq outline-level 'km/elisp-outline-level)) - -(provide 'init-elisp) -;;; init-elisp.el ends here diff --git a/lisp/init-external.el b/lisp/init-external.el deleted file mode 100644 index 2d1f11c..0000000 --- a/lisp/init-external.el +++ /dev/null @@ -1,350 +0,0 @@ -;;; init-external.el --- Configuration for shells and external programs - -;; Copyright (C) 2012-2016 Kyle Meyer <kyle@kyleam.com> - -;; Author: Kyle Meyer <kyle@kyleam.com> -;; URL: https://github.com/kyleam/emacs.d - -;; 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 <http://www.gnu.org/licenses/>. - -;;; Code: - -(setq x-select-enable-clipboard t ; Share clipboard with system. - x-select-enable-primary t) - -(setq browse-url-browser-function 'browse-url-generic - browse-url-generic-program "firefox") - -(setq ispell-program-name "aspell") - -(setq Man-notify-method 'aggressive) - -(define-prefix-command 'km/external-map) -(global-set-key (kbd "C-c z") 'km/external-map) - -(define-key km/external-map "b" 'browse-url) -(define-key km/external-map "m" 'helm-man-woman) -(define-key km/external-map "i" 'ispell-buffer) - - -;;; Shells - -(setq shell-file-name "/bin/bash") -(setq shell-command-switch "-c") - -(defvar km/terminal "urxvt") - -(defun km/open-external-terminal () - (interactive) - (start-process "ext-term" nil km/terminal)) -(define-key km/external-map "t" 'km/open-external-terminal) - -(defun km/zsh-ansi-term (&optional directory name) - "Open an ansi-term buffer running ZSH in DIRECTORY. - -If a terminal for DIRECTORY already exists, switch to that -buffer. If the current buffer is a terminal for DIRECTORY, -create an additional terminal. - -By default, DIRECTORY is `default-directory'. - -With a numeric prefix argument 0, prompt the user with existing -ZSH terminal directories. - -With a C-u prefix argument, set DIRECTORY to the user home -directory. - -With any other non-nil value, prompt for a directory. - -If NAME is non-nil, use *NAME* for the buffer name instead of -*zsh: DIRECTORY*. If that buffer already exists, it will be -grabbed regardless of whether its default-directory matches -DIRECTORY." - (interactive (km/zsh-ansi-term--args)) - (let* ((dir (abbreviate-file-name directory)) - (name (or name (concat "zsh: " dir))) - (full-name (concat "*" name "*")) - (default-directory dir)) - (pop-to-buffer-same-window - (cond - ((and (not (string= (km/zsh-ansi-term-directory) dir)) - (get-buffer full-name))) - (t - (cl-letf (((symbol-function 'switch-to-buffer) - (lambda (b &rest _) (get-buffer b)))) - (ansi-term "zsh" name))))) - (comint-goto-process-mark))) - -(defun km/zsh-toggle-ansi-term-home (&optional other-window) - (interactive "P") - (if (string= "*zsh*" (buffer-name)) - (bury-buffer) - (let ((display-buffer-overriding-action - (and other-window '(nil (inhibit-same-window . t))))) - (km/zsh-ansi-term "~/" "zsh")))) - -(defun km/zsh-ansi-term-other-window (&optional directory) - (interactive (km/zsh-ansi-term--args)) - (let ((display-buffer-overriding-action - '(nil (inhibit-same-window . t)))) - (km/zsh-ansi-term directory))) - -(defun km/zsh-ansi-term--args () - (list (cond - ((not current-prefix-arg) - default-directory) - ((= (prefix-numeric-value current-prefix-arg) 4) - "~/") - ((= (prefix-numeric-value current-prefix-arg) 0) - (let ((dirs (km/zsh-ansi-term-current-directories))) - (cl-case (length dirs) - (0 (user-error "No ZSH buffers found")) - (1 (car dirs)) - (t (completing-read "Directory: " dirs - nil nil nil nil (car dirs)))))) - (t - (read-directory-name "Directory: "))))) - -(defun km/zsh-ansi-term-directory (&optional buffer) - "Return directory name for ZSH terminal in BUFFER. -BUFFER defaults to current buffer." - (with-current-buffer (or buffer (current-buffer)) - (let ((bname (buffer-name))) - (and (derived-mode-p 'term-mode) - (string-match "^\\*zsh: \\(.*\\)\\*\\(<[0-9]+>\\)*$" - bname) - (match-string 1 bname))))) - -(defun km/zsh-ansi-term-current-directories () - (-distinct (-keep #'km/zsh-ansi-term-directory (buffer-list)))) - -(define-key km/external-map "a" 'km/zsh-ansi-term) -(define-key km/external-map "r" 'shell-command-on-region) -(define-key km/external-map "s" 'shell-command) -(define-key km/external-map "S" 'shell) - -(key-chord-define-global "kz" 'km/zsh-toggle-ansi-term-home) - -;; This overrides binding for `add-change-log-entry-other-window'. -(define-key ctl-x-4-map "a" 'km/zsh-ansi-term-other-window) - - -;;; Compilation - -(defvar km/compilation-buffer-name-prefix "compilation: ") - -(defun km/compilation-name-by-directory (&optional mode) - (let ((name (if (and mode (not (equal mode "compilation"))) - (downcase mode) - (concat km/compilation-buffer-name-prefix - (abbreviate-file-name default-directory))))) - (concat "*" name "*"))) - -(setq compilation-buffer-name-function 'km/compilation-name-by-directory) - -(defun km/compilation-buffer-p (buffer) - (with-current-buffer buffer - (and (derived-mode-p 'compilation-mode) - (string-prefix-p (concat "*" km/compilation-buffer-name-prefix) - (buffer-name))))) - -(defadvice compile (around prevent-duplicate-compilation-windows activate) - "Pop to compilation buffer only if it isn't visible. -This is useful for using multiple frames (e.g., with a two -monitor setup)." - (if (get-buffer-window (km/compilation-name-by-directory) - 'visible) - (save-window-excursion ad-do-it) - ad-do-it)) - -(defun km/compile-in-home-dir () - (interactive) - (let ((default-directory "~/")) - (call-interactively #'compile))) - -(defadvice recompile (around prevent-window-on-compilation activate) - "Prevent recompiling from spawning new windows." - (save-window-excursion ad-do-it)) - -(defun km/compilation-recompile (&optional arg) - "Recompile buffer. -By default, use `compilation-last-buffer'. If ARG is 0, get -buffer with name given by `km/compilation-name-by-directory'. -Otherwise, if ARG is non-nil, prompt with buffers from -`km/compilation-buffer-list'." - (interactive (list (and current-prefix-arg - (prefix-numeric-value current-prefix-arg)))) - (with-current-buffer (km/compilation--get-buffer arg) - (if (derived-mode-p 'occur-mode) - (revert-buffer) - (recompile)))) - -(defun km/compilation-display-buffer (&optional arg) - "Display compilation buffer. -By default, use `compilation-last-buffer'. If ARG is 0, get -buffer with name given by `km/compilation-name-by-directory'. -Otherwise, if ARG is non-nil, prompt with buffers from -`km/compilation-buffer-list'." - (interactive (list (and current-prefix-arg - (prefix-numeric-value current-prefix-arg)))) - (display-buffer (km/compilation--get-buffer arg))) - -(defun km/compilation--get-buffer (&optional arg) - (cond - ((and (not arg) - (buffer-live-p compilation-last-buffer) - compilation-last-buffer)) - ((and (numberp arg) - (= arg 0)) - (get-buffer (km/compilation-name-by-directory))) - (t - (let ((cbufs (-map #'buffer-name (km/compilation-buffer-list))) - buf) - (cl-case (length cbufs) - (0 (user-error "No compilation buffers found")) - (1 (setq buf (car cbufs))) - (t (setq buf (completing-read "Compilation buffer: " cbufs - nil nil nil nil (car cbufs))))) - buf)))) - -(defun km/compilation-buffer-list () - (-filter #'km/compilation-buffer-p (buffer-list))) - -(define-prefix-command 'km/compile-map) -(global-set-key (kbd "C-c c") 'km/compile-map) - -(define-key km/compile-map "c" 'compile) -(define-key km/compile-map "g" 'recompile) -(define-key km/compile-map "h" 'km/compile-in-home-dir) -(define-key km/compile-map "o" 'km/compilation-display-buffer) - -(key-chord-define-global "hv" 'km/compilation-recompile) - - -;;; Diff - -(setq diff-command "/bin/diff" - diff-switches "-u") - -(setq ediff-window-setup-function 'ediff-setup-windows-plain) - -(defun km/diff () - "Run `diff' and then select buffer and turn on View mode." - (interactive) - (call-interactively #'diff) - (select-window (get-buffer-window "*Diff*")) - (view-mode 1)) - -(defun km/revert-buffer-and-view () - (interactive) - (revert-buffer) - (view-mode 1)) -(after 'diff - (define-key diff-mode-map (kbd "C-c C-g") 'km/revert-buffer-and-view)) - -(defun km/ediff-with-other-window () - "Run `ediff' on current window's file and other window's file." - (interactive) - (let ((windows (window-list))) - (unless (= (length windows) 2) - (user-error "Function restricted to two-window frames")) - (-if-let* ((file-a (buffer-file-name - (window-buffer (car windows)))) - (file-b (buffer-file-name - (window-buffer (cadr windows))))) - (ediff file-a file-b) - (user-error "At least one buffer is not visiting a file")))) - -(define-key km/external-map "d" 'km/diff) -(define-key km/external-map "e" 'ediff) -(define-key km/external-map "o" 'km/ediff-with-other-window) - - -;;; WebJump - -(setq webjump-sites - '(("Arch User Repository" . - [simple-query "https://aur.archlinux.org" - "https://aur.archlinux.org/packages/?K=" ""]) - ("DuckDuckGo" . - [simple-query "https://duckduckgo.com" - "https://duckduckgo.com/?q=" ""]) - ("Emacs Wiki" . - [simple-query "www.emacswiki.org" - "www.emacswiki.org/cgi-bin/wiki/" ""]) - ("GitHub" . "https://github.com") - ("GitHub search" . - [simple-query "https://github.com" - "https://github.com/search?q=" ""]) - ("Google" . - [simple-query "www.google.com" - "www.google.com/search?q=" ""]) - ("Google Scholar" . - [simple-query "http://scholar.google.com" - "http://scholar.google.com/scholar?&q=" ""]) - ("Wikipedia" . - [simple-query "wikipedia.org" - "wikipedia.org/wiki/" ""]))) - -(defun km/webjump-read-string (prompt) - "Like `webjump-read-string', but set default." - (let* ((default (if (use-region-p) - (buffer-substring-no-properties - (region-beginning) (region-end)) - (thing-at-point 'symbol))) - (prompt (if default - (format "%s (%s): " prompt default) - (concat prompt ": "))) - (input (read-string prompt nil nil default))) - (unless (webjump-null-or-blank-string-p input) - (substring-no-properties input)))) - -(defun km/webjump () - "Run`webjump' with symbol at point or region as default query. -This affects only sites in the `simple-query' format." - (interactive) - (cl-letf (((symbol-function 'webjump-read-string) #'km/webjump-read-string)) - (call-interactively #'webjump))) - -(define-key km/external-map "j" 'km/webjump) - - -;;; Other - -(defun km/columnify-file (delim) - "Separate current file on DELIM using column program. - -By default, DELIM is set to \",\". With a single prefix argument, -use whitespace as the delimiter. With two prefix arguments, -prompt for a delimiter. - -If a columnified buffer already exists, just switch to it." - (interactive (list (cond ((not current-prefix-arg) ",") - ((> (prefix-numeric-value current-prefix-arg) 4) - (read-string "Delimiter: ")) - (t nil)))) - (unless buffer-file-name - (user-error "Buffer not visiting a file")) - (let* ((output-buffer-name (concat "*cols: " (buffer-name) "*")) - (output-buffer (get-buffer output-buffer-name)) - (fname (file-relative-name buffer-file-name)) - (args (cons "--table" - (and delim (list "--separator" delim))))) - (unless output-buffer - (setq output-buffer (get-buffer-create output-buffer-name)) - (apply #'call-process "column" fname output-buffer nil args)) - (switch-to-buffer output-buffer))) - -(provide 'init-external) -;;; init-external.el ends here diff --git a/lisp/init-general.el b/lisp/init-general.el deleted file mode 100644 index b62016f..0000000 --- a/lisp/init-general.el +++ /dev/null @@ -1,110 +0,0 @@ -;;; init-general.el --- Things without a more specific home - -;; Copyright (C) 2012-2016 Kyle Meyer <kyle@kyleam.com> - -;; Author: Kyle Meyer <kyle@kyleam.com> -;; URL: https://github.com/kyleam/emacs.d - -;; 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 <http://www.gnu.org/licenses/>. - -;;; Code: - -(setq echo-keystrokes 0.1 - use-dialog-box nil - visible-bell t - enable-recursive-minibuffers t) - -(setq tramp-default-method "sshx") - -(setq-default indicate-empty-lines t - indent-tabs-mode nil) - -(setq set-mark-command-repeat-pop t) - -(setq recenter-positions '(top middle bottom)) - -;; This is intentionally not loaded. -(setq custom-file "~/.emacs.d/.custom.el") - -(setq bookmark-save-flag nil) - -(setq default-input-method "TeX") - -(defalias 'yes-or-no-p 'y-or-n-p) - -(put 'narrow-to-region 'disabled nil) -(put 'narrow-to-page 'disabled nil) -(put 'set-goal-column 'disabled nil) -(put 'downcase-region 'disabled nil) -(put 'upcase-region 'disabled nil) - -(add-hook 'after-save-hook - 'executable-make-buffer-file-executable-if-script-p) - -(add-hook 'text-mode-hook 'turn-on-auto-fill) - -(add-to-list 'auto-mode-alist '("\\.zsh\\'" . shell-script-mode)) -(add-to-list 'auto-mode-alist '("\\.*rc\\'" . conf-unix-mode)) - -(global-set-key (kbd "C-h ;") 'find-function) -(global-set-key (kbd "C-h 4 ;") 'find-function-other-window) - - -(global-set-key (kbd "C-c l") 'helm-imenu) - -;; Disable `suspend-frame' binding. -(global-set-key (kbd "C-x C-z") nil) - -;; Avoid shift key for `backward-paragraph' and `forward-paragraph'. -(global-set-key (kbd "M-}") nil) -(global-set-key (kbd "M-]") 'forward-paragraph) -(global-set-key (kbd "M-{") nil) -(global-set-key (kbd "M-[") 'backward-paragraph) - -(global-set-key (kbd "C-c x") 'eval-expression) - -(show-paren-mode) -(global-auto-revert-mode) -(key-chord-mode 1) - - -;;; Set key - -(defvar km/setkey-command nil) -(defvar km/setkey-last-call-time nil) -(defvar km/setkey-seconds-timeout 600) - -(defun km/setkey-call () - "Call `km/setkey-command'. -When `km/setkey-command' is nil or the time since the last call -has exceeded `km/setkey-seconds-timeout', read the command to -call." - (interactive) - (when (or (not km/setkey-command) - (> (- (float-time) km/setkey-last-call-time) - km/setkey-seconds-timeout)) - (setq km/setkey-command (read-command "Command: " km/setkey-command))) - (setq km/setkey-last-call-time (float-time)) - (call-interactively km/setkey-command)) - -(defun km/setkey-reset () - "Reset `km/setkey-call' command." - (interactive) - (setq km/setkey-command nil - km/setkey-last-call-time nil)) - -(global-set-key (kbd "C-c v") 'km/setkey-call) - -(provide 'init-general) -;;; init-general.el ends here diff --git a/lisp/init-god.el b/lisp/init-god.el deleted file mode 100644 index 306f476..0000000 --- a/lisp/init-god.el +++ /dev/null @@ -1,68 +0,0 @@ -;;; init-god.el --- God mode configuration - -;; Copyright (C) 2012-2016 Kyle Meyer <kyle@kyleam.com> - -;; Author: Kyle Meyer <kyle@kyleam.com> -;; URL: https://github.com/kyleam/emacs.d - -;; 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 <http://www.gnu.org/licenses/>. - -;;; Code: - -(require 'god-mode) - -(add-to-list 'god-exempt-predicates #'km/god-gnus-p) - -(add-hook 'view-mode-hook (lambda () - (if view-mode - (god-local-mode-pause) - (god-local-mode-resume)))) - -(add-hook 'org-capture-mode-hook (lambda () (god-local-mode -1))) - -(add-hook 'god-mode-enabled-hook (lambda () - (when view-mode - (view-mode -1)) - (when (derived-mode-p 'emacs-lisp-mode) - (lispy-mode -1)))) - -(add-hook 'god-mode-disabled-hook (lambda () - (when (derived-mode-p 'emacs-lisp-mode) - (lispy-mode 1)))) - -(add-hook 'god-mode-enabled-hook 'km/god-update-cursor) -(add-hook 'god-mode-disabled-hook 'km/god-update-cursor) - -(defun km/god-update-cursor () - (setq cursor-type (if god-local-mode 'bar 'box))) - -(defun km/god-gnus-p () - "Return non-nil if a Gnus-related mode is enabled." - (derived-mode-p 'gnus-group-mode - 'gnus-summary-mode - 'gnus-article-mode - 'message-mode)) - -(global-set-key (kbd "C-c d") 'god-local-mode) - -(define-key god-local-mode-map "." 'repeat) -(define-key god-local-mode-map "i" 'god-local-mode) - -(global-set-key (kbd "C-x C-1") 'delete-other-windows) -(global-set-key (kbd "C-x C-2") 'split-window-below) -(global-set-key (kbd "C-x C-3") 'split-window-right) -(global-set-key (kbd "C-x C-0") 'delete-window) - -(provide 'init-god) -;;; init-god.el ends here diff --git a/lisp/init-haskell.el b/lisp/init-haskell.el deleted file mode 100644 index f5a4064..0000000 --- a/lisp/init-haskell.el +++ /dev/null @@ -1,40 +0,0 @@ -;;; init-haskell.el --- Haskell configuration - -;; Copyright (C) 2012-2016 Kyle Meyer <kyle@kyleam.com> - -;; Author: Kyle Meyer <kyle@kyleam.com> -;; URL: https://github.com/kyleam/emacs.d - -;; 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 <http://www.gnu.org/licenses/>. - -;;; Code: - -(setq haskell-process-show-debug-tips nil) - -(add-hook 'haskell-mode-hook 'turn-on-haskell-indentation) -(add-hook 'haskell-mode-hook 'interactive-haskell-mode) -(add-hook 'haskell-mode-hook 'turn-on-haskell-doc) - -(after 'haskell-mode - (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)) - -(provide 'init-haskell) -;;; init-haskell.el ends here diff --git a/lisp/init-helm.el b/lisp/init-helm.el deleted file mode 100644 index cacdbb6..0000000 --- a/lisp/init-helm.el +++ /dev/null @@ -1,72 +0,0 @@ -;;; init-helm.el --- Helm configuration - -;; Copyright (C) 2012-2016 Kyle Meyer <kyle@kyleam.com> - -;; Author: Kyle Meyer <kyle@kyleam.com> -;; URL: https://github.com/kyleam/emacs.d - -;; 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 <http://www.gnu.org/licenses/>. - -;;; Code: - -(require 'helm) -(require 'helm-config) - -(setq helm-move-to-line-cycle-in-source t - helm-ff-newfile-prompt-p nil - helm-ff-file-name-history-use-recentf t - helm-ff-skip-boring-files t) - -(defun km/helm-display-buffer () - (interactive) - (with-helm-alive-p - (helm-quit-and-execute-action #'display-buffer))) - -(defun km/helm-display-file () - (interactive) - (with-helm-alive-p - (helm-quit-and-execute-action - (lambda (f) - (display-buffer (find-file-noselect f)))))) - -(defun km/helm-ff-org-open-file () - "Run `org-open-file' from `helm-source-find-files'." - (interactive) - (with-helm-alive-p - (helm-quit-and-execute-action #'org-open-file))) - -(global-set-key (kbd "C-c h") 'helm-command-prefix) -(global-set-key (kbd "C-x c") nil) - -(after 'helm-files - (define-key helm-find-files-map (kbd "C-c x") 'km/helm-ff-org-open-file) - (define-key helm-generic-files-map (kbd "C-c x") 'km/helm-ff-org-open-file) - ;; Overrides `helm-ff-run-switch-other-frame'. - (define-key helm-find-files-map (kbd "C-c C-o") 'km/helm-display-file) - (define-key helm-generic-files-map (kbd "C-c C-o") 'km/helm-display-file) - ;; Overrides `helm-buffer-switch-other-frame'. - (define-key helm-buffer-map (kbd "C-c C-o") 'km/helm-display-buffer)) - -(key-chord-define-global "jc" 'helm-find-files) -(key-chord-define-global "jt" 'helm-mini) -(key-chord-define-global "kx" 'helm-M-x) - -(define-key search-map "k" 'helm-swoop) - -(global-set-key (kbd "C-h a") 'helm-apropos) - -(helm-mode 1) - -(provide 'init-helm) -;;; init-helm.el ends here diff --git a/lisp/init-mail.el b/lisp/init-mail.el deleted file mode 100644 index c840eee..0000000 --- a/lisp/init-mail.el +++ /dev/null @@ -1,274 +0,0 @@ -;;; init-mail.el --- Mail configuration - -;; Copyright (C) 2012-2016 Kyle Meyer <kyle@kyleam.com> - -;; Author: Kyle Meyer <kyle@kyleam.com> -;; URL: https://github.com/kyleam/emacs.d - -;; 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 <http://www.gnu.org/licenses/>. - -;;; Code: - -(require 'gnus) -(require 'org-gnus) - -(setq gnus-home-directory "~/.gnus.d/" - gnus-directory gnus-home-directory - gnus-article-save-directory (expand-file-name "saved/" gnus-directory) - gnus-kill-files-directory (expand-file-name "scores/" gnus-directory)) - -(setq gnus-startup-file (expand-file-name "newsrc" gnus-home-directory) - gnus-init-file (expand-file-name "gnus" gnus-home-directory) - gnus-save-newsrc-file nil - gnus-read-newsrc-file nil - gnus-inhibit-startup-message t) - -(setq sendmail-program "/usr/bin/msmtp" - gnus-gcc-mark-as-read t - gnus-visible-headers '("^From" "^Subject" "^Date" "^To" "^Cc" "^User-Agent") - gnus-confirm-mail-reply-to-news t) - -(setq gnus-agent-go-online t - gnus-agent-synchronize-flags t) - -(setq mm-discouraged-alternatives '("text/html" "text/richtext")) -(setq gnus-inhibit-images t) - -(setq gnus-interactive-exit nil) - -(add-hook 'kill-emacs-hook 'gnus-grace-exit-before-kill-emacs) - -;; http://www.emacswiki.org/emacs/GnusSync -(defun gnus-grace-exit-before-kill-emacs () - (if (and (fboundp 'gnus-alive-p) - (gnus-alive-p)) - (let ((noninteractive t)) - (gnus-group-exit)))) - -(define-prefix-command 'km/mail-map) -(global-set-key (kbd "C-x m") 'km/mail-map) - -(define-key km/mail-map "g" 'gnus) -(define-key km/mail-map "p" 'gnus-plugged) -(define-key km/mail-map "u" 'gnus-unplugged) - - -;;; Gnus group buffer - -(setq gnus-topic-display-empty-topics nil - gnus-group-line-format "%M\%S\%p\%P\%5y:%B%(%G%)\n" - gnus-group-list-inactive-groups nil) - -(setq gnus-group-use-permanent-levels t) - -(setq gnus-group-sort-function '(gnus-group-sort-by-alphabet - km/gnus-group-sort-by-topic - gnus-group-sort-by-level)) - -(defun km/gnus-group-sort-by-topic (info1 info2) - "Sort alphabetically by group topic. -This allows groups to be ordered by topics even when topic mode -is off." - (require 'gnus-topic) - (string< (gnus-group-topic (gnus-info-group info1)) - (gnus-group-topic (gnus-info-group info2)))) - -(define-key gnus-group-mode-map "e" 'gnus-group-select-group) - - -;;; Gnus summary and article buffer - -(setq gnus-summary-line-format "%U%R %&user-date;%-20= %-15,15f %B %S \n" - gnus-sum-thread-tree-indent " " - gnus-sum-thread-tree-root "." - gnus-sum-thread-tree-false-root "o " - gnus-sum-thread-tree-single-indent "" - gnus-sum-thread-tree-leaf-with-other "+-> " - gnus-sum-thread-tree-vertical "| " - gnus-sum-thread-tree-single-leaf "`-> ") - -(setq gnus-auto-select-next 'quietly) - -(setq gnus-thread-hide-subtree t - gnus-thread-sort-functions '(gnus-thread-sort-by-most-recent-number)) - -(defun km/gnus-avy-goto-subword-and-select () - (interactive) - (let (avy-all-windows) - (call-interactively #'avy-goto-subword-1)) - (gnus-summary-scroll-up 0)) - -(defun km/gnus-summary-set-current-article () - (unless gnus-summary-buffer - (user-error "No summary buffer")) - (with-current-buffer gnus-summary-buffer - (save-window-excursion (gnus-summary-select-article)))) - -(defun km/gnus--last-message-link () - (with-current-buffer gnus-article-buffer - (save-excursion - (goto-char (point-max)) - (widget-forward -1) - (--when-let (or (get-text-property (point) 'gnus-string) - (get-text-property (point) 'shr-url)) - (kill-new it))))) - -(defun km/gnus--gmane-link (&optional perma) - (with-current-buffer gnus-original-article-buffer - (-when-let* ((blink (message-field-value "Archived-At")) - (link (or (and (string-match "\\`<\\(.*\\)>\\'" blink) - (match-string 1 blink)) - blink))) - (if perma - link - (replace-regexp-in-string "\\`http://permalink\.gmane\.org/" - "http://thread.gmane.org/" - link))))) - -(defun km/gnus-copy-gmane-link-as-kill (&optional perma) - (interactive "P") - (km/gnus-summary-set-current-article) - (with-current-buffer gnus-original-article-buffer - (--when-let (km/gnus--gmane-link perma) - (kill-new (message it))))) - -(defun km/gnus-copy-message-link (follow) - "Copy link for current message. -If it has an \"Archived-At\" header, use that. Otherwise, get -the link from the last widget in the buffer. With prefix -argument FOLLOW, follow link instead of copying it." - (interactive "P") - (km/gnus-summary-set-current-article) - (with-current-buffer gnus-original-article-buffer - (save-excursion - (--when-let (or (km/gnus--gmane-link) - (km/gnus--last-message-link)) - (funcall (if follow - #'browse-url - (lambda (s) (kill-new (message s)))) - it))))) - -(defun km/gnus-open-github-patch () - "Open patch from github email. -A new buffer with the patch contents is opened in another window." - (interactive) - (km/gnus-summary-set-current-article) - (let ((bufname (generate-new-buffer-name "*gnus-github-patch*")) - url) - (with-current-buffer gnus-original-article-buffer - (save-excursion - (goto-char (point-min)) - (if (re-search-forward "https://github.com/.*\\.patch") - (setq url (match-string-no-properties 0)) - (user-error "No patch found")))) - (with-current-buffer (get-buffer-create bufname) - (url-insert-file-contents url) - (diff-mode) - (view-mode 1)) - (pop-to-buffer bufname))) - -(defun km/gnus-summary-catchup (&optional no-next) - "Mark all articles as read. -Don't ask for confirmation. With prefix argument NO-NEXT, exit -to group buffer instead of moving to next group." - (interactive "P") - (let ((gnus-auto-select-next (unless no-next 'quietly))) - (gnus-summary-catchup-and-exit nil t))) - -(defun km/shr-browse-url-and-goto-next () - "Run `shr-browse-url' followed by `shr-next-link'." - (interactive) - (shr-browse-url) - (shr-next-link)) - -;; This overrides `gnus-summary-goto-last-article', which is also -;; bound to 'G l'. -(define-key gnus-summary-mode-map "l" 'km/gnus-copy-message-link) -(define-key gnus-summary-mode-map "v" 'org-capture) -(define-key gnus-summary-mode-map ";" 'gnus-summary-universal-argument) -;; This overrides `gnus-summary-post-news', which is also bound to -;; 'S p'. -(define-key gnus-summary-mode-map "c" 'km/gnus-summary-catchup) -(define-key gnus-summary-mode-map "e" 'gnus-summary-scroll-up) -(define-key gnus-summary-mode-map "j" 'km/gnus-avy-goto-subword-and-select) -(define-key gnus-summary-mode-map "o" 'km/ace-link-widget) - -;; Allow `km/ace-link-widget' binding to work even when on shr widget. -(after 'shr - (define-key shr-map "o" nil) - (define-key shr-map "O" 'shr-save-contents) - (define-key shr-map "v" nil)) - -(define-key gnus-article-mode-map - (kbd "C-c l") 'km/gnus-follow-last-message-link) -(define-key gnus-article-mode-map "e" 'km/shr-browse-url-and-goto-next) -;; This overrides `gnus-summary-save-article', which is also on 'O o'. -(define-key gnus-article-mode-map "o" 'km/ace-link-widget) -(define-key gnus-article-mode-map "v" 'org-capture) - -(define-prefix-command 'km/gnus-summary-prefix-map) -(define-key gnus-summary-mode-map (kbd "C-c m") 'km/gnus-summary-prefix-map) -(define-key km/gnus-summary-prefix-map "p" 'km/gnus-open-github-patch) -(define-key km/gnus-summary-prefix-map "l" 'km/gnus-copy-gmane-link-as-kill) - -(define-prefix-command 'km/gnus-article-prefix-map) -(define-key gnus-article-mode-map (kbd "C-c m") 'km/gnus-article-prefix-map) -(define-key km/gnus-article-prefix-map "p" 'km/gnus-open-github-patch) -(define-key km/gnus-article-prefix-map "l" 'km/gnus-copy-gmane-link-as-kill) - - -;;; Message mode - -(setq message-send-mail-function 'message-send-mail-with-sendmail - message-sendmail-envelope-from 'header - message-kill-buffer-on-exit t - footnote-section-tag "") - -(add-hook 'message-send-hook 'km/message-confirm-sender) -(add-hook 'message-mode-hook 'flyspell-mode) - -(defun km/message-confirm-sender () - "Stop sending message from the wrong address." - (unless (yes-or-no-p (format "Send message from %s?" - (message-field-value "From"))) - (user-error "Not sending message"))) - - -;;; Notmuch - -(require 'notmuch) -(require 'org-notmuch) - -(setq notmuch-fcc-dirs nil - notmuch-search-oldest-first nil) - -(add-to-list 'notmuch-saved-searches - '(:name "today" :query "date:today.." :key ".")) - -(defun km/notmuch-show-copy-message-id-as-kill () - (interactive) - (kill-new (message "%s" (notmuch-show-get-message-id)))) - -(define-key notmuch-hello-mode-map "o" 'km/ace-link-widget) - -(define-key km/mail-map "n" 'notmuch) - -(define-prefix-command 'km/notmuch-show-prefix-map) -(define-key notmuch-show-mode-map (kbd "C-c m") 'km/notmuch-show-prefix-map) - -(define-key km/notmuch-show-prefix-map "i" - 'km/notmuch-show-copy-message-id-as-kill) - -(provide 'init-mail) -;;; init-mail.el ends here diff --git a/lisp/init-server.el b/lisp/init-server.el deleted file mode 100644 index 04be8b2..0000000 --- a/lisp/init-server.el +++ /dev/null @@ -1,46 +0,0 @@ -;;; init-server.el --- Emacs server configuration - -;; Copyright (C) 2012-2016 Kyle Meyer <kyle@kyleam.com> - -;; Author: Kyle Meyer <kyle@kyleam.com> -;; URL: https://github.com/kyleam/emacs.d - -;; 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 <http://www.gnu.org/licenses/>. - -;;; Code: - -(setq server-use-tcp t) -(require 'server) -(unless (server-running-p) - (server-start)) - -(let ((server (daemonp))) - (cond - ((string= server "default") - ;; Remove all mail map bindings except notmuch. - (global-set-key (kbd "C-x m") nil) - (global-set-key (kbd "C-x m n") 'notmuch) - (add-hook 'kill-emacs-hook #'km/pydoc-save-names-file) - (setq save-abbrevs 'silently - bookmark-save-flag 1)) - ((string= server "mail") - (setq mode-line-misc-info - (cons (propertize " [Mail] " 'face 'font-lock-doc-face) - mode-line-misc-info)) - (key-chord-define-global "jg" 'km/mail-map) - (setq recentf-save-file "~/.emacs.d/cache/recentf-mail") - (setq save-abbrevs nil)))) - -(provide 'init-server) -;;; init-server.el ends here diff --git a/lisp/init-yas.el b/lisp/init-yas.el deleted file mode 100644 index 0d8c31b..0000000 --- a/lisp/init-yas.el +++ /dev/null @@ -1,47 +0,0 @@ -;;; init-yas.el --- Yasnippet configuration - -;; Copyright (C) 2012-2016 Kyle Meyer <kyle@kyleam.com> - -;; Author: Kyle Meyer <kyle@kyleam.com> -;; URL: https://github.com/kyleam/emacs.d - -;; 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 <http://www.gnu.org/licenses/>. - -;;; Code: - -(require 'yasnippet) - -(setq yas-fallback-behavior nil) - -(defvar km/personal-snippets - (file-name-as-directory (expand-file-name "psnippets" user-emacs-directory))) - -(when (file-exists-p km/personal-snippets) - (add-to-list 'yas-snippet-dirs km/personal-snippets)) - -(defun km/yas-with-comment (str) - (concat comment-start - (unless (s-ends-with? " " comment-start) " ") - str comment-end)) - -(define-key yas-minor-mode-map (kbd "C-c i") 'yas-expand) -;; Remove commands with 'C-c &' prefix, which conflicts with -;; `org-mark-ring-goto' binding' -(define-key yas-minor-mode-map (kbd "C-c &") nil) -(define-key yas-minor-mode-map (kbd "<tab>") nil) -(define-key yas-minor-mode-map (kbd "TAB") nil) - -(yas-global-mode) - -(provide 'init-yas) diff --git a/lisp/init-abbrev.el b/lisp/km-abbrev.el index f1030e3..9d81da8 100644 --- a/lisp/init-abbrev.el +++ b/lisp/km-abbrev.el @@ -1,4 +1,4 @@ -;;; init-abbrev.el --- Abbrev mode configuration +;;; km-abbrev.el --- Abbrev mode extesions ;; Copyright (C) 2012-2016 Kyle Meyer <kyle@kyleam.com> @@ -20,14 +20,9 @@ ;;; Code: -(add-hook 'text-mode-hook 'abbrev-mode) -(add-hook 'prog-mode-hook 'abbrev-mode) - -(define-abbrev-table 'typo-abbrev-table nil) -(abbrev-table-put global-abbrev-table :parents - (cons typo-abbrev-table - (abbrev-table-get global-abbrev-table :parents))) +(require 'abbrev) +;;;###autoload (defun km/abbrev-add-case-global () "Define lower abbreviation for the word before point. Like `add-global-abbrev', but always make the abbreviation the @@ -44,6 +39,7 @@ lower case variant of the word before point." name (abbrev-expansion name table)))) (define-abbrev table name exp)))) +;;;###autoload (defun km/abbrev-inverse-add-uppercase-global () "Define uppercase expansion for the word before point. Like `inverse-add-global-abbrev', but always use the lower case @@ -64,8 +60,5 @@ upper case version as the expansion." (goto-char end) (expand-abbrev))))) -(define-key abbrev-map "c" 'km/abbrev-add-case-global) -(define-key abbrev-map "iu" 'km/abbrev-inverse-add-uppercase-global) - -(provide 'init-abbrev) -;;; init-abbrev.el ends here +(provide 'km-abbrev) +;;; km-abbrev.el ends here diff --git a/lisp/init-ace.el b/lisp/km-ace-link.el index 5cc588b..3de1b05 100644 --- a/lisp/init-ace.el +++ b/lisp/km-ace-link.el @@ -1,4 +1,4 @@ -;;; init-ace.el --- Configuration for AceJump-inspired friends +;;; km-ace-link.el --- Extensions for Ace Link ;; Copyright (C) 2012-2016 Kyle Meyer <kyle@kyleam.com> @@ -20,15 +20,26 @@ ;;; Code: -;;; Avy - (require 'avy) +(require 'dash) +(require 'wid-edit) -(key-chord-define-global "jf" 'avy-goto-subword-1) -(define-key isearch-mode-map (kbd "C-'") 'avy-isearch) +(declare-function dired-next-line "dired" (arg)) +(defun km/ali--dired-collect-references () + (let ((end (window-end)) + points) + (save-excursion + (goto-char (window-start)) + (while (< (point) end) + (--when-let (dired-next-line 1) + (push it points))) + (nreverse points)))) -;;; Ace Link +(autoload 'org-open-file "org") +(declare-function dired-get-filename "dired" + (&optional localp no-error-if-not-filep)) +;;;###autoload (defun km/ace-link-dired () "Ace jump to files in dired buffers." (interactive) @@ -41,16 +52,24 @@ (km/ali--dired-collect-references) #'avy--overlay-post))) -(defun km/ali--dired-collect-references () - (let ((end (window-end)) - points) +(defun km/ali--widget-collect-references () + "Collect the positions of visible widgets in buffer." + (let (candidates pt) (save-excursion - (goto-char (window-start)) - (while (< (point) end) - (--when-let (dired-next-line 1) - (push it points))) - (nreverse points)))) + (save-restriction + (narrow-to-region + (window-start) + (window-end)) + (goto-char (point-min)) + (setq pt (point)) + (while (progn (ignore-errors (widget-forward 1)) + (> (point) pt)) + (setq pt (point)) + (push (point) candidates)) + (nreverse candidates))))) +(declare-function gnus-summary-widget-forward "gnus-sum" (arg)) +;;;###autoload (defun km/ace-link-widget () "Press a widget that is visible in the current buffer. This can be used in place of `ace-link-gnus' and has the @@ -69,45 +88,5 @@ property." (km/ali--widget-collect-references) #'avy--overlay-post))) -(defun km/ali--widget-collect-references () - "Collect the positions of visible widgets in buffer." - (require 'wid-edit) - (let (candidates pt) - (save-excursion - (save-restriction - (narrow-to-region - (window-start) - (window-end)) - (goto-char (point-min)) - (setq pt (point)) - (while (progn (ignore-errors (widget-forward 1)) - (> (point) pt)) - (setq pt (point)) - (push (point) candidates)) - (nreverse candidates))))) - -(ace-link-setup-default) -(after 'org - (define-key org-mode-map (kbd "C-c m o") 'ace-link-org)) -(after 'dired - ;; This overrides the binding for `dired-find-file-other-window'. - (define-key dired-mode-map "o" 'km/ace-link-dired) - (define-key dired-mode-map "r" 'dired-find-file-other-window)) - -;;; Ace Window - -(setq aw-keys '(?a ?s ?d ?f ?g ?h ?j ?k ?l) - aw-scope 'frame) - -(defun km/ace-window (arg) - "Run `ace-window', swapping single and double C-u's." - (interactive "p") - (cl-case arg - (4 (setq arg 16)) - (16 (setq arg 4))) - (ace-window arg)) - -(key-chord-define-global "jw" 'km/ace-window) - -(provide 'init-ace) -;;; init-ace.el ends here +(provide 'km-ace-link) +;;; km-ace-link.el ends here diff --git a/lisp/km-avy.el b/lisp/km-avy.el new file mode 100644 index 0000000..ba8e058 --- /dev/null +++ b/lisp/km-avy.el @@ -0,0 +1,70 @@ +;;; km-avy.el --- Extensions for avy + +;; Copyright (C) 2012-2016 Kyle Meyer <kyle@kyleam.com> + +;; Author: Kyle Meyer <kyle@kyleam.com> +;; URL: https://github.com/kyleam/emacs.d + +;; 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 <http://www.gnu.org/licenses/>. + +;;; Code: + +(require 'avy) + +(declare-function occur-mode-display-occurrence "replace") +;;;###autoload +(defun km/occur-avy-goto-subword-1 () + "Like `avy-goto-subword-1', but display occurence." + (interactive) + (let (avy-all-windows) + (call-interactively #'avy-goto-subword-1)) + (occur-mode-display-occurrence)) + +(declare-function compilation-display-error "compile") +;;;###autoload +(defun km/grep-avy-goto-subword-1 () + "Like `avy-goto-subword-1', but call `compilation-display-error'." + (interactive) + (let (avy-all-windows) + (call-interactively #'avy-goto-subword-1)) + (compilation-display-error)) + +(declare-function org-agenda-do-context-action "org-agenda") +;;;###autoload +(defun km/org-agenda-avy-goto-subword-1 () + (interactive) + (let (avy-all-windows) + (call-interactively #'avy-goto-subword-1)) + (org-agenda-do-context-action)) + +(declare-function magit-diff-show-or-scroll-up "magit-diff") +;;;###autoload +(defun km/magit-avy-goto-subword-1 () + "Like `km/avy-goto-subword-1', but maybe show commit and limit to window." + (interactive) + (let (avy-all-windows) + (call-interactively #'avy-goto-subword-1)) + (when (derived-mode-p 'magit-log-mode) + (magit-diff-show-or-scroll-up))) + +(declare-function gnus-summary-scroll-up "gnus-sum" (lines)) +;;;###autoload +(defun km/gnus-avy-goto-subword-and-select () + (interactive) + (let (avy-all-windows) + (call-interactively #'avy-goto-subword-1)) + (gnus-summary-scroll-up 0)) + +(provide 'km-avy) +;;; km-avy.el ends here diff --git a/lisp/init-bib.el b/lisp/km-bib.el index b998c6a..1795587 100644 --- a/lisp/init-bib.el +++ b/lisp/km-bib.el @@ -1,4 +1,4 @@ -;;; init-bib.el --- Bibliography configuration +;;; km-bib.el --- Bibliography configuration ;; Copyright (C) 2012-2016 Kyle Meyer <kyle@kyleam.com> @@ -20,31 +20,9 @@ ;;; Code: -;; Make cite key have form <last author last name><year><first word>. -(setq bibtex-autokey-titlewords 1 - bibtex-autokey-titleword-ignore '("A" "An" "On" "The" "[0-9].*") - bibtex-autokey-titleword-length nil - bibtex-autokey-titlewords-stretch 0 - bibtex-autokey-year-length 4 - bibtex-autokey-year-title-separator "") - -(setq bibtex-align-at-equal-sign t) ; Used by `bibtex-fill-entry'. - -(after 'bibtex - (setq bibtex-entry-format - (append '(realign whitespace last-comma delimiters sort-fields) - bibtex-entry-format))) - -(add-hook 'bibtex-clean-entry-hook 'km/bibtex-use-title-case) -(add-hook 'bibtex-clean-entry-hook 'km/bibtex-single-space-author-list) -(add-hook 'bibtex-clean-entry-hook 'km/bibtex-pages-use-double-hyphen) -(add-hook 'bibtex-clean-entry-hook 'km/bibtex-remove-doi-leader) -(add-hook 'bibtex-clean-entry-hook 'km/bibtex-set-coding-system) -(add-hook 'bibtex-clean-entry-hook 'km/bibtex-remove-entry-space) -(add-hook 'bibtex-clean-entry-hook 'km/bibtex-downcase-entry) -(add-hook 'bibtex-clean-entry-hook 'km/bibtex-downcase-keys) -(add-hook 'bibtex-clean-entry-hook 'km/bibtex-downcase-author-and) -(add-hook 'bibtex-clean-entry-hook 'km/bibtex-delete-article-fields) +(require 'bibtex) +(require 'dash) +(require 'org) (defvar km/bibtex-unimportant-title-words '("a" "aboard" "about" "above" "absent" "across" "after" "against" @@ -200,6 +178,7 @@ to (delete-region (bibtex-start-of-field bounds) (point)))))))) +;;;###autoload (defun km/browse-doi (doi) "Open DOI in browser. When called interactively, take the DOI from the text under @@ -208,6 +187,7 @@ point. The link is opened using the settings of (interactive (list (km/doi-at-point))) (browse-url (org-link-escape-browser (concat org-doi-server-url doi)))) +;;;###autoload (defun km/copy-doi-as-kill () "Copy DOI at point to kill ring." (interactive) @@ -221,5 +201,5 @@ point. The link is opened using the settings of (and (looking-at "\\(doi:[ \t\n]*\\)*\\([-./A-z0-9]+[A-z0-9]\\)\\b") (match-string-no-properties 2)))) -(provide 'init-bib) -;;; init-bib.el ends here +(provide 'km-bib) +;;; km-bib.el ends here diff --git a/lisp/km-buffer-cleanup.el b/lisp/km-buffer-cleanup.el new file mode 100644 index 0000000..ac0b008 --- /dev/null +++ b/lisp/km-buffer-cleanup.el @@ -0,0 +1,52 @@ +;;; km-buffer-cleanup.el --- Clean up buffer on save + +;; Copyright (C) 2012-2016 Kyle Meyer <kyle@kyleam.com> + +;; Author: Kyle Meyer <kyle@kyleam.com> +;; URL: https://github.com/kyleam/emacs.d + +;; 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 <http://www.gnu.org/licenses/>. + +;;; Code: + +(require 'whitespace) + +(defvar-local km/prevent-cleanup nil + "If set, `km/cleanup-buffer' does not perform clean up on save.") + +(defun km/toggle-prevent-cleanup () + "Toggle state of `km/prevent-cleanup'." + (interactive) + (if km/prevent-cleanup + (progn + (message "Allowing cleanup on save") + (kill-local-variable 'whitespace-style) + (global-whitespace-mode 0) + (global-whitespace-mode 1)) + (message "Preventing cleanup on save") + (setq-local whitespace-style + '(face trailing indentation + tab-mark space-mark newline-mark)) + (global-whitespace-mode 0) + (global-whitespace-mode 1)) + (setq km/prevent-cleanup (not km/prevent-cleanup))) + +(defun km/cleanup-buffer () + (interactive) + (unless km/prevent-cleanup + (whitespace-cleanup) + (delete-trailing-whitespace))) + +(provide 'km-buffer-cleanup) +;;; km-buffer-cleanup.el ends here diff --git a/lisp/init-buffers.el b/lisp/km-buffers.el index e16d6e6..b2138de 100644 --- a/lisp/init-buffers.el +++ b/lisp/km-buffers.el @@ -1,4 +1,4 @@ -;;; init-buffers.el --- Buffer-related configuration +;;; km-buffers.el --- Buffer-related extensions ;; Copyright (C) 2012-2016 Kyle Meyer <kyle@kyleam.com> @@ -20,20 +20,14 @@ ;;; Code: -(require 'uniquify) - -(setq uniquify-buffer-name-style 'forward) - -(setq ibuffer-expert t - ibuffer-restore-window-config-on-quit t - ibuffer-show-empty-filter-groups nil) - +;;;###autoload (defun km/save-and-kill-buffer () "Save current buffer and then kill it." (interactive) (save-buffer) (kill-this-buffer)) +;;;###autoload (defun km/kill-buffer (&optional arg) "Kill this buffer. With single C-u, prompt for buffer to kill. With double C-u, @@ -47,6 +41,7 @@ kill this buffer and the window." (t (call-interactively #'kill-buffer)))) +;;;###autoload (defun km/save-buffers () "Run `save-some-buffers', but don't ask to save the current buffer. `save-some-buffers' is called interactively." @@ -61,12 +56,5 @@ kill this buffer and the window." (save-buffer)))) (call-interactively #'save-some-buffers)) -(global-set-key (kbd "C-x k") 'km/kill-buffer) - -(key-chord-define-global "js" 'km/save-buffers) - -;; Replace `list-buffers' with ibuffer. -(global-set-key (kbd "C-x C-b") 'ibuffer) - -(provide 'init-buffers) -;;; init-buffers.el ends here +(provide 'km-buffers) +;;; km-buffers.el ends here diff --git a/lisp/km-compile.el b/lisp/km-compile.el new file mode 100644 index 0000000..4812afd --- /dev/null +++ b/lisp/km-compile.el @@ -0,0 +1,94 @@ +;;; km-compile.el --- Compilation extensions + +;; Copyright (C) 2012-2016 Kyle Meyer <kyle@kyleam.com> + +;; Author: Kyle Meyer <kyle@kyleam.com> +;; URL: https://github.com/kyleam/emacs.d + +;; 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 <http://www.gnu.org/licenses/>. + +;;; Code: + + +(require 'compile) +(require 'dash) + +(defvar km/compilation-buffer-name-prefix "compilation: ") + +(defun km/compilation-name-by-directory (&optional mode) + (let ((name (if (and mode (not (equal mode "compilation"))) + (downcase mode) + (concat km/compilation-buffer-name-prefix + (abbreviate-file-name default-directory))))) + (concat "*" name "*"))) + +(defun km/compilation-buffer-p (buffer) + (with-current-buffer buffer + (and (derived-mode-p 'compilation-mode) + (string-prefix-p (concat "*" km/compilation-buffer-name-prefix) + (buffer-name))))) + +;;;###autoload +(defun km/compile-in-home-dir () + (interactive) + (let ((default-directory "~/")) + (call-interactively #'compile))) + +;;;###autoload +(defun km/compilation-recompile (&optional arg) + "Recompile buffer. +By default, use `compilation-last-buffer'. If ARG is 0, get +buffer with name given by `km/compilation-name-by-directory'. +Otherwise, if ARG is non-nil, prompt with buffers from +`km/compilation-buffer-list'." + (interactive (list (and current-prefix-arg + (prefix-numeric-value current-prefix-arg)))) + (with-current-buffer (km/compilation--get-buffer arg) + (if (derived-mode-p 'occur-mode) + (revert-buffer) + (recompile)))) + +(defun km/compilation-display-buffer (&optional arg) + "Display compilation buffer. +By default, use `compilation-last-buffer'. If ARG is 0, get +buffer with name given by `km/compilation-name-by-directory'. +Otherwise, if ARG is non-nil, prompt with buffers from +`km/compilation-buffer-list'." + (interactive (list (and current-prefix-arg + (prefix-numeric-value current-prefix-arg)))) + (display-buffer (km/compilation--get-buffer arg))) + +(defun km/compilation--get-buffer (&optional arg) + (cond + ((and (not arg) + (buffer-live-p compilation-last-buffer) + compilation-last-buffer)) + ((and (numberp arg) + (= arg 0)) + (get-buffer (km/compilation-name-by-directory))) + (t + (let ((cbufs (-map #'buffer-name (km/compilation-buffer-list))) + buf) + (cl-case (length cbufs) + (0 (user-error "No compilation buffers found")) + (1 (setq buf (car cbufs))) + (t (setq buf (completing-read "Compilation buffer: " cbufs + nil nil nil nil (car cbufs))))) + buf)))) + +(defun km/compilation-buffer-list () + (-filter #'km/compilation-buffer-p (buffer-list))) + +(provide 'km-compile) +;;; km-compile.el ends here diff --git a/lisp/km-diff.el b/lisp/km-diff.el new file mode 100644 index 0000000..69a5a64 --- /dev/null +++ b/lisp/km-diff.el @@ -0,0 +1,57 @@ +;;; km-diff.el --- Diff-related extensions + +;; Copyright (C) 2012-2016 Kyle Meyer <kyle@kyleam.com> + +;; Author: Kyle Meyer <kyle@kyleam.com> +;; URL: https://github.com/kyleam/emacs.d + +;; 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 <http://www.gnu.org/licenses/>. + +;;; Code: + +(require 'dash) +(require 'diff) +(require 'ediff) +(require 'view) + +;;;###autoload +(defun km/diff () + "Run `diff' and then select buffer and turn on View mode." + (interactive) + (call-interactively #'diff) + (select-window (get-buffer-window "*Diff*")) + (view-mode 1)) + +;;;###autoload +(defun km/revert-buffer-and-view () + (interactive) + (revert-buffer) + (view-mode 1)) + +;;;###autoload +(defun km/ediff-with-other-window () + "Run `ediff' on current window's file and other window's file." + (interactive) + (let ((windows (window-list))) + (unless (= (length windows) 2) + (user-error "Function restricted to two-window frames")) + (-if-let* ((file-a (buffer-file-name + (window-buffer (car windows)))) + (file-b (buffer-file-name + (window-buffer (cadr windows))))) + (ediff file-a file-b) + (user-error "At least one buffer is not visiting a file")))) + +(provide 'km-diff) +;;; km-diff.el ends here diff --git a/lisp/init-dired.el b/lisp/km-dired.el index ba976ea..bbd38e6 100644 --- a/lisp/init-dired.el +++ b/lisp/km-dired.el @@ -1,4 +1,4 @@ -;;; init-dired.el --- Dired configuration +;;; km-dired.el --- Dired extensions ;; Copyright (C) 2012-2016 Kyle Meyer <kyle@kyleam.com> @@ -20,45 +20,16 @@ ;;; Code: -(require 'dired-x) - -(put 'dired-find-alternate-file 'disabled nil) - -;; .git is present as part of `dired-omit-extensions', but this seems to -;; only be taken into account if a non-exension part exists. -(setq dired-omit-files - (concat dired-omit-files - "\\|^\\.git$\\|^\\.gitignore$" - "\\|^__pycache__$\\|^\\.snakemake$")) - -(defvar km/latex-omit-extensions '(".aux" - ".fdb_latexmk" - ".fls" - ".log" - ".nav" - ".out" - ".snm") - "Intermediate LaTeX files") - -(setq dired-omit-extensions - (append dired-omit-extensions km/latex-omit-extensions)) - -(setq-default dired-omit-mode t) -(setq dired-dwim-target t - dired-listing-switches "-alht") - -(setq dired-guess-shell-alist-user - '(("\\.pdf\\'" "zathura"))) - -(setq dired-recursive-copies t - dired-recursive-deletes t) - -(add-hook 'dired-mode-hook 'dired-hide-details-mode) +(require 'dired) +(require 'org) +(require 'km-util) +(require 'projectile) (defun km/dired-switch-to-buffer () (interactive) (switch-to-buffer (km/dired-completing-buffer))) +;;;###autoload (defun km/dired-switch-to-buffer-other-window () (interactive) (pop-to-buffer (km/dired-completing-buffer))) @@ -67,6 +38,7 @@ (completing-read "Dired buffer: " (mapcar #'buffer-name (km/mode-buffers 'dired-mode)))) +;;;###autoload (defun km/org-open-dired-marked-files (&optional arg) "Open marked files (or next ARG) with `org-open-file'." (interactive "p") @@ -77,11 +49,13 @@ (yes-or-no-p (format "Open %s files?" num-files))) (dolist (f files) (org-open-file f))))) +;;;###autoload (defun km/dired-view-file-other-window () "In Dired, view this file in another window." (interactive) (view-file-other-window (dired-get-file-for-visit))) +;;;###autoload (defun km/dired-copy-and-edit () "Copy file and enter `wdired-mode' for completing rename." (interactive) @@ -101,56 +75,10 @@ flag)) (replace-match "" t nil nil 1))) -;; This overrides the binding for `list-directory'. -(global-set-key (kbd "C-x C-d") 'km/dired-switch-to-buffer) -(define-key dired-mode-map "c" 'dired-do-copy) -(define-key dired-mode-map "C" 'km/dired-copy-and-edit) -;; This overrides `dired-do-run-mail'. -(define-key dired-mode-map "V" 'km/dired-view-file-other-window) - -(define-key ctl-x-4-map "D" 'km/dired-switch-to-buffer-other-window) - -(define-prefix-command 'km/dired-prefix-map) -(define-key dired-mode-map (kbd "C-c m") 'km/dired-prefix-map) - -(after 'org - ;; This overrides `dired-find-file', which is also bound to "f". - (define-key dired-mode-map "e" 'km/org-open-dired-marked-files)) - - -;;; Dired Narrow - -(define-key dired-mode-map "/" 'dired-narrow) - -(define-prefix-command 'km/dired-narrow-prefix-map) -(define-key km/dired-prefix-map "n" 'km/dired-narrow-prefix-map) - -(define-key km/dired-narrow-prefix-map "f" 'dired-narrow-fuzzy) -(define-key km/dired-narrow-prefix-map "n" 'dired-narrow) -(define-key km/dired-narrow-prefix-map "r" 'dired-narrow-regexp) - - -;;; Dired Subtree - -(define-prefix-command 'km/dired-subtree-prefix-map) -(define-key km/dired-prefix-map "s" 'km/dired-subtree-prefix-map) - -(define-key km/dired-subtree-prefix-map "@" 'dired-subtree-mark-subtree) -(define-key km/dired-subtree-prefix-map "." 'dired-subtree-unmark-subtree) -(define-key km/dired-subtree-prefix-map "<" 'dired-subtree-beginning) -(define-key km/dired-subtree-prefix-map ">" 'dired-subtree-end) -(define-key km/dired-subtree-prefix-map "g" 'dired-subtree-revert) -(define-key km/dired-subtree-prefix-map "d" 'dired-subtree-down) -(define-key km/dired-subtree-prefix-map "i" 'dired-subtree-insert) -(define-key km/dired-subtree-prefix-map "n" 'dired-subtree-next-sibling) -(define-key km/dired-subtree-prefix-map "p" 'dired-subtree-previous-sibling) -(define-key km/dired-subtree-prefix-map "r" 'dired-subtree-remove) -(define-key km/dired-subtree-prefix-map "s" 'dired-subtree-narrow) -(define-key km/dired-subtree-prefix-map "u" 'dired-subtree-up) - ;;; Copying file names +;;;###autoload (defun km/dired-copy-project-filename-as-kill () "Copy names of marked project files into kill ring. This is similar to `dired-copy-filename-as-kill', but the leading @@ -159,6 +87,7 @@ path is always relative to `projectile-project-root'." (km/dired-copy-filename-relative-to-directory (projectile-project-root))) +;;;###autoload (defun km/dired-copy-relative-filename-as-kill (&optional arg) "Copy names of marked (or next ARG) files into kill ring. This is similar to `dired-copy-filename-as-kill', but the leading @@ -188,15 +117,5 @@ relative to DIRECTORY." (other-window 1) default-directory)) -(define-prefix-command 'km/dired-copy-filename-map) -;; This overrides the default binding for `dired-copy-filename-as-kill'. -(define-key dired-mode-map "w" 'km/dired-copy-filename-map) - -(after 'projectile - (define-key km/dired-copy-filename-map "p" - 'km/dired-copy-project-filename-as-kill)) -(define-key km/dired-copy-filename-map "o" 'km/dired-copy-relative-filename-as-kill) -(define-key km/dired-copy-filename-map "w" 'dired-copy-filename-as-kill) - -(provide 'init-dired) -;;; init-dired.el ends here +(provide 'km-dired) +;;; km-dired.el ends here diff --git a/lisp/init-editing.el b/lisp/km-editing.el index 618431c..eb93d0c 100644 --- a/lisp/init-editing.el +++ b/lisp/km-editing.el @@ -1,4 +1,4 @@ -;;; init-editing.el --- Editing-related configuration +;;; km-editing.el --- Editing-related extensions ;; Copyright (C) 2012-2016 Kyle Meyer <kyle@kyleam.com> @@ -20,37 +20,22 @@ ;;; Code: -;; http://irreal.org/blog/?p=1536 -(autoload 'zap-up-to-char "misc" - "Kill up to, but not including ARGth occurrence of CHAR.") - -(setq hippie-expand-try-functions-list '(try-complete-file-name-partially - try-complete-file-name - try-expand-all-abbrevs - try-expand-dabbrev - try-expand-dabbrev-all-buffers - try-expand-dabbrev-from-kill - try-complete-lisp-symbol-partially - try-complete-lisp-symbol)) - -;; This is bound separately in `km/editing-map'. -(setq iedit-toggle-key-default nil) - -(setq flyspell-auto-correct-binding (kbd "C-c e ;")) - -(after 'flyspell - (define-key flyspell-mode-map (kbd "C-.") nil)) - -(put 'fill-paragraph-function 'safe-local-variable - (lambda (v) (equal v (lambda (_) t)))) +(require 'dash) +(require 'outline) +(require 's) +(require 'select) +(require 'thingatpt) +(require 'whitespace) ;; http://www.emacswiki.org/emacs/UnfillParagraph +;;;###autoload (defun km/unfill-paragraph () "Convert a multi-line paragraph to a single line of text." (interactive) (let ((fill-column (point-max))) (fill-paragraph nil))) +;;;###autoload (defun km/fill-surrounding-indented () "Fill current line with all surrounding lines of same indentation. This is like `fill-individual-paragraphs', but 1) it acts only on @@ -83,6 +68,7 @@ special case. (setq end (point)))) (fill-region (or beg (point-min)) (or end (point-max)))))) +;;;###autoload (defun km/reduce-to-single-spaces () "Reduce consecutive blank lines to a single line." (interactive) @@ -92,6 +78,7 @@ special case. (forward-line -1) (delete-blank-lines)))) +;;;###autoload (defun km/export-wrapped-text (&optional xselect) "Export the text in current buffer as wrapped text. @@ -117,6 +104,7 @@ XSELECT is non-nil, copy the region with `x-select-text'." (buffer-substring-no-properties (point-min) (point-max))))) (pop-to-buffer wrapped-buffer))) +;;;###autoload (defun km/narrow-to-comment-heading () "Narrow to the current comment heading subtree. @@ -170,6 +158,7 @@ and '<<<' mark the bounds of the narrowed region. (outline-mark-subtree) (narrow-to-region (region-beginning) (region-end))))) +;;;###autoload (defun km/toggle-line-or-region-comment (beg end) "Comment or uncomment the current line or region. If there is an active region, act on all lines that the region @@ -187,6 +176,7 @@ touches." (forward-line)))) ;; Modified from http://oremacs.com/2015/01/26/occur-dwim/. +;;;###autoload (defun km/occur () "Call `occur' with active region or symbol at point." (interactive) @@ -197,99 +187,10 @@ touches." (push it regexp-history)) (call-interactively 'occur)) -(defun km/occur-avy-goto-subword-1 () - "Like `avy-goto-subword-1', but display occurence." - (interactive) - (let (avy-all-windows) - (call-interactively #'avy-goto-subword-1)) - (occur-mode-display-occurrence)) - -(global-set-key (kbd "C-x \\") 'align-regexp) - -(global-set-key (kbd "C-.") 'er/expand-region) - -(global-set-key [remap kill-ring-save] 'easy-kill) - -;; Overrides `suspend-emacs' (which is also bound to C-x C-z). -(global-set-key (kbd "C-z") 'zap-to-char) -(global-set-key (kbd "M-z") 'zap-up-to-char) -(global-set-key (kbd "C-'") 'backward-kill-word) - -(global-set-key (kbd "M-/") 'hippie-expand) - -(key-chord-define-global "jx" 'km/toggle-line-or-region-comment) -(key-chord-define-global "qp" 'fill-paragraph) - -(define-key ctl-x-4-map "nd" 'ni-narrow-to-defun-indirect-other-window) -(define-key ctl-x-4-map "nn" 'ni-narrow-to-region-indirect-other-window) -(define-key ctl-x-4-map "np" 'ni-narrow-to-page-indirect-other-window) - -(define-key narrow-map "c" 'km/narrow-to-comment-heading) - -(define-key occur-mode-map "n" 'next-line) -(define-key occur-mode-map "p" 'previous-line) -(define-key occur-mode-map "j" 'km/occur-avy-goto-subword-1) - -;; Override default `occur'. -(define-key search-map "o" 'km/occur) -(define-key search-map "s" 'query-replace) -(define-key search-map "S" 'replace-string) -(define-key search-map "r" 'query-replace-regexp) -(define-key search-map "R" 'replace-regexp) - -(define-prefix-command 'km/editing-map) -(global-set-key (kbd "C-c e") 'km/editing-map) - -(define-key km/editing-map (kbd "C-i") 'indent-relative) -(define-key km/editing-map "f" 'km/fill-surrounding-indented) -(define-key km/editing-map "i" 'iedit-mode) -(define-key km/editing-map "l" 'toggle-truncate-lines) -(define-key km/editing-map "u" 'km/unfill-paragraph) -(define-key km/editing-map "w" 'ispell-word) - -(electric-indent-mode -1) -(electric-pair-mode 1) - - -;;; Buffer cleanup - -(setq whitespace-style '(face trailing indentation)) - -(global-whitespace-mode 1) - -(add-hook 'before-save-hook 'km/cleanup-buffer) - -(defvar-local km/prevent-cleanup nil - "If set, `km/cleanup-buffer' does not perform clean up on save.") - -(defun km/toggle-prevent-cleanup () - "Toggle state of `km/prevent-cleanup'." - (interactive) - (if km/prevent-cleanup - (progn - (message "Allowing cleanup on save") - (kill-local-variable 'whitespace-style) - (global-whitespace-mode 0) - (global-whitespace-mode 1)) - (message "Preventing cleanup on save") - (setq-local whitespace-style - '(face trailing indentation - tab-mark space-mark newline-mark)) - (global-whitespace-mode 0) - (global-whitespace-mode 1)) - (setq km/prevent-cleanup (not km/prevent-cleanup))) - -(defun km/cleanup-buffer () - (interactive) - (unless km/prevent-cleanup - (whitespace-cleanup) - (delete-trailing-whitespace))) - -(define-key km/editing-map "t" 'km/toggle-prevent-cleanup) - ;;; Kill map +;;;###autoload (defun km/kill-string-at-point () (interactive) (let ((string-start (nth 8 (syntax-ppss)))) @@ -297,6 +198,7 @@ touches." (kill-sexp))) ;; Taken from prelude-core.el. +;;;###autoload (defun km/join-next-line-with-space () "Join current line to the next line with a space in between." (interactive) @@ -314,84 +216,5 @@ touches." (km/make-kill-thing-at-point "sentence") (km/make-kill-thing-at-point "word") -(define-prefix-command 'km/kill-map) -(global-set-key (kbd "C-c k") 'km/kill-map) - -(define-key km/kill-map "." 'km/kill-sentence-at-point) -(define-key km/kill-map "j" 'km/join-next-line-with-space) -(define-key km/kill-map "l" 'km/kill-line-at-point) -(define-key km/kill-map "p" 'km/kill-paragraph-at-point) -(define-key km/kill-map "s" 'km/kill-string-at-point) -(define-key km/kill-map "w" 'km/kill-word-at-point) - - -;;; Multiple cursors - -;; Multiple cursors hydra is modified from -;; https://github.com/abo-abo/hydra/wiki/multiple-cursors -(define-key km/editing-map "o" - (defhydra hydra-multiple-cursors (:hint nil) - " - ^^Up ^^Down -_p_ Next _n_ Next -_P_ Skip _N_ Skip -_y_ Unmark _u_ Unmark - -" - ("l" mc/edit-lines "edit lines" :exit t) - ("a" mc/mark-all-like-this "mark all" :exit t) - ("n" mc/mark-next-like-this) - ("N" mc/skip-to-next-like-this) - ("u" mc/unmark-next-like-this) - ("p" mc/mark-previous-like-this) - ("P" mc/skip-to-previous-like-this) - ("y" mc/unmark-previous-like-this))) - - -;;; Keyboard macros - -(define-key km/editing-map "k" - (defhydra hydra-kmacro (:hint nil :exit t) - " - ^^Defining ^^Applying -_?_ Query _c_ Call -_b_ Bind to key _o_ Call 2nd in ring -_e_ Edit _r_ Apply to region lines -_E_ Step edit -_N_ Name last -_l_ Use recent strokes -_s_ Start defining -_x_ To register - - ^^Ring ^^Counter -_D_ Delete ring head _+_ Add counter -_n_ Cycle next _=_ Set counter -_p_ Cycle previous _f_ Set format -_t_ Swap _i_ Insert counter -_v_ View - -" - ("+" kmacro-add-counter) - ("=" kmacro-set-counter) - ("D" kmacro-delete-ring-head) - ("f" kmacro-set-format) - ("i" kmacro-insert-counter) - ("c" kmacro-end-and-call-macro :exit nil) - ("o" kmacro-call-ring-2nd-repeat) - ("e" kmacro-edit-macro) - ("E" kmacro-step-edit-macro) - ("n" kmacro-cycle-ring-next :exit nil) - ("p" kmacro-cycle-ring-previous :exit nil) - ("t" kmacro-swap-ring) - ("v" kmacro-view-macro-repeat) - ("b" kmacro-bind-to-key) - ("l" kmacro-edit-lossage) - ("N" kmacro-name-last-macro) - ("?" kbd-macro-query) - ("r" apply-macro-to-region-lines) - ("s" kmacro-start-macro) - ("x" kmacro-to-register) - ("q" nil "quit" :hint t))) - -(provide 'init-editing) -;;; init-editing.el ends here +(provide 'km-editing) +;;; km-editing.el ends here diff --git a/lisp/init-ess.el b/lisp/km-ess.el index d951ede..c7c2c8c 100644 --- a/lisp/init-ess.el +++ b/lisp/km-ess.el @@ -1,4 +1,4 @@ -;;; init-ess.el --- ESS configuration +;;; km-ess.el --- ESS extensions ;; Copyright (C) 2012-2016 Kyle Meyer <kyle@kyleam.com> @@ -20,24 +20,11 @@ ;;; Code: -(autoload 'R-mode "ess-site") - -(setq ess-smart-S-assign-key ";") - -(setq ess-use-ido nil) - -(add-to-list 'auto-mode-alist '("\\.[rR]\\'" . R-mode)) - -(define-abbrev-table 'ess-mode-abbrev-table - '(("true" "TRUE") - ("false" "FALSE")) - :system t) - -(dolist (hook '(ess-mode-hook inferior-ess-mode-hook)) - (add-hook hook (lambda () - (setq local-abbrev-table ess-mode-abbrev-table))) - (add-hook hook 'abbrev-mode)) +(require 'ess-comp) +(require 'ess-inf) +(require 'ess-s-l) +;;;###autoload (defun km/ess-eval-buffer-up-to-line () "Send up to the current line to inferior ESS process." (interactive) @@ -45,6 +32,7 @@ (defvar km/ess-dplry-pipe-key "|") +;;;###autoload (defun km/ess-insert-dplyr-pipe () "Insert `km/ess-dplry-pipe' using `ess-smart-S-assign'. Based on instructions in `ess-smart-S-assign-key', I didn't think @@ -54,12 +42,5 @@ this would work, but it seems to so far." (ess-smart-S-assign-key km/ess-dplry-pipe-key)) (call-interactively #'ess-smart-S-assign))) -(after 'ess-mode - (define-key ess-mode-map (kbd "C-c C-.") 'km/ess-eval-buffer-up-to-line) - (define-key ess-mode-map "|" 'km/ess-insert-dplyr-pipe)) - -(after 'ess-inf - (define-key inferior-ess-mode-map "|" 'km/ess-insert-dplyr-pipe)) - -(provide 'init-ess) -;;; init-ess.el ends here +(provide 'km-ess) +;;; km-ess.el ends here diff --git a/lisp/init-files.el b/lisp/km-files.el index 8b53a38..8c1f679 100644 --- a/lisp/init-files.el +++ b/lisp/km-files.el @@ -1,4 +1,4 @@ -;;; init-files.el --- File-related configuration +;;; km-files.el --- File-related extensions ;; Copyright (C) 2012-2016 Kyle Meyer <kyle@kyleam.com> @@ -20,23 +20,9 @@ ;;; Code: -(require 'uniquify) - -(add-to-list 'load-path "~/src/emacs/nlines/") -(require 'nlines-autoloads) - -(setq require-final-newline t - ffap-machine-p-known 'reject) - -(after 'mailcap - (mailcap-parse-mailcaps) - (pcase-dolist (`(_ . ,info) - (cdr (assoc-string "application" mailcap-mime-data))) - ;; Instead of deleting doc-view-mode entry, just make its test - ;; always fail. - (when (eq (cdr (assq 'viewer info)) 'doc-view-mode) - (setf (cdr (assq 'test info)) (lambda (&rest _) nil))))) +(require 'recentf) +;;;###autoload (defun km/rename-current-buffer-file () "Rename current buffer and file it is visiting." (interactive) @@ -55,6 +41,7 @@ name (file-name-nondirectory new-name))))))) ;; https://github.com/purcell/emacs.d/blob/master/lisp/init-utils.el +;;;###autoload (defun km/delete-this-file () "Delete the current file, and kill the buffer." (interactive) @@ -65,6 +52,7 @@ (kill-this-buffer))) ;; http://emacs-fu.blogspot.com/2013/03/editing-with-root-privileges-once-more.html +;;;###autoload (defun km/find-file-as-root () "Automatically edit file with root-privileges." (interactive) @@ -73,6 +61,8 @@ (setq file (concat "/sudo:root@localhost:" file))) (find-file file))) +(declare-function dired-jump (&optional other-window file-name)) +;;;###autoload (defun km/dired-jump-file-at-point () "Run `dired-jump' on file at point." (interactive) @@ -84,6 +74,7 @@ (dired-jump 'other-window (expand-file-name file)) (user-error "No file at point")))) +;;;###autoload (defun km/touch-buffer-file () "Run touch on `buffer-file-name'." (interactive) @@ -91,6 +82,7 @@ (or (buffer-file-name (buffer-base-buffer)) (user-error "Not visiting file")))) +;;;###autoload (defun km/write-file () "Run `write-file'. Use the current file name as initial input of prompt." @@ -101,100 +93,22 @@ Use the current file name as initial input of prompt." init-file))) (write-file new-file t))) -(global-set-key (kbd "C-x C-w") 'km/write-file) - -(define-key ctl-x-4-map "v" 'view-file-other-window) - -(define-prefix-command 'km/file-map) -(global-set-key (kbd "C-c f") 'km/file-map) - -(define-key km/file-map "j" 'km/dired-jump-file-at-point) -(define-key km/file-map "R" 'km/find-file-as-root) -(define-key km/file-map "n" 'km/rename-current-buffer-file) -(define-key km/file-map "l" 'nlines-run-command) -(define-key km/file-map "t" 'km/touch-buffer-file) -(define-key km/file-map "v" 'view-file) - - -;;; Search - -(autoload 'vc-git-grep "vc-git" - "Run git grep, searching for REGEXP in FILES in directory DIR. -The search is limited to file names matching shell pattern FILES. -FILES may use abbreviations defined in `grep-files-aliases', e.g. -entering `ch' is equivalent to `*.[ch]'.") - -(add-hook 'grep-setup-hook 'km/grep-hide-header) -(add-hook 'grep-mode-hook 'toggle-truncate-lines) - -(defun km/grep-hide-header () - (let ((beg (save-excursion (goto-char (point-min)) - (line-beginning-position 5)))) - (narrow-to-region beg (point-max)))) - -(defun km/grep-avy-goto-subword-1 () - "Like `avy-goto-subword-1', but call `compilation-display-error'." - (interactive) - (let (avy-all-windows) - (call-interactively #'avy-goto-subword-1)) - (compilation-display-error)) - -(after 'grep - (define-key grep-mode-map "j" 'km/grep-avy-goto-subword-1)) - -(define-prefix-command 'km/file-search-map) -(define-key km/file-map "s" 'hydra-file-search-map/body) - -(defhydra hydra-file-search-map (:hint nil :color blue) - " -^^Grep ^^Dired -^^------------ ^^------------------ -_f_: grep-find _d_: find-grep-dired -_g_: lgrep _D_: find-dired -_G_: grep _n_: find-name-dired -_r_: rgrep -_v_: vc-git-grep -_z_: zgrep -\n" - ("f" grep-find) - ("g" lgrep) - ("G" grep) - ("r" rgrep) - ("v" vc-git-grep) - ("z" zrgrep) - - ("d" find-grep-dired) - ("D" find-dired) - ("n" find-name-dired) - - ("q" nil "quit")) - - -;;; Recent files - -(setq recentf-max-menu-items 15 - recentf-max-saved-items 200 - recentf-save-file "~/.emacs.d/cache/recentf") -(recentf-mode) - ;; Modified from prelude +;;;###autoload (defun km/recentf-find-file () "Find a file from `recentf-list'." (interactive) (find-file (km/read-recent-file))) +;;;###autoload (defun km/recentf-find-file-other-window () "Find a file from `recentf-list' in other window." (interactive) (find-file-other-window (km/read-recent-file))) -;; This overrides `find-file-read-only-other-window', but -;; `view-file-other-window', which I map to 'v', has the same -;; functionality. + (defun km/read-recent-file () (completing-read "Choose recent file: " recentf-list nil t)) -(define-key ctl-x-4-map "r" 'km/recentf-find-file-other-window) - ;;; Scratch files @@ -213,6 +127,7 @@ _z_: zgrep Format of each element should be (CHARACTER EXTENSION DOC). DOC is not required.") +;;;###autoload (defun km/scratch-find-file (&optional pwd) "Find scratch buffer. @@ -224,6 +139,7 @@ With prefix argument PWD, find the scratch file in (interactive "P") (switch-to-buffer (km/scratch--find-file-no-select pwd))) +;;;###autoload (defun km/scratch-find-file-other-window (&optional pwd) "Like `km/find-scratch-file', but open buffer in another window." (interactive "P") @@ -238,8 +154,5 @@ With prefix argument PWD, find the scratch file in (ext (cadr (assq ch km/find-scratch-buffers)))) (concat (if pwd default-directory "/tmp/") "scratch" ext))) -(global-set-key (kbd "C-c s") 'km/scratch-find-file) -(define-key ctl-x-4-map "s" 'km/scratch-find-file-other-window) - -(provide 'init-files) -;;; init-files.el ends here +(provide 'km-files) +;;; km-files.el ends here diff --git a/lisp/init-framewin.el b/lisp/km-framewin.el index 8821610..a81f464 100644 --- a/lisp/init-framewin.el +++ b/lisp/km-framewin.el @@ -1,4 +1,4 @@ -;;; init-framewin.el --- Frame and window configuration +;;; km-framewin.el --- Frame and window extensions ;; Copyright (C) 2012-2016 Kyle Meyer <kyle@kyleam.com> @@ -20,6 +20,7 @@ ;;; Code: +;;;###autoload (defun km/clone-indirect-buffer-other-window-and-widen () "Clone as indirect buffer and then widen." (interactive) @@ -27,6 +28,7 @@ (widen)) ;; From prelude +;;;###autoload (defun km/swap-windows () "Swap 2 windows." (interactive) @@ -45,6 +47,7 @@ (other-window 1)) ;; http://www.emacswiki.org/emacs/ToggleWindowSplit +;;;###autoload (defun km/switch-window-split () "If the window is split vertically, split it horizontally or vice versa. Assumes that the window is only split into two." @@ -58,30 +61,5 @@ Assumes that the window is only split into two." (split-window-vertically)) (switch-to-buffer nil))) -(defhydra hydra-window-map (:hint nil) - " -_l_: Switch split _r_: Winner redo _o_: Scroll other -_s_: Swap _u_: Winner undo _i_: Scroll other down -\n" - ("l" km/switch-window-split) - ("s" km/swap-windows) - - ("r" winner-redo) - ("u" winner-undo) - - ("o" scroll-other-window) - ("i" scroll-other-window-down) - - ("f" make-frame "new frame" :color blue) - ("q" nil "quit")) - -(global-set-key (kbd "C-c w") 'hydra-window-map/body) - -(key-chord-define-global "lq" 'winner-undo) - -(define-key ctl-x-4-map "c" 'km/clone-indirect-buffer-other-window-and-widen) - -(winner-mode 1) - -(provide 'init-framewin) -;;; init-framewin.el ends here +(provide 'km-framewin) +;;; km-framewin.el ends here diff --git a/lisp/init-bog.el b/lisp/km-god.el index b0a845d..172dff0 100644 --- a/lisp/init-bog.el +++ b/lisp/km-god.el @@ -1,4 +1,4 @@ -;;; init-bog.el --- Bog mode configuration +;;; km-god.el --- God mode extensions ;; Copyright (C) 2012-2016 Kyle Meyer <kyle@kyleam.com> @@ -20,18 +20,17 @@ ;;; Code: -(add-to-list 'load-path "~/src/emacs/bog/") -(require 'bog-autoloads) +(require 'god-mode) -(setq bog-subdirectory-group 2 - bog-combined-bib-ignore-not-found t - bog-use-citekey-cache t) +(defun km/god-update-cursor () + (setq cursor-type (if god-local-mode 'bar 'box))) -(setq bog-keymap-prefix (kbd "C-c b")) +(defun km/god-gnus-p () + "Return non-nil if a Gnus-related mode is enabled." + (derived-mode-p 'gnus-group-mode + 'gnus-summary-mode + 'gnus-article-mode + 'message-mode)) -(add-hook 'org-mode-hook 'bog-mode) - -(global-set-key bog-keymap-prefix bog-command-map) - -(provide 'init-bog) -;;; init-bog.el ends here +(provide 'km-god) +;;; km-god.el ends here diff --git a/lisp/init-view.el b/lisp/km-helm.el index 7128a6b..9be507a 100644 --- a/lisp/init-view.el +++ b/lisp/km-helm.el @@ -1,4 +1,4 @@ -;;; init-view.el --- View mode configuration +;;; km-helm.el --- Helm configuration ;; Copyright (C) 2012-2016 Kyle Meyer <kyle@kyleam.com> @@ -20,14 +20,29 @@ ;;; Code: -(after 'view - (define-key view-mode-map "l" 'recenter-top-bottom) - (define-key view-mode-map "f" 'forward-word) - (define-key view-mode-map "b" 'backward-word) - (define-key view-mode-map "]" 'forward-paragraph) - (define-key view-mode-map "[" 'backward-paragraph) - (define-key view-mode-map "j" 'avy-goto-subword-1)) - -(key-chord-define-global "hq" 'view-mode) - -(provide 'init-view) +(require 'helm) + +;;;###autoload +(defun km/helm-display-buffer () + (interactive) + (with-helm-alive-p + (helm-exit-and-execute-action #'display-buffer))) + +;;;###autoload +(defun km/helm-display-file () + (interactive) + (with-helm-alive-p + (helm-exit-and-execute-action + (lambda (f) + (display-buffer (find-file-noselect f)))))) + +(autoload 'org-open-file "org") +;;;###autoload +(defun km/helm-ff-org-open-file () + "Run `org-open-file' from `helm-source-find-files'." + (interactive) + (with-helm-alive-p + (helm-exit-and-execute-action #'org-open-file))) + +(provide 'km-helm) +;;; km-helm.el ends here diff --git a/lisp/km-hydra.el b/lisp/km-hydra.el new file mode 100644 index 0000000..94e47cc --- /dev/null +++ b/lisp/km-hydra.el @@ -0,0 +1,203 @@ +;;; km-hydra.el --- Hydra definitions + +;; Copyright (C) 2012-2016 Kyle Meyer <kyle@kyleam.com> + +;; Author: Kyle Meyer <kyle@kyleam.com> +;; URL: https://github.com/kyleam/emacs.d + +;; 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 <http://www.gnu.org/licenses/>. + +;;; Code: + +(require 'hydra) + +(defhydra hydra-org-link-edit () + "Org Link Edit" + ("j" org-link-edit-forward-slurp "forward slurp") + ("k" org-link-edit-forward-barf "forward barf") + ("u" org-link-edit-backward-slurp "backward slurp") + ("i" org-link-edit-backward-barf "backward barf") + ("l" km/org-link-edit-slurp-link "slurp link" :color blue) + ("q" nil "cancel")) + +(defhydra hydra-smerge (:hint nil) + " +_b_ keep base _d_ diff _n_ next +_m_ keep mine _e_ ediff _p_ previous +_o_ keep other _h_ refine +_a_ keep all +\n" + ("b" smerge-keep-base) + ("m" smerge-keep-mine) + ("o" smerge-keep-other) + ("a" smerge-keep-all) + ("n" smerge-next) + ("p" smerge-prev) + ("h" smerge-refine) + ("e" smerge-ediff :color blue) + ("d" (call-interactively + (pcase (read-char-choice + "< base-mine, > base-other, = mine-other" + (list ?< ?> ?=)) + (?< #'smerge-diff-base-mine) + (?> #'smerge-diff-base-other) + (?= #'smerge-diff-mine-other)))) + ("l" recenter-top-bottom "recenter") + ("u" undo "undo") + ("q" nil "quit")) + +(defhydra hydra-file-search-map (:hint nil :color blue) + " +^^Grep ^^Dired +^^------------ ^^------------------ +_f_: grep-find _d_: find-grep-dired +_g_: lgrep _D_: find-dired +_G_: grep _n_: find-name-dired +_r_: rgrep +_v_: vc-git-grep +_z_: zgrep +\n" + ("f" grep-find) + ("g" lgrep) + ("G" grep) + ("r" rgrep) + ("v" vc-git-grep) + ("z" zrgrep) + + ("d" find-grep-dired) + ("D" find-dired) + ("n" find-name-dired) + + ("q" nil "quit")) + +;; Modified from https://github.com/abo-abo/hydra/wiki/Emacs +(defhydra hydra-outline-mode (:hint nil) + " + ^^Hide ^^Show ^^Move +_q_ sublevels _a_ all _u_ up +_t_ body _e_ entry _n_ next visible +_o_ other _i_ children _p_ previous visible +_c_ entry _k_ branches _f_ forward same level +_h_ leaves _s_ subtree _b_ backward same level +_d_ subtree + +" + ("q" hide-sublevels) + ("t" hide-body) + ("o" hide-other) + ("c" hide-entry) + ("h" hide-leaves) + ("d" hide-subtree) + + ("a" show-all) + ("e" show-entry) + ("i" show-children) + ("k" show-branches) + ("s" show-subtree) + + ("u" outline-up-heading) + ("n" outline-next-visible-heading) + ("p" outline-previous-visible-heading) + ("f" outline-forward-same-level) + ("b" outline-backward-same-level) + + ("l" km/outline-jump-to-heading "jump" :color blue) + ("m" outline-mark-subtree "mark" :color blue)) + +(defun km/hydra-outline-mode () + (interactive) + (unless outline-minor-mode + (outline-minor-mode)) + (hydra-outline-mode/body)) + +(defhydra hydra-window-map (:hint nil) + " +_l_: Switch split _r_: Winner redo _o_: Scroll other +_s_: Swap _u_: Winner undo _i_: Scroll other down +\n" + ("l" km/switch-window-split) + ("s" km/swap-windows) + + ("r" winner-redo) + ("u" winner-undo) + + ("o" scroll-other-window) + ("i" scroll-other-window-down) + + ("f" make-frame "new frame" :color blue) + ("q" nil "quit")) + +;; Multiple cursors hydra is modified from +;; https://github.com/abo-abo/hydra/wiki/multiple-cursors +(defhydra hydra-multiple-cursors (:hint nil) + " + ^^Up ^^Down +_p_ Next _n_ Next +_P_ Skip _N_ Skip +_y_ Unmark _u_ Unmark + +" + ("l" mc/edit-lines "edit lines" :exit t) + ("a" mc/mark-all-like-this "mark all" :exit t) + ("n" mc/mark-next-like-this) + ("N" mc/skip-to-next-like-this) + ("u" mc/unmark-next-like-this) + ("p" mc/mark-previous-like-this) + ("P" mc/skip-to-previous-like-this) + ("y" mc/unmark-previous-like-this)) + +(defhydra hydra-kmacro (:hint nil :exit t) + " + ^^Defining ^^Applying +_?_ Query _c_ Call +_b_ Bind to key _o_ Call 2nd in ring +_e_ Edit _r_ Apply to region lines +_E_ Step edit +_N_ Name last +_l_ Use recent strokes +_s_ Start defining +_x_ To register + + ^^Ring ^^Counter +_D_ Delete ring head _+_ Add counter +_n_ Cycle next _=_ Set counter +_p_ Cycle previous _f_ Set format +_t_ Swap _i_ Insert counter +_v_ View + +" + ("+" kmacro-add-counter) + ("=" kmacro-set-counter) + ("D" kmacro-delete-ring-head) + ("f" kmacro-set-format) + ("i" kmacro-insert-counter) + ("c" kmacro-end-and-call-macro :exit nil) + ("o" kmacro-call-ring-2nd-repeat) + ("e" kmacro-edit-macro) + ("E" kmacro-step-edit-macro) + ("n" kmacro-cycle-ring-next :exit nil) + ("p" kmacro-cycle-ring-previous :exit nil) + ("t" kmacro-swap-ring) + ("v" kmacro-view-macro-repeat) + ("b" kmacro-bind-to-key) + ("l" kmacro-edit-lossage) + ("N" kmacro-name-last-macro) + ("?" kbd-macro-query) + ("r" apply-macro-to-region-lines) + ("s" kmacro-start-macro) + ("x" kmacro-to-register) + ("q" nil "quit" :hint t)) + +(provide 'km-hydra) +;;; km-hydra.el ends here diff --git a/lisp/init-git.el b/lisp/km-magit.el index ef954eb..616f975 100644 --- a/lisp/init-git.el +++ b/lisp/km-magit.el @@ -1,4 +1,4 @@ -;;; init-git.el --- (Ma)git configuration +;;; km-magit.el --- Magit extensions ;; Copyright (C) 2012-2016 Kyle Meyer <kyle@kyleam.com> @@ -20,54 +20,10 @@ ;;; Code: -(require 'git-annex) - -(setq vc-follow-symlinks t) - -(setq git-annex-commit nil) - -(define-prefix-command 'km/git-map) -(global-set-key (kbd "C-c g") 'km/git-map) - - -;;; Magit - -(add-to-list 'load-path "~/src/emacs/magit/lisp/") +(require 'avy) +(require 'git-rebase) (require 'magit) - -(add-to-list 'load-path "~/src/emacs/orgit/") -(require 'orgit) - -(setq magit-revert-buffers 'silent - magit-revert-buffers-only-for-tracked-files nil - magit-push-always-verify nil - magit-delete-by-moving-to-trash nil - magit-diff-auto-show-delay 0.1 - magit-revision-show-gravatars nil - magit-log-section-arguments nil - magit-log-show-margin nil) - -(setq magit-uniquify-buffer-names nil - magit-buffer-name-format "*%M%v: %t*") - -(setq git-commit-finish-query-functions nil) - -(setq magit-no-confirm '(stage-all-changes unstage-all-changes reverse)) - -(setq git-commit-finish-query-functions nil) - -(remove-hook 'magit-refs-sections-hook 'magit-insert-tags) - -(add-hook 'git-commit-setup-hook - (lambda () - (add-hook 'with-editor-pre-finish-hook - 'git-commit-save-message nil t))) -(add-hook 'git-commit-setup-hook 'git-commit-turn-on-flyspell) - -(add-hook 'magit-post-display-buffer-hook - (lambda () - (when (eq major-mode 'magit-status-mode) - (delete-other-windows)))) +(require 'projectile) (defun km/magit-auto-commit () "Commit all changes with \"auto\" commit message. @@ -77,6 +33,7 @@ a proper commit." (interactive) (magit-run-git "commit" "--all" "--message=auto")) +;;;###autoload (defun km/magit-show-commit-at-point (&optional choose-project) "Show commit point. If there is no current project or if the prefix argument @@ -95,6 +52,7 @@ CHOOSE-PROJECT is non-nil, prompt for the project name." (magit-show-commit hash (car (magit-diff-arguments)))) (user-error "No hash found at point"))) +;;;###autoload (defun km/magit-commit-extend-with-file () "Extend last commit with changes in the current file." (interactive) @@ -109,6 +67,7 @@ CHOOSE-PROJECT is non-nil, prompt for the project name." (t (message "No changes to %s" file))))) +;;;###autoload (defun km/magit-commit-wip-with-file () "Make a WIP commit for the current file. Unlike `magit-wip-*' commands, this commit is made to the current @@ -316,6 +275,7 @@ and 'squash!' titles." (goto-char (apply #'max commit-pts)) (message "No matching commits found")))) +;;;###autoload (defun km/magit-reset-file (rev file &optional checkout) "Reset FILE from revision REV. @@ -331,6 +291,7 @@ instead. (magit-run-git (if checkout "checkout" "reset") rev "--" file))) +;;;###autoload (defun km/magit-pin-file (&optional other-rev) "Pin this file to the current revision. @@ -362,6 +323,7 @@ the file has changed." (forward-line (1- line)) (move-to-column col)))) +;;;###autoload (defun km/magit-revfile-reset (&optional checkout) "Reset to revision from current revfile. If CHECKOUT is non-nil, checkout file instead." @@ -372,6 +334,7 @@ If CHECKOUT is non-nil, checkout file instead." (magit-run-git (if checkout "checkout" "reset") magit-buffer-refname "--" magit-buffer-file-name))) +;;;###autoload (defun km/magit-find-recently-changed-file (n) "Find a file that changed from \"HEAD~N..HEAD\". N defaults to 20." @@ -423,6 +386,7 @@ command will still offer the staged files)." (defun km/magit-shorten-hash (hash &optional n) (magit-rev-parse (format "--short=%s" (or n (magit-abbrev-length))) hash)) +;;;###autoload (defun km/magit-shorten-hash-at-point (&optional n) "Shorten hash at point to N characters. @@ -469,6 +433,7 @@ These will be given one argument (the current prefix value) and should succeed by copying and returning non-nil or fail by returning nil.") +;;;###autoload (defun km/magit-copy-commit-summary (commit) "Copy a citation for the COMMIT at point. Format the reference as '<hash>, (<subject>, <date>)'. If there @@ -535,14 +500,6 @@ function." 'km/magit-copy-hook current-prefix-arg)) (magit-copy-section-value))) -(defun km/magit-avy-goto-subword-1 () - "Like `km/avy-goto-subword-1', but maybe show commit and limit to window." - (interactive) - (let (avy-all-windows) - (call-interactively #'avy-goto-subword-1)) - (when (derived-mode-p 'magit-log-mode) - (magit-diff-show-or-scroll-up))) - (defun km/magit-rev-ancestor-p (rev-a rev-b) "Report whether REV-A is the ancestor of REV-B. Use the revision at point as REV-B. With prefix argument or if @@ -618,200 +575,5 @@ argument. Interactively, this can be accessed using the command (interactive "P") (km/magit-diff-visit-file prev-rev t)) -(define-key ctl-x-4-map "g" 'magit-find-file-other-window) -(define-key km/file-map "g" 'magit-find-file) - -(key-chord-define-global "jg" 'magit-status) - -;; Remove `magit-add-change-log-entry-other-window', which overrides -;; my binding for `km/zsh-ansi-term-other-window'. -(define-key magit-mode-map (kbd "C-x 4 a") nil) -(define-key magit-mode-map "o" 'magit-push-popup) -(define-key magit-mode-map "P" 'magit-submodule-popup) -(define-key magit-mode-map "Q" 'km/magit-mode-bury-all-windows) -(define-key magit-mode-map (kbd "C-w") 'km/magit-copy-as-kill) - -;; `magit-diff-visit-file-worktree' is also on C-RET. -(define-key magit-file-section-map (kbd "C-j") 'magit-diff-visit-file-worktree) -(define-key magit-hunk-section-map (kbd "C-j") 'magit-diff-visit-file-worktree) -(define-key magit-file-section-map (kbd "C-o") 'km/magit-diff-visit-file-other-window) -(define-key magit-hunk-section-map (kbd "C-o") 'km/magit-diff-visit-file-other-window) - -(define-key magit-log-mode-map "j" 'km/magit-avy-goto-subword-1) -(define-key magit-refs-mode-map "j" 'km/magit-avy-goto-subword-1) -(define-key magit-cherry-mode-map "j" 'km/magit-avy-goto-subword-1) - -(define-key magit-refs-mode-map (kbd "C-c C-t") 'km/magit-refs-toggle-tags) - -(define-key magit-file-section-map [remap magit-visit-thing] - 'km/magit-diff-visit-file) -(define-key magit-hunk-section-map [remap magit-visit-thing] - 'km/magit-diff-visit-file) - -(define-key magit-refs-mode-map (kbd "C-c C-f") 'km/magit-refs-filter-recent) - -(define-key magit-process-mode-map (kbd "C-c C-k") 'magit-process-kill) - -(define-prefix-command 'km/magit-map) -(define-key magit-mode-map "." 'km/magit-map) -(define-key km/magit-map "c" 'km/magit-find-commit-file) -(define-key km/magit-map "g" 'km/git-map) -(define-key km/magit-map "l" 'magit-toggle-buffer-lock) -(define-key km/magit-map "f" 'km/magit-flip-revs) - -(define-prefix-command 'km/magit-wip-map) -(define-key km/git-map "w" 'km/magit-wip-map) -(define-key km/magit-wip-map "a" 'magit-wip-after-apply-mode) -(define-key km/magit-wip-map "b" 'magit-wip-before-change-mode) -(define-key km/magit-wip-map "c" 'magit-wip-commit) -(define-key km/magit-wip-map "f" 'magit-wip-commit-buffer-file) -(define-key km/magit-wip-map "l" 'magit-wip-log-current) -(define-key km/magit-wip-map "o" 'magit-wip-log) -(define-key km/magit-wip-map "s" 'magit-wip-after-save-mode) -(define-key km/magit-wip-map "S" 'magit-wip-after-save-local-mode) -(define-key km/magit-wip-map "w" 'km/magit-commit-wip-with-file) - -(define-key km/git-map "." 'km/magit-show-commit-at-point) -(define-key km/git-map "c" 'km/magit-copy-commit-summary) -(define-key km/git-map "d" 'magit-dispatch-popup) -(define-key km/git-map "e" 'km/magit-commit-extend-with-file) -(define-key km/git-map "f" 'km/magit-reset-file) -(define-key km/git-map "i" 'km/magit-insert-staged-file) -(define-key km/git-map "n" 'km/magit-shorten-hash-at-point) -(define-key km/git-map "l" 'magit-log-buffer-file) -(define-key km/git-map "p" 'km/magit-pin-file) -(define-key km/git-map "r" 'km/magit-find-recently-changed-file) -(define-key km/git-map "s" 'magit-stage-file) -(define-key km/git-map "u" 'km/magit-auto-commit) -(define-key km/git-map "v" 'km/magit-revfile-reset) - -(define-key magit-log-select-mode-map "." - 'km/magit-log-select-guess-fixup-commit) - - -;;; Magit popups - -(setq magit-popup-show-help-echo nil - magit-popup-show-common-commands nil - magit-popup-use-prefix-argument 'default) - -(setq magit-branch-arguments - (delete "--track" magit-branch-arguments)) - -(define-key magit-popup-mode-map (kbd "SPC <t>") 'magit-invoke-popup-switch) -(define-key magit-popup-mode-map (kbd "SPC SPC <t>") 'magit-invoke-popup-option) - -(setq magit-patch-popup - (plist-put magit-patch-popup :use-prefix 'popup)) - -(magit-define-popup-action 'magit-commit-popup - ?u "Auto commit" 'km/magit-auto-commit) - -(magit-define-popup-action 'magit-push-popup - ?a "Push all" 'km/magit-push-all) -(magit-define-popup-action 'magit-push-popup - ?h "Push HEAD" 'km/magit-push-head) - -(magit-define-popup-action 'magit-merge-popup - ?u "Merge upstream" 'km/magit-ff-merge-upstream) - -(magit-define-popup-action 'magit-diff-popup - ?e "Edit options" 'magit-diff-refresh-popup) - -(magit-change-popup-key 'magit-stash-popup :action - ?Z ?s) - -(magit-define-popup-switch 'magit-log-popup - ?p "First parent" "--first-parent") -(magit-define-popup-switch 'magit-log-popup - ?n "No merges" "--no-merges") -(magit-define-popup-switch 'magit-log-popup - ?t "Date order" "--date-order") - -(magit-define-popup-action 'magit-log-popup - ?e "Edit options" 'magit-log-refresh-popup) -(magit-define-popup-action 'magit-log-popup - ?w "Log current WIP" 'magit-wip-log-current) -(magit-define-popup-action 'magit-log-popup - ?W "Log other WIP" 'magit-wip-log) - -(magit-change-popup-key 'magit-branch-popup :action - ?c ?o) -(magit-change-popup-key 'magit-branch-popup :action - ?n ?C) -(magit-change-popup-key 'magit-branch-popup :action - ?m ?R) -(magit-change-popup-key 'magit-branch-popup :action - ?s ?v) - -(magit-define-popup-action 'magit-branch-popup - ?c "Create & checkout from current" - 'km/magit-branch-and-checkout-from-current) - -(magit-define-popup-action 'magit-branch-popup - ?K "Delete previous branch" 'km/magit-delete-previous-branch) -(magit-define-popup-action 'magit-branch-popup - ?m "Checkout master" 'km/magit-checkout-master) -(magit-define-popup-action 'magit-branch-popup - ?n "Checkout recent ref" 'km/magit-checkout-recent-ref) -(magit-define-popup-action 'magit-branch-popup - ?N "Track recent ref" 'km/magit-checkout-track-recent-ref) -(magit-define-popup-action 'magit-branch-popup - ?l "Checkout previous" 'km/magit-checkout-previous-branch) -(magit-define-popup-action 'magit-branch-popup - ?r "Rename branch" 'km/magit-branch-rename) -(magit-define-popup-action 'magit-branch-popup - ?s "Backup current branch" 'km/magit-backup-branch) -(magit-define-popup-action 'magit-branch-popup - ?t "Local tracking" 'km/magit-checkout-local-tracking) - -(defadvice magit-merge-editmsg (around km/magit-merge-editmsg-no-ff activate) - "Set '--no-ff' flag when running `magit-merge-editmsg'." - (let ((args '("--no-ff"))) - ad-do-it)) - - -;;; Magit Annex - -(add-to-list 'load-path "~/src/emacs/magit-annex/") -(require 'magit-annex) - -(setq magit-annex-unused-open-function #'org-open-file) - -(setq magit-annex-all-action-arguments - (delete "--auto" magit-annex-all-action-arguments)) - - -;;; Other git - -(setq smerge-diff-switches '("-d" "-b" "-u")) - -(define-key km/git-map "m" - (defhydra hydra-smerge (:hint nil) - " -_b_ keep base _d_ diff _n_ next -_m_ keep mine _e_ ediff _p_ previous -_o_ keep other _h_ refine -_a_ keep all -\n" - ("b" smerge-keep-base) - ("m" smerge-keep-mine) - ("o" smerge-keep-other) - ("a" smerge-keep-all) - ("n" smerge-next) - ("p" smerge-prev) - ("h" smerge-refine) - ("e" smerge-ediff :color blue) - ("d" (call-interactively - (pcase (read-char-choice - "< base-mine, > base-other, = mine-other" - (list ?< ?> ?=)) - (?< #'smerge-diff-base-mine) - (?> #'smerge-diff-base-other) - (?= #'smerge-diff-mine-other)))) - ("l" recenter-top-bottom "recenter") - ("u" undo "undo") - ("q" nil "quit"))) - -(provide 'init-git) -;;; init-git.el ends here +(provide 'km-magit) +;;; km-magit.el ends here diff --git a/lisp/km-mail.el b/lisp/km-mail.el new file mode 100644 index 0000000..9a3a3ab --- /dev/null +++ b/lisp/km-mail.el @@ -0,0 +1,150 @@ +;;; km-mail.el --- Mail-related extensions + +;; Copyright (C) 2012-2016 Kyle Meyer <kyle@kyleam.com> + +;; Author: Kyle Meyer <kyle@kyleam.com> +;; URL: https://github.com/kyleam/emacs.d + +;; 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 <http://www.gnu.org/licenses/>. + +;;; Code: + +(require 'dash) +(require 'gnus) +(require 'gnus-group) +(require 'gnus-topic) +(require 'gnus-sum) +(require 'notmuch) +(require 'shr) + +;; http://www.emacswiki.org/emacs/GnusSync +(defun km/gnus-grace-exit-before-kill-emacs () + (if (and (fboundp 'gnus-alive-p) + (gnus-alive-p)) + (let ((noninteractive t)) + (gnus-group-exit)))) + + +(defun km/gnus-group-sort-by-topic (info1 info2) + "Sort alphabetically by group topic. +This allows groups to be ordered by topics even when topic mode +is off." + (require 'gnus-topic) + (string< (gnus-group-topic (gnus-info-group info1)) + (gnus-group-topic (gnus-info-group info2)))) + +(defun km/gnus-summary-set-current-article () + (unless gnus-summary-buffer + (user-error "No summary buffer")) + (with-current-buffer gnus-summary-buffer + (save-window-excursion (gnus-summary-select-article)))) + +(defun km/gnus--last-message-link () + (with-current-buffer gnus-article-buffer + (save-excursion + (goto-char (point-max)) + (widget-forward -1) + (--when-let (or (get-text-property (point) 'gnus-string) + (get-text-property (point) 'shr-url)) + (kill-new it))))) + +(defun km/gnus--gmane-link (&optional perma) + (with-current-buffer gnus-original-article-buffer + (-when-let* ((blink (message-field-value "Archived-At")) + (link (or (and (string-match "\\`<\\(.*\\)>\\'" blink) + (match-string 1 blink)) + blink))) + (if perma + link + (replace-regexp-in-string "\\`http://permalink\.gmane\.org/" + "http://thread.gmane.org/" + link))))) + +(defun km/gnus-copy-gmane-link-as-kill (&optional perma) + (interactive "P") + (km/gnus-summary-set-current-article) + (with-current-buffer gnus-original-article-buffer + (--when-let (km/gnus--gmane-link perma) + (kill-new (message it))))) + +(defun km/gnus-copy-message-link (follow) + "Copy link for current message. +If it has an \"Archived-At\" header, use that. Otherwise, get +the link from the last widget in the buffer. With prefix +argument FOLLOW, follow link instead of copying it." + (interactive "P") + (km/gnus-summary-set-current-article) + (with-current-buffer gnus-original-article-buffer + (save-excursion + (--when-let (or (km/gnus--gmane-link) + (km/gnus--last-message-link)) + (funcall (if follow + #'browse-url + (lambda (s) (kill-new (message s)))) + it))))) + +(defun km/gnus-open-github-patch () + "Open patch from github email. +A new buffer with the patch contents is opened in another window." + (interactive) + (km/gnus-summary-set-current-article) + (let ((bufname (generate-new-buffer-name "*gnus-github-patch*")) + url) + (with-current-buffer gnus-original-article-buffer + (save-excursion + (goto-char (point-min)) + (if (re-search-forward "https://github.com/.*\\.patch") + (setq url (match-string-no-properties 0)) + (user-error "No patch found")))) + (with-current-buffer (get-buffer-create bufname) + (url-insert-file-contents url) + (diff-mode) + (view-mode 1)) + (pop-to-buffer bufname))) + +(defun km/gnus-summary-catchup (&optional no-next) + "Mark all articles as read. +Don't ask for confirmation. With prefix argument NO-NEXT, exit +to group buffer instead of moving to next group." + (interactive "P") + (let ((gnus-auto-select-next (unless no-next 'quietly))) + (gnus-summary-catchup-and-exit nil t))) + +(defun km/shr-browse-url-and-goto-next () + "Run `shr-browse-url' followed by `shr-next-link'." + (interactive) + (shr-browse-url) + (shr-next-link)) + + +;;; Message mode + +(defun km/message-confirm-sender () + "Stop sending message from the wrong address." + (unless (yes-or-no-p (format "Send message from %s?" + (message-field-value "From"))) + (user-error "Not sending message"))) + + +;;; Notmuch + +(require 'notmuch) + +;;;###autoload +(defun km/notmuch-show-copy-message-id-as-kill () + (interactive) + (kill-new (message "%s" (notmuch-show-get-message-id)))) + +(provide 'km-mail) +;;; km-mail.el ends here diff --git a/lisp/init-org.el b/lisp/km-org.el index 147f6e9..fcf82ed 100644 --- a/lisp/init-org.el +++ b/lisp/km-org.el @@ -1,4 +1,4 @@ -;;; init-org.el --- Org mode configuration +;;; km-org.el --- Org mode extensions ;; Copyright (C) 2012-2016 Kyle Meyer <kyle@kyleam.com> @@ -20,57 +20,15 @@ ;;; Code: -(add-to-list 'load-path "~/src/emacs/org-mode/lisp/") -(add-to-list 'load-path "~/src/emacs/org-mode/contrib/lisp/" t) -(add-to-list 'Info-directory-list "~/src/emacs/org-mode/doc/") - -(setq org-modules '(org-bibtex org-gnus org-info ox-md)) - -(setq org-log-done t - org-log-into-drawer t - org-clock-into-drawer t - org-todo-keywords '((sequence "TODO(t)" "STARTED(s)" "WAITING(w@)" - "|" "DONE(d)" "NA(n@)"))) - -(setq org-catch-invisible-edits 'error - org-special-ctrl-k t - org-insert-heading-respect-content t - org-M-RET-may-split-line nil - org-adapt-indentation nil - org-blank-before-new-entry '((heading . t) (plain-list-item . auto))) - -(setq org-use-speed-commands t - org-use-extra-keys t - org-fast-tag-selection-single-key 'expert) - -(setq org-outline-path-complete-in-steps nil - org-goto-interface 'outline-path-completionp - org-goto-max-level 3) - -(put 'org-goto-max-level 'safe-local-variable #'integerp) - -(after 'org - (setq org-structure-template-alist - (append '(("p" "#+property: ") - ("o" "#+options: ") - ("d" "#+date: ") - ("t" "#+title: ") - ("S" "#+setupfile: ?") - ("n" "#+name: ") - ("w" "#+begin_note\n ?\n#+end_note") - ("C" "#+caption: ") - ("b" "#+label: ") - ("r" "#+attr_latex: ") - ("R" "#+attr_html: ")) - (mapcar (lambda (i) (list (car i) (downcase (cadr i)))) - org-structure-template-alist)))) - -(add-to-list 'auto-mode-alist '("\\.org.txt\\'" . org-mode)) - -(add-hook 'next-error-hook (lambda () - (when (eq major-mode 'org-mode) - (org-show-context)))) +(require 'cl-lib) +(require 'dash) +(require 'org) +(require 'org-agenda) +(require 'org-link-edit) +(require 'ox-ascii) +(require 's) +;;;###autoload (defun km/org-tree-to-indirect-buffer (&optional arg) "Run `org-tree-to-indirect-buffer', keeping previous buffer. By default, `org-tree-to-indirect-buffer' deletes the previous @@ -84,6 +42,7 @@ a different meaning, it is left untouched." (setq arg (not arg))) (org-tree-to-indirect-buffer arg)) +;;;###autoload (defun km/org-tree-to-indirect-buffer-current-window (&optional arg) "Create indirect buffer and narrow to subtree in this window. Before running `org-tree-to-indirect-buffer', set @@ -92,6 +51,7 @@ Before running `org-tree-to-indirect-buffer', set (let ((org-indirect-buffer-display 'current-window)) (km/org-tree-to-indirect-buffer arg))) +;;;###autoload (defun km/org-clone-and-shift-by-repeater () "Clone current subtree, shifting new timestamp by repeater. The repeater is removed from the original subtree." @@ -108,6 +68,7 @@ The repeater is removed from the original subtree." (user-error "Subtree does not have repeater")) (org-clone-subtree-with-time-shift 0 repeater)))) +;;;###autoload (defun km/org-delete-checked-items () "Delete checked items. @@ -179,6 +140,7 @@ as `org-sort-entries' does." (beginning-of-line) (goto-char (+ (point) chars-after-heading))))) +;;;###autoload (defun km/org-sort-parent (arg) "Sort on parent heading ARG levels up. After sorting, return point to its previous location under the @@ -248,11 +210,13 @@ For example (when sort-args (apply #'org-sort-entries sort-args)))) +;;;###autoload (defun km/org-maybe-sort-buffer-headings () "Call `km/org-maybe-sort' on buffer headings." (interactive) (org-map-entries #'km/org-maybe-sort)) +;;;###autoload (defun km/org-maybe-sort-parent () "Sort parent heading based on \"SORT\" property. See `km/org-maybe-sort' for details of property value format." @@ -277,6 +241,7 @@ See `km/org-maybe-sort' for details of property value format." (setq heading-words (cdr heading-words))) (mapconcat #'identity heading-words " "))) +;;;###autoload (defun km/org-remove-title-leader () "Remove leader from Org heading title. @@ -307,12 +272,15 @@ to (beginning-of-line) (open-line 1))))) +(autoload 'km/reduce-to-single-spaces "km-editing") +;;;###autoload (defun km/org-normalize-spaces () "Reduce to single spaces and add space before headings." (interactive) (km/reduce-to-single-spaces) (km/org-add-blank-before-heading)) +;;;###autoload (defun km/org-switch-to-buffer-other-window (&optional arg) (interactive "P") (cl-letf (((symbol-function 'org-pop-to-buffer-same-window) @@ -320,6 +288,7 @@ to (funcall #'pop-to-buffer buffer-or-name)))) (org-switchb arg))) +;;;###autoload (defun km/org-open-at-point-stay () "Like `org-open-at-point', but stay on heading. This variant is convient to use in `org-speed-commands-user' @@ -331,124 +300,18 @@ called through the speed command interface." (save-excursion (call-interactively #'org-open-at-point))) -(after 'org - (define-key org-mode-map (kbd "C-c C-x B") - 'km/org-tree-to-indirect-buffer-current-window) - (define-key org-mode-map [remap org-tree-to-indirect-buffer] - 'km/org-tree-to-indirect-buffer) - - ;; Rebind `org-insert-drawer' to so that `org-metadown' has the - ;; expected "C-c C-x" keybinding. - (define-key org-mode-map (kbd "C-c C-x d") 'org-metadown) - (define-key org-mode-map (kbd "C-c C-x w") 'org-insert-drawer) - - ;; Rebind `org-set-property' to free up binding for - ;; `org-previous-item'. - (define-key org-mode-map (kbd "C-c C-x s") 'org-set-property) - (define-key org-mode-map (kbd "C-c C-x n") 'org-next-item) - (define-key org-mode-map (kbd "C-c C-x p") 'org-previous-item) - - ;; Override global `imenu' binding. - (define-key org-mode-map (kbd "C-c l") 'org-goto) - ;; Don't let `org-cycle-agenda-files' binding override custom - ;; `backward-kill-word' binding (`org-cycle-agenda-files' is still bound - ;; to C-,). - (define-key org-mode-map (kbd "C-'") nil) - - (define-key org-mode-map (kbd "C-c m") 'km/org-prefix-map) - - (add-to-list 'org-speed-commands-user '("o" . km/org-open-at-point-stay))) - -(define-prefix-command 'km/org-prefix-map) -(define-key km/org-prefix-map "c" 'km/org-clone-and-shift-by-repeater) -(define-key km/org-prefix-map "D" 'km/org-delete-checked-items) -(define-key km/org-prefix-map "l" 'km/org-remove-title-leader) -(define-key km/org-prefix-map "n" 'km/org-normalize-spaces) -(define-key km/org-prefix-map "s" 'km/org-sort-parent) - - -(define-prefix-command 'km/global-org-map) -(global-set-key (kbd "C-c o") 'km/global-org-map) - -(define-key km/global-org-map "b" 'org-iswitchb) -(define-key km/global-org-map "o" 'org-open-at-point-global) -(define-key km/global-org-map "p" 'poporg-dwim) -(define-key km/global-org-map "s" 'org-save-all-org-buffers) - -(define-key ctl-x-4-map "o" 'km/org-switch-to-buffer-other-window) - -(after 'poporg - (define-key poporg-mode-map (kbd "C-c C-c") 'poporg-edit-exit)) - ;;; Agenda -(setq org-default-notes-file "~/notes/agenda/tasks.org") -(defvar km/org-agenda-file-directory "~/notes/agenda/") -(setq org-agenda-files (list km/org-agenda-file-directory)) -(setq org-agenda-text-search-extra-files - (file-expand-wildcards "~/notes/extra/*.org")) - -(setq org-agenda-restore-windows-after-quit t - org-agenda-window-setup 'only-window - org-agenda-sticky t) - -(setq org-agenda-dim-blocked-tasks nil - org-agenda-show-all-dates t - org-agenda-skip-deadline-if-done t - org-agenda-skip-scheduled-if-done t - org-agenda-start-on-weekday nil - org-agenda-use-time-grid nil) - -(setq org-agenda-sorting-strategy - '((agenda time-up deadline-up scheduled-up priority-down category-keep) - (todo priority-down category-keep) - (tags priority-down category-keep) - (search category-keep))) - -(setq org-agenda-custom-commands - '(("d" todo "DONE" nil) - ("u" "Unschedule TODO entries" alltodo "" - ((org-agenda-skip-function - (lambda nil - (org-agenda-skip-entry-if 'scheduled 'deadline - 'regexp "\n]+>"))) - (org-agenda-overriding-header "Unscheduled TODO entries: "))) - ("p" "Past timestamps" tags "TIMESTAMP<=\"<now>\""))) - -(setq org-capture-templates - '(("t" "task" entry (file+headline "~/notes/tasks.org" "Inbox") - "* TODO %?%i" :prepend t) - ("d" "date" entry (file+headline "~/notes/calendar.org" "Inbox") - "* %?%i" :prepend t) - ("b" "bookmark" entry (file+headline "~/notes/bookmarks.org" "Inbox") - "* %?%i" :prepend t) - ("v" "Visit" checkitem (file+headline "~/notes/tasks.org" "Visit") - "- [ ] %?%i\n" :prepend t) - ("r" "Revisit" checkitem (file+headline "~/notes/tasks.org" "Revisit") - "- [ ] %?%i\n" :prepend t) - ;; Link counterparts - ("T" "task link" entry (file+headline "~/notes/tasks.org" "Inbox") - "* TODO %?%i\n\n%a" :prepend t) - ("D" "date link" entry (file+headline "~/notes/calendar.org" "Inbox") - "* %?%i\n\n%a" :prepend t) - ("B" "bookmark link" entry - (file+headline "~/notes/bookmarks.org" "Inbox") - "* %?%i\n\n%a" :prepend t) - ;; Clipboard - ("x" "task clipboard" entry (file+headline "~/notes/tasks.org" "Inbox") - "* TODO %?%i\n\n%x" :prepend t) - ("X" "bookmark clipboard" entry - (file+headline "~/notes/bookmarks.org" "Inbox") - "* %?%i\n\n%x" :prepend t))) - -(add-hook 'org-agenda-mode-hook 'km/org-agenda-cd-and-read-dir-locals) -(add-hook 'org-agenda-finalize-hook 'km/org-agenda-store-current-span) +(defvar km/org-agenda-file-directory nil) + +;;;###autoload (defun km/org-agenda-cd-and-read-dir-locals () (setq default-directory "~/notes/") (hack-local-variables)) +;;;###autoload (defun km/org-agenda-store-current-span () "Store the current span value in `org-agenda-span'. This allows the view to persist when the agenda buffer is @@ -456,6 +319,7 @@ killed." (when org-agenda-current-span (setq org-agenda-span org-agenda-current-span))) +;;;###autoload (defun km/org-agenda-add-or-remove-file (file) "Add or remove link to FILE in `km/org-agenda-file-directory'. If a link for FILE does not exist, create it. Otherwise, remove @@ -477,6 +341,7 @@ displayed in the agenda." (when (called-interactively-p) (message "Adding %s" agenda-file)) (make-symbolic-link file agenda-file)))) +;;;###autoload (defun km/org-open-default-notes-file-inbox () "Open \"Inbox\" heading of `org-default-notes-file'." (interactive) @@ -485,6 +350,7 @@ displayed in the agenda." (recenter-top-bottom 0) (show-children)) +;;;###autoload (defun km/org-goto-agenda-heading () "Jump to heading in agenda files." (interactive) @@ -493,46 +359,14 @@ displayed in the agenda." (org-agenda-text-search-extra-files :maxlevel . 3)))) (org-refile '(4)))) -(defun km/org-agenda-avy-goto-subword-1 () - (interactive) - (let (avy-all-windows) - (call-interactively #'avy-goto-subword-1)) - (org-agenda-do-context-action)) - -(define-key km/global-org-map "a" 'org-agenda) -(define-key km/global-org-map "c" 'org-capture) -(define-key km/global-org-map "j" 'km/org-goto-agenda-heading) -(define-key km/global-org-map "m" 'km/org-open-default-notes-file-inbox) -(define-key km/global-org-map "n" 'km/org-agenda-add-or-remove-file) - -(after 'org-agenda - ;; Bind `org-agenda-follow-mode' to same key as - ;; `next-error-follow-minor-mode'. - (define-key org-agenda-mode-map (kbd "C-c C-f") 'org-agenda-follow-mode) - ;; Free up 'j' for `km/org-agenda-avy-goto-subword-1'. - (define-key org-agenda-mode-map (kbd "C-j") 'org-agenda-goto-date) - (define-key org-agenda-mode-map "j" 'km/org-agenda-avy-goto-subword-1)) - ;;; Refiling -(setq org-reverse-note-order t) - -(setq org-refile-target-verify-function 'km/org-refile-verify-target) - -(setq org-refile-targets '((nil :maxlevel . 2)) - org-refile-cache nil) - -(add-hook 'org-after-refile-insert-hook 'km/org-maybe-sort-parent) - (defvar km/org-agenda-refile-targets '((nil :maxlevel . 3) (org-agenda-files :maxlevel . 2) (org-agenda-text-search-extra-files :maxlevel . 2))) -(add-to-list 'safe-local-variable-values - (cons 'org-refile-targets km/org-agenda-refile-targets)) - (defun km/org-refile-verify-target () "Exclude DONE state from refile targets." (not (member (nth 2 (org-heading-components)) org-done-keywords))) @@ -646,28 +480,13 @@ global value. A numeric prefix sets MAXLEVEL (defaults to 2)." (set (make-local-variable 'org-refile-targets) `((,buffer-file :maxlevel . ,maxlevel)))))) -(define-key km/global-org-map "w" 'org-refile-goto-last-stored) -(define-key km/org-prefix-map "w" 'km/org-refile-to-other-org-buffer) -(define-key km/org-prefix-map "i" 'km/org-refile-list-item) - -(after 'org - (define-key org-mode-map [remap org-refile] 'km/org-refile-dwim) - (add-to-list 'org-speed-commands-user '("w" . km/org-refile-dwim))) - ;;; Links -(add-to-list 'load-path "~/src/emacs/org-link-edit/") -(require 'org-link-edit) - -(setq org-link-search-must-match-exact-headline nil) - -(after 'org - (org-add-link-type "pmid" 'km/org-pmid-open)) - (defvar km/org-pmid-search-url "http://www.ncbi.nlm.nih.gov/pubmed/?term=%s" "URL to search for PMID.") +;;;###autoload (defun km/org-pmid-open (path) "Search for PMID at `km/org-pmid-search-url'." (browse-url (format km/org-pmid-search-url path))) @@ -699,88 +518,30 @@ beginning of the link." (goto-char beg) slurped)))) -(define-key km/org-prefix-map "d" 'km/org-link-dired-jump) -(define-key km/global-org-map "l" 'org-store-link) - -(define-key km/org-prefix-map "." - (defhydra hydra-org-link-edit () - "Org Link Edit" - ("j" org-link-edit-forward-slurp "forward slurp") - ("k" org-link-edit-forward-barf "forward barf") - ("u" org-link-edit-backward-slurp "backward slurp") - ("i" org-link-edit-backward-barf "backward barf") - ("l" km/org-link-edit-slurp-link "slurp link" :color blue) - ("q" nil "cancel"))) - ;;; Export -(after 'org - (add-to-list 'org-latex-packages-alist '("" "amsmath" t))) - -(after 'ox-latex - (add-to-list 'org-latex-classes - '("short" - "\\documentclass{short}" - ("\\section{%s}" . "\\section*{%s}") - ("\\subsection{%s}" . "\\subsection*{%s}") - ("\\subsubsection{%s}" . "\\subsubsection*{%s}") - ("\\paragraph{%s}" . "\\paragraph*{%s}") - ("\\subparagraph{%s}" . "\\subparagraph*{%s}")))) - (defvar km/org-md-fill-column fill-column "Fill column for exported markdown. This is a separate variable instead of `fill-column' to allow it to be easily overriden.") -(defun km/org-md--fill-string (contents) + +;;;###autoload +(defun km/org-md-fill-string (contents) "Use `org-ascii--fill-string' to fill ox-md paragraphs." (org-ascii--fill-string contents km/org-md-fill-column nil)) -(after 'ox-md - (advice-add 'org-md-paragraph :filter-return #'km/org-md--fill-string)) - (defun km/org-md-export-unfilled-buffer () (interactive) (let ((km/org-md-fill-column (point-max))) (org-md-export-as-markdown))) -;;; Org Babel - -(setq org-confirm-babel-evaluate nil - org-src-fontify-natively t) - -(org-babel-do-load-languages - 'org-babel-load-languages - '((shell . t) - (python . t) - (R . t) - (emacs-lisp . t) - (latex . t))) - - -;;; Org Contacts - -(require 'org-contacts) - -(setq org-contacts-files '("~/notes/contacts.org")) - -(add-to-list 'org-capture-templates - '("a" "email address" entry (file+headline "~/notes/contacts.org" "Inbox") - " -** %(org-contacts-template-name) -:PROPERTIES: -:EMAIL: %(org-contacts-template-email) -:END:")) - - ;;; Org open file -(defadvice org-open-file (after km/org-open-add-to-recentf activate) - (recentf-add-file path)) - +;;;###autoload (defun km/org-open-file-at-point () "Open file at point with `org-open-file'." (interactive) @@ -795,12 +556,15 @@ to be easily overriden.") (org-open-file file) (km/org-open-file))))) +;;;###autoload (defun km/org-open-file () "Interactive version of `org-open-file'." (interactive) (org-open-file (read-file-name "Open file: " nil nil t))) (autoload 'magit-annex-present-files "magit-annex") +(autoload 'magit-completing-read "magit-utils") +;;;###autoload (defun km/org-open-annex-file () "Open a git annex file with `org-open-file'." (interactive) @@ -808,16 +572,12 @@ to be easily overriden.") (org-open-file (magit-completing-read "Open annex file" it nil t)) (message "No annex files found"))) +(autoload 'km/read-recent-file "km-files") +;;;###autoload (defun km/org-open-recent-file () "Open a file from `recentf-list' with `org-open-file'." (interactive) (org-open-file (km/read-recent-file))) -(after 'init-files - (define-key km/file-map "a" 'km/org-open-annex-file) - (define-key km/file-map "o" 'km/org-open-file) - (define-key km/file-map "p" 'km/org-open-file-at-point) - (define-key km/file-map "r" 'km/org-open-recent-file)) - -(provide 'init-org) -;;; init-org.el ends here +(provide 'km-org) +;;; km-org.el ends here diff --git a/lisp/init-outline.el b/lisp/km-outline.el index 1d21531..45560fd 100644 --- a/lisp/init-outline.el +++ b/lisp/km-outline.el @@ -1,4 +1,4 @@ -;;; init-outline.el --- Outline mode configuration +;;; init-outline.el --- Outline mode extensions ;; Copyright (C) 2012-2016 Kyle Meyer <kyle@kyleam.com> @@ -20,6 +20,8 @@ ;;; Code: +(require 'outline) + (defun km/outline--parent-levels (n) "Return list of parent levels. 4 -> (1 2 3) @@ -61,6 +63,8 @@ text is taken as everything on the line after the (push (cons head-level head) path-alist))) (nreverse index))) +(declare-function helm-imenu "helm-imenu") +;;;###autoload (defun km/outline-jump-to-heading () "Jump to heading specified by `outline-regexp'." (interactive) @@ -70,47 +74,5 @@ text is taken as everything on the line after the helm-cached-imenu-candidates) (call-interactively #'helm-imenu))) -;; Modified from https://github.com/abo-abo/hydra/wiki/Emacs -(defhydra hydra-outline-mode (:hint nil) - " - ^^Hide ^^Show ^^Move -_q_ sublevels _a_ all _u_ up -_t_ body _e_ entry _n_ next visible -_o_ other _i_ children _p_ previous visible -_c_ entry _k_ branches _f_ forward same level -_h_ leaves _s_ subtree _b_ backward same level -_d_ subtree - -" - ("q" hide-sublevels) - ("t" hide-body) - ("o" hide-other) - ("c" hide-entry) - ("h" hide-leaves) - ("d" hide-subtree) - - ("a" show-all) - ("e" show-entry) - ("i" show-children) - ("k" show-branches) - ("s" show-subtree) - - ("u" outline-up-heading) - ("n" outline-next-visible-heading) - ("p" outline-previous-visible-heading) - ("f" outline-forward-same-level) - ("b" outline-backward-same-level) - - ("l" km/outline-jump-to-heading "jump" :color blue) - ("m" outline-mark-subtree "mark" :color blue)) - -(defun km/hydra-outline-mode () - (interactive) - (unless outline-minor-mode - (outline-minor-mode)) - (hydra-outline-mode/body)) - -(global-set-key (kbd "C-c n") 'km/hydra-outline-mode) - -(provide 'init-outline) -;;; init-outline.el ends here +(provide 'km-outline) +;;; km-outline.el ends here diff --git a/lisp/init-projectile.el b/lisp/km-projectile.el index 4c63a9e..27b4075 100644 --- a/lisp/init-projectile.el +++ b/lisp/km-projectile.el @@ -1,4 +1,4 @@ -;;; init-projectile.el --- Projectile configuration +;;; km-projectile.el --- Projectile configuration ;; Copyright (C) 2012-2016 Kyle Meyer <kyle@kyleam.com> @@ -20,15 +20,11 @@ ;;; Code: +(require 'dired) (require 'projectile) -(require 'helm-projectile) - -(setq projectile-find-dir-includes-top-level t - projectile-completion-system 'helm - projectile-use-git-grep t) - -(projectile-register-project-type 'snakemake '("Snakefile") "snakemake -p" "") +(require 'org-element) +;;;###autoload (defun km/projectile-switch-project (&optional arg) "Switch to a project. @@ -45,26 +41,24 @@ end up in the project if the buffers are now dead." (let ((projectile-switch-project-action 'km/projectile-maybe-restore-thing)) (projectile-switch-project))) -(defun km/projectile-ignore-directory-p (name) - (or (file-remote-p name) - (string-prefix-p "/tmp/" name))) - -(setq projectile-ignored-project-function #'km/projectile-ignore-directory-p) - +(declare-function km/open-external-terminal "km-shell") +;;;###autoload (defun km/projectile-open-external-terminal-in-root () "Run `km/open-external-terminal' in project root." (interactive) (let ((default-directory (projectile-project-root))) (km/open-external-terminal))) +;;;###autoload (defun km/projectile-view-file () "View project file. Interactive arguments are processed according to `projectile-find-file'." (interactive) - (call-interactively 'projectile-find-file) + (call-interactively #'projectile-find-file) (view-mode 1)) +;;;###autoload (defun km/projectile-view-file-other-window () "View project file in other window. Interactive arguments are processed according to @@ -90,6 +84,7 @@ names separated by a space." (if (listp fname) fname (list fname)) " ")))) +;;;###autoload (defun km/projectile-copy-project-filename-as-kill () "Copy name of project file. If point is on a file, copy this as the file name. Otherwise, @@ -109,6 +104,7 @@ use the name of the current file." The keys are project roots (strings), so use `lax-plist-put' and `lax-plist-get'.") +;;;###autoload (defun km/projectile-save-thing (thing) "Save thing for current project. @@ -182,141 +178,5 @@ Like `projectile-kill-buffers', but (cl-letf (((symbol-function 'yes-or-no-p) (lambda (&rest args) t))) (projectile-kill-buffers))) -;; I'm redefining a lot of bindings, so just set the whole map here to -;; have everything in one place. - -(setq projectile-command-map - (let ((map (make-sparse-keymap))) - (define-key map (kbd "4 b") 'projectile-switch-to-buffer-other-window) - (define-key map (kbd "4 C-o") 'projectile-display-buffer) - (define-key map (kbd "4 d") 'projectile-find-dir-other-window) - (define-key map (kbd "4 f") 'projectile-find-file-other-window) - (define-key map (kbd "4 v") 'km/projectile-view-file-other-window) - (define-key map (kbd ".") 'km/projectile-copy-project-filename-as-kill) - (define-key map "!" 'projectile-run-shell-command-in-root) - (define-key map "&" 'projectile-run-async-shell-command-in-root) - (define-key map "b" 'helm-projectile-switch-to-buffer) - (define-key map "c" 'projectile-compile-project) - (define-key map "d" 'helm-projectile-find-dir) - (define-key map "e" 'km/projectile-restore-thing) - (define-key map "f" 'helm-projectile-find-file) - (define-key map "F" 'helm-projectile-find-file-in-known-projects) - (define-key map "g" 'projectile-vc) - (define-key map "i" 'projectile-ibuffer) - (define-key map "I" 'projectile-invalidate-cache) - (define-key map "k" 'km/projectile-kill-buffers) - (define-key map "l" 'projectile-project-buffers-other-buffer) - (define-key map "m" 'projectile-commander) - (define-key map "o" 'projectile-multi-occur) - (define-key map "p" 'helm-projectile-switch-project) - (define-key map "q" 'projectile-replace) - (define-key map "r" 'helm-projectile-recentf) - (define-key map "s" 'projectile-grep) - (define-key map "v" 'km/projectile-view-file) - (define-key map "w" 'km/projectile-save-thing) - map)) -(fset 'projectile-command-map projectile-command-map) - -(key-chord-define-global "jq" 'projectile-commander) -(key-chord-define-global "gp" 'km/projectile-switch-project) - -(define-prefix-command 'km/projectile-ctl-x-4-map) -(define-key ctl-x-4-map "p" 'km/projectile-ctl-x-4-map) - -(define-key km/projectile-ctl-x-4-map (kbd "C-o") - 'projectile-display-buffer) -(define-key km/projectile-ctl-x-4-map "b" - 'projectile-switch-to-buffer-other-window) -(define-key km/projectile-ctl-x-4-map "d" - 'projectile-find-dir-other-window) -(define-key km/projectile-ctl-x-4-map "f" - 'projectile-find-file-other-window) -(define-key km/projectile-ctl-x-4-map "t" - 'projectile-find-implementation-or-test-other-window) -(define-key km/projectile-ctl-x-4-map "v" - 'km/projectile-view-file-other-window) - - -;;; Commander methods - -;; Like `projectile-command-map', I'm redefining a lot of bindings, so -;; unset pre-defined methods and define everyting here. - -(setq projectile-commander-methods nil) - -(def-projectile-commander-method ?b - "Find project buffer." - (call-interactively 'helm-projectile-switch-to-buffer)) - -(def-projectile-commander-method ?c - "Run project compilation command." - (call-interactively 'projectile-compile-project)) - -(def-projectile-commander-method ?d - "Find directory in project." - (helm-projectile-find-dir)) - -(def-projectile-commander-method ?D - "Find a project directory in other window." - (call-interactively 'projectile-find-dir-other-window)) - -(def-projectile-commander-method ?e - "Restore saved thing." - (km/projectile-restore-thing)) - -(def-projectile-commander-method ?f - "Open project file." - (helm-projectile-find-file)) - -(def-projectile-commander-method ?F - "Find project file in other window." - (call-interactively 'projectile-find-file-other-window)) - -(def-projectile-commander-method ?g - "Open project root in vc-dir or magit." - (projectile-vc)) - -(def-projectile-commander-method ?i - "Open an IBuffer window showing all buffers in the current project." - (call-interactively 'projectile-ibuffer)) - -(def-projectile-commander-method ?k - "Kill all project buffers." - (call-interactively 'km/projectile-kill-buffers)) - -(def-projectile-commander-method ?o - "Display a project buffer in other window." - (call-interactively 'projectile-display-buffer)) - -(def-projectile-commander-method ?O - "Run multi-occur on project buffers." - (projectile-multi-occur)) - -(def-projectile-commander-method ?p - "Switch project." - (helm-projectile-switch-project)) - -(def-projectile-commander-method ?r - "Find recently visited file in project." - (projectile-recentf)) - -(def-projectile-commander-method ?s - "Run grep on project." - (call-interactively #'projectile-grep)) - -(def-projectile-commander-method ?v - "View project file." - (km/projectile-view-file)) - -(def-projectile-commander-method ?V - "View project file in other window." - (km/projectile-view-file-other-window)) - -(def-projectile-commander-method ?w - "Save thing." - (call-interactively #'km/projectile-save-thing)) - -(projectile-global-mode) - -(provide 'init-projectile) -;;; init-projectile.el ends here +(provide 'km-projectile) +;;; km-projectile.el ends here diff --git a/lisp/init-python.el b/lisp/km-python.el index 3af81ec..dd11b75 100644 --- a/lisp/init-python.el +++ b/lisp/km-python.el @@ -1,4 +1,4 @@ -;;; init-python.el --- Python configuration +;;; km-python.el --- Python extensions ;; Copyright (C) 2012-2016 Kyle Meyer <kyle@kyleam.com> @@ -20,39 +20,17 @@ ;;; Code: -(setq python-fill-docstring-style 'pep-257-nn - python-indent-guess-indent-offset nil) - -(setq python-shell-interpreter "ipython" - python-shell-prompt-detect-enabled nil) - -(add-to-list 'interpreter-mode-alist '("python2" . python-mode)) -(add-to-list 'interpreter-mode-alist '("python3" . python-mode)) - -(add-hook 'python-mode-hook 'km/python-set-local-vars) -(add-hook 'python-mode-hook - (lambda () - (add-hook - 'post-self-insert-hook - #'km/python-indent-post-self-insert-function 'append 'local))) - -(defun km/python-set-local-vars () - (setq outline-regexp "####* ") - (setq outline-level 'km/python-outline-level) - ;; Stop semantic from taking over imenu. - (setq imenu-create-index-function #'python-imenu-create-index) - (set (make-local-variable 'compile-command) "py.test")) - -(defun km/python-outline-level () - (and (looking-at (concat "^" outline-regexp)) - (- (match-end 0) (match-beginning 0) 3))) +(require 'python) +(require 'km-util) +;;;###autoload (defun km/toggle-ipython-shell () "Switch between using python and IPython for interactive shell." (interactive) (setq python-shell-interpreter (if (string= python-shell-interpreter "python") "ipython" "python"))) +;;;###autoload (defun km/find-python-test-file-other-window (arg) "Open test file for the current Python file in another window. If the file does not already exist, import the original Python @@ -66,6 +44,7 @@ file. Unless ARG is non-nil, py.test is also imported." (unless arg (insert "import pytest\n"))))) +;;;###autoload (defun km/python-shell-send-function-or-paragraph-and-step () "Send function or paragraph to Python shell. @@ -87,6 +66,7 @@ This is inspired by `ess-eval-function-or-paragraph-and-step'." (goto-char end))) (km/python-next-code-line 1)) +;;;###autoload (defun km/python-shell-send-buffer-up-to-line () "Send beginning of buffer to the current line to Python shell." (interactive) @@ -127,6 +107,8 @@ This is inspired by `ess-eval-function-or-paragraph-and-step'." n)) (defvar km/python-shell-current-string nil) + +;;;###autoload (defun km/python-shell-send-set-string (set) "Send previously set string to Python shell. If a string has not been set previously or SET is non-nil, prompt @@ -165,6 +147,7 @@ Return point at the beginning input entry." (funcall move-func)) (point-at-bol))) +;;;###autoload (defun km/python-copy-last-shell-line-as-comment (&optional which-shell) "Insert last input and output Python shell as comment. When the current buffer is not associated with a Python shell or @@ -220,36 +203,10 @@ being turned on." (when (< (current-indentation) indentation) (indent-line-to indentation)))))) -(after 'python - (define-key python-mode-map (kbd "C-c C-.") - 'km/python-shell-send-buffer-up-to-line) - (define-key python-mode-map (kbd "C-c C-b") 'python-shell-send-buffer) - ;; Rebind `python-shell-send-buffer'. - (define-key python-mode-map (kbd "C-c C-c") - 'km/python-shell-send-function-or-paragraph-and-step) - - (define-key python-mode-map (kbd "C-c C-d") 'km/python-shell-send-set-string) - - ;; Swap `python-shell-send-defun' and `python-eldoc-at-point'. - (define-key python-mode-map (kbd "C-c C-f") 'python-shell-send-defun) - (define-key python-mode-map (kbd "C-M-x") 'python-eldoc-at-point) - - (define-prefix-command 'km/python-prefix-map) - (define-key python-mode-map (kbd "C-c m") 'km/python-prefix-map) - - (define-key km/python-prefix-map "c" 'km/python-copy-last-shell-line-as-comment) - (define-key km/python-prefix-map "t" 'km/find-python-test-file-other-window)) - ;;; Pydoc -(defvar km/pydoc-dir "~/src/emacs/pydoc/") - -(when (file-exists-p km/pydoc-dir) - (add-to-list 'load-path km/pydoc-dir) - (autoload 'pydoc "pydoc" nil t)) - -(setq pydoc-make-method-buttons nil) +(require 'pydoc) (defvar km/pydoc-names nil "List of names that have been sucessfully loaded by `pydoc'.") @@ -257,8 +214,7 @@ being turned on." (defvar km/pydoc-names-file "~/.emacs.d/.pydoc-names" "File to save `km/pydoc-names' to.") -(add-hook 'pydoc-after-finish-hook #'km/pydoc-store-name) - +;;;###autoload (defun km/pydoc () "Run `pydoc', prompting with `km/pydoc-names'." (interactive) @@ -294,6 +250,7 @@ FILE is `km/pydoc-names-file' by default." (print (sort km/pydoc-names #'string-lessp) (current-buffer)))))) +;;;###autoload (defun km/pydoc-read-names-file (&optional file) "Read `km/pydoc-names-file' from FILE. FILE is `km/pydoc-names-file' by default." @@ -306,14 +263,5 @@ FILE is `km/pydoc-names-file' by default." (insert-file-contents (or file km/pydoc-names-file)) (setq km/pydoc-names (read (current-buffer))))) -(after 'pydoc - ;; Don't shadow my `ace-link' binding. - (define-key pydoc-mode-map "o" #'ace-link-help)) - -(when (file-exists-p km/pydoc-names-file) - (km/pydoc-read-names-file km/pydoc-names-file)) - -(global-set-key (kbd "C-h y") #'km/pydoc) - -(provide 'init-python) -;;; init-python.el ends here +(provide 'km-python) +;;; km-python.el ends here diff --git a/lisp/km-shell.el b/lisp/km-shell.el new file mode 100644 index 0000000..fe9d25d --- /dev/null +++ b/lisp/km-shell.el @@ -0,0 +1,117 @@ +;;; km-shell.el --- Shell-related extensions + +;; Copyright (C) 2012-2016 Kyle Meyer <kyle@kyleam.com> + +;; Author: Kyle Meyer <kyle@kyleam.com> +;; URL: https://github.com/kyleam/emacs.d + +;; 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 <http://www.gnu.org/licenses/>. + +;;; Code: + +(require 'comint) +(require 'dash) +(require 'term) + +(defvar km/terminal "urxvt") + +;;;###autoload +(defun km/open-external-terminal () + (interactive) + (start-process "ext-term" nil km/terminal)) + +;;;###autoload +(defun km/zsh-ansi-term (&optional directory name) + "Open an ansi-term buffer running ZSH in DIRECTORY. + +If a terminal for DIRECTORY already exists, switch to that +buffer. If the current buffer is a terminal for DIRECTORY, +create an additional terminal. + +By default, DIRECTORY is `default-directory'. + +With a numeric prefix argument 0, prompt the user with existing +ZSH terminal directories. + +With a C-u prefix argument, set DIRECTORY to the user home +directory. + +With any other non-nil value, prompt for a directory. + +If NAME is non-nil, use *NAME* for the buffer name instead of +*zsh: DIRECTORY*. If that buffer already exists, it will be +grabbed regardless of whether its default-directory matches +DIRECTORY." + (interactive (km/zsh-ansi-term--args)) + (let* ((dir (abbreviate-file-name directory)) + (name (or name (concat "zsh: " dir))) + (full-name (concat "*" name "*")) + (default-directory dir)) + (pop-to-buffer-same-window + (cond + ((and (not (string= (km/zsh-ansi-term-directory) dir)) + (get-buffer full-name))) + (t + (cl-letf (((symbol-function 'switch-to-buffer) + (lambda (b &rest _) (get-buffer b)))) + (ansi-term "zsh" name))))) + (comint-goto-process-mark))) + +;;;###autoload +(defun km/zsh-toggle-ansi-term-home (&optional other-window) + (interactive "P") + (if (string= "*zsh*" (buffer-name)) + (bury-buffer) + (let ((display-buffer-overriding-action + (and other-window '(nil (inhibit-same-window . t))))) + (km/zsh-ansi-term "~/" "zsh")))) + +;;;###autoload +(defun km/zsh-ansi-term-other-window (&optional directory) + (interactive (km/zsh-ansi-term--args)) + (let ((display-buffer-overriding-action + '(nil (inhibit-same-window . t)))) + (km/zsh-ansi-term directory))) + +(defun km/zsh-ansi-term--args () + (list (cond + ((not current-prefix-arg) + default-directory) + ((= (prefix-numeric-value current-prefix-arg) 4) + "~/") + ((= (prefix-numeric-value current-prefix-arg) 0) + (let ((dirs (km/zsh-ansi-term-current-directories))) + (cl-case (length dirs) + (0 (user-error "No ZSH buffers found")) + (1 (car dirs)) + (t (completing-read "Directory: " dirs + nil nil nil nil (car dirs)))))) + (t + (read-directory-name "Directory: "))))) + +(defun km/zsh-ansi-term-directory (&optional buffer) + "Return directory name for ZSH terminal in BUFFER. +BUFFER defaults to current buffer." + (with-current-buffer (or buffer (current-buffer)) + (let ((bname (buffer-name))) + (and (derived-mode-p 'term-mode) + (string-match "^\\*zsh: \\(.*\\)\\*\\(<[0-9]+>\\)*$" + bname) + (match-string 1 bname))))) + +(defun km/zsh-ansi-term-current-directories () + (-distinct (-keep #'km/zsh-ansi-term-directory (buffer-list)))) + +(provide 'km-shell) +;;; km-shell.el ends here diff --git a/lisp/init-snakemake.el b/lisp/km-snakemake.el index 09b2065..01fa7f1 100644 --- a/lisp/init-snakemake.el +++ b/lisp/km-snakemake.el @@ -1,4 +1,4 @@ -;;; init-snakemake.el --- Snakemake mode configuration +;;; km-snakemake.el --- Extensions for Snakemake mode ;; Copyright (C) 2012-2016 Kyle Meyer <kyle@kyleam.com> @@ -20,25 +20,11 @@ ;;; Code: -(add-to-list 'load-path "~/src/emacs/snakemake-mode/") -(require 'snakemake-mode-autoloads) - -(autoload 'snakemake-compile-command "snakemake-mode") - -(setq snakemake-compile-command-options '("-p")) - -;; Although `compile-command' and `imenu-create-index-function' are -;; set when snakemake-mode is derived from Python mode, I need to -;; define them again here because I have a Python mode hook overrides -;; the Python versions. -(add-hook 'snakemake-mode-hook #'km/snakemake-set-local-vars) - -(defun km/snakemake-set-local-vars () - (set (make-local-variable 'compile-command) - (snakemake-compile-command)) - (set (make-local-variable 'imenu-create-index-function) - #'snakemake-imenu-create-index)) +(require 'projectile) +(require 'km-projectile) +(require 'snakemake-mode) +;;;###autoload (defun km/snakemake-compile-project-file (jobs) "Run Snakemake to produce project file at point. The numeric prefix JOBS controls the number of jobs that @@ -56,20 +42,12 @@ run. If JOBS is negative, just touch the output files." (default-directory (projectile-project-root))) (call-interactively 'compile))) +;;;###autoload (defun km/snakemake-compile-project-rule () "Run `snakemake-compile-rule' from project root." (interactive) (let ((default-directory (projectile-project-root))) (call-interactively #'snakemake-compile-rule))) -(after 'init-external - (define-key km/compile-map "b" - 'km/snakemake-compile-project-rule) - (define-key km/compile-map "p" - 'km/snakemake-compile-project-file)) - -(after 'dired - (define-key dired-mode-map "b" 'km/snakemake-compile-project-file)) - -(provide 'init-snakemake) -;;; init-snakemake.el ends here +(provide 'km-snakemake) +;;; km-snakemake.el ends here diff --git a/lisp/init-tex.el b/lisp/km-tex.el index 87f949e..15447d3 100644 --- a/lisp/init-tex.el +++ b/lisp/km-tex.el @@ -1,4 +1,4 @@ -;;; init-tex.el --- TeX configuration +;;; km-tex.el --- TeX extensions ;; Copyright (C) 2012-2016 Kyle Meyer <kyle@kyleam.com> @@ -20,20 +20,8 @@ ;;; Code: -(setq reftex-default-bibliography '("refs.bib")) - -(setq font-latex-fontify-sectioning 'color - TeX-electric-math '("$" . "$")) - -(put 'LaTeX-narrow-to-environment 'disabled nil) - -(add-to-list 'auto-mode-alist '("\\.[tT]e[xX]\\'" . latex-mode)) - -(add-hook 'LaTeX-mode-hook 'turn-on-reftex) -(add-hook 'LaTeX-mode-hook 'flyspell-mode) -(add-hook 'LaTeX-mode-hook (lambda () - (setq imenu-create-index-function - #'km/latex-imenu-create-index-function))) +(require 'tex) +(require 'latex) (defun km/latex-imenu-create-index-function () ;; See `LaTeX-imenu-create-index-function'. @@ -57,5 +45,5 @@ entries))) (nreverse entries))) -(provide 'init-tex) -;;; init-tex.el ends here +(provide 'km-tex) +;;; km-tex.el ends here diff --git a/lisp/init-appearance.el b/lisp/km-theme.el index 72c575d..4eeb799 100644 --- a/lisp/init-appearance.el +++ b/lisp/km-theme.el @@ -1,4 +1,4 @@ -;;; init-appearance.el --- Appearance-related configuration +;;; km-theme.el --- Tweaks to the stekene light theme ;; Copyright (C) 2012-2016 Kyle Meyer <kyle@kyleam.com> @@ -20,20 +20,6 @@ ;;; Code: -(setq inhibit-splash-screen t - initial-scratch-message nil) - -(scroll-bar-mode -1) -(tool-bar-mode -1) -(menu-bar-mode -1) -(blink-cursor-mode -1) - -(line-number-mode) -(column-number-mode) -(size-indication-mode) - -;;; Theme - (load-theme 'stekene-light t) (custom-theme-set-faces @@ -95,5 +81,5 @@ '(dired-subtree-depth-3-face ((t (:background "gray95")))) '(whitespace-indentation ((t (:background "gray90"))))) -(provide 'init-appearance) -;;; init-appearance.el ends here +(provide 'km-theme) +;;; km-theme.el ends here diff --git a/lisp/init-util.el b/lisp/km-util.el index c085738..8957862 100644 --- a/lisp/init-util.el +++ b/lisp/km-util.el @@ -1,4 +1,4 @@ -;;; init-util.el --- Utilities +;;; km-util.el --- Utilities ;; Copyright (C) 2012-2016 Kyle Meyer <kyle@kyleam.com> @@ -34,5 +34,5 @@ (--filter (with-current-buffer it (derived-mode-p mode)) (buffer-list))) -(provide 'init-util) -;;; init-util.el ends here +(provide 'km-util) +;;; km-util.el ends here diff --git a/lisp/km-webjump.el b/lisp/km-webjump.el new file mode 100644 index 0000000..94b3842 --- /dev/null +++ b/lisp/km-webjump.el @@ -0,0 +1,48 @@ +;;; km-webjump.el --- Extensions for webjump + +;; Copyright (C) 2012-2016 Kyle Meyer <kyle@kyleam.com> + +;; Author: Kyle Meyer <kyle@kyleam.com> +;; URL: https://github.com/kyleam/emacs.d + +;; 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 <http://www.gnu.org/licenses/>. + +;;; Code: + +(require 'cl-lib) +(require 'webjump) + +(defun km/webjump-read-string (prompt) + "Like `webjump-read-string', but set default." + (let* ((default (if (use-region-p) + (buffer-substring-no-properties + (region-beginning) (region-end)) + (thing-at-point 'symbol))) + (prompt (if default + (format "%s (%s): " prompt default) + (concat prompt ": "))) + (input (read-string prompt nil nil default))) + (unless (webjump-null-or-blank-string-p input) + (substring-no-properties input)))) + +;;;###autoload +(defun km/webjump () + "Run`webjump' with symbol at point or region as default query. +This affects only sites in the `simple-query' format." + (interactive) + (cl-letf (((symbol-function 'webjump-read-string) #'km/webjump-read-string)) + (call-interactively #'webjump))) + +(provide 'km-webjump) +;;; km-webjump.el ends here diff --git a/lisp/setkey.el b/lisp/setkey.el new file mode 100644 index 0000000..e5d3ec1 --- /dev/null +++ b/lisp/setkey.el @@ -0,0 +1,48 @@ +;;; setkey.el --- Set a temporary key binding + +;; Copyright (C) 2012-2016 Kyle Meyer <kyle@kyleam.com> + +;; Author: Kyle Meyer <kyle@kyleam.com> +;; URL: https://github.com/kyleam/emacs.d + +;; 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 <http://www.gnu.org/licenses/>. + +;;; Code: + +(defvar setkey-command nil) +(defvar setkey-last-call-time nil) +(defvar setkey-seconds-timeout 600) + +;;;###autoload +(defun setkey-call () + "Call `setkey-command'. +When `setkey-command' is nil or the time since the last call +has exceeded `setkey-seconds-timeout', read the command to +call." + (interactive) + (when (or (not setkey-command) + (> (- (float-time) setkey-last-call-time) + setkey-seconds-timeout)) + (setq setkey-command (read-command "Command: " setkey-command))) + (setq setkey-last-call-time (float-time)) + (call-interactively setkey-command)) + +(defun setkey-reset () + "Reset `setkey-call' command." + (interactive) + (setq setkey-command nil + setkey-last-call-time nil)) + +(provide 'setkey) +;;; setkey.el ends here |