]> rtime.felk.cvut.cz Git - sojka/company-mode.git/blobdiff - company.el
Bumped version to 0.4.
[sojka/company-mode.git] / company.el
index 086c021c749c25080b7ca33fa031be8f1306acb5..9233d576059b2f743d3883775541098689b683fd 100644 (file)
@@ -3,7 +3,7 @@
 ;; Copyright (C) 2009 Nikolaj Schumacher
 ;;
 ;; Author: Nikolaj Schumacher <bugs * nschum de>
-;; Version: 0.2.1
+;; Version: 0.4
 ;; Keywords: abbrev, convenience, matchis
 ;; URL: http://nschum.de/src/emacs/company/
 ;; Compatibility: GNU Emacs 22.x, GNU Emacs 23.x
 ;;
 ;;; Change Log:
 ;;
+;; 2009-04-18 (0.4)
+;;    Automatic completion is now aborted if the prefix gets too short.
+;;    Added option `company-dabbrev-time-limit'.
+;;    `company-backends' now supports merging back-ends.
+;;    Added back-end `company-dabbrev-code' for generic code.
+;;    Fixed `company-begin-with'.
+;;
+;; 2009-04-15 (0.3.1)
+;;    Added 'stop prefix to prevent dabbrev from completing inside of symbols.
+;;    Fixed issues with tabbar-mode and line-spacing.
+;;    Performance enhancements.
+;;
+;; 2009-04-12 (0.3)
+;;    Added `company-begin-commands' option.
 ;;    Added abbrev, tempo and Xcode back-ends.
 ;;    Back-ends are now interactive.  You can start them with M-x backend-name.
 ;;    Added `company-begin-with' for starting company from elisp-code.
@@ -233,18 +247,50 @@ The visualized data is stored in `company-prefix', `company-candidates',
                                 company-preview-if-just-one-frontend)
                          (function :tag "custom function" nil))))
 
+(defvar company-safe-backends
+  '((company-abbrev . "Abbrev")
+    (company-css . "CSS")
+    (company-dabbrev . "dabbrev for plain text")
+    (company-dabbrev-code . "dabbrev for code")
+    (company-elisp . "Emacs Lisp")
+    (company-etags . "etags")
+    (company-files . "Files")
+    (company-gtags . "GNU Global")
+    (company-ispell . "ispell")
+    (company-keywords . "Programming language keywords")
+    (company-nxml . "nxml")
+    (company-oddmuse . "Oddmuse")
+    (company-semantic . "CEDET Semantic")
+    (company-tempo . "Tempo templates")
+    (company-xcode . "Xcode")))
+(put 'company-safe-backends 'risky-local-variable t)
+
+(defun company-safe-backends-p (backends)
+  (and (consp backends)
+       (not (dolist (backend backends)
+              (unless (if (consp backend)
+                          (company-safe-backends-p backend)
+                        (assq backend company-safe-backends))
+                (return t))))))
+
 (defcustom company-backends '(company-elisp company-nxml company-css
-                              company-semantic company-xcode company-gtags
-                              company-etags company-oddmuse company-files
-                              company-dabbrev)
+                              company-semantic company-xcode
+                              (company-gtags company-etags company-dabbrev-code
+                               company-keywords)
+                              company-oddmuse company-files company-dabbrev)
   "*The list of active back-ends (completion engines).
+Each list elements can itself be a list of back-ends.  In that case their
+completions are merged.  Otherwise only the first matching back-end returns
+results.
+
 Each back-end is a function that takes a variable number of arguments.
 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.
+back-end.  The function should return 'stop if it should complete but cannot
+\(e.g. if it is in the middle of a string\).
 
 'candidates: The second argument is the prefix to be completed.  The
 return value should be a list of candidates that start with the prefix.
@@ -254,6 +300,9 @@ 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.
 
+'duplicates: If non-nil, company will take care of removing duplicates
+from the list.
+
 'no-cache: Usually company doesn't ask for candidates again as completion
 progresses, unless the back-end returns t for this command.  The second
 argument is the latest prefix.
