From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: =?UTF-8?Q?=C3=93scar?= Fuentes Newsgroups: gmane.emacs.bugs Subject: bug#14334: 24.3.50; Memory usage grows indefinititely Date: Thu, 02 May 2013 14:30:48 +0200 Message-ID: <87zjwdmumf.fsf@wanadoo.es> NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-Trace: ger.gmane.org 1367497901 10571 80.91.229.3 (2 May 2013 12:31:41 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Thu, 2 May 2013 12:31:41 +0000 (UTC) To: 14334@debbugs.gnu.org Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Thu May 02 14:31:40 2013 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1UXsfj-00037q-PW for geb-bug-gnu-emacs@m.gmane.org; Thu, 02 May 2013 14:31:40 +0200 Original-Received: from localhost ([::1]:46110 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UXsfj-0002eU-B1 for geb-bug-gnu-emacs@m.gmane.org; Thu, 02 May 2013 08:31:39 -0400 Original-Received: from eggs.gnu.org ([208.118.235.92]:59629) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UXsfd-0002eI-BG for bug-gnu-emacs@gnu.org; Thu, 02 May 2013 08:31:34 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1UXsfY-0000QM-Db for bug-gnu-emacs@gnu.org; Thu, 02 May 2013 08:31:33 -0400 Original-Received: from debbugs.gnu.org ([140.186.70.43]:50621) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UXsfY-0000QC-9t for bug-gnu-emacs@gnu.org; Thu, 02 May 2013 08:31:28 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.72) (envelope-from ) id 1UXsg6-000186-1H for bug-gnu-emacs@gnu.org; Thu, 02 May 2013 08:32:02 -0400 X-Loop: help-debbugs@gnu.org Resent-From: =?UTF-8?Q?=C3=93scar?= Fuentes Original-Sender: debbugs-submit-bounces@debbugs.gnu.org Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Thu, 02 May 2013 12:32:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: report 14334 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: X-Debbugs-Original-To: bug-gnu-emacs@gnu.org Original-Received: via spool by submit@debbugs.gnu.org id=B.13674979034294 (code B ref -1); Thu, 02 May 2013 12:32:01 +0000 Original-Received: (at submit) by debbugs.gnu.org; 2 May 2013 12:31:43 +0000 Original-Received: from localhost ([127.0.0.1]:54729 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.72) (envelope-from ) id 1UXsfm-000176-4I for submit@debbugs.gnu.org; Thu, 02 May 2013 08:31:42 -0400 Original-Received: from eggs.gnu.org ([208.118.235.92]:48122) by debbugs.gnu.org with esmtp (Exim 4.72) (envelope-from ) id 1UXsfh-00016r-6v for submit@debbugs.gnu.org; Thu, 02 May 2013 08:31:39 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1UXsf5-0000FB-V2 for submit@debbugs.gnu.org; Thu, 02 May 2013 08:31:02 -0400 Original-Received: from lists.gnu.org ([208.118.235.17]:55682) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UXsf5-0000F7-RO for submit@debbugs.gnu.org; Thu, 02 May 2013 08:30:59 -0400 Original-Received: from eggs.gnu.org ([208.118.235.92]:59477) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UXsf4-0002c5-4p for bug-gnu-emacs@gnu.org; Thu, 02 May 2013 08:30:59 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1UXsey-0000Cp-Sv for bug-gnu-emacs@gnu.org; Thu, 02 May 2013 08:30:58 -0400 Original-Received: from impaqm4.telefonica.net ([213.4.138.20]:26917 helo=telefonica.net) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UXsey-0000CE-CV for bug-gnu-emacs@gnu.org; Thu, 02 May 2013 08:30:52 -0400 Original-Received: from IMPmailhost5.adm.correo ([10.20.102.126]) by IMPaqm4.telefonica.net with bizsmtp id Wvrr1l00T2jdgqJ3Q0WqhP; Thu, 02 May 2013 14:30:50 +0200 Original-Received: from qcore ([83.40.116.149]) by IMPmailhost5.adm.correo with BIZ IMP id X0Wn1l00l3DUQuj1l0WoZG; Thu, 02 May 2013 14:30:49 +0200 X-CMAE-Analysis: v=1.1 cv=bANl1MxOKKE0XAgTJ5KDo1Nh9SH0otGhU58K7+V3S60= c=1 sm=1 a=DQlLCnKHR5QA:10 a=5XuOO5ARXv8A:10 a=sSE9TqpJnXXWdi4WNHITQg==:17 a=NEAV23lmAAAA:8 a=aR16PxjQAAAA:8 a=nKQeYurI0hwwgO1Ddd0A:9 a=CiSHi91Bn78A:10 a=fFFQV2gLAAAA:8 a=ZQJETNVY014h-2RWaEwA:9 a=lDPeAoKtc-EA:10 a=O_8ClqRTTNDnCnbB:21 a=BSH-LItkSZzzGXoG:21 a=ByQ3zSdK6Dplk8APv3EA:9 a=piO7owlCDg3dWo9g:21 a=kddG6-Bz2E3ZvkZP:21 a=sSE9TqpJnXXWdi4WNHITQg==:117 X-original-sender: 981711563@telefonica.net User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.3.50 (gnu/linux) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6.x X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6.x X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.13 Precedence: list X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6.x X-Received-From: 140.186.70.43 X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Original-Sender: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.bugs:73891 Archived-At: --=-=-= Content-Type: text/plain Found this problem while experimenting with the flx package ( https://github.com/lewang/flx ). Put the two attached files somewhere on you load-path. emacs -Q eval this: (require 'flx-ido) (ido-mode 1) (setq ido-enable-flex-matching t) (setq flx-ido-use t) Now do C-x b for switching to another buffer. Once the list of candidates is shown, press C-s (which would usually cycle to the next candidate.) Emacs will start using 100% CPU and consuming memory at a very quick rate. C-g makes Emacs responsive again. flx developer reported that the bug is not reproducible on his Emacs 24.3.1. The original bug report is here: https://github.com/lewang/flx/issues/6 In GNU Emacs 24.3.50.5 (x86_64-unknown-linux-gnu, X toolkit) of 2013-04-06 on qcore Windowing system distributor `The X.Org Foundation', version 11.0.11303000 System Description: Ubuntu 13.04 Configured using: `configure --with-x-toolkit=lucid --without-toolkit-scroll-bars' Important settings: value of $LANG: en_US.UTF-8 locale-coding-system: utf-8-unix default enable-multibyte-characters: t Major mode: Lisp Interaction Minor modes in effect: tooltip-mode: t mouse-wheel-mode: t tool-bar-mode: t menu-bar-mode: t file-name-shadow-mode: t global-font-lock-mode: t font-lock-mode: t blink-cursor-mode: t auto-composition-mode: t auto-encryption-mode: t auto-compression-mode: t line-number-mode: t transient-mark-mode: t Recent input: Recent messages: For information about GNU Emacs and the GNU system, type C-h C-a. Starting new Ispell process [/usr/bin/aspell::default] ... Checking spelling of INDEFINITITELY... byte-code: Window # too small for splitting Load-path shadows: None found. Features: (shadow sort gnus-util mail-extr ispell emacsbug message format-spec rfc822 mml easymenu mml-sec mm-decode mm-bodies mm-encode mail-parse rfc2231 mailabbrev gmm-utils mailheader sendmail rfc2047 rfc2045 ietf-drums mm-util mail-prsvr mail-utils time-date tooltip ediff-hook vc-hooks lisp-float-type mwheel x-win x-dnd tool-bar dnd fontset image regexp-opt fringe tabulated-list newcomment lisp-mode register page menu-bar rfn-eshadow timer select scroll-bar mouse jit-lock font-lock syntax facemenu font-core frame cham georgian utf-8-lang misc-lang vietnamese tibetan thai tai-viet lao korean japanese hebrew greek romanian slovak czech european ethiopic indian cyrillic chinese case-table epa-hook jka-cmpr-hook help simple abbrev minibuffer loaddefs button faces cus-face macroexp files text-properties overlay sha1 md5 base64 format env code-pages mule custom widget hashtable-print-readable backquote make-network-process inotify dynamic-setting font-render-setting x-toolkit x multi-tty emacs) --=-=-= Content-Type: application/emacs-lisp Content-Disposition: attachment; filename=flx-ido.el Content-Transfer-Encoding: quoted-printable ;;; flx-ido.el --- flx integration for ido ;; this file is not part of Emacs ;; Copyright (C) 2013 Le Wang ;; Author: Le Wang ;; Maintainer: Le Wang ;; Description: flx integration for ido ;; Author: Le Wang ;; Maintainer: Le Wang ;; Created: Sun Apr 21 20:38:36 2013 (+0800) ;; Version: 0.1 ;; Last-Updated: ;; By: ;; Update #: 2 ;; URL: ;; Keywords: ;; Compatibility: ;;; Installation: ;; Add to your init file: ;; ;; (require 'flx-ido) ;; (setq ido-enable-flex-matchint t ;; flx-ido-use t) ;; ;; ;;; Commentary: ;; ;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; 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. ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; ;;; credit to Scott Frazer's blog entry here:http://scottfrazersblog.blogsp= ot.com.au/2009/12/emacs-better-ido-flex-matching.html ;;; ;;; Code: (eval-when-compile (require 'cl)) (require 'ido) (require 'flx) (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 (flx-ido-undecorate items)) (let (best-match exact res) (loop for key being the hash-key of flx-ido-narrowed-matches-hash do (when (and (>=3D (length query) (length key)) (eq t (compare-strings query 0 (min (length query) (length key)) key 0 nil)) (> (length key) (length best-match))) (setq best-match key) (when (=3D (length key) (length query)) (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-narr= owed-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) (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 (substring-no-properties thing) ;; copy the string in case it's "pure" (flx-propertize (copy-sequence (car thing)) (cdr thing= )))) (if clear (nthcdr decorate-count things) (mapcar 'car (nthcdr decorate-count things)))))) (defun flx-ido-match (query items) "Better sorting for flx ido matching." (destructuring-bind (exact items) (flx-ido-narrowed query items) (if exact ; `ido-rotate' case is covered by exa= ct match items (let* ((matches (loop for item in items for score =3D (flx-score item query flx-file-ca= che) if score collect (cons item score) into matches finally return matches)) res) (setq res (flx-ido-decorate (sort matches (lambda (x y) (> (cadr x) (cadr y= )))))) (puthash query res flx-ido-narrowed-matches-hash))))) (defvar flx-ido-use t "Use flx matching for ido.") (defadvice ido-read-internal (before flx-ido-reset-hash activate) "clear our narrowed hash." (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 (and flx-ido-use ido-enable-flex-matching) (setq ad-return-value (flx-ido-match ido-text (ad-get-arg 0))) ad-do-it)) (provide 'flx-ido) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; flx-ido.el ends here --=-=-= Content-Type: application/emacs-lisp Content-Disposition: attachment; filename=flx.el Content-Transfer-Encoding: quoted-printable ;;; flx.el --- fuzzy matching with good sorting ;; this file is not part of Emacs ;; Copyright (C) 2013 Le Wang ;; Author: Le Wang ;; Maintainer: Le Wang ;; Description: fuzzy matching with good sorting ;; Author: Le Wang ;; Maintainer: Le Wang ;; Created: Wed Apr 17 01:01:41 2013 (+0800) ;; Version: 0.1 ;; Last-Updated: ;; By: ;; Update #: 3 ;; URL: ;; Keywords: ;; Compatibility: ;;; Installation: ;; ;; ;; ;;; Commentary: ;; ;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; 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. ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Code: ;;; credit to scott frazer's blog entry here:http://scottfrazersblog.blogsp= ot.com.au/2009/12/emacs-better-ido-flex-matching.html ;;; credit to ido-hacks for ido optimization ;;; Use defsubst instead of defun ;;; Notes: ;;; ;;; * 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 benef= its ;;; of an optimization. ;;; (eval-when-compile (require 'cl)) (defface flx-highlight-face '((t (:inherit font-lock-variable-name-face :b= old 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-is-word (char) "returns t if char is word" (and char (not (memq char '(?\ ?- ?_ ?. ?/ ?\\))))) (defsubst flx-is-capital (char) "returns t if char is word" (and char (and (<=3D char ?Z) (<=3D ?A char)))) (defsubst flx-is-boundary (last-char char) (or (flx-is-capital char) (null last-char) (and (not (flx-is-word last-char)) (flx-is-word char)))) (defsubst flx-inc-vec (vec &optional inc beg end) "increment each element of vectory by INC(default=3D1) 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 =3D nil with group-word-count =3D 0 do (progn (let ((effective-last-char ;; before we find any words, all separaters are ;; considered words of length 1. This is so "foo/__a= b" ;; gets penalized compared to "foo/ab". (if (zerop group-word-count) nil last-char))) (when (flx-is-boundary effective-last-char char) (setcdr (cdar groups-alist) (cons index (cddar groups-al= ist)))) (when (and (not (flx-is-word last-char)) (flx-is-word 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 (=3D 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 =3D 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 (not last-group-limit))) (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 (=3D index 0) -3 (+ -5 (1- index))))) (flx-inc-vec scores num (1+ group-start) last-group-limi= t)) (loop for word in (cddr group) for word-index from (1- words-length) downto 0 with last-word =3D (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" (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)) (best-score nil)) (mapc (lambda (match-vector) (let ((score 0) (contiguous-count 0) last-match) (loop for index in match-vector do (progn (if (and last-match (=3D (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-vector))))) matches) best-score))) (defun flx-propertize (str score &optional add-score) "Return propertized string according to score." (let ((block-started (cadr score)) (last-char nil)) (loop for char in (cdr score) do (progn (when (and last-char (not (=3D (1+ last-char) char))) (put-text-property block-started (1+ last-char) 'face 'fl= x-highlight-face str) (setq block-started char)) (setq last-char char))) (put-text-property block-started (1+ last-char) 'face 'flx-highlight-f= ace str) (when add-score (setq str (format "%s [%s]" str (car score)))) 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 --=-=-=--