emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] master 4c1fd0e 16/78: Merge pull request #706 from nikital/compan


From: Dmitry Gutov
Subject: [elpa] master 4c1fd0e 16/78: Merge pull request #706 from nikital/company-tng
Date: Sun, 18 Feb 2018 07:40:13 -0500 (EST)

branch: master
commit 4c1fd0ea05bdcc188f6de43275cef73ccc89ec0a
Merge: c0098af 66a9e65
Author: Dmitry Gutov <address@hidden>
Commit: GitHub <address@hidden>

    Merge pull request #706 from nikital/company-tng
    
    Company Tab and Go
---
 NEWS.md        |   5 ++
 company-tng.el | 155 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 company.el     |  23 ++++++---
 3 files changed, 175 insertions(+), 8 deletions(-)

diff --git a/NEWS.md b/NEWS.md
index 5d5c63c..acc5968 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -3,6 +3,11 @@
 ## Next
 
 * New user option `company-tooltip-maximum-width`.
+* New feature `company-tng'. When added as a frontend, it allows you to insert
+  the candidates as soon they are selected, eliminating the need to press RET 
to
+  confirm your selection. See `company-tng.el` and use
+  `(company-tng-configure-default)` to give it a try.
+  ([#526](https://github.com/company-mode/company-mode/issues/526))
 
 ## 2017-07-15 (0.9.4)
 
diff --git a/company-tng.el b/company-tng.el
new file mode 100644
index 0000000..3996f31
--- /dev/null
+++ b/company-tng.el
@@ -0,0 +1,155 @@
+;;; company-tng.el --- company-mode frontend that inserts a candidate
+;;; into the buffer as soon as it's selected, Vim style
+
+;; Copyright (C) 2017  Free Software Foundation, Inc.
+
+;; Author: Nikita Leshenko
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
+
+
+;;; Commentary:
+;;
+;; company-tng (tab and go) allows you to use TAB to both select a
+;; completion candidate from the list and to insert it into the
+;; buffer.
+;;
+;; It cycles the candidates like `yank-pop' or `dabbrev-expand' or
+;; Vim: Pressing TAB selects the first item in the completion menu and
+;; inserts it in the buffer. Pressing TAB again selects the second
+;; item and replaces the inserted item with the second one. This can
+;; continue as long as the user wishes to cycle through the menu.
+;;
+;; The benefits are that there is only one shortcut key to interact
+;; with and there is no need to confirm an entry.
+;;
+;; Usage:
+;;
+;; To apply the default configuration for company-tng call
+;; `company-tng-configure-default' from your configuration file.
+;;
+;; You can also configure company-tng manually:
+;;
+;; Add `company-tng-frontend' to `company-frontends':
+;; (add-to-list 'company-frontends 'company-tng-frontend)
+;;
+;; We recommend to bind TAB to `company-select-next', S-TAB to
+;; `company-select-previous', and unbind RET and other now-unnecessary
+;; keys from `company-active-map':
+;; (define-key company-active-map (kbd "TAB") 'company-select-next)
+;; (define-key company-active-map (kbd "<backtab>") 'company-select-previous)
+;; (define-key company-active-map (kbd "RET") nil)
+;; Note that it's not necessary to rebind keys to use this frontend,
+;; you can use the arrow keys or M-n/M-p to select and insert
+;; candidates. You also need to decide which keys to unbind, depending
+;; on whether you want them to do the Company action or the default
+;; Emacs action (for example C-s or C-w).
+
+;;; Code:
+
+(require 'company)
+(require 'cl-lib)
+
+(defvar-local company-tng--overlay nil)
+
+;;;###autoload
+(defun company-tng-frontend (command)
+  "When the user changes the selection at least once, this
+frontend will display the candidate in the buffer as if it's
+already there and any key outside of `company-active-map' will
+confirm the selection and finish the completion."
+  (cl-case command
+    (show
+     (let ((ov (make-overlay (point) (point))))
+       (setq company-tng--overlay ov)
+       (overlay-put ov 'priority 2))
+     (advice-add 'company-select-next :before-until 
'company-tng--allow-unselected)
+     (advice-add 'company-fill-propertize :filter-args 
'company-tng--adjust-tooltip-highlight))
+    (update
+     (let ((ov company-tng--overlay)
+           (selected (nth company-selection company-candidates))
+           (prefix (length company-prefix)))
+       (move-overlay ov (- (point) prefix) (point))
+       (overlay-put ov
+                    (if (= prefix 0) 'after-string 'display)
+                    (and company-selection-changed selected))
+       (overlay-put ov 'display (and company-selection-changed selected))))
+    (hide
+     (when company-tng--overlay
+       (delete-overlay company-tng--overlay)
+       (kill-local-variable 'company-tng--overlay))
+     (advice-remove 'company-select-next 'company-tng--allow-unselected)
+     (advice-remove 'company-fill-propertize 
'company-tng--adjust-tooltip-highlight))
+    (pre-command
+     (when (and company-selection-changed
+                (not (company--company-command-p (this-command-keys))))
+       (company--unread-this-command-keys)
+       (setq this-command 'company-complete-selection)))))
+
+;;;###autoload
+(defun company-tng-configure-default ()
+  "Applies the default configuration to enable company-tng."
+  (add-to-list 'company-frontends 'company-tng-frontend)
+  (let ((keymap company-active-map))
+    (define-key keymap [return] nil)
+    (define-key keymap (kbd "RET") nil)
+    (define-key keymap [tab] 'company-select-next)
+    (define-key keymap (kbd "TAB") 'company-select-next)
+    (define-key keymap [backtab] 'company-select-previous)
+    (define-key keymap (kbd "S-TAB") 'company-select-previous)))
+
+(defun company-tng--allow-unselected (&optional arg)
+  "Advice `company-select-next' to allow for an 'unselected'
+state. Unselected means that no user interaction took place on the
+completion candidates and it's marked by setting
+`company-selection-changed' to nil. This advice will call the underlying
+`company-select-next' unless we need to transition to or from an unselected
+state.
+
+Possible state transitions:
+- (arg > 0) unselected -> first candidate selected
+- (arg < 0) first candidate selected -> unselected
+- (arg < 0 wrap-round) unselected -> last candidate selected
+- (arg < 0 no wrap-round) unselected -> unselected
+
+There is no need to advice `company-select-previous' because it calls
+`company-select-next' internally."
+  (cond
+   ;; Selecting next
+   ((or (not arg) (> arg 0))
+    (unless company-selection-changed
+      (company-set-selection (1- (or arg 1)) 'force-update)
+      t))
+   ;; Selecting previous
+   ((< arg 0)
+    (when (and company-selection-changed
+               (< (+ company-selection arg) 0))
+      (company-set-selection 0)
+      (setq company-selection-changed nil)
+      (company-call-frontends 'update)
+      t)
+    )))
+
+(defun company-tng--adjust-tooltip-highlight (args)
+  "Prevent the tooltip from highlighting the current selection if it wasn't
+made explicitly (i.e. `company-selection-changed' is true)"
+  (unless company-selection-changed
+    ;; The 4th arg of `company-fill-propertize' is selected
+    (setf (nth 3 args) nil))
+  args)
+
+(provide 'company-tng)
+;;; company-tng.el ends here
diff --git a/company.el b/company.el
index 1cb02ab..ad35411 100644
--- a/company.el
+++ b/company.el
@@ -815,6 +815,11 @@ means that `company-mode' is always turned on except in 
`message-mode' buffers."
 (defun company-uninstall-map ()
   (setf (cdar company-emulation-alist) nil))
 
+(defun company--company-command-p (keys)
+  "Checks if the keys are part of company's overriding keymap"
+  (or (equal [company-dummy-event] keys)
+      (lookup-key company-my-keymap keys)))
+
 ;; Hack:
 ;; 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.
@@ -1840,7 +1845,7 @@ each one wraps a part of the input string."
   (interactive)
   (company--search-assert-enabled)
   (company-search-mode 0)
-  (company--unread-last-input))
+  (company--unread-this-command-keys))
 
 (defun company-search-delete-char ()
   (interactive)
@@ -1984,7 +1989,7 @@ With ARG, move by that many elements."
   (if (> company-candidates-length 1)
       (company-select-next arg)
     (company-abort)
-    (company--unread-last-input)))
+    (company--unread-this-command-keys)))
 
 (defun company-select-previous-or-abort (&optional arg)
   "Select the previous candidate if more than one, else abort
@@ -1995,7 +2000,7 @@ With ARG, move by that many elements."
   (if (> company-candidates-length 1)
       (company-select-previous arg)
     (company-abort)
-    (company--unread-last-input)))
+    (company--unread-this-command-keys)))
 
 (defun company-next-page ()
   "Select the candidate one page further."
@@ -2063,7 +2068,7 @@ With ARG, move by that many elements."
                                       0)))
           t)
       (company-abort)
-      (company--unread-last-input)
+      (company--unread-this-command-keys)
       nil)))
 
 (defun company-complete-mouse (event)
@@ -2240,10 +2245,12 @@ character, stripping the modifiers.  That character 
must be a digit."
             (< (- (window-height) row 2) company-tooltip-limit)
             (recenter (- (window-height) row 2))))))
 
-(defun company--unread-last-input ()
-  (when last-input-event
-    (clear-this-command-keys t)
-    (setq unread-command-events (list last-input-event))))
+(defun company--unread-this-command-keys ()
+  (when (> (length (this-command-keys)) 0)
+    (setq unread-command-events (nconc
+                                 (listify-key-sequence (this-command-keys))
+                                 unread-command-events))
+    (clear-this-command-keys t)))
 
 (defun company-show-doc-buffer ()
   "Temporarily show the documentation buffer for the selection."



reply via email to

[Prev in Thread] Current Thread [Next in Thread]