@@ -278,9 +327,20 @@ 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 (function :tag "function" nil)))
-
-(defvar start-count 0)
+  :type `(repeat
+          (choice
+           :tag "Back-end"
+           ,@(mapcar (lambda (b) `(const :tag ,(cdr b) ,(car b)))
+                     company-safe-backends)
+           (symbol :tag "User defined")
+           (repeat :tag "Merged Back-ends"
+                   (choice :tag "Back-end"
+                           ,@(mapcar (lambda (b)
+                                       `(const :tag ,(cdr b) ,(car b)))
+                                     company-safe-backends)
+                           (symbol :tag "User defined"))))))
+
+(put 'company-backends 'safe-local-variable 'company-safe-backend-p)
 
 (defcustom company-completion-started-hook nil
   "*Hook run when company starts completing.
@@ -335,7 +395,7 @@ the selected completion.  This can also be a function."
   "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
-`modify-char-syntax'), all characters with that syntax auto-complete.
+`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.
@@ -369,6 +429,17 @@ immediately when a prefix of `company-minimum-prefix-length' is reached."
                  (const :tag "immediate (t)" t)
                  (number :tag "seconds")))
 
+(defcustom company-begin-commands t
+  "*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
+  :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
@@ -411,6 +482,19 @@ The work-around consists of adding a newline.")
     keymap)
   "Keymap that is enabled during an active completion.")
 
+(defun company-init-backend (backend)
+  (and (symbolp backend)
+       (not (fboundp backend))
+       (ignore-errors (require backend nil t)))
+
+  (if (or (symbolp backend)
+          (functionp backend))
+      (if (ignore-errors (funcall backend 'init) t)
+          (put backend 'company-init t)
+        (message "Company back-end '%s' could not be initialized"
+                 backend))
+    (mapc 'company-init-backend backend)))
+
 ;;;###autoload
 (define-minor-mode company-mode
   "\"complete anything\"; in in-buffer completion framework.
@@ -441,13 +525,7 @@ keymap during active completions (`company-active-map'):
       (progn
         (add-hook 'pre-command-hook 'company-pre-command nil t)
         (add-hook 'post-command-hook 'company-post-command nil t)
-        (dolist (backend company-backends)
-          (when (symbolp backend)
-            (unless (fboundp backend)
-              (ignore-errors (require backend nil t)))
-            (unless (fboundp backend)
-              (message "Company back-end '%s' could not be initialized"
-                       backend)))))
+        (mapc 'company-init-backend company-backends))
     (remove-hook 'pre-command-hook 'company-pre-command t)
     (remove-hook 'post-command-hook 'company-post-command t)
     (company-cancel)
@@ -490,7 +568,8 @@ keymap during active completions (`company-active-map'):
 ;; Emacs calculates the active keymaps before reading the event.  That means we
 ;; cannot change the keymap from a timer.  So we send a bogus command.
 (defun company-ignore ()
-  (interactive))
+  (interactive)
+  (setq this-command last-command))
 
 (global-set-key '[31415926] 'company-ignore)
 
@@ -499,13 +578,50 @@ keymap during active completions (`company-active-map'):
 
 ;;; backends ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
-(defun company-grab (regexp &optional expression)
-  (when (looking-back regexp)
+(defun company-grab (regexp &optional expression limit)
+  (when (looking-back regexp limit)
     (or (match-string-no-properties (or expression 0)) "")))
 
-(defun company-in-string-or-comment (&optional point)
-  (let ((pos (syntax-ppss)))
-    (or (nth 3 pos) (nth 4 pos) (nth 7 pos))))
+(defun company-grab-line (regexp &optional expression)
+  (company-grab regexp expression (point-at-bol)))
+
+(defun company-grab-symbol ()
+  (if (looking-at "\\_>")
+      (buffer-substring (point) (save-excursion (skip-syntax-backward "w_")
+                                                (point)))
+    (unless (and (char-after) (memq (char-syntax (char-after)) '(?w ?_)))
+      "")))
+
+(defun company-grab-word ()
+  (if (looking-at "\\>")
+      (buffer-substring (point) (save-excursion (skip-syntax-backward "w")
+                                                (point)))
+    (unless (and (char-after) (eq (char-syntax (char-after)) ?w))
+      "")))
+
+(defun company-in-string-or-comment ()
+  (let ((ppss (syntax-ppss)))
+    (or (car (setq ppss (nthcdr 3 ppss)))
+        (car (setq ppss (cdr ppss)))
+        (nth 3 ppss))))
+
+(defun company-call-backend (&rest args)
+  (if (functionp company-backend)
+      (apply company-backend args)
+    (apply 'company--multi-backend-adapter company-backend args)))
+
+(defun company--multi-backend-adapter (backends command &rest args)
+  (case command
+    ('candidates
+     (apply 'append (mapcar (lambda (backend) (apply backend command args))
+                            backends)))
+    ('sorted nil)
+    ('duplicates t)
+    (otherwise
+     (let (value)
+       (dolist (backend backends)
+         (when (setq value (apply backend command args))
+           (return value)))))))
 
 ;;; completion mechanism ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
@@ -540,6 +656,11 @@ keymap during active completions (`company-active-map'):
   "Non-nil, if explicit completion took place.")
 (make-variable-buffer-local 'company--explicit-action)
 
+(defvar company--point-max nil)
+(make-variable-buffer-local 'company--point-max)
+
+(defvar company--this-command nil)
+
 (defvar company-point nil)
 (make-variable-buffer-local 'company-point)
 
@@ -561,10 +682,14 @@ keymap during active completions (`company-active-map'):
   ;; It's mory efficient to fix it only when they are displayed.
   (concat company-prefix (substring candidate (length company-prefix))))
 
-(defsubst company-should-complete (prefix)
-  (and (eq company-idle-delay t)
-       (not (and transient-mark-mode mark-active))
-       (>= (length prefix) company-minimum-prefix-length)))
+(defun company--should-complete ()
+  (and (not (or buffer-read-only overriding-terminal-local-map
+                overriding-local-map))
+       (eq company-idle-delay t)
+       (or (eq t company-begin-commands)
+           (memq company--this-command company-begin-commands)
+           (and (symbolp this-command) (get this-command 'company-begin)))
+       (not (and transient-mark-mode mark-active))))
 
 (defsubst company-call-frontends (command)
   (dolist (frontend company-frontends)
@@ -606,7 +731,7 @@ keymap during active completions (`company-active-map'):
   ;; Save in cache:
   (push (cons company-prefix company-candidates) company-candidates-cache)
   ;; Calculate common.
-  (let ((completion-ignore-case (funcall company-backend 'ignore-case)))
+  (let ((completion-ignore-case (company-call-backend 'ignore-case)))
     (setq company-common (try-completion company-prefix company-candidates)))
   (when (eq company-common t)
     (setq company-candidates nil)))
@@ -616,19 +741,25 @@ keymap during active completions (`company-active-map'):
          (or (cdr (assoc prefix company-candidates-cache))
              (when company-candidates-cache
                (let ((len (length prefix))
-                     (completion-ignore-case (funcall company-backend
-                                                      'ignore-case))
+                     (completion-ignore-case (company-call-backend
+                                              'ignore-case))
                      prev)
-                 (dotimes (i len)
+                 (dotimes (i (1+ len))
                    (when (setq prev (cdr (assoc (substring prefix 0 (- len i))
                                                 company-candidates-cache)))
                      (return (all-completions prefix prev))))))
-             (let ((c (funcall company-backend 'candidates prefix)))
+             (let ((c (company-call-backend 'candidates prefix)))
                (when company-candidates-predicate
                  (setq c (company-apply-predicate
                           c company-candidates-predicate)))
-               (unless (funcall company-backend 'sorted)
+               (unless (company-call-backend 'sorted)
                  (setq c (sort c 'string<)))
+               (when (company-call-backend 'duplicates)
+                 ;; strip duplicates
+                 (let ((c2 c))
+                   (while c2
+                     (setcdr c2 (progn (while (equal (pop c2) (car c2)))
+                                       c2)))))
                c))))
     (if (or (cdr candidates)
             (not (equal (car candidates) prefix)))
@@ -657,18 +788,15 @@ keymap during active completions (`company-active-map'):
   (and company-mode
        (not company-candidates)
        (let ((company-idle-delay t)
-             (company-minimum-prefix-length 0))
+             (company-minimum-prefix-length 0)
+             (company-begin-commands t))
          (setq company--explicit-action t)
          (company-begin)))
   ;; Return non-nil if active.
   company-candidates)
 
-(defsubst company-incremental-p (old-prefix new-prefix)
-  (and (> (length new-prefix) (length old-prefix))
-       (equal old-prefix (substring new-prefix 0 (length old-prefix)))))
-
 (defun company-require-match-p ()
-  (let ((backend-value (funcall company-backend 'require-match)))
+  (let ((backend-value (company-call-backend 'require-match)))
     (or (eq backend-value t)
         (and (if (functionp company-require-match)
                  (funcall company-require-match)
@@ -679,84 +807,113 @@ keymap during active completions (`company-active-map'):
   "Return non-nil, if input starts with punctuation or parentheses."
   (memq (char-syntax (string-to-char input)) '(?. ?\( ?\))))
 
-(defun company-auto-complete-p (beg end)
+(defun company-auto-complete-p (input)
   "Return non-nil, if input starts with punctuation or parentheses."
-  (and (> end beg)
-       (if (functionp company-auto-complete)
+  (and (if (functionp company-auto-complete)
            (funcall company-auto-complete)
          company-auto-complete)
        (if (functionp company-auto-complete-chars)
-           (funcall company-auto-complete-chars (buffer-substring beg end))
+           (funcall company-auto-complete-chars input)
          (if (consp company-auto-complete-chars)
-             (memq (char-syntax (char-after beg)) company-auto-complete-chars)
-           (string-match (buffer-substring beg (1+ beg))
-                         company-auto-complete-chars)))))
-
-(defun company-continue ()
-  (when company-candidates
-    (when (funcall company-backend 'no-cache company-prefix)
-      ;; Don't complete existing candidates, fetch new ones.
-      (setq company-candidates-cache nil))
-    (let ((new-prefix (funcall company-backend 'prefix)))
-      (unless (and (= (- (point) (length new-prefix))
-                      (- company-point (length company-prefix)))
-                   (or (equal company-prefix new-prefix)
-                       (let ((c (company-calculate-candidates new-prefix)))
-                         ;; t means complete/unique.
-                         (if (eq c t)
-                             (progn (company-cancel new-prefix) t)
-                           (when (consp c)
-                             (setq company-prefix new-prefix)
-                             (company-update-candidates c)
-                             t)))))
-        (if (company-auto-complete-p company-point (point))
-            (save-excursion
-              (goto-char company-point)
-              (company-complete-selection)
-              (setq company-candidates nil))
-          (if (not (and (company-incremental-p company-prefix new-prefix)
-                        (company-require-match-p)))
-              (progn
-                (when (equal company-prefix (car company-candidates))
-                  ;; cancel, but last input was actually success
-                  (company-cancel company-prefix))
-                (setq company-candidates nil))
-            (backward-delete-char (length new-prefix))
-            (insert company-prefix)
-            (ding)
-            (message "Matching input is required")))
-        company-candidates))))
+             (memq (char-syntax (string-to-char input))
+                   company-auto-complete-chars)
+           (string-match (substring input 0 1) company-auto-complete-chars)))))
+
+(defun company--incremental-p ()
+  (and (> (point) company-point)
+       (> (point-max) company--point-max)
+       (equal (buffer-substring (- company-point (length company-prefix))
+                                company-point)
+              company-prefix)))
+
+(defsubst company--string-incremental-p (old-prefix new-prefix)
+  (and (> (length new-prefix) (length old-prefix))
+       (equal old-prefix (substring new-prefix 0 (length old-prefix)))))
+
+(defun company--continue-failed (new-prefix)
+  (when (company--incremental-p)
+    (let ((input (buffer-substring-no-properties (point) company-point)))
+      (cond
+       ((company-auto-complete-p input)
+        ;; auto-complete
+        (save-excursion
+          (goto-char company-point)
+          (company-complete-selection)
+          nil))
+       ((and (company--string-incremental-p company-prefix new-prefix)
+             (company-require-match-p))
+        ;; wrong incremental input, but required match
+        (backward-delete-char (length input))
+        (ding)
+        (message "Matching input is required")
+        company-candidates)
+       ((equal company-prefix (car company-candidates))
+        ;; last input was actually success
+        (company-cancel company-prefix)
+        nil)))))
+
+(defun company--continue ()
+  (when (company-call-backend 'no-cache company-prefix)
+    ;; Don't complete existing candidates, fetch new ones.
+    (setq company-candidates-cache nil))
+  (let* ((new-prefix (company-call-backend 'prefix))
+         (c (when (and (stringp new-prefix)
+                       (or (company-explicit-action-p)
+                           (>= (length new-prefix)
+                               company-minimum-prefix-length))
+                       (= (- (point) (length new-prefix))
+                          (- company-point (length company-prefix))))
+              (company-calculate-candidates new-prefix))))
+    (cond
+     ((eq c t)
+      ;; t means complete/unique.
+      (company-cancel new-prefix)
+      nil)
+     ((consp c)
+      ;; incremental match
+      (setq company-prefix new-prefix)
+      (company-update-candidates c)
+      c)
+     (t (company--continue-failed new-prefix)))))
+
+(defun company--begin-new ()
+  (let (prefix c)
+    (dolist (backend (if company-backend
+                         ;; prefer manual override
+                         (list company-backend)
+                       company-backends))
+      (setq prefix
+            (if (or (symbolp backend)
+                    (functionp backend))
+                (when (or (not (symbolp backend))
+                          (get backend 'company-init))
+                  (funcall backend 'prefix))
+              (company--multi-backend-adapter backend 'prefix)))
+      (when prefix
+        (when (and (stringp prefix)
+                   (>= (length prefix) company-minimum-prefix-length))
+          (setq company-backend backend
+                company-prefix prefix
+                c (company-calculate-candidates prefix))
+          ;; t means complete/unique.  We don't start, so no hooks.
+          (when (consp c)
+            (company-update-candidates c)
+            (run-hook-with-args 'company-completion-started-hook
+                                (company-explicit-action-p))
+            (company-call-frontends 'show)))
+        (return c)))))
 
 (defun company-begin ()
-  (if (or buffer-read-only overriding-terminal-local-map overriding-local-map)
-      ;; Don't complete in these cases.
-      (setq company-candidates nil)
-    (company-continue)
-    (unless company-candidates
-      (let (prefix)
-        (dolist (backend (if company-backend
-                             ;; prefer manual override
-                             (list company-backend)
-                           (cons company-backend company-backends)))
-          (when (and (functionp backend)
-                     (setq prefix (funcall backend 'prefix)))
-            (setq company-backend backend)
-            (when (company-should-complete prefix)
-              (let ((c (company-calculate-candidates prefix)))
-                ;; t means complete/unique.  We don't start, so no hooks.
-                (when (consp c)
-                  (setq company-prefix prefix)
-                  (company-update-candidates c)
-                  (run-hook-with-args 'company-completion-started-hook
-                                      (company-explicit-action-p))
-                  (company-call-frontends 'show))))
-            (return prefix))))))
+  (setq company-candidates
+        (or (and company-candidates (company--continue))
+            (and (company--should-complete) (company--begin-new))))
   (if company-candidates
       (progn
         (when (and company-end-of-buffer-workaround (eobp))
           (save-excursion (insert "\n"))
           (setq company-added-newline (buffer-chars-modified-tick)))
-        (setq company-point (point))
+        (setq company-point (point)
+              company--point-max (point-max))
         (company-enable-overriding-keymap company-active-map)
         (company-call-frontends 'update))
     (company-cancel)))
@@ -784,6 +941,7 @@ keymap during active completions (`company-active-map'):
         company-selection 0
         company-selection-changed nil
         company--explicit-action nil
+        company--point-max nil
         company-point nil)
   (when company-timer
     (cancel-timer company-timer))
@@ -822,6 +980,7 @@ keymap during active completions (`company-active-map'):
   (unless (company-keep this-command)
     (condition-case err
         (progn
+          (setq company--this-command this-command)
           (unless (equal (point) company-point)
             (company-begin))
           (when company-candidates
@@ -1043,8 +1202,8 @@ followed by `company-search-kill-others' after each input."
   "Select the candidate picked by the mouse."
   (interactive "e")
   (when (nth 4 (event-start event))
-    (company-set-selection (- (cdr (posn-col-row (event-start event)))
-                              (cdr (posn-col-row (posn-at-point)))
+    (company-set-selection (- (cdr (posn-actual-col-row (event-start event)))
+                              (cdr (posn-actual-col-row (posn-at-point)))
                               1))
     t))
 
@@ -1064,8 +1223,8 @@ followed by `company-search-kill-others' after each input."
   "Complete the common part of all candidates."
   (interactive)
   (when (company-manual-begin)
-    (if (equal company-common (car company-candidates))
-        ;; for success message
+    (if (and (not (cdr company-candidates))
+             (equal company-common (car company-candidates)))
         (company-complete-selection)
       (insert (company-strip-prefix company-common)))))
 
@@ -1082,7 +1241,9 @@ when the selection has been changed, the selected candidate is completed."
       (setq this-command 'company-complete-common))))
 
 (defun company-complete-number (n)
-  "Complete the Nth candidate."
+  "Complete the Nth candidate.
+To show the number next to the candidates in some back-ends, enable
+`company-show-numbers'."
   (when (company-manual-begin)
     (and (< n 1) (> n company-candidates-length)
          (error "No candidate number %d" n))
@@ -1122,7 +1283,7 @@ when the selection has been changed, the selected candidate is completed."
   (let ((selected (nth company-selection company-candidates)))
     (unless (equal selected (car company-last-metadata))
       (setq company-last-metadata
-            (cons selected (funcall company-backend 'meta selected))))
+            (cons selected (company-call-backend 'meta selected))))
     (cdr company-last-metadata)))
 
 (defun company-doc-buffer (&optional string)
@@ -1135,7 +1296,7 @@ when the selection has been changed, the selected candidate is completed."
   `(when (company-manual-begin)
      (save-window-excursion
        (let ((height (window-height))
-             (row (cdr (posn-col-row (posn-at-point)))))
+             (row (cdr (posn-actual-col-row (posn-at-point)))))
          ,@body
          (and (< (window-height) height)
               (< (- (window-height) row 2) company-tooltip-limit)
@@ -1152,7 +1313,7 @@ when the selection has been changed, the selected candidate is completed."
   (interactive)
   (company-electric
     (let ((selected (nth company-selection company-candidates)))
-      (display-buffer (or (funcall company-backend 'doc-buffer selected)
+      (display-buffer (or (company-call-backend 'doc-buffer selected)
                           (error "No documentation available")) t))))
 (put 'company-show-doc-buffer 'company-keep t)
 
@@ -1161,7 +1322,7 @@ when the selection has been changed, the selected candidate is completed."
   (interactive)
   (company-electric
     (let* ((selected (nth company-selection company-candidates))
-           (location (funcall company-backend 'location selected))
+           (location (company-call-backend 'location selected))
            (pos (or (cdr location) (error "No location available")))
            (buffer (or (and (bufferp (car location)) (car location))
                        (find-file-noselect (car location) t))))
@@ -1177,9 +1338,14 @@ when the selection has been changed, the selected candidate is completed."
 (defvar company-callback nil)
 (make-variable-buffer-local 'company-callback)
 
+(defvar company-begin-with-marker nil)
+(make-variable-buffer-local 'company-begin-with-marker)
+
 (defun company-remove-callback (&optional ignored)
   (remove-hook 'company-completion-finished-hook company-callback t)
-  (remove-hook 'company-completion-cancelled-hook 'company-remove-callback t))
+  (remove-hook 'company-completion-cancelled-hook 'company-remove-callback t)
+  (remove-hook 'company-completion-finished-hook 'company-remove-callback t)
+  (set-marker company-begin-with-marker nil))
 
 (defun company-begin-backend (backend &optional callback)
   "Start a completion at point using BACKEND."
@@ -1188,13 +1354,10 @@ when the selection has been changed, the selected candidate is completed."
                                            'functionp nil "company-")))
                  (when val
                    (list (intern val)))))
-  (when callback
-    (setq company-callback
-          `(lambda (completion)
-             (funcall ',callback completion)
-             (company-remove-callback)))
-    (add-hook 'company-completion-cancelled-hook 'company-remove-callback nil t)
+  (when (setq company-callback callback)
     (add-hook 'company-completion-finished-hook company-callback nil t))
+  (add-hook 'company-completion-cancelled-hook 'company-remove-callback nil t)
+  (add-hook 'company-completion-finished-hook 'company-remove-callback nil t)
   (setq company-backend backend)
   ;; Return non-nil if active.
   (or (company-manual-begin)
@@ -1211,15 +1374,17 @@ completes the input.
 
 Example:
 \(company-begin-with '\(\"foo\" \"foobar\" \"foobarbaz\"\)\)"
+  (setq company-begin-with-marker (copy-marker (point) t))
   (company-begin-backend
-   (let ((start (- (point) (or prefix-length 0))))
-     `(lambda (command &optional arg &rest ignored)
-        (case command-history
-          ('prefix (message "prefix %s" (buffer-substring ,start (point)))
-                   (when (>= (point) ,start)
-                     (buffer-substring ,start (point))))
-          ('candidates (all-completions arg ',candidates))
-          ('require-match ,require-match))))
+   `(lambda (command &optional arg &rest ignored)
+      (cond
+       ((eq command 'prefix)
+        (when (equal (point) (marker-position company-begin-with-marker))
+          (buffer-substring ,(- (point) (or prefix-length 0)) (point))))
+       ((eq command 'candidates)
+        (all-completions arg ',candidates))
+       ((eq command 'require-match)
+        ,require-match)))
    callback))
 
 ;;; pseudo-tooltip ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -1299,7 +1464,7 @@ Example:
 
 (defun company-buffer-lines (beg end)
   (goto-char beg)
-  (let ((row (cdr (posn-col-row (posn-at-point))))
+  (let ((row (cdr (posn-actual-col-row (posn-at-point))))
         lines)
     (while (and (equal (move-to-window-line (incf row)) row)
                 (<= (point) end))
@@ -1348,7 +1513,7 @@ Example:
                       (setq remainder (format "...(%d)" remainder))))
 
     (decf selection company-tooltip-offset)
-    (setq width (min (length previous) (length remainder))
+    (setq width (max (length previous) (length remainder))
           lines (nthcdr company-tooltip-offset company-candidates)
           len (min limit len)
           lines-copy lines)
@@ -1360,9 +1525,8 @@ Example:
     (setq lines-copy lines)
 
     ;; number can make tooltip too long
-    (and company-show-numbers
-         (< (setq numbered company-tooltip-offset) 10)
-         (incf width 2))
+    (when company-show-numbers
+      (setq numbered company-tooltip-offset))
 
     (when previous
       (push (propertize (company-safe-substring previous 0 width)
@@ -1425,8 +1589,10 @@ Example:
       (overlay-put company-pseudo-tooltip-overlay 'window (selected-window)))))
 
 (defun company-pseudo-tooltip-show-at-point (pos)
-  (let ((col-row (posn-col-row (posn-at-point pos))))
-    (company-pseudo-tooltip-show (1+ (cdr col-row)) (car col-row) company-selection)))
+  (let ((col-row (posn-actual-col-row (posn-at-point 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* ((old-string (overlay-get company-pseudo-tooltip-overlay 'company-old))