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

Reply via email to