(eval-when-compile (require 'cl))
+;; FIXME: Use `user-error'.
(add-to-list 'debug-ignored-errors "^.* frontend cannot be used twice$")
(add-to-list 'debug-ignored-errors "^Echo area cannot be used twice$")
(add-to-list 'debug-ignored-errors "^No \\(document\\|loc\\)ation available$")
Each front-end is a function that takes one argument. It is called with
one of the following arguments:
-'show: When the visualization should start.
+`show': When the visualization should start.
-'hide: When the visualization should end.
+`hide': When the visualization should end.
-'update: When the data has been updated.
+`update': When the data has been updated.
-'pre-command: Before every command that is executed while the
+`pre-command': Before every command that is executed while the
visualization is active.
-'post-command: After every command that is executed while the
+`post-command': After every command that is executed while the
visualization is active.
The visualized data is stored in `company-prefix', `company-candidates',
(defvar company-safe-backends
'((company-abbrev . "Abbrev")
+ (company-capf . "completion-at-point-functions")
(company-clang . "Clang")
(company-css . "CSS")
(company-dabbrev . "dabbrev for plain text")
(assq backend company-safe-backends))
(return t))))))
-(defun company-capf (command &optional arg &rest args)
- "`company-mode' back-end using `completion-at-point-functions'.
-Requires Emacs 24.1 or newer."
- (interactive (list 'interactive))
- (case command
- (interactive (company-begin-backend 'company-capf))
- (prefix
- (let ((res (run-hook-wrapped 'completion-at-point-functions
- ;; Ignore misbehaving functions.
- #'completion--capf-wrapper 'optimist)))
- (when (consp res)
- (if (> (nth 2 res) (point))
- 'stop
- (buffer-substring-no-properties (nth 1 res) (point))))))
- (candidates
- (let ((res (run-hook-wrapped 'completion-at-point-functions
- ;; Ignore misbehaving functions.
- #'completion--capf-wrapper 'optimist)))
- (when (consp res)
- (all-completions arg (nth 3 res)
- (plist-get (nthcdr 4 res) :predicate)))))))
-
(defcustom company-backends '(company-elisp company-nxml company-css
company-semantic company-clang company-eclim
company-xcode company-ropemacs
The first argument is the command requested from the back-end. It is one
of the following:
-`prefix': The back-end should return the text to be completed. It must be
-text immediately before `point'. Returning nil passes control to the next
-back-end. The function should return 'stop if it should complete but cannot
-\(e.g. if it is in the middle of a string\). If the returned value is only
-part of the prefix (e.g. the part after \"->\" in C), the back-end may return a
-cons of prefix and prefix length, which is then used in the
-`company-minimum-prefix-length' test.
+`prefix': The back-end should return the text to be completed. It must be text
+immediately before point. Returning nil passes control to the next back-end.
+The function should return `stop' if it should complete but cannot \(e.g. if it
+is in the middle of a string\). Instead of a string, the back-end may return a
+cons where car is the prefix and cdr is used in `company-minimum-prefix-length'
+test. It's either number or t, in which case the test automatically succeeds.
`candidates': The second argument is the prefix to be completed. The
return value should be a list of candidates that start with the prefix.
"If enabled, disallow non-matching input.
This can be a function do determine if a match is required.
-This can be overridden by the back-end, if it returns t or 'never to
-'require-match. `company-auto-complete' also takes precedence over this."
+This can be overridden by the back-end, if it returns t or `never' to
+`require-match'. `company-auto-complete' also takes precedence over this."
:type '(choice (const :tag "Off" nil)
(function :tag "Predicate function")
(const :tag "On, if user interaction took place"
;;; backends ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(defvar company-backend nil)
+(make-variable-buffer-local 'company-backend)
+
(defun company-grab (regexp &optional expression limit)
(when (looking-back regexp limit)
(or (match-string-no-properties (or expression 0)) "")))
;;; completion mechanism ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(defvar company-backend nil)
-(make-variable-buffer-local 'company-backend)
-
(defvar company-prefix nil)
(make-variable-buffer-local 'company-prefix)
(defun company-require-match-p ()
(let ((backend-value (company-call-backend 'require-match)))
(or (eq backend-value t)
- (and (if (functionp company-require-match)
+ (and (not (eq backend-value 'never))
+ (if (functionp company-require-match)
(funcall company-require-match)
- (eq company-require-match t))
- (not (eq backend-value 'never))))))
+ (eq company-require-match t))))))
(defun company-auto-complete-p (input)
"Return non-nil, if input starts with punctuation or parentheses."
((and (company--string-incremental-p company-prefix new-prefix)
(company-require-match-p))
;; wrong incremental input, but required match
- (backward-delete-char (length input))
+ (delete-char (- (length input)))
(ding)
(message "Matching input is required")
company-candidates)
(defun company--good-prefix-p (prefix)
(and (or (company-explicit-action-p)
(unless (eq prefix 'stop)
- (>= (or (cdr-safe prefix) (length prefix))
- company-minimum-prefix-length)))
+ (or (eq (cdr-safe prefix) t)
+ (>= (or (cdr-safe prefix) (length prefix))
+ company-minimum-prefix-length))))
(stringp (or (car-safe prefix) prefix))))
(defun company--continue ()
(kill-local-variable 'company-search-old-selection)
(company-enable-overriding-keymap company-active-map)))
-(defsubst company-search-assert-enabled ()
+(defun company-search-assert-enabled ()
(company-assert-enabled)
(unless company-search-mode
(company-uninstall-map)
(company-abort)
(company--unread-last-input)))
+(defvar company-pseudo-tooltip-overlay)
+
+(defvar company-tooltip-offset)
+
+(defun company--inside-tooltip-p (event-col-row row height)
+ (let* ((ovl company-pseudo-tooltip-overlay)
+ (column (overlay-get ovl 'company-column))
+ (width (overlay-get ovl 'company-width))
+ (evt-col (car event-col-row))
+ (evt-row (cdr event-col-row)))
+ (and (>= evt-col column)
+ (< evt-col (+ column width))
+ (if (> height 0)
+ (and (> evt-row row)
+ (<= evt-row (+ row height) ))
+ (and (< evt-row row)
+ (>= evt-row (+ row height)))))))
+
(defun company-select-mouse (event)
"Select the candidate picked by the mouse."
(interactive "e")
- (when (nth 4 (event-start event))
- (company-set-selection (- (cdr (posn-actual-col-row (event-start event)))
- (company--row)
- 1))
- t))
+ (let ((event-col-row (posn-actual-col-row (event-start event)))
+ (ovl-row (company--row))
+ (ovl-height (and company-pseudo-tooltip-overlay
+ (min (overlay-get company-pseudo-tooltip-overlay
+ 'company-height)
+ company-candidates-length))))
+ (if (and ovl-height
+ (company--inside-tooltip-p event-col-row ovl-row ovl-height))
+ (progn
+ (company-set-selection (+ (cdr event-col-row)
+ (if (zerop company-tooltip-offset)
+ -1
+ (- company-tooltip-offset 2))
+ (- ovl-row)
+ (if (< ovl-height 0)
+ (- 1 ovl-height)
+ 0)))
+ t)
+ (company-abort)
+ (company--unread-last-input)
+ nil)))
(defun company-complete-mouse (event)
"Complete the candidate picked by the mouse."
(cons selected (company-call-backend 'meta selected))))
(cdr company-last-metadata)))
-(defun company-doc-buffer (&optional string)
+(defun company-doc-buffer (&optional _string)
(with-current-buffer (get-buffer-create "*Company meta-data*")
(erase-buffer)
(current-buffer)))
Example:
\(company-begin-with '\(\"foo\" \"foobar\" \"foobarbaz\"\)\)"
+ ;; FIXME: When Emacs 23 is no longer a concern, replace
+ ;; `company-begin-with-marker' with a lexical variable; use a lexical closure.
(setq company-begin-with-marker (copy-marker (point) t))
(company-begin-backend
`(lambda (command &optional arg &rest ignored)
(defun company-buffer-lines (beg end)
(goto-char beg)
- (let (lines done)
- (while (and (< (point) end) (not done))
+ (let (lines)
+ (while (< (point) end)
(let ((bol (point)))
;; A visual line can contain several physical lines (e.g. with outline's
;; folding overlay). Take only the first one.
(re-search-forward "$")
(push (buffer-substring bol (min end (point))) lines))
- (unless (= 1 (vertical-motion 1))
- (setq done t)))
+ (vertical-motion 1))
(nreverse lines)))
(defsubst company-modify-line (old new offset)
(let (new)
(when align-top
;; untouched lines first
- (dotimes (i (- (length old) (length lines)))
+ (dotimes (_ (- (length old) (length lines)))
(push (pop old) new)))
;; length into old lines.
(while old
len (min limit len)
lines-copy lines)
- (dotimes (i len)
+ (dotimes (_ len)
(setq width (max (length (pop lines-copy)) width)))
(setq width (min width (window-width)))
(let* ((height (company--pseudo-tooltip-height))
above)
+ (when (and header-line-format
+ (version< "24" emacs-version))
+ (decf row))
+
(when (< height 0)
(setq row (+ row height -1)
above t))
(setq company-pseudo-tooltip-overlay ov)
(overlay-put ov 'company-replacement-args args)
- (overlay-put ov 'company-before
- (apply 'company--replacement-string
- (company--create-lines selection (abs height))
- args))
+
+ (let ((lines (company--create-lines selection (abs height))))
+ (overlay-put ov 'company-before
+ (apply 'company--replacement-string lines args))
+ (overlay-put ov 'company-width (string-width (car lines))))
(overlay-put ov 'company-column column)
(overlay-put ov 'company-height height)))))
(company-pseudo-tooltip-show (1+ (cdr col-row)) (car col-row)
company-selection))))
-(defun company-pseudo-tooltip-edit (lines selection)
- (let ((column (overlay-get company-pseudo-tooltip-overlay 'company-column))
- (height (overlay-get company-pseudo-tooltip-overlay 'company-height)))
+(defun company-pseudo-tooltip-edit (selection)
+ (let ((height (overlay-get company-pseudo-tooltip-overlay 'company-height)))
(overlay-put company-pseudo-tooltip-overlay 'company-before
(apply 'company--replacement-string
(company--create-lines selection (abs height))
(hide (company-pseudo-tooltip-hide)
(setq company-tooltip-offset 0))
(update (when (overlayp company-pseudo-tooltip-overlay)
- (company-pseudo-tooltip-edit company-candidates
- company-selection)))))
+ (company-pseudo-tooltip-edit company-selection)))))
(defun company-pseudo-tooltip-unless-just-one-frontend (command)
"`company-pseudo-tooltip-frontend', but not shown for single candidates."