------------------------------------------------------------ revno: 377 committer: Dmitry Gutov <dgu...@yandex.ru> branch nick: elpa timestamp: Mon 2013-04-01 09:30:58 +0400 message: company: Release 0.6.6 ## 2013-04-01 (0.6.6) * `company-elisp` doesn't offer completions when typing the name and the arguments of a new function or macro definition, allowing to fall back to other back-ends like `company-dabbrev-code`. ## 2013-03-30 (0.6.5) * Fixed keybindings when running in a terminal. * `company-elisp-show-locals-first`: new customizable variable. * `company-elisp` shows more accurate and comprehensive candidates list. ## 2013-03-26 (0.6.4) * `company-eclim` shows valid completions after an opening paren. * Expanded template does not get removed until the point leaves it. After your input the last argument in a method call expanded by `company-eclim`, you can press `<tab>` once more, to jump after the closing paren. No other bundled back-ends are affected. ## 2013-03-25 (0.6.3) * New tooltip face colors used on themes with light background. * Pseudo-tooltip stays up-to-date when text is inserted after the point. * Fixed `company-require-match` mechanics. modified: packages/company/company-eclim.el packages/company/company-elisp.el packages/company/company-pkg.el packages/company/company-template.el packages/company/company-tests.el packages/company/company.el
=== modified file 'packages/company/company-eclim.el' --- a/packages/company/company-eclim.el 2013-03-23 22:22:44 +0000 +++ b/packages/company/company-eclim.el 2013-04-01 05:30:58 +0000 @@ -21,12 +21,12 @@ ;;; Commentary: ;; -;; Eclim version 1.7.13 or newer (?) is required. -;; -;; This completion backend is pretty barebone. -;; -;; `emacs-eclim' provides an alternative backend, and it also allows you to -;; actually control Eclim from Emacs. +;; Using `emacs-eclim' together with (or instead of) this back-end is +;; recommended, as it allows you to use other Eclim features. +;; +;; The alternative back-end provided by `emacs-eclim' uses `yasnippet' +;; instead of `company-template' to expand function calls, and it supports +;; some languages other than Java. ;;; Code: @@ -98,11 +98,9 @@ (let ((dir (company-eclim--project-dir))) (when dir (setq company-eclim--project-name - (let ((project (loop for project in (company-eclim--project-list) - when (equal (cdr (assoc 'path project)) dir) - return project))) - (when project - (cdr (assoc 'name project))))))))) + (loop for project in (company-eclim--project-list) + when (equal (cdr (assoc 'path project)) dir) + return (cdr (assoc 'name project)))))))) (defun company-eclim--candidates (prefix) (interactive "d") @@ -122,7 +120,8 @@ (company-eclim--call-process "java_complete" "-p" (company-eclim--project-name) "-f" project-file - "-o" (number-to-string (1- (point))) + "-o" (number-to-string + (company-eclim--search-point prefix)) "-e" "utf-8" "-l" "standard")))) (let* ((meta (cdr (assoc 'info item))) @@ -133,6 +132,11 @@ (let ((completion-ignore-case nil)) (all-completions prefix company-eclim--doc))) +(defun company-eclim--search-point (prefix) + (if (or (plusp (length prefix)) (eq (char-before) ?.)) + (1- (point)) + (point))) + (defun company-eclim--meta (candidate) (gethash candidate company-eclim--doc)) @@ -150,8 +154,10 @@ (company-template-move-to-first templ))) (defun company-eclim (command &optional arg &rest ignored) - "A `company-mode' completion back-end for eclim. -eclim provides access to Eclipse Java IDE features for other editors. + "A `company-mode' completion back-end for Eclim. +Eclim provides access to Eclipse Java IDE features for other editors. + +Eclim version 1.7.13 or newer (?) is required. Completions only work correctly when the buffer has been saved. `company-eclim-auto-save' determines whether to do this automatically."
=== modified file 'packages/company/company-elisp.el' --- a/packages/company/company-elisp.el 2013-03-23 22:22:44 +0000 +++ b/packages/company/company-elisp.el 2013-04-01 05:30:58 +0000 @@ -1,6 +1,6 @@ -;;; company-elisp.el --- A company-mode completion back-end for emacs-lisp-mode +;;; company-elisp.el --- A company-mode completion back-end for emacs-lisp-mode -*- lexical-binding: t -*- -;; Copyright (C) 2009, 2011-2012 Free Software Foundation, Inc. +;; Copyright (C) 2009, 2011-2013 Free Software Foundation, Inc. ;; Author: Nikolaj Schumacher @@ -37,76 +37,145 @@ :type '(choice (const :tag "Off" nil) (const :tag "On" t))) -(defun company-grab-lisp-symbol () +(defcustom company-elisp-show-locals-first t + "If enabled, locally bound variables and functions are displayed +first in the candidates list." + :group 'company + :type '(choice (const :tag "Off" nil) + (const :tag "On" t))) + +(defun company-elisp--prefix () (let ((prefix (company-grab-symbol))) (if prefix - (unless (and (company-in-string-or-comment) - (/= (char-before (- (point) (length prefix))) ?`)) + (when (if (company-in-string-or-comment) + (= (char-before (- (point) (length prefix))) ?`) + (company-elisp--should-complete)) prefix) 'stop))) -(defun company-elisp-predicate (symbol) +(defun company-elisp--predicate (symbol) (or (boundp symbol) (fboundp symbol) (facep symbol) (featurep symbol))) +(defun company-elisp--fns-regexp (&rest names) + (concat "\\_<\\(?:cl-\\)?" (regexp-opt names) "\\*?\\_>")) + (defvar company-elisp-parse-limit 30) (defvar company-elisp-parse-depth 100) -(defvar company-elisp-binding-regexp - (concat "([ \t\n]*\\_<" (regexp-opt '("let" "defun" "defmacro" "defsubst" - "lambda" "lexical-let" "flet" "labels")) - "\\*?") - "Regular expression matching sexps containing variable bindings.") - -(defvar company-elisp-binding-regexp-1 - (concat "([ \t\n]*\\_<" (regexp-opt '("dolist" "dotimes"))) - "Regular expression matching sexps containing one variable binding.") - -(defun company-elisp-parse-local (prefix vars) +(defvar company-elisp-defun-names '("defun" "defmacro" "defsubst")) + +(defvar company-elisp-var-binding-regexp + (apply #'company-elisp--fns-regexp "let" "lambda" "lexical-let" + company-elisp-defun-names) + "Regular expression matching head of a multiple variable bindings form.") + +(defvar company-elisp-var-binding-regexp-1 + (company-elisp--fns-regexp "dolist" "dotimes") + "Regular expression matching head of a form with one variable binding.") + +(defvar company-elisp-fun-binding-regexp + (company-elisp--fns-regexp "flet" "labels") + "Regular expression matching head of a function bindings form.") + +(defvar company-elisp-defuns-regexp + (concat "([ \t\n]*" + (apply #'company-elisp--fns-regexp company-elisp-defun-names))) + +(defun company-elisp--should-complete () + (let ((start (point)) + (depth (car (syntax-ppss)))) + (not + (when (> depth 0) + (save-excursion + (up-list (- depth)) + (when (looking-at company-elisp-defuns-regexp) + (forward-char) + (forward-sexp 1) + (unless (= (point) start) + (condition-case nil + (let ((args-end (scan-sexps (point) 2))) + (or (null args-end) + (> args-end start))) + (scan-error + t))))))))) + +(defun company-elisp--locals (prefix functions-p) (let ((regexp (concat "[ \t\n]*\\(\\_<" (regexp-quote prefix) "\\(?:\\sw\\|\\s_\\)*\\_>\\)")) - (pos (point))) - (ignore-errors - (save-excursion - (dotimes (i company-elisp-parse-depth) - (up-list -1) - (save-excursion - (cond - ((looking-at company-elisp-binding-regexp) - (down-list 2) - (ignore-errors - (dotimes (i company-elisp-parse-limit) - (save-excursion - (when (looking-at "[ \t\n]*(") - (down-list 1)) - (and (looking-at regexp) - ;; Don't add incomplete text as candidate. - (not (eq (match-end 0) pos)) - (add-to-list 'vars (match-string-no-properties 1)))) - (forward-sexp)))) - ((looking-at company-elisp-binding-regexp-1) - (down-list 2) - (and (looking-at regexp) - ;; Don't add incomplete text as candidate. - (not (eq (match-end 0) pos)) - (add-to-list 'vars (match-string-no-properties 1))))))))) - vars)) + (pos (point)) + res) + (condition-case nil + (save-excursion + (dotimes (i company-elisp-parse-depth) + (up-list -1) + (save-excursion + (when (eq (char-after) ?\() + (forward-char 1) + (when (ignore-errors + (save-excursion (forward-list) + (<= (point) pos))) + (skip-chars-forward " \t\n") + (cond + ((looking-at (if functions-p + company-elisp-fun-binding-regexp + company-elisp-var-binding-regexp)) + (down-list 1) + (condition-case nil + (dotimes (i company-elisp-parse-limit) + (save-excursion + (when (looking-at "[ \t\n]*(") + (down-list 1)) + (when (looking-at regexp) + (pushnew (match-string-no-properties 1) res))) + (forward-sexp)) + (scan-error nil))) + ((unless functions-p + (looking-at company-elisp-var-binding-regexp-1)) + (down-list 1) + (when (looking-at regexp) + (pushnew (match-string-no-properties 1) res))))))))) + (scan-error nil)) + res)) (defun company-elisp-candidates (prefix) + (let* ((predicate (company-elisp--candidates-predicate prefix)) + (locals (company-elisp--locals prefix (eq predicate 'fboundp))) + (globals (company-elisp--globals prefix predicate)) + (locals (loop for local in locals + when (not (member local globals)) + collect local))) + (if company-elisp-show-locals-first + (append (sort locals 'string<) + (sort globals 'string<)) + (append locals globals)))) + +(defun company-elisp--globals (prefix predicate) + (all-completions prefix obarray predicate)) + +(defun company-elisp--candidates-predicate (prefix) (let* ((completion-ignore-case nil) - (before (char-before (- (point) (length prefix)))) - (predicate (if (and company-elisp-detect-function-context - (not (eq before ?'))) - (if (eq before ?\() - 'fboundp - 'boundp) - 'company-elisp-predicate)) - (candidates (all-completions prefix obarray predicate))) - (company-elisp-parse-local prefix candidates))) + (before (char-before (- (point) (length prefix))))) + (if (and company-elisp-detect-function-context + (not (eq before ?'))) + (if (and (eq before ?\() + (not + (save-excursion + (ignore-errors + (up-list -2) + (and (save-excursion + (forward-char 1) + (looking-at "[ \t\n]*(")) + (prog1 (search-backward "(") + (forward-char 1)) + (looking-at company-elisp-var-binding-regexp)))))) + 'fboundp + 'boundp) + 'company-elisp--predicate))) -(defun company-elisp-doc (symbol) +(defun company-elisp--doc (symbol) (let* ((symbol (intern symbol)) (doc (if (fboundp symbol) (documentation symbol t) @@ -122,9 +191,10 @@ (case command (interactive (company-begin-backend 'company-elisp)) (prefix (and (eq (derived-mode-p 'emacs-lisp-mode) 'emacs-lisp-mode) - (company-grab-lisp-symbol))) + (company-elisp--prefix))) (candidates (company-elisp-candidates arg)) - (meta (company-elisp-doc arg)) + (sorted company-elisp-show-locals-first) + (meta (company-elisp--doc arg)) (doc-buffer (let ((symbol (intern arg))) (save-window-excursion (ignore-errors === modified file 'packages/company/company-pkg.el' --- a/packages/company/company-pkg.el 2013-03-23 22:22:44 +0000 +++ b/packages/company/company-pkg.el 2013-04-01 05:30:58 +0000 @@ -1,1 +1,1 @@ -(define-package "company" "0.6.2" "Modular in-buffer completion framework") +(define-package "company" "0.6.6" "Modular in-buffer completion framework") === modified file 'packages/company/company-template.el' --- a/packages/company/company-template.el 2013-03-23 04:19:13 +0000 +++ b/packages/company/company-template.el 2013-04-01 05:30:58 +0000 @@ -39,7 +39,9 @@ (defun company-template-templates-at (pos) (let (os) (dolist (o (overlays-at pos)) - (when (overlay-get o 'company-template-fields) + ;; FIXME: Always return the whole list of templates? + ;; We remove templates not at point after every command. + (when (memq o company-template--buffer-templates) (push o os))) os)) @@ -121,11 +123,9 @@ (defun company-template-clean-up (&optional pos) "Clean up all templates that don't contain POS." - (unless pos (setq pos (point))) - (let ((local-ovs (overlays-in (- pos 2) pos))) + (let ((local-ovs (overlays-at (or pos (point))))) (dolist (templ company-template--buffer-templates) - (unless (and (memq templ local-ovs) - (overlay-get templ 'company-template-fields)) + (unless (memq templ local-ovs) (company-template-remove-template templ))))) ;; hooks ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; === modified file 'packages/company/company-tests.el' --- a/packages/company/company-tests.el 2013-03-23 04:19:13 +0000 +++ b/packages/company/company-tests.el 2013-04-01 05:30:58 +0000 @@ -66,11 +66,305 @@ (company-mode) (should-error (company-begin-backend (lambda (command &rest ignore)))) - (let ((company-backends + (let (company-frontends + (company-backends (list (lambda (command &optional arg) (case command (prefix "a") (candidates '("a" "ab" "ac"))))))) - (company-complete) - (setq this-command 'company-complete) + (let (this-command) + (company-call 'complete)) (should (eq 3 company-candidates-length))))) + +(ert-deftest company-require-match-explicit () + (with-temp-buffer + (insert "ab") + (company-mode) + (let (company-frontends + (company-require-match 'company-explicit-action-p) + (company-backends + (list (lambda (command &optional arg) + (case command + (prefix (buffer-substring (point-min) (point))) + (candidates '("abc" "abd"))))))) + (let (this-command) + (company-complete)) + (let ((last-command-event ?e)) + (company-call 'self-insert-command 1)) + (should (eq 2 company-candidates-length)) + (should (eq 3 (point)))))) + +(ert-deftest company-dont-require-match-when-idle () + (with-temp-buffer + (insert "ab") + (company-mode) + (let (company-frontends + (company-require-match 'company-explicit-action-p) + (company-backends + (list (lambda (command &optional arg) + (case command + (prefix (buffer-substring (point-min) (point))) + (candidates '("abc" "abd"))))))) + (company-idle-begin (current-buffer) (selected-window) + (buffer-chars-modified-tick) (point)) + (let ((last-command-event ?e)) + (company-call 'self-insert-command 1)) + (should (eq nil company-candidates-length)) + (should (eq 4 (point)))))) + +(ert-deftest company-auto-complete-explicit () + (with-temp-buffer + (insert "ab") + (company-mode) + (let (company-frontends + (company-auto-complete 'company-explicit-action-p) + (company-auto-complete-chars '(? )) + (company-backends + (list (lambda (command &optional arg) + (case command + (prefix (buffer-substring (point-min) (point))) + (candidates '("abcd" "abef"))))))) + (let (this-command) + (company-complete)) + (let ((last-command-event ? )) + (company-call 'self-insert-command 1)) + (should (string= "abcd " (buffer-string)))))) + +(ert-deftest company-no-auto-complete-when-idle () + (with-temp-buffer + (insert "ab") + (company-mode) + (let (company-frontends + (company-auto-complete 'company-explicit-action-p) + (company-auto-complete-chars '(? )) + (company-backends + (list (lambda (command &optional arg) + (case command + (prefix (buffer-substring (point-min) (point))) + (candidates '("abcd" "abef"))))))) + (company-idle-begin (current-buffer) (selected-window) + (buffer-chars-modified-tick) (point)) + (let ((last-command-event ? )) + (company-call 'self-insert-command 1)) + (should (string= "ab " (buffer-string)))))) + +(ert-deftest company-clears-explicit-action-when-no-matches () + (with-temp-buffer + (company-mode) + (let (company-frontends + company-backends) + (company-call 'manual-begin) ;; fails + (should (null company-candidates)) + (should (null (company-explicit-action-p)))))) + +(ert-deftest company-pseudo-tooltip-does-not-get-displaced () + (with-temp-buffer + (save-window-excursion + (set-window-buffer nil (current-buffer)) + (save-excursion (insert " ff")) + (company-mode) + (let ((company-frontends '(company-pseudo-tooltip-frontend)) + (company-begin-commands '(self-insert-command)) + (company-backends + (list (lambda (c &optional arg) + (case c (prefix "") (candidates '("a" "b" "c"))))))) + (let (this-command) + (company-call 'complete)) + (company-call 'open-line 1) + (should (eq 2 (overlay-start company-pseudo-tooltip-overlay))))))) + +(ert-deftest company-template-removed-after-the-last-jump () + (with-temp-buffer + (insert "{ }") + (goto-char 2) + (let ((tpl (company-template-declare-template (point) (1- (point-max))))) + (save-excursion + (dotimes (i 2) + (insert " ") + (company-template-add-field tpl (point) "foo") + (forward-char 3))) + (company-call 'template-forward-field) + (should (= 3 (point))) + (company-call 'template-forward-field) + (should (= 7 (point))) + (company-call 'template-forward-field) + (should (= 11 (point))) + (should (zerop (length (overlay-get tpl 'company-template-fields)))) + (should (null (overlay-buffer tpl)))))) + +(ert-deftest company-template-removed-after-input-and-jump () + (with-temp-buffer + (insert "{ }") + (goto-char 2) + (let ((tpl (company-template-declare-template (point) (1- (point-max))))) + (save-excursion + (insert " ") + (company-template-add-field tpl (point) "bar")) + (company-call 'template-move-to-first tpl) + (should (= 3 (point))) + (dolist (c (string-to-list "tee")) + (let ((last-command-event c)) + (company-call 'self-insert-command 1))) + (should (string= "{ tee }" (buffer-string))) + (should (overlay-buffer tpl)) + (company-call 'template-forward-field) + (should (= 7 (point))) + (should (null (overlay-buffer tpl)))))) + +(defun company-call (name &rest args) + (let* ((maybe (intern (format "company-%s" name))) + (command (if (fboundp maybe) maybe name))) + (apply command args) + (let ((this-command command)) + (run-hooks 'post-command-hook)))) + +(defmacro company-elisp-with-buffer (contents &rest body) + (declare (indent 0)) + `(with-temp-buffer + (insert ,contents) + (setq major-mode 'emacs-lisp-mode) + (re-search-backward "|") + (replace-match "") + ,@body)) + +(ert-deftest company-elisp-candidates-predicate () + (company-elisp-with-buffer + "(foo ba|)" + (should (eq (let ((company-elisp-detect-function-context t)) + (company-elisp--candidates-predicate "ba")) + 'boundp)) + (should (eq (let (company-elisp-detect-function-context) + (company-elisp--candidates-predicate "ba")) + 'company-elisp--predicate))) + (company-elisp-with-buffer + "(foo| )" + (should (eq (let ((company-elisp-detect-function-context t)) + (company-elisp--candidates-predicate "foo")) + 'fboundp)) + (should (eq (let (company-elisp-detect-function-context) + (company-elisp--candidates-predicate "foo")) + 'company-elisp--predicate))) + (company-elisp-with-buffer + "(foo 'b|)" + (should (eq (let ((company-elisp-detect-function-context t)) + (company-elisp--candidates-predicate "b")) + 'company-elisp--predicate)))) + +;; This one's also an integration test. +(ert-deftest company-elisp-candidates-recognizes-binding-form () + (let ((company-elisp-detect-function-context t) + (obarray [when what whelp]) + (what 1) + (whelp 2) + (wisp 3)) + (company-elisp-with-buffer + "(let ((foo 7) (wh| )))" + (should (equal '("what" "whelp") + (company-elisp-candidates "wh")))) + (company-elisp-with-buffer + "(cond ((null nil) (wh| )))" + (should (equal '("when") + (company-elisp-candidates "wh")))))) + +(ert-deftest company-elisp-finds-vars () + (let ((obarray [boo bar baz backquote]) + (boo t) + (bar t) + (baz t)) + (should (equal '("bar" "baz") + (company-elisp--globals "ba" 'boundp))))) + +(ert-deftest company-elisp-finds-functions () + (let ((obarray [when what whelp]) + (what t) + (whelp t)) + (should (equal '("when") + (company-elisp--globals "wh" 'fboundp))))) + +(ert-deftest company-elisp-finds-things () + (let ((obarray [when what whelp]) + (what t) + (whelp t)) + (should (equal '("what" "whelp" "when") + (sort (company-elisp--globals "wh" 'company-elisp--predicate) + 'string<))))) + +(ert-deftest company-elisp-locals-vars () + (company-elisp-with-buffer + "(let ((foo 5) (bar 6)) + (cl-labels ((borg ())) + (lambda (boo baz) + b|)))" + (should (equal '("bar" "baz" "boo") + (company-elisp--locals "b" nil))))) + +(ert-deftest company-elisp-locals-single-var () + (company-elisp-with-buffer + "(dotimes (itk 100) + (dolist (item items) + it|))" + (should (equal '("itk" "item") + (company-elisp--locals "it" nil))))) + +(ert-deftest company-elisp-locals-funs () + (company-elisp-with-buffer + "(cl-labels ((foo ()) + (fee ())) + (let ((fun 4)) + (f| )))" + (should (equal '("fee" "foo") + (sort (company-elisp--locals "f" t) 'string<))))) + +(ert-deftest company-elisp-locals-skips-current-varlist () + (company-elisp-with-buffer + "(let ((foo 1) + (f| )))" + (should (null (company-elisp--locals "f" nil))))) + +(ert-deftest company-elisp-show-locals-first () + (company-elisp-with-buffer + "(let ((floo 1) + (flop 2) + (flee 3)) + fl|)" + (let ((obarray [float-pi])) + (let (company-elisp-show-locals-first) + (should (eq nil (company-elisp 'sorted)))) + (let ((company-elisp-show-locals-first t)) + (should (eq t (company-elisp 'sorted))) + (should (equal '("flee" "floo" "flop" "float-pi") + (company-elisp-candidates "fl"))))))) + +(ert-deftest company-elisp-candidates-no-duplicates () + (company-elisp-with-buffer + "(let ((float-pi 4)) + f|)" + (let ((obarray [float-pi]) + (company-elisp-show-locals-first t)) + (should (equal '("float-pi") (company-elisp-candidates "f")))))) + +(ert-deftest company-elisp-shouldnt-complete-defun-name () + (company-elisp-with-buffer + "(defun foob|)" + (should (null (company-elisp 'prefix))))) + +(ert-deftest company-elisp-should-complete-def-call () + (company-elisp-with-buffer + "(defu|" + (should (equal "defu" (company-elisp 'prefix))))) + +(ert-deftest company-elisp-should-complete-in-defvar () + ;; It will also complete the var name, at least for now. + (company-elisp-with-buffer + "(defvar abc de|" + (should (equal "de" (company-elisp 'prefix))))) + +(ert-deftest company-elisp-shouldnt-complete-in-defun-arglist () + (company-elisp-with-buffer + "(defsubst foobar (ba|" + (should (null (company-elisp 'prefix))))) + +(ert-deftest company-elisp-prefix-in-defun-body () + (company-elisp-with-buffer + "(defun foob ()|)" + (should (equal "" (company-elisp 'prefix))))) === modified file 'packages/company/company.el' --- a/packages/company/company.el 2013-03-23 22:22:44 +0000 +++ b/packages/company/company.el 2013-04-01 05:30:58 +0000 @@ -1,10 +1,10 @@ -;;; 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 <dgu...@yandex.ru> -;; Version: 0.6.2 +;; Version: 0.6.6 ;; Keywords: abbrev, convenience, matching ;; URL: http://company-mode.github.com/ ;; Compatibility: GNU Emacs 22.x, GNU Emacs 23.x, GNU Emacs 24.x @@ -86,14 +86,20 @@ :group 'matching) (defface company-tooltip - '((t :background "yellow" - :foreground "black")) + '((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 tool tip." :group 'company) (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) @@ -104,14 +110,20 @@ :group 'company) (defface company-tooltip-common - '((t :inherit company-tooltip - :foreground "red")) + '((default :inherit company-tooltip) + (((background light)) + :foreground "darkred") + (((background dark)) + :foreground "red")) "Face used for the common completion in the tool tip." :group 'company) (defface company-tooltip-common-selection - '((t :inherit company-tooltip-selection - :foreground "red")) + '((default :inherit company-tooltip-selection) + (((background light)) + :foreground "darkred") + (((background dark)) + :foreground "red")) "Face used for the selected common completion in the tool tip." :group 'company) @@ -316,7 +328,7 @@ 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 +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. @@ -363,7 +375,10 @@ (defcustom company-completion-finished-hook nil "Hook run when company successfully completes. -The hook is called with the selected candidate as an argument." +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." :group 'company :type 'hook) @@ -405,7 +420,7 @@ 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." +A character that is part of a valid candidate never triggers auto-completion." :group 'company :type '(choice (string :tag "Characters") (set :tag "Syntax" @@ -475,7 +490,9 @@ (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) @@ -841,14 +858,13 @@ (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 @@ -879,7 +895,10 @@ (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)) @@ -1781,7 +1800,7 @@ args)) (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))) @@ -1794,7 +1813,7 @@ (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 height) + (company--create-lines selection (abs height)) (overlay-get company-pseudo-tooltip-overlay 'company-replacement-args))))) @@ -1815,6 +1834,10 @@ (overlay-get company-pseudo-tooltip-overlay 'company-before)) (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." (case command @@ -1826,10 +1849,15 @@ 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))