branch: elpa/evil-nerd-commenter
commit dac58399e8b1144d74d92d0a70a2d11187d1e797
Author: Chen Bin <[email protected]>
Commit: Chen Bin <[email protected]>

    select/yank text object of irregular lines
---
 README.org                      |   4 +-
 evil-nerd-commenter-operator.el | 160 +++++++++++++++++++++++++++-------------
 evil-nerd-commenter-sdk.el      |  10 ++-
 evil-nerd-commenter.el          |   7 +-
 pkg.sh                          |   2 +-
 5 files changed, 121 insertions(+), 62 deletions(-)

diff --git a/README.org b/README.org
index ae1a30fb08..e933a43092 100644
--- a/README.org
+++ b/README.org
@@ -1,4 +1,4 @@
-* evil-nerd-commenter (v3.0.3)
+* evil-nerd-commenter (v3.1.0)
 
 
[[http://melpa.org/#/evil-nerd-commenter][file:http://melpa.org/packages/evil-nerd-commenter-badge.svg]]
 
[[http://stable.melpa.org/#/evil-nerd-commenter][file:http://stable.melpa.org/packages/evil-nerd-commenter-badge.svg]]
 
@@ -175,8 +175,6 @@ Press =vac= to select outer object (comment with limiters).
 Press =vic= to select inner object (comment without limiter).
 
 You can assign other key instead of "c" to the text object by customizing 
=evilnc-comment-text-object=.
-
-Please note in order to select innner object precisely, either the first or 
last line is the longest line.
 ** evilnc-comment-operator
 =evilnc-comment-operator= acts much like the delete/change operator. Takes a 
motion or text object and comments it out, yanking its content in the process.
 
diff --git a/evil-nerd-commenter-operator.el b/evil-nerd-commenter-operator.el
index f9d9b0aba3..59ec4a9a5a 100644
--- a/evil-nerd-commenter-operator.el
+++ b/evil-nerd-commenter-operator.el
@@ -46,7 +46,36 @@
     perl-mode
     php-mode
     swift-mode
-    web-mode))
+    web-mode)
+  "Major modes using C comment syntax.")
+
+(defvar evilnc-temporary-goal-column 0
+  "Value passed to `temporary-goal-column' which specify the right edge
+of rectangle yank.")
+
+(defadvice evil-visual-highlight-block (around 
evil-visual-highlight-block-hack activate)
+  ad-do-it
+  (when (eq this-command 'evilnc-inner-comment)
+    (dolist (overlay evil-visual-block-overlays)
+      (let* ((b (overlay-start overlay))
+             (e (save-excursion
+                  (goto-char (overlay-end overlay))
+                  (line-end-position))))
+        (move-overlay overlay b e)))))
+
+(defadvice evil-apply-on-block (around evil-apply-on-block-around-hack 
activate)
+  (let* ((tmp-command last-command))
+    ;; force `evil-apply-on-block' use our temporary-goal-column
+    (when (> evilnc-temporary-goal-column 0)
+      (setq temporary-goal-column (max temporary-goal-column
+                                       evilnc-temporary-goal-column))
+      ;; Read `evil-apply-on-block'. Note `temporary-goal-column' is used
+      ;; if and only if `last-command' is `next-line' or `previous-line'
+      (setq last-command 'next-line))
+    ad-do-it
+    ;; restore last command
+    (setq last-command tmp-command)
+    (setq evilnc-temporary-goal-column 0)))
 
 (evil-define-operator evilnc-comment-operator (beg end type)
   "Comments text from BEG to END with TYPE."
@@ -73,7 +102,7 @@
     (let* ((newpos (evilnc--extend-to-whole-comment beg end) ))
       (evilnc--comment-or-uncomment-region (nth 0 newpos) (nth 1 newpos)))))
 
-  ;; place cursor on beginning of line
+  place cursor on beginning of line
   (if (and (called-interactively-p 'any)
            (eq type 'line))
     (evil-first-non-blank)))
@@ -98,15 +127,18 @@
       (comment-region beg end))))
 
 (defun evilnc-is-one-line-comment (b e)
-  "one line comment, just select the comment."
+  "One line comment."
   (save-excursion
     (goto-char b)
     (and (<= (line-beginning-position) b)
-         (<= e (line-end-position)))))
+         ;; e is the upper limit great than (line-end-position)
+         (<= e (1+ (line-end-position))))))
 
 (defun evilnc-get-comment-bounds ()
+  "Return bounds like (cons beg end)."
   (let* ((b (point))
          (e (point))
+         (col 0)
          rlt)
     ;; extend begin
     (while (evilnc-is-comment (- b 1))
@@ -154,12 +186,12 @@
     ;; avoid selecting comment limiter
     (cond
      ((and (memq major-mode evilnc-c-style-comment-modes)
-           (= end-char 47) ; "/" => 47
-           (= next-end-char 42)) ; "*" => 42
+           (= end-char ?/)
+           (= next-end-char ?*))
       ;; avoid selecting the ending comment limiter "*/"
       (setq e (- e 2))
       (while (and (> e b)
-                  (= (evilnc-get-char (- e 1)) 42))
+                  (= (evilnc-get-char (- e 1)) ?*))
         (setq e (- e 1))))
      (t
       ;; other languages we can safely use font face
@@ -168,65 +200,87 @@
         (setq e (- e 1)))))
     e))
 
