Browse Source

add ido

pull/1/head
Brett Langdon 12 years ago
parent
commit
0c90c31ca0
10 changed files with 611 additions and 0 deletions
  1. +15
    -0
      emacs.d/elpa/flx-0.1/flx-autoloads.el
  2. +1
    -0
      emacs.d/elpa/flx-0.1/flx-pkg.el
  3. BIN
      emacs.d/elpa/flx-0.1/flx-pkg.elc
  4. +346
    -0
      emacs.d/elpa/flx-0.1/flx.el
  5. BIN
      emacs.d/elpa/flx-0.1/flx.elc
  6. +33
    -0
      emacs.d/elpa/flx-ido-0.2/flx-ido-autoloads.el
  7. +1
    -0
      emacs.d/elpa/flx-ido-0.2/flx-ido-pkg.el
  8. BIN
      emacs.d/elpa/flx-ido-0.2/flx-ido-pkg.elc
  9. +215
    -0
      emacs.d/elpa/flx-ido-0.2/flx-ido.el
  10. BIN
      emacs.d/elpa/flx-ido-0.2/flx-ido.elc

+ 15
- 0
emacs.d/elpa/flx-0.1/flx-autoloads.el View File

@ -0,0 +1,15 @@
;;; flx-autoloads.el --- automatically extracted autoloads
;;
;;; Code:
(add-to-list 'load-path (or (file-name-directory #$) (car load-path)))
;;;### (autoloads nil nil ("flx.el") (21271 14901 609415 333000))
;;;***
;; Local Variables:
;; version-control: never
;; no-byte-compile: t
;; no-update-autoloads: t
;; End:
;;; flx-autoloads.el ends here

+ 1
- 0
emacs.d/elpa/flx-0.1/flx-pkg.el View File

@ -0,0 +1 @@
(define-package "flx" "0.1" "fuzzy matching with good sorting" 'nil)

BIN
emacs.d/elpa/flx-0.1/flx-pkg.elc View File


+ 346
- 0
emacs.d/elpa/flx-0.1/flx.el View File

@ -0,0 +1,346 @@
;;; flx.el --- fuzzy matching with good sorting
;; Copyright © 2013 Le Wang
;; Author: Le Wang
;; Maintainer: Le Wang
;; Description: fuzzy matching with good sorting
;; Created: Wed Apr 17 01:01:41 2013 (+0800)
;; Version: 0.1
;; URL: https://github.com/lewang/flx
;; This file is NOT part of GNU Emacs.
;;; License
;; 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 this program; see the file COPYING. If not, write to
;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
;; Floor, Boston, MA 02110-1301, USA.
;;; Commentary:
;; Implementation notes
;; --------------------
;;
;; Use defsubst instead of defun
;;
;; * Using bitmaps to check for matches worked out to be SLOWER than just
;; scanning the string and using `flx-get-matches'.
;;
;; * Consing causes GC, which can often slowdown Emacs more than the benefits
;; of an optimization.
;;; Acknowledgments
;; Scott Frazer's blog entry http://scottfrazersblog.blogspot.com.au/2009/12/emacs-better-ido-flex-matching.html
;; provided a lot of inspiration.
;; ido-hacks was helpful for ido optimization
;;; Code:
(eval-when-compile (require 'cl))
(defface flx-highlight-face '((t (:inherit font-lock-variable-name-face :bold t :underline t)))
"Face used by flx for highlighting flx match characters."
:group 'flx)
(defun flx-get-hash-for-string (str heatmap-func)
"Return hash-table for string where keys are characters value
is a sorted list of indexes for character occurrences."
(let* ((res (make-hash-table :test 'eq :size 32))
(str-len (length str))
char)
(loop for index from (1- str-len) downto 0
do (progn
(setq char (downcase (aref str index)))
(push index (gethash char res))))
(puthash 'heatmap (funcall heatmap-func str) res)
res))
;;; Do we need more word separators than ST?
(defsubst flx-word-p (char)
"Check if CHAR is a word character."
(and char
(not (memq char '(?\ ?- ?_ ?: ?. ?/ ?\\)))))
(defsubst flx-capital-p (char)
"Check if CHAR is an uppercase character."
(and char
(flx-word-p char)
(= char (upcase char))))
(defsubst flx-boundary-p (last-char char)
"Check is LAST-CHAR is the end of a word and CHAR the start of the next.
The function is camel-case aware."
(or (null last-char)
(and (not (flx-capital-p last-char))
(flx-capital-p char))
(and (not (flx-word-p last-char))
(flx-word-p char))))
(defsubst flx-inc-vec (vec &optional inc beg end)
"increment each element of vectory by INC(default=1)
from BEG (inclusive) to end (not inclusive).
"
(or inc
(setq inc 1))
(or beg
(setq beg 0))
(or end
(setq end (length vec)))
(while (< beg end)
(incf (aref vec beg) inc)
(incf beg))
vec)
;; So we store one fixnum per character. Is this too memory inefficient?
(defun flx-get-heatmap-str (str &optional group-separator)
"Generate heat map vector of string.
See documentation for logic."
(let* ((str-len (length str))
(str-last-index (1- str-len))
;; ++++ base
(scores (make-vector str-len -35))
(penalty-lead ?.)
(groups-alist (list (list -1 0))))
;; ++++ final char bonus
(incf (aref scores str-last-index) 1)
;; Establish baseline mapping
(loop for char across str
for index from 0
with last-char = nil
with group-word-count = 0
do (progn
(let ((effective-last-char
;; before we find any words, all separaters are
;; considered words of length 1. This is so "foo/__ab"
;; gets penalized compared to "foo/ab".
(if (zerop group-word-count) nil last-char)))
(when (flx-boundary-p effective-last-char char)
(setcdr (cdar groups-alist) (cons index (cddar groups-alist))))
(when (and (not (flx-word-p last-char))
(flx-word-p char))
(incf group-word-count)))
;; ++++ -45 penalize extension
(when (eq last-char penalty-lead)
(incf (aref scores index) -45))
(when (eq group-separator char )
(setcar (cdar groups-alist) group-word-count)
(setq group-word-count 0)
(push (nconc (list index group-word-count)) groups-alist))
(if (= index str-last-index)
(setcar (cdar groups-alist) group-word-count)
(setq last-char char))))
(let* ((group-count (length groups-alist))
(separator-count (1- group-count)))
;; ++++ slash group-count penalty
(unless (zerop separator-count)
(flx-inc-vec scores (* -2 group-count)))
;; score each group further
(loop for group in groups-alist
for index from separator-count downto 0
with last-group-limit = nil
with basepath-found = nil
do (let ((group-start (car group))
(word-count (cadr group))
;; this is the number of effective word groups
(words-length (length (cddr group)))
basepath-p)
(when (and (not (zerop words-length))
(not basepath-found))
(setq basepath-found t)
(setq basepath-p t))
(let (num)
(setq num
(if basepath-p
(+ 35
;; ++++ basepath separator-count boosts
(if (> separator-count 1)
(1- separator-count)
0)
;; ++++ basepath word count penalty
(- word-count))
;; ++++ non-basepath penalties
(if (= index 0)
-3
(+ -5 (1- index)))))
(flx-inc-vec scores num (1+ group-start) last-group-limit))
(loop for word in (cddr group)
for word-index from (1- words-length) downto 0
with last-word = (or last-group-limit
str-len)
do (progn
(incf (aref scores word)
;; ++++ beg word bonus AND
85)
(loop for index from word below last-word
for char-i from 0
do (incf (aref scores index)
(-
;; ++++ word order penalty
(* -3 word-index)
;; ++++ char order penalty
char-i)))
(setq last-word word)))
(setq last-group-limit (1+ group-start)))))
scores))
(defun flx-get-heatmap-file (filename)
"Return heatmap vector for filename."
(flx-get-heatmap-str filename ?/))
(defsubst flx-bigger-sublist (sorted-list val)
"return sublist bigger than VAL from sorted SORTED-LIST
if VAL is nil, return entire list."
(if val
(loop for sub on sorted-list
do (when (> (car sub) val)
(return sub)))
sorted-list))
(defun flx-get-matches (hash query &optional greater-than q-index)
"Return list of all unique indexes into str where query can match.
That is all character sequences of query that occur in str are returned.
HASH accept as the cached analysis of str.
sstr
e.g. (\"aab\" \"ab\") returns
'((0 2) (1 2)
"
(setq q-index (or q-index 0))
(let* ((q-char (aref query q-index))
(indexes (flx-bigger-sublist
(gethash q-char hash) greater-than)))
(if (< q-index (1- (length query)))
(apply ; `mapcan'
'nconc
(mapcar
(lambda (index)
(let ((next-matches-for-rest (flx-get-matches hash query index (1+ q-index))))
(when next-matches-for-rest
(mapcar (lambda (match)
(cons index match))
next-matches-for-rest))))
indexes))
(mapcar 'list indexes))))
(defun flx-make-filename-cache ()
"Return cache hashtable appropraite for storeing filenames."
(flx-make-string-cache 'flx-get-heatmap-file))
(defun flx-make-string-cache (&optional heat-func)
"Return cache hashtable appropraite for storeing strings."
(let ((hash (make-hash-table :test 'equal
:size 4096)))
(puthash 'heatmap-func (or heat-func 'flx-get-heatmap-str) hash)
hash))
(defun flx-process-cache (str cache)
"Get calculated heatmap from cache, add it if necessary."
(let ((res (when cache
(gethash str cache))))
(or res
(progn
(setq res (flx-get-hash-for-string
str
(or (and cache (gethash 'heatmap-func cache))
'flx-get-heatmap-str)))
(when cache
(puthash str res cache))
res))))
(defun flx-score (str query &optional cache)
"return best score matching QUERY against STR"
(setq query (downcase query))
(unless (or (zerop (length query))
(zerop (length str)))
(let* ((info-hash (flx-process-cache str cache))
(heatmap (gethash 'heatmap info-hash))
(matches (flx-get-matches info-hash query))
(query-length (length query))
(full-match-boost (and (< query-length 5)
(> query-length 1)))
(best-score nil))
(mapc (lambda (match-positions)
(let ((score (if (and
full-match-boost
(= (length match-positions)
(length str)))
10000
0))
(contiguous-count 0)
last-match)
(loop for index in match-positions
do (progn
(if (and last-match
(= (1+ last-match) index))
(incf contiguous-count)
(setq contiguous-count 0))
(incf score (aref heatmap index))
(when (> contiguous-count 0)
(incf score (+ 45 (* 15 (min contiguous-count 4)))))
(setq last-match index)))
(if (or (null best-score)
(> score (car best-score)))
(setq best-score (cons score match-positions)))))
matches)
best-score)))
(defun flx-propertize (obj score &optional add-score)
"Return propertized copy of obj according to score.
SCORE of nil means to clear the properties."
(let ((block-started (cadr score))
(last-char nil)
(str (if (consp obj)
(substring-no-properties (car obj))
(substring-no-properties obj))))
(unless (null score)
(loop for char in (cdr score)
do (progn
(when (and last-char
(not (= (1+ last-char) char)))
(put-text-property block-started (1+ last-char) 'face 'flx-highlight-face str)
(setq block-started char))
(setq last-char char)))
(put-text-property block-started (1+ last-char) 'face 'flx-highlight-face str)
(when add-score
(setq str (format "%s [%s]" str (car score)))))
(if (consp obj)
(cons str (cdr obj))
str)))
(defvar flx-file-cache (flx-make-filename-cache)
"Cached heatmap info about strings.")
(defvar flx-strings-cache (flx-make-string-cache)
"Cached heatmap info about filenames.")
(provide 'flx)
;;; flx.el ends here

BIN
emacs.d/elpa/flx-0.1/flx.elc View File


+ 33
- 0
emacs.d/elpa/flx-ido-0.2/flx-ido-autoloads.el View File

@ -0,0 +1,33 @@
;;; flx-ido-autoloads.el --- automatically extracted autoloads
;;
;;; Code:
(add-to-list 'load-path (or (file-name-directory #$) (car load-path)))
;;;### (autoloads nil "flx-ido" "flx-ido.el" (21271 14911 502817
;;;;;; 181000))
;;; Generated autoloads from flx-ido.el
(defvar flx-ido-mode nil "\
Non-nil if Flx-Ido mode is enabled.
See the command `flx-ido-mode' for a description of this minor mode.")
(custom-autoload 'flx-ido-mode "flx-ido" nil)
(autoload 'flx-ido-mode "flx-ido" "\
Toggle flx ido mode
\(fn &optional ARG)" t nil)
;;;***
;;;### (autoloads nil nil ("flx-ido-pkg.el") (21271 14911 544818
;;;;;; 226000))
;;;***
;; Local Variables:
;; version-control: never
;; no-byte-compile: t
;; no-update-autoloads: t
;; End:
;;; flx-ido-autoloads.el ends here

+ 1
- 0
emacs.d/elpa/flx-ido-0.2/flx-ido-pkg.el View File

@ -0,0 +1 @@
(define-package "flx-ido" "0.2" "flx integration for ido" '((flx "0.1")))

BIN
emacs.d/elpa/flx-ido-0.2/flx-ido-pkg.elc View File


+ 215
- 0
emacs.d/elpa/flx-ido-0.2/flx-ido.el View File

@ -0,0 +1,215 @@
;;; flx-ido.el --- flx integration for ido
;; Copyright © 2013 Le Wang
;; Author: Le Wang
;; Maintainer: Le Wang
;; Description: flx integration for ido
;; Created: Sun Apr 21 20:38:36 2013 (+0800)
;; Version: 0.2
;; URL: https://github.com/lewang/flx
;; Package-Requires: ((flx "0.1"))
;; This file is NOT part of GNU Emacs.
;;; License
;; 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 this program; 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 provides a more powerful alternative to `ido-mode''s
;; built-in flex matching.
;;; Acknowledgments
;; Scott Frazer's blog entry http://scottfrazersblog.blogspot.com.au/2009/12/emacs-better-ido-flex-matching.html
;; provided a lot of inspiration.
;;
;; ido-hacks was helpful for ido optimization and fontification ideas
;;; Installation:
;; Add the following code to your init file:
;;
;; (require 'flx-ido)
;; (ido-mode 1)
;; (ido-everywhere 1)
;; (flx-ido-mode 1)
;; ;; disable ido faces to see flx highlights.
;; (setq ido-use-faces nil)
;;; Code:
(eval-when-compile (require 'cl))
(require 'ido)
(require 'flx)
(defcustom flx-ido-threshhold 6000
"flx will not kick in until collection is filtered below this size with \"flex\"."
:group 'ido)
(defcustom flx-ido-use-faces t
"Use `flx-highlight-face' to indicate characters contributing to best score."
:group 'ido)
(unless (fboundp 'ido-delete-runs)
(defun ido-delete-runs (list)
"Delete consecutive runs of same item in list.
Comparison done with `equal'. Runs may loop back on to the first
item, in which case, the ending items are deleted."
(let ((tail list)
before-last-run)
(while tail
(if (consp (cdr tail))
(if (equal (car tail) (cadr tail))
(setcdr tail (cddr tail))
(setq before-last-run tail)
(setq tail (cdr tail)))
(setq tail (cdr tail))))
(when (and before-last-run
(equal (car list) (cadr before-last-run)))
(setcdr before-last-run nil)))
list))
(defvar flx-ido-narrowed-matches-hash (make-hash-table :test 'equal))
(defun flx-ido-narrowed (query items)
"Get the value from `flx-ido-narrowed-matches-hash' with the
longest prefix match."
(if (zerop (length query))
(list t (nreverse items))
(let ((query-key (flx-ido-key-for-query query))
best-match
exact
res)
(loop for key being the hash-key of flx-ido-narrowed-matches-hash
do (when (and (>= (length query-key) (length key))
(eq t
(compare-strings query-key 0 (min (length query-key)
(length key))
key 0 nil))
(or (null best-match)
(> (length key) (length best-match))))
(setq best-match key)
(when (= (length key)
(length query-key))
(setq exact t)
(return))))
(setq res (cond (exact
(gethash best-match flx-ido-narrowed-matches-hash))
(best-match
(flx-ido-undecorate (gethash best-match flx-ido-narrowed-matches-hash)))
(t
(flx-ido-undecorate items))))
(list exact res))))
(defun flx-ido-undecorate (strings)
(flx-ido-decorate strings t))
(defun flx-ido-decorate (things &optional clear)
(if flx-ido-use-faces
(let ((decorate-count (min ido-max-prospects
(length things))))
(nconc
(loop for thing in things
for i from 0 below decorate-count
collect (if clear
(flx-propertize thing nil)
(flx-propertize (car thing) (cdr thing))))
(if clear
(nthcdr decorate-count things)
(mapcar 'car (nthcdr decorate-count things)))))
(if clear
things
(mapcar 'car things))))
(defun flx-ido-match-internal (query items)
(if (< (length items) flx-ido-threshhold)
(let* ((matches (loop for item in items
for string = (if (consp item) (car item) item)
for score = (flx-score string query flx-file-cache)
if score
collect (cons item score)
into matches
finally return matches)))
(flx-ido-decorate (ido-delete-runs
(sort matches
(lambda (x y) (> (cadr x) (cadr y)))))))
(let ((regexp (mapconcat 'identity (split-string query "" t) ".*")))
(loop for item in items
if (string-match regexp (if (consp item) (car item) item))
collect item
into matches
finally return matches))))
(defun flx-ido-key-for-query (query)
(concat ido-current-directory query))
(defun flx-ido-cache (query items)
(if (memq ido-cur-item '(file dir))
items
(puthash (flx-ido-key-for-query query) items flx-ido-narrowed-matches-hash)))
(defun flx-ido-match (query items)
"Better sorting for flx ido matching."
(destructuring-bind (exact res-items)
(flx-ido-narrowed query items)
(flx-ido-cache query (if exact
res-items
(flx-ido-match-internal query res-items)))))
(defadvice ido-exit-minibuffer (around flx-ido-undecorate activate)
"Remove flx properties after."
(let* ((obj (car ido-matches))
(str (if (consp obj)
(car obj)
obj)))
(when (and flx-ido-mode str)
(remove-text-properties 0 (length str)
'(face flx-highlight-face) str)))
ad-do-it)
(defadvice ido-read-internal (before flx-ido-reset-hash activate)
"Clear flx narrowed hash beforehand."
(when flx-ido-mode
(clrhash flx-ido-narrowed-matches-hash)))
(defadvice ido-restrict-to-matches (before flx-ido-reset-hash activate)
"Clear flx narrowed hash."
(when flx-ido-mode
(clrhash flx-ido-narrowed-matches-hash)))
(defadvice ido-set-matches-1 (around flx-ido-set-matches-1 activate)
"Choose between the regular ido-set-matches-1 and my-ido-fuzzy-match"
(if flx-ido-mode
(setq ad-return-value (flx-ido-match ido-text (ad-get-arg 0)))
ad-do-it))
;;;###autoload
(define-minor-mode flx-ido-mode
"Toggle flx ido mode"
:init-value nil
:lighter ""
:group 'ido
:global t)
(provide 'flx-ido)
;;; flx-ido.el ends here

BIN
emacs.d/elpa/flx-ido-0.2/flx-ido.elc View File


Loading…
Cancel
Save