jcs-elpa / company-fuzzy

Fuzzy matching for `company-mode'
GNU General Public License v3.0
121 stars 9 forks source link

Report special case for company backend #12

Open jcs090218 opened 4 years ago

jcs090218 commented 4 years ago

This thread is a special thread to let other users to report the company backends that isn't working properly with this package. Please report any company backend that isn't working properly with this package.


These backends are special backends that have to implemented individually.

πŸ” Backends must take it's own prefix

πŸ” Backends parse prefix with no strong connection between candidates and prefix commands

πŸ” Unresolved (not working)


Here is list of confirmed normal cases. That said, you don't have to do any special implementation to these backends. And do NOT add it to company-fuzzy-history-backends list.

πŸ” Normal (working properly)

TrunovS commented 4 years ago

@jcs090218 Can't get candidates with company-c-headers. (add-to-list 'company-fuzzy-full-input-backends 'company-c-headers) seems to do nothing.

jcs090218 commented 4 years ago

@TrunovS Hi! I have tested company-c-headers and it works like other backends! So I assumed you don't need to add company-c-headers to company-fuzzy-full-input-backends. That said, the backend company-c-headers isn't a special case! Hope this helps! πŸ˜„

TrunovS commented 4 years ago

@jcs090218 Found the culprit! When variable company-c-headers-path-user set (for example in user defined include dir) company-c-headers--candidates works very strange. In some cases it expects prefix with first symbol \". company-fuzzy--match-char splits prefix by symbols and prepares without one? Not sure that problem in company-fuzzy. Very strange way to differentiate between cases in company-c-headers--candidates.

(defun company-c-headers--candidates (prefix)
  "Return candidates for PREFIX."
  (let ((p (if (equal (aref prefix 0) ?\")
               (call-if-function company-c-headers-path-user)
             (call-if-function company-c-headers-path-system)))
        (next (when (equal (aref prefix 0) ?\")
                (call-if-function company-c-headers-path-system)))
        candidates)
    (while p
      (when (file-directory-p (car p))
        (setq candidates (append candidates (company-c-headers--candidates-for prefix (car p)))))

      (setq p (or (cdr p)
                  (let ((tmp next))
                    (setq next nil)
                    tmp)))
      )
    (cl-remove-duplicates candidates :test 'equal)
    ))

In system include directories everything works fine.) Maybe there is a way to make company-fuzzy ignore some company-backends and do default completition without fuzzy?

jcs090218 commented 4 years ago

Okay, there are many problems here.

[company-c-headers]() don't return list of candidates without the correct prefix, which are " and <. It's common to see if the completion is base on the prefix, but with the current implementation I am not able to get candidates the way I have already implemented here. See fd1e79b8ab75e0ea61cfd9598ed3ae8dbef960b2; and this should return a better prefix. Try the latest version (0.8.2), and this issue should be resolved.

CsBigDataHub commented 4 years ago

company-keywords backend is not working after the update.

current package-version - company-fuzzy-20201020-1552

emacs-version - 27.1

company-version - 0.9.13 - package-version = company-20201004.735

Update :

Can confirm that it is working until this commit - 2f70e6fe78c45d0cbbb22b1d994f90aa9c78553b I have tested it using quelpa.

(use-package company-fuzzy
  :quelpa
  (company-fuzzy
   :fetcher github
   :repo "jcs-elpa/company-fuzzy"
   :commit "2f70e6fe78c45d0cbbb22b1d994f90aa9c78553b"
   )
  :init
  (setq company-fuzzy-sorting-backend 'flx)
  (setq company-fuzzy-prefix-ontop nil)
  (with-eval-after-load 'company
    (global-company-fuzzy-mode t)))
jcs090218 commented 4 years ago

company-keywords backend is not working after the update.

You sure about this? It works on my side. πŸ˜•

The newest version of company-fuzzy respects the order of your company-backends settings. On my end, I have this for my company-mode initial setup.

(setq company-backends
        (append
         ;; --- Internal ---
         '(company-capf company-semantic)
         '(company-abbrev company-dabbrev company-dabbrev-code)
         '(company-files)
         '(company-etags company-gtags)
         '(company-keywords company-yasnippet)
         ;; --- External ---
         '(company-emoji)))

The only issue I figured it out is that company-dabbrev is so broad and it somehow takes over company-keywords. If you want the annotation to show keywords instead of dabbrev then set company-keywords before company-dabbrev. Like the following snippet,

(setq company-backends
        (append
         ;; --- Internal ---
         '(company-capf company-semantic)
         '(company-keywords)    ; Put infront of `company-dabbrev'
         '(company-abbrev company-dabbrev company-dabbrev-code)
         '(company-files)
         '(company-etags company-gtags)
         '(company-yasnippet)
         ;; --- External ---
         '(company-emoji)))

