branch: externals/company commit e31d39350bdf7e13d2361f1e54135eba87c3b031 Author: Dmitry Gutov <dmi...@gutov.dev> Commit: Dmitry Gutov <dmi...@gutov.dev>
New option `company-dabbrev-code-completion-styles` #1215 --- NEWS.md | 10 +++++++ company-dabbrev-code.el | 75 ++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 68 insertions(+), 17 deletions(-) diff --git a/NEWS.md b/NEWS.md index c12124deb2..a5608dfeb6 100644 --- a/NEWS.md +++ b/NEWS.md @@ -2,6 +2,16 @@ # Next +* New user option `company-dabbrev-code-completion-styles`. Use it to enable + fuzzy matching in `company-dabbrev-code` + ([#1215](https://github.com/company-mode/company-mode/pull/1215)). An example + configuration one can try: + +```el +(setq company-dabbrev-code-ignore-case t + company-dabbrev-code-completion-styles '(basic flex)) +``` + * The backend command `keep-prefix` is being phased out. The built-in backends implement it internally now, which resolved a number of sharp edges (mostly) around "grouped" backends. To make that easier, several helpers were added, diff --git a/company-dabbrev-code.el b/company-dabbrev-code.el index 4eddf38e0a..fd8a1abbc1 100644 --- a/company-dabbrev-code.el +++ b/company-dabbrev-code.el @@ -1,6 +1,6 @@ ;;; company-dabbrev-code.el --- dabbrev-like company-mode backend for code -*- lexical-binding: t -*- -;; Copyright (C) 2009-2011, 2013-2016, 2021 Free Software Foundation, Inc. +;; Copyright (C) 2009-2011, 2013-2016, 2021-2023 Free Software Foundation, Inc. ;; Author: Nikolaj Schumacher @@ -69,11 +69,29 @@ also `company-dabbrev-code-time-limit'." "Non-nil to ignore case when collecting completion candidates." :type 'boolean) +(defcustom company-dabbrev-code-completion-styles nil + "Non-nil to use the completion styles for fuzzy matching." + :type '(choice (const :tag "Prefix matching only" nil) + (const :tag "Matching according to `completion-styles'" t) + (list :tag "Custom list of styles" symbol))) + (defun company-dabbrev-code--make-regexp (prefix) - (concat "\\_<" (if (equal prefix "") - "\\([a-zA-Z]\\|\\s_\\)" - (regexp-quote prefix)) - "\\(\\sw\\|\\s_\\)*\\_>")) + (let ((prefix-re + (cond + ((equal prefix "") + "\\([a-zA-Z]\\|\\s_\\)") + ((not company-dabbrev-code-completion-styles) + (regexp-quote prefix)) + (t + ;; Use the cache at least after 2 chars. We could also cache + ;; earlier, for users who set company-min-p-l to 1 or 0. + (let ((prefix (if (>= (length prefix) 2) + (substring prefix 0 2) + prefix))) + (mapconcat #'regexp-quote + (string-split prefix "" t) + "\\(\\sw\\|\\s_\\)*")))))) + (concat "\\_<" prefix-re "\\(\\sw\\|\\s_\\)*\\_>"))) ;;;###autoload (defun company-dabbrev-code (command &optional arg &rest _ignored) @@ -88,21 +106,44 @@ comments or strings." (or company-dabbrev-code-everywhere (not (company-in-string-or-comment))) (or (company-grab-symbol) 'stop))) - (candidates (let ((case-fold-search company-dabbrev-code-ignore-case) - (completion-ignore-case company-dabbrev-code-ignore-case)) - (all-completions - "" - (company-dabbrev--search - (company-dabbrev-code--make-regexp arg) - company-dabbrev-code-time-limit - (pcase company-dabbrev-code-other-buffers - (`t (list major-mode)) - (`code company-dabbrev-code-modes) - (`all `all)) - (not company-dabbrev-code-everywhere))))) + (candidates + (let* ((case-fold-search company-dabbrev-code-ignore-case) + (regexp (company-dabbrev-code--make-regexp arg))) + (company-dabbrev-code--filter + arg + (company-cache-fetch + 'dabbrev-code-candidates + (lambda () + (company-dabbrev--search + regexp + company-dabbrev-code-time-limit + (pcase company-dabbrev-code-other-buffers + (`t (list major-mode)) + (`code company-dabbrev-code-modes) + (`all `all)) + (not company-dabbrev-code-everywhere))) + :expire t + :check-tag regexp)))) (kind 'text) + (no-cache t) (ignore-case company-dabbrev-code-ignore-case) (duplicates t))) +(defun company-dabbrev-code--filter (prefix table) + (let ((completion-ignore-case company-dabbrev-code-ignore-case) + (completion-styles (if (listp company-dabbrev-code-completion-styles) + company-dabbrev-code-completion-styles + completion-styles)) + res) + (if (not company-dabbrev-code-completion-styles) + (all-completions prefix table) + (setq res (completion-all-completions + prefix + table + nil (length prefix))) + (if (numberp (cdr (last res))) + (setcdr (last res) nil)) + res))) + (provide 'company-dabbrev-code) ;;; company-dabbrev-code.el ends here