• Stars
    star
    120
  • Rank 295,983 (Top 6 %)
  • Language
    Emacs Lisp
  • License
    GNU General Publi...
  • Created over 5 years ago
  • Updated 5 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Fuzzy matching for `company-mode'

License: GPL v3 JCS-ELPA MELPA MELPA Stable

company-fuzzy

Fuzzy matching for `company-mode'.

CI

Pure elisp fuzzy completion for company-mode. This plugin search through all the buffer local company-backends and fuzzy search all candidates.

πŸ† Features

  • Work across all backends - Any backend that gives list of string should work.
  • Only uses native elisp code - I personally don't prefer any external program unless is necessary.
  • Combined all backends to one backend - Opposite to company-try-hard, hence all possible candidates will be shown in the auto-complete menu.

πŸ§ͺ Differences from other alternatives

  • company-ycmd
    • Uses ycmd as backend to provide functionalities.
    • Quite hard to config properly.
  • company-flx
    • Uses library flx. (Optional for us)
    • Only works with capf backend currently.

πŸ’Ύ Quickstart

(use-package company-fuzzy
  :hook (company-mode . company-fuzzy-mode)
  :init
  (setq company-fuzzy-sorting-backend 'flx
        company-fuzzy-prefix-on-top nil
        company-fuzzy-trigger-symbols '("." "->" "<" "\"" "'" "@")))

πŸ”§ Usage

You can enable it globally by adding this line to your config

(global-company-fuzzy-mode 1)

Or you can just enable it in any specific buffer/mode you want.

(company-fuzzy-mode 1)

Make sure you call either of these functions after all company-backends are set and config properly. Because this plugin will replace all backends to this minor mode specific backend (basically take all backends away, so this mode could combine all sources and do the fuzzy work).

πŸ” Sorting/Scoring backend

There are multiple sorting algorithms for auto-completion. You can choose your own backend by customize company-fuzzy-sorting-backend variable like this.

(setq company-fuzzy-sorting-backend 'alphabetic)

Currently supports these values,

  • none - Gives you the raw result.
  • alphabetic - Sort in the alphabetic order. (VSCode)
  • flex - Use library flex as matching engine.
  • flx - Use library flx as matching engine. (Sublime Text)
  • flx-rs - Use library flx-rs as matching engine. (Sublime Text)
  • flxy - Use library flxy as matching engine.
  • fuz-skim - Use library fuz.el's skim algorithm.
  • fuz-clangd - Use library fuz.el's clangd algorithm.
  • fuz-bin-skim - Use library fuz-bin's skim algorithm.
  • fuz-bin-clangd - Use library fuz-bin's clangd algorithm.
  • liquidmetal - Use library liquidmetal similar to Quicksilver algorithm.
  • sublime-fuzzy - Use library sublime-fuzzy as matching engine. (Sublime Text)

Or implements your sorting algorithm yourself? Assgin the function to company-fuzzy-sorting-function variable like this.

(setq company-fuzzy-sorting-function (lambda (candidates)
                                       (message "%s" candidates)
                                       candidates))  ; Don't forget to return the candidaites!

πŸ” Prefix On Top

If you wish the prefix matchs on top of all other selection, customize this variable to t like the line below.

(setq company-fuzzy-prefix-on-top t)

P.S. If you set company-fuzzy-sorting-backend to 'flx then you probably don't need this to be on because the flx scoring engine already take care of that!

πŸ” For annotation

You can toggle company-fuzzy-show-annotation for showing annotation or not.

(setq company-fuzzy-show-annotation t)

You can also customize annotation using format variable.

  • company-fuzzy-annotation-format => <%s>

πŸ” Excluding

You can customize variable company-fuzzy-passthrough-backends to exclude some of the backends from polluting the fuzzy matching.

(setq company-fuzzy-passthrough-backends '(company-capf))

P.S. This is design to use with semantic backends, like lsp-mode (uses company-capf) , or eglot, etc.

πŸ’¬ Details

Since company granted most control to users, every company backend developer has different method of implementing company backend. It is hard to manage all backends to one by varies of rules.

Recommended Settings

There are something that company design it weirdly, in order to make this plugin work smoothly I would recommend these company's variables to be set.

(use-package company
  :init
  (setq company-require-match nil            ; Don't require match, so you can still move your cursor as expected.
        company-tooltip-align-annotations t  ; Align annotation to the right side.
        company-eclim-auto-save nil          ; Stop eclim auto save.
        company-dabbrev-downcase nil)        ; No downcase when completion.
  :config
  ;; Enable downcase only when completing the completion.
  (defun jcs--company-complete-selection--advice-around (fn)
    "Advice execute around `company-complete-selection' command."
    (let ((company-dabbrev-downcase t))
      (call-interactively fn)))
  (advice-add 'company-complete-selection :around #'jcs--company-complete-selection--advice-around))

P.S. For the full configuration, you can check out my configuration here.

❓ FAQ

πŸ’« Why is company-fuzzy not working?

Try to log out the company-backends and make sure company-fuzzy-all-other-backends is the only backend in your list. If it's not, enable company-fuzzy-mode to swap out all backends and hand it over to company-fuzzy to manage it.

(message "%s" company-backends)         ; '(company-fuzzy-all-other-backends)
(message "%s" company-fuzzy--backends)  ; .. backends has been handed over to `company-fuzzy`

πŸ’« When should I call company-fuzzy-mode?

You should call company-fuzzy-mode after you have done configured variable company-backends.

(setq company-backends '(company-capf company-yasnippets)  ; configure backends

.. (other configuration)

(company-fuzzy-mode 1)                                     ; enable fuzzy matching at the very last

πŸ’« What if I want to add backends to specific major-mode?

You can add any backends as long as you call company-fuzzy-mode at the very end of your mode hook. You can log out variable company-fuzzy--backends and see what backends are currently handled by company-fuzzy-mode!

Or, you can hack through by configuring variable company-fuzzye--backends directly but this is not recommended since after you disable company-fuzzy-mode it will not be restored back to company-backends. Unless you change it with variable company-fuzzy--recorded-backends simutamiously so it can be restored back to your company-backends' true form.

❗ UPDATE: You can now use the following functions to accomplish these tasks in a much elegant way:

(company-fuzzy-backend-add    'company-capf)
(company-fuzzy-backend-remove 'company-yasnippets)

πŸ’« Why do some candidates aren't showing up?

This can cause by various reasons. The common causes are:

πŸ”Ž 1. Cause by Semantic backend rules

company-fuzzy respects backends' rule. Meaning the candidates can be restricted by the backend you are using. For example,

(defvar my-variable)  ; You declare a variable

(my-vari.. )          ; but you are trying to use the variable as a function

The my-variable would not show up since the backend thinks it should be a function and not a variable.

πŸ”Ž 2. Cause by completion-styles

Candidates are first filtered by Emacs built-on completion engine. Try tweaking the variable completion-styles with other possible options.

(setq completion-styles '(partial-completion))

Or hook up with the company's hooks:

(add-hook 'company-completion-started-hook
          (lambda ()
            (setq completion-styles '(partial-completion))))

(add-hook 'company-after-completion-hook
          (lambda ()
            ;; Revert `completion-styles' to original values
            (setq completion-styles ..)))

See Completion Alternatives for more information.

πŸ”Ž 3. Scores lower than 0

Another cause would be the candidate has been eliminated by the scoring engine (it scores lower than 0); hence it would not be shown.

Best way to debug this, is to feed query and candidate to the scoring functions. The following example uses flx:

(flx-score "window-system" "win-sys")  ; return score and it's match data

Another example using the liquidmetal:

(liquidmetal-score "window-system" "win-sys")  ; return score

πŸ’« Why are some variables not respected with special symbols? (@, :, etc)

company-fuzzy detects prefix depends on the Syntax Table . And those special symbols normally doesn't get treated as a whole prefix, hence you should see the completion get inserted incorrectly,

<!-- Try to complete `:link:` emoji -->
:lin

<!-- WRONG, the symbol `:` colon doesn't count as a prefix -->
::link:

How to solve this? You should configure your syntax table by doing something similar to

(add-hook 'markdown-mode-hook (lambda () (modify-syntax-entry ?: "w"))

See related issue #22 (ruby-mode with @ symbol).

Contribute

PRs Welcome Elisp styleguide Donate on paypal Become a patron

If you would like to contribute to this project, you may either clone or make pull requests to this repository. Or you can clone the project and establish your branch of this tool. Any methods are welcome!

More Repositories

1

transwin

Make window/frame transparent.
Emacs Lisp
32
star
2

parse-it

Basic Parser in Emacs Lisp.
Emacs Lisp
25
star
3

ffmpeg-player

Play video using ffmpeg.
Emacs Lisp
22
star
4

flx-rs

flx in Rust using dynamic module
Emacs Lisp
21
star
5

indent-control

Generic control the indentation level for each mode.
Emacs Lisp
18
star
6

define-it

Define, translate, wiki the word.
Emacs Lisp
16
star
7

use-ttf

Keep font consistency across different OSs.
Emacs Lisp
16
star
8

manage-minor-mode-table

Manage minor-modes in table.
Emacs Lisp
15
star
9

com-css-sort

Common way of sorting the CSS attributes.
Emacs Lisp
15
star
10

license-templates

Create LICENSE using GitHub API
Emacs Lisp
14
star
11

organize-imports-java

Automatically organize imports in Java code.
Emacs Lisp
14
star
12

reveal-in-folder

Reveal current file/directory in folder.
Emacs Lisp
13
star
13

better-scroll

Improve user experience when scrolling window.
Emacs Lisp
13
star
14

impatient-showdown

Preview markdown buffer live over HTTP.
Emacs Lisp
12
star
15

show-eol

Show end of line symbol in buffer.
Emacs Lisp
12
star
16

marquee-header

Code interface for displaying marquee in header.
Emacs Lisp
12
star
17

preview-it

Preview anything at point.
Emacs Lisp
11
star
18

company-emojify

Company completion for Emojify
Emacs Lisp
10
star
19

project-abbrev

Customize your own abbreviation expansion in the project.
Emacs Lisp
10
star
20

logms

Log message with clickable links to context
Emacs Lisp
9
star
21

diminish-buffer

Diminish (hide) buffers from buffer-menu.
Emacs Lisp
8
star
22

isearch-project

Incremental search through the whole project.
Emacs Lisp
8
star
23

file-header

Highly customizable self design file header. (Emacs)
Emacs Lisp
7
star
24

searcher

Searcher in pure elisp
Emacs Lisp
7
star
25

nerd-icons-buffer-menu

Display nerd icons in buffer-menu.
Emacs Lisp
6
star
26

elenv

Environment variable management
Emacs Lisp
6
star
27

ansi-colorful

Toggle render ansi-color
Emacs Lisp
6
star
28

package-bot

Review new package PR on MELPA automatically
JavaScript
5
star
29

msgu

Utility functions help output the messages
Emacs Lisp
5
star
30

multi-shell

Managing multiple shell buffers.
Emacs Lisp
5
star
31

emoji-github

Display list of GitHub's emoji. (cheat sheet)
Emacs Lisp
5
star
32

toggle-quotes-plus

Simple quote toggler that cycle through " ' and `
Emacs Lisp
5
star
33

guard-lf

Guard large files
Emacs Lisp
5
star
34

undo-tree-vf

visualizer follow mode for undo-tree
Emacs Lisp
4
star
35

prt

Progress Reporter Library (Emacs)
Emacs Lisp
4
star
36

ic

Pretty print to debug
Emacs Lisp
4
star
37

emp

Emacs Music Playlist
Emacs Lisp
3
star
38

vertico-flx

flx integration for vertico
Emacs Lisp
3
star
39

message-clean-mode

Keep messages buffer clean
Emacs Lisp
3
star
40

ffpc

Find file in project or current directory
Emacs Lisp
3
star
41

buffer-menu-filter

Filter buffer-menu items using fake header
Emacs Lisp
3
star
42

github-tags

Retrieve tags information through GitHub API
Emacs Lisp
2
star
43

8comic

[WIP] Use 8comic to read manga.
Emacs Lisp
2
star
44

alt-codes

Insert alt codes using meta key.
Emacs Lisp
2
star
45

turbo-log

Automating the process of writing meaningful log messages.
Emacs Lisp
2
star
46

buffer-menu-project

List buffers relative to project
Emacs Lisp
2
star
47

buffer-wrap

Wrap the beginning and the end of buffer.
Emacs Lisp
2
star
48

fill-page

Fill the buffer so you don't see empty lines at the end.
Emacs Lisp
2
star
49

vc-refresh

Refresh vc-state in certain events for better UX
Emacs Lisp
1
star
50

easy-tabulated-list

Simplify usage for `tabulated-list'.
Emacs Lisp
1
star
51

modablist

Modifiable tabulated-list extension.
Emacs Lisp
1
star
52

sound-async

Play sound asynchronously
Emacs Lisp
1
star
53

watch-cursor

Display cursor from all live windows
Emacs Lisp
1
star
54

cursor-preview

Preivew cursor movement while executing command interactively.
Emacs Lisp
1
star
55

responsive-window

Adapt to different screen sizes automatically
Emacs Lisp
1
star
56

repos-window

Reposition window when needed
Emacs Lisp
1
star
57

flx-style

Completion style for flx
Emacs Lisp
1
star
58

qss-mode

Major mode for Qt Style Sheets
Emacs Lisp
1
star
59

helafy

minify/uglify/prettify contents
Emacs Lisp
1
star
60

recentf-excl

Exclude commands for recent files
Emacs Lisp
1
star