Does company-keywords doesn't show up at all? πŸ˜•

CsBigDataHub commented 4 years ago

Yes company-keywords doesn't show up at all. It used to work fine earlier and that is the reason I have downgraded it.

I just tested it with jenkinsfile-mode, code - https://github.com/john2x/jenkinsfile-mode/blob/65bf3925852c35c6bd499978f08f83c1193f4347/jenkinsfile-mode.el#L299

Here is my company configuration -

(use-package company
  :diminish
  :defines (company-dabbrev-ignore-case company-dabbrev-downcase)
  :commands (company-cancel
             company-complete-common)
  :bind (("M-s-Γ·" . company-complete);;my-personal-config
         ("C-M-i" . company-complete)
         ("M-s-Ζ’" . company-files)
         ("M-s-i" . company-complete);;my-personal-config
         ("M-s-k" . company-keywords)
         ("M-s-p" . company-dabbrev)
         ("M-s-f" . company-files)
         :map company-mode-map
         ("<backtab>" . company-yasnippet)
         :map company-active-map
         ("C-p" . company-select-previous)
         ("C-n" . company-select-next)
         ("<tab>" . company-complete-common-or-cycle)
         ("<backtab>" . my-company-yasnippet)
         :map company-search-map
         ("C-p" . company-select-previous)
         ("C-n" . company-select-next))
  :hook (after-init . global-company-mode)
  :init
  (setq company-tooltip-align-annotations t
        company-tooltip-limit 12
        company-idle-delay 0
        company-echo-delay (if (display-graphic-p) nil 0)
        company-minimum-prefix-length 1
        company-show-numbers 'left ;;my-personal-config
        company-require-match nil
        company-dabbrev-code-everywhere t 
        company-dabbrev-code-modes t 
        company-dabbrev-other-buffers 'all 
        company-dabbrev-code-other-buffers 'all
        company-dabbrev-ignore-case t
        company-dabbrev-char-regexp "\\(\\sw\\|\\s_\\|_\\|-\\)" 
        company-dabbrev-downcase nil
        ;; company backend is my-personal-config
        ;; company-backends '(company-capf
        ;;  (company-dabbrev-code company-gtags company-etags
        ;;                        company-keywords)
        ;;  company-files
        ;;  company-dabbrev)
        ;; company backend is my-personal-config
        company-global-modes '(not erc-mode message-mode help-mode
                                   gud-mode eshell-mode shell-mode)
        company-backends '((company-capf :with company-yasnippet)
                           (company-dabbrev-code company-keywords company-files)
                           company-dabbrev))

  (defun my-company-yasnippet ()
    "Hide the current completeions and show snippets."
    (interactive)
    (company-cancel)
    (call-interactively 'company-yasnippet))
  :config
  ;; `yasnippet' integration
  (with-no-warnings
    (with-eval-after-load 'yasnippet
      (defun company-backend-with-yas (backend)
        "Add `yasnippet' to company backend."
        (if (and (listp backend) (member 'company-yasnippet backend))
            backend
          (append (if (consp backend) backend (list backend))
                  '(:with company-yasnippet))))

      (defun my-company-enbale-yas (&rest _)
        "Enable `yasnippet' in `company'."
        (setq company-backends (mapcar #'company-backend-with-yas company-backends)))

      (defun my-lsp-fix-company-capf ()
        "Remove redundant `comapny-capf'."
        (setq company-backends
              (remove 'company-backends (remq 'company-capf company-backends))))
      (advice-add #'lsp-completion--enable :after #'my-lsp-fix-company-capf)

      (defun my-company-yasnippet-disable-inline (fun command &optional arg &rest _ignore)
        "Enable yasnippet but disable it inline."
        (if (eq command 'prefix)
            (when-let ((prefix (funcall fun 'prefix)))
              (unless (memq (char-before (- (point) (length prefix)))
                            '(?. ?< ?> ?\( ?\) ?\[ ?{ ?} ?\" ?' ?`))
                prefix))
          (progn
            (when (and (bound-and-true-p lsp-mode)
                       arg (not (get-text-property 0 'yas-annotation-patch arg)))
              (let* ((name (get-text-property 0 'yas-annotation arg))
                     (snip (format "%s (Snippet)" name))
                     (len (length arg)))
                (put-text-property 0 len 'yas-annotation snip arg)
                (put-text-property 0 len 'yas-annotation-patch t arg)))
            (funcall fun command arg))))
      (advice-add #'company-yasnippet :around #'my-company-yasnippet-disable-inline)))

  ;;  remove completion on numbers
  ;; https://emacs.stackexchange.com/questions/9835/how-can-i-prevent-company-mode-completing-numbers
  ;; https://emacs.stackexchange.com/questions/35345/how-to-turn-off-autocompletion-for-numbers-and-numbers-only-in-company-mode-in
  ;; https://github.com/company-mode/company-mode/issues/358

  (push (apply-partially #'cl-remove-if
                         (lambda (c)
                           (or (string-match-p "[^\x00-\x7F]+" c)
                               (string-match-p "[0-9]+" c)
                               (string-match-p "\\`[0-9]+\\'" c)
                               ;;(if (equal major-mode "org")
                               ;;    (>= (length c) 15))
                               )))
        company-transformers)
  ;; my-personal - remove competion on numbers - end

  ;; Better sorting and filtering
  (use-package company-prescient
    :init (company-prescient-mode 1))

  ;; Icons and quickhelp
  (when emacs/>=26p
    (use-package company-box
      :diminish
      :defines company-box-icons-all-the-icons
      :hook (company-mode . company-box-mode)
      :init (setq company-box-enable-icon centaur-icon
                  company-box-backends-colors nil
                  company-box-doc-delay 0.3
                  company-box-highlight-prefix t
                  )
      :config
      (with-no-warnings
        ;; Prettify icons
        (defun my-company-box-icons--elisp (candidate)
          (when (or (derived-mode-p 'emacs-lisp-mode) (derived-mode-p 'lisp-mode))
            (let ((sym (intern candidate)))
              (cond ((fboundp sym) 'Function)
                    ((featurep sym) 'Module)
                    ((facep sym) 'Color)
                    ((boundp sym) 'Variable)
                    ((symbolp sym) 'Text)
                    (t . nil)))))
        (advice-add #'company-box-icons--elisp :override #'my-company-box-icons--elisp))

      (when (icons-displayable-p)
        (declare-function all-the-icons-faicon 'all-the-icons)
        (declare-function all-the-icons-material 'all-the-icons)
        (declare-function all-the-icons-octicon 'all-the-icons)
        (setq company-box-icons-all-the-icons
              `((Unknown . ,(all-the-icons-material "find_in_page" :height 0.8 :v-adjust -0.15))
                (Text . ,(all-the-icons-faicon "text-width" :height 0.8 :v-adjust -0.02))
                (Method . ,(all-the-icons-faicon "cube" :height 0.8 :v-adjust -0.02 :face 'all-the-icons-purple))
                (Function . ,(all-the-icons-faicon "cube" :height 0.8 :v-adjust -0.02 :face 'all-the-icons-purple))
                (Constructor . ,(all-the-icons-faicon "cube" :height 0.8 :v-adjust -0.02 :face 'all-the-icons-purple))
                (Field . ,(all-the-icons-octicon "tag" :height 0.85 :v-adjust 0 :face 'all-the-icons-lblue))
                (Variable . ,(all-the-icons-octicon "tag" :height 0.85 :v-adjust 0 :face 'all-the-icons-lblue))
                (Class . ,(all-the-icons-material "settings_input_component" :height 0.8 :v-adjust -0.15 :face 'all-the-icons-orange))
                (Interface . ,(all-the-icons-material "share" :height 0.8 :v-adjust -0.15 :face 'all-the-icons-lblue))
                (Module . ,(all-the-icons-material "view_module" :height 0.8 :v-adjust -0.15 :face 'all-the-icons-lblue))
                (Property . ,(all-the-icons-faicon "wrench" :height 0.8 :v-adjust -0.02))
                (Unit . ,(all-the-icons-material "settings_system_daydream" :height 0.8 :v-adjust -0.15))
                (Value . ,(all-the-icons-material "format_align_right" :height 0.8 :v-adjust -0.15 :face 'all-the-icons-lblue))
                (Enum . ,(all-the-icons-material "storage" :height 0.8 :v-adjust -0.15 :face 'all-the-icons-orange))
                (Keyword . ,(all-the-icons-material "filter_center_focus" :height 0.8 :v-adjust -0.15))
                (Snippet . ,(all-the-icons-material "format_align_center" :height 0.8 :v-adjust -0.15))
                (Color . ,(all-the-icons-material "palette" :height 0.8 :v-adjust -0.15))
                (File . ,(all-the-icons-faicon "file-o" :height 0.8 :v-adjust -0.02))
                (Reference . ,(all-the-icons-material "collections_bookmark" :height 0.8 :v-adjust -0.15))
                (Folder . ,(all-the-icons-faicon "folder-open" :height 0.8 :v-adjust -0.02))
                (EnumMember . ,(all-the-icons-material "format_align_right" :height 0.8 :v-adjust -0.15))
                (Constant . ,(all-the-icons-faicon "square-o" :height 0.8 :v-adjust -0.1))
                (Struct . ,(all-the-icons-material "settings_input_component" :height 0.8 :v-adjust -0.15 :face 'all-the-icons-orange))
                (Event . ,(all-the-icons-octicon "zap" :height 0.8 :v-adjust 0 :face 'all-the-icons-orange))
                (Operator . ,(all-the-icons-material "control_point" :height 0.8 :v-adjust -0.15))
                (TypeParameter . ,(all-the-icons-faicon "arrows" :height 0.8 :v-adjust -0.02))
                (Template . ,(all-the-icons-material "format_align_left" :height 0.8 :v-adjust -0.15)))
              company-box-icons-alist 'company-box-icons-all-the-icons))))

  ;; Popup documentation for completion candidates
  (when (and (not emacs/>=26p) (display-graphic-p))
    (use-package company-quickhelp
      :defines company-quickhelp-delay
      :bind (:map company-active-map
             ([remap company-show-doc-buffer] . company-quickhelp-manual-begin))
      :hook (global-company-mode . company-quickhelp-mode)
      :init (setq company-quickhelp-delay 0.5))))
jcs090218 commented 4 years ago

Hmm... Since this isn't issue about handling company backend in the different way. Can you open in another issue and so we can discuss over there? Thanks!

felzix commented 3 years ago

The company-tide backend doesn't work: none of its suggestions populate the list.

This might be a constraint of tide: https://github.com/ananthakumaran/tide/pull/332

jcs090218 commented 3 years ago

@felzix I have added support for async backends in #21. I think this would work with company-tide, but not sure how well the performance is.

jcs090218 commented 2 years ago

This issue may no longer be useful since this package should able to handle ALL backends after version 1.3.0.

Except some special backends. e.g. company-yasnippet since it has a strict rule on their key-prefix. But in general, this package works well with almost all backends!