spacemacs-ivy: New layer

This layer configures spacemacs to use the ivy/counsel/swiper family of
packages. Default completion is done with ivy. This is meant to replace
helm for those who want it.
This commit is contained in:
justbur 2016-01-04 14:17:35 -05:00 committed by syl20bnr
parent ba9d2cc0cd
commit 67abb7df58
2 changed files with 620 additions and 0 deletions

View File

@ -0,0 +1,353 @@
;;; ivy-spacemacs-help.el --- Spacemacs layer exploration with `ivy'.
;; Author: Justin Burkett <justin@burkett.cc>
;; Keywords: ivy, spacemacs
;; Version: 0.1
;; Package-Requires: ((ivy "0.7"))
;; 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 file 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., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.
;;; Commentary:
;; This package adds a convenient way to discover Spacemacs configuration
;; layers thanks to ivy.
;;; Code:
(require 'cl)
(require 'ht)
(require 'ivy)
(require 'core-configuration-layer)
(defvar ivy-spacemacs-help-all-layers nil
"Alist of all configuration layers.")
(defvar ivy-spacemacs-help-all-packages nil
"Hash table of all packages in all layers.")
(defun ivy-spacemacs-help//init (&optional arg)
(when (or arg (null ivy-spacemacs-help-all-packages))
(mapc (lambda (layer) (push (configuration-layer/make-layer layer)
ivy-spacemacs-help-all-layers))
(configuration-layer/get-layers-list))
(dolist (layer ivy-spacemacs-help-all-layers)
(unless (configuration-layer/layer-usedp (oref layer :name))
(configuration-layer//load-layer-files layer '("funcs.el"
"config.el"))))
(setq ivy-spacemacs-help-all-packages (configuration-layer/get-packages
ivy-spacemacs-help-all-layers))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Docs
(defun ivy-spacemacs-help//documentation-candidates ()
(let (result file-extension)
(dolist (filename (directory-files spacemacs-docs-directory))
(setq file-extension (file-name-extension filename))
(when (or (equal file-extension "md")
(equal file-extension "org"))
(push filename result)))
;; CONTRIBUTING.org is a special case as it should be at the root of the
;; repository to be linked as the contributing guide on Github.
(push "CONTRIBUTING.org" result)
;; delete DOCUMENTATION.org to make it the first guide
(delete "DOCUMENTATION.org" result)
(push "DOCUMENTATION.org" result)
;; give each document an appropriate title
(mapcar (lambda (r)
(cond
((string-equal r "CONTRIBUTING.org")
`("How to contribute to Spacemacs" . ,r))
((string-equal r "CONVENTIONS.org")
`("Spacemacs conventions" . ,r))
((string-equal r "DOCUMENTATION.org")
`("Spacemacs documentation" . ,r))
((string-equal r "FAQ.org")
`("Spacemacs FAQ" . ,r))
((string-equal r "HOWTOs.org")
`("Quick HOW-TOs for Spacemacs" . ,r))
((string-equal r "LAYERS.org")
`("Tips on writing layers for Spacemacs" . ,r))
((string-equal r "QUICK_START.org")
`("Quick start guide for Spacemacs" . ,r))
((string-equal r "VIMUSERS.org")
`("Vim users migration guide" . ,r))
(t
`(r . ,r))))
result)))
(defun ivy-spacemacs-help//documentation-action-open-file (candidate)
"Open documentation FILE."
(let ((file (if (string= candidate "CONTRIBUTING.org")
;; CONTRIBUTING.org is a special case as it should be at the
;; root of the repository to be linked as the contributing
;; guide on Github.
(concat user-emacs-directory candidate)
(concat spacemacs-docs-directory candidate))))
(cond ((equal (file-name-extension file) "md")
(condition-case nil
(with-current-buffer (find-file-noselect file)
(gh-md-render-buffer)
(kill-this-buffer))
;; if anything fails, fall back to simply open file
(find-file file)))
((equal (file-name-extension file) "org")
(spacemacs/view-org-file file "^" 'all))
(t
(find-file file)))))
;;;###autoload
(defun ivy-spacemacs-help-docs (arg)
(interactive "P")
(ivy-spacemacs-help//init arg)
(ivy-read "Spacemacs Documentation: "
(ivy-spacemacs-help//documentation-candidates)
:action #'ivy-spacemacs-help//documentation-action-open-file))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Layers
(defun ivy-spacemacs-help//layer-candidates ()
(sort (mapcar 'symbol-name (configuration-layer/get-layers-list))
'string<))
(defun ivy-spacemacs-help//layer-action-open-file (file candidate &optional edit)
"Open FILE of the passed CANDIDATE. If EDIT is false, open in view mode."
(let ((path (if (and (equalp file "README.org") (equalp candidate "spacemacs"))
;; Readme for spacemacs is in the project root
(ht-get configuration-layer-paths (intern candidate))
(file-name-as-directory
(concat (ht-get configuration-layer-paths
(intern candidate))
candidate)))))
(if (equal (file-name-extension file) "org")
(if edit
(find-file (concat path file))
(spacemacs/view-org-file (concat path file) "^" 'all))
(find-file (concat path file)))))
(defun ivy-spacemacs-help//layer-action-open-readme (candidate)
"Open the `README.org' file of the passed CANDIDATE for reading."
(ivy-spacemacs-help//layer-action-open-file "README.org" candidate))
(defun ivy-spacemacs-help//layer-action-add-layer (candidate)
"Adds layer to dotspacemacs file and reloads configuration"
(if (configuration-layer/layer-usedp (intern candidate))
(message "Layer already added.")
(let ((dotspacemacs (find-file-noselect (dotspacemacs/location))))
(with-current-buffer dotspacemacs
(beginning-of-buffer)
(let ((insert-point (re-search-forward
"dotspacemacs-configuration-layers *\n?.*\\((\\)")))
(insert (format "\n%s\n" candidate))
(indent-region insert-point (+ insert-point (length candidate)))
(save-current-buffer)))
(dotspacemacs/sync-configuration-layers))))
(defun ivy-spacemacs-help//layer-action-open-readme-edit (candidate)
"Open the `README.org' file of the passed CANDIDATE for editing."
(ivy-spacemacs-help//layer-action-open-file "README.org" candidate t))
(defun ivy-spacemacs-help//layer-action-open-packages (candidate)
"Open the `packages.el' file of the passed CANDIDATE."
(ivy-spacemacs-help//layer-action-open-file "packages.el" candidate))
;; TODO remove extensions in 0.105.0
(defun ivy-spacemacs-help//layer-action-open-extensions (candidate)
"Open the `extensions.el' file of the passed CANDIDATE."
(ivy-spacemacs-help//layer-action-open-file "extensions.el" candidate))
;;;###autoload
(defun ivy-spacemacs-help-layers ()
(interactive)
(ivy-spacemacs-help//init)
(ivy-read "Spacemacs Layers: "
(ivy-spacemacs-help//layer-candidates)
:action 'ivy-spacemacs-help//layer-action-open-readme
:caller 'ivy-spacemacs-help-layers))
(ivy-set-actions
'ivy-spacemacs-help-layers
'(("a" ivy-spacemacs-help//layer-action-add-layer "add layer")
("e" ivy-spacemacs-help//layer-action-open-readme-edit "add readme for editing")
("p" ivy-spacemacs-help//layer-action-open-packages "open packages.el")
("r" ivy-spacemacs-help//layer-action-open-readme "open readme")))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Layers and packages
(defun ivy-spacemacs-help//help-candidates ()
"Return the sorted candidates for package source."
(let (result
(left-column-width
(number-to-string
(cl-reduce
(lambda (a x) (max (length (symbol-name (oref x :name))) a))
ivy-spacemacs-help-all-layers :initial-value 0))))
(dolist (pkg ivy-spacemacs-help-all-packages)
(push (list (format (concat "%-" left-column-width "S %s %s")
(oref pkg :owner)
(propertize (symbol-name (oref pkg :name))
'face 'font-lock-type-face)
(propertize
(if (package-installed-p (oref pkg :name))
"[installed]" "")
'face 'font-lock-comment-face))
(symbol-name (oref pkg :owner))
(symbol-name (oref pkg :name)))
result))
(sort result (lambda (a b) (string< (car a) (car b))))))
(defun ivy-spacemacs-help//help-action (args)
"Open the file `packages.el' and go to the init function."
(let* ((layer-str (car args))
(layer-sym (intern layer-str))
(package-str (cadr args))
(path (file-name-as-directory
(concat (ht-get configuration-layer-paths layer-sym)
layer-str)))
(filename (concat path "packages.el")))
(find-file filename)
(goto-char (point-min))
(re-search-forward (format "init-%s" package-str))
(beginning-of-line)))
(defun ivy-spacemacs-help//help-action-add-layer (args)
(let* ((layer-str (car args))
(layer-sym (intern layer-str))
(package-str (cadr args))
(path (file-name-as-directory
(concat (ht-get configuration-layer-paths layer-sym)
layer-str)))
(filename (concat path "packages.el")))
(find-file filename)
(goto-char (point-min))
(re-search-forward (format "init-%s" package-str))
(beginning-of-line)))
(defun ivy-spacemacs-help//help-action-open-packages (args)
"Open the `packages.el' file of the passed CANDIDATE."
(ivy-spacemacs-help//layer-action-open-file "packages.el" (car args)))
(defun ivy-spacemacs-help//help-action-open-readme (args)
"Open the `README.org' file of the passed CANDIDATE for reading."
(ivy-spacemacs-help//layer-action-open-file "README.org" (car args)))
(defun ivy-spacemacs-help//help-action-open-readme-edit (args)
"Open the `README.org' file of the passed CANDIDATE for editing."
(ivy-spacemacs-help//layer-action-open-file "README.org" (car args) t))
(defun ivy-spacemacs-help//help-action-add-layer (args)
"Adds layer to dotspacemacs file and reloads configuration"
(if (configuration-layer/layer-usedp (intern (car args)))
(message "Layer already added.")
(let ((dotspacemacs (find-file-noselect (dotspacemacs/location))))
(with-current-buffer dotspacemacs
(beginning-of-buffer)
(let ((insert-point (re-search-forward
"dotspacemacs-configuration-layers *\n?.*\\((\\)")))
(insert (format "\n%s\n" (car args)))
(indent-region insert-point (+ insert-point (length (car args))))
(save-current-buffer)))
(dotspacemacs/sync-configuration-layers))))
;;;###autoload
(defun ivy-spacemacs-help ()
(interactive)
(ivy-spacemacs-help//init)
(ivy-read "Spacemacs Layers and Packages: "
(ivy-spacemacs-help//help-candidates)
:action 'ivy-spacemacs-help//help-action
:caller 'ivy-spacemacs-help))
(ivy-set-actions
'ivy-spacemacs-help
'(("a" ivy-spacemacs-help//help-action-add-layer "add layer")
("e" ivy-spacemacs-help//help-action-open-readme-edit "add readme for editing")
("p" ivy-spacemacs-help//help-action-open-packages "open packages.el")
("r" ivy-spacemacs-help//help-action-open-readme "open readme")))
;;;###autoload
(defalias 'ivy-spacemacs-help-packages 'ivy-spacemacs-help)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Toggles
(defun ivy-spacemacs-help//toggle-candidates ()
"Return the sorted candidates for toggle source."
(let (result)
(dolist (toggle spacemacs-toggles)
(let* ((toggle-symbol (symbol-name (car toggle)))
(toggle-name (capitalize (replace-regexp-in-string "-" " " toggle-symbol)))
(toggle-doc (format "%s: %s"
toggle-name
(propertize
(or (plist-get (cdr toggle) :documentation) "")
'face 'font-lock-doc-face))))
(when (plist-member (cdr toggle) :evil-leader)
(let ((key (key-description
(kbd (concat dotspacemacs-leader-key " "
(plist-get (cdr toggle) :evil-leader))))))
(setq toggle-doc
(format "%s (%s)"
toggle-doc
(propertize key 'face 'helm-M-x-key)))))
(if (plist-member (cdr toggle) :documentation)
(push `(,toggle-doc . ,toggle-symbol) result)
(push `(,toggle-name . ,toggle-symbol) result))))
(setq result (cl-sort result 'string< :key 'car))
result))
(defun ivy-spacemacs-help//toggle (candidate)
"Toggle candidate."
(let ((toggle (assq (intern candidate) spacemacs-toggles)))
(when toggle
(funcall (plist-get (cdr toggle) :function)))))
;;;###autoload
(defun ivy-spacemacs-help-toggles ()
(interactive)
(ivy-read "Spacemacs Toggles: "
(ivy-spacemacs-help//toggle-candidates)
:action 'ivy-spacemacs-help//toggle))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; .spacemacs vars
(defun ivy-spacemacs-help//dotspacemacs-candidates ()
"Return the sorted candidates for all the dospacemacs variables."
(sort (dotspacemacs/get-variable-string-list) 'string<))
(defun ivy-spacemacs-help//go-to-dotfile-variable (candidate)
"Go to candidate in the dotfile."
(find-file dotspacemacs-filepath)
(goto-char (point-min))
;; try to exclude comments
(re-search-forward (format "^[a-z\s\\(\\-]*%s" candidate))
(beginning-of-line))
;;;###autoload
(defun ivy-spacemacs-help-dotspacemacs ()
(interactive)
(ivy-read ".spacemacs variables: "
(ivy-spacemacs-help//dotspacemacs-candidates)
:action 'ivy-spacemacs-help//go-to-dotfile-variable))
(provide 'ivy-spacemacs-help)
;;; ivy-spacemacs-help.el ends here

View File

@ -0,0 +1,267 @@
;;; packages.el --- Spacemacs Core Layer packages File
;;
;; Copyright (c) 2012-2014 Sylvain Benner
;; Copyright (c) 2014-2015 Sylvain Benner & Contributors
;;
;; Author: Sylvain Benner <sylvain.benner@gmail.com>
;; URL: https://github.com/syl20bnr/spacemacs
;;
;; This file is not part of GNU Emacs.
;;
;;; License: GPLv3
(setq spacemacs-ivy-packages
'(counsel
flx
hydra
(ivy-spacemacs-help :location local)
smex
swiper))
;; Initialization of packages
(defun spacemacs-ivy/init-counsel ()
(defvar spacemacs--counsel-commands
'(("ag" . "ag --vimgrep %S .")
("pt" . "pt.exe -e --nocolor --nogroup --column %S .")
("ack" . "ack --nocolor --nogroup --column %S .")
("grep" . "grep -nrP %S ."))
"Alist of search commands and their corresponding commands
with options to run in the shell.")
(defvar spacemacs--counsel-search-max-path-length 30
"Truncate the current path in counsel search if it is longer
than this amount.")
;; see `counsel-ag-function'
(defun spacemacs//make-counsel-search-function (tool)
(lexical-let ((base-cmd
(cdr (assoc-string tool spacemacs--counsel-commands))))
(lambda (string &optional _pred &rest _unused)
"Grep in the current directory for STRING."
(if (< (length string) 3)
(counsel-more-chars 3)
(let ((default-directory counsel--git-grep-dir)
(regex (counsel-unquote-regex-parens
(setq ivy--old-re
(ivy--regex string)))))
(counsel--async-command (format base-cmd regex))
nil)))))
;; see `counsel-ag'
(defun spacemacs/counsel-search
(&optional tools use-initial-input initial-directory)
"Search using the first available tool in TOOLS. Default tool
to try is grep. If INPUT is non nil, use the region or the symbol
at the point as the initial input. If DIR is non nil start in
that directory."
(interactive)
(letf* ((initial-input (when use-initial-input
(if (region-active-p)
(buffer-substring-no-properties
(region-beginning) (region-end))
(thing-at-point 'symbol t))))
(tool (catch 'tool
(dolist (tool tools)
(when (and (assoc-string tool spacemacs--counsel-commands)
(executable-find tool))
(throw 'tool tool)))
(throw 'tool "grep"))))
(setq counsel--git-grep-dir (or initial-directory default-directory))
(ivy-read
(format "%s from [%s]: "
tool
(if (< (length counsel--git-grep-dir)
spacemacs--counsel-search-max-path-length)
counsel--git-grep-dir
(concat "..."
(substring counsel--git-grep-dir
(- (length counsel--git-grep-dir)
spacemacs--counsel-search-max-path-length)
(length counsel--git-grep-dir)))))
(spacemacs//make-counsel-search-function tool)
:initial-input initial-input
:dynamic-collection t
:history 'counsel-git-grep-history
:action #'counsel-git-grep-action
:unwind (lambda ()
(counsel-delete-process)
(swiper--cleanup)))))
(cl-loop for (tools tool-name) in '((dotspacemacs-search-tools "auto")
((list "ag") "ag")
((list "pt") "pt")
((list "ack") "ack")
((list "grep") "grep"))
do
(eval
`(progn
(defun ,(intern (format "spacemacs/search-%s" tool-name)) ()
,(format
"Use `spacemacs/counsel-search' to search in the current
directory with %s." (if (string= tool-name "auto")
"a tool selected from `dotspacemacs-search-tools'."
tool-name))
(interactive)
(spacemacs/counsel-search ,tools))
(defun ,(intern (format "spacemacs/search-%s-region-or-symbol"
tool-name)) ()
,(format
"Use `spacemacs/counsel-search' to search for
the selected region or the symbol under the point in the current
directory with %s." (if (string= tool-name "auto")
"a tool selected from `dotspacemacs-search-tools'."
tool-name))
(interactive)
(spacemacs/counsel-search ,tools t))
(defun ,(intern (format "spacemacs/search-project-%s" tool-name)) ()
,(format
"Use `spacemacs/counsel-search' to search in the current
project with %s." (if (string= tool-name "auto")
"a tool selected from `dotspacemacs-search-tools'."
tool-name))
(interactive)
(spacemacs/counsel-search ,tools nil (projectile-project-root)))
(defun ,(intern (format "spacemacs/search-project-%s-region-or-symbol"
tool-name)) ()
,(format
"Use `spacemacs/counsel-search' to search for
the selected region or the symbol under the point in the current
project with %s." (if (string= tool-name "auto")
"a tool selected from `dotspacemacs-search-tools'."
tool-name))
(interactive)
(spacemacs/counsel-search ,tools t (projectile-project-root))))))
(defun spacemacs/counsel-git-grep-region-or-symbol ()
"Use `counsel-git-grep' to search for the selected region or
the symbol under the point in the current project with git grep."
(let ((input (if (region-active-p)
(buffer-substring-no-properties
(region-beginning) (region-end))
(thing-at-point 'symbol t))))
(counsel-git-grep nil input)))
(use-package counsel
:config
(spacemacs/set-leader-keys
dotspacemacs-command-key 'counsel-M-x
;; files
"ff" 'counsel-find-file
"fL" 'counsel-locate
;; help
"hdf" 'counsel-describe-function
"hdv" 'counsel-describe-variable
"hdk" 'describe-key
"hdp" 'describe-package
"hdc" 'describe-command
"hdb" 'describe-bindings
;; insert
"iu" 'counsel-unicode-char
;; projects
"pp" 'projectile-switch-project
;; jumping
"sj" 'counsel-imenu
;; themes
"Tc" 'counsel-load-theme
;; search
"/" 'spacemacs/search-project-auto
"*" 'spacemacs/search-project-auto-region-or-symbol
"sf" 'spacemacs/search-auto
"sF" 'spacemacs/search-auto-region-or-symbol
"sp" 'spacemacs/search-project
"sP" 'spacemacs/search-project-region-or-symbol
"saf" 'spacemacs/search-ag
"saF" 'spacemacs/search-ag-region-or-symbol
"sap" 'spacemacs/search-project-ag
"saP" 'spacemacs/search-project-ag-region-or-symbol
"stf" 'spacemacs/search-pt
"stF" 'spacemacs/search-pt-region-or-symbol
"stp" 'spacemacs/search-project-pt
"stP" 'spacemacs/search-project-pt-region-or-symbol
"sgf" 'spacemacs/search-grep
"sgF" 'spacemacs/search-grep-region-or-symbol
"sgp" 'counsel-git-grep
"sgP" 'spacemacs/counsel-git-grep-region-or-symbol
"skf" 'spacemacs/search-ack
"skF" 'spacemacs/search-ack-region-or-symbol
"skp" 'spacemacs/search-project-ack
"skP" 'spacemacs/search-project-ack-region-or-symbol)))
(defun spacemacs-ivy/init-flx ())
(defun spacemacs-ivy/init-hydra ())
(defun spacemacs-ivy/init-ivy-spacemacs-help ()
(use-package ivy-spacemacs-help
:init
(progn
(spacemacs/set-leader-keys
"h SPC d" 'ivy-spacemacs-help-docs
"h SPC ." 'ivy-spacemacs-help-dotspacemacs
;; "h SPC f" 'ivy-spacemacs-help-faq
"h SPC l" 'ivy-spacemacs-help-layers
"h SPC SPC" 'ivy-spacemacs-help
"h SPC p" 'ivy-spacemacs-help-packages
"h SPC t" 'ivy-spacemacs-help-toggles))))
(defun spacemacs-ivy/init-smex ()
(use-package smex
:defer t
:init
(progn
(setq-default smex-history-length 32
smex-save-file (concat spacemacs-cache-directory
".smex-items")))))
(defun spacemacs-ivy/init-swiper ()
(use-package ivy
:config
(spacemacs/set-leader-keys
"fr" 'ivy-recentf
"ir" 'ivy-resume
"bb" 'ivy-switch-buffer)
(setq ivy-height 15
;; merge recentf and bookmarks into buffer switching
ivy-use-virtual-buffers t)
(when (configuration-layer/package-usedp 'projectile)
(setq projectile-completion-system 'ivy))
(ivy-mode 1)
(global-set-key (kbd "C-c C-r") 'ivy-resume)
(global-set-key (kbd "<f6>") 'ivy-resume)
(spacemacs//hjkl-completion-navigation))
(use-package swiper
:config
(defun spacemacs/swiper-region-or-symbol ()
"Run `swiper' with the selected region or the symbol under
the point as the initial input."
(interactive)
(let ((input (if (region-active-p)
(buffer-substring-no-properties
(region-beginning) (region-end))
(thing-at-point 'symbol t))))
(swiper--ivy input)))
(defun spacemacs/swiper-all-region-or-symbol ()
"Run `swiper-all' with the selected region or the symbol
under the point as the initial input."
(interactive)
(ivy-read "Swiper: " (swiper--multi-candidates
(cl-remove-if-not
#'buffer-file-name
(buffer-list)))
:initial-input (if (region-active-p)
(buffer-substring-no-properties
(region-beginning) (region-end))
(thing-at-point 'symbol t))
:action 'swiper-multi-action-2
:unwind #'swiper--cleanup
:caller 'swiper-multi))
(spacemacs/set-leader-keys
"ss" 'swiper
"sS" 'spacemacs/swiper-region-or-symbol
"sb" 'swiper-all
"sB" 'spacemacs/swiper-all-region-or-symbol)
(global-set-key "\C-s" 'swiper)))