| @ -0,0 +1,18 @@ | |||
| ;;; dash-autoloads.el --- automatically extracted autoloads | |||
| ;; | |||
| ;;; Code: | |||
| ;;;### (autoloads nil nil ("dash-pkg.el" "dash.el") (21002 9889 395401 | |||
| ;;;;;; 0)) | |||
| ;;;*** | |||
| (provide 'dash-autoloads) | |||
| ;; Local Variables: | |||
| ;; version-control: never | |||
| ;; no-byte-compile: t | |||
| ;; no-update-autoloads: t | |||
| ;; coding: utf-8 | |||
| ;; End: | |||
| ;;; dash-autoloads.el ends here | |||
| @ -0,0 +1 @@ | |||
| (define-package "dash" "1.5.0" "A modern list library for Emacs" (quote nil)) | |||
| @ -0,0 +1,85 @@ | |||
| ;;; grizzl-autoloads.el --- automatically extracted autoloads | |||
| ;; | |||
| ;;; Code: | |||
| ;;;### (autoloads (grizzl-result-strings grizzl-result-count grizzl-search | |||
| ;;;;;; grizzl-make-index) "grizzl-core" "grizzl-core.el" (21002 | |||
| ;;;;;; 10325 0 0)) | |||
| ;;; Generated autoloads from grizzl-core.el | |||
| (autoload 'grizzl-make-index "grizzl-core" "\ | |||
| Makes an index from the list STRINGS for use with `grizzl-search'. | |||
| If :PROGRESS-FN is given as a keyword argument, it is called repeatedly | |||
| with integers N and TOTAL. | |||
| If :CASE-SENSITIVE is specified as a non-nil keyword argument, the index | |||
| will be created case-sensitive, otherwise it will be case-insensitive. | |||
| \(fn STRINGS &rest OPTIONS)" nil nil) | |||
| (autoload 'grizzl-search "grizzl-core" "\ | |||
| Fuzzy searches for TERM in INDEX prepared with `grizzl-make-index'. | |||
| OLD-RESULT may be specified as an existing search result to increment from. | |||
| The result can be read with `grizzl-result-strings'. | |||
| \(fn TERM INDEX &optional OLD-RESULT)" nil nil) | |||
| (autoload 'grizzl-result-count "grizzl-core" "\ | |||
| Returns the number of matches present in RESULT. | |||
| \(fn RESULT)" nil nil) | |||
| (autoload 'grizzl-result-strings "grizzl-core" "\ | |||
| Returns the ordered list of matched strings in RESULT, using INDEX. | |||
| If the :START option is specified, results are read from the given offset. | |||
| If the :END option is specified, up to :END results are returned. | |||
| \(fn RESULT INDEX &rest OPTIONS)" nil nil) | |||
| ;;;*** | |||
| ;;;### (autoloads (grizzl-set-selection-1 grizzl-set-selection+1 | |||
| ;;;;;; grizzl-selected-result grizzl-completing-read) "grizzl-read" | |||
| ;;;;;; "grizzl-read.el" (21002 10325 0 0)) | |||
| ;;; Generated autoloads from grizzl-read.el | |||
| (autoload 'grizzl-completing-read "grizzl-read" "\ | |||
| Performs a completing-read in the minibuffer using INDEX to fuzzy search. | |||
| Each key pressed in the minibuffer filters down the list of matches. | |||
| \(fn PROMPT INDEX)" nil nil) | |||
| (autoload 'grizzl-selected-result "grizzl-read" "\ | |||
| Get the selected string from INDEX in a `grizzl-completing-read'. | |||
| \(fn INDEX)" nil nil) | |||
| (autoload 'grizzl-set-selection+1 "grizzl-read" "\ | |||
| Move the selection up one row in `grizzl-completing-read'. | |||
| \(fn)" t nil) | |||
| (autoload 'grizzl-set-selection-1 "grizzl-read" "\ | |||
| Move the selection down one row in `grizzl-completing-read'. | |||
| \(fn)" t nil) | |||
| ;;;*** | |||
| ;;;### (autoloads nil nil ("grizzl-pkg.el" "grizzl.el") (21002 10325 | |||
| ;;;;;; 472906 0)) | |||
| ;;;*** | |||
| (provide 'grizzl-autoloads) | |||
| ;; Local Variables: | |||
| ;; version-control: never | |||
| ;; no-byte-compile: t | |||
| ;; no-update-autoloads: t | |||
| ;; coding: utf-8 | |||
| ;; End: | |||
| ;;; grizzl-autoloads.el ends here | |||
| @ -0,0 +1,226 @@ | |||
| ;;; grizzl-core.el --- Fast fuzzy search index for Emacs. | |||
| ;; Copyright © 2013 Chris Corbyn | |||
| ;; | |||
| ;; Author: Chris Corbyn <chris@w3style.co.uk> | |||
| ;; URL: https://github.com/d11wtq/grizzl | |||
| ;; Version: 0.1.1 | |||
| ;; Keywords: convenience, usability | |||
| ;; This file is NOT part of GNU Emacs. | |||
| ;;; --- License | |||
| ;; Licensed under the same terms as Emacs. | |||
| ;;; --- Commentary | |||
| ;; Grizzl provides a fuzzy completion framework for general purpose | |||
| ;; use in Emacs Lisp projects. | |||
| ;; | |||
| ;; grizzl-core.el provides the underlying data structures and sesrch | |||
| ;; algorithm without any UI attachment. At the core, a fuzzy search | |||
| ;; index is created from a list of strings, using `grizzl-make-index'. | |||
| ;; A fuzzy search term is then used to get a result from this index | |||
| ;; with `grizzl-search'. Because grizzl considers the usage of a | |||
| ;; fuzzy search index to operate in real-time as a user enters a | |||
| ;; search term in the minibuffer, the framework optimizes for this use | |||
| ;; case. Any result can be passed back into `grizzl-search' as a hint | |||
| ;; to continue searching. The search algorithm is able to understand | |||
| ;; insertions and deletions and therefore minimizes the work it needs | |||
| ;; to do in this case. The intended use here is to collect a result | |||
| ;; on each key press and feed that result into the search for the next | |||
| ;; key press. Once a search is complete, the matched strings are then | |||
| ;; read, using `grizzl-result-strings'. The results are ordered on the | |||
| ;; a combination of the Levenshtein Distance and a character-proximity | |||
| ;; scoring calculation. This means shorter strings are favoured, but | |||
| ;; adjacent letters are more heavily favoured. | |||
| ;; | |||
| ;; It is assumed that the index will be re-used across multiple | |||
| ;; searches on larger sets of data. | |||
| ;; | |||
| ;; | |||
| (eval-when-compile | |||
| (require 'cl-lib)) | |||
| ;;; --- Public Functions | |||
| ;;;###autoload | |||
| (defun grizzl-make-index (strings &rest options) | |||
| "Makes an index from the list STRINGS for use with `grizzl-search'. | |||
| If :PROGRESS-FN is given as a keyword argument, it is called repeatedly | |||
| with integers N and TOTAL. | |||
| If :CASE-SENSITIVE is specified as a non-nil keyword argument, the index | |||
| will be created case-sensitive, otherwise it will be case-insensitive." | |||
| (let ((lookup-table (make-hash-table)) | |||
| (total-strs (length strings)) | |||
| (case-sensitive (plist-get options :case-sensitive)) | |||
| (progress-fn (plist-get options :progress-fn)) | |||
| (string-data (vconcat (mapcar (lambda (s) | |||
| (cons s (length s))) | |||
| strings)))) | |||
| (reduce (lambda (list-offset str) | |||
| (grizzl-index-insert str list-offset lookup-table | |||
| :case-sensitive case-sensitive) | |||
| (when progress-fn | |||
| (funcall progress-fn (1+ list-offset) total-strs)) | |||
| (1+ list-offset)) | |||
| strings | |||
| :initial-value 0) | |||
| (maphash (lambda (char str-map) | |||
| (maphash (lambda (list-offset locations) | |||
| (puthash list-offset (reverse locations) str-map)) | |||
| str-map)) lookup-table) | |||
| `((case-sensitive . ,case-sensitive) | |||
| (lookup-table . ,lookup-table) | |||
| (string-data . ,string-data)))) | |||
| ;;;###autoload | |||
| (defun grizzl-search (term index &optional old-result) | |||
| "Fuzzy searches for TERM in INDEX prepared with `grizzl-make-index'. | |||
| OLD-RESULT may be specified as an existing search result to increment from. | |||
| The result can be read with `grizzl-result-strings'." | |||
| (let* ((cased-term (if (grizzl-index-case-sensitive-p index) | |||
| term | |||
| (downcase term))) | |||
| (result (grizzl-rewind-result cased-term index old-result)) | |||
| (matches (copy-hash-table (grizzl-result-matches result))) | |||
| (from-pos (length (grizzl-result-term result))) | |||
| (remainder (substring cased-term from-pos)) | |||
| (lookup-table (grizzl-lookup-table index))) | |||
| (reduce (lambda (acc-res ch) | |||
| (let ((sub-table (gethash ch lookup-table))) | |||
| (if (not sub-table) | |||
| (clrhash matches) | |||
| (grizzl-search-increment sub-table matches)) | |||
| (grizzl-cons-result cased-term matches acc-res))) | |||
| remainder | |||
| :initial-value result))) | |||
| ;;;###autoload | |||
| (defun grizzl-result-count (result) | |||
| "Returns the number of matches present in RESULT." | |||
| (hash-table-count (grizzl-result-matches result))) | |||
| ;;;###autoload | |||
| (defun grizzl-result-strings (result index &rest options) | |||
| "Returns the ordered list of matched strings in RESULT, using INDEX. | |||
| If the :START option is specified, results are read from the given offset. | |||
| If the :END option is specified, up to :END results are returned." | |||
| (let* ((matches (grizzl-result-matches result)) | |||
| (strings (grizzl-index-strings index)) | |||
| (loaded '()) | |||
| (start (plist-get options :start)) | |||
| (end (plist-get options :end))) | |||
| (maphash (lambda (string-offset char-offset) | |||
| (push string-offset loaded)) | |||
| matches) | |||
| (let* ((ordered (sort loaded | |||
| (lambda (a b) | |||
| (< (cadr (gethash a matches)) | |||
| (cadr (gethash b matches)))))) | |||
| (best (if (or start end) | |||
| (delete-if-not 'identity | |||
| (subseq ordered (or start 0) end)) | |||
| ordered))) | |||
| (mapcar (lambda (n) | |||
| (car (elt strings n))) | |||
| best)))) | |||
| ;;; --- Private Functions | |||
| (defun grizzl-cons-result (term matches results) | |||
| "Build a new result for TERM and hash-table MATCHES consed with RESULTS." | |||
| (cons (cons term matches) results)) | |||
| (defun grizzl-rewind-result (term index result) | |||
| "Adjusts RESULT according to TERM, ready for a new search." | |||
| (if result | |||
| (let* ((old-term (grizzl-result-term result)) | |||
| (new-len (length term)) | |||
| (old-len (length old-term))) | |||
| (if (and (>= new-len old-len) | |||
| (string-equal old-term (substring term 0 old-len))) | |||
| result | |||
| (grizzl-rewind-result term index (cdr result)))) | |||
| (grizzl-cons-result "" (grizzl-base-matches index) nil))) | |||
| (defun grizzl-base-matches (index) | |||
| "Returns the full set of matches in INDEX, with an out-of-bound offset." | |||
| (let ((matches (make-hash-table))) | |||
| (reduce (lambda (n s-len) | |||
| (puthash n (list -1 0 (cdr s-len)) matches) | |||
| (1+ n)) | |||
| (grizzl-index-strings index) | |||
| :initial-value 0) | |||
| matches)) | |||
| (defun grizzl-result-term (result) | |||
| "Returns the search term used to find the matches in RESULT." | |||
| (car (car result))) | |||
| (defun grizzl-result-matches (result) | |||
| "Returns the internal hash used to track the matches in RESULT." | |||
| (cdar result)) | |||
| (defun grizzl-index-insert (string list-offset index &rest options) | |||
| "Inserts STRING at LIST-OFFSET into INDEX." | |||
| (let ((case-sensitive (plist-get options :case-sensitive))) | |||
| (reduce (lambda (char-offset cs-char) | |||
| (let* ((char (if case-sensitive | |||
| cs-char | |||
| (downcase cs-char))) | |||
| (str-map (or (gethash char index) | |||
| (puthash char (make-hash-table) index))) | |||
| (offsets (gethash list-offset str-map))) | |||
| (puthash list-offset | |||
| (cons char-offset offsets) | |||
| str-map) | |||
| (1+ char-offset))) | |||
| string | |||
| :initial-value 0))) | |||
| (defun grizzl-lookup-table (index) | |||
| "Returns the lookup table portion of INDEX." | |||
| (cdr (assoc 'lookup-table index))) | |||
| (defun grizzl-index-strings (index) | |||
| "Returns the vector of strings stored in INDEX." | |||
| (cdr (assoc 'string-data index))) | |||
| (defun grizzl-index-case-sensitive-p (index) | |||
| "Predicate to test of INDEX is case-sensitive." | |||
| (cdr (assoc 'case-sensitive index))) | |||
| (defun grizzl-search-increment (sub-table result) | |||
| "Use the search lookup table to filter already-accumulated results." | |||
| (cl-flet ((next-offset (key current sub-table) | |||
| (find-if (lambda (v) | |||
| (> v current)) | |||
| (gethash key sub-table)))) | |||
| (maphash (lambda (k v) | |||
| (let* ((oldpos (car v)) | |||
| (oldrank (cadr v)) | |||
| (len (caddr v)) | |||
| (newpos (next-offset k oldpos sub-table))) | |||
| (if newpos | |||
| (puthash k (list newpos | |||
| (grizzl-inc-rank oldrank oldpos newpos len) | |||
| len) | |||
| result) | |||
| (remhash k result)))) | |||
| result))) | |||
| (defun grizzl-inc-rank (oldrank oldpos newpos len) | |||
| "Increment the current match distance as a new char is matched." | |||
| (let ((distance (if (< oldpos 0) 1 (- newpos oldpos)))) | |||
| (+ oldrank (* len (* distance distance))))) | |||
| (provide 'grizzl-core) | |||
| ;;; grizzl-core.el ends here | |||
| @ -0,0 +1,3 @@ | |||
| (define-package "grizzl" "0.1.1" | |||
| "Fuzzy Search Library & Completing Read" | |||
| '((cl-lib "0.1"))) | |||
| @ -0,0 +1,186 @@ | |||
| ;;; grizzl-read.el --- A fuzzy completing-read backed by grizzl. | |||
| ;; Copyright © 2013 Chris Corbyn | |||
| ;; | |||
| ;; Author: Chris Corbyn <chris@w3style.co.uk> | |||
| ;; URL: https://github.com/d11wtq/grizzl | |||
| ;; Version: 0.1.1 | |||
| ;; Keywords: convenience, usability | |||
| ;; This file is NOT part of GNU Emacs. | |||
| ;;; --- License | |||
| ;; Licensed under the same terms as Emacs. | |||
| ;;; --- Commentary | |||
| ;; grizzl-read.el provides an implementation of the built-in Emacs | |||
| ;; completing-read function, except it is backed by the grizzl fuzzy | |||
| ;; search index. The goals are similar to ido-mode and helm, but grizzl | |||
| ;; is heavily optimized for large data-sets, and as-such uses a | |||
| ;; persistent fuzzy search index in its algorithm. | |||
| ;; | |||
| ;; The indexing and searching algorithm itself is defined in grizzl-core.el | |||
| ;; with grizzl-read.el simply wrapping the search in a minibuffer with a | |||
| ;; minor-mode defined. | |||
| ;; | |||
| ;; ---- Usage | |||
| ;; | |||
| ;; Call `grizzl-completing-read' with an index returned by | |||
| ;; `grizzl-make-index': | |||
| ;; | |||
| ;; (defvar *index* (grizzl-make-index '("one" "two" "three"))) | |||
| ;; (grizzl-completing-read "Number: " index) | |||
| ;; | |||
| ;; When the user hits ENTER, either one of the strings is returned on | |||
| ;; success, or nil of nothing matched. | |||
| ;; | |||
| ;; The arrow keys can be used to navigate within the results. | |||
| ;; | |||
| (eval-when-compile | |||
| (require 'cl-lib)) | |||
| ;;; --- Configuration Variables | |||
| (defvar *grizzl-read-max-results* 10 | |||
| "The maximum number of results to show in `grizzl-completing-read'.") | |||
| ;;; --- Runtime Processing Variables | |||
| (defvar *grizzl-current-result* nil | |||
| "The search result in `grizzl-completing-read'.") | |||
| (defvar *grizzl-current-selection* 0 | |||
| "The selected offset in `grizzl-completing-read'.") | |||
| ;;; --- Minor Mode Definition | |||
| (defvar *grizzl-keymap* (make-sparse-keymap) | |||
| "Internal keymap used by the minor-mode in `grizzl-completing-read'.") | |||
| (define-key *grizzl-keymap* (kbd "<up>") 'grizzl-set-selection+1) | |||
| (define-key *grizzl-keymap* (kbd "C-p") 'grizzl-set-selection+1) | |||
| (define-key *grizzl-keymap* (kbd "<down>") 'grizzl-set-selection-1) | |||
| (define-key *grizzl-keymap* (kbd "C-n") 'grizzl-set-selection-1) | |||
| (define-minor-mode grizzl-mode | |||
| "Toggle the internal mode used by `grizzl-completing-read'." | |||
| nil | |||
| " Grizzl" | |||
| *grizzl-keymap*) | |||
| ;;; --- Public Functions | |||
| ;;;###autoload | |||
| (defun grizzl-completing-read (prompt index) | |||
| "Performs a completing-read in the minibuffer using INDEX to fuzzy search. | |||
| Each key pressed in the minibuffer filters down the list of matches." | |||
| (minibuffer-with-setup-hook | |||
| (lambda () | |||
| (setq *grizzl-current-result* nil) | |||
| (setq *grizzl-current-selection* 0) | |||
| (grizzl-mode 1) | |||
| (lexical-let* | |||
| ((hookfun (lambda () | |||
| (setq *grizzl-current-result* | |||
| (grizzl-search (minibuffer-contents) | |||
| index | |||
| *grizzl-current-result*)) | |||
| (grizzl-display-result index prompt))) | |||
| (exitfun (lambda () | |||
| (grizzl-mode -1) | |||
| (remove-hook 'post-command-hook hookfun t)))) | |||
| (add-hook 'minibuffer-exit-hook exitfun nil t) | |||
| (add-hook 'post-command-hook hookfun nil t))) | |||
| (read-from-minibuffer ">>> ") | |||
| (grizzl-selected-result index))) | |||
| ;;;###autoload | |||
| (defun grizzl-selected-result (index) | |||
| "Get the selected string from INDEX in a `grizzl-completing-read'." | |||
| (elt (grizzl-result-strings *grizzl-current-result* index | |||
| :start 0 | |||
| :end *grizzl-read-max-results*) | |||
| (grizzl-current-selection))) | |||
| ;;;###autoload | |||
| (defun grizzl-set-selection+1 () | |||
| "Move the selection up one row in `grizzl-completing-read'." | |||
| (interactive) | |||
| (grizzl-move-selection 1)) | |||
| ;;;###autoload | |||
| (defun grizzl-set-selection-1 () | |||
| "Move the selection down one row in `grizzl-completing-read'." | |||
| (interactive) | |||
| (grizzl-move-selection -1)) | |||
| ;;; --- Private Functions | |||
| (defun grizzl-move-selection (delta) | |||
| "Move the selection by DELTA rows in `grizzl-completing-read'." | |||
| (setq *grizzl-current-selection* (+ (grizzl-current-selection) delta)) | |||
| (when (not (= (grizzl-current-selection) *grizzl-current-selection*)) | |||
| (beep))) | |||
| (defun grizzl-display-result (index prompt) | |||
| "Renders a series of overlays to list the matches in the result." | |||
| (let* ((matches (grizzl-result-strings *grizzl-current-result* index | |||
| :start 0 | |||
| :end *grizzl-read-max-results*))) | |||
| (delete-all-overlays) | |||
| (overlay-put (make-overlay (point-min) (point-min)) | |||
| 'before-string | |||
| (format "%s\n%s\n" | |||
| (mapconcat 'identity | |||
| (grizzl-map-format-matches matches) | |||
| "\n") | |||
| (grizzl-format-prompt-line prompt))) | |||
| (set-window-text-height nil (max 3 (+ 2 (length matches)))))) | |||
| (defun grizzl-map-format-matches (matches) | |||
| "Convert the set of string MATCHES into propertized text objects." | |||
| (if (= 0 (length matches)) | |||
| (list (propertize "-- NO MATCH --" 'face 'outline-3)) | |||
| (cdr (reduce (lambda (acc str) | |||
| (let* ((idx (car acc)) | |||
| (lst (cdr acc)) | |||
| (sel (= idx (grizzl-current-selection)))) | |||
| (cons (1+ idx) | |||
| (cons (grizzl-format-match str sel) lst)))) | |||
| matches | |||
| :initial-value '(0))))) | |||
| (defun grizzl-format-match (match-str selected) | |||
| "Default match string formatter in `grizzl-completing-read'. | |||
| MATCH-STR is the string in the selection list and SELECTED is non-nil | |||
| if this is the current selection." | |||
| (let ((margin (if selected "> " " ")) | |||
| (face (if selected 'diredp-symlink 'default))) | |||
| (propertize (format "%s%s" margin match-str) 'face face))) | |||
| (defun grizzl-format-prompt-line (prompt) | |||
| "Returns a string to render a full-width prompt in `grizzl-completing-read'." | |||
| (let* ((count (grizzl-result-count *grizzl-current-result*)) | |||
| (match-info (format " (%d candidate%s) ---- *-" | |||
| count (if (= count 1) "" "s")))) | |||
| (concat (propertize (format "-*%s *-" prompt) 'face 'modeline-inactive) | |||
| (propertize " " | |||
| 'face 'modeline-inactive | |||
| 'display `(space :align-to (- right | |||
| ,(1+ (length match-info))))) | |||
| (propertize match-info 'face 'modeline-inactive)))) | |||
| (defun grizzl-current-selection () | |||
| "Get the currently selected index in `grizzl-completing-read'." | |||
| (let ((max-selection | |||
| (min (1- *grizzl-read-max-results*) | |||
| (1- (grizzl-result-count *grizzl-current-result*))))) | |||
| (max 0 (min max-selection *grizzl-current-selection*)))) | |||
| (provide 'grizzl-read) | |||
| ;;; grizzl-read.el ends here | |||
| @ -0,0 +1,26 @@ | |||
| ;;; grizzl.el --- Fast fuzzy search index for Emacs. | |||
| ;; Copyright © 2013 Chris Corbyn | |||
| ;; | |||
| ;; Author: Chris Corbyn <chris@w3style.co.uk> | |||
| ;; URL: https://github.com/d11wtq/grizzl | |||
| ;; Version: 0.1.1 | |||
| ;; Keywords: convenience, usability | |||
| ;; This file is NOT part of GNU Emacs. | |||
| ;;; --- License | |||
| ;; Licensed under the same terms as Emacs. | |||
| ;;; --- Commentary | |||
| ;; This package is broken into separate files. | |||
| ;; | |||
| (require 'grizzl-core) | |||
| (require 'grizzl-read) | |||
| (provide 'grizzl) | |||
| ;;; grizzl.el ends here | |||
| @ -0,0 +1,52 @@ | |||
| ;;; projectile-autoloads.el --- automatically extracted autoloads | |||
| ;; | |||
| ;;; Code: | |||
| ;;;### (autoloads (projectile-global-mode projectile-mode) "projectile" | |||
| ;;;;;; "projectile.el" (21002 9890 0 0)) | |||
| ;;; Generated autoloads from projectile.el | |||
| (autoload 'projectile-mode "projectile" "\ | |||
| Minor mode to assist project management and navigation. | |||
| \\{projectile-mode-map} | |||
| \(fn &optional ARG)" t nil) | |||
| (defvar projectile-global-mode nil "\ | |||
| Non-nil if Projectile-Global mode is enabled. | |||
| See the command `projectile-global-mode' 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 `projectile-global-mode'.") | |||
| (custom-autoload 'projectile-global-mode "projectile" nil) | |||
| (autoload 'projectile-global-mode "projectile" "\ | |||
| Toggle Projectile mode in all buffers. | |||
| With prefix ARG, enable Projectile-Global mode if ARG is positive; | |||
| otherwise, disable it. If called from Lisp, enable the mode if | |||
| ARG is omitted or nil. | |||
| Projectile mode is enabled in all buffers where | |||
| `projectile-on' would do it. | |||
| See `projectile-mode' for more information on Projectile mode. | |||
| \(fn &optional ARG)" t nil) | |||
| ;;;*** | |||
| ;;;### (autoloads nil nil ("projectile-pkg.el") (21002 9890 671493 | |||
| ;;;;;; 0)) | |||
| ;;;*** | |||
| (provide 'projectile-autoloads) | |||
| ;; Local Variables: | |||
| ;; version-control: never | |||
| ;; no-byte-compile: t | |||
| ;; no-update-autoloads: t | |||
| ;; coding: utf-8 | |||
| ;; End: | |||
| ;;; projectile-autoloads.el ends here | |||
| @ -0,0 +1 @@ | |||
| (define-package "projectile" "0.9.2" "Manage and navigate projects in Emacs easily" (quote ((s "1.0.0") (dash "1.0.0")))) | |||
| @ -0,0 +1,18 @@ | |||
| ;;; s-autoloads.el --- automatically extracted autoloads | |||
| ;; | |||
| ;;; Code: | |||
| ;;;### (autoloads nil nil ("s-pkg.el" "s.el") (21002 9889 830403 | |||
| ;;;;;; 0)) | |||
| ;;;*** | |||
| (provide 's-autoloads) | |||
| ;; Local Variables: | |||
| ;; version-control: never | |||
| ;; no-byte-compile: t | |||
| ;; no-update-autoloads: t | |||
| ;; coding: utf-8 | |||
| ;; End: | |||
| ;;; s-autoloads.el ends here | |||
| @ -0,0 +1 @@ | |||
| (define-package "s" "1.6.1" "The long lost Emacs string manipulation library." (quote nil)) | |||
| @ -0,0 +1,532 @@ | |||
| ;;; s.el --- The long lost Emacs string manipulation library. | |||
| ;; Copyright (C) 2012 Magnar Sveen | |||
| ;; Author: Magnar Sveen <magnars@gmail.com> | |||
| ;; Version: 1.6.1 | |||
| ;; Keywords: strings | |||
| ;; 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: | |||
| ;; The long lost Emacs string manipulation library. | |||
| ;; | |||
| ;; See documentation on https://github.com/magnars/s.el#functions | |||
| ;;; Code: | |||
| (defun s-trim-left (s) | |||
| "Remove whitespace at the beginning of S." | |||
| (if (string-match "\\`[ \t\n\r]+" s) | |||
| (replace-match "" t t s) | |||
| s)) | |||
| (defun s-trim-right (s) | |||
| "Remove whitespace at the end of S." | |||
| (if (string-match "[ \t\n\r]+\\'" s) | |||
| (replace-match "" t t s) | |||
| s)) | |||
| (defun s-trim (s) | |||
| "Remove whitespace at the beginning and end of S." | |||
| (s-trim-left (s-trim-right s))) | |||
| (defun s-collapse-whitespace (s) | |||
| "Convert all adjacent whitespace characters to a single space." | |||
| (replace-regexp-in-string "[ \t\n\r]+" " " s)) | |||
| (defun s-split (separator s &optional omit-nulls) | |||
| "Split S into substrings bounded by matches for regexp SEPARATOR. | |||
| If OMIT-NULLS is t, zero-length substrings are omitted. | |||
| This is a simple wrapper around the built-in `split-string'." | |||
| (split-string s separator omit-nulls)) | |||
| (defun s-lines (s) | |||
| "Splits S into a list of strings on newline characters." | |||
| (s-split "\\(\r\n\\|[\n\r]\\)" s)) | |||
| (defun s-join (separator strings) | |||
| "Join all the strings in STRINGS with SEPARATOR in between." | |||
| (mapconcat 'identity strings separator)) | |||
| (defun s-concat (&rest strings) | |||
| "Join all the string arguments into one string." | |||
| (apply 'concat strings)) | |||
| (defun s-prepend (prefix s) | |||
| "Concatenate PREFIX and S." | |||
| (concat prefix s)) | |||
| (defun s-append (suffix s) | |||
| "Concatenate S and SUFFIX." | |||
| (concat s suffix)) | |||
| (defun s-repeat (num s) | |||
| "Make a string of S repeated NUM times." | |||
| (let (ss) | |||
| (while (> num 0) | |||
| (setq ss (cons s ss)) | |||
| (setq num (1- num))) | |||
| (apply 'concat ss))) | |||
| (defun s-chop-suffix (suffix s) | |||
| "Remove SUFFIX if it is at end of S." | |||
| (let ((pos (- (length suffix)))) | |||
| (if (and (>= (length s) (length suffix)) | |||
| (string= suffix (substring s pos))) | |||
| (substring s 0 pos) | |||
| s))) | |||
| (defun s-chop-suffixes (suffixes s) | |||
| "Remove SUFFIXES one by one in order, if they are at the end of S." | |||
| (while suffixes | |||
| (setq s (s-chop-suffix (car suffixes) s)) | |||
| (setq suffixes (cdr suffixes))) | |||
| s) | |||
| (defun s-chop-prefix (prefix s) | |||
| "Remove PREFIX if it is at the start of S." | |||
| (let ((pos (length prefix))) | |||
| (if (and (>= (length s) (length prefix)) | |||
| (string= prefix (substring s 0 pos))) | |||
| (substring s pos) | |||
| s))) | |||
| (defun s-chop-prefixes (prefixes s) | |||
| "Remove PREFIXES one by one in order, if they are at the start of S." | |||
| (while prefixes | |||
| (setq s (s-chop-prefix (car prefixes) s)) | |||
| (setq prefixes (cdr prefixes))) | |||
| s) | |||
| (defun s-shared-start (s1 s2) | |||
| "Returns the longest prefix S1 and S2 have in common." | |||
| (let ((search-length (min (length s1) (length s2))) | |||
| (i 0)) | |||
| (while (and (< i search-length) | |||
| (= (aref s1 i) (aref s2 i))) | |||
| (setq i (1+ i))) | |||
| (substring s1 0 i))) | |||
| (defun s-shared-end (s1 s2) | |||
| "Returns the longest suffix S1 and S2 have in common." | |||
| (let* ((l1 (length s1)) | |||
| (l2 (length s2)) | |||
| (search-length (min l1 l2)) | |||
| (i 0)) | |||
| (while (and (< i search-length) | |||
| (= (aref s1 (- l1 i 1)) (aref s2 (- l2 i 1)))) | |||
| (setq i (1+ i))) | |||
| ;; If I is 0, then it means that there's no common suffix between | |||
| ;; S1 and S2. | |||
| ;; | |||
| ;; However, since (substring s (- 0)) will return the whole | |||
| ;; string, `s-shared-end' should simply return the empty string | |||
| ;; when I is 0. | |||
| (if (zerop i) | |||
| "" | |||
| (substring s1 (- i))))) | |||
| (defun s-chomp (s) | |||
| "Remove one trailing `\\n`, `\\r` or `\\r\\n` from S." | |||
| (s-chop-suffixes '("\n" "\r") s)) | |||
| (defun s-truncate (len s) | |||
| "If S is longer than LEN, cut it down and add ... at the end." | |||
| (if (> (length s) len) | |||
| (format "%s..." (substring s 0 (- len 3))) | |||
| s)) | |||
| (defun s-word-wrap (len s) | |||
| "If S is longer than LEN, wrap the words with newlines." | |||
| (with-temp-buffer | |||
| (insert s) | |||
| (let ((fill-column len)) | |||
| (fill-region (point-min) (point-max))) | |||
| (buffer-substring-no-properties (point-min) (point-max)))) | |||
| (defun s-center (len s) | |||
| "If S is shorter than LEN, pad it with spaces so it is centered." | |||
| (let ((extra (max 0 (- len (length s))))) | |||
| (concat | |||
| (make-string (ceiling extra 2) ? ) | |||
| s | |||
| (make-string (floor extra 2) ? )))) | |||
| (defun s-pad-left (len padding s) | |||
| "If S is shorter than LEN, pad it with PADDING on the left." | |||
| (let ((extra (max 0 (- len (length s))))) | |||
| (concat (make-string extra (string-to-char padding)) | |||
| s))) | |||
| (defun s-pad-right (len padding s) | |||
| "If S is shorter than LEN, pad it with PADDING on the left." | |||
| (let ((extra (max 0 (- len (length s))))) | |||
| (concat s | |||
| (make-string extra (string-to-char padding))))) | |||
| (defun s-left (len s) | |||
| "Returns up to the LEN first chars of S." | |||
| (if (> (length s) len) | |||
| (substring s 0 len) | |||
| s)) | |||
| (defun s-right (len s) | |||
| "Returns up to the LEN last chars of S." | |||
| (let ((l (length s))) | |||
| (if (> l len) | |||
| (substring s (- l len) l) | |||
| s))) | |||
| (defun s-ends-with? (suffix s &optional ignore-case) | |||
| "Does S end with SUFFIX? | |||
| If IGNORE-CASE is non-nil, the comparison is done without paying | |||
| attention to case differences. | |||
| Alias: `s-suffix?'" | |||
| (let ((start-pos (- (length s) (length suffix)))) | |||
| (and (>= start-pos 0) | |||
| (eq t (compare-strings suffix nil nil | |||
| s start-pos nil ignore-case))))) | |||
| (defalias 's-ends-with-p 's-ends-with?) | |||
| (defun s-starts-with? (prefix s &optional ignore-case) | |||
| "Does S start with PREFIX? | |||
| If IGNORE-CASE is non-nil, the comparison is done without paying | |||
| attention to case differences. | |||
| Alias: `s-prefix?'. This is a simple wrapper around the built-in | |||
| `string-prefix-p'." | |||
| (string-prefix-p prefix s ignore-case)) | |||
| (defalias 's-starts-with-p 's-starts-with?) | |||
| (defalias 's-suffix? 's-ends-with?) | |||
| (defalias 's-prefix? 's-starts-with?) | |||
| (defalias 's-suffix-p 's-ends-with?) | |||
| (defalias 's-prefix-p 's-starts-with?) | |||
| (defun s--truthy? (val) | |||
| (not (null val))) | |||
| (defun s-contains? (needle s &optional ignore-case) | |||
| "Does S contain NEEDLE? | |||
| If IGNORE-CASE is non-nil, the comparison is done without paying | |||
| attention to case differences." | |||
| (let ((case-fold-search ignore-case)) | |||
| (s--truthy? (string-match-p (regexp-quote needle) s)))) | |||
| (defalias 's-contains-p 's-contains?) | |||
| (defun s-equals? (s1 s2) | |||
| "Is S1 equal to S2? | |||
| This is a simple wrapper around the built-in `string-equal'." | |||
| (string-equal s1 s2)) | |||
| (defalias 's-equals-p 's-equals?) | |||
| (defun s-less? (s1 s2) | |||
| "Is S1 less than S2? | |||
| This is a simple wrapper around the built-in `string-lessp'." | |||
| (string-lessp s1 s2)) | |||
| (defalias 's-less-p 's-less?) | |||
| (defun s-matches? (regexp s &optional start) | |||
| "Does REGEXP match S? | |||
| If START is non-nil the search starts at that index. | |||
| This is a simple wrapper around the built-in `string-match-p'." | |||
| (s--truthy? (string-match-p regexp s start))) | |||
| (defalias 's-matches-p 's-matches?) | |||
| (defun s-blank? (s) | |||
| "Is S nil or the empty string?" | |||
| (or (null s) (string= "" s))) | |||
| (defun s-lowercase? (s) | |||
| "Are all the letters in S in lower case?" | |||
| (let ((case-fold-search nil)) | |||
| (not (string-match-p "[[:upper:]]" s)))) | |||
| (defun s-uppercase? (s) | |||
| "Are all the letters in S in upper case?" | |||
| (let ((case-fold-search nil)) | |||
| (not (string-match-p "[[:lower:]]" s)))) | |||
| (defun s-mixedcase? (s) | |||
| "Are there both lower case and upper case letters in S?" | |||
| (let ((case-fold-search nil)) | |||
| (s--truthy? | |||
| (and (string-match-p "[[:lower:]]" s) | |||
| (string-match-p "[[:upper:]]" s))))) | |||
| (defun s-capitalized? (s) | |||
| "In S, is the first letter upper case, and all other letters lower case?" | |||
| (let ((case-fold-search nil)) | |||
| (s--truthy? | |||
| (string-match-p "^[A-ZÆØÅ][^A-ZÆØÅ]*$" s)))) | |||
| (defun s-numeric? (s) | |||
| "Is S a number?" | |||
| (s--truthy? | |||
| (string-match-p "^[0-9]+$" s))) | |||
| (defun s-replace (old new s) | |||
| "Replaces OLD with NEW in S." | |||
| (replace-regexp-in-string (regexp-quote old) new s t t)) | |||
| (defun s--aget (alist key) | |||
| (cdr (assoc key alist))) | |||
| (defun s-replace-all (replacements s) | |||
| "REPLACEMENTS is a list of cons-cells. Each `car` is replaced with `cdr` in S." | |||
| (replace-regexp-in-string (regexp-opt (mapcar 'car replacements)) | |||
| (lambda (it) (s--aget replacements it)) | |||
| s)) | |||
| (defun s-downcase (s) | |||
| "Convert S to lower case. | |||
| This is a simple wrapper around the built-in `downcase'." | |||
| (downcase s)) | |||
| (defun s-upcase (s) | |||
| "Convert S to upper case. | |||
| This is a simple wrapper around the built-in `upcase'." | |||
| (upcase s)) | |||
| (defun s-capitalize (s) | |||
| "Convert the first word's first character to upper case and the rest to lower case in S." | |||
| (concat (upcase (substring s 0 1)) (downcase (substring s 1)))) | |||
| (defun s-titleize (s) | |||
| "Convert each word's first character to upper case and the rest to lower case in S. | |||
| This is a simple wrapper around the built-in `capitalize'." | |||
| (capitalize s)) | |||
| (defmacro s-with (s form &rest more) | |||
| "Threads S through the forms. Inserts S as the last item | |||
| in the first form, making a list of it if it is not a list | |||
| already. If there are more forms, inserts the first form as the | |||
| last item in second form, etc." | |||
| (if (null more) | |||
| (if (listp form) | |||
| `(,(car form) ,@(cdr form) ,s) | |||
| (list form s)) | |||
| `(s-with (s-with ,s ,form) ,@more))) | |||
| (put 's-with 'lisp-indent-function 1) | |||
| (defun s-index-of (needle s &optional ignore-case) | |||
| "Returns first index of NEEDLE in S, or nil. | |||
| If IGNORE-CASE is non-nil, the comparison is done without paying | |||
| attention to case differences." | |||
| (let ((case-fold-search ignore-case)) | |||
| (string-match-p (regexp-quote needle) s))) | |||
| (defun s-reverse (s) ;; from org-babel-reverse-string | |||
| "Return the reverse of S." | |||
| (apply 'string (nreverse (string-to-list s)))) | |||
| (defun s-match-strings-all (regex string) | |||
| "Return a list of matches for REGEX in STRING. | |||
| Each element itself is a list of matches, as per | |||
| `match-string'. Multiple matches at the same position will be | |||
| ignored after the first." | |||
| (let ((all-strings ()) | |||
| (i 0)) | |||
| (while (and (< i (length string)) | |||
| (string-match regex string i)) | |||
| (setq i (1+ (match-beginning 0))) | |||
| (let (strings | |||
| (num-matches (/ (length (match-data)) 2)) | |||
| (match 0)) | |||
| (while (/= match num-matches) | |||
| (push (match-string match string) strings) | |||
| (setq match (1+ match))) | |||
| (push (nreverse strings) all-strings))) | |||
| (nreverse all-strings))) | |||
| (defun s-match (regexp s &optional start) | |||
| "When the given expression matches the string, this function returns a list | |||
| of the whole matching string and a string for each matched subexpressions. | |||
| If it did not match the returned value is an empty list (nil). | |||
| When START is non-nil the search will start at that index." | |||
| (save-match-data | |||
| (if (string-match regexp s start) | |||
| (let ((match-data-list (match-data)) | |||
| result) | |||
| (while match-data-list | |||
| (let* ((beg (car match-data-list)) | |||
| (end (cadr match-data-list)) | |||
| (subs (if (and beg end) (substring s beg end) nil))) | |||
| (setq result (cons subs result)) | |||
| (setq match-data-list | |||
| (cddr match-data-list)))) | |||
| (nreverse result))))) | |||
| (defun s-slice-at (regexp s) | |||
| "Slices S up at every index matching REGEXP." | |||
| (save-match-data | |||
| (let (i) | |||
| (setq i (string-match regexp s 1)) | |||
| (if i | |||
| (cons (substring s 0 i) | |||
| (s-slice-at regexp (substring s i))) | |||
| (list s))))) | |||
| (defun s-split-words (s) | |||
| "Split S into list of words." | |||
| (s-split | |||
| "[^A-Za-z0-9]+" | |||
| (let ((case-fold-search nil)) | |||
| (replace-regexp-in-string "\\([a-z]\\)\\([A-Z]\\)" "\\1 \\2" s)) | |||
| t)) | |||
| (defun s--mapcar-head (fn-head fn-rest list) | |||
| "Like MAPCAR, but applies a different function to the first element." | |||
| (if list | |||
| (cons (funcall fn-head (car list)) (mapcar fn-rest (cdr list))))) | |||
| (defun s-lower-camel-case (s) | |||
| "Convert S to lowerCamelCase." | |||
| (s-join "" (s--mapcar-head 'downcase 'capitalize (s-split-words s)))) | |||
| (defun s-upper-camel-case (s) | |||
| "Convert S to UpperCamelCase." | |||
| (s-join "" (mapcar 'capitalize (s-split-words s)))) | |||
| (defun s-snake-case (s) | |||
| "Convert S to snake_case." | |||
| (s-join "_" (mapcar 'downcase (s-split-words s)))) | |||
| (defun s-dashed-words (s) | |||
| "Convert S to dashed-words." | |||
| (s-join "-" (mapcar 'downcase (s-split-words s)))) | |||
| (defun s-capitalized-words (s) | |||
| "Convert S to Capitalized Words." | |||
| (let ((words (s-split-words s))) | |||
| (s-join " " (cons (capitalize (car words)) (mapcar 'downcase (cdr words)))))) | |||
| (defun s-titleized-words (s) | |||
| "Convert S to Titleized Words." | |||
| (s-join " " (mapcar 's-titleize (s-split-words s)))) | |||
| ;; Errors for s-format | |||
| (progn | |||
| (put 's-format-resolve | |||
| 'error-conditions | |||
| '(error s-format s-format-resolve)) | |||
| (put 's-format-resolve | |||
| 'error-message | |||
| "Cannot resolve a template to values")) | |||
| (defun s-format (template replacer &optional extra) | |||
| "Format TEMPLATE with the function REPLACER. | |||
| REPLACER takes an argument of the format variable and optionally | |||
| an extra argument which is the EXTRA value from the call to | |||
| `s-format'. | |||
| Several standard `s-format' helper functions are recognized and | |||
| adapted for this: | |||
| (s-format \"${name}\" 'gethash hash-table) | |||
| (s-format \"${name}\" 'aget alist) | |||
| (s-format \"$0\" 'elt sequence) | |||
| The REPLACER function may be used to do any other kind of | |||
| transformation." | |||
| (let ((saved-match-data (match-data))) | |||
| (unwind-protect | |||
| (replace-regexp-in-string | |||
| "\\$\\({\\([^}]+\\)}\\|[0-9]+\\)" | |||
| (lambda (md) | |||
| (let ((var | |||
| (let ((m (match-string 2 md))) | |||
| (if m m | |||
| (string-to-number (match-string 1 md))))) | |||
| (replacer-match-data (match-data))) | |||
| (unwind-protect | |||
| (let ((v | |||
| (cond | |||
| ((eq replacer 'gethash) | |||
| (funcall replacer var extra)) | |||
| ((eq replacer 'aget) | |||
| (funcall 's--aget extra var)) | |||
| ((eq replacer 'elt) | |||
| (funcall replacer extra var)) | |||
| (t | |||
| (set-match-data saved-match-data) | |||
| (if extra | |||
| (funcall replacer var extra) | |||
| (funcall replacer var)))))) | |||
| (if v v (signal 's-format-resolve md))) | |||
| (set-match-data replacer-match-data)))) template | |||
| ;; Need literal to make sure it works | |||
| t t) | |||
| (set-match-data saved-match-data)))) | |||
| (defvar s-lex-value-as-lisp nil | |||
| "If `t' interpolate lisp values as lisp. | |||
| `s-lex-format' inserts values with (format \"%S\").") | |||
| (defun s-lex-fmt|expand (fmt) | |||
| "Expand FMT into lisp." | |||
| (list 's-format fmt (quote 'aget) | |||
| (append '(list) | |||
| (mapcar | |||
| (lambda (matches) | |||
| (list | |||
| 'cons | |||
| (cadr matches) | |||
| `(format | |||
| (if s-lex-value-as-lisp "%S" "%s") | |||
| ,(intern (cadr matches))))) | |||
| (s-match-strings-all "${\\([^}]+\\)}" fmt))))) | |||
| (defmacro s-lex-format (format-str) | |||
| "`s-format` with the current environment. | |||
| FORMAT-STR may use the `s-format' variable reference to refer to | |||
| any variable: | |||
| (let ((x 1)) | |||
| (s-lex-format \"x is: ${x}\")) | |||
| The values of the variables are interpolated with \"%s\" unless | |||
| the variable `s-lex-value-as-lisp' is `t' and then they are | |||
| interpolated with \"%S\"." | |||
| (s-lex-fmt|expand format-str)) | |||
| (provide 's) | |||
| ;;; s.el ends here | |||