--- /dev/null
+;;; bind-chord.el --- key-chord binding helper for use-package-chords
+
+;; Copyright (C) 2015-2017 Justin Talbott
+
+;; Author: Justin Talbott <justin@waymondo.com>
+;; Keywords: convenience, tools, extensions
+;; URL: https://github.com/waymondo/use-package-chords
+;; Version: 0.2
+;; Package-Requires: ((bind-key "1.0") (key-chord "0.6"))
+;; Filename: bind-chord.el
+;; License: GNU General Public License version 3, or (at your option) any later version
+;;
+
+;;; Commentary:
+;;
+
+;;; Code:
+
+(require 'bind-key)
+(require 'key-chord)
+
+;;;###autoload
+(defmacro bind-chord (chord command &optional keymap)
+ "Bind CHORD to COMMAND in KEYMAP (`global-map' if not passed)."
+ (let ((key1 (logand 255 (aref chord 0)))
+ (key2 (logand 255 (aref chord 1))))
+ (if (eq key1 key2)
+ `(bind-key (vector 'key-chord ,key1 ,key2) ,command ,keymap)
+ `(progn
+ (bind-key (vector 'key-chord ,key1 ,key2) ,command ,keymap)
+ (bind-key (vector 'key-chord ,key2 ,key1) ,command ,keymap)))))
+
+;;;###autoload
+(defmacro bind-chords (&rest args)
+ "Bind multiple chords at once.
+
+Accepts keyword argument:
+:map - a keymap into which the keybindings should be added
+
+The rest of the arguments are conses of keybinding string and a
+function symbol (unquoted)."
+ (let* ((map (plist-get args :map))
+ (maps (if (listp map) map (list map)))
+ (key-bindings (progn
+ (while (keywordp (car args))
+ (pop args)
+ (pop args))
+ args)))
+ (macroexp-progn
+ (apply
+ #'nconc
+ (mapcar (lambda (form)
+ (if maps
+ (mapcar
+ #'(lambda (m)
+ `(bind-chord ,(car form) ',(cdr form) ,m)) maps)
+ `((bind-chord ,(car form) ',(cdr form)))))
+ key-bindings)))))
+
+(provide 'bind-chord)
+;;; bind-chord.el ends here
--- /dev/null
+;;; use-package-chords.el --- key-chord keyword for use-package
+
+;; Copyright (C) 2015-2017 Justin Talbott
+
+;; Author: Justin Talbott <justin@waymondo.com>
+;; Keywords: convenience, tools, extensions
+;; URL: https://github.com/waymondo/use-package-chords
+;; Version: 0.2
+;; Package-Requires: ((use-package "2.1") (bind-key "1.0") (bind-chord "0.2") (key-chord "0.6"))
+;; Filename: use-package-chords.el
+;; License: GNU General Public License version 3, or (at your option) any later version
+;;
+
+;;; Commentary:
+;;
+;; The `:chords' keyword allows you to define `key-chord' bindings for
+;; `use-package' declarations in the same manner as the `:bind'
+;; keyword.
+;;
+
+;;; Code:
+
+(require 'use-package)
+(require 'bind-chord)
+
+(add-to-list 'use-package-keywords :chords t)
+
+(defalias 'use-package-normalize/:chords 'use-package-normalize-binder)
+
+(defun use-package-handler/:chords (name keyword arg rest state)
+ "Handler for `:chords' keyword in `use-package'."
+ (let* ((commands (remq nil (mapcar #'(lambda (arg)
+ (if (listp arg)
+ (cdr arg)
+ nil)) arg)))
+ (chord-binder
+ (use-package-concat
+ (use-package-process-keywords name
+ (use-package-sort-keywords
+ (use-package-plist-maybe-put rest :defer t))
+ (use-package-plist-append state :commands commands))
+ `((ignore
+ ,(macroexpand
+ `(bind-chords :package ,name ,@arg)))))))
+ (use-package-handler/:preface name keyword chord-binder rest state)))
+
+(provide 'use-package-chords)
+;;; use-package-chords.el ends here
--- /dev/null
+;;; use-package-ensure-system-package.el --- auto install system packages
+
+;; Copyright (C) 2017 Justin Talbott
+
+;; Author: Justin Talbott <justin@waymondo.com>
+;; Keywords: convenience, tools, extensions
+;; URL: https://github.com/waymondo/use-package-ensure-system-package
+;; Version: 0.1
+;; Package-Requires: ((use-package "2.1") (system-packages "0.1"))
+;; Filename: use-package-ensure-system-package.el
+;; License: GNU General Public License version 3, or (at your option) any later version
+;;
+
+;;; Commentary:
+;;
+;; The `:ensure-system-package` keyword allows you to ensure system
+;; binaries exist alongside your `use-package` declarations.
+;;
+
+;;; Code:
+
+(require 'use-package)
+(require 'system-packages)
+
+(add-to-list 'use-package-keywords :ensure-system-package t)
+
+(defun use-package-ensure-system-package-install-command (pack)
+ "Return the default install command for `pack'."
+ (let ((command
+ (cdr (assoc 'install (cdr (assoc system-packages-packagemanager
+ system-packages-supported-package-managers))))))
+ (unless command
+ (error (format "%S not supported in %S" 'install system-packages-packagemanager)))
+ (unless (listp command)
+ (setq command (list command)))
+ (when system-packages-usesudo
+ (setq command (mapcar (lambda (part) (concat "sudo " part)) command)))
+ (setq command (mapconcat 'identity command " && "))
+ (mapconcat 'identity (list command pack) " ")))
+
+(defun use-package-ensure-system-package-consify (arg)
+ "Turn `arg' into a cons of (`package-name' . `install-command')."
+ (cond
+ ((stringp arg)
+ (cons arg (use-package-ensure-system-package-install-command arg)))
+ ((symbolp arg)
+ (cons arg (use-package-ensure-system-package-install-command (symbol-name arg))))
+ ((consp arg) arg)))
+
+(defun use-package-normalize/:ensure-system-package (name-symbol keyword args)
+ "Turn `arg' into a list of cons-es of (`package-name' . `install-command')."
+ (use-package-only-one (symbol-name keyword) args
+ (lambda (label arg)
+ (cond
+ ((and (listp arg) (listp (cdr arg)))
+ (mapcar #'use-package-ensure-system-package-consify arg))
+ (t
+ (list (use-package-ensure-system-package-consify arg)))))))
+
+(defun use-package-handler/:ensure-system-package (name keyword arg rest state)
+ "Execute the handler for `:ensure-system-package' keyword in `use-package'."
+ (let ((body (use-package-process-keywords name rest state)))
+ (use-package-concat
+ (mapcar #'(lambda (cons)
+ `(unless (executable-find (symbol-name ',(car cons)))
+ (async-shell-command ,(cdr cons)))) arg)
+ body)))
+
+(provide 'use-package-ensure-system-package)
+;;; use-package-ensure-system-package.el ends here