aboutsummaryrefslogtreecommitdiff
path: root/.config/emacs/lisp/evil-nerd-commenter
diff options
context:
space:
mode:
authorJack Jamison <jackqjamison@gmail.com>2026-07-30 20:09:00 -0400
committerJack Jamison <jackqjamison@gmail.com>2026-07-30 20:18:37 -0400
commit8c4e09dff83847ac7f07bf1da7751e9328006c4d (patch)
treea0e245567ce225f8bcb63b66e4d2373b5d033e4a /.config/emacs/lisp/evil-nerd-commenter
parent1e33b30749bb1043ffc6ceb5a2fb0977446788b3 (diff)
actual final changes and get rid of junk in lisp dir
actually works fine
Diffstat (limited to '.config/emacs/lisp/evil-nerd-commenter')
-rw-r--r--.config/emacs/lisp/evil-nerd-commenter/evil-nerd-commenter-operator.el402
-rw-r--r--.config/emacs/lisp/evil-nerd-commenter/evil-nerd-commenter-sdk.el127
-rw-r--r--.config/emacs/lisp/evil-nerd-commenter/evil-nerd-commenter.el1013
3 files changed, 0 insertions, 1542 deletions
diff --git a/.config/emacs/lisp/evil-nerd-commenter/evil-nerd-commenter-operator.el b/.config/emacs/lisp/evil-nerd-commenter/evil-nerd-commenter-operator.el
deleted file mode 100644
index 15739a1..0000000
--- a/.config/emacs/lisp/evil-nerd-commenter/evil-nerd-commenter-operator.el
+++ /dev/null
@@ -1,402 +0,0 @@
-;;; evil-nerd-commenter-operator.el --- evil operator for this program -*- lexical-binding: t -*-
-
-;; Author: Chen Bin <chenbin.sh@gmail.com>
-
-;; This file is not part of GNU Emacs.
-
-;;; License:
-
-;; This program 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, or (at your option)
-;; any later version.
-
-;; This program 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 this program; if not, write to the Free Software
-;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-;;; Commentary:
-
-;; Provides operators for evil-mode.
-
-;;; Code:
-
-(require 'evil)
-(require 'evil-nerd-commenter-sdk)
-
-(defvar evilnc-c-style-comment-modes
- '(awk-mode
- c++-mode
- c-mode
- css-mode
- dart-mode
- ess-mode
- go-mode
- java-mode
- javascript-mode
- js-mode
- js2-mode
- perl-mode
- php-mode
- swift-mode
- web-mode)
- "Major modes using C comment syntax.")
-
-(defvar evilnc-current-text-object nil
- "Internal variable to detect current object working on.")
-
-(defvar evilnc-whole-line-text-objects
- '(evil-forward-paragraph
- evil-backward-paragraph)
- "Comment operator operates on wholes when dealing with these text objects.")
-
-(defvar evilnc-temporary-goal-column 0
- "Value of`temporary-goal-column' specifying right edge of rectangle yank.")
-
-(defadvice evil-visual-highlight-block (around evil-visual-highlight-block-hack activate)
- "Show overlay over inner comment text object."
- ad-do-it
- (when (eq this-command 'evilnc-inner-commenter)
- (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)
- "Yank correct region of inner comment text object."
- (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)))
-
-(defun evilnc-expand-to-whole-comment-or-line (start end)
- "Expand the comment region defined by START and END.
-Make sure all comment is included.
-Or expand the region to contain whole lines."
-
- (cond
- ((evilnc-pure-comment-p start)
- (save-excursion
- (let* ((newstart start)
- (newend end))
-
- ;; expand the beginning
- (goto-char newstart)
- (while (and (>= (1- newstart) (line-beginning-position)) (evilnc-pure-comment-p (1- newstart)))
- (setq newstart (1- newstart)))
-
- ;; expand the end
- (goto-char newend)
- (while (and (<= newend (line-end-position)) (evilnc-pure-comment-p newend))
- (setq newend (1+ newend)))
-
- (cons newstart newend))))
-
- ;; try to expand region to contain whole line if,
- ;; - currently more than one line text in the region,
- ;; - a specific text object is touched just before the operator
- ((and (not (evilnc-sdk-inside-one-line-p start end))
- evilnc-current-text-object
- (member (car evilnc-current-text-object) evilnc-whole-line-text-objects)
- ;; 0.5 second
- (< (- (float-time (current-time)) (cdr evilnc-current-text-object)) 0.5))
- (evilnc-sdk-expand-to-contain-whole-lines start end))
- (t
- (cons start end))))
-
-;; {{ know text object type to operate on
-(defun evilnc-set-current-text-object (text-object)
- "Set current TEXT-OBJECT."
- (setq evilnc-current-text-object
- (cons text-object (float-time (current-time)))))
-
-(defadvice evil-select-an-object (before evilnc-evil-select-an-object-hack activate)
- "Figure out text object type."
- (let* ((thing (car (ad-get-args 0))))
- ;; record the thing and timestamp `evil-select-an-object' is called
- (evilnc-set-current-text-object thing)))
-
-(defadvice evil-backward-paragraph (before evilnc-evil-backward-paragraph-hack activate)
- "Record current text object."
- (evilnc-set-current-text-object 'evil-backward-paragraph))
-
-(defadvice evil-forward-paragraph (before evilnc-evil-forward-paragraph-hack activate)
- "Record current text object."
- (evilnc-set-current-text-object 'evil-forward-paragraph))
-;; }}
-
-(evil-define-operator evilnc-comment-operator (start end type)
- "Comments text from START to END with TYPE."
- (interactive "<R>")
- (cond
- ((eq type 'block)
- (let* ((newpos (evilnc-expand-to-whole-comment-or-line start end) ))
- (evil-apply-on-block #'evilnc-comment-or-uncomment-region
- (car newpos)
- (cdr newpos)
- nil)))
-
- ((and (eq type 'line)
- (= end (point-max))
- (or (= start end)
- (/= (char-before end) ?\n))
- (/= start (point-min))
- (= (char-before start) ?\n))
- (evilnc-comment-or-uncomment-region (1- start) end))
-
- ((eq type 'line)
- ;; comment whole line, for now
- (evilnc-comment-or-uncomment-region start
- (save-excursion
- (goto-char (1- end))
- (line-end-position))))
-
- (t
- (when (and start end)
- (let* ((newpos (evilnc-expand-to-whole-comment-or-line start end)))
- (evilnc-comment-or-uncomment-region (car newpos) (cdr newpos))))))
-
- ;; place cursor on beginning of line
- (if (and (called-interactively-p 'any) (eq type 'line))
- (evil-first-non-blank)))
-
-(defun evilnc-comment-or-uncomment-region-then-action (start end commenter &optional action)
- "Comment/uncomment between START and END using COMMENTER, then take ACTION."
- (evil-with-single-undo
- ;; yank original text
- (evil-yank-lines start end nil 'lines)
-
- (when (evil-visual-state-p)
- ;; `evil-paste-before' does not work in visual state.
- (evil-normal-state))
-
- (cond
- (evilnc-original-above-comment-when-copy-and-comment
- (let* ((p (point)))
- (funcall commenter start end)
- (goto-char start)
- (when action (funcall action))
- (goto-char p)))
-
- (t
- (goto-char end)
- (when action (funcall action))
- ;; actual comment operation should happen at last
- ;; or else "(start end)" is screwed up
- (funcall commenter start end)))))
-
-(evil-define-operator evilnc-yank-and-comment-operator (start end)
- "(Un)comment and yank the text from START to END."
- :move-point (not evilnc-original-above-comment-when-copy-and-comment)
- (interactive "<r>")
- (evilnc-comment-or-uncomment-region-then-action start
- end
- evilnc-comment-or-uncomment-region-function))
-
-(evil-define-operator evilnc-copy-and-comment-operator (start end)
- "Inserts a commented copy of the text from START to END."
- :move-point (not evilnc-original-above-comment-when-copy-and-comment)
- (interactive "<r>")
- (evilnc-comment-or-uncomment-region-then-action start
- end
- 'comment-region
- (lambda () (evil-paste-before 1))))
-
-(defun evilnc-one-line-comment-p (start end)
- "Test if text between START and END is one line comment."
- (save-excursion
- (goto-char start)
- (and (<= (line-beginning-position) start)
- ;; end is the upper limit great than (line-end-position)
- (<= end (1+ (line-end-position))))))
-
-(defun evilnc-get-comment-bounds ()
- "Return bounds like (cons start end)."
- (let* ((b (point))
- (e (point))
- (col 0)
- rlt)
- ;; decrease start position
- (while (evilnc-comment-p (- b 1))
- (setq b (- b 1)))
-
- ;; increase end
- (while (evilnc-comment-p (+ e 1))
- (setq e (+ e 1)))
-
- ;; we could select extra spaces at the end of comment
- ;; so we need go back
- (let* ((str (save-excursion
- (goto-char e)
- (evilnc-sdk-cur-line e)))
- (empty-line-p (string-match "^[ \t]*$" str)))
- (when empty-line-p
- ;; empty line plus line feed
- (setq e (- e (length str) 1))))
- (cond
- ((>= b e)
- (setq rlt nil))
- ((evilnc-one-line-comment-p b e)
- ;; contract from start position
- (while (not (evilnc-pure-comment-p b))
- (setq b (+ b 1)))
-
- ;; contract from end position
- (while (not (evilnc-pure-comment-p e))
- (setq e (- e 1)))
-
- (if (< b e) (setq rlt (cons b e))))
- (t
- ;; multi-line comment
- (setq rlt (cons b e))))
- rlt))
-
-(defun evilnc-adjusted-comment-end (b e)
- "Adjust comment end of region between B and E."
- (let* ((next-end-char (evilnc-get-char (- e 2)))
- (end-char (evilnc-get-char (- e 1))))
- ;; avoid selecting CR/LF at the end of comment
- (while (and (< b e)
- (memq (evilnc-get-char (- e 1)) '(10 13)))
- (setq e (- e 1)))
-
- ;; avoid selecting comment limiter
- (cond
- ((and (memq major-mode evilnc-c-style-comment-modes)
- (= end-char ?/)
- (= next-end-char ?*))
- ;; avoid selecting the ending comment limiter "*/"
- (setq e (- e 2))
- (while (and (> e b)
- (= (evilnc-get-char (- e 1)) ?*))
- (setq e (- e 1))))
- (t
- ;; other languages we can safely use font face
- (while (and (> e b)
- (evilnc-comment-delimiter-p (- e 1)))
- (setq e (- e 1)))))
- e))
-
-(defun evilnc-c-style-comment-p (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 (start end &optional c-style)
- "From START to END find column bounds of rectangle selection.
-Return (cons col-min col-max) or nil. If C-STYLE is t,
-we are processing C like language."
- (let* ((col-min most-positive-fixnum)
- (col-max 0))
- (while (< start end)
- (when (and (not (evilnc-whitespace-p start))
- (evilnc-pure-comment-p start)
- (not (or (evilnc-comment-delimiter-p start)
- (and c-style
- (memq (evilnc-get-char start) '(?/ ?*))))))
- (let* ((col (evil-column start)))
- (if (< col col-min)
- (setq col-min col))
- (if (> col col-max)
- (setq col-max col))))
- (setq start (1+ start)))
- (if (< col-min col-max)
- (cons col-min col-max))))
-
-(evil-define-text-object evilnc-inner-commenter (&optional count start end type)
- "An inner comment text object."
- (let* ((bounds (evilnc-get-comment-bounds))
- b
- e
- c-style)
- (cond
- (bounds
- (setq b (car bounds))
- (setq e (cdr bounds))
- (cond
- ((setq c-style (evilnc-c-style-comment-p b))
- (while (and (< b e)
- (or (evilnc-whitespace-p b)
- (evilnc-line-end-p b)
- (memq (evilnc-get-char b) '(?/ ?*))))
- (setq b (1+ b)))
- (while (and (< b e)
- (or (evilnc-whitespace-p e)
- (evilnc-line-end-p 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)))
- (setq e (save-excursion
- (goto-char (cdr bounds))
- (goto-char (evilnc-adjusted-comment-end b (line-end-position)))
- (point)))))
- (cond
- ((evilnc-one-line-comment-p b e)
- ;; keep move e to the end of comment
- (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
- (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 evilnc-temporary-goal-column (evil-column e)))))
- (evil-range b e 'block :expanded t))))
- (t
- (error "Not inside a comment")))))
-
-(evil-define-text-object evilnc-outer-commenter (&optional count start end type)
- "An outer comment text object."
- (let* ((bounds (evilnc-get-comment-bounds)))
- (cond
- (bounds
- (evil-range (car bounds) (cdr bounds) 'exclusive :expanded t))
- (t
- (error "Not inside a comment")))))
-
-(evil-define-text-object evilnc-inner-comment (&optional count start end type)
- "An inner comment text object."
- (evilnc-inner-commenter count start end type))
-
-(evil-define-text-object evilnc-outer-comment (&optional count start end type)
- "An outer comment text object."
- (evilnc-outer-commenter count start end type))
-
-(provide 'evil-nerd-commenter-operator)
-;;; evil-nerd-commenter-operator.el ends here
-
-;; Local Variables:
-;; no-byte-compile: t
-;; End:
diff --git a/.config/emacs/lisp/evil-nerd-commenter/evil-nerd-commenter-sdk.el b/.config/emacs/lisp/evil-nerd-commenter/evil-nerd-commenter-sdk.el
deleted file mode 100644
index 60d31dc..0000000
--- a/.config/emacs/lisp/evil-nerd-commenter/evil-nerd-commenter-sdk.el
+++ /dev/null
@@ -1,127 +0,0 @@
-;;; evil-nerd-commenter-sdk.el --- SDK used by other files -*- lexical-binding: t -*-
-
-;; Author: Chen Bin
-
-;;; License:
-
-;; This file is not part of GNU Emacs.
-
-;; This program 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, or (at your option)
-;; any later version.
-
-;; This program 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 this program; if not, write to the Free Software
-;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-;;; Commentary:
-;; SDK used internally
-
-;;; Code:
-
-(require 'evil nil t)
-(defvar evil-state)
-
-(defun evilnc--check-fonts (fonts-under-cursor fonts-list)
- "Check whether FONTS-UNDER-CURSOR among FONTS-LIST."
- (delq nil
- (mapcar #'(lambda (f)
- ;; learn this trick from flyspell
- (member f fonts-list))
- fonts-under-cursor)))
-
-(defun evilnc-web-mode-comment-p (&optional pos)
- "Check whether the code at POS is comment.
-`web-mode' removes its API, so create our own."
- (unless pos (setq pos (point)))
- (not (null (or (eq (get-text-property pos 'tag-type) 'comment)
- (eq (get-text-property pos 'block-token) 'comment)
- (eq (get-text-property pos 'part-token) 'comment)))))
-
-(defun evilnc-fonts-at-point (pos)
- "Get font faces at POS."
- (let* ((fontfaces (if (> pos 0) (get-text-property pos 'face))))
- (if (listp fontfaces) fontfaces (list fontfaces))))
-
-(defun evilnc-pure-comment-p (pos)
- "Check character at POS is pure comment."
- (or (and (eq major-mode 'web-mode)
- (evilnc-web-mode-comment-p pos))
- (evilnc--check-fonts (evilnc-fonts-at-point pos)
- '(font-lock-comment-face
- tree-sitter-hl-face:comment
- font-lock-comment-delimiter-face))))
-
-(defmacro evilnc-get-char (position)
- "Get character at POSITION."
- `(char-after ,position))
-
-(defmacro evilnc-whitespace-p (position)
- "Character at POSITION is white space."
- `(member (evilnc-get-char ,position) '(32 9)))
-
-(defmacro evilnc-line-end-p (position)
- "Character at POSITION is line end."
- `(member (evilnc-get-char ,position) '(10 11)))
-
-(defun evilnc-comment-p (pos)
- "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."
- (cond
- ((or (< pos (point-min)) (> pos (point-max)))
- nil)
- ((not (evilnc-fonts-at-point pos))
- ;; character under cursor is SPACE or TAB
- ;; and out of comment
- (evilnc-whitespace-p pos))
- (t
- (evilnc-pure-comment-p pos))))
-
-(defun evilnc-comment-delimiter-p (position)
- "Is character at POSITION a comment delimiter?"
- (let* ((fontfaces (evilnc-fonts-at-point position)))
- (and fontfaces
- (evilnc--check-fonts fontfaces
- '(font-lock-comment-delimiter-face)))))
-
-(defun evilnc-sdk-inside-one-line-p (start end)
- "Test START and END is inside one line."
- (and (<= (line-beginning-position) start)
- (<= end (line-end-position))))
-
-(defun evilnc-sdk-cur-line (&optional end)
- "String from line beginning to END or line end."
- (buffer-substring-no-properties (line-beginning-position)
- (or end (line-end-position))))
-
-(defun evilnc-sdk-expand-to-contain-whole-lines (start end)
- "Expand region between START and END so the region contain whole lines.
-Return new range like '(region_begin . region_end)."
- (save-excursion
- ;; Another work around for evil-visual-line bug:
- ;; In `evil-mode', if we use hotkey V or `evil-visual-line' to select line,
- ;; the (line-beginning-position) of the line which is after the last selected
- ;; line is always (region-end)! Don't know why.
- (when (and (> end start)
- (save-excursion
- (goto-char end)
- (= end (line-beginning-position)))
- (boundp 'evil-state)
- (eq evil-state 'visual))
- (setq end (1- end)))
-
- (goto-char start)
- (setq start (line-beginning-position))
- (goto-char end)
- (setq end (line-end-position)))
- (cons start end))
-
-(provide 'evil-nerd-commenter-sdk)
-;;; evil-nerd-commenter-sdk.el ends here
diff --git a/.config/emacs/lisp/evil-nerd-commenter/evil-nerd-commenter.el b/.config/emacs/lisp/evil-nerd-commenter/evil-nerd-commenter.el
deleted file mode 100644
index 21498c4..0000000
--- a/.config/emacs/lisp/evil-nerd-commenter/evil-nerd-commenter.el
+++ /dev/null
@@ -1,1013 +0,0 @@
-;;; evil-nerd-commenter.el --- Comment/uncomment lines efficiently. Like Nerd Commenter in Vim -*- lexical-binding: t -*-
-
-;; Author: Chen Bin <chenbin.sh@gmail.com>
-
-;; URL: http://github.com/redguardtoo/evil-nerd-commenter
-;; Version: 3.6.1
-;; Package-Requires: ((emacs "26.1"))
-;; Keywords: convenience evil
-;;
-;; This file is not part of GNU Emacs.
-
-;;; Credits:
-
-;; - Lally Oppenheimer added the support for text-object in Evil
-;; - Tom Willemse provided the fix to make Emacs 24.4 work
-
-;;; License:
-
-;; This program 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.
-;;
-;; This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;;
-;; This program emulates nerd-commenter.vim by Marty Grenfell.
-;;
-;; It helps you comment/uncomment multiple lines without selecting them.
-;;
-;; `M-x evilnc-default-hotkeys` assigns hotkey `M-;` to
-;; `evilnc-comment-or-uncomment-lines'
-;;
-;; `M-x evilnc-comment-or-uncomment-lines` comment or uncomment lines.
-;;
-;; `M-x evilnc-quick-comment-or-uncomment-to-the-line` will comment/uncomment
-;; from current line to specified line.
-;; The last digit(s) of line number is parameter of the command.
-;;
-;; For example, `C-u 9 evilnc-quick-comment-or-uncomment-to-the-line` comments
-;; code from current line to line 99 if you current line is 91.
-;;
-;; Though this program could be used *independently*, it's recommended to
-;; us it with Evil.
-;;
-;; Evil makes you take advantage of power of Vi to comment lines.
-;; For example, you can press key `99,ci` to comment out 99 lines.
-;;
-;; Setup:
-;;
-;; If comma is your leader key, as most Vim users do, setup is one liner,
-;; (evilnc-default-hotkeys)
-;;
-;; Or else you can set up key bindings of below commands by yourself.
-;; `evilnc-comment-or-uncomment-lines'
-;; `evilnc-quick-comment-or-uncomment-to-the-line'
-;; `evilnc-comment-and-kill-ring-save'
-;; `evilnc-copy-and-comment-lines'
-;; `evilnc-comment-or-uncomment-paragraphs'
-;; `evilnc-comment-box'
-;; `evilnc-toggle-invert-comment-line-by-line'
-;; `evilnc-copy-and-comment-operator'
-;; `evilnc-comment-operator'
-;; `evilnc-comment-or-uncomment-html-tag'
-;; `evilnc-comment-or-uncomment-html-paragraphs'
-;;
-;; Set up `evilnc-original-above-comment-when-copy-and-comment'
-;; to decide which style to use in `evilnc-copy-and-comment-lines'
-;; and `evilnc-copy-and-comment-operator',
-;; - Place the commented out text above original text
-;; - Or place the original text above commented out text
-;;
-;; `evilnc-yank-and-comment-operator' (un)comment&yank text in one shot.
-;;
-;; Comment text object "c" is defined. It can have multi-lines.
-;; 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'. Either,
-;; (setq evilnc-comment-text-object "c")
-;; (evilnc-default-hotkeys)
-;;
-;; Or,
-;; (setq evilnc-comment-text-object "a")
-;; (define-key evil-inner-text-objects-map evilnc-comment-text-object 'evilnc-inner-commenter)
-;; (define-key evil-outer-text-objects-map evilnc-comment-text-object 'evilnc-outer-commenter)
-;;
-;; You can list of comments in current buffer through using imenu.
-;; by setup `imenu-create-index-function' to `evilnc-imenu-create-index-function',
-;;
-;; (defun counsel-imenu-comments ()
-;; (interactive)
-;; (let* ((imenu-create-index-function 'evilnc-imenu-create-index-function))
-;; (unless (featurep 'counsel) (require 'counsel))
-;; (counsel-imenu)))
-;;
-;; For certain major modes, you need manual setup to override its original
-;; keybindings,
-;;
-;; (defun matlab-mode-hook-config ()
-;; (local-set-key (kbd "M-;") 'evilnc-comment-or-uncomment-lines))
-;; (add-hook 'matlab-mode-hook 'matlab-mode-hook-config)
-;;
-;; Most commands call `evilnc-comment-or-uncomment-region-function'.
-;; You can modify this variable to customize the comment style,
-;;
-;; (with-eval-after-load 'evil-nerd-commenter
-;; (defun my-comment-or-uncomment-region (start end)
-;; (let* ((comment-start "aaa")
-;; (comment-end "bbb"))
-;; (evilnc-comment-or-uncomment-region-internal start end)))
-;; (setq evilnc-comment-or-uncomment-region-function
-;; 'my-comment-or-uncomment-region))
-;;
-;; See "Options Controlling Comments" in Emacs manual for comment options.
-;;
-;; See https://github.com/redguardtoo/evil-nerd-commenter for detail.
-;;
-;;; Code:
-
-(require 'subr-x) ; required by `string-trim'
-(require 'sgml-mode)
-(require 'newcomment)
-(require 'evil-nerd-commenter-sdk)
-
-(autoload 'count-lines "simple")
-
-(defvar evilnc-original-above-comment-when-copy-and-comment nil
- "Keep the original text above the commented copy, when using either:
-`evilnc-copy-and-comment-lines' or `evilnc-copy-and-comment-operator'.")
-
-(defvar evilnc-invert-comment-line-by-line nil
- "If t then invert region comment status line by line.
-Please note it has NOT effect on evil text object!")
-
-(defvar evilnc-comment-or-uncomment-region-function
- 'evilnc-comment-or-uncomment-region-internal
- "Comment or uncomment region.")
-
-(defvar evilnc-cpp-like-comment-syntax-modes
- '(java-mode
- javascript-mode
- js-mode
- js2-mode
- js3-mode
- rjsx-mode
- js2-jsx-mode
- rust-mode
- c++-mode
- c-mode
- objc-mode)
- "Major modes which has C++ like comment syntax.")
-
-(defvar evilnc-comment-text-object "c"
- "The comment object.
-`vic` to select inner object.
-`vac` to select outer object.")
-
-(defvar evilnc-use-comment-object-setup t
- "Use evil text object setup when calling `evilnc-default-hotkeys'.")
-
-(defvar evilnc-min-comment-length-for-imenu 8
- "Minimum length of comment to display in imenu.")
-
-(defvar evilnc-html-comment-delimiters
- '((evilnc-html-jsx-p "{/* " " */}")
- ("js-mode" "{/* " " */}")
- (("web-mode" "html-mode") "<!-- " " -->"))
- "List of html tag comment rules.
-The 1st item of each rule is the major mode(s) to match current `major-mode'.
-Current `major-mode' could equal or derive from the listed major mode(s).
-The 2nd and 3rd item is the comment start and comment end.")
-
-(defun evilnc-html-jsx-p ()
- "Test if current file is jsx."
- (and buffer-file-name
- (string-match-p "\.[tj]sx?$" buffer-file-name)))
-
-(defun evilnc-html-match-comment-delimiters-p (target-mode)
- "Use `major-mode' to match TARGET-MODE which could be:
-One major mode.
-List of major modes.
-A function to return t or nil."
- (let* (rlt)
- (cond
- ((functionp target-mode)
- (setq rlt (funcall target-mode)))
- ((stringp target-mode)
- ;; convert name of `major-mode' to symbol
- (when (or (eq major-mode (intern target-mode))
- (derived-mode-p (intern target-mode)))
- (setq rlt t)))
- ((listp target-mode)
- (while (and (not rlt) target-mode)
- (unless (setq rlt (evilnc-html-match-comment-delimiters-p (nth 0 target-mode)))
- ;; continue looping
- (setq target-mode (cdr target-mode))))))
- rlt))
-
-(defun evilnc-html-find-comment-delimiter ()
- "Found comment delimiter from `evilnc-html-find-comment-delimiter'."
- (let* (found
- (delimiters evilnc-html-comment-delimiters)
- rule)
- (while (and (not found) delimiters)
- (setq rule (car delimiters))
- (cond
- ((evilnc-html-match-comment-delimiters-p (nth 0 rule))
- (setq found rule))
- (t
- ;; keep looping
- (setq delimiters (cdr delimiters)))))
- found))
-
-(defun evilnc-html-comment-start ()
- "Return start of html comment."
- (let* ((s (evilnc-html-find-comment-delimiter)))
- (if s (nth 1 s) "<!-- ")))
-
-(defun evilnc-html-comment-end ()
- "Return end of html comment."
- (let* ((s (evilnc-html-find-comment-delimiter)))
- (if s (nth 2 s) " -->")))
-
-(defun evilnc--goto-line (line-num)
- "Shamelessly copied from `goto-line'. Goto line with LINE-NUM."
- (save-restriction
- (widen)
- (goto-char (point-min))
- (if (eq selective-display t)
- (re-search-forward "[\n\C-m]" nil 'end (1- line-num))
- (forward-line (1- line-num)))))
-
-(defun evilnc--fix-buggy-major-modes ()
- "Fix major modes whose comment regex is buggy.
-See http://lists.gnu.org/archive/html/bug-gnu-emacs/2013-03/msg00891.html."
- (cond
- ((eq major-mode 'autoconf-mode)
- ;; since comment-use-syntax is nil in autoconf.el, the comment-start-skip need
- ;; make sure its first parenthesized expression match the string exactly before
- ;; the "dnl", check the comment-start-skip in lisp-mode for sample.
- ;; See code in (defun comment-search-forward) from emacs 24.2:
- ;; (if (not comment-use-syntax)
- ;; (if (re-search-forward comment-start-skip limit noerror)
- ;; (or (match-end 1) (match-beginning 0)))
- ;; (do-something))
- ;; My regex makes sure (match-end 1) return the position of comment starter
- (when (and (boundp 'comment-use-syntax) (not comment-use-syntax))
- ;; Maybe autoconf.el will (setq comment-use-syntax t) in the future?
- (setq comment-start-skip "^\\(\\s*\\)\\(dnl\\|#\\) +")))
- ((eq major-mode 'haml-mode)
- (setq comment-use-syntax nil)
- (setq comment-start "-# ")
- (setq comment-start-skip "-##*[ \t]*"))))
-
-(defun evilnc--forward-line (num)
- "Move NUM source or screen lines forward, depending on visual-line settings."
- (cond
- ((or (and visual-line-mode
- (or (not (bound-and-true-p evil-mode))
- (bound-and-true-p evil-respect-visual-line-mode)))
- (and (boundp 'display-line-numbers-type)
- (eq display-line-numbers-type 'visual)))
- (vertical-motion num))
- (t
- (forward-line num))))
-
-(defun evilnc--operation-on-lines-or-region (fn &optional num)
- "Apply FN on NUM lines or selected region."
- (cond
- ;; NO region is selected
- ((not (region-active-p))
- (let* ((b (line-beginning-position)) e)
- (save-excursion
- (evilnc--forward-line (- num 1))
- (setq e (line-end-position)))
- (funcall fn b e)))
-
- ((evilnc-sdk-inside-one-line-p (region-beginning) (region-end))
- (cond
- ;; current comment syntax is NOT fit to comment out a region.
- ;; So we also need hack the `comment-start' and `comment-end'.
- ((and (string= "" comment-end)
- (member major-mode evilnc-cpp-like-comment-syntax-modes))
- (let* ((comment-start-old comment-start)
- (comment-end-old comment-end)
- (comment-start-skip-old comment-start-skip)
- (comment-end-skip-old comment-end-skip))
-
- ;; use C comment syntax temporarily
- (setq comment-start "/* ")
- (setq comment-end " */")
- (setq comment-start-skip "\\(//+\\|/\\*+\\)\\s *")
- (setq comment-end-skip "[ ]*\\(\\s>\\|\\*+/\\)")
-
- (funcall fn (region-beginning) (region-end))
-
- ;; Restore the original comment syntax
- (setq comment-start comment-start-old)
- (setq comment-end comment-end-old)
- (setq comment-start-skip comment-start-skip-old)
- (setq comment-end-skip comment-end-skip-old)))
- ;; just comment out the region
- (t (funcall fn (region-beginning) (region-end)))))
-
- ;; Select more than one line
- (t
- ;; selected region spans MORE than one line
- (let* ((range (evilnc-sdk-expand-to-contain-whole-lines (region-beginning)
- (region-end)))
- (b (car range))
- (e (cdr range)))
- (save-excursion
- (funcall fn b e))))))
-
-(defun evilnc--get-one-paragraph-region ()
- "Select a paragraph which has NO empty line."
- (let* ((b (save-excursion
- (cond
- ((re-search-backward "^[ \t]*$" nil t)
- (forward-line)
- (line-beginning-position))
- (t
- 1))))
- (e (save-excursion
- (cond
- ((re-search-forward "^[ \t]*$" nil t)
- (forward-line -1)
- (line-end-position))
- (t
- (point-max))))))
- (list b e)))
-
-(defun evilnc--invert-comment (start end)
- "Scan the region from START to END line by line, invert its comment status."
- (let* (done b e)
- (save-excursion
- (goto-char end)
- (while (not done)
- (setq b (line-beginning-position))
- (setq e (line-end-position))
- (funcall (if (comment-only-p b e)
- 'uncomment-region 'comment-region)
- b e)
-
- (forward-line -1)
- (if (or (= (line-beginning-position) b)
- (< (line-end-position) start))
- (setq done t))))))
-
-(defvar org-src-lang-modes)
-(declare-function org-show-subtree "org")
-(declare-function outline-up-heading "outline")
-(declare-function org-element-property "org-element")
-
-(defun evilnc--org-src-block-info ()
- "Return src-block info in org. It's like (start end language)."
- (cond
- ;; Emacs 24.4+
- ((fboundp 'org-edit-src-find-region-and-lang)
- (let* ((info (org-edit-src-find-region-and-lang)))
- (list (nth 0 info)
- (1+ (nth 1 info))
- (nth 2 info))))
-
- ;; Emacs 26.1
- ((fboundp 'org-element-at-point)
- (let* ((elem (org-element-at-point))
- (b (org-element-property :begin elem))
- (e (org-element-property :end elem))
- (lang (org-element-property :language elem))
- (str (buffer-substring-no-properties b e))
- (case-fold-search t))
- (when (string-match ".\+BEGIN_SRC .*$" str)
- (setq b (+ b (length (match-string 0 str)) 1)))
- (save-excursion
- (goto-char b)
- (search-forward "#+END_SRC" e t)
- ;; - 1 to remove line feed
- (setq e (- (point) (length "#+END_SRC"))))
- ;; Now Emacs 24.4 and Emacs 26.1 return same result
- (list b e lang)))))
-
-(defun evilnc--org-lang-major-mode (info)
- "Get `major-mode' from INFO of org source block."
- (let* ((lang (nth 2 info)))
- (cond
- ((setq lang (or (cdr (assoc lang org-src-lang-modes))
- lang))
- (intern (concat (if (symbolp lang) (symbol-name lang) lang)
- "-mode")))
- (t
- nil))))
-
-(defun evilnc--working-on-region (start end fn)
- "Region from START to END is applied with operation FN.
-Code snippets embedded in Org-mode is identified and right `major-mode' is used."
- (let* ((old-pos (point))
- (info (if (eq major-mode 'org-mode) (evilnc--org-src-block-info)))
- (lang-f (and info (evilnc--org-lang-major-mode info))))
-
- ;; turn on 3rd party language's major-mode temporarily
- (cond
- (lang-f
- (let* ((src-beg (nth 0 info))
- (src-end (nth 1 info))
- (comment-beg-in-buf (1+ (- start src-beg)))
- (comment-end-in-buf (1+ (- end src-beg)))
- (new-pos (1+ (- old-pos src-beg)))
- (old-code (buffer-substring-no-properties src-beg src-end))
- new-code)
- (with-temp-buffer
- (goto-char (point-min))
- (insert old-code)
- (funcall lang-f)
- (goto-char new-pos)
-
- (cond
- (evilnc-invert-comment-line-by-line
- (evilnc--invert-comment comment-beg-in-buf comment-end-in-buf))
- (t
- (funcall fn comment-beg-in-buf comment-end-in-buf)))
-
- (setq new-code (buffer-substring-no-properties (point-min) (point-max))))
-
- (delete-region src-beg src-end)
- (insert new-code)
- ;; go back to original position when comment inside org src-block
- (goto-char old-pos)))
- (t
- (cond
- (evilnc-invert-comment-line-by-line
- (evilnc--invert-comment start end))
- (t
- (funcall fn start end)))))))
-
-(declare-function web-mode-comment-or-uncomment "ext:web-mode")
-(declare-function web-mode-uncomment-erb-block "ext:web-mode")
-(declare-function web-mode-comment-erb-block "ext:web-mode")
-(defvar web-mode-engine)
-
-(defun evilnc--warn-on-web-mode (is-comment)
- "Check certain part of html code IS-COMMENT."
- (let* ((comment-operation (concat "web-mode-"
- (if is-comment "comment-" "uncomment-")
- web-mode-engine
- "-block")))
- (unless (intern-soft comment-operation)
- (message "defun %s NOT implemented in web-mode! Fix it or report to its maintainer."
- comment-operation))
- is-comment))
-
-;;;###autoload
-(defun evilnc-comment-or-uncomment-region-internal (start end)
- "Comment or uncomment region from START to END."
- (cond
- ((eq major-mode 'web-mode)
- ;; elixir is not supported in web-mode for now
- (unless (fboundp 'web-mode-comment-elixir-block)
- (defun web-mode-comment-elixir-block (pos)
- (funcall 'web-mode-comment-erb-block pos))
- (defun web-mode-uncomment-elixir-block (pos)
- (funcall 'web-mode-uncomment-erb-block pos)))
- (web-mode-comment-or-uncomment-region start end))
- (t
- (evilnc--working-on-region start end 'comment-or-uncomment-region))))
-
-;;;###autoload
-(defun evilnc-comment-or-uncomment-region (start end)
- "Comment or uncomment region from START to END."
- (funcall evilnc-comment-or-uncomment-region-function start end))
-
-(defun evilnc--current-line-num ()
- "Get current line number."
- (save-restriction
- (widen)
- (save-excursion
- (beginning-of-line)
- (1+ (count-lines 1 (point))))))
-
-(defun evilnc--get-line-num (position)
- "Get line number at POSITION."
- (save-excursion
- (goto-char position)
- (evilnc--current-line-num)))
-
-(defun evilnc--find-destination-linenum (last-digits)
- "Find closest line whose line number ends with digit LAST-DIGITS.
-If LAST-DIGITS is 16, line 16, line 116, and line 216 are candidates.
-Then if current line is 17, 16 is the final result."
- (let* ((cur-line-num (evilnc--current-line-num))
- (r 1)
- (l (length (number-to-string last-digits))))
- (while (> l 0)
- (setq r (* r 10))
- (setq l (- l 1)))
- (if (>= (mod cur-line-num r) last-digits)
- (setq last-digits (+ last-digits r)))
- (+ cur-line-num (- last-digits (mod cur-line-num r)))))
-
-(defun evilnc-do-paragraphs (action num)
- "Apply ACTION on NUM paragraphs."
- (let* ((i 0)
- rlt
- (b (point-max))
- (e 0)
- linenum)
- (catch 'break
- (while (< i num)
- (when (setq rlt (evilnc--get-one-paragraph-region))
- (setq b (nth 0 rlt))
- (setq e (nth 1 rlt))
- (setq linenum (evilnc--get-line-num e)))
-
- ;; Original algorithm select all paragraph and comment once
- ;; New algorithm comment paragraph by paragraph
- (when (<= b e)
- (save-excursion
- (funcall action b e)))
-
- ;; prepare for the next paragraph
- (cond
- ((and rlt (< i num))
- (evilnc--goto-line linenum)
-
- ;; move to an empty line
- (forward-line)
-
- ;; move to next non-empty line
- (re-search-forward "^[ \t]*[^ \t]" nil t)
- (if (<= (line-beginning-position) e)
- (throw 'break i)))
-
- (t
- (throw 'break i)))
-
- (setq i (1+ i))))))
-
-;;;###autoload
-(defun evilnc-comment-or-uncomment-paragraphs (&optional num)
- "Comment or uncomment NUM paragraph(s).
-A paragraph is a continuation non-empty lines.
-Paragraphs are separated by empty lines."
- (interactive "p")
- (evilnc-do-paragraphs
- (lambda (b e)
- (evilnc--fix-buggy-major-modes)
- (evilnc-comment-or-uncomment-region b e))
- num))
-
-;;;###autoload
-(defun evilnc-comment-or-uncomment-to-the-line (&optional line-num)
- "Comment or uncomment from current line to LINE-NUM line."
- (interactive "nLine: ")
- (if (not (region-active-p))
- (let* ((b (line-beginning-position))
- (e (line-end-position)))
- (save-excursion
- (evilnc--goto-line line-num)
- (if (< (line-beginning-position) b)
- (setq b (line-beginning-position)))
- (if (> (line-end-position) e)
- (setq e (line-end-position)))
- (evilnc--fix-buggy-major-modes)
- (evilnc-comment-or-uncomment-region b e)))))
-
-;;;###autoload
-(defun evilnc-quick-comment-or-uncomment-to-the-line (&optional last-digits)
- "Comment/uncomment to line number by LAST-DIGITS.
-For example, you can use either \
-\\<M-53>\\[evilnc-quick-comment-or-uncomment-to-the-line] \
-or \\<M-3>\\[evilnc-quick-comment-or-uncomment-to-the-line] \
-to comment to the line 6453"
- (interactive "p")
- (let* ((l (evilnc--find-destination-linenum last-digits)))
- (evilnc-comment-or-uncomment-to-the-line l)
- (evilnc--goto-line (+ 1 l))))
-
-;;;###autoload
-(defun evilnc-toggle-invert-comment-line-by-line ()
- "Please note this command may NOT work on complex evil text objects."
- (interactive)
- (if evilnc-invert-comment-line-by-line
- (setq evilnc-invert-comment-line-by-line nil)
- (setq evilnc-invert-comment-line-by-line t))
- (message (if evilnc-invert-comment-line-by-line
- "Each line's comment status will be inverted"
- "Each line's comment status will NOT be inverted")))
-
-;;;###autoload
-(defun evilnc-toggle-comment-empty-lines ()
- "Toggle the flag which decide if empty line will be commented."
- (interactive)
- (if comment-empty-lines
- (setq comment-empty-lines nil)
- (setq comment-empty-lines t))
- (message (if comment-empty-lines
- "Empty line(s) will be commented"
- "Empty line(s) will NOT be commented")))
-
-(defun evilnc-visual-line-p ()
- "In Evil visual line mode."
- (and (fboundp 'evil-visual-type) (eq (evil-visual-type) 'line)))
-
-(defun evilnc-guess-position-at-point ()
- "Guess current position when evil visual line state is on or off."
- (cond
- ((and (evilnc-visual-line-p)
- (eq (point) (nth 1 (evil-visual-range))))
- ;; In evil visual line state, point is beginning or end visual range
- (cons (line-number-at-pos) (1- (current-column))))
- (t
- (cons (line-number-at-pos) (current-column)))))
-
-;;;###autoload
-(defun evilnc-comment-or-uncomment-lines (&optional num)
- "Comment or uncomment NUM lines. NUM could be negative.
-
-Case 1: If no region selected, comment/uncomment on current line.
-If NUM>1, comment/uncomment extra N-1 lines from next line.
-
-Case 2: Selected region is expanded to make it contain whole lines.
-Then we comment/uncomment the expanded region. NUM is ignored.
-
-Case 3: If a region inside of ONE line is selected,
-we comment/uncomment that region.
-CORRECT comment syntax will be used for C++/Java/Javascript."
- (interactive "p")
- (let* ((orig-pos (evilnc-guess-position-at-point)))
- ;; donot move the cursor
- ;; support negative number
- (cond
- ((and (= 1 num) (string-match "^[ \t]*$" (evilnc-sdk-cur-line)))
- ;; comment on current empty line
- (comment-dwim nil))
- (t
- (save-excursion
- (when (< num 0)
- (evilnc--forward-line (1+ num))
- (setq num (- 0 num)))
- (evilnc--operation-on-lines-or-region
- (lambda (b e)
- (evilnc--fix-buggy-major-modes)
- ;; when comment in evil visual state, the cursor may be rogue
- (when (evilnc-visual-line-p) (evil-normal-state))
- (evilnc-comment-or-uncomment-region b e))
- num))
-
- (evilnc--goto-line (car orig-pos))
- ;; make sure we stay on original line
- (goto-char (min (+ (line-beginning-position) (cdr orig-pos))
- (1- (line-end-position))))))))
-
-;;;###autoload
-(defun evilnc-copy-and-comment-lines (&optional num)
- "Copy&paste NUM lines and comment out original lines.
-NUM could be negative.
-
-Case 1: If no region selected, operate on current line.
-if NUM>1, comment/uncomment extra N-1 lines from next line
-
-Case 2: Selected region is expanded to make it contain whole lines.
-Then we operate the expanded region. NUM is ignored."
- (interactive "p")
- ;; support negative number
- (when (< num 0)
- (evilnc--forward-line (1+ num))
- (setq num (- 0 num)))
-
- (let* ((original-column (current-column)))
- (evilnc--operation-on-lines-or-region
- '(lambda (start end)
- (evilnc--fix-buggy-major-modes)
- (let* ((str (buffer-substring-no-properties start end)))
- (cond
- (evilnc-original-above-comment-when-copy-and-comment
- (let* ((p (point)))
- (comment-region start end)
- (goto-char start)
- (insert-before-markers (concat str "\n"))
- (goto-char p)))
- (t
- (goto-char end)
- (newline 1)
- (insert-before-markers str)
- (comment-region start end)))))
- num)
- ;; Go to original column after evilnc-copy-and-comment-lines
- ;; @see https://github.com/redguardtoo/evil-nerd-commenter/issues/79
- ;; Thanks for Kevin Brubeck (AKA unhammer) for idea/implementation
- (move-to-column original-column)))
-
-;;;###autoload
-(defun evilnc-comment-and-kill-ring-save (&optional num)
- "Comment lines save origin lines into `kill-ring'.
-NUM could be negative.
-
-Case 1: If no region selected, operate on current line.
-;; if NUM>1, comment/uncomment extra N-1 lines from next line
-
-Case 2: Selected region is expanded to make it contain whole lines.
-Then we operate the expanded region. NUM is ignored."
- (interactive "p")
- ;; support negative number
- (when (< num 0)
- (evilnc--forward-line (1+ num))
- (setq num (- 0 num)))
-
- (evilnc--operation-on-lines-or-region
- '(lambda (start end)
- (evilnc--fix-buggy-major-modes)
- (kill-new (buffer-substring-no-properties start end))
- (comment-region start end))
- num))
-
-;; {{ for non-evil user only
-;;;###autoload
-(defun evilnc-copy-to-line (&optional LINENUM)
- "Copy from current line to LINENUM line. For non-evil user only."
- (interactive "nCopy to line: ")
- (if (not (region-active-p))
- (let* ((b (line-beginning-position))
- (e (line-end-position)))
- (save-excursion
- (evilnc--goto-line LINENUM)
- (if (< (line-beginning-position) b)
- (setq b (line-beginning-position)))
- (if (> (line-end-position) e)
- (setq e (line-end-position)))
- (kill-new (buffer-substring-no-properties b e))))))
-
-;;;###autoload
-(defun evilnc-kill-to-line (&optional linenum)
- "Kill from the current line to the LINENUM line. For non-evil user only."
- (interactive "NKill to line: ")
- (if (not (region-active-p))
- (let* ((b (line-beginning-position))
- (e (line-end-position)))
- (save-excursion
- (evilnc--goto-line linenum)
- (if (< (line-beginning-position) b)
- (setq b (line-beginning-position)))
- (if (> (line-end-position) e)
- (setq e (line-end-position)))
- ;; +1 because we need remove the CR
- (setq e (+ 1 e))
- (if (> e (point-max)) (setq e (point-max)))
- (kill-region b e)))))
-;; }}
-
-;;;###autoload
-(defun evilnc-version ()
- "The version number."
- (interactive)
- (message "3.5.8"))
-
-(defvar evil-normal-state-map)
-(defvar evil-visual-state-map)
-(defvar evil-inner-text-objects-map)
-(defvar evil-outer-text-objects-map)
-
-;;;###autoload
-(defun evilnc-default-hotkeys (&optional no-evil-keybindings no-emacs-keybindings)
- "Setup the key bindings of evil-nerd-comment.
-If NO-EVIL-KEYBINDINGS is t, we don't define keybindings in EVIL,
-if NO-EMACS-KEYBINDINGS is t, we don't define keybindings in EMACS mode."
- (interactive)
- ;; Install hotkeys for Emacs mode
- (unless no-emacs-keybindings
- (global-set-key (kbd "M-;") 'evilnc-comment-or-uncomment-lines)
- (global-set-key (kbd "C-c l") 'evilnc-quick-comment-or-uncomment-to-the-line)
- (global-set-key (kbd "C-c c") 'evilnc-copy-and-comment-lines)
- (global-set-key (kbd "C-c p") 'evilnc-comment-or-uncomment-paragraphs))
-
- ;; Install key bindings for evil
- (when (and (not no-evil-keybindings) (fboundp 'evil-mode))
- (define-key evil-normal-state-map ",ci" 'evilnc-comment-or-uncomment-lines)
- (define-key evil-visual-state-map ",ci" 'evilnc-comment-or-uncomment-lines)
- (define-key evil-normal-state-map ",cl" 'evilnc-quick-comment-or-uncomment-to-the-line)
- (define-key evil-normal-state-map ",ll" 'evilnc-quick-comment-or-uncomment-to-the-line)
- (define-key evil-normal-state-map ",cc" 'evilnc-copy-and-comment-lines)
- (define-key evil-visual-state-map ",cc" 'evilnc-copy-and-comment-lines)
- (define-key evil-normal-state-map ",cp" 'evilnc-comment-or-uncomment-paragraphs)
- (define-key evil-normal-state-map ",cs" 'evilnc-comment-box)
- (define-key evil-visual-state-map ",cs" 'evilnc-comment-box)
- (define-key evil-normal-state-map ",cr" 'comment-or-uncomment-region)
- (define-key evil-normal-state-map ",cv" 'evilnc-toggle-invert-comment-line-by-line)
-
- ;; comment itself is text object
- (define-key evil-inner-text-objects-map evilnc-comment-text-object 'evilnc-inner-commenter)
- (define-key evil-outer-text-objects-map evilnc-comment-text-object 'evilnc-outer-commenter)
-
- (when evilnc-use-comment-object-setup
- ;; Install operator for evil text objects
- (define-key evil-normal-state-map ",." 'evilnc-copy-and-comment-operator)
- (define-key evil-visual-state-map ",." 'evilnc-copy-and-comment-operator)
- (define-key evil-normal-state-map ",," 'evilnc-comment-operator)
- (define-key evil-visual-state-map ",," 'evilnc-comment-operator))))
-
-(defun evilnc-frame-wide-string (s)
- "Build summary from S."
- (let* ((w (frame-width))
- ;; display kill ring item in one line
- (key (replace-regexp-in-string "[ \t]*[\n\r]+[ \t]*" "\\\\n" s)))
- ;; strip the whitespace
- (setq key (replace-regexp-in-string "^[ \t]+" "" key))
- ;; fit to the minibuffer width
- (if (> (length key) w)
- (setq key (concat (substring key 0 (- w 4)) "...")))
- key))
-
-;;;###autoload
-(defun evilnc-imenu-create-index-function ()
- "Imenu function find comments."
- (let* (start end linenum str searching cands)
- (save-excursion
- (goto-char (point-min))
- ;; learn this skill from etags-select
- ;; use simple string search to speed up searching
- (setq searching t)
- (while searching
- ;; C/C++ might use "/* " as comment-start
- (setq start (search-forward (string-trim comment-start) (point-max) t))
- ;; OK, it's comment
- (cond
- ((not start)
- (setq searching nil))
-
- (t
- (setq start (1+ start))))
-
- (when (and searching (evilnc-comment-p start))
- (setq linenum (line-number-at-pos start) )
-
- (cond
- ((string= comment-end "")
- (setq end (line-end-position)))
-
- (t
- (setq end (search-forward comment-end (point-max) t))))
-
- (cond
- ((and end (> end start))
- (setq str (string-trim (buffer-substring-no-properties start end)))
- ;; no empty line
- (setq str (replace-regexp-in-string "[\r\n]+" "\n" str))
- ;; could be multi-lines comment
- (let* ((a (split-string str "[\r\n]+"))
- (pre-pattern (concat "^[ \t]*["
- (string-trim comment-start)
- "]*[ \t]*"))
- (post-pattern (concat "[ \t]*["
- (string-trim comment-end)
- "]*[ \t]*$")))
- ;; remove empty lines
- (setq a (delq nil (mapcar (lambda (s)
- (setq s (replace-regexp-in-string pre-pattern "" s))
- (setq s (replace-regexp-in-string post-pattern "" s))
- (setq s (string-trim s))
- (unless (string-match-p "^[ \t]*$" s) s))
- a)))
- (setq str (mapconcat 'identity a "\n" )))
-
-
- (when (and (not (string-match-p "^[ \t\n\r]*$" str))
- (> (length str) evilnc-min-comment-length-for-imenu))
- (let* ((m (make-marker)))
- (set-marker m start)
- (push (cons (evilnc-frame-wide-string (format "%d:%s" linenum str)) m)
- cands)))
-
- (goto-char (min (1+ end) (point-max))))
-
- (t
- (setq searching nil))))))
- (nreverse cands)))
-
-(defun evilnc-html-comment-region (start end)
- "Comment region between START and END."
- (save-excursion
- (goto-char end)
- (insert (evilnc-html-comment-end))
- (goto-char start)
- (insert (evilnc-html-comment-start))))
-
-(defun evilnc-html-uncomment-region (start end)
- "Uncomment HTML tag between START and END."
- (let* (mark-start-pos
- mark-end-pos
- (len-comment-start (length (evilnc-html-comment-start))))
- (save-excursion
- (goto-char start)
- (setq mark-start-pos (search-forward (evilnc-html-comment-start) end t))
- (goto-char end)
- (setq mark-end-pos (search-backward (evilnc-html-comment-end) start t))
- (when (and mark-start-pos mark-end-pos)
- (goto-char mark-end-pos)
- (delete-char (length (evilnc-html-comment-end)))
- (goto-char (- mark-start-pos len-comment-start))
- (delete-char len-comment-start)))))
-
-(defun evilnc-html-tag-comment-p (start)
- "Test if html tag comment is at position START position."
- (save-excursion
- (goto-char start)
- (string-match-p (concat "^[ \t]*" (regexp-quote (evilnc-html-comment-start)))
- (evilnc-sdk-cur-line))))
-
-;;;###autoload
-(defun evilnc-comment-or-uncomment-html-tag ()
- "Comment or uncomment html tag(s).
-If no region is selected, current tag under focus is automatically selected.
-In this case, only one tag is selected.
-If users manually select region, the region could cross multiple sibling tags
-and automatically expands to include complete tags.
-Users can press \"v\" key in evil mode to select multiple tags.
-This command is not dependent on any 3rd party package."
- (interactive)
- (let* (beg end beg-line-beg end-line-end)
- (cond
- ((region-active-p)
- (setq beg (region-beginning))
- (setq end (region-end))
- (save-excursion
- (goto-char beg)
- (setq beg-line-beg (line-beginning-position))
- (goto-char end)
- (setq end-line-end (line-end-position))
- (when (< beg-line-beg (line-beginning-position))
- ;; it's multiple lines region
- (goto-char beg-line-beg)
- (setq beg (re-search-forward "^[ \t]*" end t))
- (setq end end-line-end))))
- (t
- (save-excursion
- (sgml-skip-tag-backward 1)
- (setq beg (point))
- (setq beg-line-beg (line-beginning-position))
- (sgml-skip-tag-forward 1)
- (setq end (point))
- (setq end-line-end (line-end-position)))))
-
- (cond
- ((evilnc-html-tag-comment-p beg)
- ;; make sure all tags plus comment marks are selected
- (evilnc-html-uncomment-region beg-line-beg end-line-end))
- (t
- ;; the whole tags is already selected
- (evilnc-html-comment-region beg end)))))
-
-;;;###autoload
-(defun evilnc-comment-or-uncomment-html-paragraphs (&optional num)
- "Comment or uncomment NUM paragraphs contain html tag.
-A paragraph is a continuation non-empty lines.
-Paragraphs are separated by empty lines."
- (interactive "p")
- (evilnc-do-paragraphs
- (lambda (b e)
- (ignore e)
- ;; {{ make sure tag is focused
- (goto-char b)
- (sgml-skip-tag-forward 1)
- ;; }}
- (evilnc-comment-or-uncomment-html-tag))
- num))
-
-(defun evilnc-comment-box (&optional num)
- "Comment out NUM lines, putting it inside a box. NUM could be negative.
-If NUM is nil, comment out current paragraph. This command uses `comment-box'."
- (interactive "P")
- (let* ((orig-pos (evilnc-guess-position-at-point))
- range)
-
- (cond
- ((or (not num))
- (when (setq range (bounds-of-thing-at-point 'paragraph))
- (evilnc--fix-buggy-major-modes)
- (when (evilnc-visual-line-p) (evil-normal-state))
- (comment-box (car range) (cdr range) 1)))
- (t
- (save-excursion
- (when (< num 0)
- (evilnc--forward-line (1+ num))
- (setq num (- 0 num)))
- (evilnc--operation-on-lines-or-region
- (lambda (b e)
- (evilnc--fix-buggy-major-modes)
- ;; when comment in evil visual state, the cursor may be rogue
- (when (evilnc-visual-line-p) (evil-normal-state))
- (comment-box b e 1))
- num))))
-
- (unless (eq (evilnc-guess-position-at-point) orig-pos)
- (evilnc--goto-line (car orig-pos))
- ;; make sure we stay on original line
- (goto-char (min (+ (line-beginning-position) (cdr orig-pos))
- (1- (line-end-position)))))))
-
-;; Attempt to define the operator on first load.
-;; Will only work if evil has been loaded
-(with-eval-after-load 'evil
- (require 'evil-nerd-commenter-operator))
-
-(provide 'evil-nerd-commenter)
-;;; evil-nerd-commenter.el ends here