Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
818 lines (682 sloc) 28.7 KB
;; config-packages.el --- configure my Emacs packages.
;;; Author: Nate Eagleson
;;; Version: 0.0.1
;;; Commentary:
;; Just a big collection of use-package invocations.
;;; Code:
(require 'use-package)
(use-package s
:commands s-replace s-trim)
(use-package my-functions
:commands hit-servlet comment-or-uncomment-region-or-line wrap-args
move-current-buffer insert-date insert-time unfill-paragraph
add-auto-mode)
(use-package daily-log
:commands daily-log-show-total-time
daily-log-show-current-week-time
daily-log-show-current-week-time-remaining)
(use-package my-keybindings)
(use-package config-windows
:commands set-windows-env)
(use-package cygwin-mount
:commands cygwin-mount-activate)
;; Make it easy to find the cursor after scrolling.
(use-package beacon
:init (beacon-mode 1)
:diminish beacon-mode)
;; Solarized is better than your theme.
;;
;; Sorry, it's just true.
(use-package solarized-theme
:config
(load-theme 'solarized-dark t)
(let ((line (face-attribute 'mode-line :underline)))
(set-face-attribute 'mode-line nil :overline line)
(set-face-attribute 'mode-line nil :underline line)
(set-face-attribute 'mode-line-inactive nil :overline line)
(set-face-attribute 'mode-line-inactive nil :underline line)
(set-face-attribute 'mode-line nil :box nil)
(set-face-attribute 'mode-line-inactive nil :box nil)))
(use-package moody
:config
(setq x-underline-at-descent-line t)
(moody-replace-mode-line-buffer-identification)
(moody-replace-vc-mode))
;; N.B.: I can get colors from Git by setting TERM=ansi after the session
;; starts. I suppose I should figure out the right solution to that problem
;; then turn it into code.
(use-package shell-pop
;; Make shell-pop's shell appear in the window it created for it. Workaround
;; from open GitHub issue:
;;
;; https://github.com/kyagi/shell-pop-el/issues/51#issuecomment-297470855
:config (push (cons "\\*shell\\*" display-buffer--same-window-action) display-buffer-alist)
(setq shell-pop-full-span t
shell-pop-universal-key "C-'"
shell-pop-shell-type '("ansi-term" "*ansi-term*"
(lambda nil
(ansi-term shell-pop-term-shell)))))
(use-package notmuch
:config
(progn
;; TODO Stop marking deleted and spam messages as read.
;;
;; I'm marking them as read just to keep the gmail inbox semi-usable, and
;; to make sure the next time I change my sync program and therefore have
;; to re-index from scratch, it's not as *much* of a disaster, in that I'll
;; at least have a clear record of what I've processed and what I haven't.
;;
;; ...granted, the right answer here is to figure out how to sync notmuch
;; tags to IMAP folders. Someday.
(define-key notmuch-search-mode-map "d"
(lambda (&optional beg end)
"mark message as deleted"
(interactive (notmuch-search-interactive-region))
(notmuch-search-tag (list "+deleted" "-unread") beg end)))
(define-key notmuch-search-mode-map "r"
(lambda (&optional beg end)
"mark message as an archived receipt"
(interactive (notmuch-search-interactive-region))
(notmuch-search-tag (list "+receipts" "-unread" "-inbox") beg end)))
(define-key notmuch-search-mode-map "s"
(lambda (&optional beg end)
"mark message as spam"
(interactive (notmuch-search-interactive-region))
(notmuch-search-tag (list "+spam" "-inbox" "-unread") beg end)))
;; Be evil-ish, because I want that.
(define-key notmuch-show-mode-map "j" 'next-line)
(define-key notmuch-show-mode-map "k" 'previous-line)
(define-key notmuch-search-mode-map "j" 'next-line)
(define-key notmuch-search-mode-map "k" 'previous-line)
;; Make it easier to open attachments in the corresponding tool.
(define-key notmuch-show-mode-map (kbd "o")
'notmuch-show-interactively-view-part)
(define-key notmuch-show-mode-map (kbd "D")
(lambda ()
"Delete current message and move to the next message or thread.
TODO Make this delete all messages in buffer, a la notmuch-show-archive-thread-then-next?"
(interactive)
(notmuch-show-tag (list "+deleted" "-inbox" "-unread"))
(unless (notmuch-show-next-open-message)
(notmuch-show-next-thread t))))
(define-key notmuch-show-mode-map "w"
(lambda ()
"Mark message as watched and reply to the sender."
(interactive)
(notmuch-show-tag (list "+watched"))
(notmuch-show-reply-sender)))
(define-key notmuch-show-mode-map "W"
(lambda ()
"Mark message as watched and reply to all."
(interactive)
(notmuch-show-tag (list "+watched"))
(notmuch-show-reply)))
;; I already have a keybinding for 'archive thread', so rebind Spacebar to
;; just let me advance the thread and move to the next one when I'm done
;; with it, rather than moving to the next one and archiving.
(define-key notmuch-show-mode-map (kbd "SPC")
(lambda ()
"Move to the next message or thread.
I feel like this should be built-in somewhere to notmuch-mode, but I haven't
found it."
(interactive)
(if (notmuch-show-advance)
(notmuch-show-next-thread t))))
;; Download an attachment locally.
;;
;; A rebinding of the standard 'w' keybinding, since I use 'w' for
;; something else."
(define-key notmuch-show-mode-map "d" 'notmuch-show-save-attachments)
(defun ne/notmuch-tag-sent-emails (&optional arg)
"Use shell command to tag sent emails as sent and read.
The shell command lives in my dotfiles repo."
(start-process "tag-sent-emails" nil "tag-sent-emails"))
(advice-add 'notmuch-mua-send-and-exit :after #'ne/notmuch-tag-sent-emails)
(require 'notmuch-address)
(notmuch-address-setup)
;; TODO Get address completion to work correctly. I can trigger it now, but
;; it assumes I want the first result, which is not often true and thus
;; forces me to type more than I want to.
(define-key notmuch-message-mode-map
(kbd "<backtab>")
'(lambda () (interactive) (notmuch-address-expand-name)))))
(use-package uniquify
:init
(setq
uniquify-buffer-name-style 'post-forward
uniquify-separator ":"
uniquify-after-kill-buffer-p t
uniquify-ignore-buffers-re "^\\*"))
(use-package projectile
:diminish projectile-mode
:init (projectile-mode))
(use-package helm-projectile
:commands helm-projectile-find-file)
(use-package helm
:diminish helm-mode
:init
(progn
(helm-mode 1)
;; Yoinked from spacemacs:
;;
;; https://github.com/syl20bnr/spacemacs/blob/522366bbd179bc332a863efeb523daa09c603458/layers/+distribution/spacemacs-base/packages.el#L787-L795
(define-key helm-map (kbd "C-j") 'helm-next-line)
(define-key helm-map (kbd "C-k") 'helm-previous-line)
(define-key helm-map (kbd "C-h") 'helm-next-source)
(define-key helm-map (kbd "C-S-h") 'describe-key)
(define-key helm-map (kbd "C-l") (kbd "RET"))
(dolist (keymap (list helm-find-files-map helm-read-file-map))
(define-key keymap (kbd "C-l") 'helm-execute-persistent-action)
(define-key keymap (kbd "C-h") 'helm-find-files-up-one-level)
(define-key keymap (kbd "C-S-h") 'describe-key))
(define-key helm-find-files-map (kbd "C-c d") 'insert-date)
(global-set-key (kbd "M-x") 'helm-M-x)
(global-set-key (kbd "C-x C-f") 'helm-find-files)))
(use-package flycheck
:diminish
:defer t
:config (progn
(flycheck-define-checker proselint
"A linter for prose."
:command ("proselint" source)
:error-patterns
((warning line-start (file-name) ":" line ":" column ": "
(id (one-or-more (not (any " "))))
(message) line-end))
:modes (text-mode markdown-mode gfm-mode rst-mode))
(add-to-list 'flycheck-checkers 'proselint)
(flycheck-objc-clang-setup)
;; Prefer locally-installed eslint, if available.
;;
;; Yanked from lunaryorn himself:
;;
;; http://emacs.stackexchange.com/a/21207/351
(defun my/use-eslint-from-node-modules ()
(let* ((root (locate-dominating-file
(or (buffer-file-name) default-directory)
"node_modules"))
(eslint (and root
(expand-file-name "node_modules/eslint/bin/eslint.js"
root))))
(when (and eslint (file-executable-p eslint))
(setq-local flycheck-javascript-eslint-executable eslint))))
(add-hook 'flycheck-mode-hook #'my/use-eslint-from-node-modules)))
(use-package ledger-mode
:hook (ledger-mode . evil-ledger-mode))
;; Since emacs 24.4 made revert undoable, this option is perfectly safe and
;; pretty convenient.
(use-package autorevert
:diminish auto-revert-mode
:init
(global-auto-revert-mode))
(use-package ne-yas-auto-insert
:commands ne-yas-auto-insert-activate
ne-yas-auto-insert-config)
(use-package autoinsert
:init
(progn
(ne-yas-auto-insert-config)
(ne-yas-auto-insert-activate)
(auto-insert-mode)))
;; undo-tree improves on emacs' default infinite undo by teaching it to be
;; intelligent in how it handles branching, and offering a nice UI for
;; comparing things across branches.
;;
;; If it weren't for the bug that destroys undo history, it would be an
;; unmitigated spectacular win.
(use-package undo-tree
:diminish undo-tree-mode
:init
(global-undo-tree-mode)
;; Store undo history in my autosaves directory (which is configured
;; elsewhere).
(setq undo-tree-auto-save-history t)
(setq undo-tree-history-directory-alist `(("." . ,my-autosaves-dir)))
;; Evil has built-in logic to set up bindings in undo-tree mode.
;;
;; However, there doesn't seem to be a built-in way to say 'turn on
;; evil-local-mode whenever we run undo-tree-visualize'.
;;
;; Therefore, set that up here.
(defadvice undo-tree-visualize (after evil-2 activate)
(evil-local-mode)))
(use-package my-frame-setup
:commands my-set-up-frame)
(use-package space-trail
;; TODO Remove commands once it's packaged and has autoloads.
:commands space-trail-activate
:init (space-trail-activate))
(use-package evil-exchange
:commands evil-exchange-install)
(use-package evil-commentary
:commands evil-commentary-mode)
(use-package ne-evil-textobjects
:commands ne/install-textobjects)
;; Adds a text object to evil for selecting HTML attributes, bound by default
;; to 'x'.
;;
;; I do this often enough it seemed worth installing.
(use-package exato)
(use-package crontab-mode
:mode "\\.cron\\(tab\\)?\\'"
:config (add-hook 'crontab-mode-hook 'conf-mode-init))
(use-package evil-smartparens
:commands evil-sp-smartparens-config)
(use-package evil
:commands evil-local-mode
:config
;; I used to use evil-escape to let me use 'jk' to return to
;; evil-normal-state from evil-insert-state.
;;
;; I have abandoned that by making Control with no other keys send Escape
;; on my keyboards.
;;
;; This change was largely motivated by typing 'jk' way more often than I
;; meant to when working on a machine other than my own. By conforming to
;; standard Vim keybindings and just making it easier to trigger them, I
;; still have a comfortable personal environment but find it way easier to
;; work in foreign ones.
;; (setq evil-mode-line-format nil)
;; Use regular emacs keybindings for insert-mode (except for ESC-ESC-ESC,
;; because vim keybindings are still vim).
(setq evil-insert-state-map (make-sparse-keymap))
(define-key evil-insert-state-map (kbd "<escape>") 'evil-normal-state)
;; Trying out evil-smartparens. We'll see if it works out.
(evil-sp-smartparens-config)
;; Always use a leader key, because the leader is awesome. See
;; my-keybindings.el for my actual leader keybindings.
(global-evil-leader-mode)
(evil-leader/set-leader "<SPC>")
;; Turn on surround everywhere.
(global-evil-surround-mode)
;; Use 'gx' for swapping vim textobjects/motions.
(evil-exchange-install)
;; Add vim operator for commenting things.
(evil-commentary-mode)
(diminish 'evil-commentary-mode)
;; Set up my custom textobjects.
(ne/install-textobjects)
;; If a buffer is empty on evil-mode start, go directly to insert-mode,
;; because we'll almost certainly want to start typing.
;;
;; An empty buffer isn't the *only* case where this is the case, but it's a
;; starting point.
(add-hook 'evil-local-mode-hook
'(lambda ()
;; HACK Magit buffers seem to start at size 0, but they
;; populate very quickly, so waiting just a bit before
;; checking whether we should be in insert-mode seems to work
;; okay in practice. Doesn't work for *scratch*, though.
(run-at-time "0.1 sec"
nil
(lambda ()
(when (and evil-local-mode
(= (buffer-size) 0)
;; HACK *scratch* buffer seems to
;; start out at 0 length, so I
;; explicitly ignore it.
(not (string-equal (buffer-name)
"*scratch*")))
(evil-insert-state)))))))
(use-package git-gutter
:diminish
:config
(add-to-list 'git-gutter:update-hooks 'focus-in-hook)
(add-to-list 'git-gutter:update-hooks 'magit-post-refresh-hook))
(use-package magit
:defer t
:hook ((magit-mode . magit-svn-mode)
(magit-status-mode . evil-local-mode)
(magit-rebase-mode . evil-local-mode))
:config (require 'evil-magit)
;; I never use magit's gitignore editing and because evil-magit
;; doesn't have support for everything I want to do from
;; evil-normal-state, I change to evil-insert-state sometimes.
;;
;; Specifically I can't jump to end-of-line/start-of-line in
;; normal-state because magit binds '$', '^' and '0'. I also can't
;; trigger magit-svn with its default binding of 'N', because evil
;; rightfully binds 'N' to evil-search-previous.
(define-key magit-status-mode-map (kbd "i") nil))
(use-package git-commit
:init (global-git-commit-mode 1)
(add-hook 'git-commit-mode-hook 'evil-insert-state))
(use-package abbrev
:defer t
:diminish abbrev-mode)
(use-package simple
:diminish auto-fill-function)
(use-package set-minor-mode-key
:commands set-minor-mode-key)
(use-package aggressive-fill-paragraph
:defer t
:config (afp-advise-filled-functions))
(use-package string-edit
:hook ((string-edit-mode . evil-local-mode)))
;; Commented out because this is crashing my setup for some reason, and I'm not
;; currently using eclim.
;; (use-package eclimd
;; :defer t
;; :diminish
;; :init
;; (progn
;; (autoload 'eclimd--running-p "eclimd" nil t)))
;; (use-package eclim
;; :defer t
;; :diminish)
(use-package ne-smart-dash-hacks
:commands ne-smart-dash-hacks-sh-mode-install)
(use-package smart-dash
:hook ((smart-dash-mode . (lambda () (when (equal major-mode 'sh-mode)
(ne-smart-dash-hacks-sh-mode-install))))))
(use-package sh-script
:config (defun ne-sh-mode-maybe-insert-equals ()
(interactive)
(if (looking-back "^[[:space:]]*" nil)
(progn (self-insert-command 1)
(backward-char))
(self-insert-command 1)))
:mode (("\\.envrc\\'" . sh-mode)
("\\.env" . sh-mode))
:bind (:map sh-mode-map ("=" . 'ne-sh-mode-maybe-insert-equals))
:hook ((sh-mode . (lambda () (setq-local ne-yas-auto-insert-snippet-name
"shell-script")))))
(use-package gnuplot-mode
:interpreter "gnuplot")
(use-package tern
:diminish tern-mode
:config (add-hook 'tern-mode-hook '(lambda ()
(require 'tern-auto-complete)
(tern-ac-setup)
;; Keybinding to force Tern's
;; autocompletion, for cases like
;; discussing data structures and APIs in
;; comments.
(define-key
tern-mode-keymap
(kbd "C-<tab>")
'tern-ac-complete)
(setq tern-ac-sync t)
(add-to-list 'ac-sources
'ac-source-tern-completion))))
(use-package ac-ispell
:commands ac-ispell-setup)
(use-package tern-auto-complete
:commands tern-ac-setup
:config
;; Make tern's ac-source work with ac-trigger-key-command.
;;
;; Without this advice, completions are not fired when I press Tab with my
;; config.
;;
;; TODO Turn this into a PR to tern-auto-complete?
;;
;; It's almost an exact copy of the advice from there on auto-complete, and
;; should prevent other people who use an ac-trigger-key from having the same
;; issue.
(defadvice ac-trigger-key-command (around add-tern-ac-candidates first activate)
"Load tern-js candidates before ac-start."
(if (and tern-ac-sync
(memq major-mode tern-ac-js-major-modes)
(not (or (ac-menu-live-p) (ac-inline-live-p)))
;; Extension - do not complete if there is no prefix, so TAB
;; fallback behavior can occur in that case.
(ac-prefix-default))
(tern-ac-complete-request
'(lambda ()
(auto-complete-1 :triggered 'trigger-key)))
ad-do-it))
;; ac-source-yasnippet fails with the above advice if I don't do this.
;;
;; TODO Make this more robust. It should only add ac-trigger-key-command if
;; it isn't already in there.
(if yas-expand-only-for-last-commands
(add-to-list 'yas-expand-only-for-last-commands 'ac-trigger-key-command))
)
(use-package json-mode
;; There's nothing that needs to be configured, but don't forget the
;; jq-interactively command. It can be very handy when trying to figure out
;; how to transform some arbitrary JSON with jq.
:config (add-hook 'json-mode-hook 'js-mode-init))
(use-package jedi-force
:commands jedi-force-set-up-hooks)
(use-package python-mode
:init (jedi-force-set-up-hooks)
:config
(add-hook 'python-mode-hook '(lambda ()
(my-prog-mode-init)
(setq jedi:use-shortcuts t)
(setq jedi:complete-on-dot t))))
(use-package csharp-mode
:config
(add-hook 'csharp-mode-hook 'omnisharp-mode))
(use-package cquery)
(use-package yaml-mode
:mode "\\.yaml\\'"
:defer t
:config
(add-hook 'yaml-mode-hook
'my-prog-mode-init))
(use-package groovy-mode
:defer t
:mode "\\.groovy$"
:mode "\\.gradle$"
:config
(add-hook 'groovy-mode-hook 'my-prog-mode-init))
(use-package nxml-mode
:mode ("web.config$" . xml-mode)
:defer t
:config
(progn
(setq nxml-child-indent 4)
(setq nxml-slash-auto-complete-flag t)
(add-hook 'nxml-mode-hook (lambda () (emmet-mode t)))))
(use-package web-mode
:mode (("\\.html\\'" . web-mode)
("\\.tmpl\\'" . web-mode)
("\\.blade.php\\'" . web-mode)
("\\.twig\\'" . web-mode)
("\\.hbs\\'" . web-mode)
("\\.handlebars\\'" . web-mode))
:config
(add-hook 'web-mode-hook 'web-mode-init))
;; TODO Extract html-scratchpad to a standalone package with autoloads. Then I
;; wouldn't have to declare the command.
(use-package html-scratchpad
:commands html-scratchpad-make-new)
(use-package css-mode
:mode (("\\.css\\'" . css-mode)
("\\.scss\\'" . scss-mode))
:config
(add-hook 'scss-mode-hook
(lambda ()
;; Use SCSS-style comments, largely so that comment functions
;; don't go crazy the way they do in css-mode.
(setq comment-start "//"
comment-end ""))))
(use-package lisp-mode
:mode (("\\.el\\'" . emacs-lisp-mode)
("/Cask\\'" . emacs-lisp-mode))
:config
;; Wait to set up elisp customizations until initialization is done.
;;
;; Otherwise, the various elisp buffers like *scratch* that appear before my
;; config is finished loading throw errors for all the dependencies that
;; aren't loaded yet.
;;
;; This still results in *scratch* having the extras, though, since the hook
;; runs first time it's set. For a workaround, this is a pretty seamless one.
(add-hook 'after-init-hook
'(lambda ()
(add-hook 'emacs-lisp-mode-hook 'emacs-lisp-init))))
(use-package slime
:config
(progn
(defun mit-scheme-start-swank (file encoding)
(format "%S\n\n" `(start-swank ,file)))
(defun mit-scheme-find-buffer-package ()
(save-excursion
(let ((case-fold-search t))
(goto-char (point-min))
(and (re-search-forward "^;+ package: \\(([^)]+)\\)" nil t)
(match-string-no-properties 1)))))
(defun mit-scheme-slime-mode-init ()
(slime-mode t)
(make-local-variable 'slime-find-buffer-package-function)
(setq slime-find-buffer-package-function 'mit-scheme-find-buffer-package))
(slime-setup)
(if (not (memq 'mit-scheme slime-lisp-implementations))
(setq slime-lisp-implementations
(cons '(mit-scheme ("mit-scheme")
:init mit-scheme-start-swank)
slime-lisp-implementations)))
(setq slime-default-lisp 'mit-scheme)
(add-hook 'scheme-mode-hook 'mit-scheme-slime-mode-init)))
(use-package hideshow
:defer t
:config
(progn
(diminish 'hs-minor-mode)))
(use-package yasnippet
:diminish yas-minor-mode
:config
(progn
;; Set up all snippet dirs to lazy-load.
(yas-reload-all)
;; Give keys_with_underscores priority over non-underscored-keys.
;; This lets things like require_once in php-mode not be overridden by
;; 'once' from cc-mode, php-mode's parent mode.
(setq yas-key-syntaxes (list "w_" "w" "w_." "w_.()" "^ "))
;; GRIPE For reasons I don't understand, I need this invocation in
;; order to avoid a never-ending recursion of defining keybindings. I
;; think it's some interaction between yasnippet and auto-complete, but
;; I'm not really sure.
(define-key yas-minor-mode-map (kbd "TAB") yas-maybe-expand)
(define-key yas-minor-mode-map (kbd "C-c y") yas-maybe-expand)
(define-key yas-minor-mode-map [(tab)] nil)))
(use-package glasses
:commands glasses-mode
:diminish glasses-mode)
(use-package diff-mode
:init (add-hook 'diff-mode-hook
'(lambda ()
;; TODO Submit this as a patch to diff-mode.
;;
;; It already has these semantics, in that lines starting
;; with a # do not cause the hunk headers to adjust, so
;; that should probably be properly reflected.
(setq-local comment-start "#")
(text-mode-init)
))
:bind (:map diff-mode-map
("M-\d" . backward-kill-word)))
(use-package apache-mode
:hook (apache-mode . conf-mode-init))
(use-package diffview
:commands diffview-current)
;; eldoc-overlay mode is interesting, but has some quirks that make it kinda
;; painful.
;;
;; Hence, just commenting this out for now.
;;
;; (use-package eldoc
;; :diminish
;; :init (add-hook 'eldoc-mode-hook 'eldoc-overlay-mode))
;; Use camel-spell to spell-check camel-cased words, mostly to catch spelling
;; errors in source code.
;;
;; In principle I think the algorithm it applies should be supported at the
;; spellchecker level, because then you can apply the tool generally, not just
;; in Emacs - spell-check your code as part of your build process, for
;; instance.
;;
;; The algorithm can even be a bit smarter, which I intend to fix - with words
;; like SimpleHTTPServer, you can and should split between 'P' and 'S', as the
;; closing capital letter is part of the next word, by very strong convention.
;;
;; For now, though, this works, and is a big improvement on what I had before.
;;
;; TODO Get an open-source spellchecker to add support for camelCasing words.
(use-package camel-spell)
(use-package flyspell
:defer t
:config
(progn
;; Function to use popup.el menu for flyspell instead of the GUI menu. From
;; Emacswiki: http://www.emacswiki.org/emacs/FlySpell#toc11 It'd be nice to
;; convert this to a package.
;;
;; FIXME Get this working with camel-spell. For some reason it doesn't seem
;; to want to.
(defun flyspell-emacs-popup-textual (event poss word)
"A textual flyspell popup menu."
(require 'popup)
(let* ((corrects (if flyspell-sort-corrections
(sort (car (cdr (cdr poss))) 'string<)
(car (cdr (cdr poss)))))
(cor-menu (if (consp corrects)
(mapcar (lambda (correct)
(list correct correct))
corrects)
'()))
(affix (car (cdr (cdr (cdr poss)))))
show-affix-info
(base-menu (let ((save (if (and (consp affix) show-affix-info)
(list
(list (concat "Save affix: " (car affix))
'save)
'("Accept (session)" session)
'("Accept (buffer)" buffer))
'(("Save word" save)
("Accept (session)" session)
("Accept (buffer)" buffer)))))
(if (consp cor-menu)
(append cor-menu (cons "" save))
save)))
(menu (mapcar
(lambda (arg) (if (consp arg) (car arg) arg))
base-menu)))
(cadr (assoc (popup-menu* menu :scroll-bar t) base-menu))))
(fset 'flyspell-emacs-popup 'flyspell-emacs-popup-textual)))
(use-package atomic-chrome
:demand
:functions (atomic-chrome-start-server atomic-chrome-stop-server)
:config (progn
;; Don't start Atomic Chrome if another Emacs instance is already
;; running it, and don't kill it if we didn't start the server.
;;
;; Since I do a fair bit of elisp hacking, I start a second Emacs
;; pretty often as part of my workflow, to verify that my init code
;; is doing what I expect, and vanilla Atomic Chrome causes startup
;; failures.
;;
;; TODO Get this fixed upstream. A real pidfile could be an option.
(defvar ne/atomic-chrome-started-by-us nil
"Whether this Emacs instance started an Atomic Chrome server.")
(defun ne/atomic-chrome-mark-server-started ()
(when (not (file-exists-p "~/.atomic-chrome-running"))
(setq ne/atomic-chrome-started-by-us t)
(write-region "" nil "~/.atomic-chrome-running")))
(defun ne/atomic-chrome-mark-server-stopped ()
(when ne/atomic-chrome-started-by-us
(delete-file "~/.atomic-chrome-running")))
(advice-add 'atomic-chrome-start-server :before
#'ne/atomic-chrome-mark-server-started)
(advice-add 'atomic-chrome-stop-server :before
#'ne/atomic-chrome-mark-server-stopped)
(add-hook 'kill-emacs-hook 'ne/atomic-chrome-mark-server-stopped)
(when (not (file-exists-p "~/.atomic-chrome-running"))
(atomic-chrome-start-server)))
)
(use-package conf-mode
;; As a rule of thumb, if it's in dotfiles/src and it doesn't match a
;; more-specific regex, it should probably open in conf-mode.
:mode "dotfiles/src/.+")
;; EmacsWiki-based packages that used to be on MELPA but are no more:
;;
;; https://github.com/melpa/melpa/pull/5008#issuecomment-360098939
(use-package ascii
:commands ascii-on ascii-off ascii-display ascii-customize)
(use-package frame-cmds
:commands maximize-frame-vertically)
;;; config-packages.el ends here