summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--evil-surround.el35
-rw-r--r--test/evil-surround-test.el10
2 files changed, 40 insertions, 5 deletions
diff --git a/evil-surround.el b/evil-surround.el
index 91b6d1c..6eb3a11 100644
--- a/evil-surround.el
+++ b/evil-surround.el
@@ -88,13 +88,23 @@ Each item is of the form (OPERATOR . OPERATION)."
(defvar evil-surround-read-tag-map
(let ((map (copy-keymap minibuffer-local-map)))
- (define-key map ">" 'exit-minibuffer)
+ (define-key map ">" (lambda ()
+ (interactive)
+ (call-interactively 'self-insert-command)
+ (run-at-time nil nil
+ (lambda ()
+ (when (active-minibuffer-window)
+ (select-window (active-minibuffer-window))
+ (exit-minibuffer))))))
map)
"Keymap used by `evil-surround-read-tag'.")
(defvar evil-surround-record-repeat nil
"Flag to indicate we're manually recording repeat info.")
+(defvar evil-surround-last-deleted-left ""
+ "The previously deleted LEFT region.")
+
(defun evil-surround-read-from-minibuffer (&rest args)
(when evil-surround-record-repeat
(evil-repeat-keystrokes 'post))
@@ -124,13 +134,27 @@ Each item is of the form (OPERATOR . OPERATION)."
(cons (format "%s(" (or fname ""))
")")))
+(defconst evil-surround-tag-name-re "\\([0-9a-z-]+\\)"
+ "Regexp matching an XML tag name.")
+
+(defun evil-surround-tag-p (string)
+ "Return t if `STRING' looks like a tag."
+ (string-match-p evil-surround-tag-name-re string))
+
(defun evil-surround-read-tag ()
"Read a XML tag from the minibuffer."
(let* ((input (evil-surround-read-from-minibuffer "<" "" evil-surround-read-tag-map))
- (match (string-match "\\([0-9a-z-]+\\)\\(.*?\\)[>]*$" input))
+ (match (string-match (concat evil-surround-tag-name-re "\\(.*?\\)\\([>]*\\)$") input))
(tag (match-string 1 input))
- (rest (match-string 2 input)))
- (cons (format "<%s%s>" (or tag "") (or rest ""))
+ (rest (match-string 2 input))
+ (keep-attributes (not (string-match-p ">" input)))
+ (original-tag (when (evil-surround-tag-p evil-surround-last-deleted-left)
+ (substring evil-surround-last-deleted-left
+ (string-match (concat "<" evil-surround-tag-name-re) evil-surround-last-deleted-left)
+ (match-end 0))))
+ (original-attributes (when (and keep-attributes original-tag)
+ (substring evil-surround-last-deleted-left (length original-tag)))))
+ (cons (format "<%s%s%s" (or tag "") (or rest "") (or original-attributes ">"))
(format "</%s>" (or tag "")))))
(defun evil-surround-valid-char-p (char)
@@ -217,7 +241,8 @@ between these overlays is what is deleted."
(interactive (evil-surround-input-char))
(cond
((and outer inner)
- (delete-region (overlay-start outer) (overlay-start inner))
+ (setq evil-surround-last-deleted-left
+ (delete-and-extract-region (overlay-start outer) (overlay-start inner)))
(delete-region (overlay-end inner) (overlay-end outer))
(goto-char (overlay-start outer)))
(t
diff --git a/test/evil-surround-test.el b/test/evil-surround-test.el
index df71b11..c70f181 100644
--- a/test/evil-surround-test.el
+++ b/test/evil-surround-test.el
@@ -93,6 +93,16 @@
"<a>tag1</a> tag2"
("W.")
"<a>tag1</a> <a>tag2</a>"))
+ (ert-info ("optionally keep xml attributes")
+ (evil-test-buffer
+ :visual-start nil
+ :visual-end nil
+ "<div class=\"foo\">Bar</div>"
+ (turn-on-evil-surround-mode)
+ ("cst<span")
+ "<span class=\"foo\">Bar</span>"
+ ("cst<p>")
+ "<p>Bar</p>"))
(ert-info ("repeat surrounding")
(evil-test-buffer
"[o]ne two three"