### 8.6 Fuzzy Completion ¶

The package `slime-fuzzy` implements yet another symbol completion heuristic.

`C-c M-i` ¶
`M-x slime-fuzzy-complete-symbol`

  Presents a list of likely completions to choose from for an abbreviation at point. If you set the variable `slime-complete-symbol-function` to this command, fuzzy completion will also be used for `M-TAB`.

#### 8.6.1 The Algorithm ¶

It attempts to complete a symbol all at once, instead of in pieces. For example, “mvb” will find “`multiple-value-bind`” and “norm-df” will find “`least-positive-normalized-double-float`”.

The algorithm tries to expand every character in various ways and rates the list of possible completions with the following heuristic.

Letters are given scores based on their position in the string. Letters at the beginning of a string or after a prefix letter at the beginning of a string are scored highest. Letters after a word separator such as #\- are scored next highest. Letters at the end of a string or before a suffix letter at the end of a string are scored medium, and letters anywhere else are scored low.

If a letter is directly after another matched letter, and its intrinsic value in that position is less than a percentage of the previous letter’s value, it will use that percentage instead.

Finally, a small scaling factor is applied to favor shorter matches, all other things being equal.

#### 8.6.2 Duplicate Symbols ¶

In case a symbol is accessible via several packages, duplicate symbol filter specified via `*fuzzy-duplicate-symbol-filter*` swank variable is applied. `:nearest-package` value specifies that only symbols in the package with highest score should be kept. `:home-package` specifies that only the match that represents the home package of the symbol is used, and `:all` value specifies that duplicate symbol filter mode should be turned off.

To specify a custom filter, set `*fuzzy-duplicate-symbol-filter*` to a function accepting three arguments: the name of package being examined, the list of names of all packages being examined with packages with highest matching score listed first and an `equal` hash-table that is shared between calls to the function and can be used for deduplication purposes. The function should return a deduplication filter function which accepts a symbol and returns true if the symbol should be kept.

For example, the effect of `:nearest-package` can be also achieved by specifying the following custom filter in `~/.swank.lisp`:

    (setf *fuzzy-duplicate-symbol-filter*
          (lambda (cur-package all-packages dedup-table)
            (declare (ignore cur-package all-packages))
            (lambda (symbol)
               (unless (gethash (symbol-name symbol) dedup-table)
                  (setf (gethash (symbol-name symbol) dedup-table) t)))))

And instead of `:home-package`, the following can be used:

    (setf *fuzzy-duplicate-symbol-filter*
          (lambda (cur-package all-packages dedup-table)
            (declare (ignore dedup-table))
            (let ((packages (mapcar #'find-package
                                    (remove cur-package all-packages))))
              (lambda (symbol)
                (not (member (symbol-package symbol) packages))))))