+(defun evilnc-is-c-style-comment (pos)
+  "Is C style comment at POS?"
+  (and (memq major-mode evilnc-c-style-comment-modes)
+       (= (evilnc-get-char pos) ?/)
+       (= (memq (evilnc-get-char (1+ pos)) '(?/ ?*)))))
+
+(defun evilnc-comment-column-bounds (beg end &optional c-style)
+  "From BEG to END find column bounds of rectangle selection.
+Return (cons col-min col-max) or nil."
+  (let* ((col-min most-positive-fixnum)
+         (col-max 0))
+    (while (< beg end)
+      (when (and (not (evilnc-is-whitespace beg))
+                 (evilnc-is-pure-comment beg)
+                 (not (or (evilnc-is-comment-delimiter beg)
+                          (and c-style
+                               (memq (evilnc-get-char beg) '(?/ ?*))))))
+        (let* ((col (evil-column beg)))
+          (if (< col col-min)
+              (setq col-min col))
+          (if (> col col-max)
+              (setq col-max col))))
+      (setq beg (1+ beg)))
+    (if (< col-min col-max)
+        (cons col-min col-max))))
+
 (evil-define-text-object evilnc-inner-comment (&optional count begin end type)
   "An inner comment text object."
-  (let* ((bounds (evilnc-get-comment-bounds)))
+  (let* ((bounds (evilnc-get-comment-bounds))
+         b
+         e
+         c-style)
     (cond
      (bounds
-      (let* ((b (save-excursion
+      (setq b (car bounds))
+      (setq e (cdr bounds))
+      (cond
+       ((setq c-style (evilnc-is-c-style-comment b))
+        (while (and (< b e)
+                    (or (evilnc-is-whitespace b)
+                        (evilnc-is-line-end b)
+                        (memq (evilnc-get-char b) '(?/ ?*))))
+          (setq b (1+ b)))
+        (while (and (< b e)
+                    (or (evilnc-is-whitespace e)
+                        (evilnc-is-line-end e)
+                        (memq (evilnc-get-char e) '(?/ ?*))))
+          (setq e (1- e)))
+        (setq e (1+ e))
+        (setq b (save-excursion
+                  (goto-char b)
+                  (forward-word 1)
+                  (forward-word -1)
+                  (point))))
+       (t
+        (setq b (save-excursion
                   (goto-char (car bounds))
                   (forward-word 1)
                   (forward-word -1)
                   (point)))
-             (line-end-of-b (save-excursion
-                                    (goto-char b)
-                                    (line-end-position)))
-             (offset-b (save-excursion
-                         (goto-char b)
-                         (- b (line-beginning-position))))
-             (e (save-excursion
+        (setq e (save-excursion
                   (goto-char (cdr bounds))
                   (goto-char (evilnc-adjusted-comment-end b 
(line-end-position)))
-                  (point)))
-             line-beginning-of-e
-             offset-e)
+                  (point)))))
+      (cond
+       ((evilnc-is-one-line-comment b e)
         ;; keep move e to the end of comment
-        (when (evilnc-is-one-line-comment b e)
-          (while (and (< b e)
-                      (or (evilnc-is-comment-delimiter e)
-                          (and (evilnc-is-pure-comment e)
-                               (evilnc-is-whitespace e))))
-            (setq e (- e 1)))
-          (setq e (+ e 1)))
-        ;;     b                line-end-of-b
-        ;;     +---------------------+
-        ;;     |                     |
-        ;;     +---------------------|
-        ;; line-beginning-of-e       e
-        (setq line-beginning-of-e (save-excursion
-                                    (goto-char e)
-                                    (+ (line-beginning-position) offset-b)
-                                    (forward-word 1)
-                                    (forward-word -1)
-                                    (point)))
-        (setq offset-e (save-excursion
-                         (goto-char e)
-                         (- line-beginning-of-e (line-beginning-position))))
-        ;; switch start/end of block region if required
-        (let* (block-b block-e)
+        (evil-range b ;; (if c-style (1+ e) e)
+                    e))
+       (t
+        ;; multi-line comment
+        (let* ((col-b (evil-column b))
+               (col-bounds (evilnc-comment-column-bounds b e c-style)))
           (cond
-           ((> (- line-end-of-b b)
-                   (- e line-beginning-of-e))
-            (setq block-b (if (> offset-e offset-b) (- line-beginning-of-e
-                                                       (- offset-e offset-b))
-                            line-beginning-of-e))
-            (setq block-e line-end-of-b))
+           (col-bounds
+            (if (> col-b (car col-bounds))
+                (setq b (- b (- col-b (car col-bounds)))))
+            (setq evilnc-temporary-goal-column (cdr col-bounds)))
            (t
-            (setq block-b (if (> offset-b offset-e) (- b (- offset-b
-                                                            offset-e))
-                            b))
-            (setq block-e e)))
-          (evil-range block-b block-e 'block :expanded t))))
+            (setq evilnc-temporary-goal-column (evil-column e)))))
+        (evil-range b e 'block :expanded t))))
      (t
       (error "Not inside a comment.")))))
 
diff --git a/evil-nerd-commenter-sdk.el b/evil-nerd-commenter-sdk.el
index a079c07a16..abb1ae7f44 100644
--- a/evil-nerd-commenter-sdk.el
+++ b/evil-nerd-commenter-sdk.el
@@ -43,6 +43,7 @@
                  (eq (get-text-property pos 'part-token) 'comment)))))
 
 (defun evilnc-is-pure-comment (pos)
+  "Check character at POS is pure comment."
   (let* ((fontfaces (if (> pos 0) (get-text-property pos 'face))))
     (if (not (listp fontfaces))
         (setf fontfaces (list fontfaces)))
@@ -53,10 +54,17 @@
                                font-lock-comment-delimiter-face)))))
 
 (defun evilnc-is-whitespace (pos)
+  "Character at POS is white space."
   (member (evilnc-get-char pos) '(32 9)))
 
+(defun evilnc-is-line-end (pos)
+  "Character at POS is line end."
+  (member (evilnc-get-char pos) '(10 11)))
+
 (defun evilnc-is-comment (pos)
-  "Check whether the code at POS is comment by comparing font face."
+  "Check whether the code at POS is comment by comparing font face.
+Please note the white spaces out of comment is treated as comment,
+or else we can't select multiple lines comment."
   (let* ((fontfaces (if (> pos 0) (get-text-property pos 'face))))
     (if (not (listp fontfaces))
         (setf fontfaces (list fontfaces)))
diff --git a/evil-nerd-commenter.el b/evil-nerd-commenter.el
index 9150520100..369d363785 100644
--- a/evil-nerd-commenter.el
+++ b/evil-nerd-commenter.el
@@ -4,7 +4,7 @@
 
 ;; Author: Chen Bin <[email protected]>
 ;; URL: http://github.com/redguardtoo/evil-nerd-commenter
-;; Version: 3.0.3
+;; Version: 3.1.0
 ;; Keywords: commenter vim line evil
 ;;
 ;; This file is not part of GNU Emacs.
@@ -89,8 +89,7 @@
 ;; We defined comment text object "c" which can have multi-lines.
 ;; Press "vac" to select outer object (comment with limiters).
 ;; Press "vic" to select inner object (comment without limiter).
-;; Please note in order to select innner object precisel,x
-;; either the first or last line is the longest line.
+;;
 ;; You can assign other key instead of "c" to the text object by
 ;; customizing `evilnc-comment-text-object'.
 
@@ -686,7 +685,7 @@ Then we operate the expanded region.  NUM is ignored."
 (defun evilnc-version ()
   "The version number."
   (interactive)
-  (message "3.0.3"))
+  (message "3.1.0"))
 
 (defvar evil-normal-state-map)
 (defvar evil-visual-state-map)
diff --git a/pkg.sh b/pkg.sh
index 02aea7ed3d..20dfdf40b8 100755
--- a/pkg.sh
+++ b/pkg.sh
@@ -1,6 +1,6 @@
 #!/bin/bash
 name=evil-nerd-commenter
-version=3.0.3
+version=3.1.0
 pkg=$name-$version
 mkdir $pkg
 cp *.el $pkg

Reply via email to