 ;; http://projectile.readthedocs.io/en/latest/
 ;;;;
 
-;;; Enable Projectile everywhere.
-(projectile-global-mode 1)
+(when (member 'projectile radon-packages)
+
+  ;;; Enable Projectile everywhere.
+  (projectile-global-mode 1))
 
 ;;;; Package: Helm
 ;; Shows completions for switching to files and buffers in a separate,
 ;; easy-to-navigate buffer.
 ;;;;
 
-;;; Use Helm mode for many standard Emacs commands.
-(helm-mode 1)
-
-;;; Use Helm mode for Projectile commands. Using helm-projectile-toggle
-;;; instead of helm-projectile-on means we don't get a useless "Turn on
-;;; helm-projectile key bindings" message in the minibuffer during startup.
-
-;; The local binding of ad-redefinition works around a warning message
-;; "ad-handle-definition: `tramp-read-passwd' got redefined", as described at:
-;; https://github.com/emacs-helm/helm/issues/1498#issuecomment-218249480
-
-(let ((ad-redefinition-action 'accept))
-  (helm-projectile-toggle 1))
-
-;;; Use Helm mode for M-x, using helm-smex to get sorting by usage.
-(global-set-key (kbd "M-x") 'helm-smex)
-
-;;; Use fuzzy matching.
-(setq helm-mode-fuzzy-match t)
-
-;;; Get rid of the awful background color for buffers corresponding to files
-;;; modified outside of Emacs.
-(when radon-tweak-colors
-  (set-face-background 'helm-buffer-saved-out nil))
+(when (member 'helm radon-packages)
+
+  ;;; Use Helm mode for many standard Emacs commands.
+  (helm-mode 1)
+
+  (when (member 'helm-projectile radon-packages)
+
+    ;;; Use Helm mode for Projectile commands. Using helm-projectile-toggle
+    ;;; instead of helm-projectile-on means we don't get a useless "Turn on
+    ;;; helm-projectile key bindings" message in the minibuffer during startup.
+
+    ;; The local binding of ad-redefinition works around a warning message
+    ;; "ad-handle-definition: `tramp-read-passwd' got redefined", as described at:
+    ;; https://github.com/emacs-helm/helm/issues/1498#issuecomment-218249480
+
+    (let ((ad-redefinition-action 'accept))
+      (helm-projectile-toggle 1)))
+
+  (when (member 'helm-smex radon-packages)
+
+    ;;; Use Helm mode for M-x, using helm-smex to get sorting by usage.
+    (global-set-key (kbd "M-x") 'helm-smex))
+
+  ;;; Use fuzzy matching.
+  (setq helm-mode-fuzzy-match t)
+
+  ;;; Get rid of the awful background color for buffers corresponding to files
+  ;;; modified outside of Emacs.
+  (when radon-tweak-colors
+    (set-face-background 'helm-buffer-saved-out nil)))
 
 ;;;; Package: Company
 ;; Shows autocompletion suggestions in a pop-up menu while typing. Includes
 ;; interop with CIDER.
 ;;;;
 
-;;; Turn on Company mode everywhere.
-(global-company-mode 1)
-
-;;; Show completions instantly, rather than after half a second.
-(setq company-idle-delay 0)
-
-;;; Show completions after typing a single character, rather than after
-;;; typing three characters.
-(setq company-minimum-prefix-length 1)
-
-;;; Show a maximum of 20 suggestions, rather than 10.
-(setq company-tooltip-limit 20)
-
-;;; Always display the entire suggestion list onscreen, placing it above
-;;; the cursor if necessary.
-(setq company-tooltip-minimum 21)
-
-;;; Always display suggestions in the tooltip, even if there is only one.
-;;; Also, don't display metadata in the echo area. (This conflicts with
-;;; ElDoc mode.)
-(setq company-frontends '(company-pseudo-tooltip-frontend))
-
-;;; Show quick-reference numbers in the tooltip. (Select a completion with
-;;; M-1 through M-0.)
-(setq company-show-numbers t)
-
-;;; Don't prevent non-matching input (which will dismiss the completions
-;;; menu), even if the user interacts explicitly with Company.
-(setq company-require-match nil)
-
-;;; Prevent suggestions from being triggered automatically. In particular,
-;;; this makes it so that:
-;;; - TAB will always complete the current selection.
-;;; - RET will only complete the current selection if the user has explicitly
-;;;   interacted with Company.
-;;; - SPC will never complete the current selection.
-;;;
-;;; Based on https://github.com/company-mode/company-mode/issues/530#issuecomment-226566961
-
-(defun company-complete-if-explicit ()
-  "Complete the current selection, but only if the user has interacted
+(when (member 'company radon-packages)
+
+  ;;; Turn on Company mode everywhere.
+  (global-company-mode 1)
+
+  ;;; Show completions instantly, rather than after half a second.
+  (setq company-idle-delay 0)
+
+  ;;; Show completions after typing a single character, rather than after
+  ;;; typing three characters.
+  (setq company-minimum-prefix-length 1)
+
+  ;;; Show a maximum of 20 suggestions, rather than 10.
+  (setq company-tooltip-limit 20)
+
+  ;;; Always display the entire suggestion list onscreen, placing it above
+  ;;; the cursor if necessary.
+  (setq company-tooltip-minimum 21)
+
+  ;;; Always display suggestions in the tooltip, even if there is only one.
+  ;;; Also, don't display metadata in the echo area. (This conflicts with
+  ;;; ElDoc mode.)
+  (setq company-frontends '(company-pseudo-tooltip-frontend))
+
+  ;;; Show quick-reference numbers in the tooltip. (Select a completion with
+  ;;; M-1 through M-0.)
+  (setq company-show-numbers t)
+
+  ;;; Don't prevent non-matching input (which will dismiss the completions
+  ;;; menu), even if the user interacts explicitly with Company.
+  (setq company-require-match nil)
+
+  ;;; Prevent suggestions from being triggered automatically. In particular,
+  ;;; this makes it so that:
+  ;;; - TAB will always complete the current selection.
+  ;;; - RET will only complete the current selection if the user has explicitly
+  ;;;   interacted with Company.
+  ;;; - SPC will never complete the current selection.
+  ;;;
+  ;;; Based on https://github.com/company-mode/company-mode/issues/530#issuecomment-226566961
+
+  (defun company-complete-if-explicit ()
+    "Complete the current selection, but only if the user has interacted
 explicitly with Company."
-  (interactive)
-  (if (company-explicit-action-p)
-      (company-complete)
-    (call-interactively
-     (key-binding (this-command-keys)))))
-
-;; <return> is for windowed Emacs; RET is for terminal Emacs
-(define-key company-active-map (kbd "<return>") #'company-complete-if-explicit)
-(define-key company-active-map (kbd "RET") #'company-complete-if-explicit)
-(define-key company-active-map (kbd "TAB") #'company-complete-selection)
-(define-key company-active-map (kbd "SPC") nil)
-
-;; Company appears to override the above keymap based on company-auto-complete-chars.
-;; Turning it off ensures we have full control.
-(setq company-auto-complete-chars nil)
-
-;;; Prevent Company completions from being lowercased in the completion menu.
-;;; This appears to only be an issue in comments and strings in Clojure.
-(setq company-dabbrev-downcase nil)
+    (interactive)
+    (if (company-explicit-action-p)
+        (company-complete)
+      (call-interactively
+       (key-binding (this-command-keys)))))
+
+  ;; <return> is for windowed Emacs; RET is for terminal Emacs
+  (define-key company-active-map (kbd "<return>") #'company-complete-if-explicit)
+  (define-key company-active-map (kbd "RET") #'company-complete-if-explicit)
+  (define-key company-active-map (kbd "TAB") #'company-complete-selection)
+  (define-key company-active-map (kbd "SPC") nil)
+
+  ;; Company appears to override the above keymap based on company-auto-complete-chars.
+  ;; Turning it off ensures we have full control.
+  (setq company-auto-complete-chars nil)
+
+  ;;; Prevent Company completions from being lowercased in the completion menu.
+  ;;; This appears to only be an issue in comments and strings in Clojure.
+  (setq company-dabbrev-downcase nil))
 
 ;;;; Package: Company Statistics
 ;; Sorts Company completions by usage. Persistent between Emacs sessions.
 ;;;;
 
-(company-statistics-mode 1)
+(when (member 'company-statistics radon-packages)
+
+  ;;; Turn on company-statistics.
+  (company-statistics-mode 1))
 
 ;;;; Package: ElDoc
 ;; Automatically shows the signature of the function at point in the echo

;;; Solarized Light theme in your terminal emulator).
(setq radon-tweak-colors t)

;;;; User-specific configuration (1 of 4).
(radon-load-user-config "init.local.el")

;;;; Appearance

;;; Disable the "For information about GNU Emacs..." message at startup,
;;; for *all* users.
(defun display-startup-echo-area-message ())

;;; Disable the *About GNU Emacs* buffer at startup, and go straight for
;;; the scratch buffer. This is especially useful because Projectile won't
;;; work in the startup buffer, which is annoying.
(setq inhibit-startup-screen t)

;;; Disable the menu bar, as it doesn't seem very useful...
(menu-bar-mode -1)

;;; When point is on a paren, highlight the matching paren instantly.
(setq show-paren-delay 0)
(show-paren-mode 1)

;;;; Elisp customization

;;; This is required to have access to some basic data manipulation
;;; functions, like cl-every. Why aren't these available by default?
(require 'cl-lib)

;;; Define keybindings for opening and reloading init.el.

(defun open-initfile ()
  (interactive)
  (find-file "~/.emacs.d/init.el")
  "Opens init.el in the current buffer.")

(defun reload-initfile ()
  (interactive)
  (load-file "~/.emacs.d/init.el")
  "Reloads init.el.")

(global-set-key (kbd "<f9>") 'open-initfile)
(global-set-key (kbd "<f12>") 'reload-initfile)

;;;; OSX interop

;;; Add mouse support
;;; Based on http://stackoverflow.com/a/8859057/3538165
(unless (display-graphic-p)
  (xterm-mouse-mode t)
  ;; Enable scrolling.
  (global-set-key [mouse-4]
                  (lambda ()
                    (interactive)
                    (scroll-down 1)))
  (global-set-key [mouse-5]
                  (lambda ()
                    (interactive)
                    (scroll-up 1))))

;;; Add clipboard support
;;; Based on https://gist.github.com/the-kenny/267162

(defun copy-from-osx ()
  (shell-command-to-string "pbpaste"))

(defun paste-to-osx (text &optional push)
  (let ((process-connection-type nil))
    (let ((proc (start-process "pbcopy" "*Messages*" "pbcopy")))
      (process-send-string proc text)
      (process-send-eof proc))))

(setq interprogram-cut-function 'paste-to-osx)
(setq interprogram-paste-function 'copy-from-osx)

;;;; File saving and loading

;;; Put backup files in $HOME/.emacs-backups, rather than in the current
;;; directory.
(setq backup-directory-alist '(("." . "~/.emacs-backups")))

;;; Always use copying to make backup files. This prevents links from
;;; being made to point at the backup file rather than the original.
(setq backup-by-copying t)

;;; Keep multiple numbered backup files, rather than a single unnumbered
;;; backup file.
(setq version-control t)

;;; Delete old backups silently, instead of asking for confirmation.
(setq delete-old-versions t)

;;; Don't make autosave files.
(setq auto-save-default nil)

;;; Trim trailing whitespace on save. This will get rid of end-of-line
;;; whitespace, and reduce the number of blank lines at the end of the
;;; file to one.
(add-hook 'before-save-hook 'delete-trailing-whitespace)

;;; Add a trailing newline if there is not one already, when
;;; saving. This is enabled for default for certain modes, but we want
;;; it everywhere (e.g. when editing .gitignore files).
(setq require-final-newline t)

;;; Automatically reload files that were changed on disk, if they have
;;; not been modified in Emacs since the last time they were saved.
(global-auto-revert-mode 1)

;;; Turn the delay on auto-reloading from 5 seconds down to 1 second.
(setq auto-revert-interval 1)

;;; Follow symlinks without prompting. If this isn't done, then you will
;;; get a prompt every time you edit init.el with F9. (This is assuming
;;; that ~/.emacs.d/init.el is a symlink, which is how the setup script
;;; sets it up.)
(setq vc-follow-symlinks t)

;;; Suppress the 'ls does not support --dired' warning. Doing this instead
;;; of installing a dired-compatibile ls is much easier, although it may
;;; cause problems with e.g. filenames that have leading spaces. If you
;;; have a lot of filenames with leading spaces, though, you probably have
;;; bigger problems ;)
(setq dired-use-ls-dired nil)

;;;; Text format

;;; Don't use tabs for indentation, even in deeply indented lines. (Why
;;; would anyone want their editor to *sometimes* use tabs?)
(setq-default indent-tabs-mode nil)

;;; Sentences end with one space, not two. If you end sentences with
;;; one space, this has two concrete effects on filling with M-q.
;;; Firstly, it allows Emacs to break directly after a sentence.
;;; Secondly, consider the case when the end of a line has an
;;; end-of-sentence period followed by trailing whitespace and when at
;;; least the last word of the sentence is too long for the line. In
;;; that case, this option prevents filling from inserting two spaces
;;; after the period when it is wrapped to the next line.
(setq sentence-end-double-space nil)

;;;; Packages
;; Downloads any packages that are not included with Emacs 24 by default.
;; This allows the setup to run on other systems without any additional
;; setup (other than Emacs 24 being installed).
;;;;

;;; Based on http://batsov.com/articles/2012/02/19/package-management-in-emacs-the-good-the-bad-and-the-ugly/

;;; Initialize the package management system, before we start trying
;;; to add packages.
(require 'package)
(package-initialize)

;;; The default package repository in Emacs doesn't have a lot of the
;;; packages we need, such as Projectile. Therefore, add the melpa-stable
;;; repository. We need melpa (non-stable) for helm-smex.
(add-to-list 'package-archives
             '("melpa-stable" . "https://stable.melpa.org/packages/")
             t) ; this appends to the end of the list
(add-to-list 'package-archives
             '("melpa" . "https://melpa.org/packages/")
             t) ; this appends to the end of the list

(defvar radon-packages
  '(
    ace-jump-mode ; quickly jump to words, characters, or lines onscreen

  "Construct for the mode line that shows [*] if the buffer
has been modified, and whitespace otherwise.")

(when (member 'projectile radon-packages)
  (defvar mode-line-projectile-project
    '("["
      (:eval (projectile-project-name))
      "]")
    "Construct for the mode line that shows the current Projectile
project (or a hyphen if there is no current project) between
brackets."))

(setq-default mode-line-format
              (list
