[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."
- [elpa] master 0295c8f 20/78: And more, (continued)
- [elpa] master 0295c8f 20/78: And more, Dmitry Gutov, 2018/02/18
- [elpa] master b07eaf9 17/78: Move the entry up, Dmitry Gutov, 2018/02/18
- [elpa] master 74d85d1 09/78: company-tng: Advice company-select-next to allow unselected state, Dmitry Gutov, 2018/02/18
- [elpa] master 4240367 08/78: company-tng: Implement visualisation and completion, Dmitry Gutov, 2018/02/18
- [elpa] master 1a9f0b8 14/78: company-tng: Kill local overlay variable after completion is done, Dmitry Gutov, 2018/02/18
- [elpa] master a528433 21/78: Fix the link text, Dmitry Gutov, 2018/02/18
- [elpa] master 66a9e65 15/78: company-tng: Use 'after-string when the prefix is empty, Dmitry Gutov, 2018/02/18
- [elpa] master 44b19b6 19/78: Tweak some more, Dmitry Gutov, 2018/02/18
- [elpa] master afa592d 18/78: Rewrite the tng documentation a bit, Dmitry Gutov, 2018/02/18
- [elpa] master eaddef4 22/78: company-tng: Remove redundant call to overlay-put, Dmitry Gutov, 2018/02/18
- [elpa] master 4c1fd0e 16/78: Merge pull request #706 from nikital/company-tng,
Dmitry Gutov <=
- [elpa] master 096991d 26/78: Merge pull request #716 from jeffersoncarpenter/master, Dmitry Gutov, 2018/02/18
- [elpa] master 3d9272d 23/78: company-tng: Fully replace default frontend list, Dmitry Gutov, 2018/02/18
- [elpa] master 99fa5a0 30/78: Refine col-row calculation in the presence of line numbering, Dmitry Gutov, 2018/02/18
- [elpa] master 8dea612 39/78: Merge pull request #740 from Havner/master, Dmitry Gutov, 2018/02/18
- [elpa] master a4e14ed 40/78: Add some Commentary, Dmitry Gutov, 2018/02/18
- [elpa] master a574418 46/78: Fix last change, Dmitry Gutov, 2018/02/18
- [elpa] master 4a34571 25/78: Place cursor at correct location for completions, Dmitry Gutov, 2018/02/18
- [elpa] master 78cbc69 32/78: Test in Emacs 25, too, Dmitry Gutov, 2018/02/18
- [elpa] master cf89f7c 27/78: Abort dabbrev search on input pending, Dmitry Gutov, 2018/02/18
- [elpa] master 1de463a 29/78: company--window-width: Account for display-line-numbers, Dmitry Gutov, 2018/02/18