branch: externals/company
commit 50a4c55a989666383b9aff1e78201024ed55d66c
Merge: ec3345050b 32488c25fb
Author: Dmitry Gutov <[email protected]>
Commit: Dmitry Gutov <[email protected]>
Merge branch 'master' into better-doc-and-location-bindings
---
NEWS.md | 9 +++
company-capf.el | 3 +-
company-childframe.el | 23 ++++++--
company.el | 151 ++++++++++++++++++++++++++++++++++++++++++++------
4 files changed, 162 insertions(+), 24 deletions(-)
diff --git a/NEWS.md b/NEWS.md
index a19a1dbbb8..9adecdb63e 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -17,6 +17,15 @@
(define-key company-active-map (kbd "M-g") nil))
```
+* `company-search-regexp-function` defaults to
+ `company-search-words-in-any-order-regexp`. Another alternative value for it
+ was also added: `company-search-flex-words-in-any-order-regexp`, working
+ somewhat similar to the popular completion style Orderless.
+* The `search` faces in the popup inherit from `isearch`.
+* New option `company-global-minibuffer` for completion during
`eval-expression`
+ (`M-:`). The "pseudo-tooltip" frontend is not supported by this feature,
+ `company-childframe` is recommended instead.
+* `C-M-i` is bound to `company-complete-common` when completion is active.
* Search mode input is displayed at the bottom of the popup
([#1535](https://github.com/company-mode/company-mode/pull/1535)).
* New built-in frontend using "real graphical" widget for the popup
diff --git a/company-capf.el b/company-capf.el
index 8d159608c9..5c7b8486b3 100644
--- a/company-capf.el
+++ b/company-capf.el
@@ -36,7 +36,8 @@
:group 'company)
(defcustom company-capf-disabled-functions '(tags-completion-at-point-function
- ispell-completion-at-point)
+ ispell-completion-at-point
+
company--fake-capf-complete-common)
"List of completion functions which should be ignored in this backend.
By default it contains the functions that duplicate the built-in backends
diff --git a/company-childframe.el b/company-childframe.el
index 6a45c125e7..103948c52d 100644
--- a/company-childframe.el
+++ b/company-childframe.el
@@ -88,17 +88,28 @@ Users of HiDPI screens might like to set it to 2."
(defun company-childframe-show-at-prefix (info)
"Poshandler showing `company-childframe' at `company-prefix'."
(let* ((parent-window (plist-get info :parent-window))
- (point (with-current-buffer (window-buffer parent-window)
- (- (plist-get info :position)
- (plist-get info :company-prefix-length))))
+ (point (- (plist-get info :position)
+ (plist-get info :company-prefix-length)))
+ (after-string-width
+ (with-current-buffer (window-buffer parent-window)
+ (thread-last
+ (and (= point (point-max))
+ (overlays-in point point))
+ (mapcar (lambda (o) (company--string-pixel-width
+ (overlay-get o 'after-string))))
+ (cl-reduce #'+))))
(posn (posn-at-point point parent-window))
;; TODO: Strictly speaking, if company-childframe-font is not nil,
that
;; should be used to find the default width...
(expected-margin-width (* (plist-get info :company-margin)
(default-font-width)))
(xy (posn-x-y posn)))
- (setcar xy (- (car xy) expected-margin-width (if (display-graphic-p)
-
company-childframe-border-width
- 0)))
+ (setcar xy (- (car xy) expected-margin-width
+ (if (display-graphic-p)
+ company-childframe-border-width
+ 0)
+ ;; Might bite us if the posn-at-point behavior changes
+ ;; someday, but the odds seem low.
+ after-string-width))
(posframe-poshandler-point-bottom-left-corner (plist-put info :position
posn))))
(defun company-childframe-show ()
diff --git a/company.el b/company.el
index 32b977c27c..83e116896f 100644
--- a/company.el
+++ b/company.el
@@ -98,11 +98,11 @@
"Face used for the deprecated items.")
(defface company-tooltip-search
- '((default :inherit highlight))
+ '((default :inherit isearch))
"Face used for the search string in the tooltip.")
(defface company-tooltip-search-selection
- '((default :inherit highlight))
+ '((default :inherit isearch))
"Face used for the search string inside the selection in the tooltip.")
(defface company-tooltip-mouse
@@ -174,7 +174,7 @@
"Face used for the common part of the completion preview.")
(defface company-preview-search
- '((default :inherit company-tooltip-common-selection))
+ '((default :inherit isearch))
"Face used for the search string in the completion preview.")
(defface company-echo nil
@@ -886,7 +886,11 @@ asynchronous call into synchronous.")
;;; mode
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(defvar company-mode-map (make-sparse-keymap)
+(defvar company-mode-map
+ (let ((keymap (make-sparse-keymap)))
+ (define-key keymap [remap indent-for-tab-command]
'company-indent-for-tab-command)
+ (define-key keymap [remap c-indent-line-or-region]
'company-indent-for-tab-command)
+ keymap)
"Keymap used by `company-mode'.")
(defvar company-active-map
@@ -910,6 +914,7 @@ asynchronous call into synchronous.")
(define-key keymap [tab] 'company-complete-common-or-cycle)
(define-key keymap (kbd "TAB") 'company-complete-common-or-cycle)
(define-key keymap [backtab] 'company-cycle-backward)
+ (define-key keymap (kbd "C-M-i") 'company-complete-common)
(define-key keymap (kbd "<f1>") 'company--show-doc-buffer-and-warn)
(define-key keymap (kbd "C-h") 'company--show-doc-buffer-and-warn)
(define-key keymap (kbd "M-h") 'company-show-doc-buffer)
@@ -1043,8 +1048,20 @@ means that `company-mode' is always turned on except in
`message-mode' buffers."
(const :tag "Except" not)
(repeat :inline t (symbol :tag "mode")))))
+(defcustom company-global-minibuffer t
+ "Non-nil to enable `company-mode' in the minibuffer.
+The value can be t (meaning only enable if the minibuffer has a local
+`completion-at-point-functions' value) or a custom predicate function.
+
+The overlay based popup is not supported, completion won't start in
+minibuffer if it's in configured frontends: use `company-childframe'."
+ :type 'boolean)
+
;;;###autoload
-(define-globalized-minor-mode global-company-mode company-mode company-mode-on)
+(define-globalized-minor-mode global-company-mode company-mode company-mode-on
+ (if global-company-mode
+ (add-hook 'minibuffer-setup-hook #'company--minibuffer-on 100)
+ (remove-hook 'minibuffer-setup-hook #'company--minibuffer-on)))
(defun company-mode-on ()
(when (and (not (or noninteractive (eq (aref (buffer-name) 0) ?\s)))
@@ -1055,6 +1072,14 @@ means that `company-mode' is always turned on except in
`message-mode' buffers."
(t (memq major-mode company-global-modes))))
(company-mode 1)))
+(defun company--minibuffer-on ()
+ (when (and company-global-minibuffer
+ (not (try-completion "company-pseudo-tooltip" company-frontends))
+ (if (eq company-global-minibuffer t)
+ (local-variable-p 'completion-at-point-functions)
+ (funcall company-global-minibuffer)))
+ (company-mode 1)))
+
(defsubst company-assert-enabled ()
(unless company-mode
(company-uninstall-map)
@@ -2237,7 +2262,7 @@ Searches for each in the currently visible part of the
current buffer and
prioritizes the matches according to `company-occurrence-weight-function'.
The rest of the list is appended unchanged.
Keywords and function definition names are ignored."
- (let* ((w-start (window-start))
+ (let* ((w-start (max (window-start) (field-beginning)))
(w-end (window-end))
(start-point (point))
occurs
@@ -2734,7 +2759,7 @@ For more details see `company-insertion-on-trigger' and
;;; search
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(defcustom company-search-regexp-function #'regexp-quote
+(defcustom company-search-regexp-function
#'company-search-words-in-any-order-regexp
"Function to construct the search regexp from input.
It's called with one argument, the current search input. It must return
either a regexp without groups, or one where groups don't intersect and
@@ -2745,7 +2770,9 @@ each one wraps a part of the input string."
(const :tag "Words separated with spaces, in any order"
company-search-words-in-any-order-regexp)
(const :tag "All characters in given order, with anything in between"
- company-search-flex-regexp)))
+ company-search-flex-regexp)
+ (const :tag "Space separated words in any order, all chars inside a
word with anything in between"
+ company-search-flex-words-in-any-order-regexp)))
(defvar-local company-search-string "")
@@ -2779,12 +2806,23 @@ each one wraps a part of the input string."
(defun company-search-flex-regexp (input)
(if (zerop (length input))
""
- (concat (regexp-quote (string (aref input 0)))
+ (concat (format "\\(%s\\)" (regexp-quote (string (aref input 0))))
(mapconcat (lambda (c)
(concat "[^" (string c) "]*"
- (regexp-quote (string c))))
+ (format "\\(%s\\)"
+ (regexp-quote (string c)))))
(substring input 1) ""))))
+(defun company-search-flex-words-in-any-order-regexp (input)
+ (let* ((words (mapcar (lambda (word) (format "\\(?:%s\\)"
+ (company-search-flex-regexp word)))
+ (split-string input " +" t)))
+ (permutations (company--permutations words)))
+ (mapconcat (lambda (words)
+ (mapconcat #'identity words ".*"))
+ permutations
+ "\\|")))
+
(defun company--permutations (lst)
(if (not lst)
'(nil)
@@ -2835,9 +2873,16 @@ each one wraps a part of the input string."
(let* ((selection (or company-selection 0))
(pos (company--search new (nthcdr selection company-candidates))))
(if (null pos)
+ (let ((pos (company--search new (nthcdr (- company-candidates-length
+ selection)
+ (reverse
company-candidates)))))
+ (if (null pos)
+ (ding)
+ (setq company-search-string new)
+ (company-set-selection (- selection pos 1) t)))
(ding)
- (setq company-search-string new)
- (company-set-selection (+ selection pos) t))))
+ (setq company-search-string new)
+ (company-set-selection (+ selection pos) t))))
(defun company--search-assert-input ()
(company--search-assert-enabled)
@@ -2850,7 +2895,7 @@ each one wraps a part of the input string."
(company--search-assert-input)
(let* ((selection (or company-selection 0))
(pos (company--search company-search-string
- (cdr (nthcdr selection company-candidates)))))
+ (cdr (nthcdr selection company-candidates)))))
(if (null pos)
(ding)
(company-set-selection (+ selection pos 1) t))))
@@ -3535,6 +3580,25 @@ from the candidates list.")
(let ((win (display-buffer doc-buffer t)))
(set-window-start win (if start start (point-min)))))))
+(defun company--fake-capf-complete-common (&rest _)
+ (company-complete-common)
+ (list (point) (point) nil))
+
+(defun company-indent-for-tab-command (&optional arg)
+ "Like `indent-for-tab-command' which see but calls `company-complete-common'
+instead of `completion-at-point' as the fallback. That only happens when
+`tab-always-indent' is `complete', and only when reindentation was a no-op."
+ (interactive)
+ (unwind-protect
+ (progn
+ (add-hook 'completion-at-point-functions
+ #'company--fake-capf-complete-common
+ nil t)
+ (funcall-interactively #'indent-for-tab-command arg))
+ (remove-hook 'completion-at-point-functions
+ #'company--fake-capf-complete-common
+ t)))
+
(defun company-show-doc-buffer (&optional toggle-auto-update)
"Show the documentation buffer for the selection.
With a prefix argument TOGGLE-AUTO-UPDATE, toggle the value of
@@ -4253,7 +4317,11 @@ Value of SELECTED determines the added face."
(if company-search-filtering
'filter
'search))))
- (left (funcall company-format-margin-function "" nil))
+ (left (if company-format-margin-function
+ (funcall company-format-margin-function "" nil)
+ (concat
+ (company-space-string company-tooltip-margin)
+ (format "%s: " (company-call-backend 'kind)))))
(line (concat
company-search-string))
(width (+ (company--string-width left) width (length right-margin))))
@@ -4516,6 +4584,9 @@ Delay is determined by `company-tooltip-idle-delay'."
(defvar-local company-preview-overlay nil)
(defun company-preview-show-at-point (pos completion &optional boundaries)
+ (when (minibufferp)
+ (company-echo-hide))
+
(company-preview-hide)
(let* ((boundaries (or boundaries (company--boundaries completion)))
@@ -4576,6 +4647,8 @@ Delay is determined by `company-tooltip-idle-delay'."
(let ((ov company-preview-overlay))
(overlay-put ov (if (> end beg) 'display 'after-string)
completion)
+ ;; Show before minibuffer-message-overlay if there.
+ (overlay-put ov 'priority 1101)
(overlay-put ov 'window (selected-window))))))
(defun company-preview-hide ()
@@ -4655,9 +4728,31 @@ Delay is determined by `company-tooltip-idle-delay'."
(defun company-echo-show (&optional getter)
(let ((last-msg company-echo-last-msg)
(message-log-max nil)
+ (preview-o company-preview-overlay)
(message-truncate-lines company-echo-truncate-lines))
(when getter
(setq company-echo-last-msg (funcall getter)))
+ (when-let* ((mini-window (and company-echo-truncate-lines
+ (active-minibuffer-window)))
+ (posn (posn-at-point
+ (with-current-buffer (window-buffer mini-window)
+ (max (point-min)
+ (1- (point-max))))
+ mini-window))
+ (max-len (max 0
+ (- (window-width mini-window)
+ (car
+ (posn-col-row posn))
+ (if preview-o
+ (company--string-width
+ (or
+ (overlay-get preview-o 'display)
+ (overlay-get preview-o 'after-string)
+ ""))
+ 0)
+ 5))))
+ (when (> (length company-echo-last-msg) max-len)
+ (setq company-echo-last-msg (substring company-echo-last-msg 0
max-len))))
;; Avoid modifying the echo area if we don't have anything to say, and we
;; didn't put the previous message there (thus there's nothing to clear),
;; https://debbugs.gnu.org/cgi/bugreport.cgi?bug=62816#20
@@ -4743,8 +4838,7 @@ Delay is determined by `company-tooltip-idle-delay'."
(defun company-echo-hide ()
(unless (string-empty-p company-echo-last-msg)
- (setq company-echo-last-msg "")
- (company-echo-show)))
+ (company-echo-show #'ignore)))
(defun company-echo-frontend (command)
"`company-mode' frontend showing the candidates in the echo area."
@@ -4762,11 +4856,34 @@ Delay is determined by `company-tooltip-idle-delay'."
"`company-mode' frontend showing the documentation in the echo area."
(pcase command
(`pre-command
- (when (> company-echo-delay 0)
+ (when (and (> company-echo-delay 0)
+ (or (not (minibufferp))
+ (memq this-command
+ '(self-insert-command
+ delete-backward-char
+ company-select-next
+ company-select-previous
+ company-select-next-or-abort
+ company-select-previous-or-abort
+ company-next-page
+ company-previous-page
+ company-search-repeat-forward
+ company-search-repeat-backward
+ company-complete-common-or-cycle))))
(company-echo-show)))
(`post-command (company-echo-show-soon 'company-fetch-metadata))
(`unhide (company-echo-show))
(`hide (company-echo-hide))))
+(eldoc-add-command-completions "company-")
+
+(defun company--eldoc-no-inteference-p ()
+ (or (not company-candidates)
+ (member company-echo-last-msg '(nil ""))))
+
+(advice-add #'eldoc-display-message-no-interference-p
+ :after-while
+ #'company--eldoc-no-inteference-p)
+
(provide 'company)
;;; company.el ends here