Support Vim, Tmux, Emacs with Stow

After moving off of Meta, Dotfiles has a greater responsibility to
manage configs. Vim, Tmux, and Emacs are now within Stow's purview.
This commit is contained in:
William Carroll 2018-09-10 14:51:14 -04:00
parent 8b2fadf477
commit 17ee0e400b
1338 changed files with 330350 additions and 24 deletions

View file

@ -1 +0,0 @@
shared/gpg/.gnupg

View file

@ -0,0 +1,68 @@
;;; ace-window-autoloads.el --- automatically extracted autoloads
;;
;;; Code:
(add-to-list 'load-path (directory-file-name (or (file-name-directory #$) (car load-path))))
;;;### (autoloads nil "ace-window" "ace-window.el" (23377 60991 457690
;;;;;; 292000))
;;; Generated autoloads from ace-window.el
(autoload 'ace-select-window "ace-window" "\
Ace select window.
\(fn)" t nil)
(autoload 'ace-delete-window "ace-window" "\
Ace delete window.
\(fn)" t nil)
(autoload 'ace-swap-window "ace-window" "\
Ace swap window.
\(fn)" t nil)
(autoload 'ace-delete-other-windows "ace-window" "\
Ace delete other windows.
\(fn)" t nil)
(autoload 'ace-window "ace-window" "\
Select a window.
Perform an action based on ARG described below.
By default, behaves like extended `other-window'.
Prefixed with one \\[universal-argument], does a swap between the
selected window and the current window, so that the selected
buffer moves to current window (and current buffer moves to
selected window).
Prefixed with two \\[universal-argument]'s, deletes the selected
window.
\(fn ARG)" t nil)
(defvar ace-window-display-mode nil "\
Non-nil if Ace-Window-Display mode is enabled.
See the `ace-window-display-mode' command
for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `ace-window-display-mode'.")
(custom-autoload 'ace-window-display-mode "ace-window" nil)
(autoload 'ace-window-display-mode "ace-window" "\
Minor mode for showing the ace window key in the mode line.
\(fn &optional ARG)" t nil)
;;;***
;; Local Variables:
;; version-control: never
;; no-byte-compile: t
;; no-update-autoloads: t
;; End:
;;; ace-window-autoloads.el ends here

View file

@ -0,0 +1,2 @@
;;; -*- no-byte-compile: t -*-
(define-package "ace-window" "20180607.1223" "Quickly switch windows." '((avy "0.2.0")))

View file

@ -0,0 +1,802 @@
;;; ace-window.el --- Quickly switch windows. -*- lexical-binding: t -*-
;; Copyright (C) 2015 Free Software Foundation, Inc.
;; Author: Oleh Krehel <ohwoeowho@gmail.com>
;; Maintainer: Oleh Krehel <ohwoeowho@gmail.com>
;; URL: https://github.com/abo-abo/ace-window
;; Package-Version: 20180607.1223
;; Version: 0.9.0
;; Package-Requires: ((avy "0.2.0"))
;; Keywords: window, location
;; This file is part of GNU Emacs.
;; This file 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, 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.
;; For a full copy of the GNU General Public License
;; see <http://www.gnu.org/licenses/>.
;;; Commentary:
;;
;; The main function, `ace-window' is meant to replace `other-window'
;; by assigning each window a short, unique label. When there are only
;; two windows present, `other-window' is called (unless
;; aw-dispatch-always is set non-nil). If there are more, each
;; window will have its first label character highlighted. Once a
;; unique label is typed, ace-window will switch to that window.
;;
;; To setup this package, just add to your .emacs:
;;
;; (global-set-key (kbd "M-o") 'ace-window)
;;
;; replacing "M-o" with an appropriate shortcut.
;;
;; By default, ace-window uses numbers for window labels so the window
;; labeling is intuitively ordered. But if you prefer to type keys on
;; your home row for quicker access, use this setting:
;;
;; (setq aw-keys '(?a ?s ?d ?f ?g ?h ?j ?k ?l))
;;
;; Whenever ace-window prompts for a window selection, it grays out
;; all the window characters, highlighting window labels in red. To
;; disable this behavior, set this:
;;
;; (setq aw-background nil)
;;
;; If you want to know the selection characters ahead of time, turn on
;; `ace-window-display-mode'.
;;
;; When prefixed with one `universal-argument', instead of switching
;; to the selected window, the selected window is swapped with the
;; current one.
;;
;; When prefixed with two `universal-argument', the selected window is
;; deleted instead.
;;; Code:
(require 'avy)
(require 'ring)
(require 'subr-x)
;;* Customization
(defgroup ace-window nil
"Quickly switch current window."
:group 'convenience
:prefix "aw-")
(defcustom aw-keys '(?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9)
"Keys for selecting window."
:type '(repeat character))
(defcustom aw-scope 'global
"The scope used by `ace-window'."
:type '(choice
(const :tag "visible frames" visible)
(const :tag "global" global)
(const :tag "frame" frame)))
(defcustom aw-minibuffer-flag nil
"When non-nil, also display `ace-window-mode' string in the minibuffer when ace-window is active."
:type 'boolean)
(defcustom aw-ignored-buffers '("*Calc Trail*" "*LV*")
"List of buffers and major-modes to ignore when choosing a window from the window list.
Active only when `aw-ignore-on' is non-nil. Windows displaying these
buffers can still be chosen by typing their specific labels."
:type '(repeat string))
(defcustom aw-ignore-on t
"When t, `ace-window' will ignore buffers and major-modes in `aw-ignored-buffers'.
Use M-0 `ace-window' to toggle this value."
:type 'boolean)
(defcustom aw-ignore-current nil
"When t, `ace-window' will ignore `selected-window'."
:type 'boolean)
(defcustom aw-background t
"When t, `ace-window' will dim out all buffers temporarily when used."
:type 'boolean)
(defcustom aw-leading-char-style 'char
"Style of the leading char overlay."
:type '(choice
(const :tag "single char" 'char)
(const :tag "full path" 'path)))
(defcustom aw-dispatch-always nil
"When non-nil, `ace-window' will issue a `read-char' even for one window.
This will make `ace-window' act different from `other-window' for
one or two windows."
:type 'boolean)
(defcustom aw-dispatch-when-more-than 2
"If the number of windows is more than this, activate ace-window-ness."
:type 'integer)
(defcustom aw-reverse-frame-list nil
"When non-nil `ace-window' will order frames for selection in
the reverse of `frame-list'"
:type 'boolean)
(defcustom aw-frame-offset '(13 . 23)
"Increase in pixel offset for new ace-window frames relative to the selected frame.
Its value is an (x-offset . y-offset) pair in pixels."
:type '(cons integer integer))
(defcustom aw-frame-size nil
"Frame size to make new ace-window frames.
Its value is a (width . height) pair in pixels or nil for the default frame size.
(0 . 0) is special and means make the frame size the same as the last selected frame size."
:type '(cons integer integer))
(defcustom aw-char-position 'top-left
"Window positions of the character overlay.
Consider changing this if the overlay tends to overlap with other things."
:type '(choice
(const :tag "top left corner only" 'top-left)
(const :tag "both left corners" 'left)))
;; Must be defined before `aw-make-frame-char' since its :set function references this.
(defvar aw-dispatch-alist
'((?x aw-delete-window "Delete Window")
(?m aw-swap-window "Swap Windows")
(?M aw-move-window "Move Window")
(?j aw-switch-buffer-in-window "Select Buffer")
(?n aw-flip-window)
(?u aw-switch-buffer-other-window "Switch Buffer Other Window")
(?c aw-split-window-fair "Split Fair Window")
(?v aw-split-window-vert "Split Vert Window")
(?b aw-split-window-horz "Split Horz Window")
(?o delete-other-windows "Delete Other Windows")
(?? aw-show-dispatch-help))
"List of actions for `aw-dispatch-default'.
Each action is a list of either:
(char function description) where function takes a single window argument
or
(char function) where function takes no argument and the description is omitted.")
(defun aw-set-make-frame-char (option value)
;; Signal an error if `aw-make-frame-char' is ever set to an invalid
;; or conflicting value.
(when value
(cond ((not (characterp value))
(user-error "`aw-make-frame-char' must be a character, not `%s'" value))
((memq value aw-keys)
(user-error "`aw-make-frame-char' is `%c'; this conflicts with the same character in `aw-keys'" value))
((assq value aw-dispatch-alist)
(user-error "`aw-make-frame-char' is `%c'; this conflicts with the same character in `aw-dispatch-alist'" value))))
(set option value))
(defcustom aw-make-frame-char ?z
"Non-existing ace window label character that triggers creation of a new single-window frame for display."
:set 'aw-set-make-frame-char
:type 'character)
(defface aw-leading-char-face
'((((class color)) (:foreground "red"))
(((background dark)) (:foreground "gray100"))
(((background light)) (:foreground "gray0"))
(t (:foreground "gray100" :underline nil)))
"Face for each window's leading char.")
(defface aw-background-face
'((t (:foreground "gray40")))
"Face for whole window background during selection.")
(defface aw-mode-line-face
'((t (:inherit mode-line-buffer-id)))
"Face used for displaying the ace window key in the mode-line.")
(defface aw-key-face
'((t :inherit font-lock-builtin-face))
"Face used by `aw-show-dispatch-help'.")
;;* Implementation
(defun aw-ignored-p (window)
"Return t if WINDOW should be ignored when choosing from the window list."
(or (and aw-ignore-on
;; Ignore major-modes and buffer-names in `aw-ignored-buffers'.
(or (memq (buffer-local-value 'major-mode (window-buffer window))
aw-ignored-buffers)
(member (buffer-name (window-buffer window)) aw-ignored-buffers)))
;; Ignore selected window if `aw-ignore-current' is non-nil.
(and aw-ignore-current
(equal window (selected-window)))
;; When `ignore-window-parameters' is nil, ignore windows whose
;; `no-other-window or `no-delete-other-windows' parameter is non-nil.
(unless ignore-window-parameters
(cl-case this-command
(ace-select-window (window-parameter window 'no-other-window))
(ace-delete-window (window-parameter window 'no-delete-other-windows))
(ace-delete-other-windows (window-parameter
window 'no-delete-other-windows))))))
(defun aw-window-list ()
"Return the list of interesting windows."
(sort
(cl-remove-if
(lambda (w)
(let ((f (window-frame w)))
(or (not (and (frame-live-p f)
(frame-visible-p f)))
(string= "initial_terminal" (terminal-name f))
(aw-ignored-p w))))
(cl-case aw-scope
(visible
(cl-mapcan #'window-list (visible-frame-list)))
(global
(cl-mapcan #'window-list (frame-list)))
(frame
(window-list))
(t
(error "Invalid `aw-scope': %S" aw-scope))))
'aw-window<))
(defvar aw-overlays-back nil
"Hold overlays for when `aw-background' is t.")
(defvar ace-window-mode nil
"Minor mode during the selection process.")
;; register minor mode
(or (assq 'ace-window-mode minor-mode-alist)
(nconc minor-mode-alist
(list '(ace-window-mode ace-window-mode))))
(defvar aw-empty-buffers-list nil
"Store the read-only empty buffers which had to be modified.
Modify them back eventually.")
(defun aw--done ()
"Clean up mode line and overlays."
;; mode line
(aw-set-mode-line nil)
;; background
(mapc #'delete-overlay aw-overlays-back)
(setq aw-overlays-back nil)
(avy--remove-leading-chars)
(dolist (b aw-empty-buffers-list)
(with-current-buffer b
(when (string= (buffer-string) " ")
(let ((inhibit-read-only t))
(delete-region (point-min) (point-max))))))
(setq aw-empty-buffers-list nil))
(defun aw--overlay-str (wnd pos path)
"Return the replacement text for an overlay in WND at POS,
accessible by typing PATH."
(let ((old-str (or
(ignore-errors
(with-selected-window wnd
(buffer-substring pos (1+ pos))))
"")))
(concat
(cl-case aw-leading-char-style
(char
(string (avy--key-to-char (car (last path)))))
(path
(mapconcat
(lambda (x) (string (avy--key-to-char x)))
(reverse path)
""))
(t
(error "Bad `aw-leading-char-style': %S"
aw-leading-char-style)))
(cond ((string-equal old-str "\t")
(make-string (1- tab-width) ?\ ))
((string-equal old-str "\n")
"\n")
(t
(make-string
(max 0 (1- (string-width old-str)))
?\ ))))))
(defun aw--lead-overlay (path leaf)
"Create an overlay using PATH at LEAF.
LEAF is (PT . WND)."
(let ((wnd (cdr leaf)))
(with-selected-window wnd
(when (= 0 (buffer-size))
(push (current-buffer) aw-empty-buffers-list)
(let ((inhibit-read-only t))
(insert " ")))
(let* ((pt (car leaf))
(ol (make-overlay pt (1+ pt) (window-buffer wnd))))
(overlay-put ol 'display (aw--overlay-str wnd pt path))
(overlay-put ol 'face 'aw-leading-char-face)
(overlay-put ol 'window wnd)
(push ol avy--overlays-lead))
(when (eq aw-char-position 'left)
(let* ((pt
(save-excursion
;; Move to the start of the last visible line in the buffer.
(move-to-window-line -1)
(move-beginning-of-line nil)
;; If this line is empty, use the previous line so we
;; have space for the overlay.
(when (equal (point) (point-max))
(forward-line -1))
(point)))
(ol (make-overlay pt (1+ pt) (window-buffer wnd))))
(overlay-put ol 'display (aw--overlay-str wnd pt path))
(overlay-put ol 'face 'aw-leading-char-face)
(overlay-put ol 'window wnd)
(push ol avy--overlays-lead))))))
(defun aw--make-backgrounds (wnd-list)
"Create a dim background overlay for each window on WND-LIST."
(when aw-background
(setq aw-overlays-back
(mapcar (lambda (w)
(let ((ol (make-overlay
(window-start w)
(window-end w)
(window-buffer w))))
(overlay-put ol 'face 'aw-background-face)
ol))
wnd-list))))
(define-obsolete-variable-alias
'aw-flip-keys 'aw--flip-keys "0.1.0"
"Use `aw-dispatch-alist' instead.")
(defvar aw-dispatch-function 'aw-dispatch-default
"Function to call when a character not in `aw-keys' is pressed.")
(defvar aw-action nil
"Function to call at the end of `aw-select'.")
(defun aw-set-mode-line (str)
"Set mode line indicator to STR."
(setq ace-window-mode str)
(when (and aw-minibuffer-flag ace-window-mode)
(message "%s" (string-trim-left str)))
(force-mode-line-update))
(defun aw--dispatch-action (char)
"Return item from `aw-dispatch-alist' matching CHAR."
(assoc char aw-dispatch-alist))
(defun aw-make-frame ()
"Make a new Emacs frame using the values of `aw-frame-size' and `aw-frame-offset'."
(make-frame
(delq nil
(list
;; This first parameter is important because an
;; aw-dispatch-alist command may not want to leave this
;; frame with input focus. If it is given focus, the
;; command may not be able to return focus to a different
;; frame since this is done asynchronously by the window
;; manager.
'(no-focus-on-map . t)
(when aw-frame-size
(cons 'width
(if (zerop (car aw-frame-size))
(frame-width)
(car aw-frame-size))))
(when aw-frame-size
(cons 'height
(if (zerop (cdr aw-frame-size))
(frame-height)
(car aw-frame-size))))
(cons 'left (+ (car aw-frame-offset)
(car (frame-position))))
(cons 'top (+ (cdr aw-frame-offset)
(cdr (frame-position))))))))
(defun aw-use-frame (window)
"Create a new frame using the contents of WINDOW.
The new frame is set to the same size as the previous frame, offset by
`aw-frame-offset' (x . y) pixels."
(aw-switch-to-window window)
(aw-make-frame))
(defun aw-clean-up-avy-current-path ()
"Edit `avy-current-path' so only window label characters remain."
;; Remove any possible ace-window command char that may
;; precede the last specified window label, so
;; functions can use `avy-current-path' as the chosen
;; window label.
(when (and (> (length avy-current-path) 0)
(assq (aref avy-current-path 0) aw-dispatch-alist))
(setq avy-current-path (substring avy-current-path 1))))
(defun aw-dispatch-default (char)
"Perform an action depending on CHAR."
(cond ((and (fboundp 'avy-mouse-event-window)
(avy-mouse-event-window char)))
((= char (aref (kbd "C-g") 0))
(throw 'done 'exit))
((= char aw-make-frame-char)
;; Make a new frame and perform any action on its window.
(let ((start-win (selected-window))
(end-win (frame-selected-window (aw-make-frame))))
(if aw-action
;; Action must be called from the start-win. The action
;; determines which window to leave selected.
(progn (select-frame-set-input-focus (window-frame start-win))
(funcall aw-action end-win))
;; Select end-win when no action
(aw-switch-to-window end-win)))
(throw 'done 'exit))
(t
(let ((action (aw--dispatch-action char)))
(if action
(cl-destructuring-bind (_key fn &optional description) action
(if (and fn description)
(prog1 (setq aw-action fn)
(aw-set-mode-line (format " Ace - %s" description)))
(funcall fn)
(throw 'done 'exit)))
(aw-clean-up-avy-current-path)
;; Prevent any char from triggering an avy dispatch command.
(let ((avy-dispatch-alist))
(avy-handler-default char)))))))
(defun aw-select (mode-line &optional action)
"Return a selected other window.
Amend MODE-LINE to the mode line for the duration of the selection."
(setq aw-action action)
(let ((start-window (selected-window))
(next-window-scope (cl-case aw-scope
('visible 'visible)
('global 'visible)
('frame 'frame)))
(wnd-list (aw-window-list))
window)
(setq window
(cond ((<= (length wnd-list) 1)
(when aw-dispatch-always
(setq aw-action
(unwind-protect
(catch 'done
(funcall aw-dispatch-function (read-char)))
(aw--done)))
(when (eq aw-action 'exit)
(setq aw-action nil)))
(or (car wnd-list) start-window))
((and (<= (length wnd-list) aw-dispatch-when-more-than)
(not aw-dispatch-always)
(not aw-ignore-current))
(let ((wnd (next-window nil nil next-window-scope)))
(while (and (or (not (memq wnd wnd-list))
(aw-ignored-p wnd))
(not (equal wnd start-window)))
(setq wnd (next-window wnd nil next-window-scope)))
wnd))
(t
(let ((candidate-list
(mapcar (lambda (wnd)
(cons (aw-offset wnd) wnd))
wnd-list)))
(aw--make-backgrounds wnd-list)
(aw-set-mode-line mode-line)
;; turn off helm transient map
(remove-hook 'post-command-hook 'helm--maybe-update-keymap)
(unwind-protect
(let* ((avy-handler-function aw-dispatch-function)
(avy-translate-char-function #'identity)
(res (avy-read (avy-tree candidate-list aw-keys)
#'aw--lead-overlay
#'avy--remove-leading-chars)))
(if (eq res 'exit)
(setq aw-action nil)
(or (cdr res)
start-window)))
(aw--done))))))
(if aw-action
(funcall aw-action window)
window)))
;;* Interactive
;;;###autoload
(defun ace-select-window ()
"Ace select window."
(interactive)
(aw-select " Ace - Window"
#'aw-switch-to-window))
;;;###autoload
(defun ace-delete-window ()
"Ace delete window."
(interactive)
(aw-select " Ace - Delete Window"
#'aw-delete-window))
;;;###autoload
(defun ace-swap-window ()
"Ace swap window."
(interactive)
(aw-select " Ace - Swap Window"
#'aw-swap-window))
;;;###autoload
(defun ace-delete-other-windows ()
"Ace delete other windows."
(interactive)
(aw-select " Ace - Delete Other Windows"
#'delete-other-windows))
(define-obsolete-function-alias
'ace-maximize-window 'ace-delete-other-windows "0.10.0")
;;;###autoload
(defun ace-window (arg)
"Select a window.
Perform an action based on ARG described below.
By default, behaves like extended `other-window'.
Prefixed with one \\[universal-argument], does a swap between the
selected window and the current window, so that the selected
buffer moves to current window (and current buffer moves to
selected window).
Prefixed with two \\[universal-argument]'s, deletes the selected
window."
(interactive "p")
(cl-case arg
(0
(setq aw-ignore-on
(not aw-ignore-on))
(ace-select-window))
(4 (ace-swap-window))
(16 (ace-delete-window))
(t (ace-select-window))))
;;* Utility
(unless (fboundp 'frame-position)
(defun frame-position (&optional frame)
(cons (frame-parameter frame 'left)
(frame-parameter frame 'top))))
(defun aw-window< (wnd1 wnd2)
"Return true if WND1 is less than WND2.
This is determined by their respective window coordinates.
Windows are numbered top down, left to right."
(let ((f1 (window-frame wnd1))
(f2 (window-frame wnd2))
(e1 (window-edges wnd1))
(e2 (window-edges wnd2)))
(cond ((< (car (frame-position f1)) (car (frame-position f2)))
(not aw-reverse-frame-list))
((> (car (frame-position f1)) (car (frame-position f2)))
aw-reverse-frame-list)
((< (car e1) (car e2))
t)
((> (car e1) (car e2))
nil)
((< (cadr e1) (cadr e2))
t))))
(defvar aw--window-ring (make-ring 10)
"Hold the window switching history.")
(defun aw--push-window (window)
"Store WINDOW to `aw--window-ring'."
(when (or (zerop (ring-length aw--window-ring))
(not (equal
(ring-ref aw--window-ring 0)
window)))
(ring-insert aw--window-ring (selected-window))))
(defun aw--pop-window ()
"Return the removed top of `aw--window-ring'."
(let (res)
(condition-case nil
(while (or (not (window-live-p
(setq res (ring-remove aw--window-ring 0))))
(equal res (selected-window))))
(error
(if (= (length (aw-window-list)) 2)
(progn
(other-window 1)
(setq res (selected-window)))
(error "No previous windows stored"))))
res))
(defun aw-switch-to-window (window)
"Switch to the window WINDOW."
(let ((frame (window-frame window)))
(aw--push-window (selected-window))
(when (and (frame-live-p frame)
(not (eq frame (selected-frame))))
(select-frame-set-input-focus frame))
(if (window-live-p window)
(select-window window)
(error "Got a dead window %S" window))))
(defun aw-flip-window ()
"Switch to the window you were previously in."
(interactive)
(aw-switch-to-window (aw--pop-window)))
(defun aw-show-dispatch-help ()
"Display action shortucts in echo area."
(interactive)
(message "%s" (mapconcat
(lambda (action)
(cl-destructuring-bind (key fn &optional description) action
(format "%s: %s"
(propertize
(char-to-string key)
'face 'aw-key-face)
(or description fn))))
aw-dispatch-alist
"\n"))
;; Prevent this from replacing any help display
;; in the minibuffer.
(let (aw-minibuffer-flag)
(mapc #'delete-overlay aw-overlays-back)
(call-interactively 'ace-window)))
(defun aw-delete-window (window)
"Delete window WINDOW."
(let ((frame (window-frame window)))
(when (and (frame-live-p frame)
(not (eq frame (selected-frame))))
(select-frame-set-input-focus (window-frame window)))
(if (= 1 (length (window-list)))
(delete-frame frame)
(if (window-live-p window)
(delete-window window)
(error "Got a dead window %S" window)))))
(defun aw-switch-buffer-in-window (window)
"Select buffer in WINDOW."
(aw-switch-to-window window)
(aw--switch-buffer))
(declare-function ivy-switch-buffer "ext:ivy")
(defun aw--switch-buffer ()
(cond ((bound-and-true-p ivy-mode)
(ivy-switch-buffer))
((bound-and-true-p ido-mode)
(ido-switch-buffer))
(t
(call-interactively 'switch-to-buffer))))
(defcustom aw-swap-invert nil
"When non-nil, the other of the two swapped windows gets the point."
:type 'boolean)
(defun aw-swap-window (window)
"Swap buffers of current window and WINDOW."
(cl-labels ((swap-windows (window1 window2)
"Swap the buffers of WINDOW1 and WINDOW2."
(let ((buffer1 (window-buffer window1))
(buffer2 (window-buffer window2)))
(set-window-buffer window1 buffer2)
(set-window-buffer window2 buffer1)
(select-window window2))))
(let ((frame (window-frame window))
(this-window (selected-window)))
(when (and (frame-live-p frame)
(not (eq frame (selected-frame))))
(select-frame-set-input-focus (window-frame window)))
(when (and (window-live-p window)
(not (eq window this-window)))
(aw--push-window this-window)
(if aw-swap-invert
(swap-windows window this-window)
(swap-windows this-window window))))))
(defun aw-move-window (window)
"Move the current buffer to WINDOW.
Switch the current window to the previous buffer."
(let ((buffer (current-buffer)))
(switch-to-buffer (other-buffer))
(aw-switch-to-window window)
(switch-to-buffer buffer)))
(defun aw-split-window-vert (window)
"Split WINDOW vertically."
(select-window window)
(split-window-vertically))
(defun aw-split-window-horz (window)
"Split WINDOW horizontally."
(select-window window)
(split-window-horizontally))
(defcustom aw-fair-aspect-ratio 2
"The aspect ratio to aim for when splitting windows.
Sizes are based on the number of characters, not pixels.
Increase to prefer wider windows, or decrease for taller windows."
:type 'number)
(defun aw-split-window-fair (window)
"Split WINDOW vertically or horizontally, based on its current dimensions.
Modify `aw-fair-aspect-ratio' to tweak behavior."
(let ((w (window-body-width window))
(h (window-body-height window)))
(if (< (* h aw-fair-aspect-ratio) w)
(aw-split-window-horz window)
(aw-split-window-vert window))))
(defun aw-switch-buffer-other-window (window)
"Switch buffer in WINDOW without selecting WINDOW."
(aw-switch-to-window window)
(aw--switch-buffer)
(aw-flip-window))
(defun aw-offset (window)
"Return point in WINDOW that's closest to top left corner.
The point is writable, i.e. it's not part of space after newline."
(let ((h (window-hscroll window))
(beg (window-start window))
(end (window-end window))
(inhibit-field-text-motion t))
(with-current-buffer
(window-buffer window)
(save-excursion
(goto-char beg)
(while (and (< (point) end)
(< (- (line-end-position)
(line-beginning-position))
h))
(forward-line))
(+ (point) h)))))
;;* Mode line
;;;###autoload
(define-minor-mode ace-window-display-mode
"Minor mode for showing the ace window key in the mode line."
:global t
(if ace-window-display-mode
(progn
(aw-update)
(set-default
'mode-line-format
`((ace-window-display-mode
(:eval (window-parameter (selected-window) 'ace-window-path)))
,@(assq-delete-all
'ace-window-display-mode
(default-value 'mode-line-format))))
(force-mode-line-update t)
(add-hook 'window-configuration-change-hook 'aw-update)
;; Add at the end so does not precede select-frame call.
(add-hook 'after-make-frame-functions (lambda (_) (aw-update)) t))
(set-default
'mode-line-format
(assq-delete-all
'ace-window-display-mode
(default-value 'mode-line-format)))
(remove-hook 'window-configuration-change-hook 'aw-update)
(remove-hook 'after-make-frame-functions 'aw-update)))
(defun aw-update ()
"Update ace-window-path window parameter for all windows.
Ensure all windows are labeled so the user can select a specific
one, even from the set of windows typically ignored when making a
window list."
(let ((aw-ignore-on)
(aw-ignore-current)
(ignore-window-parameters t))
(avy-traverse
(avy-tree (aw-window-list) aw-keys)
(lambda (path leaf)
(set-window-parameter
leaf 'ace-window-path
(propertize
(apply #'string (reverse path))
'face 'aw-mode-line-face))))))
(provide 'ace-window)
;;; ace-window.el ends here

View file

@ -0,0 +1,35 @@
;;; add-node-modules-path-autoloads.el --- automatically extracted autoloads
;;
;;; Code:
(add-to-list 'load-path (directory-file-name (or (file-name-directory #$) (car load-path))))
;;;### (autoloads nil "add-node-modules-path" "add-node-modules-path.el"
;;;;;; (23438 54284 226170 718000))
;;; Generated autoloads from add-node-modules-path.el
(defvar add-node-modules-path-debug nil "\
Enable verbose output when non nil.")
(custom-autoload 'add-node-modules-path-debug "add-node-modules-path" t)
(defvar add-node-modules-max-depth 20 "\
Max depth to look for node_modules.")
(custom-autoload 'add-node-modules-max-depth "add-node-modules-path" t)
(autoload 'add-node-modules-path "add-node-modules-path" "\
Search the current buffer's parent directories for `node_modules/.bin`.
Traverse the directory structure up, until reaching the user's home directory,
or hitting add-node-modules-max-depth.
Any path found is added to the `exec-path'.
\(fn)" t nil)
;;;***
;; Local Variables:
;; version-control: never
;; no-byte-compile: t
;; no-update-autoloads: t
;; End:
;;; add-node-modules-path-autoloads.el ends here

View file

@ -0,0 +1,2 @@
;;; -*- no-byte-compile: t -*-
(define-package "add-node-modules-path" "20180710.2342" "Add node_modules to your exec-path" 'nil :commit "f31e69ccb681f882aebb806ce6e9478e3ac39708" :keywords '("javascript" "node" "node_modules" "eslint") :authors '(("Neri Marschik" . "marschik_neri@cyberagent.co.jp")) :maintainer '("Neri Marschik" . "marschik_neri@cyberagent.co.jp") :url "https://github.com/codesuki/add-node-modules-path")

View file

@ -0,0 +1,79 @@
;;; add-node-modules-path.el --- Add node_modules to your exec-path
;; Copyright (C) 2016 Neri Marschik
;; This package uses the MIT License.
;; See the LICENSE file.
;; Author: Neri Marschik <marschik_neri@cyberagent.co.jp>
;; Version: 1.0
;; Package-Version: 20180710.2342
;; Package-Requires: ()
;; Keywords: javascript, node, node_modules, eslint
;; URL: https://github.com/codesuki/add-node-modules-path
;;; Commentary:
;;
;; This file provides `add-node-modules-path', which searches
;; the current files parent directories for the `node_modules/.bin/' directory
;; and adds it to the buffer local `exec-path'.
;; This allows Emacs to find project based installs of e.g. eslint.
;;
;; Usage:
;; M-x add-node-modules-path
;;
;; To automatically run it when opening a new buffer:
;; (Choose depending on your favorite mode.)
;;
;; (eval-after-load 'js-mode
;; '(add-hook 'js-mode-hook #'add-node-modules-path))
;;
;; (eval-after-load 'js2-mode
;; '(add-hook 'js2-mode-hook #'add-node-modules-path))
;;; Code:
;;;###autoload
(defcustom add-node-modules-path-debug nil
"Enable verbose output when non nil."
:type 'boolean)
;;;###autoload
(defcustom add-node-modules-max-depth 20
"Max depth to look for node_modules."
:type 'integer)
;;;###autoload
(defun add-node-modules-path ()
"Search the current buffer's parent directories for `node_modules/.bin`.
Traverse the directory structure up, until reaching the user's home directory,
or hitting add-node-modules-max-depth.
Any path found is added to the `exec-path'."
(interactive)
(let* ((default-dir (expand-file-name default-directory))
(file (or (buffer-file-name) default-dir))
(home (expand-file-name "~"))
(iterations add-node-modules-max-depth)
(root (directory-file-name (or (and (buffer-file-name) (file-name-directory (buffer-file-name))) default-dir)))
(roots '()))
(while (and root (> iterations 0))
(setq iterations (1- iterations))
(let ((bindir (expand-file-name "node_modules/.bin/" root)))
(when (file-directory-p bindir)
(add-to-list 'roots bindir)))
(if (string= root home)
(setq root nil)
(setq root (directory-file-name (file-name-directory root)))))
(if roots
(progn
(make-local-variable 'exec-path)
(while roots
(add-to-list 'exec-path (car roots))
(when add-node-modules-path-debug
(message (concat "added " (car roots) " to exec-path")))
(setq roots (cdr roots))))
(when add-node-modules-path-debug
(message (concat "node_modules/.bin not found for " file))))))
(provide 'add-node-modules-path)
;;; add-node-modules-path.el ends here

View file

@ -0,0 +1,94 @@
;;; alert-autoloads.el --- automatically extracted autoloads
;;
;;; Code:
(add-to-list 'load-path (directory-file-name (or (file-name-directory #$) (car load-path))))
;;;### (autoloads nil "alert" "alert.el" (23377 61297 758177 48000))
;;; Generated autoloads from alert.el
(autoload 'alert-add-rule "alert" "\
Programmatically add an alert configuration rule.
Normally, users should custoimze `alert-user-configuration'.
This facility is for module writers and users that need to do
things the Lisp way.
Here is a rule the author currently uses with ERC, so that the
fringe gets colored whenever people chat on BitlBee:
\(alert-add-rule :status \\='(buried visible idle)
:severity \\='(moderate high urgent)
:mode \\='erc-mode
:predicate
#\\='(lambda (info)
(string-match (concat \"\\\\`[^&].*@BitlBee\\\\\\='\")
(erc-format-target-and/or-network)))
:persistent
#\\='(lambda (info)
;; If the buffer is buried, or the user has been
;; idle for `alert-reveal-idle-time' seconds,
;; make this alert persistent. Normally, alerts
;; become persistent after
;; `alert-persist-idle-time' seconds.
(memq (plist-get info :status) \\='(buried idle)))
:style \\='fringe
:continue t)
\(fn &key SEVERITY STATUS MODE CATEGORY TITLE MESSAGE PREDICATE ICON (style alert-default-style) PERSISTENT CONTINUE NEVER-PERSIST APPEND)" nil nil)
(autoload 'alert "alert" "\
Alert the user that something has happened.
MESSAGE is what the user will see. You may also use keyword
arguments to specify additional details. Here is a full example:
\(alert \"This is a message\"
:severity \\='high ;; The default severity is `normal'
:title \"Title\" ;; An optional title
:category \\='example ;; A symbol to identify the message
:mode \\='text-mode ;; Normally determined automatically
:buffer (current-buffer) ;; This is the default
:data nil ;; Unused by alert.el itself
:persistent nil ;; Force the alert to be persistent;
;; it is best not to use this
:never-persist nil ;; Force this alert to never persist
:id \\='my-id) ;; Used to replace previous message of
;; the same id in styles that support it
:style \\='fringe) ;; Force a given style to be used;
;; this is only for debugging!
If no :title is given, the buffer-name of :buffer is used. If
:buffer is nil, it is the current buffer at the point of call.
:data is an opaque value which modules can pass through to their
own styles if they wish.
Here are some more typical examples of usage:
;; This is the most basic form usage
(alert \"This is an alert\")
;; You can adjust the severity for more important messages
(alert \"This is an alert\" :severity \\='high)
;; Or decrease it for purely informative ones
(alert \"This is an alert\" :severity \\='trivial)
;; Alerts can have optional titles. Otherwise, the title is the
;; buffer-name of the (current-buffer) where the alert originated.
(alert \"This is an alert\" :title \"My Alert\")
;; Further, alerts can have categories. This allows users to
;; selectively filter on them.
(alert \"This is an alert\" :title \"My Alert\"
:category \\='some-category-or-other)
\(fn MESSAGE &key (severity (quote normal)) TITLE ICON CATEGORY BUFFER MODE DATA STYLE PERSISTENT NEVER-PERSIST ID)" nil nil)
;;;***
;; Local Variables:
;; version-control: never
;; no-byte-compile: t
;; no-update-autoloads: t
;; End:
;;; alert-autoloads.el ends here

View file

@ -0,0 +1,2 @@
;;; -*- no-byte-compile: t -*-
(define-package "alert" "20180403.38" "Growl-style notification system for Emacs" '((gntp "0.1") (log4e "0.3.0")))

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,59 @@
;;; all-the-icons-autoloads.el --- automatically extracted autoloads
;;
;;; Code:
(add-to-list 'load-path (directory-file-name (or (file-name-directory #$) (car load-path))))
;;;### (autoloads nil "all-the-icons" "all-the-icons.el" (23377 61284
;;;;;; 887385 430000))
;;; Generated autoloads from all-the-icons.el
(autoload 'all-the-icons-icon-for-file "all-the-icons" "\
Get the formatted icon for FILE.
ARG-OVERRIDES should be a plist containining `:height',
`:v-adjust' or `:face' properties like in the normal icon
inserting functions.
\(fn FILE &rest ARG-OVERRIDES)" nil nil)
(autoload 'all-the-icons-icon-for-mode "all-the-icons" "\
Get the formatted icon for MODE.
ARG-OVERRIDES should be a plist containining `:height',
`:v-adjust' or `:face' properties like in the normal icon
inserting functions.
\(fn MODE &rest ARG-OVERRIDES)" nil nil)
(autoload 'all-the-icons--icon-info-for-buffer "all-the-icons" "\
Get icon info for the current buffer.
When F is provided, the info function is calculated with the format
`all-the-icons-icon-%s-for-file' or `all-the-icons-icon-%s-for-mode'.
\(fn &optional F)" nil nil)
(autoload 'all-the-icons-install-fonts "all-the-icons" "\
Helper function to download and install the latests fonts based on OS.
When PFX is non-nil, ignore the prompt and just install
\(fn &optional PFX)" t nil)
(autoload 'all-the-icons-insert "all-the-icons" "\
Interactive icon insertion function.
When Prefix ARG is non-nil, insert the propertized icon.
When FAMILY is non-nil, limit the candidates to the icon set matching it.
\(fn &optional ARG FAMILY)" t nil)
;;;***
;;;### (autoloads nil nil ("all-the-icons-faces.el" "all-the-icons-pkg.el")
;;;;;; (23377 61284 888696 545000))
;;;***
;; Local Variables:
;; version-control: never
;; no-byte-compile: t
;; no-update-autoloads: t
;; End:
;;; all-the-icons-autoloads.el ends here

View file

@ -0,0 +1,225 @@
;;; all-the-icons-faces.el --- A module of faces for all-the-icons
;; Copyright (C) 2016 Dominic Charlesworth <dgc336@gmail.com>
;; Author: Dominic Charlesworth <dgc336@gmail.com>
;; Version: 1.0.0
;; Package-Requires: ((emacs "24.3"))
;; URL: https://github.com/domtronn/all-the-icons.el
;; Keywords: convenient, lisp
;; 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/>.
;;; Commentary:
;; This file contains all of the faces used by the package for
;; colouring icons
;;; Code:
(defgroup all-the-icons-faces nil
"Manage how All The Icons icons are coloured and themed."
:prefix "all-the-icons-"
:group 'tools
:group 'all-the-icons)
;; red
(defface all-the-icons-red
'((((background dark)) :foreground "#AC4142")
(((background light)) :foreground "#AC4142"))
"Face for red icons"
:group 'all-the-icons-faces)
(defface all-the-icons-lred
'((((background dark)) :foreground "#EB595A")
(((background light)) :foreground "#EB595A"))
"Face for lred icons"
:group 'all-the-icons-faces)
(defface all-the-icons-dred
'((((background dark)) :foreground "#843031")
(((background light)) :foreground "#843031"))
"Face for dred icons"
:group 'all-the-icons-faces)
(defface all-the-icons-red-alt
'((((background dark)) :foreground "#ce5643")
(((background light)) :foreground "#843031"))
"Face for dred icons"
:group 'all-the-icons-faces)
;; green
(defface all-the-icons-green
'((((background dark)) :foreground "#90A959")
(((background light)) :foreground "#90A959"))
"Face for green icons"
:group 'all-the-icons-faces)
(defface all-the-icons-lgreen
'((((background dark)) :foreground "#C6E87A")
(((background light)) :foreground "#3D6837"))
"Face for lgreen icons"
:group 'all-the-icons-faces)
(defface all-the-icons-dgreen
'((((background dark)) :foreground "#6D8143")
(((background light)) :foreground "#6D8143"))
"Face for dgreen icons"
:group 'all-the-icons-faces)
;; yellow
(defface all-the-icons-yellow
'((((background dark)) :foreground "#FFD446")
(((background light)) :foreground "#FFCC0E"))
"Face for yellow icons"
:group 'all-the-icons-faces)
(defface all-the-icons-lyellow
'((((background dark)) :foreground "#FFC16D")
(((background light)) :foreground "#FF9300"))
"Face for lyellow icons"
:group 'all-the-icons-faces)
(defface all-the-icons-dyellow
'((((background dark)) :foreground "#B48D56")
(((background light)) :foreground "#B48D56"))
"Face for dyellow icons"
:group 'all-the-icons-faces)
;; blue
(defface all-the-icons-blue
'((((background dark)) :foreground "#6A9FB5")
(((background light)) :foreground "#6A9FB5"))
"Face for blue icons"
:group 'all-the-icons-faces)
(defface all-the-icons-blue-alt
'((((background dark)) :foreground "#2188b6")
(((background light)) :foreground "#2188b6"))
"Face for blue icons"
:group 'all-the-icons-faces)
(defface all-the-icons-lblue
'((((background dark)) :foreground "#8FD7F4")
(((background light)) :foreground "#677174"))
"Face for lblue icons"
:group 'all-the-icons-faces)
(defface all-the-icons-dblue
'((((background dark)) :foreground "#446674")
(((background light)) :foreground "#446674"))
"Face for dblue icons"
:group 'all-the-icons-faces)
;; maroon
(defface all-the-icons-maroon
'((((background dark)) :foreground "#8F5536")
(((background light)) :foreground "#8F5536"))
"Face for maroon icons"
:group 'all-the-icons-faces)
(defface all-the-icons-lmaroon
'((((background dark)) :foreground "#CE7A4E")
(((background light)) :foreground "#CE7A4E"))
"Face for lmaroon icons"
:group 'all-the-icons-faces)
(defface all-the-icons-dmaroon
'((((background dark)) :foreground "#72584B")
(((background light)) :foreground "#72584B"))
"Face for dmaroon icons"
:group 'all-the-icons-faces)
;; purple
(defface all-the-icons-purple
'((((background dark)) :foreground "#AA759F")
(((background light)) :foreground "#68295B"))
"Face for purple icons"
:group 'all-the-icons-faces)
(defface all-the-icons-lpurple
'((((background dark)) :foreground "#E69DD6")
(((background light)) :foreground "#E69DD6"))
"Face for lpurple icons"
:group 'all-the-icons-faces)
(defface all-the-icons-dpurple
'((((background dark)) :foreground "#694863")
(((background light)) :foreground "#694863"))
"Face for dpurple icons"
:group 'all-the-icons-faces)
;; orange
(defface all-the-icons-orange
'((((background dark)) :foreground "#D4843E")
(((background light)) :foreground "#D4843E"))
"Face for orange icons"
:group 'all-the-icons-faces)
(defface all-the-icons-lorange
'((((background dark)) :foreground "#FFA500")
(((background light)) :foreground "#FFA500"))
"Face for lorange icons"
:group 'all-the-icons-faces)
(defface all-the-icons-dorange
'((((background dark)) :foreground "#915B2D")
(((background light)) :foreground "#915B2D"))
"Face for dorange icons"
:group 'all-the-icons-faces)
;; cyan
(defface all-the-icons-cyan
'((((background dark)) :foreground "#75B5AA")
(((background light)) :foreground "#75B5AA"))
"Face for cyan icons"
:group 'all-the-icons-faces)
(defface all-the-icons-cyan-alt
'((((background dark)) :foreground "#61dafb")
(((background light)) :foreground "#0595bd"))
"Face for cyan icons"
:group 'all-the-icons-faces)
(defface all-the-icons-lcyan
'((((background dark)) :foreground "#A5FDEC")
(((background light)) :foreground "#2C7D6E"))
"Face for lcyan icons"
:group 'all-the-icons-faces)
(defface all-the-icons-dcyan
'((((background dark)) :foreground "#48746D")
(((background light)) :foreground "#48746D"))
"Face for dcyan icons"
:group 'all-the-icons-faces)
;; pink
(defface all-the-icons-pink
'((((background dark)) :foreground "#F2B4B8")
(((background light)) :foreground "#FC505B"))
"Face for pink icons"
:group 'all-the-icons-faces)
(defface all-the-icons-lpink
'((((background dark)) :foreground "#FFBDC1")
(((background light)) :foreground "#FF505B"))
"Face for lpink icons"
:group 'all-the-icons-faces)
(defface all-the-icons-dpink
'((((background dark)) :foreground "#B18286")
(((background light)) :foreground "#7E5D5F"))
"Face for dpink icons"
:group 'all-the-icons-faces)
;; silver
(defface all-the-icons-silver
'((((background dark)) :foreground "#716E68")
(((background light)) :foreground "#716E68"))
"Face for silver icons"
:group 'all-the-icons-faces)
(defface all-the-icons-lsilver
'((((background dark)) :foreground "#B9B6AA")
(((background light)) :foreground "#7F7869"))
"Face for lsilver icons"
:group 'all-the-icons-faces)
(defface all-the-icons-dsilver
'((((background dark)) :foreground "#838484")
(((background light)) :foreground "#838484"))
"Face for dsilver icons"
:group 'all-the-icons-faces)
(provide 'all-the-icons-faces)
;;; all-the-icons-faces.el ends here

View file

@ -0,0 +1,9 @@
(define-package "all-the-icons" "20180125.757" "A library for inserting Developer icons"
'((emacs "24.3")
(memoize "1.0.1"))
:keywords
'("convenient" "lisp")
:url "https://github.com/domtronn/all-the-icons.el")
;; Local Variables:
;; no-byte-compile: t
;; End:

View file

@ -0,0 +1,832 @@
;;; all-the-icons.el --- A library for inserting Developer icons
;; Copyright (C) 2016 Dominic Charlesworth <dgc336@gmail.com>
;; Author: Dominic Charlesworth <dgc336@gmail.com>
;; Version: 3.1.4
;; Package-Requires: ((emacs "24.3") (memoize "1.0.1"))
;; URL: https://github.com/domtronn/all-the-icons.el
;; Keywords: convenient, lisp
;; 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/>.
;;; Commentary:
;; This package is a utility for using and formatting various Icon
;; fonts within Emacs. Icon Fonts allow you to propertize and format
;; icons the same way you would normal text. This enables things such
;; as better scaling of and anti aliasing of the icons.
;; This package was inspired by
;; - `mode-icons' for Emacs, found at https://github.com/ryuslash/mode-icons
;; - `file-icons' for Atom, found at https://atom.io/packages/file-icons
;; Currently, this package provides an interface to the following Icon Fonts
;; - Atom File Icons, found at https://atom.io/packages/file-icons
;; - FontAwesome Icons, found at http://fontawesome.io/
;; - GitHub Octicons, found at http://octicons.github.com
;; - Material Design Icons, found at http://google.github.io/material-design-icons/
;; - Weather Icons, found at https://erikflowers.github.io/weather-icons/
;; - AllTheIcons, a custom Icon Font maintained as part of this package
;; Requests for new icons will be accepted and added to the AllTheIcons Icon Font
;;; Usage:
;; The simplest usage for this package is to use the following functions;
;; `all-the-icons-icon-for-buffer'
;; `all-the-icons-icon-for-file'
;; `all-the-icons-icon-for-mode'
;; Which can be used to get a formatted icon for the current buffer, a
;; file name or a major mode respectively. e.g.
;; (insert (all-the-icons-icon-for-file "foo.js"))
;; Inserts a JavaScript icon formatted like this
;; #("some-icon" 0 1 (display (raise -0.24)
;; face (:family "dev-icons" :height 1.08 :foreground "#FFD446")))
;; You can also insert icons directly using the individual icon family
;; functions
;; `all-the-icons-alltheicon' // Custom font with fewest icons
;; `all-the-icons-devicon' // Developer Icons
;; `all-the-icons-faicon' // Font Awesome Icons
;; `all-the-icons-fileicon' // File Icons from the Atom File Icons package
;; `all-the-icons-octicon' // GitHub Octicons
;; `all-the-icons-material' // Material Design Icons
;; `all-the-icons-wicon' // Weather Icons
;; You can call these functions with the icon name you want to insert, e.g.
;; (all-the-icons-octicon "file-binary") // GitHub Octicon for Binary File
;; (all-the-icons-faicon "cogs") // FontAwesome icon for cogs
;; (all-the-icons-wicon "tornado") // Weather Icon for tornado
;; A list of all the icon names for the different font families can be
;; found in the data directory, or by inspecting the alist variables.
;; All the alist variables are prefixed with `all-the-icons-data/'
;;; Code:
(require 'memoize)
(require 'cl-lib)
(require 'data-alltheicons "./data/data-alltheicons.el")
(require 'data-faicons "./data/data-faicons.el")
(require 'data-fileicons "./data/data-fileicons.el")
(require 'data-octicons "./data/data-octicons.el")
(require 'data-weathericons "./data/data-weathericons.el")
(require 'data-material "./data/data-material.el")
(require 'all-the-icons-faces)
;;; Custom Variables
(defgroup all-the-icons nil
"Manage how All The Icons formats icons."
:prefix "all-the-icons-"
:group 'appearance
:group 'convenience)
(defcustom all-the-icons-color-icons t
"Whether or not to include a foreground colour when formatting the icon."
:group 'all-the-icons
:type 'boolean)
(defcustom all-the-icons-scale-factor 1.2
"The base Scale Factor for the `height' face property of an icon."
:group 'all-the-icons
:type 'number)
(defcustom all-the-icons-default-adjust -0.2
"The default adjustment to be made to the `raise' display property of an icon."
:group 'all-the-icons
:type 'number)
(defvar all-the-icons-font-families '() "List of defined icon font families.")
(defvar all-the-icons-font-names '() "List of defined font file names this package was built with.")
(defvar all-the-icons-icon-alist
'(
;; Meta
("\\.tags" all-the-icons-octicon "tag" :height 1.0 :v-adjust 0.0 :face all-the-icons-blue)
("^TAGS$" all-the-icons-octicon "tag" :height 1.0 :v-adjust 0.0 :face all-the-icons-blue)
("\\.log" all-the-icons-octicon "bug" :height 1.0 :v-adjust 0.0 :face all-the-icons-maroon)
;;
("\\.key$" all-the-icons-octicon "key" :v-adjust 0.0 :face all-the-icons-lblue)
("\\.pem$" all-the-icons-octicon "key" :v-adjust 0.0 :face all-the-icons-orange)
("\\.p12$" all-the-icons-octicon "key" :v-adjust 0.0 :face all-the-icons-dorange)
("\\.crt$" all-the-icons-octicon "key" :v-adjust 0.0 :face all-the-icons-lblue)
("\\.pub$" all-the-icons-octicon "key" :v-adjust 0.0 :face all-the-icons-blue)
("\\.gpg$" all-the-icons-octicon "key" :v-adjust 0.0 :face all-the-icons-lblue)
("^TODO$" all-the-icons-octicon "checklist" :v-adjust 0.0 :face all-the-icons-lyellow)
("^LICENSE$" all-the-icons-octicon "book" :height 1.0 :v-adjust 0.0 :face all-the-icons-blue)
("^readme" all-the-icons-octicon "book" :height 1.0 :v-adjust 0.0 :face all-the-icons-lcyan)
("\\.fish" all-the-icons-alltheicon "terminal" :face all-the-icons-lpink)
("\\.zsh" all-the-icons-alltheicon "terminal" :face all-the-icons-lcyan)
("\\.sh" all-the-icons-alltheicon "terminal" :face all-the-icons-purple)
;; Config
("\\.node" all-the-icons-alltheicon "nodejs" :height 1.0 :face all-the-icons-green)
("\\.babelrc$" all-the-icons-fileicon "babel" :face all-the-icons-yellow)
("\\.bashrc$" all-the-icons-alltheicon "script" :height 0.9 :face all-the-icons-dpink)
("\\.bowerrc$" all-the-icons-alltheicon "bower" :height 1.0 :v-adjust 0.0 :face all-the-icons-silver)
("^bower.json$" all-the-icons-alltheicon "bower" :height 1.0 :v-adjust 0.0 :face all-the-icons-lorange)
("\\.ini$" all-the-icons-octicon "settings" :v-adjust 0.0 :face all-the-icons-yellow)
("\\.eslintignore" all-the-icons-fileicon "eslint" :height 0.9 :face all-the-icons-purple)
("\\.eslint" all-the-icons-fileicon "eslint" :height 0.9 :face all-the-icons-lpurple)
("\\.git" all-the-icons-alltheicon "git" :height 1.0 :face all-the-icons-lred)
("nginx" all-the-icons-fileicon "nginx" :height 0.9 :face all-the-icons-dgreen)
("apache" all-the-icons-alltheicon "apache" :height 0.9 :face all-the-icons-dgreen)
("^Makefile$" all-the-icons-fileicon "gnu" :face all-the-icons-dorange)
("\\.mk$" all-the-icons-fileicon "gnu" :face all-the-icons-dorange)
("\\.dockerignore$" all-the-icons-fileicon "dockerfile" :height 1.2 :face all-the-icons-dblue)
("^\\.?Dockerfile" all-the-icons-fileicon "dockerfile" :face all-the-icons-blue)
("^Brewfile$" all-the-icons-faicon "beer" :face all-the-icons-lsilver)
("\\.npmignore" all-the-icons-fileicon "npm" :face all-the-icons-dred)
("^package.json$" all-the-icons-fileicon "npm" :face all-the-icons-red)
("^package.lock.json$" all-the-icons-fileicon "npm" :face all-the-icons-dred)
("^yarn\.lock" all-the-icons-fileicon "yarn" :face all-the-icons-blue-alt)
("\.xml$" all-the-icons-faicon "file-code-o" :height 0.95 :face all-the-icons-lorange)
;; ;; AWS
("^stack.*.json$" all-the-icons-alltheicon "aws" :face all-the-icons-orange)
("^serverless\\.yml$" all-the-icons-faicon "bolt" :v-adjust 0.0 :face all-the-icons-yellow)
("\\.[jc]son$" all-the-icons-octicon "settings" :v-adjust 0.0 :face all-the-icons-yellow)
("\\.ya?ml$" all-the-icons-octicon "settings" :v-adjust 0.0 :face all-the-icons-dyellow)
("\\.pkg$" all-the-icons-octicon "package" :v-adjust 0.0 :face all-the-icons-dsilver)
("\\.rpm$" all-the-icons-octicon "package" :v-adjust 0.0 :face all-the-icons-dsilver)
("\\.elc$" all-the-icons-octicon "file-binary" :v-adjust 0.0 :face all-the-icons-dsilver)
("\\.gz$" all-the-icons-octicon "file-binary" :v-adjust 0.0 :face all-the-icons-lmaroon)
("\\.zip$" all-the-icons-octicon "file-zip" :v-adjust 0.0 :face all-the-icons-lmaroon)
("\\.7z$" all-the-icons-octicon "file-zip" :v-adjust 0.0 :face all-the-icons-lmaroon)
("\\.dat$" all-the-icons-faicon "bar-chart" :face all-the-icons-cyan :height 0.9)
;; lock files
("~$" all-the-icons-octicon "lock" :v-adjust 0.0 :face all-the-icons-maroon)
("\\.dmg$" all-the-icons-octicon "tools" :v-adjust 0.0 :face all-the-icons-lsilver)
("\\.dll$" all-the-icons-faicon "cogs" :face all-the-icons-silver)
("\\.DS_STORE$" all-the-icons-faicon "cogs" :face all-the-icons-silver)
;; Source Codes
("\\.scpt$" all-the-icons-fileicon "apple" :face all-the-icons-pink)
("\\.aup$" all-the-icons-fileicon "audacity" :face all-the-icons-yellow)
("\\.elm" all-the-icons-fileicon "elm" :face all-the-icons-blue)
("\\.erl$" all-the-icons-alltheicon "erlang" :face all-the-icons-red :v-adjust -0.1 :height 0.9)
("\\.hrl$" all-the-icons-alltheicon "erlang" :face all-the-icons-dred :v-adjust -0.1 :height 0.9)
("\\.eex$" all-the-icons-alltheicon "elixir" :face all-the-icons-lorange :v-adjust -0.1 :height 0.9)
("\\.ex$" all-the-icons-alltheicon "elixir" :face all-the-icons-lpurple :v-adjust -0.1 :height 0.9)
("\\.exs$" all-the-icons-alltheicon "elixir" :face all-the-icons-lred :v-adjust -0.1 :height 0.9)
("^mix.lock$" all-the-icons-alltheicon "elixir" :face all-the-icons-lyellow :v-adjust -0.1 :height 0.9)
("\\.java$" all-the-icons-alltheicon "java" :height 1.0 :face all-the-icons-purple)
("\\.go$" all-the-icons-alltheicon "go" :height 1.0 :face all-the-icons-blue)
("\\.mp3$" all-the-icons-faicon "volume-up" :face all-the-icons-dred)
("\\.wav$" all-the-icons-faicon "volume-up" :face all-the-icons-dred)
("\\.m4a$" all-the-icons-faicon "volume-up" :face all-the-icons-dred)
("\\.jl$" all-the-icons-fileicon "julia" :v-adjust 0.0 :face all-the-icons-purple)
("\\.matlab$" all-the-icons-fileicon "matlab" :face all-the-icons-orange)
("\\.p[ml]$" all-the-icons-alltheicon "perl" :face all-the-icons-lorange)
("\\.pl6$" all-the-icons-fileicon "perl6" :face all-the-icons-cyan)
("\\.pod$" all-the-icons-alltheicon "perldocs" :height 1.2 :face all-the-icons-lgreen)
("\\.php$" all-the-icons-fileicon "php" :face all-the-icons-lsilver)
("\\.pony$" all-the-icons-fileicon "pony" :face all-the-icons-maroon)
("\\.prol?o?g?$" all-the-icons-alltheicon "prolog" :height 1.1 :face all-the-icons-lmaroon)
("\\.py$" all-the-icons-alltheicon "python" :height 1.0 :face all-the-icons-dblue)
("\\.rkt$" all-the-icons-fileicon "racket" :height 1.2 :face all-the-icons-red)
("\\.gem$" all-the-icons-alltheicon "ruby-alt" :face all-the-icons-red)
("_?test\\.rb$" all-the-icons-fileicon "test-ruby" :height 1.0 :v-adjust 0.0 :face all-the-icons-red)
("_?test_helper\\.rb$" all-the-icons-fileicon "test-ruby" :height 1.0 :v-adjust 0.0 :face all-the-icons-dred)
("\\.rb$" all-the-icons-octicon "ruby" :v-adjust 0.0 :face all-the-icons-lred)
("\\.rs$" all-the-icons-alltheicon "rust" :height 1.2 :face all-the-icons-maroon)
("\\.rlib$" all-the-icons-alltheicon "rust" :height 1.2 :face all-the-icons-dmaroon)
("\\.r[ds]?x?$" all-the-icons-fileicon "R" :face all-the-icons-lblue)
("\\.scala$" all-the-icons-alltheicon "scala" :face all-the-icons-red)
("\\.scm$" all-the-icons-fileicon "scheme" :height 1.2 :face all-the-icons-red)
("\\.swift$" all-the-icons-alltheicon "swift" :height 1.0 :v-adjust -0.1 :face all-the-icons-green)
("-?spec\\.ts$" all-the-icons-fileicon "test-typescript" :height 1.0 :v-adjust 0.0 :face all-the-icons-blue)
("-?test\\.ts$" all-the-icons-fileicon "test-typescript" :height 1.0 :v-adjust 0.0 :face all-the-icons-blue)
("-?spec\\.js$" all-the-icons-fileicon "test-js" :height 1.0 :v-adjust 0.0 :face all-the-icons-lpurple)
("-?test\\.js$" all-the-icons-fileicon "test-js" :height 1.0 :v-adjust 0.0 :face all-the-icons-lpurple)
("-?spec\\.jsx$" all-the-icons-fileicon "test-react" :height 1.0 :v-adjust 0.0 :face all-the-icons-blue-alt)
("-?test\\.jsx$" all-the-icons-fileicon "test-react" :height 1.0 :v-adjust 0.0 :face all-the-icons-blue-alt)
("-?spec\\." all-the-icons-fileicon "test-generic" :height 1.0 :v-adjust 0.0 :face all-the-icons-dgreen)
("-?test\\." all-the-icons-fileicon "test-generic" :height 1.0 :v-adjust 0.0 :face all-the-icons-dgreen)
;; There seems to be a a bug with this font icon which does not
;; let you propertise it without it reverting to being a lower
;; case phi
("\\.c$" all-the-icons-alltheicon "c-line" :face all-the-icons-blue)
("\\.h$" all-the-icons-alltheicon "c-line" :face all-the-icons-purple)
("\\.m$" all-the-icons-fileicon "apple" :v-adjust 0.0 :height 1.0)
("\\.mm$" all-the-icons-fileicon "apple" :v-adjust 0.0 :height 1.0)
("\\.c\\(c\\|pp\\|xx\\)$" all-the-icons-alltheicon "cplusplus-line" :v-adjust -0.2 :face all-the-icons-blue)
("\\.h\\(h\\|pp\\|xx\\)$" all-the-icons-alltheicon "cplusplus-line" :v-adjust -0.2 :face all-the-icons-purple)
("\\.csx?$" all-the-icons-alltheicon "csharp-line" :face all-the-icons-dblue)
("\\.cljc?$" all-the-icons-alltheicon "clojure-line" :height 1.0 :face all-the-icons-blue :v-adjust 0.0)
("\\.cljs$" all-the-icons-fileicon "cljs" :height 1.0 :face all-the-icons-dblue :v-adjust 0.0)
("\\.coffee$" all-the-icons-alltheicon "coffeescript" :height 1.0 :face all-the-icons-maroon)
("\\.iced$" all-the-icons-alltheicon "coffeescript" :height 1.0 :face all-the-icons-lmaroon)
;; Git
("^MERGE_" all-the-icons-octicon "git-merge" :v-adjust 0.0 :face all-the-icons-red)
("^COMMIT_EDITMSG" all-the-icons-octicon "git-commit" :v-adjust 0.0 :face all-the-icons-red)
;; Lisps
("\\.cl$" all-the-icons-fileicon "clisp" :face all-the-icons-lorange)
("\\.l\\(isp\\)?$" all-the-icons-fileicon "lisp" :face all-the-icons-orange)
("\\.el$" all-the-icons-fileicon "elisp" :height 1.0 :v-adjust -0.2 :face all-the-icons-purple)
;; Stylesheeting
("\\.css$" all-the-icons-alltheicon "css3" :face all-the-icons-yellow)
("\\.scss$" all-the-icons-alltheicon "sass" :face all-the-icons-pink)
("\\.sass$" all-the-icons-alltheicon "sass" :face all-the-icons-dpink)
("\\.less$" all-the-icons-alltheicon "less" :height 0.8 :face all-the-icons-dyellow)
("\\.postcss$" all-the-icons-fileicon "postcss" :face all-the-icons-dred)
("\\.sss$" all-the-icons-fileicon "postcss" :face all-the-icons-dred)
("\\.styl$" all-the-icons-alltheicon "stylus" :face all-the-icons-lgreen)
("stylelint" all-the-icons-fileicon "stylelint" :face all-the-icons-lyellow)
("\\.csv$" all-the-icons-octicon "graph" :v-adjust 0.0 :face all-the-icons-dblue)
("\\.hs$" all-the-icons-alltheicon "haskell" :height 1.0 :face all-the-icons-red)
;; Web modes
("\\.inky-haml$" all-the-icons-fileicon "haml" :face all-the-icons-lyellow)
("\\.haml$" all-the-icons-fileicon "haml" :face all-the-icons-lyellow)
("\\.html?$" all-the-icons-alltheicon "html5" :face all-the-icons-orange)
("\\.inky-erb?$" all-the-icons-alltheicon "html5" :face all-the-icons-lred)
("\\.erb$" all-the-icons-alltheicon "html5" :face all-the-icons-lred)
("\\.hbs$" all-the-icons-fileicon "moustache" :face all-the-icons-green)
("\\.inky-slim$" all-the-icons-octicon "dashboard" :v-adjust 0.0 :face all-the-icons-yellow)
("\\.slim$" all-the-icons-octicon "dashboard" :v-adjust 0.0 :face all-the-icons-yellow)
("\\.jade$" all-the-icons-fileicon "jade" :face all-the-icons-red)
("\\.pug$" all-the-icons-fileicon "pug-alt" :face all-the-icons-red)
;; JavaScript
("^gulpfile" all-the-icons-alltheicon "gulp" :height 1.0 :face all-the-icons-lred)
("^gruntfile" all-the-icons-alltheicon "grunt" :height 1.0 :v-adjust -0.1 :face all-the-icons-lyellow)
("^webpack" all-the-icons-fileicon "webpack" :face all-the-icons-lblue)
("\\.d3\\.?js" all-the-icons-alltheicon "d3" :height 0.8 :face all-the-icons-lgreen)
("\\.re$" all-the-icons-fileicon "reason" :height 1.0 :face all-the-icons-red-alt)
("\\.rei$" all-the-icons-fileicon "reason" :height 1.0 :face all-the-icons-dred)
("\\.ml$" all-the-icons-fileicon "ocaml" :height 1.0 :face all-the-icons-lpink)
("\\.mli$" all-the-icons-fileicon "ocaml" :height 1.0 :face all-the-icons-dpink)
("\\.react" all-the-icons-alltheicon "react" :height 1.1 :face all-the-icons-lblue)
("\\.d\\.ts$" all-the-icons-fileicon "typescript" :height 1.0 :v-adjust -0.1 :face all-the-icons-cyan-alt)
("\\.ts$" all-the-icons-fileicon "typescript" :height 1.0 :v-adjust -0.1 :face all-the-icons-blue-alt)
("\\.js$" all-the-icons-alltheicon "javascript" :height 1.0 :v-adjust 0.0 :face all-the-icons-yellow)
("\\.es[0-9]$" all-the-icons-alltheicon "javascript" :height 1.0 :v-adjust 0.0 :face all-the-icons-yellow)
("\\.jsx$" all-the-icons-fileicon "jsx-2" :height 1.0 :v-adjust -0.1 :face all-the-icons-cyan-alt)
("\\.njs$" all-the-icons-alltheicon "nodejs" :height 1.2 :face all-the-icons-lgreen)
("\\.vue$" all-the-icons-fileicon "vue" :face all-the-icons-lgreen)
;; File Types
("\\.ico$" all-the-icons-octicon "file-media" :v-adjust 0.0 :face all-the-icons-blue)
("\\.png$" all-the-icons-octicon "file-media" :v-adjust 0.0 :face all-the-icons-orange)
("\\.gif$" all-the-icons-octicon "file-media" :v-adjust 0.0 :face all-the-icons-green)
("\\.jpe?g$" all-the-icons-octicon "file-media" :v-adjust 0.0 :face all-the-icons-dblue)
("\\.svg$" all-the-icons-alltheicon "svg" :height 0.9 :face all-the-icons-lgreen)
;; Video
("\\.mov" all-the-icons-faicon "film" :face all-the-icons-blue)
("\\.mp4" all-the-icons-faicon "film" :face all-the-icons-blue)
("\\.ogv" all-the-icons-faicon "film" :face all-the-icons-dblue)
;; Fonts
("\\.ttf$" all-the-icons-fileicon "font" :v-adjust 0.0 :face all-the-icons-dcyan)
("\\.woff2?$" all-the-icons-fileicon "font" :v-adjust 0.0 :face all-the-icons-cyan)
;; Doc
("\\.pdf" all-the-icons-octicon "file-pdf" :v-adjust 0.0 :face all-the-icons-dred)
("\\.te?xt" all-the-icons-octicon "file-text" :v-adjust 0.0 :face all-the-icons-cyan)
("\\.doc[xm]?$" all-the-icons-fileicon "word" :face all-the-icons-blue)
("\\.texi?$" all-the-icons-fileicon "tex" :face all-the-icons-lred)
("\\.md$" all-the-icons-octicon "markdown" :v-adjust 0.0 :face all-the-icons-lblue)
("\\.bib$" all-the-icons-fileicon "bib" :face all-the-icons-maroon)
("\\.org$" all-the-icons-fileicon "org" :face all-the-icons-lgreen)
("\\.pp[st]$" all-the-icons-fileicon "powerpoint" :face all-the-icons-orange)
("\\.pp[st]x$" all-the-icons-fileicon "powerpoint" :face all-the-icons-red)
("\\.knt$" all-the-icons-fileicon "powerpoint" :face all-the-icons-cyan)
("bookmark" all-the-icons-octicon "bookmark" :height 1.1 :v-adjust 0.0 :face all-the-icons-lpink)
("\\.cache$" all-the-icons-octicon "database" :height 1.0 :v-adjust 0.0 :face all-the-icons-green)
("^\\*scratch\\*$" all-the-icons-faicon "sticky-note" :face all-the-icons-lyellow)
("^\\*scratch.*" all-the-icons-faicon "sticky-note" :face all-the-icons-yellow)
("^\\*new-tab\\*$" all-the-icons-material "star" :face all-the-icons-cyan)
("^\\." all-the-icons-octicon "gear" :v-adjust 0.0)
("." all-the-icons-faicon "file-o" :height 0.8 :v-adjust 0.0 :face all-the-icons-dsilver)))
(defvar all-the-icons-dir-icon-alist
'(
("trash" all-the-icons-faicon "trash-o" :height 1.2 :v-adjust -0.1)
("dropbox" all-the-icons-faicon "dropbox" :height 1.0 :v-adjust -0.1)
("google[ _-]drive" all-the-icons-alltheicon "google-drive" :height 1.3 :v-adjust -0.1)
("^atom$" all-the-icons-alltheicon "atom" :height 1.2 :v-adjust -0.1)
("documents" all-the-icons-faicon "book" :height 1.0 :v-adjust -0.1)
("download" all-the-icons-faicon "cloud-download" :height 0.9 :v-adjust -0.2)
("desktop" all-the-icons-octicon "device-desktop" :height 1.0 :v-adjust -0.1)
("pictures" all-the-icons-faicon "picture-o" :height 0.9 :v-adjust -0.2)
("photos" all-the-icons-faicon "camera-retro" :height 1.0 :v-adjust -0.1)
("music" all-the-icons-faicon "music" :height 1.0 :v-adjust -0.1)
("movies" all-the-icons-faicon "film" :height 0.9 :v-adjust -0.1)
("code" all-the-icons-octicon "code" :height 1.1 :v-adjust -0.1)
("workspace" all-the-icons-octicon "code" :height 1.1 :v-adjust -0.1)
("test" all-the-icons-fileicon "test-dir" :height 0.9)
("\\.git" all-the-icons-alltheicon "git" :height 1.0)
("." all-the-icons-octicon "file-directory" :height 1.0 :v-adjust -0.1)
))
(defvar all-the-icons-weather-icon-alist
'(
("tornado" all-the-icons-wicon "tornado")
("hurricane" all-the-icons-wicon "hurricane")
("thunderstorms" all-the-icons-wicon "thunderstorm")
("sunny" all-the-icons-wicon "day-sunny")
("rain.*snow" all-the-icons-wicon "rain-mix")
("rain.*hail" all-the-icons-wicon "rain-mix")
("sleet" all-the-icons-wicon "sleet")
("hail" all-the-icons-wicon "hail")
("drizzle" all-the-icons-wicon "sprinkle")
("rain" all-the-icons-wicon "showers" :height 1.1 :v-adjust 0.0)
("showers" all-the-icons-wicon "showers")
("blowing.*snow" all-the-icons-wicon "snow-wind")
("snow" all-the-icons-wicon "snow")
("dust" all-the-icons-wicon "dust")
("fog" all-the-icons-wicon "fog")
("haze" all-the-icons-wicon "day-haze")
("smoky" all-the-icons-wicon "smoke")
("blustery" all-the-icons-wicon "cloudy-windy")
("windy" all-the-icons-wicon "cloudy-gusts")
("cold" all-the-icons-wicon "snowflake-cold")
("partly.*cloudy.*night" all-the-icons-wicon "night-alt-partly-cloudy")
("partly.*cloudy" all-the-icons-wicon "day-cloudy-high")
("cloudy.*night" all-the-icons-wicon "night-alt-cloudy")
("cxloudy.*day" all-the-icons-wicon "day-cloudy")
("cloudy" all-the-icons-wicon "cloudy")
("clear.*night" all-the-icons-wicon "night-clear")
("fair.*night" all-the-icons-wicon "stars")
("fair.*day" all-the-icons-wicon "horizon")
("hot" all-the-icons-wicon "hot")
("not.*available" all-the-icons-wicon "na")
))
(defvar all-the-icons-mode-icon-alist
'(
(emacs-lisp-mode all-the-icons-fileicon "elisp" :height 1.0 :v-adjust -0.2 :face all-the-icons-purple)
(inferior-emacs-lisp-mode all-the-icons-fileicon "elisp" :height 1.0 :v-adjust -0.2 :face all-the-icons-lblue)
(dired-mode all-the-icons-octicon "file-directory" :v-adjust 0.0)
(lisp-interaction-mode all-the-icons-fileicon "lisp" :v-adjust -0.1 :face all-the-icons-orange)
(org-mode all-the-icons-fileicon "org" :v-adjust 0.0 :face all-the-icons-lgreen)
(typescript-mode all-the-icons-fileicon "typescript" :v-adjust -0.1 :face all-the-icons-blue-alt)
(js-mode all-the-icons-alltheicon "javascript" :v-adjust -0.1 :face all-the-icons-yellow)
(js-jsx-mode all-the-icons-alltheicon "javascript" :v-adjust -0.1 :face all-the-icons-yellow)
(js2-mode all-the-icons-alltheicon "javascript" :v-adjust -0.1 :face all-the-icons-yellow)
(js3-mode all-the-icons-alltheicon "javascript" :v-adjust -0.1 :face all-the-icons-yellow)
(rjsx-mode all-the-icons-fileicon "jsx-2" :v-adjust -0.1 :face all-the-icons-cyan-alt)
(term-mode all-the-icons-octicon "terminal" :v-adjust 0.2)
(eshell-mode all-the-icons-octicon "terminal" :v-adjust 0.0 :face all-the-icons-purple)
(magit-refs-mode all-the-icons-octicon "git-branch" :v-adjust 0.0 :face all-the-icons-red)
(magit-process-mode all-the-icons-octicon "mark-github" :v-adjust 0.0)
(magit-diff-mode all-the-icons-octicon "git-compare" :v-adjust 0.0 :face all-the-icons-lblue)
(ediff-mode all-the-icons-octicon "git-compare" :v-adjust 0.0 :Face all-the-icons-red)
(comint-mode all-the-icons-faicon "terminal" :v-adjust 0.0 :face all-the-icons-lblue)
(eww-mode all-the-icons-faicon "firefox" :v-adjust -0.1 :face all-the-icons-red)
(org-agenda-mode all-the-icons-octicon "checklist" :v-adjust 0.0 :face all-the-icons-lgreen)
(cfw:calendar-mode all-the-icons-octicon "calendar" :v-adjust 0.0)
(ibuffer-mode all-the-icons-faicon "files-o" :v-adjust 0.0 :face all-the-icons-dsilver)
(messages-buffer-mode all-the-icons-faicon "stack-overflow" :v-adjust -0.1)
(help-mode all-the-icons-faicon "info" :v-adjust -0.1 :face all-the-icons-purple)
(benchmark-init/tree-mode all-the-icons-octicon "dashboard" :v-adjust 0.0)
(jenkins-mode all-the-icons-fileicon "jenkins" :face all-the-icons-blue)
(magit-popup-mode all-the-icons-alltheicon "git" :face all-the-icons-red)
(magit-status-mode all-the-icons-alltheicon "git" :face all-the-icons-lred)
(magit-log-mode all-the-icons-alltheicon "git" :face all-the-icons-green)
(Custom-mode all-the-icons-octicon "settings")
;; Special matcher for Web Mode based on the `web-mode-content-type' of the current buffer
(web-mode all-the-icons--web-mode-icon)
(fundamental-mode all-the-icons-fileicon "elisp" :height 1.0 :v-adjust -0.2 :face all-the-icons-dsilver)
(special-mode all-the-icons-fileicon "elisp" :height 1.0 :v-adjust -0.2 :face all-the-icons-yellow)
(text-mode all-the-icons-octicon "file-text" :v-adjust 0.0 :face all-the-icons-cyan)
(ruby-mode all-the-icons-alltheicon "ruby-alt" :face all-the-icons-lred)
(inf-ruby-mode all-the-icons-alltheicon "ruby-alt" :face all-the-icons-red)
(projectile-rails-compilation-mode all-the-icons-alltheicon "ruby-alt" :face all-the-icons-red)
(rspec-compilation-mode all-the-icons-alltheicon "ruby-alt" :face all-the-icons-red)
(rake-compilation-mode all-the-icons-alltheicon "ruby-alt" :face all-the-icons-red)
(shell-mode all-the-icons-alltheicon "terminal" :face all-the-icons-purple)
(fish-mode all-the-icons-alltheicon "terminal" :face all-the-icons-lpink)
(nginx-mode all-the-icons-fileicon "nginx" :height 0.9 :face all-the-icons-dgreen)
(apache-mode all-the-icons-alltheicon "apache" :height 0.9 :face all-the-icons-dgreen)
(makefile-mode all-the-icons-fileicon "gnu" :face all-the-icons-dorange)
(dockerfile-mode all-the-icons-fileicon "dockerfile" :face all-the-icons-blue)
(docker-compose-mode all-the-icons-fileicon "dockerfile" :face all-the-icons-lblue)
(xml-mode all-the-icons-faicon "file-code-o" :height 0.95 :face all-the-icons-lorange)
(json-mode all-the-icons-octicon "settings" :face all-the-icons-yellow)
(yaml-mode all-the-icons-octicon "settings" :v-adjust 0.0 :face all-the-icons-dyellow)
(elisp-byte-code-mode all-the-icons-octicon "file-binary" :v-adjust 0.0 :face all-the-icons-dsilver)
(archive-mode all-the-icons-octicon "file-zip" :v-adjust 0.0 :face all-the-icons-lmaroon)
(elm-mode all-the-icons-fileicon "elm" :face all-the-icons-blue)
(erlang-mode all-the-icons-alltheicon "erlang" :face all-the-icons-red :v-adjust -0.1 :height 0.9)
(elixir-mode all-the-icons-alltheicon "elixir" :face all-the-icons-lorange :v-adjust -0.1 :height 0.9)
(java-mode all-the-icons-alltheicon "java" :height 1.0 :face all-the-icons-purple)
(go-mode all-the-icons-alltheicon "go" :height 1.0 :face all-the-icons-blue)
(matlab-mode all-the-icons-fileicon "matlab" :face all-the-icons-orange)
(perl-mode all-the-icons-alltheicon "perl" :face all-the-icons-lorange)
(cperl-mode all-the-icons-alltheicon "perl" :face all-the-icons-lorange)
(php-mode all-the-icons-fileicon "php" :face all-the-icons-lsilver)
(prolog-mode all-the-icons-alltheicon "prolog" :height 1.1 :face all-the-icons-lmaroon)
(python-mode all-the-icons-alltheicon "python" :height 1.0 :face all-the-icons-dblue)
(racket-mode all-the-icons-fileicon "racket" :height 1.2 :face all-the-icons-red)
(rust-mode all-the-icons-alltheicon "rust" :height 1.2 :face all-the-icons-maroon)
(scala-mode all-the-icons-alltheicon "scala" :face all-the-icons-red)
(scheme-mode all-the-icons-fileicon "scheme" :height 1.2 :face all-the-icons-red)
(swift-mode all-the-icons-alltheicon "swift" :height 1.0 :v-adjust -0.1 :face all-the-icons-green)
(c-mode all-the-icons-alltheicon "c-line" :face all-the-icons-blue)
(c++-mode all-the-icons-alltheicon "cplusplus-line" :v-adjust -0.2 :face all-the-icons-blue)
(csharp-mode all-the-icons-alltheicon "csharp-line" :face all-the-icons-dblue)
(clojure-mode all-the-icons-alltheicon "clojure-line" :height 1.0 :face all-the-icons-blue)
(cider-repl-mode all-the-icons-alltheicon "clojure-line" :height 1.0 :face all-the-icons-dblue)
(clojurescript-mode all-the-icons-fileicon "cljs" :height 1.0 :face all-the-icons-dblue)
(coffee-mode all-the-icons-alltheicon "coffeescript" :height 1.0 :face all-the-icons-maroon)
(lisp-mode all-the-icons-fileicon "lisp" :face all-the-icons-orange)
(css-mode all-the-icons-alltheicon "css3" :face all-the-icons-yellow)
(scss-mode all-the-icons-alltheicon "sass" :face all-the-icons-pink)
(sass-mode all-the-icons-alltheicon "sass" :face all-the-icons-dpink)
(less-css-mode all-the-icons-alltheicon "less" :height 0.8 :face all-the-icons-dyellow)
(stylus-mode all-the-icons-alltheicon "stylus" :face all-the-icons-lgreen)
(csv-mode all-the-icons-octicon "graph" :v-adjust 0.0 :face all-the-icons-dblue)
(haskell-mode all-the-icons-alltheicon "haskell" :height 1.0 :face all-the-icons-red)
(haml-mode all-the-icons-fileicon "haml" :face all-the-icons-lyellow)
(html-mode all-the-icons-alltheicon "html5" :face all-the-icons-orange)
(rhtml-mode all-the-icons-alltheicon "html5" :face all-the-icons-lred)
(mustache-mode all-the-icons-fileicon "moustache" :face all-the-icons-green)
(slim-mode all-the-icons-octicon "dashboard" :v-adjust 0.0 :face all-the-icons-yellow)
(jade-mode all-the-icons-fileicon "jade" :face all-the-icons-red)
(pug-mode all-the-icons-fileicon "pug" :face all-the-icons-red)
(react-mode all-the-icons-alltheicon "react" :height 1.1 :face all-the-icons-lblue)
(image-mode all-the-icons-octicon "file-media" :v-adjust 0.0 :face all-the-icons-blue)
(texinfo-mode all-the-icons-fileicon "tex" :face all-the-icons-lred)
(markdown-mode all-the-icons-octicon "markdown" :v-adjust 0.0 :face all-the-icons-lblue)
(bibtex-mode all-the-icons-fileicon "bib" :face all-the-icons-maroon)
(org-mode all-the-icons-fileicon "org" :face all-the-icons-lgreen)
(compilation-mode all-the-icons-faicon "cogs" :v-adjust 0.0 :height 1.0)
(objc-mode all-the-icons-faicon "apple" :v-adjust 0.0 :height 1.0)
))
;; ====================
;; Functions Start
;; ====================
(defun all-the-icons-auto-mode-match? (&optional file)
"Whether or not FILE's `major-mode' match against its `auto-mode-alist'."
(let* ((file (or file (buffer-file-name) (buffer-name)))
(auto-mode (all-the-icons-match-to-alist file auto-mode-alist)))
(eq major-mode auto-mode)))
(defun all-the-icons-match-to-alist (file alist)
"Match FILE against an entry in ALIST using `string-match'."
(cdr (cl-find-if (lambda (it) (string-match (car it) file)) alist)))
(defun all-the-icons-dir-is-submodule (dir)
"Checker whether or not DIR is a git submodule."
(let* ((gitmodule-dir (locate-dominating-file dir ".gitmodules"))
(modules-file (expand-file-name (format "%s.gitmodules" gitmodule-dir)))
(module-search (format "submodule \".*?%s\"" (file-name-base dir))))
(when (and gitmodule-dir (file-exists-p (format "%s/.git" dir)))
(with-temp-buffer
(insert-file-contents modules-file)
(search-forward-regexp module-search (point-max) t)))))
;; Icon functions
(defun all-the-icons-icon-for-dir (dir &optional chevron padding)
"Format an icon for DIR with CHEVRON similar to tree based directories.
If PADDING is provided, it will prepend and separate the chevron
and directory with PADDING.
Produces different symbols by inspecting DIR to distinguish
symlinks and git repositories which do not depend on the
directory contents"
(let* ((matcher (all-the-icons-match-to-alist (file-name-base dir) all-the-icons-dir-icon-alist))
(path (expand-file-name dir))
(chevron (if chevron (all-the-icons-octicon (format "chevron-%s" chevron) :height 0.8 :v-adjust -0.1) ""))
(padding (or padding "\t"))
(icon (cond
((file-symlink-p path)
(all-the-icons-octicon "file-symlink-directory" :height 1.0))
((all-the-icons-dir-is-submodule path)
(all-the-icons-octicon "file-submodule" :height 1.0))
((file-exists-p (format "%s/.git" path))
(format "%s" (all-the-icons-octicon "repo" :height 1.1)))
(t (apply (car matcher) (cdr matcher))))))
(format "%s%s%s%s%s" padding chevron padding icon padding)))
(defun all-the-icons-icon-for-buffer ()
"Get the formatted icon for the current buffer.
This function prioritises the use of the buffers file extension to
discern the icon when its `major-mode' matches its auto mode,
otherwise it will use the buffers `major-mode' to decide its
icon."
(all-the-icons--icon-info-for-buffer))
(defun all-the-icons-icon-family-for-buffer ()
"Get the icon font family for the current buffer."
(all-the-icons--icon-info-for-buffer "family"))
(defun all-the-icons--web-mode-icon (&rest arg-overrides) "Get icon for a `web-mode' buffer with ARG-OVERRIDES." (all-the-icons--web-mode nil arg-overrides))
(defun all-the-icons--web-mode-icon-family () "Get icon family for a `web-mode' buffer." (all-the-icons--web-mode t))
(defun all-the-icons--web-mode (&optional family arg-overrides)
"Return icon or FAMILY for `web-mode' based on `web-mode-content-type'.
Providing ARG-OVERRIDES will modify the creation of the icon."
(let ((non-nil-args (cl-reduce (lambda (acc it) (if it (append acc (list it)) acc)) arg-overrides :initial-value '())))
(cond
((equal web-mode-content-type "jsx")
(if family (all-the-icons-fileicon-family) (apply 'all-the-icons-fileicon (append '("jsx-2") non-nil-args))))
((equal web-mode-content-type "javascript")
(if family (all-the-icons-alltheicon-family) (apply 'all-the-icons-alltheicon (append '("javascript") non-nil-args))))
((equal web-mode-content-type "json")
(if family (all-the-icons-alltheicon-family) (apply 'all-the-icons-alltheicon (append '("less") non-nil-args))))
((equal web-mode-content-type "xml")
(if family (all-the-icons-faicon-family) (apply 'all-the-icons-faicon (append '("file-code-o") non-nil-args))))
((equal web-mode-content-type "css")
(if family (all-the-icons-alltheicon-family) (apply 'all-the-icons-alltheicon (append '("css3") non-nil-args))))
(t
(if family (all-the-icons-alltheicon-family) (apply 'all-the-icons-alltheicon (append '("html5") non-nil-args)))))))
;; Icon Functions
;;;###autoload
(defun all-the-icons-icon-for-file (file &rest arg-overrides)
"Get the formatted icon for FILE.
ARG-OVERRIDES should be a plist containining `:height',
`:v-adjust' or `:face' properties like in the normal icon
inserting functions."
(let* ((icon (all-the-icons-match-to-alist file all-the-icons-icon-alist))
(args (cdr icon)))
(when arg-overrides (setq args (append `(,(car args)) arg-overrides (cdr args))))
(apply (car icon) args)))
;;;###autoload
(defun all-the-icons-icon-for-mode (mode &rest arg-overrides)
"Get the formatted icon for MODE.
ARG-OVERRIDES should be a plist containining `:height',
`:v-adjust' or `:face' properties like in the normal icon
inserting functions."
(let* ((icon (cdr (assoc mode all-the-icons-mode-icon-alist)))
(args (cdr icon)))
(when arg-overrides (setq args (append `(,(car args)) arg-overrides (cdr args))))
(if icon (apply (car icon) args) mode)))
(memoize 'all-the-icons-icon-for-file)
(memoize 'all-the-icons-icon-for-mode)
;; Family Face Functions
(defun all-the-icons-icon-family-for-file (file)
"Get the icons font family for FILE."
(let ((icon (all-the-icons-match-to-alist file all-the-icons-icon-alist)))
(funcall (intern (format "%s-family" (car icon))))))
(defun all-the-icons-icon-family-for-mode (mode)
"Get the icons font family for MODE."
(let ((icon (cdr (assoc mode all-the-icons-mode-icon-alist))))
(if icon (funcall (intern (format "%s-family" (car icon)))) nil)))
(defun all-the-icons-icon-family (icon)
"Get a propertized ICON family programatically."
(plist-get (get-text-property 0 'face icon) :family))
(memoize 'all-the-icons-icon-family-for-file)
(memoize 'all-the-icons-icon-family-for-mode)
(memoize 'all-the-icons-icon-family)
;;;###autoload
(defun all-the-icons--icon-info-for-buffer (&optional f)
"Get icon info for the current buffer.
When F is provided, the info function is calculated with the format
`all-the-icons-icon-%s-for-file' or `all-the-icons-icon-%s-for-mode'."
(let* ((base-f (concat "all-the-icons-icon" (when f (format "-%s" f))))
(file-f (intern (concat base-f "-for-file")))
(mode-f (intern (concat base-f "-for-mode"))))
(if (and (buffer-file-name)
(all-the-icons-auto-mode-match?))
(funcall file-f (file-name-nondirectory (buffer-file-name)))
(funcall mode-f major-mode))))
;; Weather icons
(defun all-the-icons-icon-for-weather (weather)
"Get an icon for a WEATHER status."
(let ((icon (all-the-icons-match-to-alist weather all-the-icons-weather-icon-alist)))
(if icon (apply (car icon) (cdr icon)) weather)))
;; Definitions
(eval-and-compile
(defun all-the-icons--function-name (name)
"Get the symbol for an icon function name for icon set NAME."
(intern (concat "all-the-icons-" (downcase (symbol-name name)))))
(defun all-the-icons--family-name (name)
"Get the symbol for an icon family function for icon set NAME."
(intern (concat "all-the-icons-" (downcase (symbol-name name)) "-family")))
(defun all-the-icons--data-name (name)
"Get the symbol for an icon family function for icon set NAME."
(intern (concat "all-the-icons-" (downcase (symbol-name name)) "-data")))
(defun all-the-icons--insert-function-name (name)
"Get the symbol for an icon insert function for icon set NAME."
(intern (concat "all-the-icons-insert-" (downcase (symbol-name name))))))
;; Icon insertion functions
(defun all-the-icons--read-candidates ()
"Helper to build a list of candidates for all families."
(cl-reduce 'append (mapcar (lambda (it) (all-the-icons--read-candidates-for-family it t)) all-the-icons-font-families)))
(defun all-the-icons--read-candidates-for-family (family &optional show-family)
"Helper to build read candidates for FAMILY.
If SHOW-FAMILY is non-nil, displays the icons family in the candidate string."
(let ((data (funcall (all-the-icons--data-name family)))
(icon-f (all-the-icons--function-name family)))
(mapcar
(lambda (it)
(let* ((icon-name (car it))
(icon-name-head (substring icon-name 0 1))
(icon-name-tail (substring icon-name 1))
(icon-display (propertize icon-name-head 'display (format "%s\t%s" (funcall icon-f icon-name) icon-name-head)))
(icon-family (if show-family (format "\t[%s]" family) ""))
(candidate-name (format "%s%s%s" icon-display icon-name-tail icon-family))
(candidate-icon (funcall (all-the-icons--function-name family) icon-name)))
(cons candidate-name candidate-icon)))
data)))
;;;###autoload
(defun all-the-icons-install-fonts (&optional pfx)
"Helper function to download and install the latests fonts based on OS.
When PFX is non-nil, ignore the prompt and just install"
(interactive "P")
(when (or pfx (yes-or-no-p "This will download and install fonts, are you sure you want to do this?"))
(let* ((url-format "https://github.com/domtronn/all-the-icons.el/blob/master/fonts/%s?raw=true")
(font-dest (cl-case window-system
(x (concat (or (getenv "XDG_DATA_HOME") ;; Default Linux install directories
(concat (getenv "HOME") "/.local/share"))
"/fonts/"))
(mac (concat (getenv "HOME") "/Library/Fonts/" ))
(ns (concat (getenv "HOME") "/Library/Fonts/" )))) ;; Default MacOS install directory
(known-dest? (stringp font-dest))
(font-dest (or font-dest (read-directory-name "Font installation directory: " "~/"))))
(unless (file-directory-p font-dest) (mkdir font-dest t))
(mapc (lambda (font)
(url-copy-file (format url-format font) (expand-file-name font font-dest) t))
all-the-icons-font-names)
(when known-dest?
(message "Fonts downloaded, updating font cache... <fc-cache -f -v> ")
(shell-command-to-string (format "fc-cache -f -v")))
(message "%s Successfully %s `all-the-icons' fonts to `%s'!"
(all-the-icons-wicon "stars" :v-adjust 0.0)
(if known-dest? "installed" "downloaded")
font-dest))))
;;;###autoload
(defun all-the-icons-insert (&optional arg family)
"Interactive icon insertion function.
When Prefix ARG is non-nil, insert the propertized icon.
When FAMILY is non-nil, limit the candidates to the icon set matching it."
(interactive "P")
(let* ((standard-output (current-buffer))
(candidates (if family
(all-the-icons--read-candidates-for-family family)
(all-the-icons--read-candidates)))
(prompt (if family
(format "%s Icon: " (funcall (all-the-icons--family-name family)))
"Icon : "))
(selection (completing-read prompt candidates nil t))
(result (cdr (assoc selection candidates))))
(if arg (prin1 result) (insert result))))
;; Debug Helpers
(defun all-the-icons-insert-icons-for (family &optional height duration)
"Insert all of the available icons associated with FAMILY.
If a HEIGHT is provided it will render the icons at this height.
This is useful both to see the icons more clearly and to test
different height rendering. If DURATION is provided, it will
pause for DURATION seconds between printing each character."
(let* ((data-f (all-the-icons--data-name family))
(insert-f (all-the-icons--function-name family))
(height (or height 2.0))
(data (funcall data-f)))
(mapc
(lambda (it)
(insert (format "%s - %s\n" (funcall insert-f (car it) :height height) (car it)))
(when duration (sit-for duration 0)))
data)))
(defmacro define-icon (name alist family &optional font-name)
"Macro to generate functions for inserting icons for icon set NAME.
NAME defines is the name of the iconset and will produce a
function of the for `all-the-icons-NAME'.
ALIST is the alist containing maps between icon names and the
UniCode for the character. All of these can be found in the data
directory of this package.
FAMILY is the font family to use for the icons.
FONT-NAME is the name of the .ttf file providing the font, defaults to FAMILY."
`(progn
(add-to-list 'all-the-icons-font-families (quote ,name))
(add-to-list 'all-the-icons-font-names (quote ,(downcase (format "%s.ttf" (or font-name family)))))
(defun ,(all-the-icons--family-name name) () ,family)
(defun ,(all-the-icons--data-name name) () ,alist)
(defun ,(all-the-icons--function-name name) (icon-name &rest args)
(let ((icon (cdr (assoc icon-name ,alist)))
(other-face (when all-the-icons-color-icons (plist-get args :face)))
(height (* all-the-icons-scale-factor (or (plist-get args :height) 1.0)))
(v-adjust (* all-the-icons-scale-factor (or (plist-get args :v-adjust) all-the-icons-default-adjust)))
(family ,family))
(unless icon
(error (format "Unable to find icon with name `%s' in icon set `%s'" icon-name (quote ,name))))
(propertize icon
'face (if other-face
`(:family ,family :height ,height :inherit ,other-face)
`(:family ,family :height ,height))
'display `(raise ,v-adjust)
'rear-nonsticky t
'font-lock-ignore t)))
(defun ,(all-the-icons--insert-function-name name) (&optional arg)
,(format "Insert a %s icon at point." family)
(interactive "P")
(all-the-icons-insert arg (quote ,name)))))
(define-icon alltheicon all-the-icons-data/alltheicons-alist "all-the-icons")
(define-icon fileicon all-the-icons-data/file-icon-alist "file-icons")
(define-icon faicon all-the-icons-data/fa-icon-alist "FontAwesome")
(define-icon octicon all-the-icons-data/octicons-alist "github-octicons" "octicons")
(define-icon wicon all-the-icons-data/weather-icons-alist "Weather Icons" "weathericons")
(define-icon material all-the-icons-data/material-icons-alist "Material Icons" "material-design-icons")
(provide 'all-the-icons)
;;; all-the-icons.el ends here

View file

@ -0,0 +1,70 @@
(defvar all-the-icons-data/alltheicons-alist
'(
( "apache" . "\xe909" )
( "atom" . "\xe917" )
( "aws" . "\xe90c" )
( "bower" . "\xe918" )
( "c" . "\xe915" )
( "c-line" . "\xe90f" )
( "clojure" . "\xe919" )
( "clojure-line" . "\xe91a" )
( "coffeescript" . "\xe914" )
( "cplusplus" . "\xe913" )
( "cplusplus-line" . "\xe910" )
( "csharp" . "\xe911" )
( "csharp-line" . "\xe912" )
( "css3" . "\xe91b" )
( "css3-alt" . "\xe91c" )
( "d3" . "\xe90e" )
( "dlang" . "\xe935" )
( "elixir" . "\xe936" )
( "erlang" . "\xe934" )
( "git" . "\xe907" )
( "go" . "\xe91d" )
( "google-drive" . "\xe91e" )
( "grunt" . "\xe90d" )
( "grunt-line" . "\xe91f" )
( "gulp" . "\xe920" )
( "haskell" . "\xe921" )
( "html5" . "\xe932" )
( "jasmine" . "\xe904" )
( "java" . "\xe922" )
( "javascript" . "\xe906" )
( "javascript-badge" . "\xe923" )
( "javascript-shield" . "\xe924" )
( "less" . "\xe90b" )
( "nginx" . "\xe933" )
( "nodejs" . "\xe925" )
( "perl" . "\xe905" )
( "perldocs" . "\xe926" )
( "postgresql" . "\xe938" )
( "prolog" . "\xe927" )
( "python" . "\xe928" )
( "react" . "\xe929" )
( "ruby" . "\xe92a" )
( "ruby-alt" . "\xe92b" )
( "rust" . "\xe92c" )
( "sass" . "\xe92d" )
( "scala" . "\xe908" )
( "script" . "\xe90a" )
( "spring" . "\xe937" )
( "stylus" . "\xe92e" )
( "svg" . "\xe903" )
( "swift" . "\xe92f" )
( "terminal" . "\xe930" )
( "terminal-alt" . "\xe931" )
( "battery-charging" . "\xe939" )
( "arrow-left" . "\xe93a" )
( "arrow-right" . "\xe93b" )
( "cup-left" . "\xe93c" )
( "cup-right" . "\xe93d" )
( "slant-left" . "\xe93e" )
( "slant-right" . "\xe93f" )
( "wave-left" . "\xe940" )
( "wave-right" . "\xe941" )
))
(provide 'data-alltheicons)

View file

@ -0,0 +1,641 @@
(defvar all-the-icons-data/fa-icon-alist
'(
("500px" . "\xf26e")
("adjust" . "\xf042")
("adn" . "\xf170")
("align-center" . "\xf037")
("align-justify" . "\xf039")
("align-left" . "\xf036")
("align-right" . "\xf038")
("amazon" . "\xf270")
("ambulance" . "\xf0f9")
("american-sign-language-interpreting" . "\xf2a3")
("anchor" . "\xf13d")
("android" . "\xf17b")
("angellist" . "\xf209")
("angle-double-down" . "\xf103")
("angle-double-left" . "\xf100")
("angle-double-right" . "\xf101")
("angle-double-up" . "\xf102")
("angle-down" . "\xf107")
("angle-left" . "\xf104")
("angle-right" . "\xf105")
("angle-up" . "\xf106")
("apple" . "\xf179")
("archive" . "\xf187")
("area-chart" . "\xf1fe")
("arrow-circle-down" . "\xf0ab")
("arrow-circle-left" . "\xf0a8")
("arrow-circle-o-down" . "\xf01a")
("arrow-circle-o-left" . "\xf190")
("arrow-circle-o-right" . "\xf18e")
("arrow-circle-o-up" . "\xf01b")
("arrow-circle-right" . "\xf0a9")
("arrow-circle-up" . "\xf0aa")
("arrow-down" . "\xf063")
("arrow-left" . "\xf060")
("arrow-right" . "\xf061")
("arrow-up" . "\xf062")
("arrows" . "\xf047")
("arrows-alt" . "\xf0b2")
("arrows-h" . "\xf07e")
("arrows-v" . "\xf07d")
("assistive-listening-systems" . "\xf2a2")
("asterisk" . "\xf069")
("at" . "\xf1fa")
("audio-description" . "\xf29e")
("backward" . "\xf04a")
("balance-scale" . "\xf24e")
("ban" . "\xf05e")
("bar-chart" . "\xf080")
("barcode" . "\xf02a")
("bars" . "\xf0c9")
("battery-empty" . "\xf244")
("battery-full" . "\xf240")
("battery-half" . "\xf242")
("battery-quarter" . "\xf243")
("battery-three-quarters" . "\xf241")
("bed" . "\xf236")
("beer" . "\xf0fc")
("behance" . "\xf1b4")
("behance-square" . "\xf1b5")
("bell" . "\xf0f3")
("bell-o" . "\xf0a2")
("bell-slash" . "\xf1f6")
("bell-slash-o" . "\xf1f7")
("bicycle" . "\xf206")
("binoculars" . "\xf1e5")
("birthday-cake" . "\xf1fd")
("bitbucket" . "\xf171")
("bitbucket-square" . "\xf172")
("black-tie" . "\xf27e")
("blind" . "\xf29d")
("bluetooth" . "\xf293")
("bluetooth-b" . "\xf294")
("bold" . "\xf032")
("bolt" . "\xf0e7")
("bomb" . "\xf1e2")
("book" . "\xf02d")
("bookmark" . "\xf02e")
("bookmark-o" . "\xf097")
("braille" . "\xf2a1")
("briefcase" . "\xf0b1")
("btc" . "\xf15a")
("bug" . "\xf188")
("building" . "\xf1ad")
("building-o" . "\xf0f7")
("bullhorn" . "\xf0a1")
("bullseye" . "\xf140")
("bus" . "\xf207")
("buysellads" . "\xf20d")
("calculator" . "\xf1ec")
("calendar" . "\xf073")
("calendar-check-o" . "\xf274")
("calendar-minus-o" . "\xf272")
("calendar-o" . "\xf133")
("calendar-plus-o" . "\xf271")
("calendar-times-o" . "\xf273")
("camera" . "\xf030")
("camera-retro" . "\xf083")
("car" . "\xf1b9")
("caret-down" . "\xf0d7")
("caret-left" . "\xf0d9")
("caret-right" . "\xf0da")
("caret-square-o-down" . "\xf150")
("caret-square-o-left" . "\xf191")
("caret-square-o-right" . "\xf152")
("caret-square-o-up" . "\xf151")
("caret-up" . "\xf0d8")
("cart-arrow-down" . "\xf218")
("cart-plus" . "\xf217")
("cc" . "\xf20a")
("cc-amex" . "\xf1f3")
("cc-diners-club" . "\xf24c")
("cc-discover" . "\xf1f2")
("cc-jcb" . "\xf24b")
("cc-mastercard" . "\xf1f1")
("cc-paypal" . "\xf1f4")
("cc-stripe" . "\xf1f5")
("cc-visa" . "\xf1f0")
("certificate" . "\xf0a3")
("chain-broken" . "\xf127")
("check" . "\xf00c")
("check-circle" . "\xf058")
("check-circle-o" . "\xf05d")
("check-square" . "\xf14a")
("check-square-o" . "\xf046")
("chevron-circle-down" . "\xf13a")
("chevron-circle-left" . "\xf137")
("chevron-circle-right" . "\xf138")
("chevron-circle-up" . "\xf139")
("chevron-down" . "\xf078")
("chevron-left" . "\xf053")
("chevron-right" . "\xf054")
("chevron-up" . "\xf077")
("child" . "\xf1ae")
("chrome" . "\xf268")
("circle" . "\xf111")
("circle-o" . "\xf10c")
("circle-o-notch" . "\xf1ce")
("circle-thin" . "\xf1db")
("clipboard" . "\xf0ea")
("clock-o" . "\xf017")
("clone" . "\xf24d")
("cloud" . "\xf0c2")
("cloud-download" . "\xf0ed")
("cloud-upload" . "\xf0ee")
("code" . "\xf121")
("code-fork" . "\xf126")
("codepen" . "\xf1cb")
("codiepie" . "\xf284")
("coffee" . "\xf0f4")
("cog" . "\xf013")
("cogs" . "\xf085")
("columns" . "\xf0db")
("comment" . "\xf075")
("comment-o" . "\xf0e5")
("commenting" . "\xf27a")
("commenting-o" . "\xf27b")
("comments" . "\xf086")
("comments-o" . "\xf0e6")
("compass" . "\xf14e")
("compress" . "\xf066")
("connectdevelop" . "\xf20e")
("contao" . "\xf26d")
("copyright" . "\xf1f9")
("creative-commons" . "\xf25e")
("credit-card" . "\xf09d")
("credit-card-alt" . "\xf283")
("crop" . "\xf125")
("crosshairs" . "\xf05b")
("css3" . "\xf13c")
("cube" . "\xf1b2")
("cubes" . "\xf1b3")
("cutlery" . "\xf0f5")
("dashcube" . "\xf210")
("database" . "\xf1c0")
("deaf" . "\xf2a4")
("delicious" . "\xf1a5")
("desktop" . "\xf108")
("deviantart" . "\xf1bd")
("diamond" . "\xf219")
("digg" . "\xf1a6")
("dot-circle-o" . "\xf192")
("download" . "\xf019")
("dribbble" . "\xf17d")
("dropbox" . "\xf16b")
("drupal" . "\xf1a9")
("edge" . "\xf282")
("eject" . "\xf052")
("ellipsis-h" . "\xf141")
("ellipsis-v" . "\xf142")
("empire" . "\xf1d1")
("envelope" . "\xf0e0")
("envelope-o" . "\xf003")
("envelope-square" . "\xf199")
("envira" . "\xf299")
("eraser" . "\xf12d")
("eur" . "\xf153")
("exchange" . "\xf0ec")
("exclamation" . "\xf12a")
("exclamation-circle" . "\xf06a")
("exclamation-triangle" . "\xf071")
("expand" . "\xf065")
("expeditedssl" . "\xf23e")
("external-link" . "\xf08e")
("external-link-square" . "\xf14c")
("eye" . "\xf06e")
("eye-slash" . "\xf070")
("eyedropper" . "\xf1fb")
("facebook" . "\xf09a")
("facebook-official" . "\xf230")
("facebook-square" . "\xf082")
("fast-backward" . "\xf049")
("fast-forward" . "\xf050")
("fax" . "\xf1ac")
("female" . "\xf182")
("fighter-jet" . "\xf0fb")
("file" . "\xf15b")
("file-archive-o" . "\xf1c6")
("file-audio-o" . "\xf1c7")
("file-code-o" . "\xf1c9")
("file-excel-o" . "\xf1c3")
("file-image-o" . "\xf1c5")
("file-o" . "\xf016")
("file-pdf-o" . "\xf1c1")
("file-powerpoint-o" . "\xf1c4")
("file-text" . "\xf15c")
("file-text-o" . "\xf0f6")
("file-video-o" . "\xf1c8")
("file-word-o" . "\xf1c2")
("files-o" . "\xf0c5")
("film" . "\xf008")
("filter" . "\xf0b0")
("fire" . "\xf06d")
("fire-extinguisher" . "\xf134")
("firefox" . "\xf269")
("first-order" . "\xf2b0")
("flag" . "\xf024")
("flag-checkered" . "\xf11e")
("flag-o" . "\xf11d")
("flask" . "\xf0c3")
("flickr" . "\xf16e")
("floppy-o" . "\xf0c7")
("folder" . "\xf07b")
("folder-o" . "\xf114")
("folder-open" . "\xf07c")
("folder-open-o" . "\xf115")
("font" . "\xf031")
("font-awesome" . "\xf2b4")
("fonticons" . "\xf280")
("fort-awesome" . "\xf286")
("forumbee" . "\xf211")
("forward" . "\xf04e")
("foursquare" . "\xf180")
("frown-o" . "\xf119")
("futbol-o" . "\xf1e3")
("gamepad" . "\xf11b")
("gavel" . "\xf0e3")
("gbp" . "\xf154")
("genderless" . "\xf22d")
("get-pocket" . "\xf265")
("gg" . "\xf260")
("gg-circle" . "\xf261")
("gift" . "\xf06b")
("git" . "\xf1d3")
("git-square" . "\xf1d2")
("github" . "\xf09b")
("github-alt" . "\xf113")
("github-square" . "\xf092")
("gitlab" . "\xf296")
("glass" . "\xf000")
("glide" . "\xf2a5")
("glide-g" . "\xf2a6")
("globe" . "\xf0ac")
("google" . "\xf1a0")
("google-plus" . "\xf0d5")
("google-plus-official" . "\xf2b3")
("google-plus-square" . "\xf0d4")
("google-wallet" . "\xf1ee")
("graduation-cap" . "\xf19d")
("gratipay" . "\xf184")
("h-square" . "\xf0fd")
("hacker-news" . "\xf1d4")
("hand-lizard-o" . "\xf258")
("hand-o-down" . "\xf0a7")
("hand-o-left" . "\xf0a5")
("hand-o-right" . "\xf0a4")
("hand-o-up" . "\xf0a6")
("hand-paper-o" . "\xf256")
("hand-peace-o" . "\xf25b")
("hand-pointer-o" . "\xf25a")
("hand-rock-o" . "\xf255")
("hand-scissors-o" . "\xf257")
("hand-spock-o" . "\xf259")
("hashtag" . "\xf292")
("hdd-o" . "\xf0a0")
("header" . "\xf1dc")
("headphones" . "\xf025")
("heart" . "\xf004")
("heart-o" . "\xf08a")
("heartbeat" . "\xf21e")
("history" . "\xf1da")
("home" . "\xf015")
("hospital-o" . "\xf0f8")
("hourglass" . "\xf254")
("hourglass-end" . "\xf253")
("hourglass-half" . "\xf252")
("hourglass-o" . "\xf250")
("hourglass-start" . "\xf251")
("houzz" . "\xf27c")
("html5" . "\xf13b")
("i-cursor" . "\xf246")
("ils" . "\xf20b")
("inbox" . "\xf01c")
("indent" . "\xf03c")
("industry" . "\xf275")
("info" . "\xf129")
("info-circle" . "\xf05a")
("inr" . "\xf156")
("instagram" . "\xf16d")
("internet-explorer" . "\xf26b")
("ioxhost" . "\xf208")
("italic" . "\xf033")
("joomla" . "\xf1aa")
("jpy" . "\xf157")
("jsfiddle" . "\xf1cc")
("key" . "\xf084")
("keyboard-o" . "\xf11c")
("krw" . "\xf159")
("language" . "\xf1ab")
("laptop" . "\xf109")
("lastfm" . "\xf202")
("lastfm-square" . "\xf203")
("leaf" . "\xf06c")
("leanpub" . "\xf212")
("lemon-o" . "\xf094")
("level-down" . "\xf149")
("level-up" . "\xf148")
("life-ring" . "\xf1cd")
("lightbulb-o" . "\xf0eb")
("line-chart" . "\xf201")
("link" . "\xf0c1")
("linkedin" . "\xf0e1")
("linkedin-square" . "\xf08c")
("linux" . "\xf17c")
("list" . "\xf03a")
("list-alt" . "\xf022")
("list-ol" . "\xf0cb")
("list-ul" . "\xf0ca")
("location-arrow" . "\xf124")
("lock" . "\xf023")
("long-arrow-down" . "\xf175")
("long-arrow-left" . "\xf177")
("long-arrow-right" . "\xf178")
("long-arrow-up" . "\xf176")
("low-vision" . "\xf2a8")
("magic" . "\xf0d0")
("magnet" . "\xf076")
("male" . "\xf183")
("map" . "\xf279")
("map-marker" . "\xf041")
("map-o" . "\xf278")
("map-pin" . "\xf276")
("map-signs" . "\xf277")
("mars" . "\xf222")
("mars-double" . "\xf227")
("mars-stroke" . "\xf229")
("mars-stroke-h" . "\xf22b")
("mars-stroke-v" . "\xf22a")
("maxcdn" . "\xf136")
("meanpath" . "\xf20c")
("medium" . "\xf23a")
("medkit" . "\xf0fa")
("meh-o" . "\xf11a")
("mercury" . "\xf223")
("microphone" . "\xf130")
("microphone-slash" . "\xf131")
("minus" . "\xf068")
("minus-circle" . "\xf056")
("minus-square" . "\xf146")
("minus-square-o" . "\xf147")
("mixcloud" . "\xf289")
("mobile" . "\xf10b")
("modx" . "\xf285")
("money" . "\xf0d6")
("moon-o" . "\xf186")
("motorcycle" . "\xf21c")
("mouse-pointer" . "\xf245")
("music" . "\xf001")
("neuter" . "\xf22c")
("newspaper-o" . "\xf1ea")
("object-group" . "\xf247")
("object-ungroup" . "\xf248")
("odnoklassniki" . "\xf263")
("odnoklassniki-square" . "\xf264")
("opencart" . "\xf23d")
("openid" . "\xf19b")
("opera" . "\xf26a")
("optin-monster" . "\xf23c")
("outdent" . "\xf03b")
("pagelines" . "\xf18c")
("paint-brush" . "\xf1fc")
("paper-plane" . "\xf1d8")
("paper-plane-o" . "\xf1d9")
("paperclip" . "\xf0c6")
("paragraph" . "\xf1dd")
("pause" . "\xf04c")
("pause-circle" . "\xf28b")
("pause-circle-o" . "\xf28c")
("paw" . "\xf1b0")
("paypal" . "\xf1ed")
("pencil" . "\xf040")
("pencil-square" . "\xf14b")
("pencil-square-o" . "\xf044")
("percent" . "\xf295")
("phone" . "\xf095")
("phone-square" . "\xf098")
("picture-o" . "\xf03e")
("pie-chart" . "\xf200")
("pied-piper" . "\xf2ae")
("pied-piper-alt" . "\xf1a8")
("pied-piper-pp" . "\xf1a7")
("pinterest" . "\xf0d2")
("pinterest-p" . "\xf231")
("pinterest-square" . "\xf0d3")
("plane" . "\xf072")
("play" . "\xf04b")
("play-circle" . "\xf144")
("play-circle-o" . "\xf01d")
("plug" . "\xf1e6")
("plus" . "\xf067")
("plus-circle" . "\xf055")
("plus-square" . "\xf0fe")
("plus-square-o" . "\xf196")
("power-off" . "\xf011")
("print" . "\xf02f")
("product-hunt" . "\xf288")
("puzzle-piece" . "\xf12e")
("qq" . "\xf1d6")
("qrcode" . "\xf029")
("question" . "\xf128")
("question-circle" . "\xf059")
("question-circle-o" . "\xf29c")
("quote-left" . "\xf10d")
("quote-right" . "\xf10e")
("random" . "\xf074")
("rebel" . "\xf1d0")
("recycle" . "\xf1b8")
("reddit" . "\xf1a1")
("reddit-alien" . "\xf281")
("reddit-square" . "\xf1a2")
("refresh" . "\xf021")
("registered" . "\xf25d")
("renren" . "\xf18b")
("repeat" . "\xf01e")
("reply" . "\xf112")
("reply-all" . "\xf122")
("retweet" . "\xf079")
("road" . "\xf018")
("rocket" . "\xf135")
("rss" . "\xf09e")
("rss-square" . "\xf143")
("rub" . "\xf158")
("safari" . "\xf267")
("scissors" . "\xf0c4")
("scribd" . "\xf28a")
("search" . "\xf002")
("search-minus" . "\xf010")
("search-plus" . "\xf00e")
("sellsy" . "\xf213")
("server" . "\xf233")
("share" . "\xf064")
("share-alt" . "\xf1e0")
("share-alt-square" . "\xf1e1")
("share-square" . "\xf14d")
("share-square-o" . "\xf045")
("shield" . "\xf132")
("ship" . "\xf21a")
("shirtsinbulk" . "\xf214")
("shopping-bag" . "\xf290")
("shopping-basket" . "\xf291")
("shopping-cart" . "\xf07a")
("sign-in" . "\xf090")
("sign-language" . "\xf2a7")
("sign-out" . "\xf08b")
("signal" . "\xf012")
("simplybuilt" . "\xf215")
("sitemap" . "\xf0e8")
("skyatlas" . "\xf216")
("skype" . "\xf17e")
("slack" . "\xf198")
("sliders" . "\xf1de")
("slideshare" . "\xf1e7")
("smile-o" . "\xf118")
("snapchat" . "\xf2ab")
("snapchat-ghost" . "\xf2ac")
("snapchat-square" . "\xf2ad")
("sort" . "\xf0dc")
("sort-alpha-asc" . "\xf15d")
("sort-alpha-desc" . "\xf15e")
("sort-amount-asc" . "\xf160")
("sort-amount-desc" . "\xf161")
("sort-asc" . "\xf0de")
("sort-desc" . "\xf0dd")
("sort-numeric-asc" . "\xf162")
("sort-numeric-desc" . "\xf163")
("soundcloud" . "\xf1be")
("space-shuttle" . "\xf197")
("spinner" . "\xf110")
("spoon" . "\xf1b1")
("spotify" . "\xf1bc")
("square" . "\xf0c8")
("square-o" . "\xf096")
("stack-exchange" . "\xf18d")
("stack-overflow" . "\xf16c")
("star" . "\xf005")
("star-half" . "\xf089")
("star-half-o" . "\xf123")
("star-o" . "\xf006")
("steam" . "\xf1b6")
("steam-square" . "\xf1b7")
("step-backward" . "\xf048")
("step-forward" . "\xf051")
("stethoscope" . "\xf0f1")
("sticky-note" . "\xf249")
("sticky-note-o" . "\xf24a")
("stop" . "\xf04d")
("stop-circle" . "\xf28d")
("stop-circle-o" . "\xf28e")
("street-view" . "\xf21d")
("strikethrough" . "\xf0cc")
("stumbleupon" . "\xf1a4")
("stumbleupon-circle" . "\xf1a3")
("subscript" . "\xf12c")
("subway" . "\xf239")
("suitcase" . "\xf0f2")
("sun-o" . "\xf185")
("superscript" . "\xf12b")
("table" . "\xf0ce")
("tablet" . "\xf10a")
("tachometer" . "\xf0e4")
("tag" . "\xf02b")
("tags" . "\xf02c")
("tasks" . "\xf0ae")
("taxi" . "\xf1ba")
("television" . "\xf26c")
("tencent-weibo" . "\xf1d5")
("terminal" . "\xf120")
("text-height" . "\xf034")
("text-width" . "\xf035")
("th" . "\xf00a")
("th-large" . "\xf009")
("th-list" . "\xf00b")
("themeisle" . "\xf2b2")
("thumb-tack" . "\xf08d")
("thumbs-down" . "\xf165")
("thumbs-o-down" . "\xf088")
("thumbs-o-up" . "\xf087")
("thumbs-up" . "\xf164")
("ticket" . "\xf145")
("times" . "\xf00d")
("times-circle" . "\xf057")
("times-circle-o" . "\xf05c")
("tint" . "\xf043")
("toggle-off" . "\xf204")
("toggle-on" . "\xf205")
("trademark" . "\xf25c")
("train" . "\xf238")
("transgender" . "\xf224")
("transgender-alt" . "\xf225")
("trash" . "\xf1f8")
("trash-o" . "\xf014")
("tree" . "\xf1bb")
("trello" . "\xf181")
("tripadvisor" . "\xf262")
("trophy" . "\xf091")
("truck" . "\xf0d1")
("try" . "\xf195")
("tty" . "\xf1e4")
("tumblr" . "\xf173")
("tumblr-square" . "\xf174")
("twitch" . "\xf1e8")
("twitter" . "\xf099")
("twitter-square" . "\xf081")
("umbrella" . "\xf0e9")
("underline" . "\xf0cd")
("undo" . "\xf0e2")
("universal-access" . "\xf29a")
("university" . "\xf19c")
("unlock" . "\xf09c")
("unlock-alt" . "\xf13e")
("upload" . "\xf093")
("usb" . "\xf287")
("usd" . "\xf155")
("user" . "\xf007")
("user-md" . "\xf0f0")
("user-plus" . "\xf234")
("user-secret" . "\xf21b")
("user-times" . "\xf235")
("users" . "\xf0c0")
("venus" . "\xf221")
("venus-double" . "\xf226")
("venus-mars" . "\xf228")
("viacoin" . "\xf237")
("viadeo" . "\xf2a9")
("viadeo-square" . "\xf2aa")
("video-camera" . "\xf03d")
("vimeo" . "\xf27d")
("vimeo-square" . "\xf194")
("vine" . "\xf1ca")
("vk" . "\xf189")
("volume-control-phone" . "\xf2a0")
("volume-down" . "\xf027")
("volume-off" . "\xf026")
("volume-up" . "\xf028")
("weibo" . "\xf18a")
("weixin" . "\xf1d7")
("whatsapp" . "\xf232")
("wheelchair" . "\xf193")
("wheelchair-alt" . "\xf29b")
("wifi" . "\xf1eb")
("wikipedia-w" . "\xf266")
("windows" . "\xf17a")
("wordpress" . "\xf19a")
("wpbeginner" . "\xf297")
("wpforms" . "\xf298")
("wrench" . "\xf0ad")
("xing" . "\xf168")
("xing-square" . "\xf169")
("y-combinator" . "\xf23b")
("yahoo" . "\xf19e")
("yelp" . "\xf1e9")
("yoast" . "\xf2b1")
("youtube" . "\xf167")
("youtube-play" . "\xf16a")
("youtube-square" . "\xf166")
))
(provide 'data-faicons)

View file

@ -0,0 +1,487 @@
(defvar all-the-icons-data/file-icon-alist
'(
( "1c" . "\xa5ea" )
( "1c-alt" . "\xea28" )
( "MJML" . "\xea6f" )
( "R" . "\xe905" )
( "abap" . "\xe92b" )
( "abif" . "\xea4e" )
( "access" . "\xe9ea" )
( "actionscript" . "\xe92e" )
( "ada" . "\xe90b" )
( "ae" . "\xe9f3" )
( "ai" . "\xe6b4" )
( "akka" . "\xea0e" )
( "alex" . "\x29cb" )
( "alloy" . "\xe935" )
( "alpine-linux" . "\xe9ff" )
( "ampl" . "\xe94e" )
( "amx" . "\xe99b" )
( "angelscript" . "\xea5b" )
( "ansible" . "\x24b6" )
( "ansible-alt" . "\x61" )
( "ant" . "\xe93e" )
( "antlr" . "\xe92c" )
( "antwar" . "\x2591" )
( "api-blueprint" . "\xe92d" )
( "apl" . "\x234b" )
( "apl-old" . "\xe909" )
( "apple" . "\xe925" )
( "appveyor" . "\xe923" )
( "arc" . "\xe92f" )
( "arch-linux" . "\x41" )
( "arduino" . "\xe930" )
( "arttext" . "\x24d0" )
( "asciidoc" . "\xe918" )
( "ats" . "\xe934" )
( "audacity" . "\xe9f9" )
( "augeas" . "\xe931" )
( "aurelia" . "\xea48" )
( "auto-hotkey" . "\xe932" )
( "autoit" . "\xe933" )
( "babel" . "\xe91f" )
( "bazel" . "\xea5a" )
( "bem" . "\xea59" )
( "bib" . "\xe601" )
( "bintray" . "\xea6e" )
( "bithound" . "\xea2a" )
( "blender" . "\xe9fa" )
( "bluespec" . "\xe93c" )
( "boo" . "\xe939" )
( "brain" . "\xe93a" )
( "brakeman" . "\xe9d6" )
( "bro" . "\xe93b" )
( "broccoli" . "\xe922" )
( "brotli" . "\xea6c" )
( "browserslist" . "\xea80" )
( "brunch" . "\xea47" )
( "buck" . "\xea46" )
( "build-boot" . "\xf103" )
( "bundler" . "\xea45" )
( "byond" . "\xe962" )
( "cabal" . "\xe9c2" )
( "caddy" . "\xea58" )
( "cake" . "\xe9e3" )
( "cakefile" . "\xe924" )
( "cakephp" . "\xea43" )
( "cakephp-old" . "\xe9d3" )
( "cc" . "\xe9d5" )
( "ceylon" . "\xe94f" )
( "chai" . "\x63" )
( "chapel" . "\xe950" )
( "chartjs" . "\xea0b" )
( "chef" . "\xea42" )
( "chuck" . "\xe943" )
( "circle-ci" . "\xea12" )
( "cirru" . "\xe951" )
( "ckeditor" . "\xea0c" )
( "clarion" . "\xe952" )
( "clean" . "\xe95b" )
( "click" . "\xe95c" )
( "clips" . "\xe940" )
( "clj" . "\xf105" )
( "cljs" . "\xf104" )
( "closure-template" . "\xea82" )
( "cmake" . "\xe93f" )
( "cobol" . "\xea44" )
( "codecov" . "\x2602" )
( "codekit" . "\xea41" )
( "codemirror" . "\xea0d" )
( "codeship" . "\xea6a" )
( "cold-fusion" . "\xe929" )
( "clisp" . "\xe972" )
( "composer" . "\xe683" )
( "config" . "\xf07c" )
( "coq" . "\xe95f" )
( "cordova" . "\xea11" )
( "cp" . "\xe942" )
( "cpan" . "\xea87" )
( "creole" . "\xe95e" )
( "crystal" . "\xe902" )
( "cs-script" . "\xe9e2" )
( "csound" . "\xe9f0" )
( "cucumber" . "\xf02b" )
( "cython" . "\xe963" )
( "d3" . "\xea10" )
( "darcs" . "\xe964" )
( "dashboard" . "\xf07d" )
( "dbase" . "\xe9f1" )
( "default" . "\x1f5cc" )
( "delphi" . "\xea40" )
( "devicetree" . "\xea57" )
( "diff" . "\xe960" )
( "dockerfile" . "\xf106" )
( "doclets" . "\xea3f" )
( "doge" . "\xe946" )
( "dom" . "\xea71" )
( "donejs" . "\x1f3c1" )
( "doxygen" . "\xe928" )
( "dragula" . "\x1f44c" )
( "drone" . "\xea3d" )
( "dyalog" . "\xe90c" )
( "dylib" . "\xea15" )
( "e" . "\x45" )
( "eagle" . "\xe965" )
( "easybuild" . "\xea85" )
( "ec" . "\xe9c9" )
( "ecere" . "\xe966" )
( "edge" . "\xea78" )
( "editorconfig" . "\xea1b" )
( "eiffel" . "\xe967" )
( "ejs" . "\xea4b" )
( "electron" . "\xea27" )
( "elm" . "\xf102" )
( "emacs" . "\xe926" )
( "elisp" . "\xe926" )
( "ember" . "\xe61b" )
( "emberscript" . "\xe968" )
( "eq" . "\xea0a" )
( "esdoc" . "\xea5c" )
( "eslint" . "\xea0f" )
( "eslint-old" . "\xe90e" )
( "excel" . "\xe9ee" )
( "fabfile" . "\xe94b" )
( "factor" . "\xe96a" )
( "fancy" . "\xe96b" )
( "fantom" . "\xe96f" )
( "fbx" . "\xe9fc" )
( "ffmpeg" . "\xea22" )
( "finder" . "\xe9e9" )
( "firebase" . "\xea7f" )
( "flow" . "\xe921" )
( "flux" . "\xe969" )
( "font" . "\xe90f" )
( "fontforge" . "\xfb00" )
( "fortran" . "\xe90a" )
( "franca" . "\xea56" )
( "freemarker" . "\xe970" )
( "frege" . "\xe96e" )
( "fuel-ux" . "\xea09" )
( "gams" . "\xe973" )
( "gap" . "\xe971" )
( "gdb" . "\xea08" )
( "genshi" . "\xe976" )
( "gentoo" . "\xe96d" )
( "gf" . "\xe978" )
( "gitlab" . "\xea3c" )
( "glade" . "\xe938" )
( "glyphs" . "\x47" )
( "gn" . "\xea25" )
( "gnu" . "\xe679" )
( "go" . "\xe624" )
( "godot" . "\xe974" )
( "golo" . "\xe979" )
( "gosu" . "\xe97a" )
( "gradle" . "\xe903" )
( "graphql" . "\xe97c" )
( "graphviz" . "\xe97d" )
( "groovy" . "\xe904" )
( "grunt" . "\xe611" )
( "gulp" . "\xe610" )
( "hack" . "\xe9ce" )
( "haml" . "\xf15b" )
( "harbour" . "\xe97b" )
( "hashicorp" . "\xe97e" )
( "haxe" . "\xe907" )
( "haxedevelop" . "\xea3b" )
( "hg" . "\x263f" )
( "hoplon" . "\xea4d" )
( "hy" . "\xe97f" )
( "icu" . "\xea23" )
( "id" . "\xe9f4" )
( "idl" . "\xe947" )
( "idris" . "\xe983" )
( "igorpro" . "\xe980" )
( "image" . "\xf012" )
( "inform7" . "\xe984" )
( "inno" . "\xe985" )
( "io" . "\xe981" )
( "ioke" . "\xe982" )
( "ionic-project" . "\xf14b" )
( "isabelle" . "\xe945" )
( "j" . "\xe937" )
( "jade" . "\xe90d" )
( "jake" . "\xe948" )
( "jasmine" . "\xea3a" )
( "jenkins" . "\xe667" )
( "jest" . "\xea39" )
( "jinja" . "\xe944" )
( "jison" . "\xea55" )
( "jolie" . "\xea75" )
( "jsonld" . "\xe958" )
( "jsx" . "\xf100" )
( "jsx-2" . "\xf101" )
( "jsx2-alt" . "\xe9e6" )
( "julia" . "\x26ec" )
( "junos" . "\xea81" )
( "jupyter" . "\xe987" )
( "karma" . "\xe9cd" )
( "keynote" . "\xe9e5" )
( "khronos" . "\xe9f8" )
( "kicad" . "\xea4c" )
( "kitchenci" . "\xea38" )
( "kivy" . "\xe901" )
( "knockout" . "\x4b" )
( "kotlin" . "\xe989" )
( "krl" . "\xe988" )
( "labview" . "\xe98a" )
( "lasso" . "\xe98c" )
( "leaflet" . "\xea07" )
( "lean" . "\x4c" )
( "lerna" . "\xea37" )
( "lfe" . "\xe94c" )
( "libuv" . "\xea21" )
( "lightwave" . "\xe9fb" )
( "lime" . "\xea36" )
( "lisp" . "\xe908" )
( "livescript" . "\xe914" )
( "llvm" . "\xe91d" )
( "logtalk" . "\xe98d" )
( "lookml" . "\xe98e" )
( "lsl" . "\xe98b" )
( "lua" . "\xe91b" )
( "mako" . "\xe98f" )
( "man-page" . "\xe936" )
( "mapbox" . "\xe941" )
( "markdownlint" . "\xf0c9" )
( "marko" . "\xe920" )
( "mathematica" . "\xe990" )
( "mathjax" . "\xea06" )
( "matlab" . "\xe991" )
( "max" . "\xe993" )
( "maxscript" . "\xe900" )
( "maya" . "\xe9f6" )
( "mediawiki" . "\xe954" )
( "mercury" . "\xe994" )
( "meson" . "\xea54" )
( "metal" . "\x4d" )
( "meteor" . "\xe6a5" )
( "microsoft-infopath" . "\xea35" )
( "minecraft" . "\xe9dc" )
( "minizinc" . "\xea53" )
( "mirah" . "\xe995" )
( "miranda" . "\xea52" )
( "mocha" . "\x26fe" )
( "modula-2" . "\xe996" )
( "moment" . "\x1f558" )
( "moment-tz" . "\x1f30d" )
( "monkey" . "\xe997" )
( "moustache" . "\xe60f" )
( "mruby" . "\xea18" )
( "mupad" . "\xe9ca" )
( "nano" . "\xea76" )
( "nanoc" . "\xea51" )
( "nant" . "\xe9e1" )
( "nasm" . "\xea72" )
( "neko" . "\xea05" )
( "netlogo" . "\xe99c" )
( "new-relic" . "\xe9d7" )
( "nginx" . "\xf146b" )
( "nib" . "\x2712" )
( "nimrod" . "\xe998" )
( "nit" . "\xe999" )
( "nix" . "\xe99a" )
( "nmap" . "\xe94d" )
( "nodemon" . "\xea26" )
( "normalize" . "\xea04" )
( "npm" . "\xe91c" )
( "npm-old" . "\xf17b" )
( "nsis" . "\xea1e" )
( "nsis-old" . "\xe992" )
( "nuclide" . "\xea34" )
( "nuget" . "\xe9d9" )
( "numpy" . "\xe99d" )
( "nunjucks" . "\xe953" )
( "nvidia" . "\xe95d" )
( "nxc" . "\xea6b" )
( "obj" . "\xe9e8" )
( "objective-j" . "\xe99e" )
( "ocaml" . "\xe91a" )
( "octave" . "\xea33" )
( "onenote" . "\xe9eb" )
( "ooc" . "\xe9cb" )
( "opa" . "\x2601" )
( "opencl" . "\xe99f" )
( "opengl" . "\xea7a" )
( "openoffice" . "\xe9e4" )
( "openscad" . "\xe911" )
( "org" . "\xe917" )
( "owl" . "\xe957" )
( "ox" . "\xe9a1" )
( "oxygene" . "\xe9bf" )
( "oz" . "\xe9be" )
( "p4" . "\xea50" )
( "pan" . "\xe9bd" )
( "papyrus" . "\xe9bc" )
( "parrot" . "\xe9bb" )
( "pascal" . "\xe92a" )
( "patch" . "\xe961" )
( "pawn" . "\x265f" )
( "pb" . "\xea14" )
( "pegjs" . "\xea74" )
( "perl6" . "\xe96c" )
( "phalcon" . "\xe94a" )
( "phoenix" . "\xea5f" )
( "php" . "\xf147" )
( "phpunit" . "\xea32" )
( "pickle" . "\xe9c4" )
( "pike" . "\xe9b9" )
( "platformio" . "\xea2c" )
( "pm2" . "\x2630" )
( "pod" . "\xea84" )
( "pogo" . "\xe9b8" )
( "pointwise" . "\xe977" )
( "polymer" . "\xea2b" )
( "pony" . "\xe9b7" )
( "postcss" . "\xe910" )
( "postscript" . "\xe955" )
( "povray" . "\x50" )
( "powerpoint" . "\xe9ec" )
( "powershell" . "\xe9da" )
( "precision" . "\x2295" )
( "premiere" . "\xe9f5" )
( "processing" . "\xe9a0" )
( "progress" . "\xe9c0" )
( "propeller" . "\xe9b5" )
( "proselint" . "\xea6d" )
( "protractor" . "\xe9de" )
( "ps" . "\xe6b8" )
( "pug" . "\xea13" )
( "pug-alt" . "\xe9d0" )
( "puppet" . "\xf0c3" )
( "purebasic" . "\x1b5" )
( "purescript" . "\xe9b2" )
( "racket" . "\xe9b1" )
( "raml" . "\xe913" )
( "rascal" . "\xea24" )
( "rdoc" . "\xe9b0" )
( "realbasic" . "\xe9af" )
( "reason" . "\xea1d" )
( "rebol" . "\xe9ae" )
( "red" . "\xe9ad" )
( "redux" . "\xea30" )
( "regex" . "\x2a" )
( "rexx" . "\xea16" )
( "rhino" . "\xea4a" )
( "ring" . "\x1f48d" )
( "riot" . "\xe919" )
( "robot" . "\xe9ac" )
( "rollup" . "\xea20" )
( "rollup-old" . "\xe9fd" )
( "rot" . "\x1f764" )
( "rspec" . "\xea31" )
( "rst" . "\xe9cc" )
( "sage" . "\xe9ab" )
( "saltstack" . "\xe915" )
( "sas" . "\xe95a" )
( "sbt" . "\xe9d2" )
( "sc" . "\xe9a2" )
( "scheme" . "\x3bb" )
( "scilab" . "\xe9a9" )
( "scrutinizer" . "\xe9d4" )
( "self" . "\xe9a8" )
( "sequelize" . "\xea2f" )
( "sf" . "\xe9db" )
( "shen" . "\xe9a7" )
( "shipit" . "\x26f5" )
( "shippable" . "\xea2d" )
( "shopify" . "\xe9cf" )
( "shuriken" . "\x272b" )
( "silverstripe" . "\xe800" )
( "sinatra" . "\xea03" )
( "sketch" . "\xe927" )
( "sketchup-layout" . "\xea7c" )
( "sketchup-make" . "\xea7e" )
( "sketchup-stylebuilder" . "\xea7d" )
( "slash" . "\xe9a6" )
( "snyk" . "\xea1c" )
( "solidity" . "\xea86" )
( "sparql" . "\xe959" )
( "spray" . "\xea02" )
( "sqf" . "\xe9a5" )
( "sqlite" . "\xe9dd" )
( "squarespace" . "\xea5e" )
( "stan" . "\xe9a4" )
( "stata" . "\xe9a3" )
( "storyist" . "\xe9ef" )
( "strings" . "\xe9e0" )
( "stylelint" . "\xe93d" )
( "stylus" . "\x73" )
( "stylus-full" . "\xe9f7" )
( "stylus-orb" . "\x53" )
( "sublime" . "\xe986" )
( "sv" . "\xe9c3" )
( "svn" . "\xea17" )
( "swagger" . "\xea29" )
( "tag" . "\xf015" )
( "tcl" . "\xe956" )
( "telegram" . "\x2708" )
( "terminal" . "\xf0c8" )
( "tern" . "\x1f54a" )
( "terraform" . "\xe916" )
( "test-coffeescript" . "\xea62" )
( "test-dir" . "\xea60" )
( "test-generic" . "\xea63" )
( "test-js" . "\xea64" )
( "test-perl" . "\xea65" )
( "test-python" . "\xea66" )
( "test-react" . "\xea67" )
( "test-ruby" . "\xea68" )
( "test-typescript" . "\xea69" )
( "tex" . "\xe600" )
( "textile" . "\x74" )
( "textmate" . "\x2122" )
( "thor" . "\xe9d8" )
( "tinymce" . "\xea01" )
( "tsx" . "\xe9d1" )
( "tsx-alt" . "\xe9e7" )
( "tt" . "\x54" )
( "turing" . "\xe9b6" )
( "twig" . "\x2e19" )
( "twine" . "\xea5d" )
( "txl" . "\xe9c1" )
( "typedoc" . "\xe9fe" )
( "typescript" . "\xe912" )
( "typescript-alt" . "\x2a6" )
( "typings" . "\xe9df" )
( "uno" . "\xe9b3" )
( "unreal" . "\x75" )
( "urweb" . "\xe9ba" )
( "v8" . "\xea1f" )
( "vagrant" . "\x56" )
( "vcl" . "\xe9b4" )
( "verilog" . "\xe949" )
( "vertex-shader" . "\xea79" )
( "vhdl" . "\xe9aa" )
( "video" . "\xf057" )
( "virtualbox" . "\xea3e" )
( "virtualbox-alt" . "\xea2e" )
( "visio" . "\xea83" )
( "vmware" . "\xea49" )
( "vue" . "\xe906" )
( "wasm" . "\xea70" )
( "watchman" . "\xea4f" )
( "webgl" . "\xea7b" )
( "webpack" . "\xea61" )
( "webpack-old" . "\xe91e" )
( "wercker" . "\xea19" )
( "word" . "\xe9ed" )
( "x10" . "\x2169" )
( "xamarin" . "\xea77" )
( "xmos" . "\x58" )
( "xpages" . "\xe9c5" )
( "xtend" . "\xe9c6" )
( "yarn" . "\xea1a" )
( "yasm" . "\xea73" )
( "yin-yang" . "\x262f" )
( "yoyo" . "\xe975" )
( "yui" . "\xea00" )
( "zbrush" . "\xe9f2" )
( "zephir" . "\xe9c7" )
( "zimpl" . "\xe9c8" )
)
)
(provide 'data-fileicons)

View file

@ -0,0 +1,935 @@
(defvar all-the-icons-data/material-icons-alist
'(("3d_rotation" . "\xe84d")
("ac_unit" . "\xeb3b")
("access_alarm" . "\xe190")
("access_alarms" . "\xe191")
("access_time" . "\xe192")
("accessibility" . "\xe84e")
("accessible" . "\xe914")
("account_balance" . "\xe84f")
("account_balance_wallet" . "\xe850")
("account_box" . "\xe851")
("account_circle" . "\xe853")
("adb" . "\xe60e")
("add" . "\xe145")
("add_a_photo" . "\xe439")
("add_alarm" . "\xe193")
("add_alert" . "\xe003")
("add_box" . "\xe146")
("add_circle" . "\xe147")
("add_circle_outline" . "\xe148")
("add_location" . "\xe567")
("add_shopping_cart" . "\xe854")
("add_to_photos" . "\xe39d")
("add_to_queue" . "\xe05c")
("adjust" . "\xe39e")
("airline_seat_flat" . "\xe630")
("airline_seat_flat_angled" . "\xe631")
("airline_seat_individual_suite" . "\xe632")
("airline_seat_legroom_extra" . "\xe633")
("airline_seat_legroom_normal" . "\xe634")
("airline_seat_legroom_reduced" . "\xe635")
("airline_seat_recline_extra" . "\xe636")
("airline_seat_recline_normal" . "\xe637")
("airplanemode_active" . "\xe195")
("airplanemode_inactive" . "\xe194")
("airplay" . "\xe055")
("airport_shuttle" . "\xeb3c")
("alarm" . "\xe855")
("alarm_add" . "\xe856")
("alarm_off" . "\xe857")
("alarm_on" . "\xe858")
("album" . "\xe019")
("all_inclusive" . "\xeb3d")
("all_out" . "\xe90b")
("android" . "\xe859")
("announcement" . "\xe85a")
("apps" . "\xe5c3")
("archive" . "\xe149")
("arrow_back" . "\xe5c4")
("arrow_downward" . "\xe5db")
("arrow_drop_down" . "\xe5c5")
("arrow_drop_down_circle" . "\xe5c6")
("arrow_drop_up" . "\xe5c7")
("arrow_forward" . "\xe5c8")
("arrow_upward" . "\xe5d8")
("art_track" . "\xe060")
("aspect_ratio" . "\xe85b")
("assessment" . "\xe85c")
("assignment" . "\xe85d")
("assignment_ind" . "\xe85e")
("assignment_late" . "\xe85f")
("assignment_return" . "\xe860")
("assignment_returned" . "\xe861")
("assignment_turned_in" . "\xe862")
("assistant" . "\xe39f")
("assistant_photo" . "\xe3a0")
("attach_file" . "\xe226")
("attach_money" . "\xe227")
("attachment" . "\xe2bc")
("audiotrack" . "\xe3a1")
("autorenew" . "\xe863")
("av_timer" . "\xe01b")
("backspace" . "\xe14a")
("backup" . "\xe864")
("battery_alert" . "\xe19c")
("battery_charging_full" . "\xe1a3")
("battery_full" . "\xe1a4")
("battery_std" . "\xe1a5")
("battery_unknown" . "\xe1a6")
("beach_access" . "\xeb3e")
("beenhere" . "\xe52d")
("block" . "\xe14b")
("bluetooth" . "\xe1a7")
("bluetooth_audio" . "\xe60f")
("bluetooth_connected" . "\xe1a8")
("bluetooth_disabled" . "\xe1a9")
("bluetooth_searching" . "\xe1aa")
("blur_circular" . "\xe3a2")
("blur_linear" . "\xe3a3")
("blur_off" . "\xe3a4")
("blur_on" . "\xe3a5")
("book" . "\xe865")
("bookmark" . "\xe866")
("bookmark_border" . "\xe867")
("border_all" . "\xe228")
("border_bottom" . "\xe229")
("border_clear" . "\xe22a")
("border_color" . "\xe22b")
("border_horizontal" . "\xe22c")
("border_inner" . "\xe22d")
("border_left" . "\xe22e")
("border_outer" . "\xe22f")
("border_right" . "\xe230")
("border_style" . "\xe231")
("border_top" . "\xe232")
("border_vertical" . "\xe233")
("branding_watermark" . "\xe06b")
("brightness_1" . "\xe3a6")
("brightness_2" . "\xe3a7")
("brightness_3" . "\xe3a8")
("brightness_4" . "\xe3a9")
("brightness_5" . "\xe3aa")
("brightness_6" . "\xe3ab")
("brightness_7" . "\xe3ac")
("brightness_auto" . "\xe1ab")
("brightness_high" . "\xe1ac")
("brightness_low" . "\xe1ad")
("brightness_medium" . "\xe1ae")
("broken_image" . "\xe3ad")
("brush" . "\xe3ae")
("bubble_chart" . "\xe6dd")
("bug_report" . "\xe868")
("build" . "\xe869")
("burst_mode" . "\xe43c")
("business" . "\xe0af")
("business_center" . "\xeb3f")
("cached" . "\xe86a")
("cake" . "\xe7e9")
("call" . "\xe0b0")
("call_end" . "\xe0b1")
("call_made" . "\xe0b2")
("call_merge" . "\xe0b3")
("call_missed" . "\xe0b4")
("call_missed_outgoing" . "\xe0e4")
("call_received" . "\xe0b5")
("call_split" . "\xe0b6")
("call_to_action" . "\xe06c")
("camera" . "\xe3af")
("camera_alt" . "\xe3b0")
("camera_enhance" . "\xe8fc")
("camera_front" . "\xe3b1")
("camera_rear" . "\xe3b2")
("camera_roll" . "\xe3b3")
("cancel" . "\xe5c9")
("card_giftcard" . "\xe8f6")
("card_membership" . "\xe8f7")
("card_travel" . "\xe8f8")
("casino" . "\xeb40")
("cast" . "\xe307")
("cast_connected" . "\xe308")
("center_focus_strong" . "\xe3b4")
("center_focus_weak" . "\xe3b5")
("change_history" . "\xe86b")
("chat" . "\xe0b7")
("chat_bubble" . "\xe0ca")
("chat_bubble_outline" . "\xe0cb")
("check" . "\xe5ca")
("check_box" . "\xe834")
("check_box_outline_blank" . "\xe835")
("check_circle" . "\xe86c")
("chevron_left" . "\xe5cb")
("chevron_right" . "\xe5cc")
("child_care" . "\xeb41")
("child_friendly" . "\xeb42")
("chrome_reader_mode" . "\xe86d")
("class" . "\xe86e")
("clear" . "\xe14c")
("clear_all" . "\xe0b8")
("close" . "\xe5cd")
("closed_caption" . "\xe01c")
("cloud" . "\xe2bd")
("cloud_circle" . "\xe2be")
("cloud_done" . "\xe2bf")
("cloud_download" . "\xe2c0")
("cloud_off" . "\xe2c1")
("cloud_queue" . "\xe2c2")
("cloud_upload" . "\xe2c3")
("code" . "\xe86f")
("collections" . "\xe3b6")
("collections_bookmark" . "\xe431")
("color_lens" . "\xe3b7")
("colorize" . "\xe3b8")
("comment" . "\xe0b9")
("compare" . "\xe3b9")
("compare_arrows" . "\xe915")
("computer" . "\xe30a")
("confirmation_number" . "\xe638")
("contact_mail" . "\xe0d0")
("contact_phone" . "\xe0cf")
("contacts" . "\xe0ba")
("content_copy" . "\xe14d")
("content_cut" . "\xe14e")
("content_paste" . "\xe14f")
("control_point" . "\xe3ba")
("control_point_duplicate" . "\xe3bb")
("copyright" . "\xe90c")
("create" . "\xe150")
("create_new_folder" . "\xe2cc")
("credit_card" . "\xe870")
("crop" . "\xe3be")
("crop_16_9" . "\xe3bc")
("crop_3_2" . "\xe3bd")
("crop_5_4" . "\xe3bf")
("crop_7_5" . "\xe3c0")
("crop_din" . "\xe3c1")
("crop_free" . "\xe3c2")
("crop_landscape" . "\xe3c3")
("crop_original" . "\xe3c4")
("crop_portrait" . "\xe3c5")
("crop_rotate" . "\xe437")
("crop_square" . "\xe3c6")
("dashboard" . "\xe871")
("data_usage" . "\xe1af")
("date_range" . "\xe916")
("dehaze" . "\xe3c7")
("delete" . "\xe872")
("delete_forever" . "\xe92b")
("delete_sweep" . "\xe16c")
("description" . "\xe873")
("desktop_mac" . "\xe30b")
("desktop_windows" . "\xe30c")
("details" . "\xe3c8")
("developer_board" . "\xe30d")
("developer_mode" . "\xe1b0")
("device_hub" . "\xe335")
("devices" . "\xe1b1")
("devices_other" . "\xe337")
("dialer_sip" . "\xe0bb")
("dialpad" . "\xe0bc")
("directions" . "\xe52e")
("directions_bike" . "\xe52f")
("directions_boat" . "\xe532")
("directions_bus" . "\xe530")
("directions_car" . "\xe531")
("directions_railway" . "\xe534")
("directions_run" . "\xe566")
("directions_subway" . "\xe533")
("directions_transit" . "\xe535")
("directions_walk" . "\xe536")
("disc_full" . "\xe610")
("dns" . "\xe875")
("do_not_disturb" . "\xe612")
("do_not_disturb_alt" . "\xe611")
("do_not_disturb_off" . "\xe643")
("do_not_disturb_on" . "\xe644")
("dock" . "\xe30e")
("domain" . "\xe7ee")
("done" . "\xe876")
("done_all" . "\xe877")
("donut_large" . "\xe917")
("donut_small" . "\xe918")
("drafts" . "\xe151")
("drag_handle" . "\xe25d")
("drive_eta" . "\xe613")
("dvr" . "\xe1b2")
("edit" . "\xe3c9")
("edit_location" . "\xe568")
("eject" . "\xe8fb")
("email" . "\xe0be")
("enhanced_encryption" . "\xe63f")
("equalizer" . "\xe01d")
("error" . "\xe000")
("error_outline" . "\xe001")
("euro_symbol" . "\xe926")
("ev_station" . "\xe56d")
("event" . "\xe878")
("event_available" . "\xe614")
("event_busy" . "\xe615")
("event_note" . "\xe616")
("event_seat" . "\xe903")
("exit_to_app" . "\xe879")
("expand_less" . "\xe5ce")
("expand_more" . "\xe5cf")
("explicit" . "\xe01e")
("explore" . "\xe87a")
("exposure" . "\xe3ca")
("exposure_neg_1" . "\xe3cb")
("exposure_neg_2" . "\xe3cc")
("exposure_plus_1" . "\xe3cd")
("exposure_plus_2" . "\xe3ce")
("exposure_zero" . "\xe3cf")
("extension" . "\xe87b")
("face" . "\xe87c")
("fast_forward" . "\xe01f")
("fast_rewind" . "\xe020")
("favorite" . "\xe87d")
("favorite_border" . "\xe87e")
("featured_play_list" . "\xe06d")
("featured_video" . "\xe06e")
("feedback" . "\xe87f")
("fiber_dvr" . "\xe05d")
("fiber_manual_record" . "\xe061")
("fiber_new" . "\xe05e")
("fiber_pin" . "\xe06a")
("fiber_smart_record" . "\xe062")
("file_download" . "\xe2c4")
("file_upload" . "\xe2c6")
("filter" . "\xe3d3")
("filter_1" . "\xe3d0")
("filter_2" . "\xe3d1")
("filter_3" . "\xe3d2")
("filter_4" . "\xe3d4")
("filter_5" . "\xe3d5")
("filter_6" . "\xe3d6")
("filter_7" . "\xe3d7")
("filter_8" . "\xe3d8")
("filter_9" . "\xe3d9")
("filter_9_plus" . "\xe3da")
("filter_b_and_w" . "\xe3db")
("filter_center_focus" . "\xe3dc")
("filter_drama" . "\xe3dd")
("filter_frames" . "\xe3de")
("filter_hdr" . "\xe3df")
("filter_list" . "\xe152")
("filter_none" . "\xe3e0")
("filter_tilt_shift" . "\xe3e2")
("filter_vintage" . "\xe3e3")
("find_in_page" . "\xe880")
("find_replace" . "\xe881")
("fingerprint" . "\xe90d")
("first_page" . "\xe5dc")
("fitness_center" . "\xeb43")
("flag" . "\xe153")
("flare" . "\xe3e4")
("flash_auto" . "\xe3e5")
("flash_off" . "\xe3e6")
("flash_on" . "\xe3e7")
("flight" . "\xe539")
("flight_land" . "\xe904")
("flight_takeoff" . "\xe905")
("flip" . "\xe3e8")
("flip_to_back" . "\xe882")
("flip_to_front" . "\xe883")
("folder" . "\xe2c7")
("folder_open" . "\xe2c8")
("folder_shared" . "\xe2c9")
("folder_special" . "\xe617")
("font_download" . "\xe167")
("format_align_center" . "\xe234")
("format_align_justify" . "\xe235")
("format_align_left" . "\xe236")
("format_align_right" . "\xe237")
("format_bold" . "\xe238")
("format_clear" . "\xe239")
("format_color_fill" . "\xe23a")
("format_color_reset" . "\xe23b")
("format_color_text" . "\xe23c")
("format_indent_decrease" . "\xe23d")
("format_indent_increase" . "\xe23e")
("format_italic" . "\xe23f")
("format_line_spacing" . "\xe240")
("format_list_bulleted" . "\xe241")
("format_list_numbered" . "\xe242")
("format_paint" . "\xe243")
("format_quote" . "\xe244")
("format_shapes" . "\xe25e")
("format_size" . "\xe245")
("format_strikethrough" . "\xe246")
("format_textdirection_l_to_r" . "\xe247")
("format_textdirection_r_to_l" . "\xe248")
("format_underlined" . "\xe249")
("forum" . "\xe0bf")
("forward" . "\xe154")
("forward_10" . "\xe056")
("forward_30" . "\xe057")
("forward_5" . "\xe058")
("free_breakfast" . "\xeb44")
("fullscreen" . "\xe5d0")
("fullscreen_exit" . "\xe5d1")
("functions" . "\xe24a")
("g_translate" . "\xe927")
("gamepad" . "\xe30f")
("games" . "\xe021")
("gavel" . "\xe90e")
("gesture" . "\xe155")
("get_app" . "\xe884")
("gif" . "\xe908")
("golf_course" . "\xeb45")
("gps_fixed" . "\xe1b3")
("gps_not_fixed" . "\xe1b4")
("gps_off" . "\xe1b5")
("grade" . "\xe885")
("gradient" . "\xe3e9")
("grain" . "\xe3ea")
("graphic_eq" . "\xe1b8")
("grid_off" . "\xe3eb")
("grid_on" . "\xe3ec")
("group" . "\xe7ef")
("group_add" . "\xe7f0")
("group_work" . "\xe886")
("hd" . "\xe052")
("hdr_off" . "\xe3ed")
("hdr_on" . "\xe3ee")
("hdr_strong" . "\xe3f1")
("hdr_weak" . "\xe3f2")
("headset" . "\xe310")
("headset_mic" . "\xe311")
("healing" . "\xe3f3")
("hearing" . "\xe023")
("help" . "\xe887")
("help_outline" . "\xe8fd")
("high_quality" . "\xe024")
("highlight" . "\xe25f")
("highlight_off" . "\xe888")
("history" . "\xe889")
("home" . "\xe88a")
("hot_tub" . "\xeb46")
("hotel" . "\xe53a")
("hourglass_empty" . "\xe88b")
("hourglass_full" . "\xe88c")
("http" . "\xe902")
("https" . "\xe88d")
("image" . "\xe3f4")
("image_aspect_ratio" . "\xe3f5")
("import_contacts" . "\xe0e0")
("import_export" . "\xe0c3")
("important_devices" . "\xe912")
("inbox" . "\xe156")
("indeterminate_check_box" . "\xe909")
("info" . "\xe88e")
("info_outline" . "\xe88f")
("input" . "\xe890")
("insert_chart" . "\xe24b")
("insert_comment" . "\xe24c")
("insert_drive_file" . "\xe24d")
("insert_emoticon" . "\xe24e")
("insert_invitation" . "\xe24f")
("insert_link" . "\xe250")
("insert_photo" . "\xe251")
("invert_colors" . "\xe891")
("invert_colors_off" . "\xe0c4")
("iso" . "\xe3f6")
("keyboard" . "\xe312")
("keyboard_arrow_down" . "\xe313")
("keyboard_arrow_left" . "\xe314")
("keyboard_arrow_right" . "\xe315")
("keyboard_arrow_up" . "\xe316")
("keyboard_backspace" . "\xe317")
("keyboard_capslock" . "\xe318")
("keyboard_hide" . "\xe31a")
("keyboard_return" . "\xe31b")
("keyboard_tab" . "\xe31c")
("keyboard_voice" . "\xe31d")
("kitchen" . "\xeb47")
("label" . "\xe892")
("label_outline" . "\xe893")
("landscape" . "\xe3f7")
("language" . "\xe894")
("laptop" . "\xe31e")
("laptop_chromebook" . "\xe31f")
("laptop_mac" . "\xe320")
("laptop_windows" . "\xe321")
("last_page" . "\xe5dd")
("launch" . "\xe895")
("layers" . "\xe53b")
("layers_clear" . "\xe53c")
("leak_add" . "\xe3f8")
("leak_remove" . "\xe3f9")
("lens" . "\xe3fa")
("library_add" . "\xe02e")
("library_books" . "\xe02f")
("library_music" . "\xe030")
("lightbulb_outline" . "\xe90f")
("line_style" . "\xe919")
("line_weight" . "\xe91a")
("linear_scale" . "\xe260")
("link" . "\xe157")
("linked_camera" . "\xe438")
("list" . "\xe896")
("live_help" . "\xe0c6")
("live_tv" . "\xe639")
("local_activity" . "\xe53f")
("local_airport" . "\xe53d")
("local_atm" . "\xe53e")
("local_bar" . "\xe540")
("local_cafe" . "\xe541")
("local_car_wash" . "\xe542")
("local_convenience_store" . "\xe543")
("local_dining" . "\xe556")
("local_drink" . "\xe544")
("local_florist" . "\xe545")
("local_gas_station" . "\xe546")
("local_grocery_store" . "\xe547")
("local_hospital" . "\xe548")
("local_hotel" . "\xe549")
("local_laundry_service" . "\xe54a")
("local_library" . "\xe54b")
("local_mall" . "\xe54c")
("local_movies" . "\xe54d")
("local_offer" . "\xe54e")
("local_parking" . "\xe54f")
("local_pharmacy" . "\xe550")
("local_phone" . "\xe551")
("local_pizza" . "\xe552")
("local_play" . "\xe553")
("local_post_office" . "\xe554")
("local_printshop" . "\xe555")
("local_see" . "\xe557")
("local_shipping" . "\xe558")
("local_taxi" . "\xe559")
("location_city" . "\xe7f1")
("location_disabled" . "\xe1b6")
("location_off" . "\xe0c7")
("location_on" . "\xe0c8")
("location_searching" . "\xe1b7")
("lock" . "\xe897")
("lock_open" . "\xe898")
("lock_outline" . "\xe899")
("looks" . "\xe3fc")
("looks_3" . "\xe3fb")
("looks_4" . "\xe3fd")
("looks_5" . "\xe3fe")
("looks_6" . "\xe3ff")
("looks_one" . "\xe400")
("looks_two" . "\xe401")
("loop" . "\xe028")
("loupe" . "\xe402")
("low_priority" . "\xe16d")
("loyalty" . "\xe89a")
("mail" . "\xe158")
("mail_outline" . "\xe0e1")
("map" . "\xe55b")
("markunread" . "\xe159")
("markunread_mailbox" . "\xe89b")
("memory" . "\xe322")
("menu" . "\xe5d2")
("merge_type" . "\xe252")
("message" . "\xe0c9")
("mic" . "\xe029")
("mic_none" . "\xe02a")
("mic_off" . "\xe02b")
("mms" . "\xe618")
("mode_comment" . "\xe253")
("mode_edit" . "\xe254")
("monetization_on" . "\xe263")
("money_off" . "\xe25c")
("monochrome_photos" . "\xe403")
("mood" . "\xe7f2")
("mood_bad" . "\xe7f3")
("more" . "\xe619")
("more_horiz" . "\xe5d3")
("more_vert" . "\xe5d4")
("motorcycle" . "\xe91b")
("mouse" . "\xe323")
("move_to_inbox" . "\xe168")
("movie" . "\xe02c")
("movie_creation" . "\xe404")
("movie_filter" . "\xe43a")
("multiline_chart" . "\xe6df")
("music_note" . "\xe405")
("music_video" . "\xe063")
("my_location" . "\xe55c")
("nature" . "\xe406")
("nature_people" . "\xe407")
("navigate_before" . "\xe408")
("navigate_next" . "\xe409")
("navigation" . "\xe55d")
("near_me" . "\xe569")
("network_cell" . "\xe1b9")
("network_check" . "\xe640")
("network_locked" . "\xe61a")
("network_wifi" . "\xe1ba")
("new_releases" . "\xe031")
("next_week" . "\xe16a")
("nfc" . "\xe1bb")
("no_encryption" . "\xe641")
("no_sim" . "\xe0cc")
("not_interested" . "\xe033")
("note" . "\xe06f")
("note_add" . "\xe89c")
("notifications" . "\xe7f4")
("notifications_active" . "\xe7f7")
("notifications_none" . "\xe7f5")
("notifications_off" . "\xe7f6")
("notifications_paused" . "\xe7f8")
("offline_pin" . "\xe90a")
("ondemand_video" . "\xe63a")
("opacity" . "\xe91c")
("open_in_browser" . "\xe89d")
("open_in_new" . "\xe89e")
("open_with" . "\xe89f")
("pages" . "\xe7f9")
("pageview" . "\xe8a0")
("palette" . "\xe40a")
("pan_tool" . "\xe925")
("panorama" . "\xe40b")
("panorama_fish_eye" . "\xe40c")
("panorama_horizontal" . "\xe40d")
("panorama_vertical" . "\xe40e")
("panorama_wide_angle" . "\xe40f")
("party_mode" . "\xe7fa")
("pause" . "\xe034")
("pause_circle_filled" . "\xe035")
("pause_circle_outline" . "\xe036")
("payment" . "\xe8a1")
("people" . "\xe7fb")
("people_outline" . "\xe7fc")
("perm_camera_mic" . "\xe8a2")
("perm_contact_calendar" . "\xe8a3")
("perm_data_setting" . "\xe8a4")
("perm_device_information" . "\xe8a5")
("perm_identity" . "\xe8a6")
("perm_media" . "\xe8a7")
("perm_phone_msg" . "\xe8a8")
("perm_scan_wifi" . "\xe8a9")
("person" . "\xe7fd")
("person_add" . "\xe7fe")
("person_outline" . "\xe7ff")
("person_pin" . "\xe55a")
("person_pin_circle" . "\xe56a")
("personal_video" . "\xe63b")
("pets" . "\xe91d")
("phone" . "\xe0cd")
("phone_android" . "\xe324")
("phone_bluetooth_speaker" . "\xe61b")
("phone_forwarded" . "\xe61c")
("phone_in_talk" . "\xe61d")
("phone_iphone" . "\xe325")
("phone_locked" . "\xe61e")
("phone_missed" . "\xe61f")
("phone_paused" . "\xe620")
("phonelink" . "\xe326")
("phonelink_erase" . "\xe0db")
("phonelink_lock" . "\xe0dc")
("phonelink_off" . "\xe327")
("phonelink_ring" . "\xe0dd")
("phonelink_setup" . "\xe0de")
("photo" . "\xe410")
("photo_album" . "\xe411")
("photo_camera" . "\xe412")
("photo_filter" . "\xe43b")
("photo_library" . "\xe413")
("photo_size_select_actual" . "\xe432")
("photo_size_select_large" . "\xe433")
("photo_size_select_small" . "\xe434")
("picture_as_pdf" . "\xe415")
("picture_in_picture" . "\xe8aa")
("picture_in_picture_alt" . "\xe911")
("pie_chart" . "\xe6c4")
("pie_chart_outlined" . "\xe6c5")
("pin_drop" . "\xe55e")
("place" . "\xe55f")
("play_arrow" . "\xe037")
("play_circle_filled" . "\xe038")
("play_circle_outline" . "\xe039")
("play_for_work" . "\xe906")
("playlist_add" . "\xe03b")
("playlist_add_check" . "\xe065")
("playlist_play" . "\xe05f")
("plus_one" . "\xe800")
("poll" . "\xe801")
("polymer" . "\xe8ab")
("pool" . "\xeb48")
("portable_wifi_off" . "\xe0ce")
("portrait" . "\xe416")
("power" . "\xe63c")
("power_input" . "\xe336")
("power_settings_new" . "\xe8ac")
("pregnant_woman" . "\xe91e")
("present_to_all" . "\xe0df")
("print" . "\xe8ad")
("priority_high" . "\xe645")
("public" . "\xe80b")
("publish" . "\xe255")
("query_builder" . "\xe8ae")
("question_answer" . "\xe8af")
("queue" . "\xe03c")
("queue_music" . "\xe03d")
("queue_play_next" . "\xe066")
("radio" . "\xe03e")
("radio_button_checked" . "\xe837")
("radio_button_unchecked" . "\xe836")
("rate_review" . "\xe560")
("receipt" . "\xe8b0")
("recent_actors" . "\xe03f")
("record_voice_over" . "\xe91f")
("redeem" . "\xe8b1")
("redo" . "\xe15a")
("refresh" . "\xe5d5")
("remove" . "\xe15b")
("remove_circle" . "\xe15c")
("remove_circle_outline" . "\xe15d")
("remove_from_queue" . "\xe067")
("remove_red_eye" . "\xe417")
("remove_shopping_cart" . "\xe928")
("reorder" . "\xe8fe")
("repeat" . "\xe040")
("repeat_one" . "\xe041")
("replay" . "\xe042")
("replay_10" . "\xe059")
("replay_30" . "\xe05a")
("replay_5" . "\xe05b")
("reply" . "\xe15e")
("reply_all" . "\xe15f")
("report" . "\xe160")
("report_problem" . "\xe8b2")
("restaurant" . "\xe56c")
("restaurant_menu" . "\xe561")
("restore" . "\xe8b3")
("restore_page" . "\xe929")
("ring_volume" . "\xe0d1")
("room" . "\xe8b4")
("room_service" . "\xeb49")
("rotate_90_degrees_ccw" . "\xe418")
("rotate_left" . "\xe419")
("rotate_right" . "\xe41a")
("rounded_corner" . "\xe920")
("router" . "\xe328")
("rowing" . "\xe921")
("rss_feed" . "\xe0e5")
("rv_hookup" . "\xe642")
("satellite" . "\xe562")
("save" . "\xe161")
("scanner" . "\xe329")
("schedule" . "\xe8b5")
("school" . "\xe80c")
("screen_lock_landscape" . "\xe1be")
("screen_lock_portrait" . "\xe1bf")
("screen_lock_rotation" . "\xe1c0")
("screen_rotation" . "\xe1c1")
("screen_share" . "\xe0e2")
("sd_card" . "\xe623")
("sd_storage" . "\xe1c2")
("search" . "\xe8b6")
("security" . "\xe32a")
("select_all" . "\xe162")
("send" . "\xe163")
("sentiment_dissatisfied" . "\xe811")
("sentiment_neutral" . "\xe812")
("sentiment_satisfied" . "\xe813")
("sentiment_very_dissatisfied" . "\xe814")
("sentiment_very_satisfied" . "\xe815")
("settings" . "\xe8b8")
("settings_applications" . "\xe8b9")
("settings_backup_restore" . "\xe8ba")
("settings_bluetooth" . "\xe8bb")
("settings_brightness" . "\xe8bd")
("settings_cell" . "\xe8bc")
("settings_ethernet" . "\xe8be")
("settings_input_antenna" . "\xe8bf")
("settings_input_component" . "\xe8c0")
("settings_input_composite" . "\xe8c1")
("settings_input_hdmi" . "\xe8c2")
("settings_input_svideo" . "\xe8c3")
("settings_overscan" . "\xe8c4")
("settings_phone" . "\xe8c5")
("settings_power" . "\xe8c6")
("settings_remote" . "\xe8c7")
("settings_system_daydream" . "\xe1c3")
("settings_voice" . "\xe8c8")
("share" . "\xe80d")
("shop" . "\xe8c9")
("shop_two" . "\xe8ca")
("shopping_basket" . "\xe8cb")
("shopping_cart" . "\xe8cc")
("short_text" . "\xe261")
("show_chart" . "\xe6e1")
("shuffle" . "\xe043")
("signal_cellular_4_bar" . "\xe1c8")
("signal_cellular_connected_no_internet_4_bar" . "\xe1cd")
("signal_cellular_no_sim" . "\xe1ce")
("signal_cellular_null" . "\xe1cf")
("signal_cellular_off" . "\xe1d0")
("signal_wifi_4_bar" . "\xe1d8")
("signal_wifi_4_bar_lock" . "\xe1d9")
("signal_wifi_off" . "\xe1da")
("sim_card" . "\xe32b")
("sim_card_alert" . "\xe624")
("skip_next" . "\xe044")
("skip_previous" . "\xe045")
("slideshow" . "\xe41b")
("slow_motion_video" . "\xe068")
("smartphone" . "\xe32c")
("smoke_free" . "\xeb4a")
("smoking_rooms" . "\xeb4b")
("sms" . "\xe625")
("sms_failed" . "\xe626")
("snooze" . "\xe046")
("sort" . "\xe164")
("sort_by_alpha" . "\xe053")
("spa" . "\xeb4c")
("space_bar" . "\xe256")
("speaker" . "\xe32d")
("speaker_group" . "\xe32e")
("speaker_notes" . "\xe8cd")
("speaker_notes_off" . "\xe92a")
("speaker_phone" . "\xe0d2")
("spellcheck" . "\xe8ce")
("star" . "\xe838")
("star_border" . "\xe83a")
("star_half" . "\xe839")
("stars" . "\xe8d0")
("stay_current_landscape" . "\xe0d3")
("stay_current_portrait" . "\xe0d4")
("stay_primary_landscape" . "\xe0d5")
("stay_primary_portrait" . "\xe0d6")
("stop" . "\xe047")
("stop_screen_share" . "\xe0e3")
("storage" . "\xe1db")
("store" . "\xe8d1")
("store_mall_directory" . "\xe563")
("straighten" . "\xe41c")
("streetview" . "\xe56e")
("strikethrough_s" . "\xe257")
("style" . "\xe41d")
("subdirectory_arrow_left" . "\xe5d9")
("subdirectory_arrow_right" . "\xe5da")
("subject" . "\xe8d2")
("subscriptions" . "\xe064")
("subtitles" . "\xe048")
("subway" . "\xe56f")
("supervisor_account" . "\xe8d3")
("surround_sound" . "\xe049")
("swap_calls" . "\xe0d7")
("swap_horiz" . "\xe8d4")
("swap_vert" . "\xe8d5")
("swap_vertical_circle" . "\xe8d6")
("switch_camera" . "\xe41e")
("switch_video" . "\xe41f")
("sync" . "\xe627")
("sync_disabled" . "\xe628")
("sync_problem" . "\xe629")
("system_update" . "\xe62a")
("system_update_alt" . "\xe8d7")
("tab" . "\xe8d8")
("tab_unselected" . "\xe8d9")
("tablet" . "\xe32f")
("tablet_android" . "\xe330")
("tablet_mac" . "\xe331")
("tag_faces" . "\xe420")
("tap_and_play" . "\xe62b")
("terrain" . "\xe564")
("text_fields" . "\xe262")
("text_format" . "\xe165")
("textsms" . "\xe0d8")
("texture" . "\xe421")
("theaters" . "\xe8da")
("thumb_down" . "\xe8db")
("thumb_up" . "\xe8dc")
("thumbs_up_down" . "\xe8dd")
("time_to_leave" . "\xe62c")
("timelapse" . "\xe422")
("timeline" . "\xe922")
("timer" . "\xe425")
("timer_10" . "\xe423")
("timer_3" . "\xe424")
("timer_off" . "\xe426")
("title" . "\xe264")
("toc" . "\xe8de")
("today" . "\xe8df")
("toll" . "\xe8e0")
("tonality" . "\xe427")
("touch_app" . "\xe913")
("toys" . "\xe332")
("track_changes" . "\xe8e1")
("traffic" . "\xe565")
("train" . "\xe570")
("tram" . "\xe571")
("transfer_within_a_station" . "\xe572")
("transform" . "\xe428")
("translate" . "\xe8e2")
("trending_down" . "\xe8e3")
("trending_flat" . "\xe8e4")
("trending_up" . "\xe8e5")
("tune" . "\xe429")
("turned_in" . "\xe8e6")
("turned_in_not" . "\xe8e7")
("tv" . "\xe333")
("unarchive" . "\xe169")
("undo" . "\xe166")
("unfold_less" . "\xe5d6")
("unfold_more" . "\xe5d7")
("update" . "\xe923")
("usb" . "\xe1e0")
("verified_user" . "\xe8e8")
("vertical_align_bottom" . "\xe258")
("vertical_align_center" . "\xe259")
("vertical_align_top" . "\xe25a")
("vibration" . "\xe62d")
("video_call" . "\xe070")
("video_label" . "\xe071")
("video_library" . "\xe04a")
("videocam" . "\xe04b")
("videocam_off" . "\xe04c")
("videogame_asset" . "\xe338")
("view_agenda" . "\xe8e9")
("view_array" . "\xe8ea")
("view_carousel" . "\xe8eb")
("view_column" . "\xe8ec")
("view_comfy" . "\xe42a")
("view_compact" . "\xe42b")
("view_day" . "\xe8ed")
("view_headline" . "\xe8ee")
("view_list" . "\xe8ef")
("view_module" . "\xe8f0")
("view_quilt" . "\xe8f1")
("view_stream" . "\xe8f2")
("view_week" . "\xe8f3")
("vignette" . "\xe435")
("visibility" . "\xe8f4")
("visibility_off" . "\xe8f5")
("voice_chat" . "\xe62e")
("voicemail" . "\xe0d9")
("volume_down" . "\xe04d")
("volume_mute" . "\xe04e")
("volume_off" . "\xe04f")
("volume_up" . "\xe050")
("vpn_key" . "\xe0da")
("vpn_lock" . "\xe62f")
("wallpaper" . "\xe1bc")
("warning" . "\xe002")
("watch" . "\xe334")
("watch_later" . "\xe924")
("wb_auto" . "\xe42c")
("wb_cloudy" . "\xe42d")
("wb_incandescent" . "\xe42e")
("wb_iridescent" . "\xe436")
("wb_sunny" . "\xe430")
("wc" . "\xe63d")
("web" . "\xe051")
("web_asset" . "\xe069")
("weekend" . "\xe16b")
("whatshot" . "\xe80e")
("widgets" . "\xe1bd")
("wifi" . "\xe63e")
("wifi_lock" . "\xe1e1")
("wifi_tethering" . "\xe1e2")
("work" . "\xe8f9")
("wrap_text" . "\xe25b")
("youtube_searched_for" . "\xe8fa")
("zoom_in" . "\xe8ff")
("zoom_out" . "\xe900")
("zoom_out_map" . "\xe56b")))
(provide 'data-material)

View file

@ -0,0 +1,165 @@
(defvar all-the-icons-data/octicons-alist
'(
("alert" . "\xf02d")
("arrow-down" . "\xf03f")
("arrow-left" . "\xf040")
("arrow-right" . "\xf03e")
("arrow-small-down" . "\xf0a0")
("arrow-small-left" . "\xf0a1")
("arrow-small-right" . "\xf071")
("arrow-small-up" . "\xf09f")
("arrow-up" . "\xf03d")
("book" . "\xf007")
("bookmark" . "\xf07b")
("briefcase" . "\xf0d3")
("broadcast" . "\xf048")
("browser" . "\xf0c5")
("bug" . "\xf091")
("calendar" . "\xf068")
("check" . "\xf03a")
("checklist" . "\xf076")
("chevron-down" . "\xf0a3")
("chevron-left" . "\xf0a4")
("chevron-right" . "\xf078")
("chevron-up" . "\xf0a2")
("circle-slash" . "\xf084")
("circuit-board" . "\xf0d6")
("clippy" . "\xf035")
("clock" . "\xf046")
("cloud-download" . "\xf00b")
("cloud-upload" . "\xf00c")
("code" . "\xf05f")
("comment" . "\xf02b")
("comment-discussion" . "\xf04f")
("credit-card" . "\xf045")
("dash" . "\xf0ca")
("dashboard" . "\xf07d")
("database" . "\xf096")
("device-camera" . "\xf056")
("device-camera-video" . "\xf057")
("device-desktop" . "\xf27c")
("device-mobile" . "\xf038")
("diff" . "\xf04d")
("diff-added" . "\xf06b")
("diff-ignored" . "\xf099")
("diff-modified" . "\xf06d")
("diff-removed" . "\xf06c")
("diff-renamed" . "\xf06e")
("ellipsis" . "\xf09a")
("eye" . "\xf04e")
("file-binary" . "\xf094")
("file-code" . "\xf010")
("file-directory" . "\xf016")
("file-media" . "\xf012")
("file-pdf" . "\xf014")
("file-submodule" . "\xf017")
("file-symlink-directory" . "\xf0b1")
("file-symlink-file" . "\xf0b0")
("file-text" . "\xf011")
("file-zip" . "\xf013")
("flame" . "\xf0d2")
("fold" . "\xf0cc")
("gear" . "\xf02f")
("gift" . "\xf042")
("gist" . "\xf00e")
("gist-secret" . "\xf08c")
("git-branch" . "\xf020")
("git-commit" . "\xf01f")
("git-compare" . "\xf0ac")
("git-merge" . "\xf023")
("git-pull-request" . "\xf009")
("globe" . "\xf0b6")
("graph" . "\xf043")
("beaker" . "\xf0dd")
("heart" . "\x2665")
("history" . "\xf07e")
("home" . "\xf08d")
("horizontal-rule" . "\xf070")
("hourglass" . "\xf09e")
("hubot" . "\xf09d")
("inbox" . "\xf0cf")
("info" . "\xf059")
("issue-closed" . "\xf028")
("issue-opened" . "\xf026")
("issue-reopened" . "\xf027")
("jersey" . "\xf019")
("key" . "\xf049")
("keyboard" . "\xf00d")
("law" . "\xf0d8")
("light-bulb" . "\xf000")
("link" . "\xf05c")
("link-external" . "\xf07f")
("list-ordered" . "\xf062")
("list-unordered" . "\xf061")
("location" . "\xf060")
("lock" . "\xf06a")
("logo-github" . "\xf092")
("mail" . "\xf03b")
("mail-read" . "\xf03c")
("mail-reply" . "\xf051")
("mark-github" . "\xf00a")
("markdown" . "\xf0c9")
("megaphone" . "\xf077")
("mention" . "\xf0be")
("milestone" . "\xf075")
("mirror" . "\xf024")
("mortar-board" . "\xf0d7")
("mute" . "\xf080")
("no-newline" . "\xf09c")
("octoface" . "\xf008")
("organization" . "\xf037")
("package" . "\xf0c4")
("paintcan" . "\xf0d1")
("pencil" . "\xf058")
("person" . "\xf018")
("pin" . "\xf041")
("plug" . "\xf0d4")
("plus" . "\xf05d")
("primitive-dot" . "\xf052")
("primitive-square" . "\xf053")
("pulse" . "\xf085")
("puzzle" . "\xf0c0")
("question" . "\xf02c")
("quote" . "\xf063")
("radio-tower" . "\xf030")
("repo" . "\xf001")
("repo-clone" . "\xf04c")
("repo-force-push" . "\xf04a")
("repo-forked" . "\xf002")
("repo-pull" . "\xf006")
("repo-push" . "\xf005")
("rocket" . "\xf033")
("rss" . "\xf034")
("ruby" . "\xf047")
("search" . "\xf02e")
("server" . "\xf097")
("settings" . "\xf07c")
("sign-in" . "\xf036")
("sign-out" . "\xf032")
("squirrel" . "\xf0b2")
("star" . "\xf02a")
("steps" . "\xf0c7")
("stop" . "\xf08f")
("sync" . "\xf087")
("tag" . "\xf015")
("telescope" . "\xf088")
("terminal" . "\xf0c8")
("three-bars" . "\xf05e")
("thumbsdown" . "\xf0db")
("thumbsup" . "\xf0da")
("tools" . "\xf031")
("trashcan" . "\xf0d0")
("triangle-down" . "\xf05b")
("triangle-left" . "\xf044")
("triangle-right" . "\xf05a")
("triangle-up" . "\xf0aa")
("unfold" . "\xf039")
("unmute" . "\xf0ba")
("versions" . "\xf064")
("x" . "\xf081")
("zap" . "\x26A1")
))
(provide 'data-octicons)

View file

@ -0,0 +1,594 @@
(defvar all-the-icons-data/weather-icons-alist
'(
("alien" . "\xf075")
("barometer" . "\xf079")
("celsius" . "\xf03c")
("cloud" . "\xf041")
("cloud-down" . "\xf03d")
("cloud-refresh" . "\xf03e")
("cloud-up" . "\xf040")
("cloudy" . "\xf013")
("cloudy-gusts" . "\xf011")
("cloudy-windy" . "\xf012")
("day-cloudy" . "\xf002")
("day-cloudy-gusts" . "\xf000")
("day-cloudy-high" . "\xf07d")
("day-cloudy-windy" . "\xf001")
("day-fog" . "\xf003")
("day-hail" . "\xf004")
("day-haze" . "\xf0b6")
("day-light-wind" . "\xf0c4")
("day-lightning" . "\xf005")
("day-rain" . "\xf008")
("day-rain-mix" . "\xf006")
("day-rain-wind" . "\xf007")
("day-showers" . "\xf009")
("day-sleet" . "\xf0b2")
("day-sleet-storm" . "\xf068")
("day-snow" . "\xf00a")
("day-snow-thunderstorm" . "\xf06b")
("day-snow-wind" . "\xf065")
("day-sprinkle" . "\xf00b")
("day-storm-showers" . "\xf00e")
("day-sunny" . "\xf00d")
("day-sunny-overcast" . "\xf00c")
("day-thunderstorm" . "\xf010")
("day-windy" . "\xf085")
("degrees" . "\xf042")
("direction-down" . "\xf044")
("direction-down-left" . "\xf043")
("direction-down-right" . "\xf088")
("direction-left" . "\xf048")
("direction-right" . "\xf04d")
("direction-up" . "\xf058")
("direction-up-left" . "\xf087")
("direction-up-right" . "\xf057")
("dust" . "\xf063")
("earthquake" . "\xf0c6")
("fahrenheit" . "\xf045")
("fire" . "\xf0c7")
("flood" . "\xf07c")
("fog" . "\xf014")
("forecast-io-clear-day" . "\xf00d")
("forecast-io-clear-night" . "\xf02e")
("forecast-io-cloudy" . "\xf013")
("forecast-io-fog" . "\xf014")
("forecast-io-hail" . "\xf015")
("forecast-io-partly-cloudy-day" . "\xf002")
("forecast-io-partly-cloudy-night" . "\xf031")
("forecast-io-rain" . "\xf019")
("forecast-io-sleet" . "\xf0b5")
("forecast-io-snow" . "\xf01b")
("forecast-io-thunderstorm" . "\xf01e")
("forecast-io-tornado" . "\xf056")
("forecast-io-wind" . "\xf050")
("gale-warning" . "\xf0cd")
("hail" . "\xf015")
("horizon" . "\xf047")
("horizon-alt" . "\xf046")
("hot" . "\xf072")
("humidity" . "\xf07a")
("hurricane" . "\xf073")
("hurricane-warning" . "\xf0cf")
("lightning" . "\xf016")
("lunar-eclipse" . "\xf070")
("meteor" . "\xf071")
("moon-0" . "\xf095")
("moon-1" . "\xf096")
("moon-10" . "\xf09f")
("moon-11" . "\xf0a0")
("moon-12" . "\xf0a1")
("moon-13" . "\xf0a2")
("moon-14" . "\xf0a3")
("moon-15" . "\xf0a4")
("moon-16" . "\xf0a5")
("moon-17" . "\xf0a6")
("moon-18" . "\xf0a7")
("moon-19" . "\xf0a8")
("moon-2" . "\xf097")
("moon-20" . "\xf0a9")
("moon-21" . "\xf0aa")
("moon-22" . "\xf0ab")
("moon-23" . "\xf0ac")
("moon-24" . "\xf0ad")
("moon-25" . "\xf0ae")
("moon-26" . "\xf0af")
("moon-27" . "\xf0b0")
("moon-3" . "\xf098")
("moon-4" . "\xf099")
("moon-5" . "\xf09a")
("moon-6" . "\xf09b")
("moon-7" . "\xf09c")
("moon-8" . "\xf09d")
("moon-9" . "\xf09e")
("moon-alt-first-quarter" . "\xf0d6")
("moon-alt-full" . "\xf0dd")
("moon-alt-new" . "\xf0eb")
("moon-alt-third-quarter" . "\xf0e4")
("moon-alt-waning-crescent-1" . "\xf0e5")
("moon-alt-waning-crescent-2" . "\xf0e6")
("moon-alt-waning-crescent-3" . "\xf0e7")
("moon-alt-waning-crescent-4" . "\xf0e8")
("moon-alt-waning-crescent-5" . "\xf0e9")
("moon-alt-waning-crescent-6" . "\xf0ea")
("moon-alt-waning-gibbous-1" . "\xf0de")
("moon-alt-waning-gibbous-2" . "\xf0df")
("moon-alt-waning-gibbous-3" . "\xf0e0")
("moon-alt-waning-gibbous-4" . "\xf0e1")
("moon-alt-waning-gibbous-5" . "\xf0e2")
("moon-alt-waning-gibbous-6" . "\xf0e3")
("moon-alt-waxing-crescent-1" . "\xf0d0")
("moon-alt-waxing-crescent-2" . "\xf0d1")
("moon-alt-waxing-crescent-3" . "\xf0d2")
("moon-alt-waxing-crescent-4" . "\xf0d3")
("moon-alt-waxing-crescent-5" . "\xf0d4")
("moon-alt-waxing-crescent-6" . "\xf0d5")
("moon-alt-waxing-gibbous-1" . "\xf0d7")
("moon-alt-waxing-gibbous-2" . "\xf0d8")
("moon-alt-waxing-gibbous-3" . "\xf0d9")
("moon-alt-waxing-gibbous-4" . "\xf0da")
("moon-alt-waxing-gibbous-5" . "\xf0db")
("moon-alt-waxing-gibbous-6" . "\xf0dc")
("moon-first-quarter" . "\xf09c")
("moon-full" . "\xf0a3")
("moon-new" . "\xf095")
("moon-third-quarter" . "\xf0aa")
("moon-waning-crescent-1" . "\xf0ab")
("moon-waning-crescent-2" . "\xf0ac")
("moon-waning-crescent-3" . "\xf0ad")
("moon-waning-crescent-4" . "\xf0ae")
("moon-waning-crescent-5" . "\xf0af")
("moon-waning-crescent-6" . "\xf0b0")
("moon-waning-gibbous-1" . "\xf0a4")
("moon-waning-gibbous-2" . "\xf0a5")
("moon-waning-gibbous-3" . "\xf0a6")
("moon-waning-gibbous-4" . "\xf0a7")
("moon-waning-gibbous-5" . "\xf0a8")
("moon-waning-gibbous-6" . "\xf0a9")
("moon-waxing-crescent-1" . "\xf096")
("moon-waxing-crescent-2" . "\xf097")
("moon-waxing-crescent-3" . "\xf098")
("moon-waxing-crescent-4" . "\xf099")
("moon-waxing-crescent-5" . "\xf09a")
("moon-waxing-crescent-6" . "\xf09b")
("moon-waxing-gibbous-1" . "\xf09d")
("moon-waxing-gibbous-2" . "\xf09e")
("moon-waxing-gibbous-3" . "\xf09f")
("moon-waxing-gibbous-4" . "\xf0a0")
("moon-waxing-gibbous-5" . "\xf0a1")
("moon-waxing-gibbous-6" . "\xf0a2")
("moonrise" . "\xf0c9")
("moonset" . "\xf0ca")
("na" . "\xf07b")
("night-alt-cloudy" . "\xf086")
("night-alt-cloudy-gusts" . "\xf022")
("night-alt-cloudy-high" . "\xf07e")
("night-alt-cloudy-windy" . "\xf023")
("night-alt-hail" . "\xf024")
("night-alt-lightning" . "\xf025")
("night-alt-partly-cloudy" . "\xf081")
("night-alt-rain" . "\xf028")
("night-alt-rain-mix" . "\xf026")
("night-alt-rain-wind" . "\xf027")
("night-alt-showers" . "\xf029")
("night-alt-sleet" . "\xf0b4")
("night-alt-sleet-storm" . "\xf06a")
("night-alt-snow" . "\xf02a")
("night-alt-snow-thunderstorm" . "\xf06d")
("night-alt-snow-wind" . "\xf067")
("night-alt-sprinkle" . "\xf02b")
("night-alt-storm-showers" . "\xf02c")
("night-alt-thunderstorm" . "\xf02d")
("night-clear" . "\xf02e")
("night-cloudy" . "\xf031")
("night-cloudy-gusts" . "\xf02f")
("night-cloudy-high" . "\xf080")
("night-cloudy-windy" . "\xf030")
("night-fog" . "\xf04a")
("night-hail" . "\xf032")
("night-lightning" . "\xf033")
("night-partly-cloudy" . "\xf083")
("night-rain" . "\xf036")
("night-rain-mix" . "\xf034")
("night-rain-wind" . "\xf035")
("night-showers" . "\xf037")
("night-sleet" . "\xf0b3")
("night-sleet-storm" . "\xf069")
("night-snow" . "\xf038")
("night-snow-thunderstorm" . "\xf06c")
("night-snow-wind" . "\xf066")
("night-sprinkle" . "\xf039")
("night-storm-showers" . "\xf03a")
("night-thunderstorm" . "\xf03b")
("owm-200" . "\xf01e")
("owm-201" . "\xf01e")
("owm-202" . "\xf01e")
("owm-210" . "\xf016")
("owm-211" . "\xf016")
("owm-212" . "\xf016")
("owm-221" . "\xf016")
("owm-230" . "\xf01e")
("owm-231" . "\xf01e")
("owm-232" . "\xf01e")
("owm-300" . "\xf01c")
("owm-301" . "\xf01c")
("owm-302" . "\xf019")
("owm-310" . "\xf017")
("owm-311" . "\xf019")
("owm-312" . "\xf019")
("owm-313" . "\xf01a")
("owm-314" . "\xf019")
("owm-321" . "\xf01c")
("owm-500" . "\xf01c")
("owm-501" . "\xf019")
("owm-502" . "\xf019")
("owm-503" . "\xf019")
("owm-504" . "\xf019")
("owm-511" . "\xf017")
("owm-520" . "\xf01a")
("owm-521" . "\xf01a")
("owm-522" . "\xf01a")
("owm-531" . "\xf01d")
("owm-600" . "\xf01b")
("owm-601" . "\xf01b")
("owm-602" . "\xf0b5")
("owm-611" . "\xf017")
("owm-612" . "\xf017")
("owm-615" . "\xf017")
("owm-616" . "\xf017")
("owm-620" . "\xf017")
("owm-621" . "\xf01b")
("owm-622" . "\xf01b")
("owm-701" . "\xf01a")
("owm-711" . "\xf062")
("owm-721" . "\xf0b6")
("owm-731" . "\xf063")
("owm-741" . "\xf014")
("owm-761" . "\xf063")
("owm-762" . "\xf063")
("owm-771" . "\xf011")
("owm-781" . "\xf056")
("owm-800" . "\xf00d")
("owm-801" . "\xf011")
("owm-802" . "\xf011")
("owm-803" . "\xf012")
("owm-804" . "\xf013")
("owm-900" . "\xf056")
("owm-901" . "\xf01d")
("owm-902" . "\xf073")
("owm-903" . "\xf076")
("owm-904" . "\xf072")
("owm-905" . "\xf021")
("owm-906" . "\xf015")
("owm-957" . "\xf050")
("owm-day-200" . "\xf010")
("owm-day-201" . "\xf010")
("owm-day-202" . "\xf010")
("owm-day-210" . "\xf005")
("owm-day-211" . "\xf005")
("owm-day-212" . "\xf005")
("owm-day-221" . "\xf005")
("owm-day-230" . "\xf010")
("owm-day-231" . "\xf010")
("owm-day-232" . "\xf010")
("owm-day-300" . "\xf00b")
("owm-day-301" . "\xf00b")
("owm-day-302" . "\xf008")
("owm-day-310" . "\xf008")
("owm-day-311" . "\xf008")
("owm-day-312" . "\xf008")
("owm-day-313" . "\xf008")
("owm-day-314" . "\xf008")
("owm-day-321" . "\xf00b")
("owm-day-500" . "\xf00b")
("owm-day-501" . "\xf008")
("owm-day-502" . "\xf008")
("owm-day-503" . "\xf008")
("owm-day-504" . "\xf008")
("owm-day-511" . "\xf006")
("owm-day-520" . "\xf009")
("owm-day-521" . "\xf009")
("owm-day-522" . "\xf009")
("owm-day-531" . "\xf00e")
("owm-day-600" . "\xf00a")
("owm-day-601" . "\xf0b2")
("owm-day-602" . "\xf00a")
("owm-day-611" . "\xf006")
("owm-day-612" . "\xf006")
("owm-day-615" . "\xf006")
("owm-day-616" . "\xf006")
("owm-day-620" . "\xf006")
("owm-day-621" . "\xf00a")
("owm-day-622" . "\xf00a")
("owm-day-701" . "\xf009")
("owm-day-711" . "\xf062")
("owm-day-721" . "\xf0b6")
("owm-day-731" . "\xf063")
("owm-day-741" . "\xf003")
("owm-day-761" . "\xf063")
("owm-day-762" . "\xf063")
("owm-day-781" . "\xf056")
("owm-day-800" . "\xf00d")
("owm-day-801" . "\xf000")
("owm-day-802" . "\xf000")
("owm-day-803" . "\xf000")
("owm-day-804" . "\xf00c")
("owm-day-900" . "\xf056")
("owm-day-902" . "\xf073")
("owm-day-903" . "\xf076")
("owm-day-904" . "\xf072")
("owm-day-906" . "\xf004")
("owm-day-957" . "\xf050")
("owm-night-200" . "\xf02d")
("owm-night-201" . "\xf02d")
("owm-night-202" . "\xf02d")
("owm-night-210" . "\xf025")
("owm-night-211" . "\xf025")
("owm-night-212" . "\xf025")
("owm-night-221" . "\xf025")
("owm-night-230" . "\xf02d")
("owm-night-231" . "\xf02d")
("owm-night-232" . "\xf02d")
("owm-night-300" . "\xf02b")
("owm-night-301" . "\xf02b")
("owm-night-302" . "\xf028")
("owm-night-310" . "\xf028")
("owm-night-311" . "\xf028")
("owm-night-312" . "\xf028")
("owm-night-313" . "\xf028")
("owm-night-314" . "\xf028")
("owm-night-321" . "\xf02b")
("owm-night-500" . "\xf02b")
("owm-night-501" . "\xf028")
("owm-night-502" . "\xf028")
("owm-night-503" . "\xf028")
("owm-night-504" . "\xf028")
("owm-night-511" . "\xf026")
("owm-night-520" . "\xf029")
("owm-night-521" . "\xf029")
("owm-night-522" . "\xf029")
("owm-night-531" . "\xf02c")
("owm-night-600" . "\xf02a")
("owm-night-601" . "\xf0b4")
("owm-night-602" . "\xf02a")
("owm-night-611" . "\xf026")
("owm-night-612" . "\xf026")
("owm-night-615" . "\xf026")
("owm-night-616" . "\xf026")
("owm-night-620" . "\xf026")
("owm-night-621" . "\xf02a")
("owm-night-622" . "\xf02a")
("owm-night-701" . "\xf029")
("owm-night-711" . "\xf062")
("owm-night-721" . "\xf0b6")
("owm-night-731" . "\xf063")
("owm-night-741" . "\xf04a")
("owm-night-761" . "\xf063")
("owm-night-762" . "\xf063")
("owm-night-781" . "\xf056")
("owm-night-800" . "\xf02e")
("owm-night-801" . "\xf022")
("owm-night-802" . "\xf022")
("owm-night-803" . "\xf022")
("owm-night-804" . "\xf086")
("owm-night-900" . "\xf056")
("owm-night-902" . "\xf073")
("owm-night-903" . "\xf076")
("owm-night-904" . "\xf072")
("owm-night-906" . "\xf024")
("owm-night-957" . "\xf050")
("rain" . "\xf019")
("rain-mix" . "\xf017")
("rain-wind" . "\xf018")
("raindrop" . "\xf078")
("raindrops" . "\xf04e")
("refresh" . "\xf04c")
("refresh-alt" . "\xf04b")
("sandstorm" . "\xf082")
("showers" . "\xf01a")
("sleet" . "\xf0b5")
("small-craft-advisory" . "\xf0cc")
("smog" . "\xf074")
("smoke" . "\xf062")
("snow" . "\xf01b")
("snow" . "\xf01b")
("snow-wind" . "\xf064")
("snowflake-cold" . "\xf076")
("solar-eclipse" . "\xf06e")
("sprinkle" . "\xf01c")
("stars" . "\xf077")
("storm-showers" . "\xf01d")
("storm-showers" . "\xf01d")
("storm-warning" . "\xf0ce")
("strong-wind" . "\xf050")
("sunrise" . "\xf051")
("sunset" . "\xf052")
("thermometer" . "\xf055")
("thermometer-exterior" . "\xf053")
("thermometer-internal" . "\xf054")
("thunderstorm" . "\xf01e")
("thunderstorm" . "\xf01e")
("time-1" . "\xf08a")
("time-10" . "\xf093")
("time-11" . "\xf094")
("time-12" . "\xf089")
("time-2" . "\xf08b")
("time-3" . "\xf08c")
("time-4" . "\xf08d")
("time-5" . "\xf08e")
("time-6" . "\xf08f")
("time-7" . "\xf090")
("time-8" . "\xf091")
("time-9" . "\xf092")
("tornado" . "\xf056")
("train" . "\xf0cb")
("tsunami" . "\xf0c5")
("umbrella" . "\xf084")
("volcano" . "\xf0c8")
("wind-beaufort-0" . "\xf0b7")
("wind-beaufort-1" . "\xf0b8")
("wind-beaufort-10" . "\xf0c1")
("wind-beaufort-11" . "\xf0c2")
("wind-beaufort-12" . "\xf0c3")
("wind-beaufort-2" . "\xf0b9")
("wind-beaufort-3" . "\xf0ba")
("wind-beaufort-4" . "\xf0bb")
("wind-beaufort-5" . "\xf0bc")
("wind-beaufort-6" . "\xf0bd")
("wind-beaufort-7" . "\xf0be")
("wind-beaufort-8" . "\xf0bf")
("wind-beaufort-9" . "\xf0c0")
("wind-direction" . "\xf0b1")
("windy" . "\xf021")
("wmo4680-00" . "\xf055")
("wmo4680-01" . "\xf013")
("wmo4680-02" . "\xf055")
("wmo4680-03" . "\xf013")
("wmo4680-04" . "\xf014")
("wmo4680-05" . "\xf014")
("wmo4680-10" . "\xf014")
("wmo4680-11" . "\xf014")
("wmo4680-12" . "\xf016")
("wmo4680-18" . "\xf050")
("wmo4680-20" . "\xf014")
("wmo4680-21" . "\xf017")
("wmo4680-22" . "\xf017")
("wmo4680-23" . "\xf019")
("wmo4680-24" . "\xf01b")
("wmo4680-25" . "\xf015")
("wmo4680-26" . "\xf01e")
("wmo4680-27" . "\xf063")
("wmo4680-28" . "\xf063")
("wmo4680-29" . "\xf063")
("wmo4680-30" . "\xf014")
("wmo4680-31" . "\xf014")
("wmo4680-32" . "\xf014")
("wmo4680-33" . "\xf014")
("wmo4680-34" . "\xf014")
("wmo4680-35" . "\xf014")
("wmo4680-40" . "\xf017")
("wmo4680-41" . "\xf01c")
("wmo4680-42" . "\xf019")
("wmo4680-43" . "\xf01c")
("wmo4680-44" . "\xf019")
("wmo4680-45" . "\xf015")
("wmo4680-46" . "\xf015")
("wmo4680-47" . "\xf01b")
("wmo4680-48" . "\xf01b")
("wmo4680-50" . "\xf01c")
("wmo4680-51" . "\xf01c")
("wmo4680-52" . "\xf019")
("wmo4680-53" . "\xf019")
("wmo4680-54" . "\xf076")
("wmo4680-55" . "\xf076")
("wmo4680-56" . "\xf076")
("wmo4680-57" . "\xf01c")
("wmo4680-58" . "\xf019")
("wmo4680-60" . "\xf01c")
("wmo4680-61" . "\xf01c")
("wmo4680-62" . "\xf019")
("wmo4680-63" . "\xf019")
("wmo4680-64" . "\xf015")
("wmo4680-65" . "\xf015")
("wmo4680-66" . "\xf015")
("wmo4680-67" . "\xf017")
("wmo4680-68" . "\xf017")
("wmo4680-70" . "\xf01b")
("wmo4680-71" . "\xf01b")
("wmo4680-72" . "\xf01b")
("wmo4680-73" . "\xf01b")
("wmo4680-74" . "\xf076")
("wmo4680-75" . "\xf076")
("wmo4680-76" . "\xf076")
("wmo4680-77" . "\xf01b")
("wmo4680-78" . "\xf076")
("wmo4680-80" . "\xf019")
("wmo4680-81" . "\xf01c")
("wmo4680-82" . "\xf019")
("wmo4680-83" . "\xf019")
("wmo4680-84" . "\xf01d")
("wmo4680-85" . "\xf017")
("wmo4680-86" . "\xf017")
("wmo4680-87" . "\xf017")
("wmo4680-89" . "\xf015")
("wmo4680-90" . "\xf016")
("wmo4680-91" . "\xf01d")
("wmo4680-92" . "\xf01e")
("wmo4680-93" . "\xf01e")
("wmo4680-94" . "\xf016")
("wmo4680-95" . "\xf01e")
("wmo4680-96" . "\xf01e")
("wmo4680-99" . "\xf056")
("wu-chanceflurries" . "\xf064")
("wu-chancerain" . "\xf019")
("wu-chancesleat" . "\xf0b5")
("wu-chancesnow" . "\xf01b")
("wu-chancetstorms" . "\xf01e")
("wu-clear" . "\xf00d")
("wu-cloudy" . "\xf002")
("wu-flurries" . "\xf064")
("wu-hazy" . "\xf0b6")
("wu-mostlycloudy" . "\xf002")
("wu-mostlysunny" . "\xf00d")
("wu-partlycloudy" . "\xf002")
("wu-partlysunny" . "\xf00d")
("wu-rain" . "\xf01a")
("wu-sleat" . "\xf0b5")
("wu-snow" . "\xf01b")
("wu-sunny" . "\xf00d")
("wu-tstorms" . "\xf01e")
("wu-unknown" . "\xf00d")
("yahoo-0" . "\xf056")
("yahoo-1" . "\xf00e")
("yahoo-10" . "\xf015")
("yahoo-11" . "\xf01a")
("yahoo-12" . "\xf01a")
("yahoo-13" . "\xf01b")
("yahoo-14" . "\xf00a")
("yahoo-15" . "\xf064")
("yahoo-16" . "\xf01b")
("yahoo-17" . "\xf015")
("yahoo-18" . "\xf017")
("yahoo-19" . "\xf063")
("yahoo-2" . "\xf073")
("yahoo-20" . "\xf014")
("yahoo-21" . "\xf021")
("yahoo-22" . "\xf062")
("yahoo-23" . "\xf050")
("yahoo-24" . "\xf050")
("yahoo-25" . "\xf076")
("yahoo-26" . "\xf013")
("yahoo-27" . "\xf031")
("yahoo-28" . "\xf002")
("yahoo-29" . "\xf031")
("yahoo-3" . "\xf01e")
("yahoo-30" . "\xf002")
("yahoo-31" . "\xf02e")
("yahoo-32" . "\xf00d")
("yahoo-3200" . "\xf077")
("yahoo-33" . "\xf083")
("yahoo-34" . "\xf00c")
("yahoo-35" . "\xf017")
("yahoo-36" . "\xf072")
("yahoo-37" . "\xf00e")
("yahoo-38" . "\xf00e")
("yahoo-39" . "\xf00e")
("yahoo-4" . "\xf01e")
("yahoo-40" . "\xf01a")
("yahoo-41" . "\xf064")
("yahoo-42" . "\xf01b")
("yahoo-43" . "\xf064")
("yahoo-44" . "\xf00c")
("yahoo-45" . "\xf00e")
("yahoo-46" . "\xf01b")
("yahoo-47" . "\xf00e")
("yahoo-5" . "\xf017")
("yahoo-6" . "\xf017")
("yahoo-7" . "\xf017")
("yahoo-8" . "\xf015")
("yahoo-9" . "\xf01a")
))
(provide 'data-weathericons)

View file

@ -0,0 +1,22 @@
;;; all-the-icons-ivy-autoloads.el --- automatically extracted autoloads
;;
;;; Code:
(add-to-list 'load-path (directory-file-name (or (file-name-directory #$) (car load-path))))
;;;### (autoloads nil "all-the-icons-ivy" "all-the-icons-ivy.el"
;;;;;; (23377 61297 57158 640000))
;;; Generated autoloads from all-the-icons-ivy.el
(autoload 'all-the-icons-ivy-setup "all-the-icons-ivy" "\
Set ivy's display transformers to show relevant icons next to the candidates.
\(fn)" nil nil)
;;;***
;; Local Variables:
;; version-control: never
;; no-byte-compile: t
;; no-update-autoloads: t
;; End:
;;; all-the-icons-ivy-autoloads.el ends here

View file

@ -0,0 +1,2 @@
;;; -*- no-byte-compile: t -*-
(define-package "all-the-icons-ivy" "20180225.630" "Shows icons while using ivy and counsel" '((emacs "24.4") (all-the-icons "2.4.0") (ivy "0.8.0")))

View file

@ -0,0 +1,107 @@
;;; all-the-icons-ivy.el --- Shows icons while using ivy and counsel -*- lexical-binding: t; -*-
;; Copyright (C) 2017 asok
;; Author: asok
;; Version: 0.2.0
;; Package-Version: 20180225.630
;; Keywords: faces
;; Package-Requires: ((emacs "24.4") (all-the-icons "2.4.0") (ivy "0.8.0"))
;; 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/>.
;;; Commentary:
;; To use this package, do
;;
;; (all-the-icons-ivy-setup)
;;
;; Or if you prefer to only set transformers
;; for a subset of ivy commands:
;;
;; (require 'all-the-icons-ivy)
;; (ivy-set-display-transformer 'ivy-switch-buffer 'all-the-icons-ivy-buffer-transformer)
;;; Code:
(require 'all-the-icons)
(require 'ivy)
(defgroup all-the-icons-ivy nil
"Shows icons while using ivy and counsel."
:group 'ivy)
(defcustom all-the-icons-ivy-buffer-commands
'(ivy-switch-buffer ivy-switch-buffer-other-window counsel-projectile-switch-to-buffer)
"Commands to use with `all-the-icons-ivy-buffer-transformer'."
:type '(repeat function)
:group 'all-the-icons-ivy)
(defcustom all-the-icons-ivy-file-commands
'(counsel-find-file counsel-projectile-find-file counsel-projectile-find-dir)
"Commands to use with `all-the-icons-ivy-file-transformer'."
:type '(repeat function)
:group 'all-the-icons-ivy)
(defun all-the-icons-ivy--buffer-propertize (b s)
"If buffer B is modified apply `ivy-modified-buffer' face on string S."
(if (and (buffer-file-name b)
(buffer-modified-p b))
(propertize s 'face 'ivy-modified-buffer)
s))
(defun all-the-icons-ivy--icon-for-mode (mode)
"Apply `all-the-icons-for-mode' on MODE but either return an icon or nil."
(let ((icon (all-the-icons-icon-for-mode mode)))
(unless (symbolp icon)
icon)))
(defun all-the-icons-ivy--buffer-transformer (b s)
"Return a candidate string for buffer B named S preceded by an icon.
Try to find the icon for the buffer's B `major-mode'.
If that fails look for an icon for the mode that the `major-mode' is derived from."
(let ((mode (buffer-local-value 'major-mode b)))
(format "%s\t%s"
(propertize "\t" 'display (or
(all-the-icons-ivy--icon-for-mode mode)
(all-the-icons-ivy--icon-for-mode (get mode 'derived-mode-parent))))
(all-the-icons-ivy--buffer-propertize b s))))
(defun all-the-icons-ivy-file-transformer (s)
"Return a candidate string for filename S preceded by an icon."
(format "%s\t%s"
(propertize "\t" 'display (all-the-icons-icon-for-file s))
s))
(defun all-the-icons-ivy-buffer-transformer (s)
"Return a candidate string for buffer named S.
Assume that sometimes the buffer named S might not exists.
That can happen if `ivy-switch-buffer' does not find the buffer and it
falls back to `ivy-recentf' and the same transformer is used."
(let ((b (get-buffer s)))
(if b
(all-the-icons-ivy--buffer-transformer b s)
(all-the-icons-ivy-file-transformer s))))
;;;###autoload
(defun all-the-icons-ivy-setup ()
"Set ivy's display transformers to show relevant icons next to the candidates."
(dolist (cmd all-the-icons-ivy-buffer-commands)
(ivy-set-display-transformer cmd 'all-the-icons-ivy-buffer-transformer))
(dolist (cmd all-the-icons-ivy-file-commands)
(ivy-set-display-transformer cmd 'all-the-icons-ivy-file-transformer)))
(provide 'all-the-icons-ivy)
;;; all-the-icons-ivy.el ends here

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1 @@
Good signature from 474F05837FBDEF9B GNU ELPA Signing Agent <elpasign@elpa.gnu.org> (trust undefined) created at 2018-07-20T05:10:02-0400 using DSA

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,158 @@
;;; async-autoloads.el --- automatically extracted autoloads
;;
;;; Code:
(add-to-list 'load-path (directory-file-name (or (file-name-directory #$) (car load-path))))
;;;### (autoloads nil "async" "async.el" (23377 61605 799563 818000))
;;; Generated autoloads from async.el
(autoload 'async-start-process "async" "\
Start the executable PROGRAM asynchronously. See `async-start'.
PROGRAM is passed PROGRAM-ARGS, calling FINISH-FUNC with the
process object when done. If FINISH-FUNC is nil, the future
object will return the process object when the program is
finished. Set DEFAULT-DIRECTORY to change PROGRAM's current
working directory.
\(fn NAME PROGRAM FINISH-FUNC &rest PROGRAM-ARGS)" nil nil)
(autoload 'async-start "async" "\
Execute START-FUNC (often a lambda) in a subordinate Emacs process.
When done, the return value is passed to FINISH-FUNC. Example:
(async-start
;; What to do in the child process
(lambda ()
(message \"This is a test\")
(sleep-for 3)
222)
;; What to do when it finishes
(lambda (result)
(message \"Async process done, result should be 222: %s\"
result)))
If FINISH-FUNC is nil or missing, a future is returned that can
be inspected using `async-get', blocking until the value is
ready. Example:
(let ((proc (async-start
;; What to do in the child process
(lambda ()
(message \"This is a test\")
(sleep-for 3)
222))))
(message \"I'm going to do some work here\") ;; ....
(message \"Waiting on async process, result should be 222: %s\"
(async-get proc)))
If you don't want to use a callback, and you don't care about any
return value from the child process, pass the `ignore' symbol as
the second argument (if you don't, and never call `async-get', it
will leave *emacs* process buffers hanging around):
(async-start
(lambda ()
(delete-file \"a remote file on a slow link\" nil))
'ignore)
Note: Even when FINISH-FUNC is present, a future is still
returned except that it yields no value (since the value is
passed to FINISH-FUNC). Call `async-get' on such a future always
returns nil. It can still be useful, however, as an argument to
`async-ready' or `async-wait'.
\(fn START-FUNC &optional FINISH-FUNC)" nil nil)
;;;***
;;;### (autoloads nil "async-bytecomp" "async-bytecomp.el" (23377
;;;;;; 61605 797595 754000))
;;; Generated autoloads from async-bytecomp.el
(autoload 'async-byte-recompile-directory "async-bytecomp" "\
Compile all *.el files in DIRECTORY asynchronously.
All *.elc files are systematically deleted before proceeding.
\(fn DIRECTORY &optional QUIET)" nil nil)
(defvar async-bytecomp-package-mode nil "\
Non-nil if Async-Bytecomp-Package mode is enabled.
See the `async-bytecomp-package-mode' command
for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `async-bytecomp-package-mode'.")
(custom-autoload 'async-bytecomp-package-mode "async-bytecomp" nil)
(autoload 'async-bytecomp-package-mode "async-bytecomp" "\
Byte compile asynchronously packages installed with package.el.
Async compilation of packages can be controlled by
`async-bytecomp-allowed-packages'.
\(fn &optional ARG)" t nil)
(autoload 'async-byte-compile-file "async-bytecomp" "\
Byte compile Lisp code FILE asynchronously.
Same as `byte-compile-file' but asynchronous.
\(fn FILE)" t nil)
;;;***
;;;### (autoloads nil "dired-async" "dired-async.el" (23377 61605
;;;;;; 793062 430000))
;;; Generated autoloads from dired-async.el
(defvar dired-async-mode nil "\
Non-nil if Dired-Async mode is enabled.
See the `dired-async-mode' command
for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `dired-async-mode'.")
(custom-autoload 'dired-async-mode "dired-async" nil)
(autoload 'dired-async-mode "dired-async" "\
Do dired actions asynchronously.
\(fn &optional ARG)" t nil)
(autoload 'dired-async-do-copy "dired-async" "\
Run dired-do-copy asynchronously.
\(fn &optional ARG)" t nil)
(autoload 'dired-async-do-symlink "dired-async" "\
Run dired-do-symlink asynchronously.
\(fn &optional ARG)" t nil)
(autoload 'dired-async-do-hardlink "dired-async" "\
Run dired-do-hardlink asynchronously.
\(fn &optional ARG)" t nil)
(autoload 'dired-async-do-rename "dired-async" "\
Run dired-do-rename asynchronously.
\(fn &optional ARG)" t nil)
;;;***
;;;### (autoloads nil nil ("async-pkg.el" "smtpmail-async.el") (23377
;;;;;; 61605 801409 281000))
;;;***
;; Local Variables:
;; version-control: never
;; no-byte-compile: t
;; no-update-autoloads: t
;; End:
;;; async-autoloads.el ends here

View file

@ -0,0 +1,219 @@
;;; async-bytecomp.el --- Compile elisp files asynchronously -*- lexical-binding: t -*-
;; Copyright (C) 2014-2016 Free Software Foundation, Inc.
;; Authors: John Wiegley <jwiegley@gmail.com>
;; Thierry Volpiatto <thierry.volpiatto@gmail.com>
;; Keywords: dired async byte-compile
;; X-URL: https://github.com/jwiegley/dired-async
;; 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 2, 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 GNU Emacs; see the file COPYING. If not, write to the
;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.
;;; Commentary:
;;
;; This package provide the `async-byte-recompile-directory' function
;; which allows, as the name says to recompile a directory outside of
;; your running emacs.
;; The benefit is your files will be compiled in a clean environment without
;; the old *.el files loaded.
;; Among other things, this fix a bug in package.el which recompile
;; the new files in the current environment with the old files loaded, creating
;; errors in most packages after upgrades.
;;
;; NB: This package is advicing the function `package--compile'.
;;; Code:
(require 'cl-lib)
(require 'async)
(defcustom async-bytecomp-allowed-packages
'(async helm helm-core helm-ls-git helm-ls-hg magit)
"Packages in this list will be compiled asynchronously by `package--compile'.
All the dependencies of these packages will be compiled async too,
so no need to add dependencies to this list.
The value of this variable can also be a list with a single element,
the symbol `all', in this case packages are always compiled asynchronously."
:group 'async
:type '(repeat (choice symbol)))
(defvar async-byte-compile-log-file
(concat user-emacs-directory "async-bytecomp.log"))
;;;###autoload
(defun async-byte-recompile-directory (directory &optional quiet)
"Compile all *.el files in DIRECTORY asynchronously.
All *.elc files are systematically deleted before proceeding."
(cl-loop with dir = (directory-files directory t "\\.elc\\'")
unless dir return nil
for f in dir
when (file-exists-p f) do (delete-file f))
;; Ensure async is reloaded when async.elc is deleted.
;; This happen when recompiling its own directory.
(load "async")
(let ((call-back
(lambda (&optional _ignore)
(if (file-exists-p async-byte-compile-log-file)
(let ((buf (get-buffer-create byte-compile-log-buffer))
(n 0))
(with-current-buffer buf
(goto-char (point-max))
(let ((inhibit-read-only t))
(insert-file-contents async-byte-compile-log-file)
(compilation-mode))
(display-buffer buf)
(delete-file async-byte-compile-log-file)
(unless quiet
(save-excursion
(goto-char (point-min))
(while (re-search-forward "^.*:Error:" nil t)
(cl-incf n)))
(if (> n 0)
(message "Failed to compile %d files in directory `%s'" n directory)
(message "Directory `%s' compiled asynchronously with warnings" directory)))))
(unless quiet
(message "Directory `%s' compiled asynchronously with success" directory))))))
(async-start
`(lambda ()
(require 'bytecomp)
,(async-inject-variables "\\`\\(load-path\\)\\|byte\\'")
(let ((default-directory (file-name-as-directory ,directory))
error-data)
(add-to-list 'load-path default-directory)
(byte-recompile-directory ,directory 0 t)
(when (get-buffer byte-compile-log-buffer)
(setq error-data (with-current-buffer byte-compile-log-buffer
(buffer-substring-no-properties (point-min) (point-max))))
(unless (string= error-data "")
(with-temp-file ,async-byte-compile-log-file
(erase-buffer)
(insert error-data))))))
call-back)
(unless quiet (message "Started compiling asynchronously directory %s" directory))))
(defvar package-archive-contents)
(defvar package-alist)
(declare-function package-desc-reqs "package.el" (cl-x))
(defun async-bytecomp--get-package-deps (pkg &optional only)
;; Same as `package--get-deps' but parse instead `package-archive-contents'
;; because PKG is not already installed and not present in `package-alist'.
;; However fallback to `package-alist' in case PKG no more present
;; in `package-archive-contents' due to modification to `package-archives'.
;; See issue #58.
(let* ((pkg-desc (cadr (or (assq pkg package-archive-contents)
(assq pkg package-alist))))
(direct-deps (cl-loop for p in (package-desc-reqs pkg-desc)
for name = (car p)
when (or (assq name package-archive-contents)
(assq name package-alist))
collect name))
(indirect-deps (unless (eq only 'direct)
(delete-dups
(cl-loop for p in direct-deps append
(async-bytecomp--get-package-deps p))))))
(cl-case only
(direct direct-deps)
(separate (list direct-deps indirect-deps))
(indirect indirect-deps)
(t (delete-dups (append direct-deps indirect-deps))))))
(defun async-bytecomp-get-allowed-pkgs ()
(when (and async-bytecomp-allowed-packages
(listp async-bytecomp-allowed-packages))
(if package-archive-contents
(cl-loop for p in async-bytecomp-allowed-packages
when (assq p package-archive-contents)
append (async-bytecomp--get-package-deps p) into reqs
finally return
(delete-dups
(append async-bytecomp-allowed-packages reqs)))
async-bytecomp-allowed-packages)))
(defadvice package--compile (around byte-compile-async)
(let ((cur-package (package-desc-name pkg-desc))
(pkg-dir (package-desc-dir pkg-desc)))
(if (or (equal async-bytecomp-allowed-packages '(all))
(memq cur-package (async-bytecomp-get-allowed-pkgs)))
(progn
(when (eq cur-package 'async)
(fmakunbound 'async-byte-recompile-directory))
;; Add to `load-path' the latest version of async and
;; reload it when reinstalling async.
(when (string= cur-package "async")
(cl-pushnew pkg-dir load-path)
(load "async-bytecomp"))
;; `async-byte-recompile-directory' will add directory
;; as needed to `load-path'.
(async-byte-recompile-directory (package-desc-dir pkg-desc) t))
ad-do-it)))
;;;###autoload
(define-minor-mode async-bytecomp-package-mode
"Byte compile asynchronously packages installed with package.el.
Async compilation of packages can be controlled by
`async-bytecomp-allowed-packages'."
:group 'async
:global t
(if async-bytecomp-package-mode
(ad-activate 'package--compile)
(ad-deactivate 'package--compile)))
;;;###autoload
(defun async-byte-compile-file (file)
"Byte compile Lisp code FILE asynchronously.
Same as `byte-compile-file' but asynchronous."
(interactive "fFile: ")
(let ((call-back
(lambda (&optional _ignore)
(let ((bn (file-name-nondirectory file)))
(if (file-exists-p async-byte-compile-log-file)
(let ((buf (get-buffer-create byte-compile-log-buffer))
start)
(with-current-buffer buf
(goto-char (setq start (point-max)))
(let ((inhibit-read-only t))
(insert-file-contents async-byte-compile-log-file)
(compilation-mode))
(display-buffer buf)
(delete-file async-byte-compile-log-file)
(save-excursion
(goto-char start)
(if (re-search-forward "^.*:Error:" nil t)
(message "Failed to compile `%s'" bn)
(message "`%s' compiled asynchronously with warnings" bn)))))
(message "`%s' compiled asynchronously with success" bn))))))
(async-start
`(lambda ()
(require 'bytecomp)
,(async-inject-variables "\\`load-path\\'")
(let ((default-directory ,(file-name-directory file)))
(add-to-list 'load-path default-directory)
(byte-compile-file ,file)
(when (get-buffer byte-compile-log-buffer)
(setq error-data (with-current-buffer byte-compile-log-buffer
(buffer-substring-no-properties (point-min) (point-max))))
(unless (string= error-data "")
(with-temp-file ,async-byte-compile-log-file
(erase-buffer)
(insert error-data))))))
call-back)))
(provide 'async-bytecomp)
;;; async-bytecomp.el ends here

View file

@ -0,0 +1,6 @@
(define-package "async" "20180527.1030" "Asynchronous processing in Emacs" 'nil :keywords
'("async")
:url "https://github.com/jwiegley/emacs-async")
;; Local Variables:
;; no-byte-compile: t
;; End:

View file

@ -0,0 +1,392 @@
;;; async.el --- Asynchronous processing in Emacs -*- lexical-binding: t -*-
;; Copyright (C) 2012-2016 Free Software Foundation, Inc.
;; Author: John Wiegley <jwiegley@gmail.com>
;; Created: 18 Jun 2012
;; Version: 1.9.3
;; Keywords: async
;; X-URL: https://github.com/jwiegley/emacs-async
;; 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 2, 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 GNU Emacs; see the file COPYING. If not, write to the
;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.
;;; Commentary:
;; Adds the ability to call asynchronous functions and process with ease. See
;; the documentation for `async-start' and `async-start-process'.
;;; Code:
(eval-when-compile (require 'cl-lib))
(defgroup async nil
"Simple asynchronous processing in Emacs"
:group 'emacs)
(defcustom async-variables-noprops-function #'async-variables-noprops
"Default function to remove text properties in variables."
:group 'async
:type 'function)
(defvar async-debug nil)
(defvar async-send-over-pipe t)
(defvar async-in-child-emacs nil)
(defvar async-callback nil)
(defvar async-callback-for-process nil)
(defvar async-callback-value nil)
(defvar async-callback-value-set nil)
(defvar async-current-process nil)
(defvar async--procvar nil)
(defun async-variables-noprops (sequence)
"Remove text properties in SEQUENCE.
Argument SEQUENCE may be a list or a string, if anything else it
is returned unmodified.
Note that this is a naive function that doesn't remove text properties
in SEQUENCE recursively, only at the first level which suffice in most
cases."
(cond ((stringp sequence)
(substring-no-properties sequence))
((listp sequence)
(cl-loop for elm in sequence
if (stringp elm)
collect (substring-no-properties elm)
else collect elm))
(t sequence)))
(defun async-inject-variables
(include-regexp &optional predicate exclude-regexp noprops)
"Return a `setq' form that replicates part of the calling environment.
It sets the value for every variable matching INCLUDE-REGEXP and
also PREDICATE. It will not perform injection for any variable
matching EXCLUDE-REGEXP (if present) or representing a syntax-table
i.e. ending by \"-syntax-table\".
When NOPROPS is non nil it tries to strip out text properties of each
variable's value with `async-variables-noprops-function'.
It is intended to be used as follows:
(async-start
`(lambda ()
(require 'smtpmail)
(with-temp-buffer
(insert ,(buffer-substring-no-properties (point-min) (point-max)))
;; Pass in the variable environment for smtpmail
,(async-inject-variables \"\\`\\(smtpmail\\|\\(user-\\)?mail\\)-\")
(smtpmail-send-it)))
'ignore)"
`(setq
,@(let (bindings)
(mapatoms
(lambda (sym)
(let* ((sname (and (boundp sym) (symbol-name sym)))
(value (and sname (symbol-value sym))))
(when (and sname
(or (null include-regexp)
(string-match include-regexp sname))
(or (null exclude-regexp)
(not (string-match exclude-regexp sname)))
(not (string-match "-syntax-table\\'" sname)))
(unless (or (stringp value)
(memq value '(nil t))
(numberp value)
(vectorp value))
(setq value `(quote ,value)))
(when noprops
(setq value (funcall async-variables-noprops-function
value)))
(when (or (null predicate)
(funcall predicate sym))
(setq bindings (cons value bindings)
bindings (cons sym bindings)))))))
bindings)))
(defalias 'async-inject-environment 'async-inject-variables)
(defun async-handle-result (func result buf)
(if (null func)
(progn
(set (make-local-variable 'async-callback-value) result)
(set (make-local-variable 'async-callback-value-set) t))
(unwind-protect
(if (and (listp result)
(eq 'async-signal (nth 0 result)))
(signal (car (nth 1 result))
(cdr (nth 1 result)))
(funcall func result))
(unless async-debug
(kill-buffer buf)))))
(defun async-when-done (proc &optional _change)
"Process sentinel used to retrieve the value from the child process."
(when (eq 'exit (process-status proc))
(with-current-buffer (process-buffer proc)
(let ((async-current-process proc))
(if (= 0 (process-exit-status proc))
(if async-callback-for-process
(if async-callback
(prog1
(funcall async-callback proc)
(unless async-debug
(kill-buffer (current-buffer))))
(set (make-local-variable 'async-callback-value) proc)
(set (make-local-variable 'async-callback-value-set) t))
(goto-char (point-max))
(backward-sexp)
(async-handle-result async-callback (read (current-buffer))
(current-buffer)))
(set (make-local-variable 'async-callback-value)
(list 'error
(format "Async process '%s' failed with exit code %d"
(process-name proc) (process-exit-status proc))))
(set (make-local-variable 'async-callback-value-set) t))))))
(defun async--receive-sexp (&optional stream)
(let ((sexp (decode-coding-string (base64-decode-string
(read stream)) 'utf-8-auto))
;; Parent expects UTF-8 encoded text.
(coding-system-for-write 'utf-8-auto))
(if async-debug
(message "Received sexp {{{%s}}}" (pp-to-string sexp)))
(setq sexp (read sexp))
(if async-debug
(message "Read sexp {{{%s}}}" (pp-to-string sexp)))
(eval sexp)))
(defun async--insert-sexp (sexp)
(let (print-level
print-length
(print-escape-nonascii t)
(print-circle t))
(prin1 sexp (current-buffer))
;; Just in case the string we're sending might contain EOF
(encode-coding-region (point-min) (point-max) 'utf-8-auto)
(base64-encode-region (point-min) (point-max) t)
(goto-char (point-min)) (insert ?\")
(goto-char (point-max)) (insert ?\" ?\n)))
(defun async--transmit-sexp (process sexp)
(with-temp-buffer
(if async-debug
(message "Transmitting sexp {{{%s}}}" (pp-to-string sexp)))
(async--insert-sexp sexp)
(process-send-region process (point-min) (point-max))))
(defun async-batch-invoke ()
"Called from the child Emacs process' command-line."
;; Make sure 'message' and 'prin1' encode stuff in UTF-8, as parent
;; process expects.
(let ((coding-system-for-write 'utf-8-auto))
(setq async-in-child-emacs t
debug-on-error async-debug)
(if debug-on-error
(prin1 (funcall
(async--receive-sexp (unless async-send-over-pipe
command-line-args-left))))
(condition-case err
(prin1 (funcall
(async--receive-sexp (unless async-send-over-pipe
command-line-args-left))))
(error
(prin1 (list 'async-signal err)))))))
(defun async-ready (future)
"Query a FUTURE to see if it is ready.
I.e., if no blocking
would result from a call to `async-get' on that FUTURE."
(and (memq (process-status future) '(exit signal))
(let ((buf (process-buffer future)))
(if (buffer-live-p buf)
(with-current-buffer buf
async-callback-value-set)
t))))
(defun async-wait (future)
"Wait for FUTURE to become ready."
(while (not (async-ready future))
(sleep-for 0.05)))
(defun async-get (future)
"Get the value from process FUTURE when it is ready.
FUTURE is returned by `async-start' or `async-start-process' when
its FINISH-FUNC is nil."
(and future (async-wait future))
(let ((buf (process-buffer future)))
(when (buffer-live-p buf)
(with-current-buffer buf
(async-handle-result
#'identity async-callback-value (current-buffer))))))
(defun async-message-p (value)
"Return true of VALUE is an async.el message packet."
(and (listp value)
(plist-get value :async-message)))
(defun async-send (&rest args)
"Send the given messages to the asychronous Emacs PROCESS."
(let ((args (append args '(:async-message t))))
(if async-in-child-emacs
(if async-callback
(funcall async-callback args))
(async--transmit-sexp (car args) (list 'quote (cdr args))))))
(defun async-receive ()
"Send the given messages to the asychronous Emacs PROCESS."
(async--receive-sexp))
;;;###autoload
(defun async-start-process (name program finish-func &rest program-args)
"Start the executable PROGRAM asynchronously. See `async-start'.
PROGRAM is passed PROGRAM-ARGS, calling FINISH-FUNC with the
process object when done. If FINISH-FUNC is nil, the future
object will return the process object when the program is
finished. Set DEFAULT-DIRECTORY to change PROGRAM's current
working directory."
(let* ((buf (generate-new-buffer (concat "*" name "*")))
(proc (let ((process-connection-type nil))
(apply #'start-process name buf program program-args))))
(with-current-buffer buf
(set (make-local-variable 'async-callback) finish-func)
(set-process-sentinel proc #'async-when-done)
(unless (string= name "emacs")
(set (make-local-variable 'async-callback-for-process) t))
proc)))
(defvar async-quiet-switch "-Q"
"The Emacs parameter to use to call emacs without config.
Can be one of \"-Q\" or \"-q\".
Default is \"-Q\" but it is sometimes useful to use \"-q\" to have a
enhanced config or some more variables loaded.")
;;;###autoload
(defun async-start (start-func &optional finish-func)
"Execute START-FUNC (often a lambda) in a subordinate Emacs process.
When done, the return value is passed to FINISH-FUNC. Example:
(async-start
;; What to do in the child process
(lambda ()
(message \"This is a test\")
(sleep-for 3)
222)
;; What to do when it finishes
(lambda (result)
(message \"Async process done, result should be 222: %s\"
result)))
If FINISH-FUNC is nil or missing, a future is returned that can
be inspected using `async-get', blocking until the value is
ready. Example:
(let ((proc (async-start
;; What to do in the child process
(lambda ()
(message \"This is a test\")
(sleep-for 3)
222))))
(message \"I'm going to do some work here\") ;; ....
(message \"Waiting on async process, result should be 222: %s\"
(async-get proc)))
If you don't want to use a callback, and you don't care about any
return value from the child process, pass the `ignore' symbol as
the second argument (if you don't, and never call `async-get', it
will leave *emacs* process buffers hanging around):
(async-start
(lambda ()
(delete-file \"a remote file on a slow link\" nil))
'ignore)
Note: Even when FINISH-FUNC is present, a future is still
returned except that it yields no value (since the value is
passed to FINISH-FUNC). Call `async-get' on such a future always
returns nil. It can still be useful, however, as an argument to
`async-ready' or `async-wait'."
(let ((sexp start-func)
;; Subordinate Emacs will send text encoded in UTF-8.
(coding-system-for-read 'utf-8-auto))
(setq async--procvar
(async-start-process
"emacs" (file-truename
(expand-file-name invocation-name
invocation-directory))
finish-func
async-quiet-switch "-l"
;; Using `locate-library' ensure we use the right file
;; when the .elc have been deleted.
(locate-library "async")
"-batch" "-f" "async-batch-invoke"
(if async-send-over-pipe
"<none>"
(with-temp-buffer
(async--insert-sexp (list 'quote sexp))
(buffer-string)))))
(if async-send-over-pipe
(async--transmit-sexp async--procvar (list 'quote sexp)))
async--procvar))
(defmacro async-sandbox(func)
"Evaluate FUNC in a separate Emacs process, synchronously."
`(async-get (async-start ,func)))
(defun async--fold-left (fn forms bindings)
(let ((res forms))
(dolist (binding bindings)
(setq res (funcall fn res
(if (listp binding)
binding
(list binding)))))
res))
(defmacro async-let (bindings &rest forms)
"Implements `let', but each binding is established asynchronously.
For example:
(async-let ((x (foo))
(y (bar)))
(message \"%s %s\" x y))
expands to ==>
(async-start (foo)
(lambda (x)
(async-start (bar)
(lambda (y)
(message \"%s %s\" x y)))))"
(declare (indent 1))
(async--fold-left
(lambda (acc binding)
(let ((fun (pcase (cadr binding)
((and (pred functionp) f) f)
(f `(lambda () ,f)))))
`(async-start ,fun
(lambda (,(car binding))
,acc))))
`(progn ,@forms)
(reverse bindings)))
(provide 'async)
;;; async.el ends here

View file

@ -0,0 +1,405 @@
;;; dired-async.el --- Asynchronous dired actions -*- lexical-binding: t -*-
;; Copyright (C) 2012-2016 Free Software Foundation, Inc.
;; Authors: John Wiegley <jwiegley@gmail.com>
;; Thierry Volpiatto <thierry.volpiatto@gmail.com>
;; Keywords: dired async network
;; X-URL: https://github.com/jwiegley/dired-async
;; 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 2, 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 GNU Emacs; see the file COPYING. If not, write to the
;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.
;;; Commentary:
;; This file provide a redefinition of `dired-create-file' function,
;; performs copies, moves and all what is handled by `dired-create-file'
;; in the background using a slave Emacs process,
;; by means of the async.el module.
;; To use it, put this in your .emacs:
;; (dired-async-mode 1)
;; This will enable async copy/rename etc...
;; in dired and helm.
;;; Code:
(require 'cl-lib)
(require 'dired-aux)
(require 'async)
(eval-when-compile
(defvar async-callback))
(defgroup dired-async nil
"Copy rename files asynchronously from dired."
:group 'dired)
(defcustom dired-async-env-variables-regexp
"\\`\\(tramp-\\(default\\|connection\\|remote\\)\\|ange-ftp\\)-.*"
"Variables matching this regexp will be loaded on Child Emacs."
:type 'regexp
:group 'dired-async)
(defcustom dired-async-message-function 'dired-async-mode-line-message
"Function to use to notify result when operation finish.
Should take same args as `message'."
:group 'dired-async
:type 'function)
(defcustom dired-async-log-file "/tmp/dired-async.log"
"File use to communicate errors from Child Emacs to host Emacs."
:group 'dired-async
:type 'string)
(defcustom dired-async-mode-lighter '(:eval
(when (eq major-mode 'dired-mode)
" Async"))
"Mode line lighter used for `dired-async-mode'."
:group 'dired-async
:risky t
:type 'sexp)
(defface dired-async-message
'((t (:foreground "yellow")))
"Face used for mode-line message."
:group 'dired-async)
(defface dired-async-failures
'((t (:foreground "red")))
"Face used for mode-line message."
:group 'dired-async)
(defface dired-async-mode-message
'((t (:foreground "Gold")))
"Face used for `dired-async--modeline-mode' lighter."
:group 'dired-async)
(define-minor-mode dired-async--modeline-mode
"Notify mode-line that an async process run."
:group 'dired-async
:global t
:lighter (:eval (propertize (format " [%s Async job(s) running]"
(length (dired-async-processes)))
'face 'dired-async-mode-message))
(unless dired-async--modeline-mode
(let ((visible-bell t)) (ding))))
(defun dired-async-mode-line-message (text face &rest args)
"Notify end of operation in `mode-line'."
(message nil)
(let ((mode-line-format (concat
" " (propertize
(if args
(apply #'format text args)
text)
'face face))))
(force-mode-line-update)
(sit-for 3)
(force-mode-line-update)))
(defun dired-async-processes ()
(cl-loop for p in (process-list)
when (cl-loop for c in (process-command p) thereis
(string= "async-batch-invoke" c))
collect p))
(defun dired-async-kill-process ()
(interactive)
(let* ((processes (dired-async-processes))
(proc (car (last processes))))
(and proc (delete-process proc))
(unless (> (length processes) 1)
(dired-async--modeline-mode -1))))
(defun dired-async-after-file-create (total operation failures skipped)
"Callback function used for operation handled by `dired-create-file'."
(unless (dired-async-processes)
;; Turn off mode-line notification
;; only when last process end.
(dired-async--modeline-mode -1))
(when operation
(if (file-exists-p dired-async-log-file)
(progn
(pop-to-buffer (get-buffer-create dired-log-buffer))
(goto-char (point-max))
(setq inhibit-read-only t)
(insert "Error: ")
(insert-file-contents dired-async-log-file)
(special-mode)
(shrink-window-if-larger-than-buffer)
(delete-file dired-async-log-file))
(run-with-timer
0.1 nil
(lambda ()
;; First send error messages.
(cond (failures
(funcall dired-async-message-function
"%s failed for %d of %d file%s -- See *Dired log* buffer"
'dired-async-failures
(car operation) (length failures)
total (dired-plural-s total)))
(skipped
(funcall dired-async-message-function
"%s: %d of %d file%s skipped -- See *Dired log* buffer"
'dired-async-failures
(car operation) (length skipped) total
(dired-plural-s total))))
(when dired-buffers
(cl-loop for (_f . b) in dired-buffers
when (buffer-live-p b)
do (with-current-buffer b (revert-buffer nil t))))
;; Finally send the success message.
(funcall dired-async-message-function
"Asynchronous %s of %s on %s file%s done"
'dired-async-message
(car operation) (cadr operation)
total (dired-plural-s total)))))))
(defun dired-async-maybe-kill-ftp ()
"Return a form to kill ftp process in child emacs."
(quote
(progn
(require 'cl-lib)
(let ((buf (cl-loop for b in (buffer-list)
thereis (and (string-match
"\\`\\*ftp.*"
(buffer-name b)) b))))
(when buf (kill-buffer buf))))))
(defvar overwrite-query)
(defun dired-async-create-files (file-creator operation fn-list name-constructor
&optional _marker-char)
"Same as `dired-create-files' but asynchronous.
See `dired-create-files' for the behavior of arguments."
(setq overwrite-query nil)
(let ((total (length fn-list))
failures async-fn-list skipped callback
async-quiet-switch)
(let (to)
(dolist (from fn-list)
(setq to (funcall name-constructor from))
(if (and (equal to from)
(null (eq file-creator 'backup-file)))
(progn
(setq to nil)
(dired-log "Cannot %s to same file: %s\n"
(downcase operation) from)))
(if (not to)
(setq skipped (cons (dired-make-relative from) skipped))
(let* ((overwrite (and (null (eq file-creator 'backup-file))
(file-exists-p to)))
(dired-overwrite-confirmed ; for dired-handle-overwrite
(and overwrite
(let ((help-form `(format "\
Type SPC or `y' to overwrite file `%s',
DEL or `n' to skip to next,
ESC or `q' to not overwrite any of the remaining files,
`!' to overwrite all remaining files with no more questions." ,to)))
(dired-query 'overwrite-query "Overwrite `%s'?" to)))))
;; Handle the `dired-copy-file' file-creator specially
;; When copying a directory to another directory or
;; possibly to itself or one of its subdirectories.
;; e.g "~/foo/" => "~/test/"
;; or "~/foo/" =>"~/foo/"
;; or "~/foo/ => ~/foo/bar/")
;; In this case the 'name-constructor' have set the destination
;; TO to "~/test/foo" because the old emacs23 behavior
;; of `copy-directory' was to not create the subdirectory
;; and instead copy the contents.
;; With the new behavior of `copy-directory'
;; (similar to the `cp' shell command) we don't
;; need such a construction of the target directory,
;; so modify the destination TO to "~/test/" instead of "~/test/foo/".
(let ((destname (file-name-directory to)))
(when (and (file-directory-p from)
(file-directory-p to)
(eq file-creator 'dired-copy-file))
(setq to destname))
;; If DESTNAME is a subdirectory of FROM, not a symlink,
;; and the method in use is copying, signal an error.
(and (eq t (car (file-attributes destname)))
(eq file-creator 'dired-copy-file)
(file-in-directory-p destname from)
(error "Cannot copy `%s' into its subdirectory `%s'"
from to)))
(if overwrite
(or (and dired-overwrite-confirmed
(push (cons from to) async-fn-list))
(progn
(push (dired-make-relative from) failures)
(dired-log "%s `%s' to `%s' failed\n"
operation from to)))
(push (cons from to) async-fn-list)))))
;; Fix tramp issue #80 with emacs-26, use "-q" only when needed.
(setq async-quiet-switch
(if (and (boundp 'tramp-cache-read-persistent-data)
async-fn-list
(cl-loop for (_from . to) in async-fn-list
thereis (file-remote-p to)))
"-q" "-Q"))
;; When failures have been printed to dired log add the date at bob.
(when (or failures skipped) (dired-log t))
;; When async-fn-list is empty that's mean only one file
;; had to be copied and user finally answer NO.
;; In this case async process will never start and callback
;; will have no chance to run, so notify failures here.
(unless async-fn-list
(cond (failures
(funcall dired-async-message-function
"%s failed for %d of %d file%s -- See *Dired log* buffer"
'dired-async-failures
operation (length failures)
total (dired-plural-s total)))
(skipped
(funcall dired-async-message-function
"%s: %d of %d file%s skipped -- See *Dired log* buffer"
'dired-async-failures
operation (length skipped) total
(dired-plural-s total)))))
;; Setup callback.
(setq callback
(lambda (&optional _ignore)
(dired-async-after-file-create
total (list operation (length async-fn-list)) failures skipped)
(when (string= (downcase operation) "rename")
(cl-loop for (file . to) in async-fn-list
for bf = (get-file-buffer file)
for destp = (file-exists-p to)
do (and bf destp
(with-current-buffer bf
(set-visited-file-name to t t))))))))
;; Start async process.
(when async-fn-list
(async-start `(lambda ()
(require 'cl-lib) (require 'dired-aux) (require 'dired-x)
,(async-inject-variables dired-async-env-variables-regexp)
(let ((dired-recursive-copies (quote always))
(dired-copy-preserve-time
,dired-copy-preserve-time))
(setq overwrite-backup-query nil)
;; Inline `backup-file' as long as it is not
;; available in emacs.
(defalias 'backup-file
;; Same feature as "cp -f --backup=numbered from to"
;; Symlinks are copied as file from source unlike
;; `dired-copy-file' which is same as cp -d.
;; Directories are omitted.
(lambda (from to ok)
(cond ((file-directory-p from) (ignore))
(t (let ((count 0))
(while (let ((attrs (file-attributes to)))
(and attrs (null (nth 0 attrs))))
(cl-incf count)
(setq to (concat (file-name-sans-versions to)
(format ".~%s~" count)))))
(condition-case err
(copy-file from to ok dired-copy-preserve-time)
(file-date-error
(dired-log "Can't set date on %s:\n%s\n" from err)))))))
;; Now run the FILE-CREATOR function on files.
(cl-loop with fn = (quote ,file-creator)
for (from . dest) in (quote ,async-fn-list)
do (condition-case err
(funcall fn from dest t)
(file-error
(dired-log "%s: %s\n" (car err) (cdr err)))
nil))
(when (get-buffer dired-log-buffer)
(dired-log t)
(with-current-buffer dired-log-buffer
(write-region (point-min) (point-max)
,dired-async-log-file))))
,(dired-async-maybe-kill-ftp))
callback)
;; Run mode-line notifications while process running.
(dired-async--modeline-mode 1)
(message "%s proceeding asynchronously..." operation))))
(defvar wdired-use-interactive-rename)
(defun dired-async-wdired-do-renames (old-fn &rest args)
;; Perhaps a better fix would be to ask for renaming BEFORE starting
;; OLD-FN when `wdired-use-interactive-rename' is non-nil. For now
;; just bind it to nil to ensure no questions will be asked between
;; each rename.
(let (wdired-use-interactive-rename)
(apply old-fn args)))
(defadvice wdired-do-renames (around wdired-async)
(let (wdired-use-interactive-rename)
ad-do-it))
(defadvice dired-create-files (around dired-async)
(dired-async-create-files file-creator operation fn-list
name-constructor marker-char))
;;;###autoload
(define-minor-mode dired-async-mode
"Do dired actions asynchronously."
:group 'dired-async
:lighter dired-async-mode-lighter
:global t
(if dired-async-mode
(if (fboundp 'advice-add)
(progn (advice-add 'dired-create-files :override #'dired-async-create-files)
(advice-add 'wdired-do-renames :around #'dired-async-wdired-do-renames))
(ad-activate 'dired-create-files)
(ad-activate 'wdired-do-renames))
(if (fboundp 'advice-remove)
(progn (advice-remove 'dired-create-files #'dired-async-create-files)
(advice-remove 'wdired-do-renames #'dired-async-wdired-do-renames))
(ad-deactivate 'dired-create-files)
(ad-deactivate 'wdired-do-renames))))
(defmacro dired-async--with-async-create-files (&rest body)
"Evaluate BODY with dired-create-files set to dired-async-create-files."
(declare (indent 0))
`(cl-letf (((symbol-function 'dired-create-files) #'dired-async-create-files))
,@body))
;;;###autoload
(defun dired-async-do-copy (&optional arg)
"Run dired-do-copy asynchronously."
(interactive "P")
(dired-async--with-async-create-files
(dired-do-copy arg)))
;;;###autoload
(defun dired-async-do-symlink (&optional arg)
"Run dired-do-symlink asynchronously."
(interactive "P")
(dired-async--with-async-create-files
(dired-do-symlink arg)))
;;;###autoload
(defun dired-async-do-hardlink (&optional arg)
"Run dired-do-hardlink asynchronously."
(interactive "P")
(dired-async--with-async-create-files
(dired-do-hardlink arg)))
;;;###autoload
(defun dired-async-do-rename (&optional arg)
"Run dired-do-rename asynchronously."
(interactive "P")
(dired-async--with-async-create-files
(dired-do-rename arg)))
(provide 'dired-async)
;;; dired-async.el ends here

View file

@ -0,0 +1,73 @@
;;; smtpmail-async.el --- Send e-mail with smtpmail.el asynchronously -*- lexical-binding: t -*-
;; Copyright (C) 2012-2016 Free Software Foundation, Inc.
;; Author: John Wiegley <jwiegley@gmail.com>
;; Created: 18 Jun 2012
;; Keywords: email async
;; X-URL: https://github.com/jwiegley/emacs-async
;; 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 2, 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 GNU Emacs; see the file COPYING. If not, write to the
;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.
;;; Commentary:
;; Send e-mail with smtpmail.el asynchronously. To use:
;;
;; (require 'smtpmail-async)
;;
;; (setq send-mail-function 'async-smtpmail-send-it
;; message-send-mail-function 'async-smtpmail-send-it)
;;
;; This assumes you already have smtpmail.el working.
;;; Code:
(defgroup smtpmail-async nil
"Send e-mail with smtpmail.el asynchronously"
:group 'smptmail)
(require 'async)
(require 'smtpmail)
(require 'message)
(defvar async-smtpmail-before-send-hook nil
"Hook running in the child emacs in `async-smtpmail-send-it'.
It is called just before calling `smtpmail-send-it'.")
(defun async-smtpmail-send-it ()
(let ((to (message-field-value "To"))
(buf-content (buffer-substring-no-properties
(point-min) (point-max))))
(message "Delivering message to %s..." to)
(async-start
`(lambda ()
(require 'smtpmail)
(with-temp-buffer
(insert ,buf-content)
(set-buffer-multibyte nil)
;; Pass in the variable environment for smtpmail
,(async-inject-variables
"\\`\\(smtpmail\\|async-smtpmail\\|\\(user-\\)?mail\\)-\\|auth-sources\\|epg\\|nsm"
nil "\\`\\(mail-header-format-function\\|smtpmail-address-buffer\\|mail-mode-abbrev-table\\)")
(run-hooks 'async-smtpmail-before-send-hook)
(smtpmail-send-it)))
(lambda (&optional _ignore)
(message "Delivering message to %s...done" to)))))
(provide 'smtpmail-async)
;;; smtpmail-async.el ends here

View file

@ -0,0 +1,253 @@
;;; avy-autoloads.el --- automatically extracted autoloads
;;
;;; Code:
(add-to-list 'load-path (directory-file-name (or (file-name-directory #$) (car load-path))))
;;;### (autoloads nil "avy" "avy.el" (23377 60991 205495 602000))
;;; Generated autoloads from avy.el
(autoload 'avy-goto-char "avy" "\
Jump to the currently visible CHAR.
The window scope is determined by `avy-all-windows' (ARG negates it).
\(fn CHAR &optional ARG)" t nil)
(autoload 'avy-goto-char-in-line "avy" "\
Jump to the currently visible CHAR in the current line.
\(fn CHAR)" t nil)
(autoload 'avy-goto-char-2 "avy" "\
Jump to the currently visible CHAR1 followed by CHAR2.
The window scope is determined by `avy-all-windows'.
When ARG is non-nil, do the opposite of `avy-all-windows'.
BEG and END narrow the scope where candidates are searched.
\(fn CHAR1 CHAR2 &optional ARG BEG END)" t nil)
(autoload 'avy-goto-char-2-above "avy" "\
Jump to the currently visible CHAR1 followed by CHAR2.
This is a scoped version of `avy-goto-char-2', where the scope is
the visible part of the current buffer up to point.
The window scope is determined by `avy-all-windows'.
When ARG is non-nil, do the opposite of `avy-all-windows'.
\(fn CHAR1 CHAR2 &optional ARG)" t nil)
(autoload 'avy-goto-char-2-below "avy" "\
Jump to the currently visible CHAR1 followed by CHAR2.
This is a scoped version of `avy-goto-char-2', where the scope is
the visible part of the current buffer following point.
The window scope is determined by `avy-all-windows'.
When ARG is non-nil, do the opposite of `avy-all-windows'.
\(fn CHAR1 CHAR2 &optional ARG)" t nil)
(autoload 'avy-isearch "avy" "\
Jump to one of the current isearch candidates.
\(fn)" t nil)
(autoload 'avy-goto-word-0 "avy" "\
Jump to a word start.
The window scope is determined by `avy-all-windows'.
When ARG is non-nil, do the opposite of `avy-all-windows'.
BEG and END narrow the scope where candidates are searched.
\(fn ARG &optional BEG END)" t nil)
(autoload 'avy-goto-word-1 "avy" "\
Jump to the currently visible CHAR at a word start.
The window scope is determined by `avy-all-windows'.
When ARG is non-nil, do the opposite of `avy-all-windows'.
BEG and END narrow the scope where candidates are searched.
When SYMBOL is non-nil, jump to symbol start instead of word start.
\(fn CHAR &optional ARG BEG END SYMBOL)" t nil)
(autoload 'avy-goto-word-1-above "avy" "\
Jump to the currently visible CHAR at a word start.
This is a scoped version of `avy-goto-word-1', where the scope is
the visible part of the current buffer up to point.
The window scope is determined by `avy-all-windows'.
When ARG is non-nil, do the opposite of `avy-all-windows'.
\(fn CHAR &optional ARG)" t nil)
(autoload 'avy-goto-word-1-below "avy" "\
Jump to the currently visible CHAR at a word start.
This is a scoped version of `avy-goto-word-1', where the scope is
the visible part of the current buffer following point.
The window scope is determined by `avy-all-windows'.
When ARG is non-nil, do the opposite of `avy-all-windows'.
\(fn CHAR &optional ARG)" t nil)
(autoload 'avy-goto-symbol-1 "avy" "\
Jump to the currently visible CHAR at a symbol start.
The window scope is determined by `avy-all-windows'.
When ARG is non-nil, do the opposite of `avy-all-windows'.
\(fn CHAR &optional ARG)" t nil)
(autoload 'avy-goto-symbol-1-above "avy" "\
Jump to the currently visible CHAR at a symbol start.
This is a scoped version of `avy-goto-symbol-1', where the scope is
the visible part of the current buffer up to point.
The window scope is determined by `avy-all-windows'.
When ARG is non-nil, do the opposite of `avy-all-windows'.
\(fn CHAR &optional ARG)" t nil)
(autoload 'avy-goto-symbol-1-below "avy" "\
Jump to the currently visible CHAR at a symbol start.
This is a scoped version of `avy-goto-symbol-1', where the scope is
the visible part of the current buffer following point.
The window scope is determined by `avy-all-windows'.
When ARG is non-nil, do the opposite of `avy-all-windows'.
\(fn CHAR &optional ARG)" t nil)
(autoload 'avy-goto-subword-0 "avy" "\
Jump to a word or subword start.
The window scope is determined by `avy-all-windows' (ARG negates it).
When PREDICATE is non-nil it's a function of zero parameters that
should return true.
BEG and END narrow the scope where candidates are searched.
\(fn &optional ARG PREDICATE BEG END)" t nil)
(autoload 'avy-goto-subword-1 "avy" "\
Jump to the currently visible CHAR at a subword start.
The window scope is determined by `avy-all-windows' (ARG negates it).
The case of CHAR is ignored.
\(fn CHAR &optional ARG)" t nil)
(autoload 'avy-goto-word-or-subword-1 "avy" "\
Forward to `avy-goto-subword-1' or `avy-goto-word-1'.
Which one depends on variable `subword-mode'.
\(fn)" t nil)
(autoload 'avy-goto-line "avy" "\
Jump to a line start in current buffer.
When ARG is 1, jump to lines currently visible, with the option
to cancel to `goto-line' by entering a number.
When ARG is 4, negate the window scope determined by
`avy-all-windows'.
Otherwise, forward to `goto-line' with ARG.
\(fn &optional ARG)" t nil)
(autoload 'avy-goto-line-above "avy" "\
Goto visible line above the cursor.
OFFSET changes the distance between the closest key to the cursor and
the cursor
When BOTTOM-UP is non-nil, display avy candidates from top to bottom
\(fn &optional OFFSET BOTTOM-UP)" t nil)
(autoload 'avy-goto-line-below "avy" "\
Goto visible line below the cursor.
OFFSET changes the distance between the closest key to the cursor and
the cursor
When BOTTOM-UP is non-nil, display avy candidates from top to bottom
\(fn &optional OFFSET BOTTOM-UP)" t nil)
(autoload 'avy-copy-line "avy" "\
Copy a selected line above the current line.
ARG lines can be used.
\(fn ARG)" t nil)
(autoload 'avy-move-line "avy" "\
Move a selected line above the current line.
ARG lines can be used.
\(fn ARG)" t nil)
(autoload 'avy-copy-region "avy" "\
Select two lines and copy the text between them to point.
The window scope is determined by `avy-all-windows' or
`avy-all-windows-alt' when ARG is non-nil.
\(fn ARG)" t nil)
(autoload 'avy-move-region "avy" "\
Select two lines and move the text between them above the current line.
\(fn)" t nil)
(autoload 'avy-kill-region "avy" "\
Select two lines and kill the region between them.
The window scope is determined by `avy-all-windows' or
`avy-all-windows-alt' when ARG is non-nil.
\(fn ARG)" t nil)
(autoload 'avy-kill-ring-save-region "avy" "\
Select two lines and save the region between them to the kill ring.
The window scope is determined by `avy-all-windows'.
When ARG is non-nil, do the opposite of `avy-all-windows'.
\(fn ARG)" t nil)
(autoload 'avy-kill-whole-line "avy" "\
Select line and kill the whole selected line.
With a numerical prefix ARG, kill ARG line(s) starting from the
selected line. If ARG is negative, kill backward.
If ARG is zero, kill the selected line but exclude the trailing
newline.
\\[universal-argument] 3 \\[avy-kil-whole-line] kill three lines
starting from the selected line. \\[universal-argument] -3
\\[avy-kill-whole-line] kill three lines backward including the
selected line.
\(fn ARG)" t nil)
(autoload 'avy-kill-ring-save-whole-line "avy" "\
Select line and save the whole selected line as if killed, but dont kill it.
This command is similar to `avy-kill-whole-line', except that it
saves the line(s) as if killed, but does not kill it(them).
With a numerical prefix ARG, kill ARG line(s) starting from the
selected line. If ARG is negative, kill backward.
If ARG is zero, kill the selected line but exclude the trailing
newline.
\(fn ARG)" t nil)
(autoload 'avy-setup-default "avy" "\
Setup the default shortcuts.
\(fn)" nil nil)
(autoload 'avy-goto-char-timer "avy" "\
Read one or many consecutive chars and jump to the first one.
The window scope is determined by `avy-all-windows' (ARG negates it).
\(fn &optional ARG)" t nil)
;;;***
;; Local Variables:
;; version-control: never
;; no-byte-compile: t
;; no-update-autoloads: t
;; End:
;;; avy-autoloads.el ends here

View file

@ -0,0 +1,2 @@
;;; -*- no-byte-compile: t -*-
(define-package "avy" "20180615.801" "Jump to arbitrary positions in visible text and select text quickly." '((emacs "24.1") (cl-lib "0.5")))

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,79 @@
;;; bind-key-autoloads.el --- automatically extracted autoloads
;;
;;; Code:
(add-to-list 'load-path (directory-file-name (or (file-name-directory #$) (car load-path))))
;;;### (autoloads nil "bind-key" "bind-key.el" (23377 60538 663260
;;;;;; 569000))
;;; Generated autoloads from bind-key.el
(autoload 'bind-key "bind-key" "\
Bind KEY-NAME to COMMAND in KEYMAP (`global-map' if not passed).
KEY-NAME may be a vector, in which case it is passed straight to
`define-key'. Or it may be a string to be interpreted as
spelled-out keystrokes, e.g., \"C-c C-z\". See documentation of
`edmacro-mode' for details.
COMMAND must be an interactive function or lambda form.
KEYMAP, if present, should be a keymap and not a quoted symbol.
For example:
(bind-key \"M-h\" #'some-interactive-function my-mode-map)
If PREDICATE is non-nil, it is a form evaluated to determine when
a key should be bound. It must return non-nil in such cases.
Emacs can evaluate this form at any time that it does redisplay
or operates on menu data structures, so you should write it so it
can safely be called at any time.
\(fn KEY-NAME COMMAND &optional KEYMAP PREDICATE)" nil t)
(autoload 'unbind-key "bind-key" "\
Unbind the given KEY-NAME, within the KEYMAP (if specified).
See `bind-key' for more details.
\(fn KEY-NAME &optional KEYMAP)" nil t)
(autoload 'bind-key* "bind-key" "\
Similar to `bind-key', but overrides any mode-specific bindings.
\(fn KEY-NAME COMMAND &optional PREDICATE)" nil t)
(autoload 'bind-keys "bind-key" "\
Bind multiple keys at once.
Accepts keyword arguments:
:map MAP - a keymap into which the keybindings should be
added
:prefix KEY - prefix key for these bindings
:prefix-map MAP - name of the prefix map that should be created
for these bindings
:prefix-docstring STR - docstring for the prefix-map variable
:menu-name NAME - optional menu string for prefix map
:filter FORM - optional form to determine when bindings apply
The rest of the arguments are conses of keybinding string and a
function symbol (unquoted).
\(fn &rest ARGS)" nil t)
(autoload 'bind-keys* "bind-key" "\
\(fn &rest ARGS)" nil t)
(autoload 'describe-personal-keybindings "bind-key" "\
Display all the personal keybindings defined by `bind-key'.
\(fn)" t nil)
;;;***
;; Local Variables:
;; version-control: never
;; no-byte-compile: t
;; no-update-autoloads: t
;; End:
;;; bind-key-autoloads.el ends here

View file

@ -0,0 +1,2 @@
;;; -*- no-byte-compile: t -*-
(define-package "bind-key" "20180512.2130" "A simple way to manage personal keybindings" 'nil)

View file

@ -0,0 +1,455 @@
;;; bind-key.el --- A simple way to manage personal keybindings
;; Copyright (c) 2012-2017 John Wiegley
;; Author: John Wiegley <johnw@newartisans.com>
;; Maintainer: John Wiegley <johnw@newartisans.com>
;; Created: 16 Jun 2012
;; Modified: 29 Nov 2017
;; Version: 2.4
;; Package-Version: 20180512.2130
;; Keywords: keys keybinding config dotemacs
;; URL: https://github.com/jwiegley/use-package
;; 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, 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 gnu emacs; see the file copying. if not, write to the
;; free software foundation, inc., 59 temple place - suite 330,
;; boston, ma 02111-1307, usa.
;;; Commentary:
;; If you have lots of keybindings set in your .emacs file, it can be hard to
;; know which ones you haven't set yet, and which may now be overriding some
;; new default in a new emacs version. This module aims to solve that
;; problem.
;;
;; Bind keys as follows in your .emacs:
;;
;; (require 'bind-key)
;;
;; (bind-key "C-c x" 'my-ctrl-c-x-command)
;;
;; If the keybinding argument is a vector, it is passed straight to
;; `define-key', so remapping a key with `[remap COMMAND]' works as
;; expected:
;;
;; (bind-key [remap original-ctrl-c-x-command] 'my-ctrl-c-x-command)
;;
;; If you want the keybinding to override all minor modes that may also bind
;; the same key, use the `bind-key*' form:
;;
;; (bind-key* "<C-return>" 'other-window)
;;
;; If you want to rebind a key only in a particular keymap, use:
;;
;; (bind-key "C-c x" 'my-ctrl-c-x-command some-other-mode-map)
;;
;; To unbind a key within a keymap (for example, to stop your favorite major
;; mode from changing a binding that you don't want to override everywhere),
;; use `unbind-key':
;;
;; (unbind-key "C-c x" some-other-mode-map)
;;
;; To bind multiple keys at once, or set up a prefix map, a `bind-keys' macro
;; is provided. It accepts keyword arguments, please see its documentation
;; for a detailed description.
;;
;; To add keys into a specific map, use :map argument
;;
;; (bind-keys :map dired-mode-map
;; ("o" . dired-omit-mode)
;; ("a" . some-custom-dired-function))
;;
;; To set up a prefix map, use `:prefix-map' and `:prefix' arguments (both are
;; required)
;;
;; (bind-keys :prefix-map my-customize-prefix-map
;; :prefix "C-c c"
;; ("f" . customize-face)
;; ("v" . customize-variable))
;;
;; You can combine all the keywords together. Additionally,
;; `:prefix-docstring' can be specified to set documentation of created
;; `:prefix-map' variable.
;;
;; To bind multiple keys in a `bind-key*' way (to be sure that your bindings
;; will not be overridden by other modes), you may use `bind-keys*' macro:
;;
;; (bind-keys*
;; ("C-o" . other-window)
;; ("C-M-n" . forward-page)
;; ("C-M-p" . backward-page))
;;
;; After Emacs loads, you can see a summary of all your personal keybindings
;; currently in effect with this command:
;;
;; M-x describe-personal-keybindings
;;
;; This display will tell you if you've overriden a default keybinding, and
;; what the default was. Also, it will tell you if the key was rebound after
;; your binding it with `bind-key', and what it was rebound it to.
;;; Code:
(require 'cl-lib)
(require 'easy-mmode)
(defgroup bind-key nil
"A simple way to manage personal keybindings"
:group 'emacs)
(defcustom bind-key-column-widths '(18 . 40)
"Width of columns in `describe-personal-keybindings'."
:type '(cons integer integer)
:group 'bind-key)
(defcustom bind-key-segregation-regexp
"\\`\\(\\(C-[chx] \\|M-[gso] \\)\\([CM]-\\)?\\|.+-\\)"
"Regular expression used to divide key sets in the output from
\\[describe-personal-keybindings]."
:type 'regexp
:group 'bind-key)
(defcustom bind-key-describe-special-forms nil
"If non-nil, extract docstrings from lambdas, closures and keymaps if possible."
:type 'boolean
:group 'bind-key)
;; Create override-global-mode to force key remappings
(defvar override-global-map (make-keymap)
"override-global-mode keymap")
(define-minor-mode override-global-mode
"A minor mode so that keymap settings override other modes."
t "")
;; the keymaps in `emulation-mode-map-alists' take precedence over
;; `minor-mode-map-alist'
(add-to-list 'emulation-mode-map-alists
`((override-global-mode . ,override-global-map)))
(defvar personal-keybindings nil
"List of bindings performed by `bind-key'.
Elements have the form ((KEY . [MAP]) CMD ORIGINAL-CMD)")
;;;###autoload
(defmacro bind-key (key-name command &optional keymap predicate)
"Bind KEY-NAME to COMMAND in KEYMAP (`global-map' if not passed).
KEY-NAME may be a vector, in which case it is passed straight to
`define-key'. Or it may be a string to be interpreted as
spelled-out keystrokes, e.g., \"C-c C-z\". See documentation of
`edmacro-mode' for details.
COMMAND must be an interactive function or lambda form.
KEYMAP, if present, should be a keymap and not a quoted symbol.
For example:
(bind-key \"M-h\" #'some-interactive-function my-mode-map)
If PREDICATE is non-nil, it is a form evaluated to determine when
a key should be bound. It must return non-nil in such cases.
Emacs can evaluate this form at any time that it does redisplay
or operates on menu data structures, so you should write it so it
can safely be called at any time."
(let ((namevar (make-symbol "name"))
(keyvar (make-symbol "key"))
(kdescvar (make-symbol "kdesc"))
(bindingvar (make-symbol "binding")))
`(let* ((,namevar ,key-name)
(,keyvar (if (vectorp ,namevar) ,namevar
(read-kbd-macro ,namevar)))
(,kdescvar (cons (if (stringp ,namevar) ,namevar
(key-description ,namevar))
(quote ,keymap)))
(,bindingvar (lookup-key (or ,keymap global-map) ,keyvar)))
(let ((entry (assoc ,kdescvar personal-keybindings))
(details (list ,command
(unless (numberp ,bindingvar)
,bindingvar))))
(if entry
(setcdr entry details)
(add-to-list 'personal-keybindings (cons ,kdescvar details))))
,(if predicate
`(define-key (or ,keymap global-map) ,keyvar
'(menu-item "" nil :filter (lambda (&optional _)
(when ,predicate
,command))))
`(define-key (or ,keymap global-map) ,keyvar ,command)))))
;;;###autoload
(defmacro unbind-key (key-name &optional keymap)
"Unbind the given KEY-NAME, within the KEYMAP (if specified).
See `bind-key' for more details."
`(progn
(bind-key ,key-name nil ,keymap)
(setq personal-keybindings
(cl-delete-if #'(lambda (k)
,(if keymap
`(and (consp (car k))
(string= (caar k) ,key-name)
(eq (cdar k) ',keymap))
`(and (stringp (car k))
(string= (car k) ,key-name))))
personal-keybindings))))
;;;###autoload
(defmacro bind-key* (key-name command &optional predicate)
"Similar to `bind-key', but overrides any mode-specific bindings."
`(bind-key ,key-name ,command override-global-map ,predicate))
(defun bind-keys-form (args keymap)
"Bind multiple keys at once.
Accepts keyword arguments:
:map MAP - a keymap into which the keybindings should be
added
:prefix KEY - prefix key for these bindings
:prefix-map MAP - name of the prefix map that should be created
for these bindings
:prefix-docstring STR - docstring for the prefix-map variable
:menu-name NAME - optional menu string for prefix map
:filter FORM - optional form to determine when bindings apply
The rest of the arguments are conses of keybinding string and a
function symbol (unquoted)."
(let (map
doc
prefix-map
prefix
filter
menu-name
pkg)
;; Process any initial keyword arguments
(let ((cont t))
(while (and cont args)
(if (cond ((and (eq :map (car args))
(not prefix-map))
(setq map (cadr args)))
((eq :prefix-docstring (car args))
(setq doc (cadr args)))
((and (eq :prefix-map (car args))
(not (memq map '(global-map
override-global-map))))
(setq prefix-map (cadr args)))
((eq :prefix (car args))
(setq prefix (cadr args)))
((eq :filter (car args))
(setq filter (cadr args)) t)
((eq :menu-name (car args))
(setq menu-name (cadr args)))
((eq :package (car args))
(setq pkg (cadr args))))
(setq args (cddr args))
(setq cont nil))))
(when (or (and prefix-map (not prefix))
(and prefix (not prefix-map)))
(error "Both :prefix-map and :prefix must be supplied"))
(when (and menu-name (not prefix))
(error "If :menu-name is supplied, :prefix must be too"))
(unless map (setq map keymap))
;; Process key binding arguments
(let (first next)
(while args
(if (keywordp (car args))
(progn
(setq next args)
(setq args nil))
(if first
(nconc first (list (car args)))
(setq first (list (car args))))
(setq args (cdr args))))
(cl-flet
((wrap (map bindings)
(if (and map pkg (not (memq map '(global-map
override-global-map))))
`((if (boundp ',map)
,(macroexp-progn bindings)
(eval-after-load
,(if (symbolp pkg) `',pkg pkg)
',(macroexp-progn bindings))))
bindings)))
(append
(when prefix-map
`((defvar ,prefix-map)
,@(when doc `((put ',prefix-map 'variable-documentation ,doc)))
,@(if menu-name
`((define-prefix-command ',prefix-map nil ,menu-name))
`((define-prefix-command ',prefix-map)))
,@(if (and map (not (eq map 'global-map)))
(wrap map `((bind-key ,prefix ',prefix-map ,map ,filter)))
`((bind-key ,prefix ',prefix-map nil ,filter)))))
(wrap map
(cl-mapcan
(lambda (form)
(let ((fun (and (cdr form) (list 'function (cdr form)))))
(if prefix-map
`((bind-key ,(car form) ,fun ,prefix-map ,filter))
(if (and map (not (eq map 'global-map)))
`((bind-key ,(car form) ,fun ,map ,filter))
`((bind-key ,(car form) ,fun nil ,filter))))))
first))
(when next
(bind-keys-form (if pkg
(cons :package (cons pkg next))
next) map)))))))
;;;###autoload
(defmacro bind-keys (&rest args)
"Bind multiple keys at once.
Accepts keyword arguments:
:map MAP - a keymap into which the keybindings should be
added
:prefix KEY - prefix key for these bindings
:prefix-map MAP - name of the prefix map that should be created
for these bindings
:prefix-docstring STR - docstring for the prefix-map variable
:menu-name NAME - optional menu string for prefix map
:filter FORM - optional form to determine when bindings apply
The rest of the arguments are conses of keybinding string and a
function symbol (unquoted)."
(macroexp-progn (bind-keys-form args nil)))
;;;###autoload
(defmacro bind-keys* (&rest args)
(macroexp-progn (bind-keys-form args 'override-global-map)))
(defun get-binding-description (elem)
(cond
((listp elem)
(cond
((memq (car elem) '(lambda function))
(if (and bind-key-describe-special-forms
(stringp (nth 2 elem)))
(nth 2 elem)
"#<lambda>"))
((eq 'closure (car elem))
(if (and bind-key-describe-special-forms
(stringp (nth 3 elem)))
(nth 3 elem)
"#<closure>"))
((eq 'keymap (car elem))
"#<keymap>")
(t
elem)))
;; must be a symbol, non-symbol keymap case covered above
((and bind-key-describe-special-forms (keymapp elem))
(let ((doc (get elem 'variable-documentation)))
(if (stringp doc) doc elem)))
((symbolp elem)
elem)
(t
"#<byte-compiled lambda>")))
(defun compare-keybindings (l r)
(let* ((regex bind-key-segregation-regexp)
(lgroup (and (string-match regex (caar l))
(match-string 0 (caar l))))
(rgroup (and (string-match regex (caar r))
(match-string 0 (caar r))))
(lkeymap (cdar l))
(rkeymap (cdar r)))
(cond
((and (null lkeymap) rkeymap)
(cons t t))
((and lkeymap (null rkeymap))
(cons nil t))
((and lkeymap rkeymap
(not (string= (symbol-name lkeymap) (symbol-name rkeymap))))
(cons (string< (symbol-name lkeymap) (symbol-name rkeymap)) t))
((and (null lgroup) rgroup)
(cons t t))
((and lgroup (null rgroup))
(cons nil t))
((and lgroup rgroup)
(if (string= lgroup rgroup)
(cons (string< (caar l) (caar r)) nil)
(cons (string< lgroup rgroup) t)))
(t
(cons (string< (caar l) (caar r)) nil)))))
;;;###autoload
(defun describe-personal-keybindings ()
"Display all the personal keybindings defined by `bind-key'."
(interactive)
(with-output-to-temp-buffer "*Personal Keybindings*"
(princ (format (concat "Key name%s Command%s Comments\n%s %s "
"---------------------\n")
(make-string (- (car bind-key-column-widths) 9) ? )
(make-string (- (cdr bind-key-column-widths) 8) ? )
(make-string (1- (car bind-key-column-widths)) ?-)
(make-string (1- (cdr bind-key-column-widths)) ?-)))
(let (last-binding)
(dolist (binding
(setq personal-keybindings
(sort personal-keybindings
(lambda (l r)
(car (compare-keybindings l r))))))
(if (not (eq (cdar last-binding) (cdar binding)))
(princ (format "\n\n%s: %s\n%s\n\n"
(cdar binding) (caar binding)
(make-string (+ 21 (car bind-key-column-widths)
(cdr bind-key-column-widths)) ?-)))
(if (and last-binding
(cdr (compare-keybindings last-binding binding)))
(princ "\n")))
(let* ((key-name (caar binding))
(at-present (lookup-key (or (symbol-value (cdar binding))
(current-global-map))
(read-kbd-macro key-name)))
(command (nth 1 binding))
(was-command (nth 2 binding))
(command-desc (get-binding-description command))
(was-command-desc (and was-command
(get-binding-description was-command)))
(at-present-desc (get-binding-description at-present))
)
(let ((line
(format
(format "%%-%ds%%-%ds%%s\n" (car bind-key-column-widths)
(cdr bind-key-column-widths))
key-name (format "`%s\'" command-desc)
(if (string= command-desc at-present-desc)
(if (or (null was-command)
(string= command-desc was-command-desc))
""
(format "was `%s\'" was-command-desc))
(format "[now: `%s\']" at-present)))))
(princ (if (string-match "[ \t]+\n" line)
(replace-match "\n" t t line)
line))))
(setq last-binding binding)))))
(provide 'bind-key)
;; Local Variables:
;; outline-regexp: ";;;\\(;* [^\s\t\n]\\|###autoload\\)\\|("
;; indent-tabs-mode: nil
;; End:
;;; bind-key.el ends here

View file

@ -0,0 +1,208 @@
;;; cider-apropos.el --- Apropos functionality for Clojure -*- lexical-binding: t -*-
;; Copyright © 2014-2018 Jeff Valk, Bozhidar Batsov and CIDER contributors
;;
;; Author: Jeff Valk <jv@jeffvalk.com>
;; 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/>.
;; This file is not part of GNU Emacs.
;;; Commentary:
;; Apropos functionality for Clojure.
;;; Code:
(require 'cider-doc)
(require 'cider-util)
(require 'subr-x)
(require 'cider-compat)
(require 'cider-client)
(require 'cider-popup)
(require 'nrepl-dict)
(require 'clojure-mode)
(require 'apropos)
(require 'button)
(defconst cider-apropos-buffer "*cider-apropos*")
(defcustom cider-apropos-actions '(("display-doc" . cider-doc-lookup)
("find-def" . cider--find-var)
("lookup-on-grimoire" . cider-grimoire-lookup))
"Controls the actions to be applied on the symbol found by an apropos search.
The first action key in the list will be selected as default. If the list
contains only one action key, the associated action function will be
applied automatically. An action function can be any function that receives
the symbol found by the apropos search as argument."
:type '(alist :key-type string :value-type function)
:group 'cider
:package-version '(cider . "0.13.0"))
(define-button-type 'apropos-special-form
'apropos-label "Special form"
'apropos-short-label "s"
'face 'font-lock-keyword-face
'help-echo "mouse-2, RET: Display more help on this special form"
'follow-link t
'action (lambda (button)
(describe-function (button-get button 'apropos-symbol))))
(defun cider-apropos-doc (button)
"Display documentation for the symbol represented at BUTTON."
(cider-doc-lookup (button-get button 'apropos-symbol)))
(defun cider-apropos-summary (query ns docs-p include-private-p case-sensitive-p)
"Return a short description for the performed apropos search.
QUERY can be a regular expression list of space-separated words
\(e.g take while) which will be converted to a regular expression
\(like take.+while) automatically behind the scenes. The search may be
limited to the namespace NS, and may optionally search doc strings
\(based on DOCS-P), include private vars (based on INCLUDE-PRIVATE-P),
and be case-sensitive (based on CASE-SENSITIVE-P)."
(concat (if case-sensitive-p "Case-sensitive " "")
(if docs-p "Documentation " "")
(format "Apropos for %S" query)
(if ns (format " in namespace %S" ns) "")
(if include-private-p
" (public and private symbols)"
" (public symbols only)")))
(defun cider-apropos-highlight (doc query)
"Return the DOC string propertized to highlight QUERY matches."
(let ((pos 0))
(while (string-match query doc pos)
(setq pos (match-end 0))
(put-text-property (match-beginning 0)
(match-end 0)
'font-lock-face apropos-match-face doc)))
doc)
(defun cider-apropos-result (result query docs-p)
"Emit a RESULT matching QUERY into current buffer, formatted for DOCS-P."
(nrepl-dbind-response result (name type doc)
(let* ((label (capitalize (if (string= type "variable") "var" type)))
(help (concat "Display doc for this " (downcase label))))
(cider-propertize-region (list 'apropos-symbol name
'action 'cider-apropos-doc
'help-echo help)
(insert-text-button name 'type 'apropos-symbol)
(insert "\n ")
(insert-text-button label 'type (intern (concat "apropos-" type)))
(insert ": ")
(let ((beg (point)))
(if docs-p
(insert (cider-apropos-highlight doc query) "\n")
(insert doc)
(fill-region beg (point))))
(insert "\n")))))
(declare-function cider-mode "cider-mode")
(defun cider-show-apropos (summary results query docs-p)
"Show SUMMARY and RESULTS for QUERY in a pop-up buffer, formatted for DOCS-P."
(with-current-buffer (cider-popup-buffer cider-apropos-buffer 'select 'apropos-mode 'ancillary)
(let ((inhibit-read-only t))
(if (boundp 'header-line-format)
(setq-local header-line-format summary)
(insert summary "\n\n"))
(dolist (result results)
(cider-apropos-result result query docs-p))
(goto-char (point-min)))))
;;;###autoload
(defun cider-apropos (query &optional ns docs-p privates-p case-sensitive-p)
"Show all symbols whose names match QUERY, a regular expression.
QUERY can also be a list of space-separated words (e.g. take while) which
will be converted to a regular expression (like take.+while) automatically
behind the scenes. The search may be limited to the namespace NS, and may
optionally search doc strings (based on DOCS-P), include private vars
\(based on PRIVATES-P), and be case-sensitive (based on CASE-SENSITIVE-P)."
(interactive
(cons (read-string "Search for Clojure symbol (a regular expression): ")
(when current-prefix-arg
(list (let ((ns (completing-read "Namespace (default is all): " (cider-sync-request:ns-list))))
(if (string= ns "") nil ns))
(y-or-n-p "Search doc strings? ")
(y-or-n-p "Include private symbols? ")
(y-or-n-p "Case-sensitive? ")))))
(cider-ensure-connected)
(cider-ensure-op-supported "apropos")
(if-let* ((summary (cider-apropos-summary
query ns docs-p privates-p case-sensitive-p))
(results (cider-sync-request:apropos query ns docs-p privates-p case-sensitive-p)))
(cider-show-apropos summary results query docs-p)
(message "No apropos matches for %S" query)))
;;;###autoload
(defun cider-apropos-documentation ()
"Shortcut for (cider-apropos <query> nil t)."
(interactive)
(cider-ensure-connected)
(cider-ensure-op-supported "apropos")
(cider-apropos (read-string "Search for Clojure documentation (a regular expression): ") nil t))
(defun cider-apropos-act-on-symbol (symbol)
"Apply selected action on SYMBOL."
(let* ((first-action-key (car (car cider-apropos-actions)))
(action-key (if (= 1 (length cider-apropos-actions))
first-action-key
(completing-read (format "Choose action to apply to `%s` (default %s): "
symbol first-action-key)
cider-apropos-actions nil nil nil nil first-action-key)))
(action-fn (cdr (assoc action-key cider-apropos-actions))))
(if action-fn
(funcall action-fn symbol)
(user-error "Unknown action `%s`" action-key))))
;;;###autoload
(defun cider-apropos-select (query &optional ns docs-p privates-p case-sensitive-p)
"Similar to `cider-apropos', but presents the results in a completing read.
Show all symbols whose names match QUERY, a regular expression.
QUERY can also be a list of space-separated words (e.g. take while) which
will be converted to a regular expression (like take.+while) automatically
behind the scenes. The search may be limited to the namespace NS, and may
optionally search doc strings (based on DOCS-P), include private vars
\(based on PRIVATES-P), and be case-sensitive (based on CASE-SENSITIVE-P)."
(interactive
(cons (read-string "Search for Clojure symbol (a regular expression): ")
(when current-prefix-arg
(list (let ((ns (completing-read "Namespace (default is all): " (cider-sync-request:ns-list))))
(if (string= ns "") nil ns))
(y-or-n-p "Search doc strings? ")
(y-or-n-p "Include private symbols? ")
(y-or-n-p "Case-sensitive? ")))))
(cider-ensure-connected)
(cider-ensure-op-supported "apropos")
(if-let* ((summary (cider-apropos-summary
query ns docs-p privates-p case-sensitive-p))
(results (mapcar (lambda (r) (nrepl-dict-get r "name"))
(cider-sync-request:apropos query ns docs-p privates-p case-sensitive-p))))
(cider-apropos-act-on-symbol (completing-read (concat summary ": ") results))
(message "No apropos matches for %S" query)))
;;;###autoload
(defun cider-apropos-documentation-select ()
"Shortcut for (cider-apropos-select <query> nil t)."
(interactive)
(cider-ensure-connected)
(cider-ensure-op-supported "apropos")
(cider-apropos-select (read-string "Search for Clojure documentation (a regular expression): ") nil t))
(provide 'cider-apropos)
;;; cider-apropos.el ends here

View file

@ -0,0 +1,607 @@
;;; cider-autoloads.el --- automatically extracted autoloads
;;
;;; Code:
(add-to-list 'load-path (directory-file-name (or (file-name-directory #$) (car load-path))))
;;;### (autoloads nil "cider" "cider.el" (23377 61664 804060 975000))
;;; Generated autoloads from cider.el
(autoload 'cider-version "cider" "\
Display CIDER's version.
\(fn)" t nil)
(autoload 'cider-jack-in-clj "cider" "\
Start an nREPL server for the current project and connect to it.
PARAMS is a plist optionally containing :project-dir and :jack-in-cmd.
With the prefix argument, prompt for all these parameters.
\(fn PARAMS)" t nil)
(autoload 'cider-jack-in-cljs "cider" "\
Start an nREPL server for the current project and connect to it.
PARAMS is a plist optionally containing :project-dir, :jack-in-cmd and
:cljs-repl-type (e.g. Node, Figwheel, etc). With the prefix argument,
prompt for all these parameters.
\(fn PARAMS)" t nil)
(autoload 'cider-jack-in-clj&cljs "cider" "\
Start an nREPL server and connect with clj and cljs REPLs.
PARAMS is a plist optionally containing :project-dir, :jack-in-cmd and
:cljs-repl-type (e.g. Node, Figwheel, etc). With the prefix argument,
prompt for all these parameters. When SOFT-CLJS-START is non-nil, start
cljs REPL only when the ClojureScript dependencies are met.
\(fn &optional PARAMS SOFT-CLJS-START)" t nil)
(autoload 'cider-connect-sibling-clj "cider" "\
Create a Clojure REPL with the same server as OTHER-REPL.
PARAMS is for consistency with other connection commands and is currently
ignored. OTHER-REPL defaults to `cider-current-repl' and in programs can
also be a server buffer, in which case a new session with a REPL for that
server is created.
\(fn PARAMS &optional OTHER-REPL)" t nil)
(autoload 'cider-connect-sibling-cljs "cider" "\
Create a ClojureScript REPL with the same server as OTHER-REPL.
PARAMS is a plist optionally containing :cljs-repl-type (e.g. Node,
Figwheel, etc). All other parameters are inferred from the OTHER-REPL.
OTHER-REPL defaults to `cider-current-repl' but in programs can also be a
server buffer, in which case a new session for that server is created.
\(fn PARAMS &optional OTHER-REPL)" t nil)
(autoload 'cider-connect-clj "cider" "\
Initialize a CLJ connection to an nREPL server.
PARAMS is a plist optionally containing :host, :port and :project-dir. On
prefix argument, prompt for all the parameters.
\(fn &optional PARAMS)" t nil)
(autoload 'cider-connect-cljs "cider" "\
Initialize a CLJS connection to an nREPL server.
PARAMS is a plist optionally containing :host, :port, :project-dir and
:cljs-repl-type (e.g. Node, Figwheel, etc). On prefix, prompt for all the
parameters regardless of their supplied or default values.
\(fn &optional PARAMS)" t nil)
(autoload 'cider-connect-clj&cljs "cider" "\
Initialize a CLJ and CLJS connection to an nREPL server..
PARAMS is a plist optionally containing :host, :port, :project-dir and
:cljs-repl-type (e.g. Node, Figwheel, etc). When SOFT-CLJS-START is
non-nil, don't start if ClojureScript requirements are not met.
\(fn PARAMS &optional SOFT-CLJS-START)" t nil)
(autoload 'cider "cider" "\
Start a connection of any type interactively.
\(fn)" t nil)
(defalias 'cider-jack-in #'cider-jack-in-clj)
(defalias 'cider-jack-in-clojure #'cider-jack-in-clj)
(defalias 'cider-jack-in-clojurescript #'cider-jack-in-cljs)
(defalias 'cider-connect #'cider-connect-clj)
(defalias 'cider-connect-clojure #'cider-connect-clj)
(defalias 'cider-connect-clojurescript #'cider-connect-cljs)
(defalias 'cider-connect-sibling-clojure #'cider-connect-sibling-clj)
(defalias 'cider-connect-sibling-clojurescript #'cider-connect-sibling-cljs)
(eval-after-load 'clojure-mode '(progn (define-key clojure-mode-map (kbd "C-c M-x") #'cider) (define-key clojure-mode-map (kbd "C-c M-j") #'cider-jack-in-clj) (define-key clojure-mode-map (kbd "C-c M-J") #'cider-jack-in-cljs) (define-key clojure-mode-map (kbd "C-c M-c") #'cider-connect-clj) (define-key clojure-mode-map (kbd "C-c M-C") #'cider-connect-cljs) (define-key clojure-mode-map (kbd "C-c C-x") 'cider-start-map) (define-key clojure-mode-map (kbd "C-c C-s") 'sesman-map) (require 'sesman) (sesman-install-menu clojure-mode-map) (add-hook 'clojure-mode-hook (lambda nil (setq-local sesman-system 'CIDER)))))
;;;***
;;;### (autoloads nil "cider-apropos" "cider-apropos.el" (23377 61664
;;;;;; 770864 524000))
;;; Generated autoloads from cider-apropos.el
(autoload 'cider-apropos "cider-apropos" "\
Show all symbols whose names match QUERY, a regular expression.
QUERY can also be a list of space-separated words (e.g. take while) which
will be converted to a regular expression (like take.+while) automatically
behind the scenes. The search may be limited to the namespace NS, and may
optionally search doc strings (based on DOCS-P), include private vars
\(based on PRIVATES-P), and be case-sensitive (based on CASE-SENSITIVE-P).
\(fn QUERY &optional NS DOCS-P PRIVATES-P CASE-SENSITIVE-P)" t nil)
(autoload 'cider-apropos-documentation "cider-apropos" "\
Shortcut for (cider-apropos <query> nil t).
\(fn)" t nil)
(autoload 'cider-apropos-select "cider-apropos" "\
Similar to `cider-apropos', but presents the results in a completing read.
Show all symbols whose names match QUERY, a regular expression.
QUERY can also be a list of space-separated words (e.g. take while) which
will be converted to a regular expression (like take.+while) automatically
behind the scenes. The search may be limited to the namespace NS, and may
optionally search doc strings (based on DOCS-P), include private vars
\(based on PRIVATES-P), and be case-sensitive (based on CASE-SENSITIVE-P).
\(fn QUERY &optional NS DOCS-P PRIVATES-P CASE-SENSITIVE-P)" t nil)
(autoload 'cider-apropos-documentation-select "cider-apropos" "\
Shortcut for (cider-apropos-select <query> nil t).
\(fn)" t nil)
;;;***
;;;### (autoloads nil "cider-browse-ns" "cider-browse-ns.el" (23377
;;;;;; 61664 768380 279000))
;;; Generated autoloads from cider-browse-ns.el
(autoload 'cider-browse-ns "cider-browse-ns" "\
List all NAMESPACE's vars in BUFFER.
\(fn NAMESPACE)" t nil)
(autoload 'cider-browse-ns-all "cider-browse-ns" "\
List all loaded namespaces in BUFFER.
\(fn)" t nil)
;;;***
;;;### (autoloads nil "cider-browse-spec" "cider-browse-spec.el"
;;;;;; (23377 61664 797512 30000))
;;; Generated autoloads from cider-browse-spec.el
(autoload 'cider-browse-spec "cider-browse-spec" "\
Browse SPEC definition.
\(fn SPEC)" t nil)
(autoload 'cider-browse-spec-all "cider-browse-spec" "\
Open list of specs in a popup buffer.
With a prefix argument ARG, prompts for a regexp to filter specs.
No filter applied if the regexp is the empty string.
\(fn &optional ARG)" t nil)
;;;***
;;;### (autoloads nil "cider-cheatsheet" "cider-cheatsheet.el" (23377
;;;;;; 61664 799996 355000))
;;; Generated autoloads from cider-cheatsheet.el
(autoload 'cider-cheatsheet "cider-cheatsheet" "\
Navigate `cider-cheatsheet-hierarchy' with `completing-read'.
When you make it to a Clojure var its doc buffer gets displayed.
\(fn)" t nil)
;;;***
;;;### (autoloads nil "cider-classpath" "cider-classpath.el" (23377
;;;;;; 61664 806586 783000))
;;; Generated autoloads from cider-classpath.el
(autoload 'cider-classpath "cider-classpath" "\
List all classpath entries.
\(fn)" t nil)
(autoload 'cider-open-classpath-entry "cider-classpath" "\
Open a classpath entry.
\(fn)" t nil)
;;;***
;;;### (autoloads nil "cider-debug" "cider-debug.el" (23377 61664
;;;;;; 769634 161000))
;;; Generated autoloads from cider-debug.el
(autoload 'cider-debug-defun-at-point "cider-debug" "\
Instrument the \"top-level\" expression at point.
If it is a defn, dispatch the instrumented definition. Otherwise,
immediately evaluate the instrumented expression.
While debugged code is being evaluated, the user is taken through the
source code and displayed the value of various expressions. At each step,
a number of keys will be prompted to the user.
\(fn)" t nil)
;;;***
;;;### (autoloads nil "cider-find" "cider-find.el" (23377 61664 796304
;;;;;; 526000))
;;; Generated autoloads from cider-find.el
(autoload 'cider-find-var "cider-find" "\
Find definition for VAR at LINE.
Prompt according to prefix ARG and `cider-prompt-for-symbol'.
A single or double prefix argument inverts the meaning of
`cider-prompt-for-symbol'. A prefix of `-` or a double prefix argument causes
the results to be displayed in a different window. The default value is
thing at point.
\(fn &optional ARG VAR LINE)" t nil)
(autoload 'cider-find-dwim "cider-find" "\
Find and display the SYMBOL-FILE at point.
SYMBOL-FILE could be a var or a resource. If thing at point is empty then
show dired on project. If var is not found, try to jump to resource of the
same name. When called interactively, a prompt is given according to the
variable `cider-prompt-for-symbol'. A single or double prefix argument
inverts the meaning. A prefix of `-' or a double prefix argument causes
the results to be displayed in a different window. A default value of thing
at point is given when prompted.
\(fn SYMBOL-FILE)" t nil)
(autoload 'cider-find-resource "cider-find" "\
Find the resource at PATH.
Prompt for input as indicated by the variable `cider-prompt-for-symbol'.
A single or double prefix argument inverts the meaning of
`cider-prompt-for-symbol'. A prefix argument of `-` or a double prefix
argument causes the results to be displayed in other window. The default
value is thing at point.
\(fn PATH)" t nil)
(autoload 'cider-find-ns "cider-find" "\
Find the file containing NS.
A prefix ARG of `-` or a double prefix argument causes
the results to be displayed in a different window.
\(fn &optional ARG NS)" t nil)
(autoload 'cider-find-keyword "cider-find" "\
Find the namespace of the keyword at point and its first occurrence there.
For instance - if the keyword at point is \":cider.demo/keyword\", this command
would find the namespace \"cider.demo\" and afterwards find the first mention
of \"::keyword\" there.
Prompt according to prefix ARG and `cider-prompt-for-symbol'.
A single or double prefix argument inverts the meaning of
`cider-prompt-for-symbol'. A prefix of `-` or a double prefix argument causes
the results to be displayed in a different window. The default value is
thing at point.
\(fn &optional ARG)" t nil)
;;;***
;;;### (autoloads nil "cider-format" "cider-format.el" (23377 61664
;;;;;; 755199 681000))
;;; Generated autoloads from cider-format.el
(autoload 'cider-format-region "cider-format" "\
Format the Clojure code in the current region.
START and END represent the region's boundaries.
\(fn START END)" t nil)
(autoload 'cider-format-defun "cider-format" "\
Format the code in the current defun.
\(fn)" t nil)
(autoload 'cider-format-buffer "cider-format" "\
Format the Clojure code in the current buffer.
\(fn)" t nil)
(autoload 'cider-format-edn-buffer "cider-format" "\
Format the EDN data in the current buffer.
\(fn)" t nil)
(autoload 'cider-format-edn-region "cider-format" "\
Format the EDN data in the current region.
START and END represent the region's boundaries.
\(fn START END)" t nil)
(autoload 'cider-format-edn-last-sexp "cider-format" "\
Format the EDN data of the last sexp.
\(fn)" t nil)
;;;***
;;;### (autoloads nil "cider-grimoire" "cider-grimoire.el" (23377
;;;;;; 61664 785871 442000))
;;; Generated autoloads from cider-grimoire.el
(autoload 'cider-grimoire-web "cider-grimoire" "\
Open grimoire documentation in the default web browser.
Prompts for the symbol to use, or uses the symbol at point, depending on
the value of `cider-prompt-for-symbol'. With prefix arg ARG, does the
opposite of what that option dictates.
\(fn &optional ARG)" t nil)
(autoload 'cider-grimoire "cider-grimoire" "\
Open grimoire documentation in a popup buffer.
Prompts for the symbol to use, or uses the symbol at point, depending on
the value of `cider-prompt-for-symbol'. With prefix arg ARG, does the
opposite of what that option dictates.
\(fn &optional ARG)" t nil)
;;;***
;;;### (autoloads nil "cider-inspector" "cider-inspector.el" (23377
;;;;;; 61664 783382 910000))
;;; Generated autoloads from cider-inspector.el
(autoload 'cider-inspect-last-sexp "cider-inspector" "\
Inspect the result of the the expression preceding point.
\(fn)" t nil)
(autoload 'cider-inspect-defun-at-point "cider-inspector" "\
Inspect the result of the \"top-level\" expression at point.
\(fn)" t nil)
(autoload 'cider-inspect-last-result "cider-inspector" "\
Inspect the most recent eval result.
\(fn)" t nil)
(autoload 'cider-inspect "cider-inspector" "\
Inspect the result of the preceding sexp.
With a prefix argument ARG it inspects the result of the \"top-level\" form.
With a second prefix argument it prompts for an expression to eval and inspect.
\(fn &optional ARG)" t nil)
(autoload 'cider-inspect-expr "cider-inspector" "\
Evaluate EXPR in NS and inspect its value.
Interactively, EXPR is read from the minibuffer, and NS the
current buffer's namespace.
\(fn EXPR NS)" t nil)
;;;***
;;;### (autoloads nil "cider-macroexpansion" "cider-macroexpansion.el"
;;;;;; (23377 61664 801273 463000))
;;; Generated autoloads from cider-macroexpansion.el
(autoload 'cider-macroexpand-1 "cider-macroexpansion" "\
Invoke \\=`macroexpand-1\\=` on the expression preceding point.
If invoked with a PREFIX argument, use \\=`macroexpand\\=` instead of
\\=`macroexpand-1\\=`.
\(fn &optional PREFIX)" t nil)
(autoload 'cider-macroexpand-all "cider-macroexpansion" "\
Invoke \\=`macroexpand-all\\=` on the expression preceding point.
\(fn)" t nil)
;;;***
;;;### (autoloads nil "cider-mode" "cider-mode.el" (23377 61664 773443
;;;;;; 195000))
;;; Generated autoloads from cider-mode.el
(defvar cider-mode-line '(:eval (format " cider[%s]" (cider--modeline-info))) "\
Mode line lighter for cider mode.
The value of this variable is a mode line template as in
`mode-line-format'. See Info Node `(elisp)Mode Line Format' for details
about mode line templates.
Customize this variable to change how cider mode displays its status in the
mode line. The default value displays the current connection. Set this
variable to nil to disable the mode line entirely.")
(custom-autoload 'cider-mode-line "cider-mode" t)
(eval-after-load 'clojure-mode '(easy-menu-define cider-clojure-mode-menu-open clojure-mode-map "Menu for Clojure mode.\n This is displayed in `clojure-mode' buffers, if `cider-mode' is not active." `("CIDER" :visible (not cider-mode) ["Start a Clojure REPL" cider-jack-in :help "Starts an nREPL server (with Leiningen, Boot, or Gradle) and connects a REPL to it."] ["Connect to a Clojure REPL" cider-connect :help "Connects to a REPL that's already running."] ["Connect to a ClojureScript REPL" cider-connect-clojurescript :help "Connects to a ClojureScript REPL that's already running."] ["Start a Clojure REPL, and a ClojureScript REPL" cider-jack-in-cljs :help "Starts an nREPL server, connects a Clojure REPL to it, and then a ClojureScript REPL."] "--" ["View manual online" cider-view-manual])))
(autoload 'cider-mode "cider-mode" "\
Minor mode for REPL interaction from a Clojure buffer.
\\{cider-mode-map}
\(fn &optional ARG)" t nil)
;;;***
;;;### (autoloads nil "cider-ns" "cider-ns.el" (23377 61664 775924
;;;;;; 562000))
;;; Generated autoloads from cider-ns.el
(autoload 'cider-ns-refresh "cider-ns" "\
Reload modified and unloaded namespaces on the classpath.
With a single prefix argument, or if MODE is `refresh-all', reload all
namespaces on the classpath unconditionally.
With a double prefix argument, or if MODE is `clear', clear the state of
the namespace tracker before reloading. This is useful for recovering from
some classes of error (for example, those caused by circular dependencies)
that a normal reload would not otherwise recover from. The trade-off of
clearing is that stale code from any deleted files may not be completely
unloaded.
With a negative prefix argument, or if MODE is `inhibit-fns', prevent any
refresh functions (defined in `cider-ns-refresh-before-fn' and
`cider-ns-refresh-after-fn') from being invoked.
\(fn &optional MODE)" t nil)
;;;***
;;;### (autoloads nil "cider-profile" "cider-profile.el" (23377 61664
;;;;;; 764574 111000))
;;; Generated autoloads from cider-profile.el
(autoload 'cider-profile-samples "cider-profile" "\
Displays current max-sample-count.
If optional QUERY is specified, set max-sample-count and display new value.
\(fn &optional QUERY)" t nil)
(autoload 'cider-profile-var-profiled-p "cider-profile" "\
Displays the profiling status of var under point.
Prompts for var if none under point or QUERY is present.
\(fn QUERY)" t nil)
(autoload 'cider-profile-ns-toggle "cider-profile" "\
Toggle profiling for the ns associated with optional QUERY.
If optional argument QUERY is non-nil, prompt for ns. Otherwise use
current ns.
\(fn &optional QUERY)" t nil)
(autoload 'cider-profile-toggle "cider-profile" "\
Toggle profiling for the given QUERY.
Defaults to the symbol at point.
With prefix arg or no symbol at point, prompts for a var.
\(fn QUERY)" t nil)
(autoload 'cider-profile-summary "cider-profile" "\
Display a summary of currently collected profile data.
\(fn)" t nil)
(autoload 'cider-profile-var-summary "cider-profile" "\
Display profile data for var under point QUERY.
Defaults to the symbol at point. With prefix arg or no symbol at point,
prompts for a var.
\(fn QUERY)" t nil)
(autoload 'cider-profile-clear "cider-profile" "\
Clear any collected profile data.
\(fn)" t nil)
;;;***
;;;### (autoloads nil "cider-repl-history" "cider-repl-history.el"
;;;;;; (23377 61664 794990 521000))
;;; Generated autoloads from cider-repl-history.el
(autoload 'cider-repl-history "cider-repl-history" "\
Display items in the CIDER command history in another buffer.
\(fn)" t nil)
;;;***
;;;### (autoloads nil "cider-scratch" "cider-scratch.el" (23377 61664
;;;;;; 778379 441000))
;;; Generated autoloads from cider-scratch.el
(autoload 'cider-scratch "cider-scratch" "\
Go to the scratch buffer named `cider-scratch-buffer-name'.
\(fn)" t nil)
;;;***
;;;### (autoloads nil "cider-selector" "cider-selector.el" (23377
;;;;;; 61664 805380 173000))
;;; Generated autoloads from cider-selector.el
(autoload 'cider-selector "cider-selector" "\
Select a new buffer by type, indicated by a single character.
The user is prompted for a single character indicating the method by
which to choose a new buffer. The `?' character describes then
available methods. OTHER-WINDOW provides an optional target.
See `def-cider-selector-method' for defining new methods.
\(fn &optional OTHER-WINDOW)" t nil)
;;;***
;;;### (autoloads nil "cider-test" "cider-test.el" (23377 61664 798770
;;;;;; 508000))
;;; Generated autoloads from cider-test.el
(defvar cider-auto-test-mode nil "\
Non-nil if Cider-Auto-Test mode is enabled.
See the `cider-auto-test-mode' command
for a description of this minor mode.
Setting this variable directly does not take effect;
either customize it (see the info node `Easy Customization')
or call the function `cider-auto-test-mode'.")
(custom-autoload 'cider-auto-test-mode "cider-test" nil)
(autoload 'cider-auto-test-mode "cider-test" "\
Toggle automatic testing of Clojure files.
When enabled this reruns tests every time a Clojure file is loaded.
Only runs tests corresponding to the loaded file's namespace and does
nothing if no tests are defined or if the file failed to load.
\(fn &optional ARG)" t nil)
;;;***
;;;### (autoloads nil "cider-tracing" "cider-tracing.el" (23377 61664
;;;;;; 774719 690000))
;;; Generated autoloads from cider-tracing.el
(autoload 'cider-toggle-trace-var "cider-tracing" "\
Toggle var tracing.
Prompts for the symbol to use, or uses the symbol at point, depending on
the value of `cider-prompt-for-symbol'. With prefix arg ARG, does the
opposite of what that option dictates.
\(fn ARG)" t nil)
(autoload 'cider-toggle-trace-ns "cider-tracing" "\
Toggle ns tracing.
Defaults to the current ns. With prefix arg QUERY, prompts for a ns.
\(fn QUERY)" t nil)
;;;***
;;;### (autoloads nil "cider-util" "cider-util.el" (23377 61664 802813
;;;;;; 332000))
;;; Generated autoloads from cider-util.el
(autoload 'cider-view-manual "cider-util" "\
View the manual in your default browser.
\(fn)" t nil)
;;;***
;;;### (autoloads nil nil ("cider-client.el" "cider-common.el" "cider-compat.el"
;;;;;; "cider-completion.el" "cider-connection.el" "cider-doc.el"
;;;;;; "cider-eldoc.el" "cider-eval.el" "cider-overlays.el" "cider-pkg.el"
;;;;;; "cider-popup.el" "cider-repl.el" "cider-resolve.el" "cider-stacktrace.el"
;;;;;; "nrepl-client.el" "nrepl-dict.el") (23377 61664 793689 575000))
;;;***
;; Local Variables:
;; version-control: never
;; no-byte-compile: t
;; no-update-autoloads: t
;; End:
;;; cider-autoloads.el ends here

View file

@ -0,0 +1,232 @@
;;; cider-browse-ns.el --- CIDER namespace browser
;; Copyright © 2014-2018 John Andrews, Bozhidar Batsov and CIDER contributors
;; Author: John Andrews <john.m.andrews@gmail.com>
;; 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/>.
;; This file is not part of GNU Emacs.
;;; Commentary:
;; M-x cider-browse-ns
;;
;; Display a list of all vars in a namespace.
;; Pressing <enter> will take you to the cider-doc buffer for that var.
;; Pressing ^ will take you to a list of all namespaces (akin to `dired-mode').
;; M-x cider-browse-ns-all
;;
;; Explore Clojure namespaces by browsing a list of all namespaces.
;; Pressing <enter> expands into a list of that namespace's vars as if by
;; executing the command (cider-browse-ns "my.ns").
;;; Code:
(require 'cider-client)
(require 'cider-popup)
(require 'cider-compat)
(require 'cider-util)
(require 'nrepl-dict)
(require 'subr-x)
(require 'easymenu)
(require 'thingatpt)
(defconst cider-browse-ns-buffer "*cider-ns-browser*")
(defvar-local cider-browse-ns-current-ns nil)
;; Mode Definition
(defvar cider-browse-ns-mode-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map cider-popup-buffer-mode-map)
(define-key map "d" #'cider-browse-ns-doc-at-point)
(define-key map "s" #'cider-browse-ns-find-at-point)
(define-key map (kbd "RET") #'cider-browse-ns-operate-at-point)
(define-key map "^" #'cider-browse-ns-all)
(define-key map "n" #'next-line)
(define-key map "p" #'previous-line)
(easy-menu-define cider-browse-ns-mode-menu map
"Menu for CIDER's namespace browser"
'("Namespace Browser"
["Show doc" cider-browse-ns-doc-at-point]
["Go to definition" cider-browse-ns-find-at-point]
"--"
["Browse all namespaces" cider-browse-ns-all]))
map))
(defvar cider-browse-ns-mouse-map
(let ((map (make-sparse-keymap)))
(define-key map [mouse-1] #'cider-browse-ns-handle-mouse)
map))
(define-derived-mode cider-browse-ns-mode special-mode "browse-ns"
"Major mode for browsing Clojure namespaces.
\\{cider-browse-ns-mode-map}"
(setq-local electric-indent-chars nil)
(setq-local sesman-system 'CIDER)
(when cider-special-mode-truncate-lines
(setq-local truncate-lines t))
(setq-local cider-browse-ns-current-ns nil))
(defun cider-browse-ns--text-face (var-meta)
"Return font-lock-face for a var.
VAR-META contains the metadata information used to decide a face.
Presence of \"arglists-str\" and \"macro\" indicates a macro form.
Only \"arglists-str\" indicates a function. Otherwise, its a variable.
If the NAMESPACE is not loaded in the REPL, assume TEXT is a fn."
(cond
((not var-meta) 'font-lock-function-name-face)
((and (nrepl-dict-contains var-meta "arglists")
(string= (nrepl-dict-get var-meta "macro") "true"))
'font-lock-keyword-face)
((nrepl-dict-contains var-meta "arglists") 'font-lock-function-name-face)
(t 'font-lock-variable-name-face)))
(defun cider-browse-ns--properties (var var-meta)
"Decorate VAR with a clickable keymap and a face.
VAR-META is used to decide a font-lock face."
(let ((face (cider-browse-ns--text-face var-meta)))
(propertize var
'font-lock-face face
'mouse-face 'highlight
'keymap cider-browse-ns-mouse-map)))
(defun cider-browse-ns--list (buffer title items &optional ns noerase)
"Reset contents of BUFFER.
Display TITLE at the top and ITEMS are indented underneath.
If NS is non-nil, it is added to each item as the
`cider-browse-ns-current-ns' text property. If NOERASE is non-nil, the
contents of the buffer are not reset before inserting TITLE and ITEMS."
(with-current-buffer buffer
(cider-browse-ns-mode)
(let ((inhibit-read-only t))
(unless noerase (erase-buffer))
(goto-char (point-max))
(insert (cider-propertize title 'ns) "\n")
(dolist (item items)
(insert (propertize (concat " " item "\n")
'cider-browse-ns-current-ns ns)))
(goto-char (point-min)))))
(defun cider-browse-ns--first-doc-line (doc)
"Return the first line of the given DOC string.
If the first line of the DOC string contains multiple sentences, only
the first sentence is returned. If the DOC string is nil, a Not documented
string is returned."
(if doc
(let* ((split-newline (split-string doc "\n"))
(first-line (car split-newline)))
(cond
((string-match "\\. " first-line) (substring first-line 0 (match-end 0)))
((= 1 (length split-newline)) first-line)
(t (concat first-line "..."))))
"Not documented."))
(defun cider-browse-ns--items (namespace)
"Return the items to show in the namespace browser of the given NAMESPACE.
Each item consists of a ns-var and the first line of its docstring."
(let* ((ns-vars-with-meta (cider-sync-request:ns-vars-with-meta namespace))
(propertized-ns-vars (nrepl-dict-map #'cider-browse-ns--properties ns-vars-with-meta)))
(mapcar (lambda (ns-var)
(let* ((doc (nrepl-dict-get-in ns-vars-with-meta (list ns-var "doc")))
;; to avoid (read nil)
;; it prompts the user for a Lisp expression
(doc (when doc (read doc)))
(first-doc-line (cider-browse-ns--first-doc-line doc)))
(concat ns-var " " (propertize first-doc-line 'font-lock-face 'font-lock-doc-face))))
propertized-ns-vars)))
;; Interactive Functions
;;;###autoload
(defun cider-browse-ns (namespace)
"List all NAMESPACE's vars in BUFFER."
(interactive (list (completing-read "Browse namespace: " (cider-sync-request:ns-list))))
(with-current-buffer (cider-popup-buffer cider-browse-ns-buffer 'select nil 'ancillary)
(cider-browse-ns--list (current-buffer)
namespace
(cider-browse-ns--items namespace))
(setq-local cider-browse-ns-current-ns namespace)))
;;;###autoload
(defun cider-browse-ns-all ()
"List all loaded namespaces in BUFFER."
(interactive)
(with-current-buffer (cider-popup-buffer cider-browse-ns-buffer 'select nil 'ancillary)
(let ((names (cider-sync-request:ns-list)))
(cider-browse-ns--list (current-buffer)
"All loaded namespaces"
(mapcar (lambda (name)
(cider-browse-ns--properties name nil))
names))
(setq-local cider-browse-ns-current-ns nil))))
(defun cider-browse-ns--thing-at-point ()
"Get the thing at point.
Return a list of the type ('ns or 'var) and the value."
(let ((line (car (split-string (string-trim (thing-at-point 'line)) " "))))
(if (string-match "\\." line)
`(ns ,line)
`(var ,(format "%s/%s"
(or (get-text-property (point) 'cider-browse-ns-current-ns)
cider-browse-ns-current-ns)
line)))))
(defun cider-browse-ns-doc-at-point ()
"Show the documentation for the thing at current point."
(interactive)
(let* ((thing (cider-browse-ns--thing-at-point))
(value (cadr thing)))
;; value is either some ns or a var
(cider-doc-lookup value)))
(defun cider-browse-ns-operate-at-point ()
"Expand browser according to thing at current point.
If the thing at point is a ns it will be browsed,
and if the thing at point is some var - its documentation will
be displayed."
(interactive)
(let* ((thing (cider-browse-ns--thing-at-point))
(type (car thing))
(value (cadr thing)))
(if (eq type 'ns)
(cider-browse-ns value)
(cider-doc-lookup value))))
(declare-function cider-find-ns "cider-find")
(declare-function cider-find-var "cider-find")
(defun cider-browse-ns-find-at-point ()
"Find the definition of the thing at point."
(interactive)
(let* ((thing (cider-browse-ns--thing-at-point))
(type (car thing))
(value (cadr thing)))
(if (eq type 'ns)
(cider-find-ns nil value)
(cider-find-var current-prefix-arg value))))
(defun cider-browse-ns-handle-mouse (event)
"Handle mouse click EVENT."
(interactive "e")
(cider-browse-ns-operate-at-point))
(provide 'cider-browse-ns)
;;; cider-browse-ns.el ends here

View file

@ -0,0 +1,357 @@
;;; cider-browse-spec.el --- CIDER spec browser
;; Copyright © 2017 Juan Monetta, Bozhidar Batsov and CIDER contributors
;; Author: Juan Monetta <jpmonettas@gmail.com>
;; 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/>.
;; This file is not part of GNU Emacs.
;;; Commentary:
;; M-x cider-browse-spec
;;
;; Display a spec description you can browse.
;; Pressing <enter> over a sub spec will take you to the description of that sub spec.
;; Pressing ^ takes you to the list of all specs.
;; M-x cider-browse-spec-all
;;
;; Explore clojure.spec registry by browsing a list of all specs.
;; Pressing <enter> over a spec display the spec description you can browse.
;;; Code:
(require 'cider-client)
(require 'cider-compat)
(require 'cider-util)
(require 'cl-lib)
(require 'nrepl-dict)
(require 'seq)
(require 'subr-x)
(require 'help-mode)
;; The buffer names used by the spec browser
(defconst cider-browse-spec-buffer "*cider-spec-browser*")
(defconst cider-browse-spec-example-buffer "*cider-spec-example*")
;; Mode Definition
(defvar cider-browse-spec-mode-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map (make-composed-keymap button-buffer-map
cider-popup-buffer-mode-map))
(define-key map (kbd "RET") #'cider-browse-spec--browse-at)
(define-key map "n" #'forward-button)
(define-key map "p" #'backward-button)
map)
"Keymap for `cider-browse-spec-mode'.")
(define-derived-mode cider-browse-spec-mode special-mode "Specs"
"Major mode for browsing Clojure specs.
\\{cider-browse-spec-mode-map}"
(setq-local electric-indent-chars nil)
(setq-local sesman-system 'CIDER)
(when cider-special-mode-truncate-lines
(setq-local truncate-lines t)))
(defvar cider-browse-spec--current-spec nil)
(defvar cider-browse-spec-view-mode-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map help-mode-map)
(define-key map (kbd "RET") #'cider-browse-spec--browse-at)
(define-key map "^" #'cider-browse-spec-all)
(define-key map "e" #'cider-browse-spec--print-curr-spec-example)
(define-key map "n" #'forward-button)
(define-key map "p" #'backward-button)
map)
"Keymap for `cider-browse-spec-view-mode'.")
(define-derived-mode cider-browse-spec-view-mode help-mode "Spec"
"Major mode for displaying CIDER spec.
\\{cider-browse-spec-view-mode-map}"
(setq-local cider-browse-spec--current-spec nil)
(setq-local electric-indent-chars nil)
(setq-local sesman-system 'CIDER)
(when cider-special-mode-truncate-lines
(setq-local truncate-lines t)))
(defvar cider-browse-spec-example-mode-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map cider-popup-buffer-mode-map)
(define-key map "^" #'cider-browse-spec-all)
(define-key map "e" #'cider-browse-spec--print-curr-spec-example)
(define-key map "g" #'revert-buffer)
map)
"Keymap for `cider-browse-spec-example-mode'.")
(define-derived-mode cider-browse-spec-example-mode special-mode "Example"
"Major mode for Clojure spec examples.
\\{cider-browse-spec-example-mode-map}"
(setq-local electric-indent-chars nil)
(setq-local revert-buffer-function #'cider-browse-spec--example-revert-buffer-function)
(setq-local sesman-system 'CIDER)
(when cider-special-mode-truncate-lines
(setq-local truncate-lines t)))
;; Non interactive functions
(define-button-type 'cider-browse-spec--spec
'action #'cider-browse-spec--browse-at
'face nil
'follow-link t
'help-echo "View spec")
(defun cider-browse-spec--draw-list-buffer (buffer title specs)
"Reset contents of BUFFER.
Display TITLE at the top and SPECS are indented underneath."
(with-current-buffer buffer
(cider-browse-spec-mode)
(let ((inhibit-read-only t))
(erase-buffer)
(goto-char (point-max))
(insert (cider-propertize title 'emph) "\n")
(dolist (spec-name specs)
(insert (propertize " " 'spec-name spec-name))
(thread-first (cider-font-lock-as-clojure spec-name)
(insert-text-button 'type 'cider-browse-spec--spec)
(button-put 'spec-name spec-name))
(insert (propertize "\n" 'spec-name spec-name)))
(goto-char (point-min)))))
(defun cider--qualified-keyword-p (str)
"Return non nil if STR is a namespaced keyword."
(string-match-p "^:.+/.+$" str))
(defun cider--spec-fn-p (value fn-name)
"Return non nil if VALUE is clojure.spec.[alpha]/FN-NAME."
(string-match-p (concat "^\\(clojure.spec\\|clojure.spec.alpha\\)/" fn-name "$") value))
(defun cider-browse-spec--pprint (form)
"Given a spec FORM builds a multi line string with a pretty render of that FORM."
(cond ((stringp form)
(if (cider--qualified-keyword-p form)
(with-temp-buffer
(thread-first form
(insert-text-button 'type 'cider-browse-spec--spec)
(button-put 'spec-name form))
(buffer-string))
;; to make it easier to read replace all clojure.spec ns with s/
;; and remove all clojure.core ns
(thread-last form
(replace-regexp-in-string "^\\(clojure.spec\\|clojure.spec.alpha\\)/" "s/")
(replace-regexp-in-string "^\\(clojure.core\\)/" ""))))
((and (listp form) (stringp (cl-first form)))
(let ((form-tag (cl-first form)))
(cond
;; prettier fns #()
((string-equal form-tag "clojure.core/fn")
(if (equal (cl-second form) '("%"))
(format "#%s" (cl-reduce #'concat (mapcar #'cider-browse-spec--pprint (cl-rest (cl-rest form)))))
(format "(fn [%%] %s)" (cl-reduce #'concat (mapcar #'cider-browse-spec--pprint (cl-rest (cl-rest form)))))))
;; prettier (s/and )
((cider--spec-fn-p form-tag "and")
(format "(s/and\n%s)" (string-join (thread-last (cl-rest form)
(mapcar #'cider-browse-spec--pprint)
(mapcar (lambda (x) (format "%s" x))))
"\n")))
;; prettier (s/or )
((cider--spec-fn-p form-tag "or")
(let ((name-spec-pair (seq-partition (cl-rest form) 2)))
(format "(s/or\n%s)" (string-join
(thread-last name-spec-pair
(mapcar (lambda (s) (format "%s %s" (cl-first s) (cider-browse-spec--pprint (cl-second s))))))
"\n"))))
;; prettier (s/merge )
((cider--spec-fn-p form-tag "merge")
(format "(s/merge\n%s)" (string-join (thread-last (cl-rest form)
(mapcar #'cider-browse-spec--pprint)
(mapcar (lambda (x) (format "%s" x))))
"\n")))
;; prettier (s/keys )
((cider--spec-fn-p form-tag "keys")
(let ((keys-args (seq-partition (cl-rest form) 2)))
(format "(s/keys%s)" (thread-last
keys-args
(mapcar (lambda (s)
(let ((key-type (cl-first s))
(specs-vec (cl-second s)))
(concat "\n" key-type
" ["
(string-join (thread-last specs-vec
(mapcar #'cider-browse-spec--pprint)
(mapcar (lambda (x) (format "%s" x))))
"\n")
"]"))))
(cl-reduce #'concat)))))
;; prettier (s/multi-spec)
((cider--spec-fn-p form-tag "multi-spec")
(let ((multi-method (cl-second form))
(retag (cl-third form))
(sub-specs (cl-rest (cl-rest (cl-rest form)))))
(format "(s/multi-spec %s %s\n%s)"
multi-method
retag
(string-join
(thread-last sub-specs
(mapcar (lambda (s)
(concat "\n\n" (cl-first s) " " (cider-browse-spec--pprint (cl-second s))))))
"\n"))))
;; prettier (s/cat )
((cider--spec-fn-p form-tag "cat")
(let ((name-spec-pairs (seq-partition (cl-rest form) 2)))
(format "(s/cat %s)"
(thread-last name-spec-pairs
(mapcar (lambda (s)
(concat "\n" (cl-first s) " " (cider-browse-spec--pprint (cl-second s)))))
(cl-reduce #'concat)))))
;; prettier (s/alt )
((cider--spec-fn-p form-tag "alt")
(let ((name-spec-pairs (seq-partition (cl-rest form) 2)))
(format "(s/alt %s)"
(thread-last name-spec-pairs
(mapcar (lambda (s)
(concat "\n" (cl-first s) " " (cider-browse-spec--pprint (cl-second s)))))
(cl-reduce #'concat)))))
;; prettier (s/fspec )
((cider--spec-fn-p form-tag "fspec")
(thread-last (seq-partition (cl-rest form) 2)
(cl-remove-if (lambda (s) (and (stringp (cl-second s))
(string-empty-p (cl-second s)))))
(mapcar (lambda (s)
(format "\n%-11s: %s" (pcase (cl-first s)
(":args" "arguments")
(":ret" "returns")
(":fn" "invariants"))
(cider-browse-spec--pprint (cl-second s)))))
(cl-reduce #'concat)
(format "%s")))
;; every other with no special management
(t (format "(%s %s)"
(cider-browse-spec--pprint form-tag)
(string-join (mapcar #'cider-browse-spec--pprint (cl-rest form)) " "))))))
(t (format "%s" form))))
(defun cider-browse-spec--pprint-indented (spec-form)
"Indent (pretty-print) and font-lock SPEC-FORM.
Return the result as a string."
(with-temp-buffer
(clojure-mode)
(insert (cider-browse-spec--pprint spec-form))
(indent-region (point-min) (point-max))
(cider--font-lock-ensure)
(buffer-string)))
(defun cider-browse-spec--draw-spec-buffer (buffer spec spec-form)
"Reset contents of BUFFER and draws everything needed to browse the SPEC-FORM.
Display SPEC as a title and uses `cider-browse-spec--pprint' to display
a more user friendly representation of SPEC-FORM."
(with-current-buffer buffer
(let ((inhibit-read-only t))
(cider--help-setup-xref (list #'cider-browse-spec spec) nil buffer)
(goto-char (point-max))
(insert (cider-font-lock-as-clojure spec) "\n\n")
(insert (cider-browse-spec--pprint-indented spec-form))
(cider--make-back-forward-xrefs)
(current-buffer))))
(defun cider-browse-spec--browse (spec)
"Browse SPEC."
(cider-ensure-connected)
(cider-ensure-op-supported "spec-form")
(with-current-buffer (cider-popup-buffer cider-browse-spec-buffer 'select #'cider-browse-spec-view-mode 'ancillary)
(setq-local cider-browse-spec--current-spec spec)
(cider-browse-spec--draw-spec-buffer (current-buffer)
spec
(cider-sync-request:spec-form spec))
(goto-char (point-min))
(current-buffer)))
(defun cider-browse-spec--browse-at (&optional pos)
"View the definition of a spec.
Optional argument POS is the position of a spec, defaulting to point. POS
may also be a button, so this function can be used a the button's `action'
property."
(interactive)
(let ((pos (or pos (point))))
(when-let* ((spec (button-get pos 'spec-name)))
(cider-browse-spec--browse spec))))
;; Interactive Functions
(defun cider-browse-spec--print-curr-spec-example ()
"Generate and print an example of the current spec."
(interactive)
(cider-ensure-connected)
(cider-ensure-op-supported "spec-example")
(if-let* ((spec cider-browse-spec--current-spec))
(if-let* ((example (cider-sync-request:spec-example spec)))
(with-current-buffer (cider-popup-buffer cider-browse-spec-example-buffer 'select #'cider-browse-spec-example-mode 'ancillary)
(setq-local cider-browse-spec--current-spec spec)
(let ((inhibit-read-only t))
(insert "Example of " (cider-font-lock-as-clojure spec))
(insert "\n\n")
(insert (cider-font-lock-as-clojure example))
(goto-char (point-min))))
(error (format "No example for spec %s" spec)))
(error "No current spec")))
(defun cider-browse-spec--example-revert-buffer-function (&rest _)
"`revert-buffer' function for `cider-browse-spec-example-mode'.
Generates a new example for the current spec."
(cider-browse-spec--print-curr-spec-example))
;;;###autoload
(defun cider-browse-spec (spec)
"Browse SPEC definition."
(interactive (list (completing-read "Browse spec: "
(cider-sync-request:spec-list)
nil nil
(cider-symbol-at-point))))
(cider-browse-spec--browse spec))
(defun cider-browse-spec-regex (regex)
"Open the list of specs that matches REGEX in a popup buffer.
Displays all specs when REGEX is nil."
(cider-ensure-connected)
(cider-ensure-op-supported "spec-list")
(let ((filter-regex (or regex "")))
(with-current-buffer (cider-popup-buffer cider-browse-spec-buffer 'select nil 'ancillary)
(let ((specs (cider-sync-request:spec-list filter-regex)))
(cider-browse-spec--draw-list-buffer (current-buffer)
(if (string-empty-p filter-regex)
"All specs in registry"
(format "All specs matching regex `%s' in registry" filter-regex))
specs)))))
;;;###autoload
(defun cider-browse-spec-all (&optional arg)
"Open list of specs in a popup buffer.
With a prefix argument ARG, prompts for a regexp to filter specs.
No filter applied if the regexp is the empty string."
(interactive "P")
(cider-browse-spec-regex (if arg (read-string "Filter regex: ") "")))
(provide 'cider-browse-spec)
;;; cider-browse-spec.el ends here

View file

@ -0,0 +1,577 @@
;;; cider-cheatsheet.el --- Quick reference for Clojure -*- lexical-binding: t -*-
;; Copyright © 2018 Kris Jenkins, Bozhidar Batsov and CIDER contributors
;;
;; Author: Kris Jenkins <krisajenkins@gmail.com>
;; 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/>.
;; This file is not part of GNU Emacs.
;;; Commentary:
;; A quick reference system for Clojure. Fast, searchable & available offline.
;; Mostly taken from Kris Jenkins' `clojure-cheatsheet'
;; See: https://github.com/clojure-emacs/clojure-cheatsheet
;;; Code:
(require 'cider-doc)
(require 'seq)
(defconst cider-cheatsheet-hierarchy
'(("Primitives"
("Numbers"
("Arithmetic"
(clojure.core + - * / quot rem mod dec inc max min))
("Compare"
(clojure.core = == not= < > <= >= compare))
("Bitwise"
(clojure.core bit-and bit-and-not bit-clear bit-flip bit-not bit-or bit-set bit-shift-left bit-shift-right bit-test bit-xor unsigned-bit-shift-right))
("Cast"
(clojure.core byte short long int float double bigdec bigint biginteger num rationalize))
("Test"
(clojure.core nil? some? identical? zero? pos? neg? even? odd?))
("Random"
(clojure.core rand rand-int))
("BigDecimal"
(clojure.core with-precision))
("Ratios"
(clojure.core numerator denominator ratio?))
("Arbitrary Precision Arithmetic"
(clojure.core +\' -\' *\' inc\' dec\'))
("Unchecked"
(clojure.core *unchecked-math*
unchecked-add
unchecked-add-int
unchecked-byte
unchecked-char
unchecked-dec
unchecked-dec-int
unchecked-divide-int
unchecked-double
unchecked-float
unchecked-inc
unchecked-inc-int
unchecked-int
unchecked-long
unchecked-multiply
unchecked-multiply-int
unchecked-negate
unchecked-negate-int
unchecked-remainder-int
unchecked-short
unchecked-subtract
unchecked-subtract-int)))
("Strings"
("Create"
(clojure.core str format))
("Use"
(clojure.core count get subs compare)
(clojure.string join escape split split-lines replace replace-first reverse re-quote-replacement index-of last-index-of starts-with? ends-with? includes?))
("Regex"
(clojure.core re-find re-seq re-matches re-pattern re-matcher re-groups)
(clojure.string replace replace-first re-quote-replacement))
("Letters"
(clojure.string capitalize lower-case upper-case))
("Trim"
(clojure.string trim trim-newline triml trimr))
("Test"
(clojure.core char char? string?)
(clojure.string blank?)))
("Other"
("Characters"
(clojure.core char char-name-string char-escape-string))
("Keywords"
(clojure.core keyword keyword? find-keyword))
("Symbols"
(clojure.core symbol symbol? gensym))
("Data Readers"
(clojure.core *data-readers* default-data-readers *default-data-reader-fn*))))
("Collections"
("Generic Ops"
(clojure.core count bounded-count empty not-empty into conj))
("Tree Walking"
(clojure.walk walk prewalk prewalk-demo prewalk-replace postwalk postwalk-demo postwalk-replace keywordize-keys stringify-keys))
("Content tests"
(clojure.core distinct? empty? every? not-every? some not-any?))
("Capabilities"
(clojure.core sequential? associative? sorted? counted? reversible?))
("Type tests"
(clojure.core type class coll? list? vector? set? map? seq?
number? integer? float? decimal? class? rational? ratio?
chunked-seq? reduced? special-symbol? record?))
("Lists"
("Create"
(clojure.core list list*))
("Examine"
(clojure.core first nth peek))
("Change"
(clojure.core cons conj rest pop)))
("Vectors"
("Create"
(clojure.core vec vector vector-of))
("Examine"
(clojure.core get peek))
("Change"
(clojure.core assoc pop subvec replace conj rseq))
("Ops"
(clojure.core mapv filterv reduce-kv)))
("Sets"
("Create"
(clojure.core set hash-set sorted-set sorted-set-by))
("Examine"
(clojure.core get contains?))
("Change"
(clojure.core conj disj))
("Relational Algebra"
(clojure.set join select project union difference intersection))
("Get map"
(clojure.set index rename-keys rename map-invert))
("Test"
(clojure.set subset? superset?))
("Sorted Sets"
(clojure.core rseq subseq rsubseq)))
("Maps"
("Create"
(clojure.core hash-map array-map zipmap sorted-map sorted-map-by bean frequencies group-by))
("Examine"
(clojure.core get get-in contains? find keys vals map-entry?))
("Change"
(clojure.core assoc assoc-in dissoc merge merge-with select-keys update update-in))
("Entry"
(clojure.core key val))
("Sorted Maps"
(clojure.core rseq subseq rsubseq)))
("Hashes"
(clojure.core hash hash-ordered-coll hash-unordered-coll mix-collection-hash))
("Volatiles"
(clojure.core volatile! volatile? vreset! vswap!)))
("Functions"
("Create"
(clojure.core fn defn defn- definline identity constantly comp complement partial juxt memfn memoize fnil every-pred some-fn trampoline))
("Call"
(clojure.core -> ->> some-> some->> as-> cond-> cond->>))
("Test"
(clojure.core fn? ifn?)))
("Transducers"
("Create"
(clojure.core cat dedupe distinct drop drop-while filter halt-when interpose keep keep-indexed map map-indexed mapcat partition-all partition-by random-sample remove replace take take-nth take-while))
("Call"
(clojure.core ->Eduction eduction into sequence transduce completing run!))
("Early Termination"
(clojure.core deref reduced reduced? ensure-reduced unreduced)))
("Spec"
("Operations"
(clojure.spec.alpha valid? conform unform explain explain-data explain-str explain-out form describe assert check-asserts check-asserts?))
("Generator Ops"
(clojure.spec.alpha gen exercise exercise-fn))
("Defn & Registry"
(clojure.spec.alpha def fdef registry get-spec spec? spec with-gen))
("Logical"
(clojure.spec.alpha and or))
("Collection"
(clojure.spec.alpha coll-of map-of every every-kv keys merge))
("Regex "
(clojure.spec.alpha cat alt * + \? & keys*))
("Range"
(clojure.spec.alpha int-in inst-in double-in int-in-range? inst-in-range?))
("Custom Explain"
(clojure.spec.alpha explain-printer *explain-out*))
("Other"
(clojure.spec.alpha nilable multi-spec fspec conformer))
("Predicates with test.check generators"
("Numbers"
(clojure.core number? rational? integer? ratio? decimal? float? zero? double? int? nat-int? neg-int? pos-int?))
("Symbols & Keywords"
(clojure.core keyword? symbol? ident? qualified-ident? qualified-keyword? qualified-symbol? simple-ident? simple-keyword? simple-symbol?))
("Scalars"
(clojure.core string? true? false? nil? some? boolean? bytes? inst? uri? uuid?))
("Collections"
(clojure.core list? map? set? vector? associative? coll? sequential? seq? empty? indexed? seqable?))
("Other"
(clojure.core any?))))
("Other"
("XML"
(clojure.core xml-seq)
(clojure.xml parse))
("REPL"
(clojure.core *1 *2 *3 *e *print-dup* *print-length* *print-level* *print-meta* *print-readably*))
("EDN"
(clojure.edn read read-string))
("Compiling Code & Class Generation"
(clojure.core *compile-files* *compile-path* *file* *warn-on-reflection* compile gen-class gen-interface loaded-libs test))
("Misc"
(clojure.core eval force name *clojure-version* clojure-version *command-line-args*))
("Pretty Printing"
(clojure.pprint pprint print-table pp *print-right-margin*))
("Browser / Shell"
(clojure.java.browse browse-url)
(clojure.java.shell sh with-sh-dir with-sh-env)))
("Vars & Global Environment"
("Def Variants"
(:special def)
(clojure.core defn defn- definline defmacro defmethod defmulti defonce defrecord))
("Interned Vars"
(:special var)
(clojure.core declare intern binding find-var))
("Var Objects"
(clojure.core with-local-vars var-get var-set alter-var-root var?))
("Var Validators"
(clojure.core set-validator! get-validator)))
("Reader Conditionals"
(clojure.core reader-conditional reader-conditional? tagged-literal tagged-literal?))
("Abstractions"
("Protocols"
(clojure.core defprotocol extend extend-type extend-protocol reify extends? satisfies? extenders))
("Records & Types"
(clojure.core defrecord deftype))
("Multimethods"
("Define"
(clojure.core defmulti defmethod))
("Dispatch"
(clojure.core get-method methods))
("Remove"
(clojure.core remove-method remove-all-methods))
("Prefer"
(clojure.core prefer-method prefers))
("Relation"
(clojure.core derive isa? parents ancestors descendants make-hierarchy))))
("Macros"
("Create"
(clojure.core defmacro definline))
("Debug"
(clojure.core macroexpand-1 macroexpand)
(clojure.walk macroexpand-all))
("Branch"
(clojure.core and or when when-not when-let when-first if-not if-let cond condp case))
("Loop"
(clojure.core for doseq dotimes while))
("Arrange"
(clojure.core .. doto ->))
("Scope"
(clojure.core binding locking time)
(clojure.core with-in-str with-local-vars with-open with-out-str with-precision with-redefs with-redefs-fn))
("Lazy"
(clojure.core lazy-cat lazy-seq delay delay?))
("Doc"
(clojure.core assert comment)
(clojure.repl doc dir dir-fn source-fn)))
("Java Interop"
("General"
(:special new set!)
(clojure.core .. doto bean comparator enumeration-seq import iterator-seq memfn definterface supers bases))
("Cast"
(clojure.core boolean byte short char int long float double bigdec bigint num cast biginteger))
("Exceptions"
(:special throw try catch finally)
(clojure.core ex-info ex-data Throwable->map StackTraceElement->vec)
(clojure.repl pst))
("Arrays"
("Create"
(clojure.core boolean-array byte-array double-array char-array float-array int-array long-array make-array object-array short-array to-array))
("Manipulate"
(clojure.core aclone aget aset alength amap areduce aset-int aset-long aset-short aset-boolean aset-byte aset-char aset-double aset-float))
("Cast"
(clojure.core booleans bytes chars doubles floats ints longs shorts)))
("Proxy"
("Create"
(clojure.core proxy get-proxy-class construct-proxy init-proxy))
("Misc"
(clojure.core proxy-mappings proxy-super update-proxy))))
("Namespaces"
("Current"
(clojure.core *ns*))
("Create Switch"
(clojure.core ns in-ns create-ns))
("Add"
(clojure.core alias import intern refer refer-clojure))
("Find"
(clojure.core all-ns find-ns))
("Examine"
(clojure.core ns-aliases ns-imports ns-interns ns-map ns-name ns-publics ns-refers))
("From symbol"
(clojure.core resolve namespace ns-resolve the-ns))
("Remove"
(clojure.core ns-unalias ns-unmap remove-ns)))
("Loading"
("Load libs"
(clojure.core require use import refer))
("List Loaded"
(clojure.core loaded-libs))
("Load Misc"
(clojure.core load load-file load-reader load-string)))
("Concurrency"
("Atoms"
(clojure.core atom swap! swap-vals! reset! reset-vals! compare-and-set!))
("Futures"
(clojure.core future future-call future-cancel future-cancelled? future-done? future?))
("Threads"
(clojure.core bound-fn bound-fn* get-thread-bindings pop-thread-bindings push-thread-bindings))
("Misc"
(clojure.core locking pcalls pvalues pmap seque promise deliver))
("Refs & Transactions"
("Create"
(clojure.core ref))
("Examine"
(clojure.core deref))
("Transaction"
(clojure.core sync dosync io!))
("In Transaction"
(clojure.core ensure ref-set alter commute))
("Validators"
(clojure.core get-validator set-validator!))
("History"
(clojure.core ref-history-count ref-max-history ref-min-history)))
("Agents & Asynchronous Actions"
("Create"
(clojure.core agent))
("Examine"
(clojure.core agent-error))
("Change State"
(clojure.core send send-off restart-agent send-via set-agent-send-executor! set-agent-send-off-executor!))
("Block Waiting"
(clojure.core await await-for))
("Ref Validators"
(clojure.core get-validator set-validator!))
("Watchers"
(clojure.core add-watch remove-watch))
("Thread Handling"
(clojure.core shutdown-agents))
("Error"
(clojure.core error-handler set-error-handler! error-mode set-error-mode!))
("Misc"
(clojure.core *agent* release-pending-sends))))
("Sequences"
("Creating a Lazy Seq"
("From Collection"
(clojure.core seq sequence keys vals rseq subseq rsubseq))
("From Producer Fn"
(clojure.core lazy-seq repeatedly iterate))
("From Constant"
(clojure.core repeat range))
("From Other"
(clojure.core file-seq line-seq resultset-seq re-seq tree-seq xml-seq iterator-seq enumeration-seq))
("From Seq"
(clojure.core keep keep-indexed)))
("Seq in, Seq out"
("Get shorter"
(clojure.core distinct dedupe filter remove for))
("Get longer"
(clojure.core cons conj concat lazy-cat mapcat cycle interleave interpose)))
("Tail-items"
(clojure.core rest nthrest fnext nnext drop drop-while take-last for))
("Head-items"
(clojure.core take take-nth take-while butlast drop-last for))
("Change"
(clojure.core conj concat distinct flatten group-by partition partition-all partition-by split-at split-with filter remove replace shuffle random-sample))
("Rearrange"
(clojure.core reverse sort sort-by compare))
("Process items"
(clojure.core map pmap map-indexed mapcat for replace seque))
("Using a Seq"
("Extract item"
(clojure.core first second last rest next ffirst nfirst fnext nnext nth nthnext rand-nth when-first max-key min-key))
("Construct coll"
(clojure.core zipmap into reduce reductions set vec into-array to-array-2d))
("Pass to fn"
(clojure.core apply))
("Search"
(clojure.core some filter))
("Force evaluation"
(clojure.core doseq dorun doall))
("Check for forced"
(clojure.core realized?))))
("Zippers"
("Create"
(clojure.zip zipper seq-zip vector-zip xml-zip))
("Get loc"
(clojure.zip up down left right leftmost rightmost))
("Get seq"
(clojure.zip lefts rights path children))
("Change"
(clojure.zip make-node replace edit insert-child insert-left insert-right append-child remove))
("Move"
(clojure.zip next prev))
("XML"
(clojure.data.zip.xml attr attr= seq-test tag= text text= xml-> xml1->))
("Misc"
(clojure.zip root node branch? end?)))
("Documentation"
("REPL"
(clojure.repl doc find-doc apropos source pst)
(clojure.java.javadoc javadoc)))
("Transients"
("Create"
(clojure.core transient persistent!))
("Change"
(clojure.core conj! pop! assoc! dissoc! disj!)))
("Misc"
("Compare"
(clojure.core = == identical? not= not compare)
(clojure.data diff))
("Test"
(clojure.core true? false? nil? instance?)))
("IO"
("To/from ..."
(clojure.core spit slurp))
("To *out*"
(clojure.core pr prn print printf println newline)
(clojure.pprint print-table))
("To writer"
(clojure.pprint pprint cl-format))
("To string"
(clojure.core format with-out-str pr-str prn-str print-str println-str))
("From *in*"
(clojure.core read-line read))
("From reader"
(clojure.core line-seq read))
("From string"
(clojure.core read-string with-in-str))
("Open"
(clojure.core with-open)
(clojure.java.io reader writer input-stream output-stream))
("Interop"
(clojure.java.io make-writer make-reader make-output-stream make-input-stream))
("Misc"
(clojure.core flush file-seq *in* *out* *err*)
(clojure.java.io file copy delete-file resource as-file as-url as-relative-path make-parents)))
("Metadata"
(clojure.core meta with-meta alter-meta! reset-meta! vary-meta))
("Special Forms"
(:special def if do quote var recur throw try monitor-enter monitor-exit)
(clojure.core fn loop)
("Binding / Destructuring"
(clojure.core let fn letfn defn defmacro loop for doseq if-let if-some when-let when-some)))
("Async"
("Main"
(clojure.core.async go go-loop <! <!! >! >!! chan put! take take! close! timeout offer! poll! promise-chan))
("Choice"
(clojure.core.async alt! alt!! alts! alts!! do-alts))
("Buffering"
(clojure.core.async buffer dropping-buffer sliding-buffer unblocking-buffer?))
("Pipelines"
(clojure.core.async pipeline pipeline-async pipeline-blocking))
("Threading"
(clojure.core.async thread thread-call))
("Mixing"
(clojure.core.async admix solo-mode mix unmix unmix-all toggle merge pipe unique))
("Multiples"
(clojure.core.async mult tap untap untap-all))
("Publish/Subscribe"
(clojure.core.async pub sub unsub unsub-all))
("Higher Order"
(clojure.core.async filter< filter> map map< map> mapcat< mapcat> partition partition-by reduce remove< remove> split))
("Pre-Populate"
(clojure.core.async into onto-chan to-chan)))
("Unit Tests"
("Defining"
(clojure.test deftest deftest- testing is are))
("Running"
(clojure.test run-tests run-all-tests test-vars))
("Fixtures"
(clojure.test use-fixtures join-fixtures compose-fixtures))))
"A data structure for Clojure cheatsheet information.
It's a tree, where the head of each list determines the context of the rest
of the list. The head may be:
- A string, in which case it's a (sub)heading for the rest of the items.
- A symbol, in which case it's the Clojure namespace of the symbols that
follow it.
- The keyword :special, in which case it's a Clojure special form
- Any other keyword, in which case it's a typed item that will be passed
through.
Note that some Clojure symbols appear in more than once. This is entirely
intentional. For instance, `map` belongs in the sections on collections
and transducers.")
(defun cider-cheatsheet--expand-vars (list)
"Expand the symbols in LIST to fully-qualified var names.
This list is supposed to have the following format:
(my-ns var1 var2 var3)"
(let ((ns (car list))
(vars (cdr list)))
(if (eq ns :special)
(mapcar #'symbol-name vars)
(mapcar (lambda (var) (format "%s/%s" ns var)) vars))))
(defun cider-cheatsheet--select-var (var-list)
"Expand the symbols in VAR-LIST to fully-qualified var names.
The list can hold one or more lists inside - one per each namespace."
(let ((namespaced-vars (seq-mapcat #'cider-cheatsheet--expand-vars
(seq-remove (lambda (list)
(eq (car list) :url))
var-list))))
(cider-doc-lookup (completing-read "Select var: " namespaced-vars))))
;;;###autoload
(defun cider-cheatsheet ()
"Navigate `cider-cheatsheet-hierarchy' with `completing-read'.
When you make it to a Clojure var its doc buffer gets displayed."
(interactive)
(let ((cheatsheet-data cider-cheatsheet-hierarchy))
(while (stringp (caar cheatsheet-data))
(let* ((sections (mapcar #'car cheatsheet-data))
(sel-section (completing-read "Select cheatsheet section: " sections))
(section-data (seq-find (lambda (elem) (equal (car elem) sel-section)) cheatsheet-data)))
(setq cheatsheet-data (cdr section-data))))
(cider-cheatsheet--select-var cheatsheet-data)))
(provide 'cider-cheatsheet)
;;; cider-cheatsheet.el ends here

View file

@ -0,0 +1,112 @@
;;; cider-classpath.el --- Basic Java classpath browser
;; Copyright © 2014-2018 Bozhidar Batsov and CIDER contributors
;; 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/>.
;; This file is not part of GNU Emacs.
;;; Commentary:
;; Basic Java classpath browser for CIDER.
;;; Code:
(require 'cider-client)
(require 'cider-popup)
(require 'subr-x)
(require 'cider-compat)
(defvar cider-classpath-buffer "*cider-classpath*")
(defvar cider-classpath-mode-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map cider-popup-buffer-mode-map)
(define-key map (kbd "RET") #'cider-classpath-operate-on-point)
(define-key map "n" #'next-line)
(define-key map "p" #'previous-line)
map))
(defvar cider-classpath-mouse-map
(let ((map (make-sparse-keymap)))
(define-key map [mouse-1] #'cider-classpath-handle-mouse)
map))
(define-derived-mode cider-classpath-mode special-mode "classpath"
"Major mode for browsing the entries in Java's classpath.
\\{cider-classpath-mode-map}"
(setq-local electric-indent-chars nil)
(setq-local sesman-system 'CIDER)
(when cider-special-mode-truncate-lines
(setq-local truncate-lines t)))
(defun cider-classpath-list (buffer items)
"Populate BUFFER with ITEMS."
(with-current-buffer buffer
(cider-classpath-mode)
(let ((inhibit-read-only t))
(erase-buffer)
(dolist (item items)
(insert item "\n"))
(goto-char (point-min)))))
(defun cider-classpath-properties (text)
"Decorate TEXT with a clickable keymap and function face."
(let ((face (cond
((not (file-exists-p text)) 'font-lock-warning-face)
((file-directory-p text) 'dired-directory)
(t 'default))))
(propertize text
'font-lock-face face
'mouse-face 'highlight
'keymap cider-classpath-mouse-map)))
(defun cider-classpath-operate-on-point ()
"Expand browser according to thing at current point."
(interactive)
(let* ((bol (line-beginning-position))
(eol (line-end-position))
(line (buffer-substring-no-properties bol eol)))
(find-file-other-window line)))
(defun cider-classpath-handle-mouse (event)
"Handle mouse click EVENT."
(interactive "e")
(cider-classpath-operate-on-point))
;;;###autoload
(defun cider-classpath ()
"List all classpath entries."
(interactive)
(cider-ensure-connected)
(cider-ensure-op-supported "classpath")
(with-current-buffer (cider-popup-buffer cider-classpath-buffer 'select nil 'ancillary)
(cider-classpath-list (current-buffer)
(mapcar (lambda (name)
(cider-classpath-properties name))
(cider-sync-request:classpath)))))
;;;###autoload
(defun cider-open-classpath-entry ()
"Open a classpath entry."
(interactive)
(cider-ensure-connected)
(cider-ensure-op-supported "classpath")
(when-let* ((entry (completing-read "Classpath entries: " (cider-sync-request:classpath))))
(find-file-other-window entry)))
(provide 'cider-classpath)
;;; cider-classpath.el ends here

View file

@ -0,0 +1,577 @@
;;; cider-client.el --- A layer of abstraction above low-level nREPL client code. -*- lexical-binding: t -*-
;; Copyright © 2013-2018 Bozhidar Batsov
;;
;; Author: Bozhidar Batsov <bozhidar@batsov.com>
;; 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/>.
;; This file is not part of GNU Emacs.
;;; Commentary:
;; A layer of abstraction above the low-level nREPL client code.
;;; Code:
(require 'spinner)
(require 'nrepl-client)
(require 'cider-connection)
(require 'cider-common)
(require 'cider-util)
(require 'clojure-mode)
(require 'subr-x)
(require 'cider-compat)
(require 'seq)
;;; Eval spinner
(defcustom cider-eval-spinner-type 'progress-bar
"Appearance of the evaluation spinner.
Value is a symbol. The possible values are the symbols in the
`spinner-types' variable."
:type 'symbol
:group 'cider
:package-version '(cider . "0.10.0"))
(defcustom cider-show-eval-spinner t
"When true, show the evaluation spinner in the mode line."
:type 'boolean
:group 'cider
:package-version '(cider . "0.10.0"))
(defcustom cider-eval-spinner-delay 1
"Amount of time, in seconds, after which the evaluation spinner will be shown."
:type 'integer
:group 'cider
:package-version '(cider . "0.10.0"))
(defun cider-spinner-start (buffer)
"Start the evaluation spinner in BUFFER.
Do nothing if `cider-show-eval-spinner' is nil."
(when cider-show-eval-spinner
(with-current-buffer buffer
(spinner-start cider-eval-spinner-type nil
cider-eval-spinner-delay))))
(defun cider-eval-spinner-handler (eval-buffer original-callback)
"Return a response handler to stop the spinner and call ORIGINAL-CALLBACK.
EVAL-BUFFER is the buffer where the spinner was started."
(lambda (response)
;; buffer still exists and
;; we've got status "done" from nrepl
;; stop the spinner
(when (and (buffer-live-p eval-buffer)
(let ((status (nrepl-dict-get response "status")))
(or (member "done" status)
(member "eval-error" status)
(member "error" status))))
(with-current-buffer eval-buffer
(when spinner-current (spinner-stop))))
(funcall original-callback response)))
;;; Evaluation helpers
(defun cider-ns-form-p (form)
"Check if FORM is an ns form."
(string-match-p "^[[:space:]]*\(ns\\([[:space:]]*$\\|[[:space:]]+\\)" form))
(defun cider-ns-from-form (ns-form)
"Get ns substring from NS-FORM."
(when (string-match "^[ \t\n]*\(ns[ \t\n]+\\([^][ \t\n(){}]+\\)" ns-form)
(match-string-no-properties 1 ns-form)))
(defvar-local cider-buffer-ns nil
"Current Clojure namespace of some buffer.
Useful for special buffers (e.g. REPL, doc buffers) that have to keep track
of a namespace. This should never be set in Clojure buffers, as there the
namespace should be extracted from the buffer's ns form.")
(defun cider-current-ns (&optional no-default)
"Return the current ns.
The ns is extracted from the ns form for Clojure buffers and from
`cider-buffer-ns' for all other buffers. If it's missing, use the current
REPL's ns, otherwise fall back to \"user\". When NO-DEFAULT is non-nil, it
will return nil instead of \"user\"."
(or cider-buffer-ns
(clojure-find-ns)
(when-let* ((repl (cider-current-repl)))
(buffer-local-value 'cider-buffer-ns repl))
(if no-default nil "user")))
(defun cider-expected-ns (&optional path)
"Return the namespace string matching PATH, or nil if not found.
PATH is expected to be an absolute file path. If PATH is nil, use the path
to the file backing the current buffer. The command falls back to
`clojure-expected-ns' in the absence of an active nREPL connection."
(if (cider-connected-p)
(let* ((path (or path (file-truename (buffer-file-name))))
(relpath (thread-last (cider-sync-request:classpath)
(seq-map
(lambda (cp)
(when (string-prefix-p cp path)
(substring path (length cp)))))
(seq-filter #'identity)
(seq-sort (lambda (a b)
(< (length a) (length b))))
(car))))
(if relpath
(thread-last (substring relpath 1) ; remove leading /
(file-name-sans-extension)
(replace-regexp-in-string "/" ".")
(replace-regexp-in-string "_" "-"))
(clojure-expected-ns path)))
(clojure-expected-ns path)))
(defun cider-nrepl-op-supported-p (op &optional connection)
"Check whether the CONNECTION supports the nREPL middleware OP."
(nrepl-op-supported-p op (or connection (cider-current-repl))))
(defvar cider-version)
(defun cider-ensure-op-supported (op)
"Check for support of middleware op OP.
Signal an error if it is not supported."
(unless (cider-nrepl-op-supported-p op)
(user-error "`%s' requires the nREPL op \"%s\". Please, install (or update) cider-nrepl %s and restart CIDER" this-command op (upcase cider-version))))
(defun cider-nrepl-send-request (request callback &optional connection)
"Send REQUEST and register response handler CALLBACK.
REQUEST is a pair list of the form (\"op\" \"operation\" \"par1-name\"
\"par1\" ... ).
If CONNECTION is provided dispatch to that connection instead of
the current connection. Return the id of the sent message."
(nrepl-send-request request callback (or connection (cider-current-repl))))
(defun cider-nrepl-send-sync-request (request &optional connection abort-on-input)
"Send REQUEST to the nREPL server synchronously using CONNECTION.
Hold till final \"done\" message has arrived and join all response messages
of the same \"op\" that came along and return the accumulated response.
If ABORT-ON-INPUT is non-nil, the function will return nil
at the first sign of user input, so as not to hang the
interface."
(nrepl-send-sync-request request
(or connection (cider-current-repl))
abort-on-input))
(defun cider-nrepl-send-unhandled-request (request &optional connection)
"Send REQUEST to the nREPL CONNECTION and ignore any responses.
Immediately mark the REQUEST as done. Return the id of the sent message."
(let* ((conn (or connection (cider-current-repl)))
(id (nrepl-send-request request #'ignore conn)))
(with-current-buffer conn
(nrepl--mark-id-completed id))
id))
(defun cider-nrepl-request:eval (input callback &optional ns line column additional-params connection)
"Send the request INPUT and register the CALLBACK as the response handler.
If NS is non-nil, include it in the request. LINE and COLUMN, if non-nil,
define the position of INPUT in its buffer. ADDITIONAL-PARAMS is a plist
to be appended to the request message. CONNECTION is the connection
buffer, defaults to (cider-current-repl)."
(let ((connection (or connection (cider-current-repl))))
(nrepl-request:eval input
(if cider-show-eval-spinner
(cider-eval-spinner-handler connection callback)
callback)
connection
ns line column additional-params)
(cider-spinner-start connection)))
(defun cider-nrepl-sync-request:eval (input &optional connection ns)
"Send the INPUT to the nREPL CONNECTION synchronously.
If NS is non-nil, include it in the eval request."
(nrepl-sync-request:eval input (or connection (cider-current-repl)) ns))
(defcustom cider-pprint-fn 'pprint
"Sets the function to use when pretty-printing evaluation results.
The value must be one of the following symbols:
`pprint' - to use \\=`clojure.pprint/pprint\\=`
`fipp' - to use the Fast Idiomatic Pretty Printer, approximately 5-10x
faster than \\=`clojure.core/pprint\\=` (this is the default)
`puget' - to use Puget, which provides canonical serialization of data on
top of fipp, but at a slight performance cost
Alternatively, can be the namespace-qualified name of a Clojure function of
one argument. If the function cannot be resolved, an exception will be
thrown.
The function is assumed to respect the contract of \\=`clojure.pprint/pprint\\=`
with respect to the bound values of \\=`*print-length*\\=`, \\=`*print-level*\\=`,
\\=`*print-meta*\\=`, and \\=`clojure.pprint/*print-right-margin*\\=`."
:type '(choice (const pprint)
(const fipp)
(const puget)
string)
:group 'cider
:package-version '(cider . "0.11.0"))
(defun cider--pprint-fn ()
"Return the value to send in the pprint-fn slot of messages."
(pcase cider-pprint-fn
(`pprint "clojure.pprint/pprint")
(`fipp "cider.nrepl.middleware.pprint/fipp-pprint")
(`puget "cider.nrepl.middleware.pprint/puget-pprint")
(_ cider-pprint-fn)))
(defun cider--nrepl-pprint-request-plist (right-margin &optional pprint-fn)
"Plist to be appended to an eval request to make it use pprint.
PPRINT-FN is the name of the Clojure function to use.
RIGHT-MARGIN specifies the maximum column-width of the pretty-printed
result, and is included in the request if non-nil."
(nconc `("pprint" "true"
"pprint-fn" ,(or pprint-fn (cider--pprint-fn)))
(and right-margin `("print-right-margin" ,right-margin))))
(defun cider--nrepl-content-type-plist ()
"Plist to be appended to an eval request to make it use content-types."
'("content-type" "true"))
(defun cider-tooling-eval (input callback &optional ns connection)
"Send the request INPUT to CONNECTION and register the CALLBACK.
NS specifies the namespace in which to evaluate the request. Requests
evaluated in the tooling nREPL session don't affect the thread-local
bindings of the primary eval nREPL session (e.g. this is not going to
clobber *1/2/3)."
;; namespace forms are always evaluated in the "user" namespace
(nrepl-request:eval input
callback
(or connection (cider-current-repl))
ns nil nil nil 'tooling))
(defun cider-sync-tooling-eval (input &optional ns connection)
"Send the request INPUT to CONNECTION and evaluate in synchronously.
NS specifies the namespace in which to evaluate the request. Requests
evaluated in the tooling nREPL session don't affect the thread-local
bindings of the primary eval nREPL session (e.g. this is not going to
clobber *1/2/3)."
;; namespace forms are always evaluated in the "user" namespace
(nrepl-sync-request:eval input
(or connection (cider-current-repl))
ns
'tooling))
;; TODO: Add some unit tests and pretty those two functions up.
;; FIXME: Currently that's broken for group-id with multiple segments (e.g. org.clojure/clojure)
(defun cider-classpath-libs ()
"Return a list of all libs on the classpath."
(let ((libs (seq-filter (lambda (cp-entry)
(string-suffix-p ".jar" cp-entry))
(cider-sync-request:classpath)))
(dir-sep (if (string-equal system-type "windows-nt") "\\\\" "/")))
(thread-last libs
(seq-map (lambda (s) (split-string s dir-sep)))
(seq-map #'reverse)
(seq-map (lambda (l) (reverse (seq-take l 4)))))))
(defun cider-library-present-p (lib)
"Check whether LIB is present on the classpath.
The library is a string of the format \"group-id/artifact-id\"."
(let* ((lib (split-string lib "/"))
(group-id (car lib))
(artifact-id (cadr lib)))
(seq-find (lambda (lib)
(let ((g (car lib))
(a (cadr lib)))
(and (equal group-id g) (equal artifact-id a))))
(cider-classpath-libs))))
;;; Interrupt evaluation
(defun cider-interrupt-handler (buffer)
"Create an interrupt response handler for BUFFER."
(nrepl-make-response-handler buffer nil nil nil nil))
(defun cider-interrupt ()
"Interrupt any pending evaluations."
(interactive)
;; FIXME: does this work correctly in cljc files?
(with-current-buffer (cider-current-repl)
(let ((pending-request-ids (cider-util--hash-keys nrepl-pending-requests)))
(dolist (request-id pending-request-ids)
(nrepl-request:interrupt
request-id
(cider-interrupt-handler (current-buffer))
(cider-current-repl))))))
(defun cider-nrepl-eval-session ()
"Return the eval nREPL session id of the current connection."
(with-current-buffer (cider-current-repl)
nrepl-session))
(defun cider-nrepl-tooling-session ()
"Return the tooling nREPL session id of the current connection."
(with-current-buffer (cider-current-repl)
nrepl-tooling-session))
(defun cider--var-choice (var-info)
"Prompt to choose from among multiple VAR-INFO candidates, if required.
This is needed only when the symbol queried is an unqualified host platform
method, and multiple classes have a so-named member. If VAR-INFO does not
contain a `candidates' key, it is returned as is."
(let ((candidates (nrepl-dict-get var-info "candidates")))
(if candidates
(let* ((classes (nrepl-dict-keys candidates))
(choice (completing-read "Member in class: " classes nil t))
(info (nrepl-dict-get candidates choice)))
info)
var-info)))
(defun cider-var-info (var &optional all)
"Return VAR's info as an alist with list cdrs.
When multiple matching vars are returned you'll be prompted to select one,
unless ALL is truthy."
(when (and var (not (string= var "")))
(let ((var-info (cider-sync-request:info var)))
(if all var-info (cider--var-choice var-info)))))
(defun cider-member-info (class member)
"Return the CLASS MEMBER's info as an alist with list cdrs."
(when (and class member)
(cider-sync-request:info nil class member)))
;;; Requests
(declare-function cider-load-file-handler "cider-eval")
(defun cider-request:load-file (file-contents file-path file-name &optional connection callback)
"Perform the nREPL \"load-file\" op.
FILE-CONTENTS, FILE-PATH and FILE-NAME are details of the file to be
loaded. If CONNECTION is nil, use `cider-current-repl'. If CALLBACK
is nil, use `cider-load-file-handler'."
(cider-nrepl-send-request `("op" "load-file"
"file" ,file-contents
"file-path" ,file-path
"file-name" ,file-name)
(or callback
(cider-load-file-handler (current-buffer)))
connection))
;;; Sync Requests
(defcustom cider-filtered-namespaces-regexps
'("^cider.nrepl" "^refactor-nrepl" "^clojure.tools.nrepl")
"List of regexps used to filter out some vars/symbols/namespaces.
When nil, nothing is filtered out. Otherwise, all namespaces matching any
regexp from this list are dropped out of the \"ns-list\" op. Also,
\"apropos\" won't include vars from such namespaces. This list is passed
on to the nREPL middleware without any pre-processing. So the regexps have
to be in Clojure format (with twice the number of backslashes) and not
Emacs Lisp."
:type '(repeat string)
:safe #'listp
:group 'cider
:package-version '(cider . "0.13.0"))
(defun cider-sync-request:apropos (query &optional search-ns docs-p privates-p case-sensitive-p)
"Send \"apropos\" request for regexp QUERY.
Optional arguments include SEARCH-NS, DOCS-P, PRIVATES-P, CASE-SENSITIVE-P."
(let* ((query (replace-regexp-in-string "[ \t]+" ".+" query))
(response (cider-nrepl-send-sync-request
`("op" "apropos"
"ns" ,(cider-current-ns)
"query" ,query
,@(when search-ns `("search-ns" ,search-ns))
,@(when docs-p '("docs?" "t"))
,@(when privates-p '("privates?" "t"))
,@(when case-sensitive-p '("case-sensitive?" "t"))
"filter-regexps" ,cider-filtered-namespaces-regexps))))
(if (member "apropos-regexp-error" (nrepl-dict-get response "status"))
(user-error "Invalid regexp: %s" (nrepl-dict-get response "error-msg"))
(nrepl-dict-get response "apropos-matches"))))
(defun cider-sync-request:classpath ()
"Return a list of classpath entries."
(cider-ensure-op-supported "classpath")
(thread-first '("op" "classpath")
(cider-nrepl-send-sync-request)
(nrepl-dict-get "classpath")))
(defun cider-sync-request:complete (str context)
"Return a list of completions for STR using nREPL's \"complete\" op.
CONTEXT represents a completion context for compliment."
(when-let* ((dict (thread-first `("op" "complete"
"ns" ,(cider-current-ns)
"symbol" ,str
"context" ,context)
(cider-nrepl-send-sync-request nil 'abort-on-input))))
(nrepl-dict-get dict "completions")))
(defun cider-sync-request:complete-flush-caches ()
"Send \"complete-flush-caches\" op to flush Compliment's caches."
(cider-nrepl-send-sync-request (list "op" "complete-flush-caches"
"session" (cider-nrepl-eval-session))
'abort-on-input))
(defun cider-sync-request:info (symbol &optional class member)
"Send \"info\" op with parameters SYMBOL or CLASS and MEMBER."
(let ((var-info (thread-first `("op" "info"
"ns" ,(cider-current-ns)
,@(when symbol `("symbol" ,symbol))
,@(when class `("class" ,class))
,@(when member `("member" ,member)))
(cider-nrepl-send-sync-request))))
(if (member "no-info" (nrepl-dict-get var-info "status"))
nil
var-info)))
(defun cider-sync-request:eldoc (symbol &optional class member)
"Send \"eldoc\" op with parameters SYMBOL or CLASS and MEMBER."
(when-let* ((eldoc (thread-first `("op" "eldoc"
"ns" ,(cider-current-ns)
,@(when symbol `("symbol" ,symbol))
,@(when class `("class" ,class))
,@(when member `("member" ,member)))
(cider-nrepl-send-sync-request nil 'abort-on-input))))
(if (member "no-eldoc" (nrepl-dict-get eldoc "status"))
nil
eldoc)))
(defun cider-sync-request:eldoc-datomic-query (symbol)
"Send \"eldoc-datomic-query\" op with parameter SYMBOL."
(when-let* ((eldoc (thread-first `("op" "eldoc-datomic-query"
"ns" ,(cider-current-ns)
,@(when symbol `("symbol" ,symbol)))
(cider-nrepl-send-sync-request nil 'abort-on-input))))
(if (member "no-eldoc" (nrepl-dict-get eldoc "status"))
nil
eldoc)))
(defun cider-sync-request:spec-list (&optional filter-regex)
"Get a list of the available specs in the registry.
Optional argument FILTER-REGEX filters specs. By default, all specs are
returned."
(setq filter-regex (or filter-regex ""))
(thread-first `("op" "spec-list"
"filter-regex" ,filter-regex)
(cider-nrepl-send-sync-request)
(nrepl-dict-get "spec-list")))
(defun cider-sync-request:spec-form (spec)
"Get SPEC's form from registry."
(thread-first `("op" "spec-form"
"spec-name" ,spec)
(cider-nrepl-send-sync-request)
(nrepl-dict-get "spec-form")))
(defun cider-sync-request:spec-example (spec)
"Get an example for SPEC."
(thread-first `("op" "spec-example"
"spec-name" ,spec)
(cider-nrepl-send-sync-request)
(nrepl-dict-get "spec-example")))
(defun cider-sync-request:ns-list ()
"Get a list of the available namespaces."
(thread-first `("op" "ns-list"
"filter-regexps" ,cider-filtered-namespaces-regexps)
(cider-nrepl-send-sync-request)
(nrepl-dict-get "ns-list")))
(defun cider-sync-request:ns-vars (ns)
"Get a list of the vars in NS."
(thread-first `("op" "ns-vars"
"ns" ,ns)
(cider-nrepl-send-sync-request)
(nrepl-dict-get "ns-vars")))
(defun cider-sync-request:ns-path (ns)
"Get the path to the file containing NS."
(thread-first `("op" "ns-path"
"ns" ,ns)
(cider-nrepl-send-sync-request)
(nrepl-dict-get "path")))
(defun cider-sync-request:ns-vars-with-meta (ns)
"Get a map of the vars in NS to its metadata information."
(thread-first `("op" "ns-vars-with-meta"
"ns" ,ns)
(cider-nrepl-send-sync-request)
(nrepl-dict-get "ns-vars-with-meta")))
(defun cider-sync-request:ns-load-all ()
"Load all project namespaces."
(thread-first '("op" "ns-load-all")
(cider-nrepl-send-sync-request)
(nrepl-dict-get "loaded-ns")))
(defun cider-sync-request:resource (name)
"Perform nREPL \"resource\" op with resource name NAME."
(thread-first `("op" "resource"
"name" ,name)
(cider-nrepl-send-sync-request)
(nrepl-dict-get "resource-path")))
(defun cider-sync-request:resources-list ()
"Return a list of all resources on the classpath.
The result entries are relative to the classpath."
(when-let* ((resources (thread-first '("op" "resources-list")
(cider-nrepl-send-sync-request)
(nrepl-dict-get "resources-list"))))
(seq-map (lambda (resource) (nrepl-dict-get resource "relpath")) resources)))
(defun cider-sync-request:format-code (code)
"Perform nREPL \"format-code\" op with CODE."
(thread-first `("op" "format-code"
"code" ,code)
(cider-nrepl-send-sync-request)
(nrepl-dict-get "formatted-code")))
(defun cider-sync-request:format-edn (edn right-margin)
"Perform \"format-edn\" op with EDN and RIGHT-MARGIN."
(let* ((response (thread-first `("op" "format-edn"
"edn" ,edn)
(append (cider--nrepl-pprint-request-plist right-margin))
(cider-nrepl-send-sync-request)))
(err (nrepl-dict-get response "err")))
(when err
;; err will be a stacktrace with a first line that looks like:
;; "clojure.lang.ExceptionInfo: Unmatched delimiter ]"
(error (car (split-string err "\n"))))
(nrepl-dict-get response "formatted-edn")))
;;; Dealing with input
;; TODO: Replace this with some nil handler.
(defun cider-stdin-handler (&optional _buffer)
"Make a stdin response handler for _BUFFER."
(nrepl-make-response-handler (current-buffer)
(lambda (_buffer _value))
(lambda (_buffer _out))
(lambda (_buffer _err))
nil))
(defun cider-need-input (buffer)
"Handle an need-input request from BUFFER."
(with-current-buffer buffer
(let ((map (make-sparse-keymap)))
(set-keymap-parent map minibuffer-local-map)
(define-key map (kbd "C-c C-c") 'abort-recursive-edit)
(let ((stdin (condition-case nil
(concat (read-from-minibuffer "Stdin: " nil map) "\n")
(quit nil))))
(nrepl-request:stdin stdin
(cider-stdin-handler buffer)
(cider-current-repl))))))
(provide 'cider-client)
;;; cider-client.el ends here

View file

@ -0,0 +1,375 @@
;;; cider-common.el --- Common use functions -*- lexical-binding: t; -*-
;; Copyright © 2015-2018 Artur Malabarba
;; Author: Artur Malabarba <bruce.connor.am@gmail.com>
;; 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/>.
;;; Commentary:
;; Common functions that are useful in both Clojure buffers and REPL
;; buffers.
;;; Code:
(require 'subr-x)
(require 'cider-compat)
(require 'nrepl-dict)
(require 'cider-util)
(require 'etags) ; for find-tags-marker-ring
(require 'tramp)
(defcustom cider-prompt-for-symbol t
"Controls when to prompt for symbol when a command requires one.
When non-nil, always prompt, and use the symbol at point as the default
value at the prompt.
When nil, attempt to use the symbol at point for the command, and only
prompt if that throws an error."
:type '(choice (const :tag "always" t)
(const :tag "dwim" nil))
:group 'cider
:package-version '(cider . "0.9.0"))
(defcustom cider-special-mode-truncate-lines t
"If non-nil, contents of CIDER's special buffers will be line-truncated.
Should be set before loading CIDER."
:type 'boolean
:group 'cider
:package-version '(cider . "0.15.0"))
(defun cider--should-prompt-for-symbol (&optional invert)
"Return the value of the variable `cider-prompt-for-symbol'.
Optionally invert the value, if INVERT is truthy."
(if invert (not cider-prompt-for-symbol) cider-prompt-for-symbol))
(defun cider-prompt-for-symbol-function (&optional invert)
"Prompt for symbol if funcall `cider--should-prompt-for-symbol' is truthy.
Otherwise attempt to use the symbol at point for the command, and only
prompt if that throws an error.
INVERT is used to invert the semantics of the function `cider--should-prompt-for-symbol'."
(if (cider--should-prompt-for-symbol invert)
#'cider-read-symbol-name
#'cider-try-symbol-at-point))
(defun cider--kw-to-symbol (kw)
"Convert the keyword KW to a symbol."
(when kw
(replace-regexp-in-string "\\`:+" "" kw)))
;;; Minibuffer
(defvar cider-minibuffer-history '()
"History list of expressions read from the minibuffer.")
(defvar cider-minibuffer-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map minibuffer-local-map)
(define-key map (kbd "TAB") #'complete-symbol)
(define-key map (kbd "M-TAB") #'complete-symbol)
map)
"Minibuffer keymap used for reading Clojure expressions.")
(declare-function cider-complete-at-point "cider-completion")
(declare-function cider-eldoc "cider-eldoc")
(defun cider-read-from-minibuffer (prompt &optional value)
"Read a string from the minibuffer, prompting with PROMPT.
If VALUE is non-nil, it is inserted into the minibuffer as initial-input.
PROMPT need not end with \": \". If it doesn't, VALUE is displayed on the
prompt as a default value (used if the user doesn't type anything) and is
not used as initial input (input is left empty)."
(minibuffer-with-setup-hook
(lambda ()
(set-syntax-table clojure-mode-syntax-table)
(add-hook 'completion-at-point-functions
#'cider-complete-at-point nil t)
(setq-local eldoc-documentation-function #'cider-eldoc)
(run-hooks 'eval-expression-minibuffer-setup-hook))
(let* ((has-colon (string-match ": \\'" prompt))
(input (read-from-minibuffer (cond
(has-colon prompt)
(value (format "%s (default %s): " prompt value))
(t (format "%s: " prompt)))
(when has-colon value) ; initial-input
cider-minibuffer-map nil
'cider-minibuffer-history
(unless has-colon value)))) ; default-value
(if (and (equal input "") value (not has-colon))
value
input))))
(defun cider-read-symbol-name (prompt callback)
"Read a symbol name using PROMPT with a default of the one at point.
Use CALLBACK as the completing read var callback."
(funcall callback (cider-read-from-minibuffer
prompt
;; if the thing at point is a keyword we treat it as symbol
(cider--kw-to-symbol (cider-symbol-at-point 'look-back)))))
(defun cider-try-symbol-at-point (prompt callback)
"Call CALLBACK with symbol at point.
On failure, read a symbol name using PROMPT and call CALLBACK with that."
(condition-case nil (funcall callback (cider--kw-to-symbol (cider-symbol-at-point 'look-back)))
('error (funcall callback (cider-read-from-minibuffer prompt)))))
(declare-function cider-mode "cider-mode")
(defun cider-jump-to (buffer &optional pos other-window)
"Push current point onto marker ring, and jump to BUFFER and POS.
POS can be either a number, a cons, or a symbol.
If a number, it is the character position (the point).
If a cons, it specifies the position as (LINE . COLUMN). COLUMN can be nil.
If a symbol, `cider-jump-to' searches for something that looks like the
symbol's definition in the file.
If OTHER-WINDOW is non-nil don't reuse current window."
(with-no-warnings
(ring-insert find-tag-marker-ring (point-marker)))
(if other-window
(pop-to-buffer buffer)
;; like switch-to-buffer, but reuse existing window if BUFFER is visible
(pop-to-buffer buffer '((display-buffer-reuse-window display-buffer-same-window))))
(with-current-buffer buffer
(widen)
(goto-char (point-min))
(cider-mode +1)
(cond
;; Line-column specification.
((consp pos)
(forward-line (1- (or (car pos) 1)))
(if (cdr pos)
(move-to-column (cdr pos))
(back-to-indentation)))
;; Point specification.
((numberp pos)
(goto-char pos))
;; Symbol or string.
(pos
;; Try to find (def full-name ...).
(if (or (save-excursion
(search-forward-regexp (format "(def.*\\s-\\(%s\\)" (regexp-quote pos))
nil 'noerror))
(let ((name (replace-regexp-in-string ".*/" "" pos)))
;; Try to find (def name ...).
(or (save-excursion
(search-forward-regexp (format "(def.*\\s-\\(%s\\)" (regexp-quote name))
nil 'noerror))
;; Last resort, just find the first occurrence of `name'.
(save-excursion
(search-forward name nil 'noerror)))))
(goto-char (match-beginning 0))
(message "Can't find %s in %s" pos (buffer-file-name))))
(t nil))))
(defun cider--find-buffer-for-file (file)
"Return a buffer visiting FILE.
If FILE is a temp buffer name, return that buffer."
(if (string-prefix-p "*" file)
file
(and file
(not (cider--tooling-file-p file))
(cider-find-file file))))
(defun cider--jump-to-loc-from-info (info &optional other-window)
"Jump to location give by INFO.
INFO object is returned by `cider-var-info' or `cider-member-info'.
OTHER-WINDOW is passed to `cider-jump-to'."
(let* ((line (nrepl-dict-get info "line"))
(file (nrepl-dict-get info "file"))
(name (nrepl-dict-get info "name"))
;; the filename might actually be a REPL buffer name
(buffer (cider--find-buffer-for-file file)))
(if buffer
(cider-jump-to buffer (if line (cons line nil) name) other-window)
(error "No source location"))))
(declare-function url-filename "url-parse" (cl-x) t)
(defun cider--url-to-file (url)
"Return the filename from the resource URL.
Uses `url-generic-parse-url' to parse the url. The filename is extracted and
then url decoded. If the decoded filename has a Windows device letter followed
by a colon immediately after the leading '/' then the leading '/' is dropped to
create a valid path."
(let ((filename (url-unhex-string (url-filename (url-generic-parse-url url)))))
(if (string-match "^/\\([a-zA-Z]:/.*\\)" filename)
(match-string 1 filename)
filename)))
(defun cider-make-tramp-prefix (method user host)
"Constructs a Tramp file prefix from METHOD, USER, HOST.
It originated from Tramp's `tramp-make-tramp-file-name'. The original be
forced to make full file name with `with-parsed-tramp-file-name', not providing
prefix only option."
(concat tramp-prefix-format
(unless (zerop (length method))
(concat method tramp-postfix-method-format))
(unless (zerop (length user))
(concat user tramp-postfix-user-format))
(when host
(if (string-match tramp-ipv6-regexp host)
(concat tramp-prefix-ipv6-format host tramp-postfix-ipv6-format)
host))
tramp-postfix-host-format))
(defun cider-tramp-prefix (&optional buffer)
"Use the filename for BUFFER to determine a tramp prefix.
Defaults to the current buffer. Return the tramp prefix, or nil
if BUFFER is local."
(let* ((buffer (or buffer (current-buffer)))
(name (or (buffer-file-name buffer)
(with-current-buffer buffer
default-directory))))
(when (tramp-tramp-file-p name)
(with-parsed-tramp-file-name name v
(with-no-warnings
(cider-make-tramp-prefix v-method v-user v-host))))))
(defun cider--client-tramp-filename (name &optional buffer)
"Return the tramp filename for path NAME relative to BUFFER.
If BUFFER has a tramp prefix, it will be added as a prefix to NAME.
If the resulting path is an existing tramp file, it returns the path,
otherwise, nil."
(let* ((buffer (or buffer (current-buffer)))
(name (replace-regexp-in-string "^file:" "" name))
(name (concat (cider-tramp-prefix buffer) name)))
(if (tramp-handle-file-exists-p name)
name)))
(defun cider--server-filename (name)
"Return the nREPL server-relative filename for NAME."
(if (tramp-tramp-file-p name)
(with-parsed-tramp-file-name name nil
localname)
name))
(defvar cider-from-nrepl-filename-function
(with-no-warnings
(if (eq system-type 'cygwin)
#'cygwin-convert-file-name-from-windows
#'identity))
"Function to translate nREPL namestrings to Emacs filenames.")
(defcustom cider-prefer-local-resources nil
"Prefer local resources to remote (tramp) ones when both are available."
:type 'boolean
:group 'cider)
(defun cider--file-path (path)
"Return PATH's local or tramp path using `cider-prefer-local-resources'.
If no local or remote file exists, return nil."
(let* ((local-path (funcall cider-from-nrepl-filename-function path))
(tramp-path (and local-path (cider--client-tramp-filename local-path))))
(cond ((equal local-path "") "")
((and cider-prefer-local-resources (file-exists-p local-path))
local-path)
((and tramp-path (file-exists-p tramp-path))
tramp-path)
((and local-path (file-exists-p local-path))
local-path))))
(declare-function archive-extract "arc-mode")
(declare-function archive-zip-extract "arc-mode")
(defun cider-find-file (url)
"Return a buffer visiting the file URL if it exists, or nil otherwise.
If URL has a scheme prefix, it must represent a fully-qualified file path
or an entry within a zip/jar archive. If URL doesn't contain a scheme
prefix and is an absolute path, it is treated as such. Finally, if URL is
relative, it is expanded within each of the open Clojure buffers till an
existing file ending with URL has been found."
(require 'arc-mode)
(cond ((string-match "^file:\\(.+\\)" url)
(when-let* ((file (cider--url-to-file (match-string 1 url)))
(path (cider--file-path file)))
(find-file-noselect path)))
((string-match "^\\(jar\\|zip\\):\\(file:.+\\)!/\\(.+\\)" url)
(when-let* ((entry (match-string 3 url))
(file (cider--url-to-file (match-string 2 url)))
(path (cider--file-path file))
;; It is used for targeting useless intermediate buffer.
;; That buffer is made by (find-file path) below.
;; It has the name which is the last part of the path.
(trash (replace-regexp-in-string "^/.+/" "" path))
(name (format "%s:%s" path entry)))
(or (find-buffer-visiting name)
(if (tramp-tramp-file-p path)
(progn
;; Use emacs built in archiving.
;; This makes a list of files in archived Zip or Jar.
;; That list buffer is useless after jumping to the
;; buffer which has the real definition.
;; It'll be removed by (kill-buffer trash) below.
(find-file path)
(goto-char (point-min))
;; Make sure the file path is followed by a newline to
;; prevent eg. clj matching cljs.
(search-forward (concat entry "\n"))
;; moves up to matching line
(forward-line -1)
(archive-extract)
;; Remove useless buffer made by (find-file path) above.
(kill-buffer trash)
(current-buffer))
;; Use external zip program to just extract the single file
(with-current-buffer (generate-new-buffer
(file-name-nondirectory entry))
(archive-zip-extract path entry)
(set-visited-file-name name)
(setq-local default-directory (file-name-directory path))
(setq-local buffer-read-only t)
(set-buffer-modified-p nil)
(set-auto-mode)
(current-buffer))))))
(t (if-let* ((path (cider--file-path url)))
(find-file-noselect path)
(unless (file-name-absolute-p url)
(let ((cider-buffers (cider-util--clojure-buffers))
(url (file-name-nondirectory url)))
(or (cl-loop for bf in cider-buffers
for path = (with-current-buffer bf
(expand-file-name url))
if (and path (file-exists-p path))
return (find-file-noselect path))
(cl-loop for bf in cider-buffers
if (string= (buffer-name bf) url)
return bf))))))))
(defun cider--open-other-window-p (arg)
"Test prefix value ARG to see if it indicates displaying results in other window."
(let ((narg (prefix-numeric-value arg)))
(pcase narg
(-1 t) ; -
(16 t) ; empty empty
(_ nil))))
(defun cider-abbreviate-ns (namespace)
"Return a string that abbreviates NAMESPACE."
(when namespace
(let* ((names (reverse (split-string namespace "\\.")))
(lastname (car names)))
(concat (mapconcat (lambda (s) (concat (substring s 0 1) "."))
(reverse (cdr names))
"")
lastname))))
(defun cider-last-ns-segment (namespace)
"Return the last segment of NAMESPACE."
(when namespace
(car (reverse (split-string namespace "\\.")))))
(provide 'cider-common)
;;; cider-common.el ends here

View file

@ -0,0 +1,54 @@
;;; cider-compat.el --- Functions from newer Emacs versions for compatibility -*- lexical-binding: t -*-
;; Copyright © 2012-2013 Tim King, Phil Hagelberg, Bozhidar Batsov
;; Copyright © 2013-2018 Bozhidar Batsov, Artur Malabarba and CIDER contributors
;;
;; 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/>.
;; This file is not part of GNU Emacs.
;;; Commentary:
;; Everything here was copied from subr-x for compatibility with
;; Emacs 25.1.
;;; Code:
(eval-and-compile
(unless (fboundp 'if-let*)
(defmacro if-let* (bindings then &rest else)
"Process BINDINGS and if all values are non-nil eval THEN, else ELSE.
Argument BINDINGS is a list of tuples whose car is a symbol to be
bound and (optionally) used in THEN, and its cadr is a sexp to be
evalled to set symbol's value."
(declare (indent 2)
(debug ([&or (&rest (symbolp form)) (symbolp form)] form body)))
`(let* ,(internal--build-bindings bindings)
(if ,(car (internal--listify (car (last bindings))))
,then
,@else))))
(unless (fboundp 'when-let*)
(defmacro when-let* (bindings &rest body)
"Process BINDINGS and if all values are non-nil eval BODY.
Argument BINDINGS is a list of tuples whose car is a symbol to be
bound and (optionally) used in BODY, and its cadr is a sexp to be
evalled to set symbol's value."
(declare (indent 1) (debug if-let*))
`(if-let* ,bindings ,(macroexp-progn body)))))
(provide 'cider-compat)
;;; cider-compat.el ends here

View file

@ -0,0 +1,253 @@
;;; cider-completion.el --- Smart REPL-powered code completion -*- lexical-binding: t -*-
;; Copyright © 2013-2018 Bozhidar Batsov, Artur Malabarba and CIDER contributors
;;
;; Author: Bozhidar Batsov <bozhidar@batsov.com>
;; Artur Malabarba <bruce.connor.am@gmail.com>
;; 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/>.
;; This file is not part of GNU Emacs.
;;; Commentary:
;; Smart REPL-powered code completion and integration with company-mode.
;;; Code:
(require 'subr-x)
(require 'thingatpt)
(require 'cider-client)
(require 'cider-common)
(require 'cider-eldoc)
(require 'nrepl-dict)
(defcustom cider-completion-use-context t
"When true, uses context at point to improve completion suggestions."
:type 'boolean
:group 'cider
:package-version '(cider . "0.7.0"))
(defcustom cider-annotate-completion-candidates t
"When true, annotate completion candidates with some extra information."
:type 'boolean
:group 'cider
:package-version '(cider . "0.8.0"))
(defcustom cider-annotate-completion-function
#'cider-default-annotate-completion-function
"Controls how the annotations for completion candidates are formatted.
Must be a function that takes two arguments: the abbreviation of the
candidate type according to `cider-completion-annotations-alist' and the
candidate's namespace."
:type 'function
:group 'cider
:package-version '(cider . "0.9.0"))
(defcustom cider-completion-annotations-alist
'(("class" "c")
("field" "fi")
("function" "f")
("import" "i")
("keyword" "k")
("local" "l")
("macro" "m")
("method" "me")
("namespace" "n")
("protocol" "p")
("protocol-function" "pf")
("record" "r")
("special-form" "s")
("static-field" "sf")
("static-method" "sm")
("type" "t")
("var" "v"))
"Controls the abbreviations used when annotating completion candidates.
Must be a list of elements with the form (TYPE . ABBREVIATION), where TYPE
is a possible value of the candidate's type returned from the completion
backend, and ABBREVIATION is a short form of that type."
:type '(alist :key-type string :value-type string)
:group 'cider
:package-version '(cider . "0.9.0"))
(defcustom cider-completion-annotations-include-ns 'unqualified
"Controls passing of namespaces to `cider-annotate-completion-function'.
When set to 'always, the candidate's namespace will always be passed if it
is available. When set to 'unqualified, the namespace will only be passed
if the candidate is not namespace-qualified."
:type '(choice (const always)
(const unqualified)
(const :tag "never" nil))
:group 'cider
:package-version '(cider . "0.9.0"))
(defvar cider-completion-last-context nil)
(defun cider-completion-symbol-start-pos ()
"Find the starting position of the symbol at point, unless inside a string."
(let ((sap (symbol-at-point)))
(when (and sap (not (nth 3 (syntax-ppss))))
(car (bounds-of-thing-at-point 'symbol)))))
(defun cider-completion-get-context-at-point ()
"Extract the context at point.
If point is not inside the list, returns nil; otherwise return \"top-level\"
form, with symbol at point replaced by __prefix__."
(when (save-excursion
(condition-case _
(progn
(up-list)
(check-parens)
t)
(scan-error nil)
(user-error nil)))
(save-excursion
(let* ((pref-end (point))
(pref-start (cider-completion-symbol-start-pos))
(context (cider-defun-at-point))
(_ (beginning-of-defun))
(expr-start (point)))
(concat (when pref-start (substring context 0 (- pref-start expr-start)))
"__prefix__"
(substring context (- pref-end expr-start)))))))
(defun cider-completion-get-context ()
"Extract context depending on `cider-completion-use-context' and major mode."
(let ((context (if (and cider-completion-use-context
;; Important because `beginning-of-defun' and
;; `ending-of-defun' work incorrectly in the REPL
;; buffer, so context extraction fails there.
(derived-mode-p 'clojure-mode))
(or (cider-completion-get-context-at-point)
"nil")
"nil")))
(if (string= cider-completion-last-context context)
":same"
(setq cider-completion-last-context context)
context)))
(defun cider-completion--parse-candidate-map (candidate-map)
"Get \"candidate\" from CANDIDATE-MAP.
Put type and ns properties on the candidate"
(let ((candidate (nrepl-dict-get candidate-map "candidate"))
(type (nrepl-dict-get candidate-map "type"))
(ns (nrepl-dict-get candidate-map "ns")))
(put-text-property 0 1 'type type candidate)
(put-text-property 0 1 'ns ns candidate)
candidate))
(defun cider-complete (str)
"Complete STR with context at point."
(let* ((context (cider-completion-get-context))
(candidates (cider-sync-request:complete str context)))
(mapcar #'cider-completion--parse-candidate-map candidates)))
(defun cider-completion--get-candidate-type (symbol)
"Get candidate type for SYMBOL."
(let ((type (get-text-property 0 'type symbol)))
(or (cadr (assoc type cider-completion-annotations-alist))
type)))
(defun cider-completion--get-candidate-ns (symbol)
"Get candidate ns for SYMBOL."
(when (or (eq 'always cider-completion-annotations-include-ns)
(and (eq 'unqualified cider-completion-annotations-include-ns)
(not (cider-namespace-qualified-p symbol))))
(get-text-property 0 'ns symbol)))
(defun cider-default-annotate-completion-function (type ns)
"Get completion function based on TYPE and NS."
(concat (when ns (format " (%s)" ns))
(when type (format " <%s>" type))))
(defun cider-annotate-symbol (symbol)
"Return a string suitable for annotating SYMBOL.
If SYMBOL has a text property `type` whose value is recognised, its
abbreviation according to `cider-completion-annotations-alist' will be
used. If `type` is present but not recognised, its value will be used
unaltered. If SYMBOL has a text property `ns`, then its value will be used
according to `cider-completion-annotations-include-ns'. The formatting is
performed by `cider-annotate-completion-function'."
(when cider-annotate-completion-candidates
(let* ((type (cider-completion--get-candidate-type symbol))
(ns (cider-completion--get-candidate-ns symbol)))
(funcall cider-annotate-completion-function type ns))))
(defun cider-complete-at-point ()
"Complete the symbol at point."
(when-let* ((bounds (bounds-of-thing-at-point 'symbol)))
(when (and (cider-connected-p)
(not (or (cider-in-string-p) (cider-in-comment-p))))
(list (car bounds) (cdr bounds)
(completion-table-dynamic #'cider-complete)
:annotation-function #'cider-annotate-symbol
:company-doc-buffer #'cider-create-doc-buffer
:company-location #'cider-company-location
:company-docsig #'cider-company-docsig))))
(defun cider-completion-flush-caches ()
"Force Compliment to refill its caches.
This command should be used if Compliment fails to pick up new classnames
and methods from dependencies that were loaded dynamically after the REPL
has started."
(interactive)
(cider-sync-request:complete-flush-caches))
(defun cider-company-location (var)
"Open VAR's definition in a buffer.
Returns the cons of the buffer itself and the location of VAR's definition
in the buffer."
(when-let* ((info (cider-var-info var))
(file (nrepl-dict-get info "file"))
(line (nrepl-dict-get info "line"))
(buffer (cider-find-file file)))
(with-current-buffer buffer
(save-excursion
(goto-char (point-min))
(forward-line (1- line))
(cons buffer (point))))))
(defun cider-company-docsig (thing)
"Return signature for THING."
(let* ((eldoc-info (cider-eldoc-info thing))
(ns (lax-plist-get eldoc-info "ns"))
(symbol (lax-plist-get eldoc-info "symbol"))
(arglists (lax-plist-get eldoc-info "arglists")))
(when eldoc-info
(format "%s: %s"
(cider-eldoc-format-thing ns symbol thing
(cider-eldoc-thing-type eldoc-info))
(cider-eldoc-format-arglist arglists 0)))))
;; Fuzzy completion for company-mode
(defun cider-company-unfiltered-candidates (string &rest _)
"Return CIDER completion candidates for STRING as is, unfiltered."
(cider-complete string))
(add-to-list 'completion-styles-alist
'(cider
cider-company-unfiltered-candidates
cider-company-unfiltered-candidates
"CIDER backend-driven completion style."))
(defun cider-company-enable-fuzzy-completion ()
"Enable backend-driven fuzzy completion in the current buffer."
(setq-local completion-styles '(cider)))
(provide 'cider-completion)
;;; cider-completion.el ends here

View file

@ -0,0 +1,646 @@
;;; cider-connection.el --- Connection and session life-cycle management for CIDER -*- lexical-binding: t -*-
;;
;; Copyright © 2018 Artur Malabarba, Bozhidar Batsov, Vitalie Spinu and CIDER contributors
;;
;; Author: Artur Malabarba <bruce.connor.am@gmail.com>
;; Bozhidar Batsov <bozhidar@batsov.com>
;; Vitalie Spinu <spinuvit@gmail.com>
;;
;; Keywords: languages, clojure, cider
;;
;; 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/>.
;;
;; This file is not part of GNU Emacs.
;;
;;
;;; Commentary:
;;
;;
;;; Code:
(require 'nrepl-client)
(require 'cl-lib)
(require 'sesman)
(defcustom cider-connection-message-fn #'cider-random-words-of-inspiration
"The function to use to generate the message displayed on connect.
When set to nil no additional message will be displayed. A good
alternative to the default is `cider-random-tip'."
:type 'function
:group 'cider
:package-version '(cider . "0.11.0"))
(defcustom cider-redirect-server-output-to-repl t
"Controls whether nREPL server output would be redirected to the REPL.
When non-nil the output would end up in both the nrepl-server buffer (when
available) and the matching REPL buffer."
:type 'boolean
:group 'cider
:safe #'booleanp
:package-version '(cider . "0.17.0"))
(defcustom cider-auto-mode t
"When non-nil, automatically enable cider mode for all Clojure buffers."
:type 'boolean
:group 'cider
:safe #'booleanp
:package-version '(cider . "0.9.0"))
(defconst cider-required-nrepl-version "0.2.12"
"The minimum nREPL version that's known to work properly with CIDER.")
;;; Connect
(defun cider-nrepl-connect (params)
"Start nrepl client and create the REPL.
PARAMS is a plist containing :host, :port, :server and other parameters for
`cider-repl-create'."
(process-buffer
(nrepl-start-client-process
(plist-get params :host)
(plist-get params :port)
(plist-get params :server)
(lambda (_)
(cider-repl-create params)))))
(defun cider-connected-p ()
"Return t if CIDER is currently connected, nil otherwise."
(process-live-p (get-buffer-process (cider-current-repl))))
(defun cider-ensure-connected ()
"Ensure there is a linked CIDER session."
(sesman-ensure-session 'CIDER))
(defun cider--gather-connect-params (params proc-buffer)
"Gather all relevant connection parameters into PARAMS plist.
PROC-BUFFER is either server or client buffer."
(with-current-buffer proc-buffer
(unless nrepl-endpoint
(error "This is not a REPL or SERVER buffer; is there an active REPL?"))
(let ((server-buf (if (nrepl-server-p proc-buffer)
proc-buffer
nrepl-server-buffer)))
(cl-loop for l on nrepl-endpoint by #'cddr
do (setq params (plist-put params (car l) (cadr l))))
(setq params (thread-first params
(plist-put :project-dir nrepl-project-dir)))
(when (buffer-live-p server-buf)
(setq params (thread-first params
(plist-put :server (get-buffer-process server-buf))
(plist-put :server-command nrepl-server-command))))
;; repl-specific parameters (do not pollute server params!)
(when (nrepl-server-p proc-buffer)
(setq params (thread-first params
(plist-put :repl-type cider-repl-type)
(plist-put :repl-init-function cider-repl-init-function))))
params)))
(defun cider--close-buffer (buffer)
"Close the BUFFER and kill its associated process (if any)."
(when (buffer-live-p buffer)
(when-let* ((proc (get-buffer-process buffer)))
(when (process-live-p proc)
(delete-process proc)))
(kill-buffer buffer)))
(declare-function cider-repl-emit-interactive-stderr "cider-repl")
(defun cider--close-connection (repl &optional no-kill)
"Close connection associated with REPL.
When NO-KILL is non-nil stop the connection but don't kill the REPL
buffer."
(when (buffer-live-p repl)
(with-current-buffer repl
(when spinner-current (spinner-stop))
(when nrepl-tunnel-buffer
(cider--close-buffer nrepl-tunnel-buffer))
(when no-kill
;; inform sentinel not to kill the server, if any
(thread-first (get-buffer-process repl)
(process-plist)
(plist-put :no-server-kill t))))
(let ((proc (get-buffer-process repl)))
(when (and (process-live-p proc)
(or (not nrepl-server-buffer)
;; Sync request will hang if the server is dead.
(process-live-p (get-buffer-process nrepl-server-buffer))))
(nrepl-sync-request:close repl)
(delete-process proc)))
(when-let* ((messages-buffer (and nrepl-log-messages
(nrepl-messages-buffer repl))))
(kill-buffer messages-buffer))
(if no-kill
(with-current-buffer repl
(goto-char (point-max))
(cider-repl-emit-interactive-stderr
(format "*** Closed on %s ***\n" (current-time-string))))
(kill-buffer repl)))
(when repl
(sesman-remove-object 'CIDER nil repl (not no-kill) t)))
(defun cider-emit-manual-warning (section-id format &rest args)
"Emit a warning to the REPL and link to the online manual.
SECTION-ID is the section to link to. The link is added on the last line.
FORMAT is a format string to compile with ARGS and display on the REPL."
(let ((message (apply #'format format args)))
(cider-repl-emit-interactive-stderr
(concat "WARNING: " message "\n "
(cider--manual-button "More information" section-id)
"."))))
(defvar cider-version)
(defun cider--check-required-nrepl-version ()
"Check whether we're using a compatible nREPL version."
(if-let* ((nrepl-version (cider--nrepl-version)))
(when (version< nrepl-version cider-required-nrepl-version)
(cider-emit-manual-warning "troubleshooting/#warning-saying-you-have-to-use-nrepl-0212"
"CIDER requires nREPL %s (or newer) to work properly"
cider-required-nrepl-version))
(cider-emit-manual-warning "troubleshooting/#warning-saying-you-have-to-use-nrepl-0212"
"Can't determine nREPL's version.\nPlease, update nREPL to %s."
cider-required-nrepl-version)))
(defvar cider-minimum-clojure-version)
(defun cider--check-clojure-version-supported ()
"Ensure that we are meeting the minimum supported version of Clojure."
(if-let* ((clojure-version (cider--clojure-version)))
(when (version< clojure-version cider-minimum-clojure-version)
(cider-emit-manual-warning "installation/#prerequisites"
"Clojure version (%s) is not supported (minimum %s). CIDER will not work."
clojure-version cider-minimum-clojure-version))
(cider-emit-manual-warning "installation/#prerequisites"
"Can't determine Clojure's version. CIDER requires Clojure %s (or newer)."
cider-minimum-clojure-version)))
(defun cider--check-middleware-compatibility ()
"CIDER frontend/backend compatibility check.
Retrieve the underlying connection's CIDER-nREPL version and checks if the
middleware used is compatible with CIDER. If not, will display a warning
message in the REPL area."
(let* ((version-dict (nrepl-aux-info "cider-version" (cider-current-repl)))
(middleware-version (nrepl-dict-get version-dict "version-string" "not installed")))
(unless (equal cider-version middleware-version)
(cider-emit-manual-warning "troubleshooting/#cider-complains-of-the-cider-nrepl-version"
"CIDER's version (%s) does not match cider-nrepl's version (%s). Things will break!"
cider-version middleware-version))))
(declare-function cider-interactive-eval-handler "cider-eval")
;; TODO: Use some null handler here
(defun cider--subscribe-repl-to-server-out ()
"Subscribe to the nREPL server's *out*."
(cider-nrepl-send-request '("op" "out-subscribe")
(cider-interactive-eval-handler (current-buffer))))
(declare-function cider-mode "cider-mode")
(defun cider-enable-on-existing-clojure-buffers ()
"Enable CIDER's minor mode on existing Clojure buffers.
See command `cider-mode'."
(interactive)
(add-hook 'clojure-mode-hook #'cider-mode)
(dolist (buffer (cider-util--clojure-buffers))
(with-current-buffer buffer
(cider-mode +1))))
(defun cider-disable-on-existing-clojure-buffers ()
"Disable command `cider-mode' on existing Clojure buffers."
(interactive)
(dolist (buffer (cider-util--clojure-buffers))
(with-current-buffer buffer
(cider-mode -1))))
(defun cider-possibly-disable-on-existing-clojure-buffers ()
"If not connected, disable command `cider-mode' on existing Clojure buffers."
(unless (cider-connected-p)
(cider-disable-on-existing-clojure-buffers)))
(declare-function cider--debug-init-connection "cider-debug")
(declare-function cider-repl-init "cider-repl")
(defun cider--connected-handler ()
"Handle CIDER initialization after nREPL connection has been established.
This function is appended to `nrepl-connected-hook' in the client process
buffer."
;; `nrepl-connected-hook' is run in the connection buffer
;; `cider-enlighten-mode' changes eval to include the debugger, so we inhibit
;; it here as the debugger isn't necessarily initialized yet
(let ((cider-enlighten-mode nil))
;; after initialization, set mode-line and buffer name.
(cider-set-repl-type cider-repl-type)
(cider-repl-init (current-buffer))
(cider--check-required-nrepl-version)
(cider--check-clojure-version-supported)
(cider--check-middleware-compatibility)
(when cider-redirect-server-output-to-repl
(cider--subscribe-repl-to-server-out))
(when cider-auto-mode
(cider-enable-on-existing-clojure-buffers))
;; Middleware on cider-nrepl's side is deferred until first usage, but
;; loading middleware concurrently can lead to occasional "require" issues
;; (likely a Clojure bug). Thus, we load the heavy debug middleware towards
;; the end, allowing for the faster "server-out" middleware to load
;; first.
(cider--debug-init-connection)
(when cider-repl-init-function
(funcall cider-repl-init-function))
(run-hooks 'cider-connected-hook)))
(defun cider--disconnected-handler ()
"Cleanup after nREPL connection has been lost or closed.
This function is appended to `nrepl-disconnected-hook' in the client
process buffer."
;; `nrepl-connected-hook' is run in the connection buffer
(cider-possibly-disable-on-existing-clojure-buffers)
(run-hooks 'cider-disconnected-hook))
;;; Connection Info
(defun cider--java-version ()
"Retrieve the underlying connection's Java version."
(with-current-buffer (cider-current-repl)
(when nrepl-versions
(thread-first nrepl-versions
(nrepl-dict-get "java")
(nrepl-dict-get "version-string")))))
(defun cider--clojure-version ()
"Retrieve the underlying connection's Clojure version."
(with-current-buffer (cider-current-repl)
(when nrepl-versions
(thread-first nrepl-versions
(nrepl-dict-get "clojure")
(nrepl-dict-get "version-string")))))
(defun cider--nrepl-version ()
"Retrieve the underlying connection's nREPL version."
(with-current-buffer (cider-current-repl)
(when nrepl-versions
(thread-first nrepl-versions
(nrepl-dict-get "nrepl")
(nrepl-dict-get "version-string")))))
(defun cider--connection-info (connection-buffer &optional genericp)
"Return info about CONNECTION-BUFFER.
Info contains project name, current REPL namespace, host:port endpoint and
Clojure version. When GENERICP is non-nil, don't provide specific info
about this buffer (like variable `cider-repl-type')."
(with-current-buffer connection-buffer
(format "%s%s@%s:%s (Java %s, Clojure %s, nREPL %s)"
(if genericp "" (upcase (concat cider-repl-type " ")))
(or (cider--project-name nrepl-project-dir) "<no project>")
(plist-get nrepl-endpoint :host)
(plist-get nrepl-endpoint :port)
(cider--java-version)
(cider--clojure-version)
(cider--nrepl-version))))
;;; Cider's Connection Management UI
(defun cider-quit ()
"Quit the currently active CIDER connection."
(interactive)
(cider-ensure-connected)
(let ((connection (cider-current-repl)))
(cider--close-connection connection))
;; if there are no more connections we can kill all ancillary buffers
(unless (cider-connected-p)
(cider-close-ancillary-buffers)))
(defun cider-restart ()
"Restart the currently active CIDER connection.
Don't restart the server or other connections within the same session. Use
`sesman-restart' to restart the entire session."
(interactive)
(let* ((repl (or (cider-current-repl)
(user-error "No linked REPL")))
(params (thread-first (cider--gather-connect-params nil repl)
(plist-put :session-name (sesman-session-name-for-object 'CIDER repl))
(plist-put :repl-buffer repl))))
(cider--close-connection repl 'no-kill)
(cider-nrepl-connect params)))
(defun cider-close-ancillary-buffers ()
"Close buffers that are shared across connections."
(interactive)
(dolist (buf-name cider-ancillary-buffers)
(when (get-buffer buf-name)
(kill-buffer buf-name))))
(defun cider-describe-current-connection ()
"Display information about the current connection."
(interactive)
(message "%s" (cider--connection-info (cider-current-repl nil 'ensure))))
(define-obsolete-function-alias 'cider-display-connection-info 'cider-describe-current-connection "0.18.0")
(defconst cider-nrepl-session-buffer "*cider-nrepl-session*")
(defun cider-describe-nrepl-session ()
"Describe an nREPL session."
(interactive)
(cider-ensure-connected)
(let* ((repl (cider-current-repl nil 'ensure))
(selected-session (completing-read "Describe nREPL session: " (nrepl-sessions repl))))
(when (and selected-session (not (equal selected-session "")))
(let* ((session-info (nrepl-sync-request:describe repl))
(ops (nrepl-dict-keys (nrepl-dict-get session-info "ops")))
(session-id (nrepl-dict-get session-info "session"))
(session-type (cond
((equal session-id (cider-nrepl-eval-session)) "Active eval")
((equal session-id (cider-nrepl-tooling-session)) "Active tooling")
(t "Unknown"))))
(with-current-buffer (cider-popup-buffer cider-nrepl-session-buffer 'select nil 'ancillary)
(read-only-mode -1)
(insert (format "Session: %s\n" session-id)
(format "Type: %s session\n" session-type)
(format "Supported ops:\n"))
(mapc (lambda (op) (insert (format " * %s\n" op))) ops)))
(display-buffer cider-nrepl-session-buffer))))
;;; Sesman's Session-Wise Management UI
(cl-defmethod sesman-more-relevant-p ((_system (eql CIDER)) session1 session2)
(sesman-more-recent-p (cdr session1) (cdr session2)))
(cl-defmethod sesman-session-info ((_system (eql CIDER)) session)
(interactive "P")
(let ((repl (cadr session)))
(format "\t%s: %s\n\tREPLS: %s"
(if (buffer-local-value 'nrepl-server-buffer repl) "SERVER" "CONNECTION")
(cider--connection-info repl t)
(mapconcat #'buffer-name (cdr session) ", "))))
(declare-function cider "cider")
(cl-defmethod sesman-start-session ((_system (eql CIDER)))
"Start a connection of any type interactively.
Fallback on `cider' command."
(call-interactively #'cider))
(cl-defmethod sesman-quit-session ((_system (eql CIDER)) session)
(mapc #'cider--close-connection (cdr session))
;; if there are no more connections we can kill all ancillary buffers
(unless (cider-connected-p)
(cider-close-ancillary-buffers)))
(cl-defmethod sesman-restart-session ((_system (eql CIDER)) session)
(let* ((repls (cdr session))
(s-buf (seq-some (lambda (r)
(buffer-local-value 'nrepl-server-buffer r))
repls))
(s-params (cider--gather-connect-params nil s-buf))
(ses-name (car session)))
;; 1) kill all connections, but keep the buffers
(mapc (lambda (conn)
(cider--close-connection conn 'no-kill))
repls)
;; 2) kill the server
(message "Waiting for CIDER server to quit...")
(nrepl-kill-server-buffer s-buf)
;; 3) start server
(nrepl-start-server-process
(plist-get s-params :project-dir)
(plist-get s-params :server-command)
(lambda (server-buf)
;; 4) restart the repls reusing the buffer
(dolist (r repls)
(cider-nrepl-connect
(thread-first ()
(cider--gather-connect-params r)
;; server params (:port, :project-dir etc) have precedence
(cider--gather-connect-params server-buf)
(plist-put :session-name ses-name)
(plist-put :repl-buffer r))))
(message "Restarted CIDER %s session" ses-name)))))
(defun cider-new-session-name (params)
"Create new session name given plist of connection PARAMS."
(let* ((dir (or (plist-get params :project-dir)
(clojure-project-dir (cider-current-dir))
default-directory))
(host (plist-get params :host))
;; showing host:port on remotes only
(host-port (if (not (or (null host)
(equal host "localhost")
(equal host "127.0.0.1")))
(format ":%s:%s" host (plist-get params :port))
""))
(root-name (file-name-nondirectory (directory-file-name dir)))
(name (format "%s%s" root-name host-port))
(other-names (mapcar #'car (sesman-sessions 'CIDER)))
(i 2))
(while (member name other-names)
(setq name (concat root-name "#" (number-to-string i))
i (+ i 1)))
name))
;;; REPL Buffer Init
(defvar-local cider-repl-type nil
"The type of this REPL buffer, usually either \"clj\" or \"cljs\".")
(defun cider-repl-type (repl-buffer)
"Get REPL-BUFFER's type."
(buffer-local-value 'cider-repl-type repl-buffer))
(defun cider-repl-type-for-buffer (&optional buffer)
"Return the matching connection type (clj or cljs) for BUFFER.
BUFFER defaults to the `current-buffer'. In cljc buffers return
\"multi\". This function infers connection type based on the major mode.
For the REPL type use the function `cider-repl-type'."
(with-current-buffer (or buffer (current-buffer))
(cond
((derived-mode-p 'clojurescript-mode) "cljs")
((derived-mode-p 'clojurec-mode) "multi")
((derived-mode-p 'clojure-mode) "clj")
(cider-repl-type))))
(defun cider-set-repl-type (&optional type)
"Set REPL TYPE to \"clj\" or \"cljs\".
Assume that the current buffer is a REPL."
(interactive)
(let ((type (or type (completing-read
(format "Set REPL type (currently `%s') to: "
cider-repl-type)
'("clj" "cljs")))))
(when (or (not (equal cider-repl-type type))
(null mode-name))
(setq cider-repl-type type)
(setq mode-name (format "REPL[%s]" type))
(rename-buffer (nrepl-repl-buffer-name))
(when (and nrepl-log-messages nrepl-messages-buffer)
(let ((mbuf-name (nrepl-messages-buffer-name (current-buffer))))
(with-current-buffer nrepl-messages-buffer
(rename-buffer mbuf-name)))))))
(declare-function cider-default-err-handler "cider-eval")
(declare-function cider-repl-mode "cider-repl")
(declare-function cider-repl--state-handler "cider-repl")
(declare-function cider-repl-reset-markers "cider-repl")
(defvar-local cider-repl-init-function nil)
(defun cider-repl-create (params)
"Create new repl buffer.
PARAMS is a plist which contains :repl-type, :host, :port, :project-dir,
:repl-init-function and :session-name. When non-nil, :repl-init-function
must be a function with no arguments which is called after repl creation
function with the repl buffer set as current."
;; Connection might not have been set as yet. Please don't send requests in
;; this function, but use cider--connected-handler instead.
(let ((buffer (or (plist-get params :repl-buffer)
(get-buffer-create (generate-new-buffer-name "*cider-uninitialized-repl*")))))
(with-current-buffer buffer
(let ((ses-name (or (plist-get params :session-name)
(cider-new-session-name params))))
(sesman-add-object 'CIDER ses-name buffer t))
(unless (derived-mode-p 'cider-repl-mode)
(cider-repl-mode))
(setq nrepl-err-handler #'cider-default-err-handler
;; used as a new-repl marker in cider-set-repl-type
mode-name nil
;; REPLs start with clj and then "upgrade" to a different type
cider-repl-type "clj"
;; ran at the end of cider--connected-handler
cider-repl-init-function (plist-get params :repl-init-function))
(cider-repl-reset-markers)
(add-hook 'nrepl-response-handler-functions #'cider-repl--state-handler nil 'local)
(add-hook 'nrepl-connected-hook 'cider--connected-handler nil 'local)
(add-hook 'nrepl-disconnected-hook 'cider--disconnected-handler nil 'local)
(current-buffer))))
;;; Current/other REPLs
(defun cider-current-repl (&optional type ensure)
"Get the most recent REPL of TYPE from the current session.
TYPE is either \"clj\", \"cljs\" or \"multi\". When nil, infer the type
from the current buffer. If ENSURE is non-nil, throw an error if either
there is no linked session or there is no REPL of TYPE within the current
session."
(if (and (derived-mode-p 'cider-repl-mode)
(or (null type)
(string= cider-repl-type type)))
;; shortcut when in REPL buffer
(current-buffer)
(let* ((type (or type (cider-repl-type-for-buffer)))
(repls (cider-repls type ensure))
(repl (if (<= (length repls) 1)
(car repls)
;; pick the most recent one
(seq-find (lambda (b)
(member b repls))
(buffer-list)))))
(if (and ensure (null repl))
(user-error "No %s REPL in current session (%s)"
type (car (sesman-current-session 'CIDER)))
repl))))
(defun cider-repls (&optional type ensure)
"Return cider REPLs of TYPE from the current session.
If TYPE is nil or \"multi\", return all repls. If ENSURE is non-nil, throw
an error if no linked session exists."
(let ((repls (cdr (if ensure
(sesman-ensure-session 'CIDER)
(sesman-current-session 'CIDER)))))
(if (or (null type) (equal type "multi"))
repls
(seq-filter (lambda (b)
(string= type (cider-repl-type b)))
repls))))
(defun cider-map-repls (which function)
"Call FUNCTION once for each appropriate REPL as indicated by WHICH.
The function is called with one argument, the REPL buffer. The appropriate
connections are found by inspecting the current buffer. WHICH is one of
the following keywords:
:auto - Act on the connections whose type matches the current buffer. In
`cljc' files, mapping happens over both types of REPLs.
:clj (:cljs) - Map over clj (cljs)) REPLs only.
:clj-strict (:cljs-strict) - Map over clj (cljs) REPLs but signal a
`user-error' in `clojurescript-mode' (`clojure-mode'). Use this for
commands only supported in Clojure (ClojureScript).
Error is signaled if no REPL buffer of specified type exists."
(declare (indent 1))
(let ((cur-type (cider-repl-type-for-buffer)))
(cl-case which
(:clj-strict (when (equal cur-type "cljs")
(user-error "Clojure-only operation requested in a ClojureScript buffer")))
(:cljs-strict (when (equal cur-type "clj")
(user-error "ClojureScript-only operation requested in a Clojure buffer"))))
(let* ((type (cl-case which
((:clj :clj-strict) "clj")
((:cljs :cljs-strict) "cljs")
(:auto cur-type)))
(repls (cider-repls type 'ensure)))
(mapcar function repls))))
;; REPLs double as connections in CIDER, so it's useful to be able to refer to
;; them as connections in certain contexts.
(defalias 'cider-current-connection #'cider-current-repl)
(defalias 'cider-connections #'cider-repls)
(defalias 'cider-map-connections #'cider-map-repls)
(defalias 'cider-connection-type-for-buffer #'cider-repl-type-for-buffer)
;; Deprecation after #2324
(define-obsolete-function-alias 'cider-current-repl-buffer 'cider-current-repl "0.18")
(define-obsolete-function-alias 'cider-repl-buffers 'cider-repls "0.18")
(define-obsolete-function-alias 'cider-current-session 'cider-nrepl-eval-session "0.18")
(define-obsolete-function-alias 'cider-current-tooling-session 'cider-nrepl-tooling-session "0.18")
(define-obsolete-function-alias 'cider-display-connection-info 'cider-describe-current-connection "0.18")
(define-obsolete-function-alias 'nrepl-connection-buffer-name 'nrepl-repl-buffer-name "0.18")
(define-obsolete-function-alias 'cider-repl-set-type 'cider-set-repl-type "0.18")
(make-obsolete 'cider-assoc-buffer-with-connection 'sesman-link-with-buffer "0.18")
(make-obsolete 'cider-assoc-project-with-connection 'sesman-link-with-project "0.18")
(make-obsolete 'cider-change-buffers-designation nil "0.18")
(make-obsolete 'cider-clear-buffer-local-connection nil "0.18")
(make-obsolete 'cider-close-nrepl-session 'cider-quit "0.18")
(make-obsolete 'cider-create-sibling-cljs-repl 'cider-connect-sibling-cljs "0.18")
(make-obsolete 'cider-current-messages-buffer nil "0.18")
(make-obsolete 'cider-default-connection "see sesman." "0.18")
(make-obsolete 'cider-extract-designation-from-current-repl-buffer nil "0.18")
(make-obsolete 'cider-find-connection-buffer-for-project-directory 'sesman-linked-sessions "0.18")
(make-obsolete 'cider-find-reusable-repl-buffer nil "0.18")
(make-obsolete 'cider-make-connection-default "see sesman." "0.18")
(make-obsolete 'cider-other-connection nil "0.18")
(make-obsolete 'cider-project-connections 'sesman-linked-sessions "0.18")
(make-obsolete 'cider-project-connections-types nil "0.18")
(make-obsolete 'cider-prompt-for-project-on-connect nil "0.18")
(make-obsolete 'cider-read-connection `sesman-ask-for-session "0.18")
(make-obsolete 'cider-replicate-connection nil "0.18")
(make-obsolete 'cider-request-dispatch "see sesman." "0.18")
(make-obsolete 'cider-rotate-default-connection "see sesman." "0.18")
(make-obsolete 'cider-toggle-buffer-connection nil "0.18")
(make-obsolete 'cider-toggle-request-dispatch nil "0.18")
(make-obsolete 'nrepl-connection-buffer-name-template 'nrepl-repl-buffer-name-template "0.18")
(make-obsolete 'nrepl-create-client-buffer-function nil "0.18")
(make-obsolete 'nrepl-post-client-callback nil "0.18")
(make-obsolete 'nrepl-prompt-to-kill-server-buffer-on-quit nil "0.18")
(make-obsolete 'nrepl-use-this-as-repl-buffer nil "0.18")
;; connection manager
(make-obsolete 'cider-client-name-repl-type "see sesman." "0.18")
(make-obsolete 'cider-connection-browser "see sesman." "0.18")
(make-obsolete 'cider-connections-buffer-mode "see sesman." "0.18")
(make-obsolete 'cider-connections-buffer-mode-map "see sesman." "0.18")
(make-obsolete 'cider-connections-close-connection "see sesman." "0.18")
(make-obsolete 'cider-connections-goto-connection "see sesman." "0.18")
(make-obsolete 'cider-connections-make-default "see sesman." "0.18")
(make-obsolete 'cider-display-connected-message "see sesman." "0.18")
(make-obsolete 'cider-project-name "see sesman." "0.18")
(provide 'cider-connection)
;;; cider-connection.el ends here

View file

@ -0,0 +1,755 @@
;;; cider-debug.el --- CIDER interaction with the cider.debug nREPL middleware -*- lexical-binding: t; -*-
;; Copyright © 2015-2018 Bozhidar Batsov, Artur Malabarba and CIDER contributors
;; Author: Artur Malabarba <bruce.connor.am@gmail.com>
;; 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/>.
;;; Commentary:
;; Instrument code with `cider-debug-defun-at-point', and when the code is
;; executed cider-debug will kick in. See this function's doc for more
;; information.
;;; Code:
(require 'nrepl-dict)
(require 'nrepl-client) ; `nrepl--mark-id-completed'
(require 'cider-eval)
(require 'cider-client)
(require 'cider-util)
(require 'cider-inspector)
(require 'cider-browse-ns)
(require 'cider-common)
(require 'subr-x)
(require 'cider-compat)
(require 'seq)
(require 'spinner)
;;; Customization
(defgroup cider-debug nil
"Presentation and behaviour of the cider debugger."
:prefix "cider-debug-"
:group 'cider
:package-version '(cider . "0.10.0"))
(defface cider-debug-code-overlay-face
'((((class color) (background light)) :background "grey80")
(((class color) (background dark)) :background "grey30"))
"Face used to mark code being debugged."
:group 'cider-debug
:package-version '(cider . "0.9.1"))
(defface cider-debug-prompt-face
'((t :underline t :inherit font-lock-builtin-face))
"Face used to highlight keys in the debug prompt."
:group 'cider-debug
:package-version '(cider . "0.10.0"))
(defface cider-enlightened-face
'((((class color) (background light)) :inherit cider-result-overlay-face
:box (:color "darkorange" :line-width -1))
(((class color) (background dark)) :inherit cider-result-overlay-face
;; "#dd0" is a dimmer yellow.
:box (:color "#990" :line-width -1)))
"Face used to mark enlightened sexps and their return values."
:group 'cider-debug
:package-version '(cider . "0.11.0"))
(defface cider-enlightened-local-face
'((((class color) (background light)) :weight bold :foreground "darkorange")
(((class color) (background dark)) :weight bold :foreground "yellow"))
"Face used to mark enlightened locals (not their values)."
:group 'cider-debug
:package-version '(cider . "0.11.0"))
(defcustom cider-debug-prompt 'overlay
"If and where to show the keys while debugging.
If `minibuffer', show it in the minibuffer along with the return value.
If `overlay', show it in an overlay above the current function.
If t, do both.
If nil, don't list available keys at all."
:type '(choice (const :tag "Show in minibuffer" minibuffer)
(const :tag "Show above function" overlay)
(const :tag "Show in both places" t)
(const :tag "Don't list keys" nil))
:group 'cider-debug
:package-version '(cider . "0.10.0"))
(defcustom cider-debug-use-overlays t
"Whether to higlight debugging information with overlays.
Takes the same possible values as `cider-use-overlays', but only applies to
values displayed during debugging sessions.
To control the overlay that lists possible keys above the current function,
configure `cider-debug-prompt' instead."
:type '(choice (const :tag "End of line" t)
(const :tag "Bottom of screen" nil)
(const :tag "Both" both))
:group 'cider-debug
:package-version '(cider . "0.9.1"))
(defcustom cider-debug-print-level 10
"The print level for values displayed by the debugger.
This variable must be set before starting the repl connection."
:type '(choice (const :tag "No limit" nil)
(integer :tag "Max depth" 10))
:group 'cider-debug
:package-version '(cider . "0.10.0"))
(defcustom cider-debug-print-length 10
"The print length for values displayed by the debugger.
This variable must be set before starting the repl connection."
:type '(choice (const :tag "No limit" nil)
(integer :tag "Max depth" 10))
:group 'cider-debug
:package-version '(cider . "0.10.0"))
;;; Implementation
(defun cider-browse-instrumented-defs ()
"List all instrumented definitions."
(interactive)
(if-let* ((all (thread-first (cider-nrepl-send-sync-request '("op" "debug-instrumented-defs"))
(nrepl-dict-get "list"))))
(with-current-buffer (cider-popup-buffer cider-browse-ns-buffer t)
(let ((inhibit-read-only t))
(erase-buffer)
(dolist (list all)
(let* ((ns (car list))
(ns-vars-with-meta (cider-sync-request:ns-vars-with-meta ns))
;; seq of metadata maps of the instrumented vars
(instrumented-meta (mapcar (apply-partially #'nrepl-dict-get ns-vars-with-meta)
(cdr list))))
(cider-browse-ns--list (current-buffer) ns
(seq-mapn #'cider-browse-ns--properties
(cdr list)
instrumented-meta)
ns 'noerase)
(goto-char (point-max))
(insert "\n"))))
(goto-char (point-min)))
(message "No currently instrumented definitions")))
(defun cider--debug-response-handler (response)
"Handles RESPONSE from the cider.debug middleware."
(nrepl-dbind-response response (status id causes)
(when (member "enlighten" status)
(cider--handle-enlighten response))
(when (or (member "eval-error" status)
(member "stack" status))
;; TODO: Make the error buffer a bit friendlier when we're just printing
;; the stack.
(cider--render-stacktrace-causes causes))
(when (member "need-debug-input" status)
(cider--handle-debug response))
(when (member "done" status)
(nrepl--mark-id-completed id))))
(defun cider--debug-init-connection ()
"Initialize a connection with the cider.debug middleware."
(cider-nrepl-send-request
(nconc '("op" "init-debugger")
(when cider-debug-print-level
`("print-level" ,cider-debug-print-level))
(when cider-debug-print-length
`("print-length" ,cider-debug-print-length)))
#'cider--debug-response-handler))
;;; Debugging overlays
(defconst cider--fringe-arrow-string
#("." 0 1 (display (left-fringe right-triangle)))
"Used as an overlay's before-string prop to place a fringe arrow.")
(defun cider--debug-display-result-overlay (value)
"Place an overlay at point displaying VALUE."
(when cider-debug-use-overlays
;; This is cosmetic, let's ensure it doesn't break the session no matter what.
(ignore-errors
;; Result
(cider--make-result-overlay (cider-font-lock-as-clojure value)
:where (point-marker)
:type 'debug-result
'before-string cider--fringe-arrow-string)
;; Code
(cider--make-overlay (save-excursion (clojure-backward-logical-sexp 1) (point))
(point) 'debug-code
'face 'cider-debug-code-overlay-face
;; Higher priority than `show-paren'.
'priority 2000))))
;;; Minor mode
(defvar-local cider--debug-mode-commands-dict nil
"An nrepl-dict from keys to debug commands.
Autogenerated by `cider--turn-on-debug-mode'.")
(defvar-local cider--debug-mode-response nil
"Response that triggered current debug session.
Set by `cider--turn-on-debug-mode'.")
(defcustom cider-debug-display-locals nil
"If non-nil, local variables are displayed while debugging.
Can be toggled at any time with `\\[cider-debug-toggle-locals]'."
:type 'boolean
:group 'cider-debug
:package-version '(cider . "0.10.0"))
(defun cider--debug-format-locals-list (locals)
"Return a string description of list LOCALS.
Each element of LOCALS should be a list of at least two elements."
(if locals
(let ((left-col-width
;; To right-indent the variable names.
(apply #'max (mapcar (lambda (l) (string-width (car l))) locals))))
;; A format string to build a format string. :-P
(mapconcat (lambda (l) (format (format " %%%ds: %%s\n" left-col-width)
(propertize (car l) 'face 'font-lock-variable-name-face)
(cider-font-lock-as-clojure (cadr l))))
locals ""))
""))
(defun cider--debug-prompt (command-dict)
"Return prompt to display for COMMAND-DICT."
;; Force `default' face, otherwise the overlay "inherits" the face of the text
;; after it.
(format (propertize "%s\n" 'face 'default)
(string-join
(nrepl-dict-map (lambda (char cmd)
(when-let* ((pos (cl-search char cmd)))
(put-text-property pos (1+ pos) 'face 'cider-debug-prompt-face cmd))
cmd)
command-dict)
" ")))
(defvar-local cider--debug-prompt-overlay nil)
(defun cider--debug-mode-redisplay ()
"Display the input prompt to the user."
(nrepl-dbind-response cider--debug-mode-response (debug-value input-type locals)
(when (or (eq cider-debug-prompt t)
(eq cider-debug-prompt 'overlay))
(if (overlayp cider--debug-prompt-overlay)
(overlay-put cider--debug-prompt-overlay
'before-string (cider--debug-prompt input-type))
(setq cider--debug-prompt-overlay
(cider--make-overlay
(max (car (cider-defun-at-point 'bounds))
(window-start))
nil 'debug-prompt
'before-string (cider--debug-prompt input-type)))))
(let* ((value (concat " " cider-eval-result-prefix
(cider-font-lock-as-clojure
(or debug-value "#unknown#"))))
(to-display
(concat (when cider-debug-display-locals
(cider--debug-format-locals-list locals))
(when (or (eq cider-debug-prompt t)
(eq cider-debug-prompt 'minibuffer))
(cider--debug-prompt input-type))
(when (or (not cider-debug-use-overlays)
(eq cider-debug-use-overlays 'both))
value))))
(if (> (string-width to-display) 0)
(message "%s" to-display)
;; If there's nothing to display in the minibuffer. Just send the value
;; to the Messages buffer.
(message "%s" value)
(message nil)))))
(defun cider-debug-toggle-locals ()
"Toggle display of local variables."
(interactive)
(setq cider-debug-display-locals (not cider-debug-display-locals))
(cider--debug-mode-redisplay))
(defun cider--debug-lexical-eval (key form &optional callback _point)
"Eval FORM in the lexical context of debug session given by KEY.
Do nothing if CALLBACK is provided.
Designed to be used as `cider-interactive-eval-override' and called instead
of `cider-interactive-eval' in debug sessions."
;; The debugger uses its own callback, so if the caller is passing a callback
;; we return nil and let `cider-interactive-eval' do its thing.
(unless callback
(cider-debug-mode-send-reply (format "{:response :eval, :code %s}" form)
key)
t))
(defvar cider--debug-mode-tool-bar-map
(let ((tool-bar-map (make-sparse-keymap)))
(tool-bar-add-item "right-arrow" #'cider-debug-mode-send-reply :next :label "Next step")
(tool-bar-add-item "next-node" #'cider-debug-mode-send-reply :continue :label "Continue non-stop")
(tool-bar-add-item "jump-to" #'cider-debug-mode-send-reply :out :label "Out of sexp")
(tool-bar-add-item "exit" #'cider-debug-mode-send-reply :quit :label "Quit")
tool-bar-map))
(defvar cider--debug-mode-map)
(define-minor-mode cider--debug-mode
"Mode active during debug sessions.
In order to work properly, this mode must be activated by
`cider--turn-on-debug-mode'."
nil " DEBUG" '()
(if cider--debug-mode
(if cider--debug-mode-response
(nrepl-dbind-response cider--debug-mode-response (input-type)
;; A debug session is an ongoing eval, but it's annoying to have the
;; spinner spinning while you debug.
(when spinner-current (spinner-stop))
(setq-local tool-bar-map cider--debug-mode-tool-bar-map)
(add-hook 'kill-buffer-hook #'cider--debug-quit nil 'local)
(add-hook 'before-revert-hook #'cider--debug-quit nil 'local)
(unless (consp input-type)
(error "Activated debug-mode on a message not asking for commands: %s" cider--debug-mode-response))
;; Integrate with eval commands.
(setq cider-interactive-eval-override
(apply-partially #'cider--debug-lexical-eval
(nrepl-dict-get cider--debug-mode-response "key")))
;; Set the keymap.
(nrepl-dict-map (lambda (char _cmd)
(unless (string= char "h") ; `here' needs a special command.
(define-key cider--debug-mode-map char #'cider-debug-mode-send-reply))
(when (string= char "o")
(define-key cider--debug-mode-map (upcase char) #'cider-debug-mode-send-reply)))
input-type)
(setq cider--debug-mode-commands-dict input-type)
;; Show the prompt.
(cider--debug-mode-redisplay)
;; If a sync request is ongoing, the user can't act normally to
;; provide input, so we enter `recursive-edit'.
(when nrepl-ongoing-sync-request
(recursive-edit)))
(cider--debug-mode -1)
(if (called-interactively-p 'any)
(user-error (substitute-command-keys "Don't call this mode manually, use `\\[universal-argument] \\[cider-eval-defun-at-point]' instead"))
(error "Attempt to activate `cider--debug-mode' without setting `cider--debug-mode-response' first")))
(setq cider-interactive-eval-override nil)
(setq cider--debug-mode-commands-dict nil)
(setq cider--debug-mode-response nil)
;; We wait a moment before clearing overlays and the read-onlyness, so that
;; cider-nrepl has a chance to send the next message, and so that the user
;; doesn't accidentally hit `n' between two messages (thus editing the code).
(when-let* ((proc (unless nrepl-ongoing-sync-request
(get-buffer-process (cider-current-repl)))))
(accept-process-output proc 1))
(unless cider--debug-mode
(setq buffer-read-only nil)
(cider--debug-remove-overlays (current-buffer)))
(when nrepl-ongoing-sync-request
(ignore-errors (exit-recursive-edit)))))
;;; Bind the `:here` command to both h and H, because it behaves differently if
;;; invoked with an uppercase letter.
(define-key cider--debug-mode-map "h" #'cider-debug-move-here)
(define-key cider--debug-mode-map "H" #'cider-debug-move-here)
(defun cider--debug-remove-overlays (&optional buffer)
"Remove CIDER debug overlays from BUFFER if variable `cider--debug-mode' is nil."
(when (or (not buffer) (buffer-live-p buffer))
(with-current-buffer (or buffer (current-buffer))
(unless cider--debug-mode
(kill-local-variable 'tool-bar-map)
(remove-overlays nil nil 'category 'debug-result)
(remove-overlays nil nil 'category 'debug-code)
(setq cider--debug-prompt-overlay nil)
(remove-overlays nil nil 'category 'debug-prompt)))))
(defun cider--debug-set-prompt (value)
"Set `cider-debug-prompt' to VALUE, then redisplay."
(setq cider-debug-prompt value)
(cider--debug-mode-redisplay))
(easy-menu-define cider-debug-mode-menu cider--debug-mode-map
"Menu for CIDER debug mode"
`("CIDER Debugger"
["Next step" (cider-debug-mode-send-reply ":next") :keys "n"]
["Continue non-stop" (cider-debug-mode-send-reply ":continue") :keys "c"]
["Move out of sexp" (cider-debug-mode-send-reply ":out") :keys "o"]
["Quit" (cider-debug-mode-send-reply ":quit") :keys "q"]
"--"
["Evaluate in current scope" (cider-debug-mode-send-reply ":eval") :keys "e"]
["Inject value" (cider-debug-mode-send-reply ":inject") :keys "i"]
["Inspect value" (cider-debug-mode-send-reply ":inspect")]
["Inspect local variables" (cider-debug-mode-send-reply ":locals") :keys "l"]
"--"
("Configure keys prompt"
["Don't show keys" (cider--debug-set-prompt nil) :style toggle :selected (eq cider-debug-prompt nil)]
["Show in minibuffer" (cider--debug-set-prompt 'minibuffer) :style toggle :selected (eq cider-debug-prompt 'minibuffer)]
["Show above function" (cider--debug-set-prompt 'overlay) :style toggle :selected (eq cider-debug-prompt 'overlay)]
["Show in both places" (cider--debug-set-prompt t) :style toggle :selected (eq cider-debug-prompt t)]
"--"
["List locals" cider-debug-toggle-locals :style toggle :selected cider-debug-display-locals])
["Customize" (customize-group 'cider-debug)]))
(defun cider--uppercase-command-p ()
"Return non-nil if the last command was uppercase letter."
(ignore-errors
(let ((case-fold-search nil))
(string-match "[[:upper:]]" (string last-command-event)))))
(defun cider-debug-mode-send-reply (command &optional key force)
"Reply to the message that started current bufer's debugging session.
COMMAND is sent as the input option. KEY can be provided to reply to a
specific message. If FORCE is non-nil, send a \"force?\" argument in the
message."
(interactive (list
(if (symbolp last-command-event)
(symbol-name last-command-event)
(ignore-errors
(concat ":" (nrepl-dict-get cider--debug-mode-commands-dict
(downcase (string last-command-event))))))
nil
(cider--uppercase-command-p)))
(when (and (string-prefix-p ":" command) force)
(setq command (format "{:response %s :force? true}" command)))
(cider-nrepl-send-unhandled-request
`("op" "debug-input"
"input" ,(or command ":quit")
"key" ,(or key (nrepl-dict-get cider--debug-mode-response "key"))))
(ignore-errors (cider--debug-mode -1)))
(defun cider--debug-quit ()
"Send a :quit reply to the debugger. Used in hooks."
(when cider--debug-mode
(cider-debug-mode-send-reply ":quit")
(message "Quitting debug session")))
;;; Movement logic
(defconst cider--debug-buffer-format "*cider-debug %s*")
(defun cider--debug-trim-code (code)
"Remove whitespace and reader macros from the start of the CODE.
Return trimmed CODE."
(replace-regexp-in-string "\\`#[a-z]+[\n\r[:blank:]]*" "" code))
(declare-function cider-set-buffer-ns "cider-mode")
(defun cider--initialize-debug-buffer (code ns id &optional reason)
"Create a new debugging buffer with CODE and namespace NS.
ID is the id of the message that instrumented CODE.
REASON is a keyword describing why this buffer was necessary."
(let ((buffer-name (format cider--debug-buffer-format id)))
(if-let* ((buffer (get-buffer buffer-name)))
(cider-popup-buffer-display buffer 'select)
(with-current-buffer (cider-popup-buffer buffer-name 'select
#'clojure-mode 'ancillary)
(cider-set-buffer-ns ns)
(setq buffer-undo-list nil)
(let ((inhibit-read-only t)
(buffer-undo-list t))
(erase-buffer)
(insert (format "%s" (cider--debug-trim-code code)))
(when code
(insert "\n\n\n;; We had to create this temporary buffer because we couldn't find the original definition. That probably happened because "
reason
".")
(fill-paragraph))
(cider--font-lock-ensure)
(set-buffer-modified-p nil))))
(switch-to-buffer buffer-name)
(goto-char (point-min))))
(defun cider--debug-goto-keyval (key)
"Find KEY in current sexp or return nil."
(when-let* ((limit (ignore-errors (save-excursion (up-list) (point)))))
(search-forward-regexp (concat "\\_<" (regexp-quote key) "\\_>")
limit 'noerror)))
(defun cider--debug-move-point (coordinates)
"Place point on after the sexp specified by COORDINATES.
COORDINATES is a list of integers that specify how to navigate into the
sexp that is after point when this function is called.
As an example, a COORDINATES list of '(1 0 2) means:
- enter next sexp then `forward-sexp' once,
- enter next sexp,
- enter next sexp then `forward-sexp' twice.
In the following snippet, this takes us to the (* x 2) sexp (point is left
at the end of the given sexp).
(letfn [(twice [x]
(* x 2))]
(twice 15))
In addition to numbers, a coordinate can be a string. This string names the
key of a map, and it means \"go to the value associated with this key\"."
(condition-case-unless-debug nil
;; Navigate through sexps inside the sexp.
(let ((in-syntax-quote nil))
(while coordinates
(while (clojure--looking-at-non-logical-sexp)
(forward-sexp))
;; An `@x` is read as (deref x), so we pop coordinates once to account
;; for the extra depth, and move past the @ char.
(if (eq ?@ (char-after))
(progn (forward-char 1)
(pop coordinates))
(down-list)
;; Are we entering a syntax-quote?
(when (looking-back "`\\(#{\\|[{[(]\\)" (line-beginning-position))
;; If we are, this affects all nested structures until the next `~',
;; so we set this variable for all following steps in the loop.
(setq in-syntax-quote t))
(when in-syntax-quote
;; A `(. .) is read as (seq (concat (list .) (list .))). This pops
;; the `seq', since the real coordinates are inside the `concat'.
(pop coordinates)
;; Non-list seqs like `[] and `{} are read with
;; an extra (apply vector ...), so pop it too.
(unless (eq ?\( (char-before))
(pop coordinates)))
;; #(...) is read as (fn* ([] ...)), so we patch that here.
(when (looking-back "#(" (line-beginning-position))
(pop coordinates))
(if coordinates
(let ((next (pop coordinates)))
(when in-syntax-quote
;; We're inside the `concat' form, but we need to discard the
;; actual `concat' symbol from the coordinate.
(setq next (1- next)))
;; String coordinates are map keys.
(if (stringp next)
(cider--debug-goto-keyval next)
(clojure-forward-logical-sexp next)
(when in-syntax-quote
(clojure-forward-logical-sexp 1)
(forward-sexp -1)
;; Here a syntax-quote is ending.
(let ((match (when (looking-at "~@?")
(match-string 0))))
(when match
(setq in-syntax-quote nil))
;; A `~@' is read as the object itself, so we don't pop
;; anything.
(unless (equal "~@" match)
;; Anything else (including a `~') is read as a `list'
;; form inside the `concat', so we need to pop the list
;; from the coordinates.
(pop coordinates))))))
;; If that extra pop was the last coordinate, this represents the
;; entire #(...), so we should move back out.
(backward-up-list))))
;; Place point at the end of instrumented sexp.
(clojure-forward-logical-sexp 1))
;; Avoid throwing actual errors, since this happens on every breakpoint.
(error (message "Can't find instrumented sexp, did you edit the source?"))))
(defun cider--debug-position-for-code (code)
"Return non-nil if point is roughly before CODE.
This might move point one line above."
(or (looking-at-p (regexp-quote code))
(let ((trimmed (regexp-quote (cider--debug-trim-code code))))
(or (looking-at-p trimmed)
;; If this is a fake #dbg injected by `C-u
;; C-M-x', then the sexp we want is actually on
;; the line above.
(progn (forward-line -1)
(looking-at-p trimmed))))))
(defun cider--debug-find-source-position (response &optional create-if-needed)
"Return a marker of the position after the sexp specified in RESPONSE.
This marker might be in a different buffer! If the sexp can't be
found (file that contains the code is no longer visited or has been
edited), return nil. However, if CREATE-IF-NEEDED is non-nil, a new buffer
is created in this situation and the return value is never nil.
Follow the \"line\" and \"column\" entries in RESPONSE, and check whether
the code at point matches the \"code\" entry in RESPONSE. If it doesn't,
assume that the code in this file has been edited, and create a temp buffer
holding the original code.
Either way, navigate inside the code by following the \"coor\" entry which
is a coordinate measure in sexps."
(nrepl-dbind-response response (code file line column ns original-id coor)
(when (or code (and file line column))
;; This is for restoring current-buffer.
(save-excursion
(let ((out))
;; We prefer in-source debugging.
(when-let* ((buf (and file line column
(ignore-errors
(cider--find-buffer-for-file file)))))
;; The logic here makes it hard to use `with-current-buffer'.
(with-current-buffer buf
;; This is for restoring point inside buf.
(save-excursion
;; Get to the proper line & column in the file
(forward-line (- line (line-number-at-pos)))
(move-to-column column)
;; Check if it worked
(when (cider--debug-position-for-code code)
;; Find the desired sexp.
(cider--debug-move-point coor)
(setq out (point-marker))))))
;; But we can create a temp buffer if that fails.
(or out
(when create-if-needed
(cider--initialize-debug-buffer
code ns original-id
(if (and line column)
"you edited the code"
"your tools.nrepl version is older than 0.2.11"))
(save-excursion
(cider--debug-move-point coor)
(point-marker)))))))))
(defun cider--handle-debug (response)
"Handle debugging notification.
RESPONSE is a message received from the nrepl describing the input
needed. It is expected to contain at least \"key\", \"input-type\", and
\"prompt\", and possibly other entries depending on the input-type."
(nrepl-dbind-response response (debug-value key input-type prompt inspect)
(condition-case-unless-debug e
(progn
(pcase input-type
("expression" (cider-debug-mode-send-reply
(condition-case nil
(cider-read-from-minibuffer
(or prompt "Expression: "))
(quit "nil"))
key))
((pred sequencep)
(let* ((marker (cider--debug-find-source-position response 'create-if-needed)))
(pop-to-buffer (marker-buffer marker))
(goto-char marker))
;; The overlay code relies on window boundaries, but point could have been
;; moved outside the window by some other code. Redisplay here to ensure the
;; visible window includes point.
(redisplay)
;; Remove overlays AFTER redisplaying! Otherwise there's a visible
;; flicker even if we immediately recreate the overlays.
(cider--debug-remove-overlays)
(when cider-debug-use-overlays
(cider--debug-display-result-overlay debug-value))
(setq cider--debug-mode-response response)
(cider--debug-mode 1)))
(when inspect
(cider-inspector--render-value inspect)))
;; If something goes wrong, we send a "quit" or the session hangs.
(error (cider-debug-mode-send-reply ":quit" key)
(message "Error encountered while handling the debug message: %S" e)))))
(defun cider--handle-enlighten (response)
"Handle an enlighten notification.
RESPONSE is a message received from the nrepl describing the value and
coordinates of a sexp. Create an overlay after the specified sexp
displaying its value."
(when-let* ((marker (cider--debug-find-source-position response)))
(with-current-buffer (marker-buffer marker)
(save-excursion
(goto-char marker)
(clojure-backward-logical-sexp 1)
(nrepl-dbind-response response (debug-value erase-previous)
(when erase-previous
(remove-overlays (point) marker 'category 'enlighten))
(when debug-value
(if (memq (char-before marker) '(?\) ?\] ?}))
;; Enlightening a sexp looks like a regular return value, except
;; for a different border.
(cider--make-result-overlay (cider-font-lock-as-clojure debug-value)
:where (cons marker marker)
:type 'enlighten
:prepend-face 'cider-enlightened-face)
;; Enlightening a symbol uses a more abbreviated format. The
;; result face is the same as a regular result, but we also color
;; the symbol with `cider-enlightened-local-face'.
(cider--make-result-overlay (cider-font-lock-as-clojure debug-value)
:format "%s"
:where (cons (point) marker)
:type 'enlighten
'face 'cider-enlightened-local-face))))))))
;;; Move here command
;; This is the inverse of `cider--debug-move-point'. However, that algorithm is
;; complicated, and trying to code its inverse would probably be insane.
;; Instead, we find the coordinate by trial and error.
(defun cider--debug-find-coordinates-for-point (target &optional list-so-far)
"Return the coordinates list for reaching TARGET.
Assumes that the next thing after point is a logical Clojure sexp and that
TARGET is inside it. The returned list is suitable for use in
`cider--debug-move-point'. LIST-SO-FAR is for internal use."
(when (looking-at (rx (or "(" "[" "#{" "{")))
(let ((starting-point (point)))
(unwind-protect
(let ((x 0))
;; Keep incrementing the last coordinate until we've moved
;; past TARGET.
(while (condition-case nil
(progn (goto-char starting-point)
(cider--debug-move-point (append list-so-far (list x)))
(< (point) target))
;; Not a valid coordinate. Move back a step and stop here.
(scan-error (setq x (1- x))
nil))
(setq x (1+ x)))
(setq list-so-far (append list-so-far (list x)))
;; We have moved past TARGET, now determine whether we should
;; stop, or if target is deeper inside the previous sexp.
(if (or (= target (point))
(progn (forward-sexp -1)
(<= target (point))))
list-so-far
(goto-char starting-point)
(cider--debug-find-coordinates-for-point target list-so-far)))
;; `unwind-protect' clause.
(goto-char starting-point)))))
(defun cider-debug-move-here (&optional force)
"Skip any breakpoints up to point.
The boolean value of FORCE will be sent in the reply."
(interactive (list (cider--uppercase-command-p)))
(unless cider--debug-mode
(user-error "`cider-debug-move-here' only makes sense during a debug session"))
(let ((here (point)))
(nrepl-dbind-response cider--debug-mode-response (line column)
(if (and line column (buffer-file-name))
(progn ;; Get to the proper line & column in the file
(forward-line (1- (- line (line-number-at-pos))))
(move-to-column column))
(beginning-of-defun))
;; Is HERE inside the sexp being debugged?
(when (or (< here (point))
(save-excursion
(forward-sexp 1)
(> here (point))))
(user-error "Point is outside the sexp being debugged"))
;; Move forward untill start of sexp.
(comment-normalize-vars)
(comment-forward (point-max))
;; Find the coordinate and send it.
(cider-debug-mode-send-reply
(format "{:response :here, :coord %s :force? %s}"
(cider--debug-find-coordinates-for-point here)
(if force "true" "false"))))))
;;; User commands
;;;###autoload
(defun cider-debug-defun-at-point ()
"Instrument the \"top-level\" expression at point.
If it is a defn, dispatch the instrumented definition. Otherwise,
immediately evaluate the instrumented expression.
While debugged code is being evaluated, the user is taken through the
source code and displayed the value of various expressions. At each step,
a number of keys will be prompted to the user."
(interactive)
(cider-eval-defun-at-point 'debug-it))
(provide 'cider-debug)
;;; cider-debug.el ends here

View file

@ -0,0 +1,533 @@
;;; cider-doc.el --- CIDER documentation functionality -*- lexical-binding: t -*-
;; Copyright © 2014-2018 Bozhidar Batsov, Jeff Valk and CIDER contributors
;; Author: Jeff Valk <jv@jeffvalk.com>
;; 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/>.
;; This file is not part of GNU Emacs.
;;; Commentary:
;; Mode for formatting and presenting documentation
;;; Code:
(require 'cider-common)
(require 'subr-x)
(require 'cider-compat)
(require 'cider-util)
(require 'cider-popup)
(require 'cider-client)
(require 'cider-grimoire)
(require 'nrepl-dict)
(require 'org-table)
(require 'button)
(require 'easymenu)
(require 'cider-browse-spec)
;;; Variables
(defgroup cider-doc nil
"Documentation for CIDER."
:prefix "cider-doc-"
:group 'cider)
(defcustom cider-doc-auto-select-buffer t
"Controls whether to auto-select the doc popup buffer."
:type 'boolean
:group 'cider-doc
:package-version '(cider . "0.15.0"))
(declare-function cider-apropos "cider-apropos")
(declare-function cider-apropos-select "cider-apropos")
(declare-function cider-apropos-documentation "cider-apropos")
(declare-function cider-apropos-documentation-select "cider-apropos")
(defvar cider-doc-map
(let (cider-doc-map)
(define-prefix-command 'cider-doc-map)
(define-key cider-doc-map (kbd "a") #'cider-apropos)
(define-key cider-doc-map (kbd "C-a") #'cider-apropos)
(define-key cider-doc-map (kbd "s") #'cider-apropos-select)
(define-key cider-doc-map (kbd "C-s") #'cider-apropos-select)
(define-key cider-doc-map (kbd "f") #'cider-apropos-documentation)
(define-key cider-doc-map (kbd "C-f") #'cider-apropos-documentation)
(define-key cider-doc-map (kbd "e") #'cider-apropos-documentation-select)
(define-key cider-doc-map (kbd "C-e") #'cider-apropos-documentation-select)
(define-key cider-doc-map (kbd "d") #'cider-doc)
(define-key cider-doc-map (kbd "C-d") #'cider-doc)
(define-key cider-doc-map (kbd "r") #'cider-grimoire)
(define-key cider-doc-map (kbd "C-r") #'cider-grimoire)
(define-key cider-doc-map (kbd "w") #'cider-grimoire-web)
(define-key cider-doc-map (kbd "C-w") #'cider-grimoire-web)
(define-key cider-doc-map (kbd "j") #'cider-javadoc)
(define-key cider-doc-map (kbd "C-j") #'cider-javadoc)
cider-doc-map)
"CIDER documentation keymap.")
(defconst cider-doc-menu
'("Documentation"
["CiderDoc" cider-doc]
["JavaDoc in browser" cider-javadoc]
["Grimoire" cider-grimoire]
["Grimoire in browser" cider-grimoire-web]
["Search symbols" cider-apropos]
["Search symbols & select" cider-apropos-select]
["Search documentation" cider-apropos-documentation]
["Search documentation & select" cider-apropos-documentation-select]
"--"
["Configure Doc buffer" (customize-group 'cider-docview-mode)])
"CIDER documentation submenu.")
;;; cider-docview-mode
(defgroup cider-docview-mode nil
"Formatting/fontifying documentation viewer."
:prefix "cider-docview-"
:group 'cider)
(defcustom cider-docview-fill-column fill-column
"Fill column for docstrings in doc buffer."
:type 'list
:group 'cider-docview-mode
:package-version '(cider . "0.7.0"))
;; Faces
(defface cider-docview-emphasis-face
'((t (:inherit default :underline t)))
"Face for emphasized text"
:group 'cider-docview-mode
:package-version '(cider . "0.7.0"))
(defface cider-docview-strong-face
'((t (:inherit default :underline t :weight bold)))
"Face for strongly emphasized text"
:group 'cider-docview-mode
:package-version '(cider . "0.7.0"))
(defface cider-docview-literal-face
'((t (:inherit font-lock-string-face)))
"Face for literal text"
:group 'cider-docview-mode
:package-version '(cider . "0.7.0"))
(defface cider-docview-table-border-face
'((t (:inherit shadow)))
"Face for table borders"
:group 'cider-docview-mode
:package-version '(cider . "0.7.0"))
;; Colors & Theme Support
(defvar cider-docview-code-background-color
(cider-scale-background-color)
"Background color for code blocks.")
(defadvice enable-theme (after cider-docview-adapt-to-theme activate)
"When theme is changed, update `cider-docview-code-background-color'."
(setq cider-docview-code-background-color (cider-scale-background-color)))
(defadvice disable-theme (after cider-docview-adapt-to-theme activate)
"When theme is disabled, update `cider-docview-code-background-color'."
(setq cider-docview-code-background-color (cider-scale-background-color)))
;; Mode & key bindings
(defvar cider-docview-mode-map
(let ((map (make-sparse-keymap)))
(define-key map "q" #'cider-popup-buffer-quit-function)
(define-key map "g" #'cider-docview-grimoire)
(define-key map "G" #'cider-docview-grimoire-web)
(define-key map "j" #'cider-docview-javadoc)
(define-key map "s" #'cider-docview-source)
(define-key map (kbd "<backtab>") #'backward-button)
(define-key map (kbd "TAB") #'forward-button)
(easy-menu-define cider-docview-mode-menu map
"Menu for CIDER's doc mode"
`("CiderDoc"
["Look up in Grimoire" cider-docview-grimoire]
["Look up in Grimoire (browser)" cider-docview-grimoire-web]
["JavaDoc in browser" cider-docview-javadoc]
["Jump to source" cider-docview-source]
"--"
["Quit" cider-popup-buffer-quit-function]
))
map))
(defvar cider-docview-symbol)
(defvar cider-docview-javadoc-url)
(defvar cider-docview-file)
(defvar cider-docview-line)
(define-derived-mode cider-docview-mode help-mode "Doc"
"Major mode for displaying CIDER documentation
\\{cider-docview-mode-map}"
(setq buffer-read-only t)
(setq-local sesman-system 'CIDER)
(when cider-special-mode-truncate-lines
(setq-local truncate-lines t))
(setq-local electric-indent-chars nil)
(setq-local cider-docview-symbol nil)
(setq-local cider-docview-javadoc-url nil)
(setq-local cider-docview-file nil)
(setq-local cider-docview-line nil))
;;; Interactive functions
(defun cider-docview-javadoc ()
"Open the Javadoc for the current class, if available."
(interactive)
(if cider-docview-javadoc-url
(browse-url cider-docview-javadoc-url)
(error "No Javadoc available for %s" cider-docview-symbol)))
(defun cider-javadoc-handler (symbol-name)
"Invoke the nREPL \"info\" op on SYMBOL-NAME if available."
(when symbol-name
(let* ((info (cider-var-info symbol-name))
(url (nrepl-dict-get info "javadoc")))
(if url
(browse-url url)
(user-error "No Javadoc available for %s" symbol-name)))))
(defun cider-javadoc (arg)
"Open Javadoc documentation in a popup buffer.
Prompts for the symbol to use, or uses the symbol at point, depending on
the value of `cider-prompt-for-symbol'. With prefix arg ARG, does the
opposite of what that option dictates."
(interactive "P")
(cider-ensure-connected)
(cider-ensure-op-supported "info")
(funcall (cider-prompt-for-symbol-function arg)
"Javadoc for"
#'cider-javadoc-handler))
(defun cider-docview-source ()
"Open the source for the current symbol, if available."
(interactive)
(if cider-docview-file
(if-let* ((buffer (and (not (cider--tooling-file-p cider-docview-file))
(cider-find-file cider-docview-file))))
(cider-jump-to buffer (if cider-docview-line
(cons cider-docview-line nil)
cider-docview-symbol)
nil)
(user-error
(substitute-command-keys
"Can't find the source because it wasn't defined with `cider-eval-buffer'")))
(error "No source location for %s" cider-docview-symbol)))
(defvar cider-buffer-ns)
(declare-function cider-grimoire-lookup "cider-grimoire")
(defun cider-docview-grimoire ()
"Return the grimoire documentation for `cider-docview-symbol'."
(interactive)
(if cider-buffer-ns
(cider-grimoire-lookup cider-docview-symbol)
(error "%s cannot be looked up on Grimoire" cider-docview-symbol)))
(declare-function cider-grimoire-web-lookup "cider-grimoire")
(defun cider-docview-grimoire-web ()
"Open the grimoire documentation for `cider-docview-symbol' in a web browser."
(interactive)
(if cider-buffer-ns
(cider-grimoire-web-lookup cider-docview-symbol)
(error "%s cannot be looked up on Grimoire" cider-docview-symbol)))
(defconst cider-doc-buffer "*cider-doc*")
(defun cider-create-doc-buffer (symbol)
"Populates *cider-doc* with the documentation for SYMBOL."
(when-let* ((info (cider-var-info symbol)))
(cider-docview-render (cider-make-popup-buffer cider-doc-buffer nil 'ancillary) symbol info)))
(defun cider-doc-lookup (symbol)
"Look up documentation for SYMBOL."
(if-let* ((buffer (cider-create-doc-buffer symbol)))
(cider-popup-buffer-display buffer cider-doc-auto-select-buffer)
(user-error "Symbol %s not resolved" symbol)))
(defun cider-doc (&optional arg)
"Open Clojure documentation in a popup buffer.
Prompts for the symbol to use, or uses the symbol at point, depending on
the value of `cider-prompt-for-symbol'. With prefix arg ARG, does the
opposite of what that option dictates."
(interactive "P")
(cider-ensure-connected)
(funcall (cider-prompt-for-symbol-function arg)
"Doc for"
#'cider-doc-lookup))
;;; Font Lock and Formatting
(defun cider-docview-fontify-code-blocks (buffer mode)
"Font lock BUFFER code blocks using MODE and remove markdown characters.
This processes the triple backtick GFM markdown extension. An overlay is used
to shade the background. Blocks are marked to be ignored by other fonification
and line wrap."
(with-current-buffer buffer
(save-excursion
(while (search-forward-regexp "```\n" nil t)
(replace-match "")
(let ((beg (point))
(bg `(:background ,cider-docview-code-background-color)))
(when (search-forward-regexp "```\n" nil t)
(replace-match "")
(cider-font-lock-region-as mode beg (point))
(overlay-put (make-overlay beg (point)) 'font-lock-face bg)
(put-text-property beg (point) 'block 'code)))))))
(defun cider-docview-fontify-literals (buffer)
"Font lock BUFFER literal text and remove backtick markdown characters.
Preformatted code text blocks are ignored."
(with-current-buffer buffer
(save-excursion
(while (search-forward "`" nil t)
(if (eq (get-text-property (point) 'block) 'code)
(forward-char)
(progn
(replace-match "")
(let ((beg (point)))
(when (search-forward "`" (line-end-position) t)
(replace-match "")
(put-text-property beg (point) 'font-lock-face 'cider-docview-literal-face)))))))))
(defun cider-docview-fontify-emphasis (buffer)
"Font lock BUFFER emphasized text and remove markdown characters.
One '*' represents emphasis, multiple '**'s represent strong emphasis.
Preformatted code text blocks are ignored."
(with-current-buffer buffer
(save-excursion
(while (search-forward-regexp "\\(*+\\)\\(\\w\\)" nil t)
(if (eq (get-text-property (point) 'block) 'code)
(forward-char)
(progn
(replace-match "\\2")
(let ((beg (1- (point)))
(face (if (> (length (match-string 1)) 1)
'cider-docview-strong-face
'cider-docview-emphasis-face)))
(when (search-forward-regexp "\\(\\w\\)\\*+" (line-end-position) t)
(replace-match "\\1")
(put-text-property beg (point) 'font-lock-face face)))))))))
(defun cider-docview-format-tables (buffer)
"Align BUFFER tables and dim borders.
This processes the GFM table markdown extension using `org-table'.
Tables are marked to be ignored by line wrap."
(with-current-buffer buffer
(save-excursion
(let ((border 'cider-docview-table-border-face))
(org-table-map-tables
(lambda ()
(org-table-align)
(goto-char (org-table-begin))
(while (search-forward-regexp "[+|-]" (org-table-end) t)
(put-text-property (match-beginning 0) (match-end 0) 'font-lock-face border))
(put-text-property (org-table-begin) (org-table-end) 'block 'table)))))))
(defun cider-docview-wrap-text (buffer)
"For text in BUFFER not propertized as 'block', apply line wrap."
(with-current-buffer buffer
(save-excursion
(while (not (eobp))
(unless (get-text-property (point) 'block)
(fill-region (point) (line-end-position)))
(forward-line)))))
;;; Rendering
(defun cider-docview-render-java-doc (buffer text)
"Emit into BUFFER formatted doc TEXT for a Java class or member."
(with-current-buffer buffer
(let ((beg (point)))
(insert text)
(save-excursion
(goto-char beg)
(cider-docview-fontify-code-blocks buffer 'java-mode) ; left alone hereafter
(cider-docview-fontify-literals buffer)
(cider-docview-fontify-emphasis buffer)
(cider-docview-format-tables buffer) ; may contain literals, emphasis
(cider-docview-wrap-text buffer))))) ; ignores code, table blocks
(defun cider--abbreviate-file-protocol (file-with-protocol)
"Abbreviate the file-path in `file:/path/to/file' of FILE-WITH-PROTOCOL."
(if (string-match "\\`file:\\(.*\\)" file-with-protocol)
(let ((file (match-string 1 file-with-protocol))
(proj-dir (clojure-project-dir)))
(if (and proj-dir
(file-in-directory-p file proj-dir))
(file-relative-name file proj-dir)
file))
file-with-protocol))
(defun cider-docview-render-info (buffer info)
"Emit into BUFFER formatted INFO for the Clojure or Java symbol."
(let* ((ns (nrepl-dict-get info "ns"))
(name (nrepl-dict-get info "name"))
(added (nrepl-dict-get info "added"))
(depr (nrepl-dict-get info "deprecated"))
(macro (nrepl-dict-get info "macro"))
(special (nrepl-dict-get info "special-form"))
(forms (when-let* ((str (nrepl-dict-get info "forms-str")))
(split-string str "\n")))
(args (when-let* ((str (nrepl-dict-get info "arglists-str")))
(split-string str "\n")))
(doc (or (nrepl-dict-get info "doc")
"Not documented."))
(url (nrepl-dict-get info "url"))
(class (nrepl-dict-get info "class"))
(member (nrepl-dict-get info "member"))
(javadoc (nrepl-dict-get info "javadoc"))
(super (nrepl-dict-get info "super"))
(ifaces (nrepl-dict-get info "interfaces"))
(spec (nrepl-dict-get info "spec"))
(clj-name (if ns (concat ns "/" name) name))
(java-name (if member (concat class "/" member) class))
(see-also (nrepl-dict-get info "see-also")))
(cider--help-setup-xref (list #'cider-doc-lookup (format "%s/%s" ns name)) nil buffer)
(with-current-buffer buffer
(cl-flet ((emit (text &optional face)
(insert (if face
(propertize text 'font-lock-face face)
text)
"\n")))
(emit (if class java-name clj-name) 'font-lock-function-name-face)
(when super
(emit (concat " Extends: " (cider-font-lock-as 'java-mode super))))
(when ifaces
(emit (concat "Implements: " (cider-font-lock-as 'java-mode (car ifaces))))
(dolist (iface (cdr ifaces))
(emit (concat " "(cider-font-lock-as 'java-mode iface)))))
(when (or super ifaces)
(insert "\n"))
(when-let* ((forms (or forms args)))
(dolist (form forms)
(insert " ")
(emit (cider-font-lock-as-clojure form))))
(when special
(emit "Special Form" 'font-lock-keyword-face))
(when macro
(emit "Macro" 'font-lock-variable-name-face))
(when added
(emit (concat "Added in " added) 'font-lock-comment-face))
(when depr
(emit (concat "Deprecated in " depr) 'font-lock-keyword-face))
(if class
(cider-docview-render-java-doc (current-buffer) doc)
(emit (concat " " doc)))
(when url
(insert "\n Please see ")
(insert-text-button url
'url url
'follow-link t
'action (lambda (x)
(browse-url (button-get x 'url))))
(insert "\n"))
(when javadoc
(insert "\n\nFor additional documentation, see the ")
(insert-text-button "Javadoc"
'url javadoc
'follow-link t
'action (lambda (x)
(browse-url (button-get x 'url))))
(insert ".\n"))
(insert "\n")
(when spec
(emit "Spec:" 'font-lock-function-name-face)
(insert (cider-browse-spec--pprint-indented spec))
(insert "\n\n")
(insert-text-button "Browse spec"
'follow-link t
'action (lambda (_)
(cider-browse-spec (format "%s/%s" ns name))))
(insert "\n\n"))
(if cider-docview-file
(progn
(insert (propertize (if class java-name clj-name)
'font-lock-face 'font-lock-function-name-face)
" is defined in ")
(insert-text-button (cider--abbreviate-file-protocol cider-docview-file)
'follow-link t
'action (lambda (_x)
(cider-docview-source)))
(insert "."))
(insert "Definition location unavailable."))
(when see-also
(insert "\n\n Also see: ")
(mapc (lambda (ns-sym)
(let* ((ns-sym-split (split-string ns-sym "/"))
(see-also-ns (car ns-sym-split))
(see-also-sym (cadr ns-sym-split))
;; if the var belongs to the same namespace,
;; we omit the namespace to save some screen space
(symbol (if (equal ns see-also-ns) see-also-sym ns-sym)))
(insert-text-button symbol
'type 'help-xref
'help-function (apply-partially #'cider-doc-lookup symbol)))
(insert " "))
see-also))
(cider--doc-make-xrefs)
(let ((beg (point-min))
(end (point-max)))
(nrepl-dict-map (lambda (k v)
(put-text-property beg end k v))
info)))
(current-buffer))))
(declare-function cider-set-buffer-ns "cider-mode")
(defun cider-docview-render (buffer symbol info)
"Emit into BUFFER formatted documentation for SYMBOL's INFO."
(with-current-buffer buffer
(let ((javadoc (nrepl-dict-get info "javadoc"))
(file (nrepl-dict-get info "file"))
(line (nrepl-dict-get info "line"))
(ns (nrepl-dict-get info "ns"))
(inhibit-read-only t))
(cider-docview-mode)
(cider-set-buffer-ns ns)
(setq-local cider-docview-symbol symbol)
(setq-local cider-docview-javadoc-url javadoc)
(setq-local cider-docview-file file)
(setq-local cider-docview-line line)
(remove-overlays)
(cider-docview-render-info buffer info)
(goto-char (point-min))
(current-buffer))))
(provide 'cider-doc)
;;; cider-doc.el ends here

View file

@ -0,0 +1,481 @@
;;; cider-eldoc.el --- eldoc support for Clojure -*- lexical-binding: t -*-
;; Copyright © 2012-2013 Tim King, Phil Hagelberg, Bozhidar Batsov
;; Copyright © 2013-2018 Bozhidar Batsov, Artur Malabarba and CIDER contributors
;;
;; Author: Tim King <kingtim@gmail.com>
;; Phil Hagelberg <technomancy@gmail.com>
;; Bozhidar Batsov <bozhidar@batsov.com>
;; Artur Malabarba <bruce.connor.am@gmail.com>
;; Hugo Duncan <hugo@hugoduncan.org>
;; Steve Purcell <steve@sanityinc.com>
;; 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/>.
;; This file is not part of GNU Emacs.
;;; Commentary:
;; eldoc support for Clojure.
;;; Code:
(require 'cider-client)
(require 'cider-common) ; for cider-symbol-at-point
(require 'subr-x)
(require 'cider-compat)
(require 'cider-util)
(require 'nrepl-dict)
(require 'seq)
(require 'eldoc)
(defvar cider-extra-eldoc-commands '("yas-expand")
"Extra commands to be added to eldoc's safe commands list.")
(defcustom cider-eldoc-max-num-sexps-to-skip 30
"The maximum number of sexps to skip while searching the beginning of current sexp."
:type 'integer
:group 'cider
:package-version '(cider . "0.10.1"))
(defvar-local cider-eldoc-last-symbol nil
"The eldoc information for the last symbol we checked.")
(defcustom cider-eldoc-ns-function #'identity
"A function that returns a ns string to be used by eldoc.
Takes one argument, a namespace name.
For convenience, some functions are already provided for this purpose:
`cider-abbreviate-ns', and `cider-last-ns-segment'."
:type '(choice (const :tag "Full namespace" identity)
(const :tag "Abbreviated namespace" cider-abbreviate-ns)
(const :tag "Last name in namespace" cider-last-ns-segment)
(function :tag "Custom function"))
:group 'cider
:package-version '(cider . "0.13.0"))
(defcustom cider-eldoc-max-class-names-to-display 3
"The maximum number of classes to display in an eldoc string.
An eldoc string for Java interop forms can have a number of classes prefixed to
it, when the form belongs to more than 1 class. When, not nil we only display
the names of first `cider-eldoc-max-class-names-to-display' classes and add
a \"& x more\" suffix. Otherwise, all the classes are displayed."
:type 'integer
:safe #'integerp
:group 'cider
:package-version '(cider . "0.13.0"))
(defcustom cider-eldoc-display-for-symbol-at-point t
"When non-nil, display eldoc for symbol at point if available.
So in (map inc ...) when the cursor is over inc its eldoc would be
displayed. When nil, always display eldoc for first symbol of the sexp."
:type 'boolean
:safe #'booleanp
:group 'cider
:package-version '(cider . "0.13.0"))
(defcustom cider-eldoc-display-context-dependent-info nil
"When non-nil, display context dependent info in the eldoc where possible.
CIDER will try to add expected function arguments based on the current context,
for example for the datomic.api/q function where it will show the expected
inputs of the query at point."
:type 'boolean
:group 'cider
:package-version '(cider . "0.15.0"))
(defun cider--eldoc-format-class-names (class-names)
"Return a formatted CLASS-NAMES prefix string.
CLASS-NAMES is a list of classes to which a Java interop form belongs.
Only keep the first `cider-eldoc-max-class-names-to-display' names, and
add a \"& x more\" suffix. Return nil if the CLASS-NAMES list is empty or
mapping `cider-eldoc-ns-function' on it returns an empty list."
(when-let* ((eldoc-class-names (seq-remove #'null (mapcar (apply-partially cider-eldoc-ns-function) class-names)))
(eldoc-class-names-length (length eldoc-class-names)))
(cond
;; truncate class-names list and then format it
((and cider-eldoc-max-class-names-to-display
(> eldoc-class-names-length cider-eldoc-max-class-names-to-display))
(format "(%s & %s more)"
(thread-first eldoc-class-names
(seq-take cider-eldoc-max-class-names-to-display)
(string-join " ")
(cider-propertize 'ns))
(- eldoc-class-names-length cider-eldoc-max-class-names-to-display)))
;; format the whole list but add surrounding parentheses
((> eldoc-class-names-length 1)
(format "(%s)"
(thread-first eldoc-class-names
(string-join " ")
(cider-propertize 'ns))))
;; don't add the parentheses
(t (format "%s" (car eldoc-class-names))))))
(defun cider-eldoc-format-thing (ns symbol thing type)
"Format the eldoc subject defined by NS, SYMBOL, THING and TYPE.
THING represents the thing at point which triggered eldoc. Normally NS and
SYMBOL are used (they are derived from THING), but when empty we fallback to
THING (e.g. for Java methods). Format it as a function, if FUNCTION-P
is non-nil. Else format it as a variable."
(if-let* ((method-name (if (and symbol (not (string= symbol "")))
symbol
thing))
(propertized-method-name (cider-propertize method-name type))
(ns-or-class (if (and ns (stringp ns))
(funcall cider-eldoc-ns-function ns)
(cider--eldoc-format-class-names ns))))
(format "%s/%s"
;; we set font-lock properties of classes in `cider--eldoc-format-class-names'
;; to avoid font locking the parentheses and "& x more"
;; so we only propertize ns-or-class if not already done
(if (get-text-property 1 'face ns-or-class)
;; it is already propertized
ns-or-class
(cider-propertize ns-or-class 'ns))
propertized-method-name)
;; in case ns-or-class is nil
propertized-method-name))
(defun cider-eldoc-format-sym-doc (var ns docstring)
"Return the formatted eldoc string for VAR and DOCSTRING.
Consider the value of `eldoc-echo-area-use-multiline-p' while formatting.
If the entire line cannot fit in the echo area, the var name may be
truncated or eliminated entirely from the output to make room for the
description.
Try to truncate the var with various strategies, so that the var and
the docstring can be displayed in the minibuffer without resizing the window.
We start with `cider-abbreviate-ns' and `cider-last-ns-segment'.
Next, if the var is in current namespace, we remove NS from the eldoc string.
Otherwise, only the docstring is returned."
(let* ((ea-multi eldoc-echo-area-use-multiline-p)
;; Subtract 1 from window width since emacs will not write
;; any chars to the last column, or in later versions, will
;; cause a wraparound and resize of the echo area.
(ea-width (1- (window-width (minibuffer-window))))
(strip (- (+ (length var) (length docstring)) ea-width))
(newline (string-match-p "\n" docstring))
;; Truncated var can be ea-var long
;; Subtract 2 to account for the : and / added when including
;; the namespace prefixed form in eldoc string
(ea-var (- (- ea-width (length docstring)) 2)))
(cond
((or (eq ea-multi t)
(and (<= strip 0) (null newline))
(and ea-multi (or (> (length docstring) ea-width) newline)))
(format "%s: %s" var docstring))
;; Now we have to truncate either the docstring or the var
(newline (cider-eldoc-format-sym-doc var ns (substring docstring 0 newline)))
;; Only return the truncated docstring
((> (length docstring) ea-width)
(substring docstring 0 ea-width))
;; Try to truncate the var with cider-abbreviate-ns
((<= (length (cider-abbreviate-ns var)) ea-var)
(format "%s: %s" (cider-abbreviate-ns var) docstring))
;; Try to truncate var with cider-last-ns-segment
((<= (length (cider-last-ns-segment var)) ea-var)
(format "%s: %s" (cider-last-ns-segment var) docstring))
;; If the var is in current namespace, we try to truncate the var by
;; skipping the namespace from the returned eldoc string
((and (string-equal ns (cider-current-ns))
(<= (- (length var) (length ns)) ea-var))
(format "%s: %s"
(replace-regexp-in-string (format "%s/" ns) "" var)
docstring))
;; We couldn't fit the var and docstring in the available space,
;; so we just display the docstring
(t docstring))))
(defun cider-eldoc-format-variable (thing eldoc-info)
"Return the formatted eldoc string for a variable.
THING is the variable name. ELDOC-INFO is a p-list containing the eldoc
information."
(let* ((ns (lax-plist-get eldoc-info "ns"))
(symbol (lax-plist-get eldoc-info "symbol"))
(docstring (lax-plist-get eldoc-info "docstring"))
(formatted-var (cider-eldoc-format-thing ns symbol thing 'var)))
(when docstring
(cider-eldoc-format-sym-doc formatted-var ns docstring))))
(defun cider-eldoc-format-function (thing pos eldoc-info)
"Return the formatted eldoc string for a function.
THING is the function name. POS is the argument-index of the functions
arglists. ELDOC-INFO is a p-list containing the eldoc information."
(let ((ns (lax-plist-get eldoc-info "ns"))
(symbol (lax-plist-get eldoc-info "symbol"))
(arglists (lax-plist-get eldoc-info "arglists")))
(format "%s: %s"
(cider-eldoc-format-thing ns symbol thing 'fn)
(cider-eldoc-format-arglist arglists pos))))
(defun cider-highlight-args (arglist pos)
"Format the the function ARGLIST for eldoc.
POS is the index of the currently highlighted argument."
(let* ((rest-pos (cider--find-rest-args-position arglist))
(i 0))
(mapconcat
(lambda (arg)
(let ((argstr (format "%s" arg)))
(if (string= arg "&")
argstr
(prog1
(if (or (= (1+ i) pos)
(and rest-pos
(> (1+ i) rest-pos)
(> pos rest-pos)))
(propertize argstr 'face
'eldoc-highlight-function-argument)
argstr)
(setq i (1+ i)))))) arglist " ")))
(defun cider--find-rest-args-position (arglist)
"Find the position of & in the ARGLIST vector."
(seq-position arglist "&"))
(defun cider-highlight-arglist (arglist pos)
"Format the ARGLIST for eldoc.
POS is the index of the argument to highlight."
(concat "[" (cider-highlight-args arglist pos) "]"))
(defun cider-eldoc-format-arglist (arglist pos)
"Format all the ARGLIST for eldoc.
POS is the index of current argument."
(concat "("
(mapconcat (lambda (args) (cider-highlight-arglist args pos))
arglist
" ")
")"))
(defun cider-eldoc-beginning-of-sexp ()
"Move to the beginning of current sexp.
Return the number of nested sexp the point was over or after. Return nil
if the maximum number of sexps to skip is exceeded."
(let ((parse-sexp-ignore-comments t)
(num-skipped-sexps 0))
(condition-case _
(progn
;; First account for the case the point is directly over a
;; beginning of a nested sexp.
(condition-case _
(let ((p (point)))
(forward-sexp -1)
(forward-sexp 1)
(when (< (point) p)
(setq num-skipped-sexps 1)))
(error))
(while
(let ((p (point)))
(forward-sexp -1)
(when (< (point) p)
(setq num-skipped-sexps
(unless (and cider-eldoc-max-num-sexps-to-skip
(>= num-skipped-sexps
cider-eldoc-max-num-sexps-to-skip))
;; Without the above guard,
;; `cider-eldoc-beginning-of-sexp' could traverse the
;; whole buffer when the point is not within a
;; list. This behavior is problematic especially with
;; a buffer containing a large number of
;; non-expressions like a REPL buffer.
(1+ num-skipped-sexps)))))))
(error))
num-skipped-sexps))
(defun cider-eldoc-thing-type (eldoc-info)
"Return the type of the ELDOC-INFO being displayed by eldoc.
It can be a function or var now."
(pcase (lax-plist-get eldoc-info "type")
("function" 'fn)
("variable" 'var)))
(defun cider-eldoc-info-at-point ()
"Return eldoc info at point.
First go to the beginning of the sexp and check if the eldoc is to be
considered (i.e sexp is a method call) and not a map or vector literal.
Then go back to the point and return its eldoc."
(save-excursion
(unless (cider-in-comment-p)
(let* ((current-point (point)))
(cider-eldoc-beginning-of-sexp)
(unless (member (or (char-before (point)) 0) '(?\" ?\{ ?\[))
(goto-char current-point)
(when-let* ((eldoc-info (cider-eldoc-info
(cider--eldoc-remove-dot (cider-symbol-at-point)))))
`("eldoc-info" ,eldoc-info
"thing" ,(cider-symbol-at-point)
"pos" 0)))))))
(defun cider-eldoc-info-at-sexp-beginning ()
"Return eldoc info for first symbol in the sexp."
(save-excursion
(when-let* ((beginning-of-sexp (cider-eldoc-beginning-of-sexp))
;; If we are at the beginning of function name, this will be -1
(argument-index (max 0 (1- beginning-of-sexp))))
(unless (or (memq (or (char-before (point)) 0)
'(?\" ?\{ ?\[))
(cider-in-comment-p))
(when-let* ((eldoc-info (cider-eldoc-info
(cider--eldoc-remove-dot (cider-symbol-at-point)))))
`("eldoc-info" ,eldoc-info
"thing" ,(cider-symbol-at-point)
"pos" ,argument-index))))))
(defun cider-eldoc-info-in-current-sexp ()
"Return eldoc information from the sexp.
If `cider-eldoc-display-for-symbol-at-poin' is non-nil and
the symbol at point has a valid eldoc available, return that.
Otherwise return the eldoc of the first symbol of the sexp."
(or (when cider-eldoc-display-for-symbol-at-point
(cider-eldoc-info-at-point))
(cider-eldoc-info-at-sexp-beginning)))
(defun cider-eldoc--convert-ns-keywords (thing)
"Convert THING values that match ns macro keywords to function names."
(pcase thing
(":import" "clojure.core/import")
(":refer-clojure" "clojure.core/refer-clojure")
(":use" "clojure.core/use")
(":refer" "clojure.core/refer")
(_ thing)))
(defun cider-eldoc-info (thing)
"Return the info for THING.
This includes the arglist and ns and symbol name (if available)."
(let ((thing (cider-eldoc--convert-ns-keywords thing)))
(when (and (cider-nrepl-op-supported-p "eldoc")
thing
;; ignore empty strings
(not (string= thing ""))
;; ignore strings
(not (string-prefix-p "\"" thing))
;; ignore regular expressions
(not (string-prefix-p "#" thing))
;; ignore chars
(not (string-prefix-p "\\" thing))
;; ignore numbers
(not (string-match-p "^[0-9]" thing)))
;; check if we can used the cached eldoc info
(cond
;; handle keywords for map access
((string-prefix-p ":" thing) (list "symbol" thing
"type" "function"
"arglists" '(("map") ("map" "not-found"))))
;; handle Classname. by displaying the eldoc for new
((string-match-p "^[A-Z].+\\.$" thing) (list "symbol" thing
"type" "function"
"arglists" '(("args*"))))
;; generic case
(t (if (equal thing (car cider-eldoc-last-symbol))
(cadr cider-eldoc-last-symbol)
(when-let* ((eldoc-info (cider-sync-request:eldoc thing)))
(let* ((arglists (nrepl-dict-get eldoc-info "eldoc"))
(docstring (nrepl-dict-get eldoc-info "docstring"))
(type (nrepl-dict-get eldoc-info "type"))
(ns (nrepl-dict-get eldoc-info "ns"))
(class (nrepl-dict-get eldoc-info "class"))
(name (nrepl-dict-get eldoc-info "name"))
(member (nrepl-dict-get eldoc-info "member"))
(ns-or-class (if (and ns (not (string= ns "")))
ns
class))
(name-or-member (if (and name (not (string= name "")))
name
(format ".%s" member)))
(eldoc-plist (list "ns" ns-or-class
"symbol" name-or-member
"arglists" arglists
"docstring" docstring
"type" type)))
;; add context dependent args if requested by defcustom
;; do not cache this eldoc info to avoid showing info
;: of the previous context
(if cider-eldoc-display-context-dependent-info
(cond
;; add inputs of datomic query
((and (equal ns-or-class "datomic.api")
(equal name-or-member "q"))
(let ((arglists (lax-plist-get eldoc-plist "arglists")))
(lax-plist-put eldoc-plist "arglists"
(cider--eldoc-add-datomic-query-inputs-to-arglists arglists))))
;; if none of the clauses is successful, do cache the eldoc
(t (setq cider-eldoc-last-symbol (list thing eldoc-plist))))
;; middleware eldoc lookups are expensive, so we
;; cache the last lookup. This eliminates the need
;; for extra middleware requests within the same sexp.
(setq cider-eldoc-last-symbol (list thing eldoc-plist)))
eldoc-plist))))))))
(defun cider--eldoc-remove-dot (sym)
"Remove the preceding \".\" from a namespace qualified SYM and return sym.
Only useful for interop forms. Clojure forms would be returned unchanged."
(when sym (replace-regexp-in-string "/\\." "/" sym)))
(defun cider--eldoc-edn-file-p (file-name)
"Check whether FILE-NAME is representing an EDN file."
(and file-name (equal (file-name-extension file-name) "edn")))
(defun cider--eldoc-add-datomic-query-inputs-to-arglists (arglists)
"Add the expected inputs of the datomic query to the ARGLISTS."
(if (cider-second-sexp-in-list)
(let* ((query (cider-second-sexp-in-list))
(query-inputs (nrepl-dict-get
(cider-sync-request:eldoc-datomic-query query)
"inputs")))
(if query-inputs
(thread-first
(thread-last arglists
(car)
(remove "&")
(remove "inputs"))
(append (car query-inputs))
(list))
arglists))
arglists))
(defun cider-eldoc ()
"Backend function for eldoc to show argument list in the echo area."
(when (and (cider-connected-p)
;; don't clobber an error message in the minibuffer
(not (member last-command '(next-error previous-error)))
;; don't try to provide eldoc in EDN buffers
(not (cider--eldoc-edn-file-p buffer-file-name)))
(let* ((sexp-eldoc-info (cider-eldoc-info-in-current-sexp))
(eldoc-info (lax-plist-get sexp-eldoc-info "eldoc-info"))
(pos (lax-plist-get sexp-eldoc-info "pos"))
(thing (lax-plist-get sexp-eldoc-info "thing")))
(when eldoc-info
(if (equal (cider-eldoc-thing-type eldoc-info) 'fn)
(cider-eldoc-format-function thing pos eldoc-info)
(cider-eldoc-format-variable thing eldoc-info))))))
(defun cider-eldoc-setup ()
"Setup eldoc in the current buffer.
eldoc mode has to be enabled for this to have any effect."
(setq-local eldoc-documentation-function #'cider-eldoc)
(apply #'eldoc-add-command cider-extra-eldoc-commands))
(provide 'cider-eldoc)
;;; cider-eldoc.el ends here

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,220 @@
;;; cider-find.el --- Functionality for finding things -*- lexical-binding: t -*-
;; Copyright © 2013-2018 Bozhidar Batsov, Artur Malabarba and CIDER contributors
;;
;; Author: Bozhidar Batsov <bozhidar@batsov.com>
;; Artur Malabarba <bruce.connor.am@gmail.com>
;; 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/>.
;; This file is not part of GNU Emacs.
;;; Commentary:
;; A bunch of commands for finding resources and definitions.
;;; Code:
(require 'cider-client)
(require 'cider-common)
(require 'thingatpt)
(defun cider--find-var-other-window (var &optional line)
"Find the definition of VAR, optionally at a specific LINE.
Display the results in a different window."
(if-let* ((info (cider-var-info var)))
(progn
(if line (setq info (nrepl-dict-put info "line" line)))
(cider--jump-to-loc-from-info info t))
(user-error "Symbol `%s' not resolved" var)))
(defun cider--find-var (var &optional line)
"Find the definition of VAR, optionally at a specific LINE."
(if-let* ((info (cider-var-info var)))
(progn
(if line (setq info (nrepl-dict-put info "line" line)))
(cider--jump-to-loc-from-info info))
(user-error "Symbol `%s' not resolved" var)))
;;;###autoload
(defun cider-find-var (&optional arg var line)
"Find definition for VAR at LINE.
Prompt according to prefix ARG and `cider-prompt-for-symbol'.
A single or double prefix argument inverts the meaning of
`cider-prompt-for-symbol'. A prefix of `-` or a double prefix argument causes
the results to be displayed in a different window. The default value is
thing at point."
(interactive "P")
(cider-ensure-op-supported "info")
(if var
(cider--find-var var line)
(funcall (cider-prompt-for-symbol-function arg)
"Symbol"
(if (cider--open-other-window-p arg)
#'cider--find-var-other-window
#'cider--find-var))))
(defun cider--find-dwim (symbol-file callback &optional other-window)
"Find the SYMBOL-FILE at point.
CALLBACK upon failure to invoke prompt if not prompted previously.
Show results in a different window if OTHER-WINDOW is true."
(if-let* ((info (cider-var-info symbol-file)))
(cider--jump-to-loc-from-info info other-window)
(progn
(cider-ensure-op-supported "resource")
(if-let* ((resource (cider-sync-request:resource symbol-file))
(buffer (cider-find-file resource)))
(cider-jump-to buffer 0 other-window)
(if (cider--prompt-for-symbol-p current-prefix-arg)
(error "Resource or var %s not resolved" symbol-file)
(let ((current-prefix-arg (if current-prefix-arg nil '(4))))
(call-interactively callback)))))))
(defun cider--find-dwim-interactive (prompt)
"Get interactive arguments for jump-to functions using PROMPT as needed."
(if (cider--prompt-for-symbol-p current-prefix-arg)
(list
(cider-read-from-minibuffer prompt (thing-at-point 'filename)))
(list (or (thing-at-point 'filename) "")))) ; No prompt.
(defun cider-find-dwim-other-window (symbol-file)
"Jump to SYMBOL-FILE at point, place results in other window."
(interactive (cider--find-dwim-interactive "Jump to: "))
(cider--find-dwim symbol-file 'cider-find-dwim-other-window t))
;;;###autoload
(defun cider-find-dwim (symbol-file)
"Find and display the SYMBOL-FILE at point.
SYMBOL-FILE could be a var or a resource. If thing at point is empty then
show dired on project. If var is not found, try to jump to resource of the
same name. When called interactively, a prompt is given according to the
variable `cider-prompt-for-symbol'. A single or double prefix argument
inverts the meaning. A prefix of `-' or a double prefix argument causes
the results to be displayed in a different window. A default value of thing
at point is given when prompted."
(interactive (cider--find-dwim-interactive "Jump to: "))
(cider--find-dwim symbol-file `cider-find-dwim
(cider--open-other-window-p current-prefix-arg)))
;;;###autoload
(defun cider-find-resource (path)
"Find the resource at PATH.
Prompt for input as indicated by the variable `cider-prompt-for-symbol'.
A single or double prefix argument inverts the meaning of
`cider-prompt-for-symbol'. A prefix argument of `-` or a double prefix
argument causes the results to be displayed in other window. The default
value is thing at point."
(interactive
(list
(if (cider--prompt-for-symbol-p current-prefix-arg)
(completing-read "Resource: "
(cider-sync-request:resources-list)
nil nil
(thing-at-point 'filename))
(or (thing-at-point 'filename) ""))))
(cider-ensure-op-supported "resource")
(when (= (length path) 0)
(error "Cannot find resource for empty path"))
(if-let* ((resource (cider-sync-request:resource path))
(buffer (cider-find-file resource)))
(cider-jump-to buffer nil (cider--open-other-window-p current-prefix-arg))
(if (cider--prompt-for-symbol-p current-prefix-arg)
(error "Cannot find resource %s" path)
(let ((current-prefix-arg (cider--invert-prefix-arg current-prefix-arg)))
(call-interactively 'cider-find-resource)))))
(defun cider--invert-prefix-arg (arg)
"Invert the effect of prefix value ARG on `cider-prompt-for-symbol'.
This function preserves the `other-window' meaning of ARG."
(let ((narg (prefix-numeric-value arg)))
(pcase narg
(16 -1) ; empty empty -> -
(-1 16) ; - -> empty empty
(4 nil) ; empty -> no-prefix
(_ 4)))) ; no-prefix -> empty
(defun cider--prefix-invert-prompt-p (arg)
"Test prefix value ARG for its effect on `cider-prompt-for-symbol`."
(let ((narg (prefix-numeric-value arg)))
(pcase narg
(16 t) ; empty empty
(4 t) ; empty
(_ nil))))
(defun cider--prompt-for-symbol-p (&optional prefix)
"Check if cider should prompt for symbol.
Tests againsts PREFIX and the value of `cider-prompt-for-symbol'.
Invert meaning of `cider-prompt-for-symbol' if PREFIX indicates it should be."
(if (cider--prefix-invert-prompt-p prefix)
(not cider-prompt-for-symbol) cider-prompt-for-symbol))
(defun cider--find-ns (ns &optional other-window)
"Find the file containing NS's definition.
Optionally open it in a different window if OTHER-WINDOW is truthy."
(if-let* ((path (cider-sync-request:ns-path ns)))
(cider-jump-to (cider-find-file path) nil other-window)
(user-error "Can't find namespace `%s'" ns)))
;;;###autoload
(defun cider-find-ns (&optional arg ns)
"Find the file containing NS.
A prefix ARG of `-` or a double prefix argument causes
the results to be displayed in a different window."
(interactive "P")
(cider-ensure-connected)
(cider-ensure-op-supported "ns-path")
(if ns
(cider--find-ns ns)
(let* ((namespaces (cider-sync-request:ns-list))
(ns (completing-read "Find namespace: " namespaces)))
(cider--find-ns ns (cider--open-other-window-p arg)))))
;;;###autoload
(defun cider-find-keyword (&optional arg)
"Find the namespace of the keyword at point and its first occurrence there.
For instance - if the keyword at point is \":cider.demo/keyword\", this command
would find the namespace \"cider.demo\" and afterwards find the first mention
of \"::keyword\" there.
Prompt according to prefix ARG and `cider-prompt-for-symbol'.
A single or double prefix argument inverts the meaning of
`cider-prompt-for-symbol'. A prefix of `-` or a double prefix argument causes
the results to be displayed in a different window. The default value is
thing at point."
(interactive "P")
(cider-ensure-connected)
(let* ((kw (let ((kw-at-point (cider-symbol-at-point 'look-back)))
(if (or cider-prompt-for-symbol arg)
(read-string
(format "Keyword (default %s): " kw-at-point)
nil nil kw-at-point)
kw-at-point)))
(ns-qualifier (and
(string-match "^:+\\(.+\\)/.+$" kw)
(match-string 1 kw)))
(kw-ns (if ns-qualifier
(cider-resolve-alias (cider-current-ns) ns-qualifier)
(cider-current-ns)))
(kw-to-find (concat "::" (replace-regexp-in-string "^:+\\(.+/\\)?" "" kw))))
(when (and ns-qualifier (string= kw-ns (cider-current-ns)))
(error "Could not resolve alias `%s' in `%s'" ns-qualifier (cider-current-ns)))
(cider--find-ns kw-ns arg)
(search-forward-regexp kw-to-find nil 'noerror)))
(provide 'cider-find)
;;; cider-find.el ends here

View file

@ -0,0 +1,150 @@
;;; cider-format.el --- Code and EDN formatting functionality -*- lexical-binding: t -*-
;; Copyright © 2013-2018 Bozhidar Batsov, Artur Malabarba and CIDER contributors
;;
;; Author: Bozhidar Batsov <bozhidar@batsov.com>
;; Artur Malabarba <bruce.connor.am@gmail.com>
;; 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/>.
;; This file is not part of GNU Emacs.
;;; Commentary:
;; Middleware-powered code and EDN formatting functionality.
;;; Code:
(require 'subr-x)
(require 'cider-client)
(require 'cider-util)
;; Format
(defun cider--format-reindent (formatted start)
"Reindent FORMATTED to align with buffer position START."
(let* ((start-column (save-excursion (goto-char start) (current-column)))
(indent-line (concat "\n" (make-string start-column ? ))))
(replace-regexp-in-string "\n" indent-line formatted)))
;;; Format region
(defun cider--format-region (start end formatter)
"Format the contents of the given region.
START and END represent the region's boundaries.
FORMATTER is a function of one argument which is used to convert
the string contents of the region into a formatted string.
Uses the following heuristic to try to maintain point position:
- Take a snippet of text starting at current position, up to 64 chars.
- Search for the snippet, with lax whitespace, in the formatted text.
- If snippet is less than 64 chars (point was near end of buffer), search
from end instead of beginning.
- Place point at match beginning, or `point-min' if no match."
(let* ((original (buffer-substring-no-properties start end))
(formatted (funcall formatter original))
(indented (cider--format-reindent formatted start)))
(unless (equal original indented)
(let* ((pos (point))
(pos-max (1+ (buffer-size)))
(l 64)
(endp (> (+ pos l) pos-max))
(snippet (thread-last (buffer-substring-no-properties
pos (min (+ pos l) pos-max))
(replace-regexp-in-string "[[:space:]\t\n\r]+" "[[:space:]\t\n\r]*"))))
(delete-region start end)
(insert indented)
(goto-char (if endp (point-max) (point-min)))
(funcall (if endp #'re-search-backward #'re-search-forward) snippet nil t)
(goto-char (or (match-beginning 0) start))
(when (looking-at-p "\n") (forward-char))))))
;;;###autoload
(defun cider-format-region (start end)
"Format the Clojure code in the current region.
START and END represent the region's boundaries."
(interactive "r")
(cider-ensure-connected)
(cider--format-region start end #'cider-sync-request:format-code))
;;; Format defun
;;;###autoload
(defun cider-format-defun ()
"Format the code in the current defun."
(interactive)
(cider-ensure-connected)
(save-excursion
(mark-defun)
(cider-format-region (region-beginning) (region-end))))
;;; Format buffer
(defun cider--format-buffer (formatter)
"Format the contents of the current buffer.
Uses FORMATTER, a function of one argument, to convert the string contents
of the buffer into a formatted string."
(cider--format-region 1 (1+ (buffer-size)) formatter))
;;;###autoload
(defun cider-format-buffer ()
"Format the Clojure code in the current buffer."
(interactive)
(check-parens)
(cider-ensure-connected)
(cider--format-buffer #'cider-sync-request:format-code))
;;; Format EDN
(declare-function cider--pretty-print-width "cider-repl")
;;;###autoload
(defun cider-format-edn-buffer ()
"Format the EDN data in the current buffer."
(interactive)
(check-parens)
(cider-ensure-connected)
(cider--format-buffer (lambda (edn)
(cider-sync-request:format-edn edn (cider--pretty-print-width)))))
;;;###autoload
(defun cider-format-edn-region (start end)
"Format the EDN data in the current region.
START and END represent the region's boundaries."
(interactive "r")
(cider-ensure-connected)
(let* ((start-column (save-excursion (goto-char start) (current-column)))
(right-margin (- (cider--pretty-print-width) start-column)))
(cider--format-region start end
(lambda (edn)
(cider-sync-request:format-edn edn right-margin)))))
;;;###autoload
(defun cider-format-edn-last-sexp ()
"Format the EDN data of the last sexp."
(interactive)
(apply 'cider-format-edn-region (cider-sexp-at-point 'bounds)))
(provide 'cider-format)
;;; cider-format.el ends here

View file

@ -0,0 +1,130 @@
;;; cider-grimoire.el --- Grimoire integration -*- lexical-binding: t -*-
;; Copyright © 2014-2018 Bozhidar Batsov and CIDER contributors
;;
;; Author: Bozhidar Batsov <bozhidar@batsov.com>
;; 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/>.
;; This file is not part of GNU Emacs.
;;; Commentary:
;; A few commands for Grimoire documentation lookup.
;;; Code:
(require 'cider-client)
(require 'cider-common)
(require 'subr-x)
(require 'cider-compat)
(require 'cider-popup)
(require 'nrepl-dict)
(require 'url-vars)
(declare-function markdown-mode "markdown-mode.el")
(declare-function markdown-toggle-fontify-code-blocks-natively "markdown-mode.el")
(defconst cider-grimoire-url "http://conj.io/")
(defconst cider-grimoire-buffer "*cider-grimoire*")
(defun cider-grimoire-replace-special (name)
"Convert the dashes in NAME to a grimoire friendly format."
(thread-last name
(replace-regexp-in-string "\\?" "_QMARK_")
(replace-regexp-in-string "\\." "_DOT_")
(replace-regexp-in-string "\\/" "_SLASH_")
(replace-regexp-in-string "\\(\\`_\\)\\|\\(_\\'\\)" "")))
(defun cider-grimoire-url (name ns)
"Generate a grimoire search v0 url from NAME, NS."
(let ((base-url cider-grimoire-url))
(when (and name ns)
(concat base-url "search/v0/" ns "/" (cider-grimoire-replace-special name) "/"))))
(defun cider-grimoire-web-lookup (symbol)
"Open the grimoire documentation for SYMBOL in a web browser."
(if-let* ((var-info (cider-var-info symbol)))
(let ((name (nrepl-dict-get var-info "name"))
(ns (nrepl-dict-get var-info "ns")))
(browse-url (cider-grimoire-url name ns)))
(error "Symbol %s not resolved" symbol)))
;;;###autoload
(defun cider-grimoire-web (&optional arg)
"Open grimoire documentation in the default web browser.
Prompts for the symbol to use, or uses the symbol at point, depending on
the value of `cider-prompt-for-symbol'. With prefix arg ARG, does the
opposite of what that option dictates."
(interactive "P")
(funcall (cider-prompt-for-symbol-function arg)
"Grimoire doc for"
#'cider-grimoire-web-lookup))
(defun cider-create-grimoire-buffer (content)
"Create a new grimoire buffer with CONTENT."
(with-current-buffer (cider-popup-buffer cider-grimoire-buffer t)
(read-only-mode -1)
(insert content)
(when (require 'markdown-mode nil 'noerror)
(markdown-mode)
(cider-popup-buffer-mode 1)
(when (fboundp 'markdown-toggle-fontify-code-blocks-natively)
(markdown-toggle-fontify-code-blocks-natively 1)))
(view-mode 1)
(goto-char (point-min))
(current-buffer)))
(defun cider-grimoire-lookup (symbol)
"Look up the grimoire documentation for SYMBOL.
If SYMBOL is a special form, the clojure.core ns is used, as is
Grimoire's convention."
(if-let* ((var-info (cider-var-info symbol)))
(let ((name (nrepl-dict-get var-info "name"))
(ns (nrepl-dict-get var-info "ns" "clojure.core"))
(url-request-method "GET")
(url-request-extra-headers `(("Content-Type" . "text/plain"))))
(url-retrieve (cider-grimoire-url name ns)
(lambda (_status)
;; we need to strip the http header
(goto-char (point-min))
(re-search-forward "^$")
(delete-region (point-min) (point))
(delete-blank-lines)
;; and create a new buffer with whatever is left
(pop-to-buffer (cider-create-grimoire-buffer (buffer-string))))))
(error "Symbol %s not resolved" symbol)))
;;;###autoload
(defun cider-grimoire (&optional arg)
"Open grimoire documentation in a popup buffer.
Prompts for the symbol to use, or uses the symbol at point, depending on
the value of `cider-prompt-for-symbol'. With prefix arg ARG, does the
opposite of what that option dictates."
(interactive "P")
(when (derived-mode-p 'clojurescript-mode)
(user-error "`cider-grimoire' doesn't support ClojureScript"))
(funcall (cider-prompt-for-symbol-function arg)
"Grimoire doc for"
#'cider-grimoire-lookup))
(provide 'cider-grimoire)
;;; cider-grimoire.el ends here

View file

@ -0,0 +1,397 @@
;;; cider-inspector.el --- Object inspector -*- lexical-binding: t -*-
;; Copyright © 2013-2018 Vital Reactor, LLC
;; Copyright © 2014-2018 Bozhidar Batsov and CIDER contributors
;; Author: Ian Eslick <ian@vitalreactor.com>
;; Bozhidar Batsov <bozhidar@batsov.com>
;; 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/>.
;; This file is not part of GNU Emacs.
;;; Commentary:
;; Clojure object inspector inspired by SLIME.
;;; Code:
(require 'cl-lib)
(require 'seq)
(require 'cider-eval)
;; ===================================
;; Inspector Key Map and Derived Mode
;; ===================================
(defconst cider-inspector-buffer "*cider-inspect*")
;;; Customization
(defgroup cider-inspector nil
"Presentation and behaviour of the cider value inspector."
:prefix "cider-inspector-"
:group 'cider
:package-version '(cider . "0.10.0"))
(defcustom cider-inspector-page-size 32
"Default page size in paginated inspector view.
The page size can be also changed interactively within the inspector."
:type '(integer :tag "Page size" 32)
:group 'cider-inspector
:package-version '(cider . "0.10.0"))
(defcustom cider-inspector-fill-frame nil
"Controls whether the cider inspector window fills its frame."
:type 'boolean
:group 'cider-inspector
:package-version '(cider . "0.15.0"))
(defvar cider-inspector-mode-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map cider-popup-buffer-mode-map)
(define-key map (kbd "RET") #'cider-inspector-operate-on-point)
(define-key map [mouse-1] #'cider-inspector-operate-on-click)
(define-key map "l" #'cider-inspector-pop)
(define-key map "g" #'cider-inspector-refresh)
;; Page-up/down
(define-key map [next] #'cider-inspector-next-page)
(define-key map [prior] #'cider-inspector-prev-page)
(define-key map " " #'cider-inspector-next-page)
(define-key map (kbd "M-SPC") #'cider-inspector-prev-page)
(define-key map (kbd "S-SPC") #'cider-inspector-prev-page)
(define-key map "s" #'cider-inspector-set-page-size)
(define-key map [tab] #'cider-inspector-next-inspectable-object)
(define-key map "\C-i" #'cider-inspector-next-inspectable-object)
(define-key map [(shift tab)] #'cider-inspector-previous-inspectable-object)
;; Emacs translates S-TAB to BACKTAB on X.
(define-key map [backtab] #'cider-inspector-previous-inspectable-object)
map))
(define-derived-mode cider-inspector-mode special-mode "Inspector"
"Major mode for inspecting Clojure data structures.
\\{cider-inspector-mode-map}"
(set-syntax-table clojure-mode-syntax-table)
(setq-local electric-indent-chars nil)
(setq-local sesman-system 'CIDER)
(when cider-special-mode-truncate-lines
(setq-local truncate-lines t)))
;;;###autoload
(defun cider-inspect-last-sexp ()
"Inspect the result of the the expression preceding point."
(interactive)
(cider-inspect-expr (cider-last-sexp) (cider-current-ns)))
;;;###autoload
(defun cider-inspect-defun-at-point ()
"Inspect the result of the \"top-level\" expression at point."
(interactive)
(cider-inspect-expr (cider-defun-at-point) (cider-current-ns)))
;;;###autoload
(defun cider-inspect-last-result ()
"Inspect the most recent eval result."
(interactive)
(cider-inspect-expr "*1" (cider-current-ns)))
;;;###autoload
(defun cider-inspect (&optional arg)
"Inspect the result of the preceding sexp.
With a prefix argument ARG it inspects the result of the \"top-level\" form.
With a second prefix argument it prompts for an expression to eval and inspect."
(interactive "p")
(pcase arg
(1 (cider-inspect-last-sexp))
(4 (cider-inspect-defun-at-point))
(16 (call-interactively #'cider-inspect-expr))))
(defvar cider-inspector-location-stack nil
"A stack used to save point locations in inspector buffers.
These locations are used to emulate `save-excursion' between
`cider-inspector-push' and `cider-inspector-pop' operations.")
(defvar cider-inspector-page-location-stack nil
"A stack used to save point locations in inspector buffers.
These locations are used to emulate `save-excursion' between
`cider-inspector-next-page' and `cider-inspector-prev-page' operations.")
(defvar cider-inspector-last-command nil
"Contains the value of the most recently used `cider-inspector-*' command.
This is used as an alternative to the built-in `last-command'. Whenever we
invoke any command through \\[execute-extended-command] and its variants,
the value of `last-command' is not set to the command it invokes.")
;; Operations
;;;###autoload
(defun cider-inspect-expr (expr ns)
"Evaluate EXPR in NS and inspect its value.
Interactively, EXPR is read from the minibuffer, and NS the
current buffer's namespace."
(interactive (list (cider-read-from-minibuffer "Inspect expression: " (cider-sexp-at-point))
(cider-current-ns)))
(when-let* ((value (cider-sync-request:inspect-expr expr ns (or cider-inspector-page-size 32))))
(cider-inspector--render-value value)))
(defun cider-inspector-pop ()
"Pop the last value off the inspector stack and render it.
See `cider-sync-request:inspect-pop' and `cider-inspector--render-value'."
(interactive)
(setq cider-inspector-last-command 'cider-inspector-pop)
(when-let* ((value (cider-sync-request:inspect-pop)))
(cider-inspector--render-value value)))
(defun cider-inspector-push (idx)
"Inspect the value at IDX in the inspector stack and render it.
See `cider-sync-request:insepect-push' and `cider-inspector--render-value'"
(push (point) cider-inspector-location-stack)
(when-let* ((value (cider-sync-request:inspect-push idx)))
(cider-inspector--render-value value)))
(defun cider-inspector-refresh ()
"Re-render the currently inspected value.
See `cider-sync-request:insepect-refresh' and `cider-inspector--render-value'"
(interactive)
(when-let* ((value (cider-sync-request:inspect-refresh)))
(cider-inspector--render-value value)))
(defun cider-inspector-next-page ()
"Jump to the next page when inspecting a paginated sequence/map.
Does nothing if already on the last page."
(interactive)
(push (point) cider-inspector-page-location-stack)
(when-let* ((value (cider-sync-request:inspect-next-page)))
(cider-inspector--render-value value)))
(defun cider-inspector-prev-page ()
"Jump to the previous page when expecting a paginated sequence/map.
Does nothing if already on the first page."
(interactive)
(setq cider-inspector-last-command 'cider-inspector-prev-page)
(when-let* ((value (cider-sync-request:inspect-prev-page)))
(cider-inspector--render-value value)))
(defun cider-inspector-set-page-size (page-size)
"Set the page size in pagination mode to the specified PAGE-SIZE.
Current page will be reset to zero."
(interactive "nPage size: ")
(when-let* ((value (cider-sync-request:inspect-set-page-size page-size)))
(cider-inspector--render-value value)))
;; nREPL interactions
(defun cider-sync-request:inspect-pop ()
"Move one level up in the inspector stack."
(thread-first '("op" "inspect-pop")
(cider-nrepl-send-sync-request)
(nrepl-dict-get "value")))
(defun cider-sync-request:inspect-push (idx)
"Inspect the inside value specified by IDX."
(thread-first `("op" "inspect-push"
"idx" ,idx)
(cider-nrepl-send-sync-request)
(nrepl-dict-get "value")))
(defun cider-sync-request:inspect-refresh ()
"Re-render the currently inspected value."
(thread-first '("op" "inspect-refresh")
(cider-nrepl-send-sync-request)
(nrepl-dict-get "value")))
(defun cider-sync-request:inspect-next-page ()
"Jump to the next page in paginated collection view."
(thread-first '("op" "inspect-next-page")
(cider-nrepl-send-sync-request)
(nrepl-dict-get "value")))
(defun cider-sync-request:inspect-prev-page ()
"Jump to the previous page in paginated collection view."
(thread-first '("op" "inspect-prev-page")
(cider-nrepl-send-sync-request)
(nrepl-dict-get "value")))
(defun cider-sync-request:inspect-set-page-size (page-size)
"Set the page size in paginated view to PAGE-SIZE."
(thread-first `("op" "inspect-set-page-size"
"page-size" ,page-size)
(cider-nrepl-send-sync-request)
(nrepl-dict-get "value")))
(defun cider-sync-request:inspect-expr (expr ns page-size)
"Evaluate EXPR in context of NS and inspect its result.
Set the page size in paginated view to PAGE-SIZE."
(thread-first (append (nrepl--eval-request expr ns)
`("inspect" "true"
"page-size" ,page-size))
(cider-nrepl-send-sync-request)
(nrepl-dict-get "value")))
;; Render Inspector from Structured Values
(defun cider-inspector--render-value (value)
"Render VALUE."
(cider-make-popup-buffer cider-inspector-buffer 'cider-inspector-mode 'ancillary)
(cider-inspector-render cider-inspector-buffer value)
(cider-popup-buffer-display cider-inspector-buffer t)
(when cider-inspector-fill-frame (delete-other-windows))
(with-current-buffer cider-inspector-buffer
(when (eq cider-inspector-last-command 'cider-inspector-pop)
(setq cider-inspector-last-command nil)
;; Prevents error message being displayed when we try to pop
;; from the top-level of a data struture
(when cider-inspector-location-stack
(goto-char (pop cider-inspector-location-stack))))
(when (eq cider-inspector-last-command 'cider-inspector-prev-page)
(setq cider-inspector-last-command nil)
;; Prevents error message being displayed when we try to
;; go to a prev-page from the first page
(when cider-inspector-page-location-stack
(goto-char (pop cider-inspector-page-location-stack))))))
(defun cider-inspector-render (buffer str)
"Render STR in BUFFER."
(with-current-buffer buffer
(cider-inspector-mode)
(let ((inhibit-read-only t))
(condition-case nil
(cider-inspector-render* (car (read-from-string str)))
(error (insert "\nInspector error for: " str))))
(goto-char (point-min))))
(defun cider-inspector-render* (elements)
"Render ELEMENTS."
(dolist (el elements)
(cider-inspector-render-el* el)))
(defun cider-inspector-render-el* (el)
"Render EL."
(cond ((symbolp el) (insert (symbol-name el)))
((stringp el) (insert (propertize el 'font-lock-face 'font-lock-keyword-face)))
((and (consp el) (eq (car el) :newline))
(insert "\n"))
((and (consp el) (eq (car el) :value))
(cider-inspector-render-value (cadr el) (cl-caddr el)))
(t (message "Unrecognized inspector object: %s" el))))
(defun cider-inspector-render-value (value idx)
"Render VALUE at IDX."
(cider-propertize-region
(list 'cider-value-idx idx
'mouse-face 'highlight)
(cider-inspector-render-el* (cider-font-lock-as-clojure value))))
;; ===================================================
;; Inspector Navigation (lifted from SLIME inspector)
;; ===================================================
(defun cider-find-inspectable-object (direction limit)
"Find the next/previous inspectable object.
DIRECTION can be either 'next or 'prev.
LIMIT is the maximum or minimum position in the current buffer.
Return a list of two values: If an object could be found, the
starting position of the found object and T is returned;
otherwise LIMIT and NIL is returned."
(let ((finder (cl-ecase direction
(next 'next-single-property-change)
(prev 'previous-single-property-change))))
(let ((prop nil) (curpos (point)))
(while (and (not prop) (not (= curpos limit)))
(let ((newpos (funcall finder curpos 'cider-value-idx nil limit)))
(setq prop (get-text-property newpos 'cider-value-idx))
(setq curpos newpos)))
(list curpos (and prop t)))))
(defun cider-inspector-next-inspectable-object (arg)
"Move point to the next inspectable object.
With optional ARG, move across that many objects.
If ARG is negative, move backwards."
(interactive "p")
(let ((maxpos (point-max)) (minpos (point-min))
(previously-wrapped-p nil))
;; Forward.
(while (> arg 0)
(seq-let (pos foundp) (cider-find-inspectable-object 'next maxpos)
(if foundp
(progn (goto-char pos) (setq arg (1- arg))
(setq previously-wrapped-p nil))
(if (not previously-wrapped-p) ; cycle detection
(progn (goto-char minpos) (setq previously-wrapped-p t))
(error "No inspectable objects")))))
;; Backward.
(while (< arg 0)
(seq-let (pos foundp) (cider-find-inspectable-object 'prev minpos)
;; CIDER-OPEN-INSPECTOR inserts the title of an inspector page
;; as a presentation at the beginning of the buffer; skip
;; that. (Notice how this problem can not arise in ``Forward.'')
(if (and foundp (/= pos minpos))
(progn (goto-char pos) (setq arg (1+ arg))
(setq previously-wrapped-p nil))
(if (not previously-wrapped-p) ; cycle detection
(progn (goto-char maxpos) (setq previously-wrapped-p t))
(error "No inspectable objects")))))))
(defun cider-inspector-previous-inspectable-object (arg)
"Move point to the previous inspectable object.
With optional ARG, move across that many objects.
If ARG is negative, move forwards."
(interactive "p")
(cider-inspector-next-inspectable-object (- arg)))
(defun cider-inspector-property-at-point ()
"Return property at point."
(let* ((properties '(cider-value-idx cider-range-button
cider-action-number))
(find-property
(lambda (point)
(cl-loop for property in properties
for value = (get-text-property point property)
when value
return (list property value)))))
(or (funcall find-property (point))
(funcall find-property (1- (point))))))
(defun cider-inspector-operate-on-point ()
"Invoke the command for the text at point.
1. If point is on a value then recursively call the inspector on
that value.
2. If point is on an action then call that action.
3. If point is on a range-button fetch and insert the range."
(interactive)
(seq-let (property value) (cider-inspector-property-at-point)
(cl-case property
(cider-value-idx
(cider-inspector-push value))
;; TODO: range and action handlers
(t (error "No object at point")))))
(defun cider-inspector-operate-on-click (event)
"Move to EVENT's position and operate the part."
(interactive "@e")
(let ((point (posn-point (event-end event))))
(cond ((and point
(or (get-text-property point 'cider-value-idx)))
(goto-char point)
(cider-inspector-operate-on-point))
(t
(error "No clickable part here")))))
(provide 'cider-inspector)
;;; cider-inspector.el ends here

View file

@ -0,0 +1,206 @@
;;; cider-macroexpansion.el --- Macro expansion support -*- lexical-binding: t -*-
;; Copyright © 2012-2013 Tim King, Phil Hagelberg, Bozhidar Batsov
;; Copyright © 2013-2018 Bozhidar Batsov, Artur Malabarba and CIDER contributors
;;
;; Author: Tim King <kingtim@gmail.com>
;; Phil Hagelberg <technomancy@gmail.com>
;; Bozhidar Batsov <bozhidar@batsov.com>
;; Artur Malabarba <bruce.connor.am@gmail.com>
;; Hugo Duncan <hugo@hugoduncan.org>
;; Steve Purcell <steve@sanityinc.com>
;; 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/>.
;; This file is not part of GNU Emacs.
;;; Commentary:
;; Macro expansion support.
;;; Code:
(require 'cider-mode)
(require 'subr-x)
(require 'cider-compat)
(defconst cider-macroexpansion-buffer "*cider-macroexpansion*")
(defcustom cider-macroexpansion-display-namespaces 'tidy
"Determines if namespaces are displayed in the macroexpansion buffer.
Possible values are:
'qualified ;=> Vars are fully-qualified in the expansion
'none ;=> Vars are displayed without namespace qualification
'tidy ;=> Vars that are :refer-ed or defined in the current namespace are
displayed with their simple name, non-refered vars from other
namespaces are refered using the alias for that namespace (if
defined), other vars are displayed fully qualified."
:type '(choice (const :tag "Suppress namespaces" none)
(const :tag "Show fully-qualified namespaces" qualified)
(const :tag "Show namespace aliases" tidy))
:group 'cider
:package-version '(cider . "0.7.0"))
(defcustom cider-macroexpansion-print-metadata nil
"Determines if metadata is included in macroexpansion results."
:type 'boolean
:group 'cider
:package-version '(cider . "0.9.0"))
(defun cider-sync-request:macroexpand (expander expr &optional display-namespaces)
"Macroexpand, using EXPANDER, the given EXPR.
The default for DISPLAY-NAMESPACES is taken from
`cider-macroexpansion-display-namespaces'."
(cider-ensure-op-supported "macroexpand")
(thread-first `("op" "macroexpand"
"expander" ,expander
"code" ,expr
"ns" ,(cider-current-ns)
"display-namespaces" ,(or display-namespaces
(symbol-name cider-macroexpansion-display-namespaces)))
(nconc (when cider-macroexpansion-print-metadata
'("print-meta" "true")))
(cider-nrepl-send-sync-request)
(nrepl-dict-get "expansion")))
(defun cider-macroexpand-undo (&optional arg)
"Undo the last macroexpansion, using `undo-only'.
ARG is passed along to `undo-only'."
(interactive)
(let ((inhibit-read-only t))
(undo-only arg)))
(defvar cider-last-macroexpand-expression nil
"Specify the last macroexpansion preformed.
This variable specifies both what was expanded and the expander.")
(defun cider-macroexpand-expr (expander expr)
"Macroexpand, use EXPANDER, the given EXPR."
(when-let* ((expansion (cider-sync-request:macroexpand expander expr)))
(setq cider-last-macroexpand-expression expr)
(cider-initialize-macroexpansion-buffer expansion (cider-current-ns))))
(defun cider-macroexpand-expr-inplace (expander)
"Substitute the form preceding point with its macroexpansion using EXPANDER."
(interactive)
(let* ((expansion (cider-sync-request:macroexpand expander (cider-last-sexp)))
(bounds (cons (save-excursion (clojure-backward-logical-sexp 1) (point)) (point))))
(cider-redraw-macroexpansion-buffer
expansion (current-buffer) (car bounds) (cdr bounds))))
(defun cider-macroexpand-again ()
"Repeat the last macroexpansion."
(interactive)
(cider-initialize-macroexpansion-buffer cider-last-macroexpand-expression (cider-current-ns)))
;;;###autoload
(defun cider-macroexpand-1 (&optional prefix)
"Invoke \\=`macroexpand-1\\=` on the expression preceding point.
If invoked with a PREFIX argument, use \\=`macroexpand\\=` instead of
\\=`macroexpand-1\\=`."
(interactive "P")
(let ((expander (if prefix "macroexpand" "macroexpand-1")))
(cider-macroexpand-expr expander (cider-last-sexp))))
(defun cider-macroexpand-1-inplace (&optional prefix)
"Perform inplace \\=`macroexpand-1\\=` on the expression preceding point.
If invoked with a PREFIX argument, use \\=`macroexpand\\=` instead of
\\=`macroexpand-1\\=`."
(interactive "P")
(let ((expander (if prefix "macroexpand" "macroexpand-1")))
(cider-macroexpand-expr-inplace expander)))
;;;###autoload
(defun cider-macroexpand-all ()
"Invoke \\=`macroexpand-all\\=` on the expression preceding point."
(interactive)
(cider-macroexpand-expr "macroexpand-all" (cider-last-sexp)))
(defun cider-macroexpand-all-inplace ()
"Perform inplace \\=`macroexpand-all\\=` on the expression preceding point."
(interactive)
(cider-macroexpand-expr-inplace "macroexpand-all"))
(defun cider-initialize-macroexpansion-buffer (expansion ns)
"Create a new Macroexpansion buffer with EXPANSION and namespace NS."
(pop-to-buffer (cider-create-macroexpansion-buffer))
(setq cider-buffer-ns ns)
(setq buffer-undo-list nil)
(let ((inhibit-read-only t)
(buffer-undo-list t))
(erase-buffer)
(insert (format "%s" expansion))
(goto-char (point-max))
(cider--font-lock-ensure)))
(defun cider-redraw-macroexpansion-buffer (expansion buffer start end)
"Redraw the macroexpansion with new EXPANSION.
Text in BUFFER from START to END is replaced with new expansion,
and point is placed after the expanded form."
(with-current-buffer buffer
(let ((buffer-read-only nil))
(goto-char start)
(delete-region start end)
(insert (format "%s" expansion))
(goto-char start)
(indent-sexp)
(forward-sexp))))
(declare-function cider-mode "cider-mode")
(defun cider-create-macroexpansion-buffer ()
"Create a new macroexpansion buffer."
(with-current-buffer (cider-popup-buffer cider-macroexpansion-buffer 'select 'clojure-mode 'ancillary)
(cider-mode -1)
(cider-macroexpansion-mode 1)
(current-buffer)))
(declare-function cider-find-var "cider-find")
(defvar cider-macroexpansion-mode-map
(let ((map (make-sparse-keymap)))
(define-key map (kbd "g") #'cider-macroexpand-again)
(define-key map (kbd "q") #'cider-popup-buffer-quit-function)
(define-key map (kbd "d") #'cider-doc)
(define-key map (kbd "j") #'cider-javadoc)
(define-key map (kbd ".") #'cider-find-var)
(define-key map (kbd "m") #'cider-macroexpand-1-inplace)
(define-key map (kbd "a") #'cider-macroexpand-all-inplace)
(define-key map (kbd "u") #'cider-macroexpand-undo)
(define-key map [remap undo] #'cider-macroexpand-undo)
(easy-menu-define cider-macroexpansion-mode-menu map
"Menu for CIDER's doc mode"
'("Macroexpansion"
["Restart expansion" cider-macroexpand-again]
["Macroexpand-1" cider-macroexpand-1-inplace]
["Macroexpand-all" cider-macroexpand-all-inplace]
["Macroexpand-undo" cider-macroexpand-undo]
["Go to source" cider-find-var]
["Go to doc" cider-doc]
["Go to Javadoc" cider-docview-javadoc]
["Quit" cider-popup-buffer-quit-function]))
map))
(define-minor-mode cider-macroexpansion-mode
"Minor mode for CIDER macroexpansion.
\\{cider-macroexpansion-mode-map}"
nil
" Macroexpand"
cider-macroexpansion-mode-map)
(provide 'cider-macroexpansion)
;;; cider-macroexpansion.el ends here

Some files were not shown because too many files have changed in this diff Show more