-;;; company.el --- Modular in-buffer completion framework
+;;; company.el --- Modular in-buffer completion framework -*- lexical-binding: t -*-
;; Copyright (C) 2009-2013 Free Software Foundation, Inc.
;; Author: Nikolaj Schumacher
;; Maintainer: Dmitry Gutov <dgutov@yandex.ru>
-;; Version: 0.6.1
+;; Version: 0.6.12
;; Keywords: abbrev, convenience, matching
-;; URL: http://company-mode.github.com/
+;; URL: http://company-mode.github.io/
;; Compatibility: GNU Emacs 22.x, GNU Emacs 23.x, GNU Emacs 24.x
;; This file is part of GNU Emacs.
(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$")
:group 'matching)
(defface company-tooltip
- '((t :background "yellow"
- :foreground "black"))
- "Face used for the tool tip."
- :group 'company)
+ '((default :foreground "black")
+ (((class color) (min-colors 88) (background light))
+ (:background "cornsilk"))
+ (((class color) (min-colors 88) (background dark))
+ (:background "yellow")))
+ "Face used for the tooltip.")
(defface company-tooltip-selection
'((default :inherit company-tooltip)
- (((class color) (min-colors 88)) (:background "orange1"))
+ (((class color) (min-colors 88) (background light))
+ (:background "light blue"))
+ (((class color) (min-colors 88) (background dark))
+ (:background "orange1"))
(t (:background "green")))
- "Face used for the selection in the tool tip."
- :group 'company)
+ "Face used for the selection in the tooltip.")
(defface company-tooltip-mouse
'((default :inherit highlight))
- "Face used for the tool tip item under the mouse."
- :group 'company)
+ "Face used for the tooltip item under the mouse.")
(defface company-tooltip-common
- '((t :inherit company-tooltip
- :foreground "red"))
- "Face used for the common completion in the tool tip."
- :group 'company)
+ '((default :inherit company-tooltip)
+ (((background light))
+ :foreground "darkred")
+ (((background dark))
+ :foreground "red"))
+ "Face used for the common completion in the tooltip.")
(defface company-tooltip-common-selection
- '((t :inherit company-tooltip-selection
- :foreground "red"))
- "Face used for the selected common completion in the tool tip."
- :group 'company)
+ '((default :inherit company-tooltip-selection)
+ (((background light))
+ :foreground "darkred")
+ (((background dark))
+ :foreground "red"))
+ "Face used for the selected common completion in the tooltip.")
(defface company-preview
'((t :background "blue4"
:foreground "wheat"))
- "Face used for the completion preview."
- :group 'company)
+ "Face used for the completion preview.")
(defface company-preview-common
'((t :inherit company-preview
:foreground "red"))
- "Face used for the common part of the completion preview."
- :group 'company)
+ "Face used for the common part of the completion preview.")
(defface company-preview-search
'((t :inherit company-preview
:background "blue1"))
- "Face used for the search string in the completion preview."
- :group 'company)
+ "Face used for the search string in the completion preview.")
(defface company-echo nil
- "Face used for completions in the echo area."
- :group 'company)
+ "Face used for completions in the echo area.")
(defface company-echo-common
'((((background dark)) (:foreground "firebrick1"))
(((background light)) (:background "firebrick4")))
- "Face used for the common part of completions in the echo area."
- :group 'company)
+ "Face used for the common part of completions in the echo area.")
(defun company-frontends-set (variable value)
;; uniquify
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',
`company-common', `company-selection', `company-point' and
`company-search-string'."
:set 'company-frontends-set
- :group 'company
:type '(repeat (choice (const :tag "echo" company-echo-frontend)
(const :tag "echo, strip common"
company-echo-strip-common-frontend)
(function :tag "custom function" nil))))
(defcustom company-tooltip-limit 10
- "The maximum number of candidates in the tool tip"
- :group 'company
+ "The maximum number of candidates in the tooltip"
:type 'integer)
(defcustom company-tooltip-minimum 6
- "The minimum height of the tool tip.
+ "The minimum height of the tooltip.
If this many lines are not available, prefer to display the tooltip above."
- :group 'company
:type 'integer)
(defvar company-safe-backends
'((company-abbrev . "Abbrev")
- (company-clang . "clang")
+ (company-capf . "completion-at-point-functions")
+ (company-clang . "Clang")
+ (company-cmake . "CMake")
(company-css . "CSS")
(company-dabbrev . "dabbrev for plain text")
(company-dabbrev-code . "dabbrev for code")
- (company-eclim . "eclim (an Eclipse interace)")
+ (company-eclim . "Eclim (an Eclipse interface)")
(company-elisp . "Emacs Lisp")
(company-etags . "etags")
(company-files . "Files")
(company-gtags . "GNU Global")
- (company-ispell . "ispell")
+ (company-ispell . "Ispell")
(company-keywords . "Programming language keywords")
(company-nxml . "nxml")
(company-oddmuse . "Oddmuse")
(company-pysmell . "PySmell")
(company-ropemacs . "ropemacs")
- (company-semantic . "CEDET Semantic")
+ (company-semantic . "Semantic")
(company-tempo . "Tempo templates")
(company-xcode . "Xcode")))
(put 'company-safe-backends 'risky-local-variable t)
(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-clang company-semantic company-eclim
- company-xcode company-ropemacs
+ company-eclim company-semantic company-clang
+ company-xcode company-ropemacs company-cmake
(company-gtags company-etags company-dabbrev-code
company-keywords)
company-oddmuse company-files company-dabbrev)
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.
+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.
Optional commands:
-`sorted': The back-end may return t here to indicate that the candidates
-are sorted and will not need to be sorted again.
+`sorted': Return t here to indicate that the candidates are sorted and will
+not need to be sorted again.
`duplicates': If non-nil, company will take care of removing duplicates
from the list.
progresses, unless the back-end returns t for this command. The second
argument is the latest prefix.
-`meta': The second argument is a completion candidate. The back-end should
-return a (short) documentation string for it.
+`meta': The second argument is a completion candidate. Return a (short)
+documentation string for it.
-`doc-buffer': The second argument is a completion candidate.
-The back-end should create a buffer (preferably with `company-doc-buffer'),
-fill it with documentation and return it.
+`doc-buffer': The second argument is a completion candidate. Return a
+buffer with documentation for it. Preferably use `company-doc-buffer',
-`location': The second argument is a completion candidate. The back-end can
-return the cons of buffer and buffer location, or of file and line
-number where the completion candidate was defined.
+`location': The second argument is a completion candidate. Return the cons
+of buffer and buffer location, or of file and line number where the
+completion candidate was defined.
-`require-match': If this value is t, the user is not allowed to enter anything
-not offering as a candidate. Use with care! The default value nil gives the
-user that choice with `company-require-match'. Return value 'never overrides
-that option the other way around.
+`require-match': If this returns t, the user is not allowed to enter
+anything not offered as a candidate. Use with care! The default value nil
+gives the user that choice with `company-require-match'. Return value
+`never' overrides that option the other way around.
-`init': Called once for each buffer, the back-end can check for external
-programs and files and load any required libraries. Raising an error here will
-show up in message log once, and the backend will not be used for completion.
+`init': Called once for each buffer. The back-end can check for external
+programs and files and load any required libraries. Raising an error here
+will show up in message log once, and the back-end will not be used for
+completion.
-`post-completion': Called after a completion candidate has been inserted into
-the buffer. The second argument is the candidate. Can be used to modify it,
-e.g. to expand a snippet.
+`post-completion': Called after a completion candidate has been inserted
+into the buffer. The second argument is the candidate. Can be used to
+modify it, e.g. to expand a snippet.
The back-end should return nil for all commands it does not support or
does not know about. It should also be callable interactively and use
`company-begin-backend' to start itself in that case."
- :group 'company
:type `(repeat
(choice
:tag "Back-end"
"Hook run when company starts completing.
The hook is called with one argument that is non-nil if the completion was
started manually."
- :group 'company
:type 'hook)
(defcustom company-completion-cancelled-hook nil
"Hook run when company cancels completing.
The hook is called with one argument that is non-nil if the completion was
aborted manually."
- :group 'company
:type 'hook)
(defcustom company-completion-finished-hook nil
"Hook run when company successfully completes.
-The hook is called with the selected candidate as an argument."
- :group 'company
+The hook is called with the selected candidate as an argument.
+
+If you indend to use it to post-process candidates from a specific
+back-end, consider using the `post-completion' command instead."
:type 'hook)
(defcustom company-minimum-prefix-length 3
"The minimum prefix length for automatic completion."
- :group 'company
:type '(integer :tag "prefix length"))
(defcustom company-require-match 'company-explicit-action-p
"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."
- :group 'company
+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"
'company-explicit-action-p)
(const :tag "On" t)))
-(defcustom company-auto-complete 'company-explicit-action-p
+(defcustom company-auto-complete nil
"Determines when to auto-complete.
-If this is enabled, all characters from `company-auto-complete-chars' complete
-the selected completion. This can also be a function."
- :group 'company
+If this is enabled, all characters from `company-auto-complete-chars'
+complete the selected completion. This can also be a function."
:type '(choice (const :tag "Off" nil)
(function :tag "Predicate function")
(const :tag "On, if user interaction took place"
'company-explicit-action-p)
(const :tag "On" t)))
-(defcustom company-auto-complete-chars '(?\ ?\( ?\) ?. ?\" ?$ ?\' ?< ?| ?!)
+(defcustom company-auto-complete-chars '(?\ ?\) ?.)
"Determines which characters trigger an automatic completion.
-See `company-auto-complete'. If this is a string, each string character causes
-completion. If it is a list of syntax description characters (see
+See `company-auto-complete'. If this is a string, each string character
+causes completion. If it is a list of syntax description characters (see
`modify-syntax-entry'), all characters with that syntax auto-complete.
This can also be a function, which is called with the new input and should
return non-nil if company should auto-complete.
-A character that is part of a valid candidate never starts auto-completion."
- :group 'company
+A character that is part of a valid candidate never triggers auto-completion."
:type '(choice (string :tag "Characters")
(set :tag "Syntax"
(const :tag "Whitespace" ?\ )
"The idle delay in seconds until automatic completions starts.
A value of nil means never complete automatically, t means complete
immediately when a prefix of `company-minimum-prefix-length' is reached."
- :group 'company
:type '(choice (const :tag "never (nil)" nil)
(const :tag "immediate (t)" t)
(number :tag "seconds")))
-(defcustom company-begin-commands t
+(defcustom company-begin-commands '(self-insert-command)
"A list of commands following which company will start completing.
If this is t, it will complete after any command. See `company-idle-delay'.
-Alternatively any command with a non-nil 'company-begin property is treated as
-if it was on this list."
- :group 'company
+Alternatively any command with a non-nil `company-begin' property is treated
+as if it was on this list."
:type '(choice (const :tag "Any command" t)
(const :tag "Self insert command" '(self-insert-command))
(repeat :tag "Commands" function)))
(defcustom company-show-numbers nil
"If enabled, show quick-access numbers for the first ten candidates."
- :group 'company
:type '(choice (const :tag "off" nil)
(const :tag "on" t)))
(define-key keymap [up-mouse-1] 'ignore)
(define-key keymap [up-mouse-3] 'ignore)
(define-key keymap [return] 'company-complete-selection)
+ (define-key keymap (kbd "RET") 'company-complete-selection)
(define-key keymap [tab] 'company-complete-common)
+ (define-key keymap (kbd "TAB") 'company-complete-common)
(define-key keymap (kbd "<f1>") 'company-show-doc-buffer)
(define-key keymap "\C-w" 'company-show-location)
(define-key keymap "\C-s" 'company-search-candidates)
`company-filter-candidates'. These can be used while completion is
inactive, as well.
-The completion data is retrieved using `company-backends' and displayed using
-`company-frontends'. If you want to start a specific back-end, call it
-interactively or use `company-begin-backend'.
+The completion data is retrieved using `company-backends' and displayed
+using `company-frontends'. If you want to start a specific back-end, call
+it interactively or use `company-begin-backend'.
regular keymap (`company-mode-map'):
(company-cancel)
(kill-local-variable 'company-point)))
-(define-globalized-minor-mode global-company-mode company-mode
- (lambda () (unless (or noninteractive (eq (aref (buffer-name) 0) ?\s))
- (company-mode 1))))
+(defcustom company-global-modes t
+ "Modes for which `company-mode' mode is turned on by `global-company-mode'.
+If nil, means no modes. If t, then all major modes have it turned on.
+If a list, it should be a list of `major-mode' symbol names for which
+`company-mode' should be automatically turned on. The sense of the list is
+negated if it begins with `not'. For example:
+ (c-mode c++-mode)
+means that `company-mode' is turned on for buffers in C and C++ modes only.
+ (not message-mode)
+means that `company-mode' is always turned on except in `message-mode' buffers."
+ :type '(choice (const :tag "none" nil)
+ (const :tag "all" t)
+ (set :menu-tag "mode specific" :tag "modes"
+ :value (not)
+ (const :tag "Except" not)
+ (repeat :inline t (symbol :tag "mode")))))
+
+;;;###autoload
+(define-globalized-minor-mode global-company-mode company-mode company-mode-on)
+
+(defun company-mode-on ()
+ (when (and (not (or noninteractive (eq (aref (buffer-name) 0) ?\s)))
+ (cond ((eq company-global-modes t)
+ t)
+ ((eq (car-safe company-global-modes) 'not)
+ (not (memq major-mode (cdr company-global-modes))))
+ (t (memq major-mode company-global-modes))))
+ (company-mode 1)))
(defsubst company-assert-enabled ()
(unless company-mode
(defun company-input-noop ()
(push 31415926 unread-command-events))
-;; Hack:
-;; posn-col-row is incorrect in older Emacsen when line-spacing is set
-(defun company--col-row (&optional pos)
- (let ((posn (posn-at-point pos)))
- (cons (car (posn-col-row posn)) (cdr (posn-actual-col-row posn)))))
-
-(defsubst company--column (&optional pos)
- (car (posn-col-row (posn-at-point pos))))
-
-(defsubst company--row (&optional pos)
- (cdr (posn-actual-col-row (posn-at-point pos))))
+(defun company--column (&optional pos)
+ (save-excursion
+ (when pos (goto-char pos))
+ (save-restriction
+ (+ (save-excursion
+ (vertical-motion 0)
+ (narrow-to-region (point) (point-max))
+ (let ((prefix (get-text-property (point) 'line-prefix)))
+ (if prefix (length prefix) 0)))
+ (current-column)))))
+
+(defun company--row (&optional pos)
+ (save-excursion
+ (when pos (goto-char pos))
+ (count-screen-lines (window-start)
+ (progn (vertical-motion 0) (point)))))
;;; 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)) "")))
(apply 'company--multi-backend-adapter company-backend args)))
(defun company--multi-backend-adapter (backends command &rest args)
- (let ((backends (remove-if (lambda (b)
- (and (symbolp b)
- (eq 'failed (get b 'company-init))))
- backends)))
+ (let ((backends (loop for b in backends
+ when (not (and (symbolp b)
+ (eq 'failed (get b 'company-init))))
+ collect b)))
(case command
(candidates
(loop for backend in backends
;;; completion mechanism ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(defvar company-backend nil)
-(make-variable-buffer-local 'company-backend)
-
(defvar company-prefix nil)
(make-variable-buffer-local 'company-prefix)
(or company--explicit-action
company-selection-changed))
-(defsubst company-reformat (candidate)
+(defun company-reformat (candidate)
;; company-ispell needs this, because the results are always lower-case
;; It's mory efficient to fix it only when they are displayed.
(concat company-prefix (substring candidate (length company-prefix))))
(and (symbolp this-command) (get this-command 'company-begin)))
(not (and transient-mark-mode mark-active))))
-(defsubst company-call-frontends (command)
+(defun company-call-frontends (command)
(dolist (frontend company-frontends)
(condition-case err
(funcall frontend command)
(error (error "Company: Front-end %s error \"%s\" on command %s"
frontend (error-message-string err) command)))))
-(defsubst company-set-selection (selection &optional force-update)
+(defun company-set-selection (selection &optional force-update)
(setq selection (max 0 (min (1- company-candidates-length) selection)))
(when (or force-update (not (equal selection company-selection)))
(setq company-selection selection
(while c2
(setcdr c2 (progn (while (equal (pop c2) (car c2)))
c2)))))))
- (if (and candidates
- (or (cdr candidates)
- (not (eq t (compare-strings (car candidates) nil nil
- prefix nil nil ignore-case)))))
- candidates
- ;; Already completed and unique; don't start.
- ;; FIXME: Not the right place? maybe when setting?
- (and company-candidates t))))
+ (when candidates
+ (if (or (cdr candidates)
+ (not (eq t (compare-strings (car candidates) nil nil
+ prefix nil nil ignore-case))))
+ candidates
+ ;; Already completed and unique; don't start.
+ t))))
(defun company-idle-begin (buf win tick pos)
(and company-mode
(defun company-manual-begin ()
(interactive)
(setq company--explicit-action t)
- (company-auto-begin))
+ (unwind-protect
+ (company-auto-begin)
+ (unless company-candidates
+ (setq company--explicit-action nil))))
(defun company-other-backend (&optional backward)
(interactive (list current-prefix-arg))
(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))))))
-
-(defun company-punctuation-p (input)
- "Return non-nil, if input starts with punctuation or parentheses."
- (memq (char-syntax (string-to-char input)) '(?. ?\( ?\))))
+ (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)
Regular characters are appended to the search string.
-The command `company-search-kill-others' (\\[company-search-kill-others]) uses
- the search string to limit the completion candidates."
+The command `company-search-kill-others' (\\[company-search-kill-others])
+uses the search string to limit the completion candidates."
(interactive)
(company-search-mode 1)
(company-enable-overriding-keymap company-search-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--event-col-row (event)
+ (let* ((col-row (posn-actual-col-row (event-start event)))
+ (col (car col-row))
+ (row (cdr col-row)))
+ (incf col (window-hscroll))
+ (and header-line-format
+ (version< "24" emacs-version)
+ (decf row))
+ (cons col row)))
+
(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 (company--event-col-row 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."
(defun company-complete ()
"Complete the common part of all candidates or the current selection.
-The first time this is called, the common part is completed, the second time, or
-when the selection has been changed, the selected candidate is completed."
+The first time this is called, the common part is completed, the second
+time, or when the selection has been changed, the selected candidate is
+completed."
(interactive)
(when (company-manual-begin)
(if (or company-selection-changed
(push (make-string (- company-space-strings-limit 1 i) ?\ ) lst))
(apply 'vector lst)))
-(defsubst company-space-string (len)
+(defun company-space-string (len)
(if (< len company-space-strings-limit)
(aref company-space-strings len)
(make-string len ?\ )))
-(defsubst company-safe-substring (str from &optional to)
+(defun company-safe-substring (str from &optional to)
(if (> from (string-width str))
""
(with-temp-buffer
(cdr company-last-metadata)))
(defun company-doc-buffer (&optional string)
- (with-current-buffer (get-buffer-create "*Company meta-data*")
+ (with-current-buffer (get-buffer-create "*company-documentation*")
(erase-buffer)
+ (when string
+ (save-excursion
+ (insert string)))
(current-buffer)))
(defvar company--electric-commands
(setq unread-command-events (list last-input-event))))
(defun company-show-doc-buffer ()
- "Temporarily show a buffer with the complete documentation for the selection."
+ "Temporarily show the documentation buffer for the selection."
(interactive)
(company--electric-do
(let* ((selected (nth company-selection company-candidates))
(defun company-begin-with (candidates
&optional prefix-length require-match callback)
"Start a completion at point.
-CANDIDATES is the list of candidates to use and PREFIX-LENGTH is the length of
-the prefix that already is in the buffer before point. It defaults to 0.
+CANDIDATES is the list of candidates to use and PREFIX-LENGTH is the length
+of the prefix that already is in the buffer before point.
+It defaults to 0.
-CALLBACK is a function called with the selected result if the user successfully
-completes the input.
+CALLBACK is a function called with the selected result if the user
+successfully completes the input.
-Example:
-\(company-begin-with '\(\"foo\" \"foobar\" \"foobarbaz\"\)\)"
+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)
(defsubst company-round-tab (arg)
(* (/ (+ arg tab-width) tab-width) tab-width))
-(defun company-untabify (str)
+(defun company-plainify (str)
+ (let ((prefix (get-text-property 0 'line-prefix str)))
+ (when prefix ; Keep the original value unmodified, for no special reason.
+ (setq str (concat prefix str))
+ (remove-text-properties 0 (length str) '(line-prefix) str)))
(let* ((pieces (split-string str "\t"))
(copy pieces))
(while (cdr copy)
(let (lines)
(while (and (= 1 (vertical-motion 1))
(<= (point) end))
- (push (buffer-substring beg (min end (1- (point)))) lines)
+ (let ((bound (min end (1- (point)))))
+ ;; A visual line can contain several physical lines (e.g. with outline's
+ ;; folding overlay). Take only the first one.
+ (push (buffer-substring beg
+ (save-excursion
+ (goto-char beg)
+ (re-search-forward "$" bound 'move)
+ (point)))
+ lines))
(setq beg (point)))
(unless (eq beg end)
(push (buffer-substring beg end) lines))
(nreverse lines)))
-(defsubst company-modify-line (old new offset)
+(defun company-modify-line (old new offset)
(concat (company-safe-substring old 0 offset)
new
(company-safe-substring old (+ offset (length new)))))
(defun company--replacement-string (lines old column nl &optional align-top)
- (let ((width (length (car lines))))
- (when (> width (- (window-width) column))
- (setq column (max 0 (- (window-width) width)))))
+ (let ((width (length (car lines)))
+ (remaining-cols (- (+ (window-width) (window-hscroll))
+ column)))
+ (when (> width remaining-cols)
+ (decf column (- width remaining-cols))))
(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)))
;; show
(defsubst company--window-inner-height ()
- (let ((edges (window-inside-edges (selected-window))))
+ (let ((edges (window-inside-edges)))
(- (nth 3 edges) (nth 1 edges))))
-(defsubst company--pseudo-tooltip-height ()
+(defun company--pseudo-tooltip-height ()
"Calculate the appropriate tooltip height.
Returns a negative number if the tooltip should be displayed above point."
(let* ((lines (company--row))
(company-pseudo-tooltip-hide)
(save-excursion
- (move-to-column 0)
-
(let* ((height (company--pseudo-tooltip-height))
above)
(move-to-window-line (+ row (abs height)))
(point)))
(ov (make-overlay beg end))
- (args (list (mapcar 'company-untabify
+ (args (list (mapcar 'company-plainify
(company-buffer-lines beg end))
column nl above)))
(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-after
+ (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 (abs height))))))
+ (overlay-put ov 'company-height height)))))
(defun company-pseudo-tooltip-show-at-point (pos)
- (let ((col-row (company--col-row pos)))
- (when col-row
- (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)))
- (overlay-put company-pseudo-tooltip-overlay 'company-before
+ (let ((row (company--row pos))
+ (col (company--column pos)))
+ (company-pseudo-tooltip-show (1+ row) col company-selection)))
+
+(defun company-pseudo-tooltip-edit (selection)
+ (let ((height (overlay-get company-pseudo-tooltip-overlay 'company-height)))
+ (overlay-put company-pseudo-tooltip-overlay 'company-after
(apply 'company--replacement-string
- (company--create-lines selection height)
+ (company--create-lines selection (abs height))
(overlay-get company-pseudo-tooltip-overlay
'company-replacement-args)))))
(defun company-pseudo-tooltip-hide-temporarily ()
(when (overlayp company-pseudo-tooltip-overlay)
(overlay-put company-pseudo-tooltip-overlay 'invisible nil)
- (overlay-put company-pseudo-tooltip-overlay 'before-string nil)))
+ (overlay-put company-pseudo-tooltip-overlay 'line-prefix nil)
+ (overlay-put company-pseudo-tooltip-overlay 'after-string nil)))
(defun company-pseudo-tooltip-unhide ()
(when company-pseudo-tooltip-overlay
(overlay-put company-pseudo-tooltip-overlay 'invisible t)
- (overlay-put company-pseudo-tooltip-overlay 'before-string
- (overlay-get company-pseudo-tooltip-overlay 'company-before))
+ ;; Beat outline's folding overlays, at least.
+ (overlay-put company-pseudo-tooltip-overlay 'priority 1)
+ ;; No (extra) prefix for the first line.
+ (overlay-put company-pseudo-tooltip-overlay 'line-prefix "")
+ (overlay-put company-pseudo-tooltip-overlay 'after-string
+ (overlay-get company-pseudo-tooltip-overlay 'company-after))
(overlay-put company-pseudo-tooltip-overlay 'window (selected-window))))
+(defun company-pseudo-tooltip-guard ()
+ (buffer-substring-no-properties
+ (point) (overlay-start company-pseudo-tooltip-overlay)))
+
(defun company-pseudo-tooltip-frontend (command)
- "A `company-mode' front-end similar to a tool-tip but based on overlays."
+ "`company-mode' front-end similar to a tooltip but based on overlays."
(case command
(pre-command (company-pseudo-tooltip-hide-temporarily))
(post-command
0))
(new-height (company--pseudo-tooltip-height)))
(unless (and (>= (* old-height new-height) 0)
- (>= (abs old-height) (abs new-height)))
+ (>= (abs old-height) (abs new-height))
+ (equal (company-pseudo-tooltip-guard)
+ (overlay-get company-pseudo-tooltip-overlay
+ 'company-guard)))
;; Redraw needed.
(company-pseudo-tooltip-show-at-point (- (point)
- (length company-prefix)))))
+ (length company-prefix)))
+ (overlay-put company-pseudo-tooltip-overlay
+ 'company-guard (company-pseudo-tooltip-guard))))
(company-pseudo-tooltip-unhide))
(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."
(setq company-preview-overlay nil)))
(defun company-preview-frontend (command)
- "A `company-mode' front-end showing the selection as if it had been inserted."
+ "`company-mode' front-end showing the selection as if it had been inserted."
(case command
(pre-command (company-preview-hide))
(post-command (company-preview-show-at-point (point)))
(message "%s" company-echo-last-msg)
(message ""))))
-(defsubst company-echo-show-soon (&optional getter)
+(defun company-echo-show-soon (&optional getter)
(when company-echo-timer
(cancel-timer company-echo-timer))
(setq company-echo-timer (run-with-timer 0 nil 'company-echo-show getter)))
(defsubst company-echo-show-when-idle (&optional getter)
- (when (sit-for .01)
- (company-echo-show getter)))
-
-(defsubst company-echo-show-when-not-busy (&optional getter)
- "Run `company-echo-show' with arg GETTER once Emacs isn't busy."
(when (sit-for company-echo-delay)
(company-echo-show getter)))
(company-echo-show)))
(defun company-echo-frontend (command)
- "A `company-mode' front-end showing the candidates in the echo area."
+ "`company-mode' front-end showing the candidates in the echo area."
(case command
(post-command (company-echo-show-soon 'company-echo-format))
(hide (company-echo-hide))))
(defun company-echo-strip-common-frontend (command)
- "A `company-mode' front-end showing the candidates in the echo area."
+ "`company-mode' front-end showing the candidates in the echo area."
(case command
(post-command (company-echo-show-soon 'company-echo-strip-common-format))
(hide (company-echo-hide))))
(defun company-echo-metadata-frontend (command)
- "A `company-mode' front-end showing the documentation in the echo area."
+ "`company-mode' front-end showing the documentation in the echo area."
(case command
(post-command (company-echo-show-when-idle 'company-fetch-metadata))
(hide (company-echo-hide))))
-;; templates ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(autoload 'company-template-declare-template "company-template")
-
(provide 'company)
;;; company.el ends here