diff options
| author | Jack Jamison <jackqjamison@gmail.com> | 2026-07-30 20:09:00 -0400 |
|---|---|---|
| committer | Jack Jamison <jackqjamison@gmail.com> | 2026-07-30 20:18:37 -0400 |
| commit | 8c4e09dff83847ac7f07bf1da7751e9328006c4d (patch) | |
| tree | a0e245567ce225f8bcb63b66e4d2373b5d033e4a /.config/emacs/lisp/evil-nerd-commenter | |
| parent | 1e33b30749bb1043ffc6ceb5a2fb0977446788b3 (diff) | |
actual final changes and get rid of junk in lisp dir
actually works fine
Diffstat (limited to '.config/emacs/lisp/evil-nerd-commenter')
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 |
