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

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

[elpa] master b753952 01/12: Add function and binding to clear template


From: Dmitry Gutov
Subject: [elpa] master b753952 01/12: Add function and binding to clear template field and move to next (#660)
Date: Sat, 15 Jul 2017 13:36:43 -0400 (EDT)

branch: master
commit b753952d5a0ee288b6c49b2d8dfa9a223ff59715
Author: Peter Vasil <address@hidden>
Commit: Dmitry Gutov <address@hidden>

    Add function and binding to clear template field and move to next (#660)
    
    Add company-template-field-map and a binding that clears the field
    
    Resolves #657
---
 NEWS.md                |  5 ++++
 company-template.el    | 67 +++++++++++++++++++++++++++++++++++++++++---------
 test/template-tests.el | 51 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 112 insertions(+), 11 deletions(-)

diff --git a/NEWS.md b/NEWS.md
index 7d8ae3e..08b0b33 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -1,5 +1,10 @@
 # History of user-visible changes
 
+## Next
+
+* `company-template` has a new shortcut (`C-d`) for deleting an unmodified
+  template field while cursor is on it.
+
 ## 2017-03-29 (0.9.3)
 
 * New variable `company-echo-truncate-lines`.
diff --git a/company-template.el b/company-template.el
index 053429d..f77f365 100644
--- a/company-template.el
+++ b/company-template.el
@@ -1,6 +1,6 @@
 ;;; company-template.el --- utility library for template expansion
 
-;; Copyright (C) 2009, 2010, 2014-2016 Free Software Foundation, Inc.
+;; Copyright (C) 2009, 2010, 2014-2017 Free Software Foundation, Inc.
 
 ;; Author: Nikolaj Schumacher
 
@@ -35,6 +35,11 @@
     (define-key keymap (kbd "TAB") 'company-template-forward-field)
     keymap))
 
+(defvar company-template-field-map
+  (let ((keymap (make-sparse-keymap)))
+    (define-key keymap (kbd "C-d") 'company-template-clear-field)
+    keymap))
+
 (defvar-local company-template--buffer-templates nil)
 
 ;; interactive 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -55,19 +60,52 @@
 
 (defun company-template-forward-field ()
   (interactive)
+  (let ((start (point))
+        (next-field-start (company-template-find-next-field)))
+    (push-mark)
+    (goto-char next-field-start)
+    (company-template-remove-field (company-template-field-at start))))
+
+(defun company-template-clear-field ()
+  "Clear the field at point."
+  (interactive)
+  (let ((ovl (company-template-field-at (point))))
+    (when ovl
+      (company-template-remove-field ovl t)
+      (let ((after-clear-fn
+             (overlay-get ovl 'company-template-after-clear)))
+        (when (functionp after-clear-fn)
+          (funcall after-clear-fn))))))
+
+(defun company-template--after-clear-c-like-field ()
+  "Function that can be called after deleting a field of a c-like template.
+For c-like templates it is set as `after-post-fn' property on fields in
+`company-template-add-field'.  If there is a next field, delete everything
+from point to it.  If there is no field after point, remove preceding comma
+if present."
+  (let* ((pos (point))
+         (next-field-start (company-template-find-next-field))
+         (last-field-p (not (company-template-field-at next-field-start))))
+    (cond ((and (not last-field-p)
+                (< pos next-field-start)
+                (string-match "^[ ]*,+[ ]*$" (buffer-substring-no-properties
+                                              pos next-field-start)))
+           (delete-region pos next-field-start))
+          ((and last-field-p
+                (looking-back ",+[ ]*" (line-beginning-position)))
+           (delete-region (match-beginning 0) pos)))))
+
+(defun company-template-find-next-field ()
   (let* ((start (point))
-         (templates (company-template-templates-at (point)))
+         (templates (company-template-templates-at start))
          (minimum (apply 'max (mapcar 'overlay-end templates)))
          (fields (cl-loop for templ in templates
                           append (overlay-get templ 
'company-template-fields))))
-    (dolist (pos (mapcar 'overlay-start fields))
+    (dolist (pos (mapcar 'overlay-start fields) minimum)
       (and pos
-           (> pos (point))
+           (> pos start)
            (< pos minimum)
-           (setq minimum pos)))
-    (push-mark)
-    (goto-char minimum)
-    (company-template-remove-field (company-template-field-at start))))
+           (setq minimum pos)))))
 
 (defun company-template-field-at (&optional point)
   (cl-loop for ovl in (overlays-at (or point (point)))
@@ -93,10 +131,12 @@
         (delq templ company-template--buffer-templates))
   (delete-overlay templ))
 
-(defun company-template-add-field (templ beg end &optional display)
+(defun company-template-add-field (templ beg end &optional display 
after-clear-fn)
   "Add new field to template TEMPL spanning from BEG to END.
 When DISPLAY is non-nil, set the respective property on the overlay.
-Leave point at the end of the field."
+Leave point at the end of the field.
+AFTER-CLEAR-FN is a function that can be used to apply custom behavior
+after deleting a field in `company-template-remove-field'."
   (cl-assert templ)
   (when (> end (overlay-end templ))
     (move-overlay templ (overlay-start templ) end))
@@ -109,6 +149,10 @@ Leave point at the end of the field."
       (overlay-put ov 'display display))
     (overlay-put ov 'company-template-parent templ)
     (overlay-put ov 'insert-in-front-hooks '(company-template-insert-hook))
+    (when after-clear-fn
+      (overlay-put ov 'company-template-after-clear after-clear-fn))
+    (overlay-put ov 'keymap company-template-field-map)
+    (overlay-put ov 'priority 101)
     (push ov siblings)
     (overlay-put templ 'company-template-fields siblings)))
 
@@ -179,7 +223,8 @@ Leave point at the end of the field."
   (let ((last-pos (point)))
     (while (re-search-forward "\\([^,]+\\),?" end 'move)
       (when (zerop (car (parse-partial-sexp last-pos (point))))
-        (company-template-add-field templ last-pos (match-end 1))
+        (company-template-add-field templ last-pos (match-end 1) nil
+                                    
#'company-template--after-clear-c-like-field)
         (skip-chars-forward " ")
         (setq last-pos (point))))))
 
diff --git a/test/template-tests.el b/test/template-tests.el
index da746bd..bcca8a8 100644
--- a/test/template-tests.el
+++ b/test/template-tests.el
@@ -117,3 +117,54 @@
       (company-template-objc-templatify text)
       (should (equal (buffer-string) text))
       (company-template-field-assert-text "(NSString)"))))
+
+(ert-deftest company-template-clear-field-c-like-first-arg ()
+  (with-temp-buffer
+    (let ((text "foo(int a, short b)"))
+      (insert text)
+      (company-template-c-like-templatify text)
+      (company-template-clear-field)
+      (should (equal "foo(short b)" (buffer-string))))))
+
+(ert-deftest company-template-clear-field-c-like-last-arg ()
+  (with-temp-buffer
+    (let ((text "foo(int a, short b)"))
+      (insert text)
+      (company-template-c-like-templatify text)
+      (insert "42")
+      (company-template-forward-field)
+      (company-template-clear-field)
+      (should (equal "foo(42)" (buffer-string))))))
+
+(ert-deftest company-template-clear-field-c-like-generic-1 ()
+  (with-temp-buffer
+    (let ((text "foo<TValue>(int a, short b)"))
+      (insert text)
+      (company-template-c-like-templatify text)
+      (company-template-clear-field)
+      (should (equal "foo<>(int a, short b)" (buffer-string))))))
+
+(ert-deftest company-template-clear-field-c-like-generic-2 ()
+  (with-temp-buffer
+    (let ((text "foo<TKey, TValue>(int a, short b)"))
+      (insert text)
+      (company-template-c-like-templatify text)
+      (company-template-clear-field)
+      (should (equal "foo<TValue>(int a, short b)" (buffer-string))))))
+
+(ert-deftest company-template-clear-field-objc-first-arg ()
+  (with-temp-buffer
+    (let ((text "createBookWithTitle:andAuthor:"))
+      (insert text)
+      (company-template-objc-templatify text)
+      (company-template-clear-field)
+      (should (equal "createBookWithTitle: andAuthor:arg1" (buffer-string))))))
+
+(ert-deftest company-template-insert-hook-c-like-field ()
+  (with-temp-buffer
+    (let ((text "foo(int a, short b)"))
+      (insert text)
+      (company-template-c-like-templatify text)
+      (let ((ovl (company-template-field-at (point))))
+        (company-template-insert-hook ovl nil)
+        (should (equal "foo(, short b)" (buffer-string)))))))



reply via email to

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