Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vector support #4

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions README.org
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
- Increment / Decrement binary, octal, decimal and hex literals

- works like C-a/C-x in vim, i.e. searches for number up to eol and then
increments or decrements and keep zero padding up (unlike in vim)
increments or decrements and keep zero padding up (unlike in
vim), except for decimals in vectors like =x[10]= -> =x[9]=. The
pairs that define vectors can be customized with =evil-numbers-dont-pad-matching-pairs-for-decimal-numbers=

- When a region is active, as in evil's visual mode, all the
numbers within that region will be incremented/decremented (unlike
Expand All @@ -29,7 +31,15 @@
#+END_SRC

** Usage
Position cursor on literal and play with your numbers!
Position cursor on literal and play with your numbers!

If you don't like vim's behavior of moving a character backward
after replacement, then you can turn it off with

#+BEGIN_SRC emacs-lisp
(setq evil-numbers-dont-move-backward-to-match-vim t)
#+END_SRC


** Known Bugs
See http://github.com/cofi/evil-numbers/issues
Expand Down
65 changes: 48 additions & 17 deletions evil-numbers.el
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,25 @@

;;; Code:

(defgroup evil-numbers nil
"Evil Numbers")

(defcustom evil-numbers-dont-pad-matching-pairs-for-decimal-numbers
'(("[" "]")
("(" ")"))
"If the decimal number is enclosed in these items, don't pad the item.
For example, x[10] will not be changed to x[09] and x(10) will not be changed to x(09)"
:type '(repeat
(list
(string :tag "Match at beginning: ")
(string :tag "Match at end: ")))
:group 'evil-numbers)

(defcustom evil-numbers-dont-move-backward-to-match-vim nil
"Don't match vim's moving one character backward after replacement."
:type 'boolean
:group 'evil-numbers)

;;;###autoload
(defun evil-numbers/inc-at-pt (amount &optional no-region)
"Increment the number at point or after point before end-of-line by `amount'.
Expand All @@ -80,7 +99,8 @@ applying the regional features of `evil-numbers/inc-at-point'.
(while (re-search-forward "\\(?:0\\(?:[Bb][01]+\\|[Oo][0-7]+\\|[Xx][0-9A-Fa-f]+\\)\\|-?[0-9]+\\)" re t)
(evil-numbers/inc-at-pt amount 'no-region)
;; Undo vim compatability.
(forward-char 1)))))
(unless evil-numbers-dont-move-backward-to-match-vim
(forward-char 1))))))
(setq deactivate-mark t))
(t
(save-match-data
Expand All @@ -102,13 +122,23 @@ applying the regional features of `evil-numbers/inc-at-point'.
(progn
(skip-chars-backward "0123456789")
(skip-chars-backward "-")
(when (looking-at "-?\\([0-9]+\\)")
(cond
((and (looking-back (regexp-opt (mapcar (lambda(x) (nth 0 x)) evil-numbers-dont-pad-matching-pairs-for-decimal-numbers)))
(looking-at (concat "\\(-?[0-9]+\\)\\(" (regexp-quote (cadr (assoc (match-string 0) evil-numbers-dont-pad-matching-pairs-for-decimal-numbers))) "\\)")))
(replace-match
(format "%s\\2" (+ amount (string-to-number (match-string 1) 10))))
;; Move point one position back to conform with Vim
(unless evil-numbers-dont-move-backward-to-match-vim
(forward-char (- 1 (length (match-string 2)))))
t)
((looking-at "-?\\([0-9]+\\)")
(replace-match
(format (format "%%0%dd" (- (match-end 1) (match-beginning 1)))
(+ amount (string-to-number (match-string 0) 10))))
;; Moves point one position back to conform with Vim
(forward-char -1)
t))
(unless evil-numbers-dont-move-backward-to-match-vim
(forward-char -1))
t)))
(error "No number at point or until end of line")))))))

;;;###autoload
Expand All @@ -135,21 +165,21 @@ decimal: [0-9]+, e.g. 42 or 23"
(or
;; numbers or format specifier in front
(looking-back (rx (or (+? digit)
(and "0" (or (and (in "bB") (*? (in "01")))
(and (in "oO") (*? (in "0-7")))
(and (in "xX") (*? (in digit "A-Fa-f"))))))))
(and "0" (or (and (in "bB") (*? (in "01")))
(and (in "oO") (*? (in "0-7")))
(and (in "xX") (*? (in digit "A-Fa-f"))))))))
;; search for number in rest of line
;; match 0 of specifier or digit, being in a literal and after specifier is
;; handled above
(and
(re-search-forward "[[:digit:]]" (point-at-eol) t)
(or
(not (memq (char-after) '(?b ?B ?o ?O ?x ?X)))
(/= (char-before) ?0)
(and (> (point) 2) ; Should also take bofp into consideration
(not (looking-back "\\W0" 2)))
;; skip format specifiers and interpret as bool
(<= 0 (skip-chars-forward "bBoOxX"))))))
(re-search-forward "[[:digit:]]" (point-at-eol) t)
(or
(not (memq (char-after) '(?b ?B ?o ?O ?x ?X)))
(/= (char-before) ?0)
(and (> (point) 2) ; Should also take bofp into consideration
(not (looking-back "\\W0" 2)))
;; skip format specifiers and interpret as bool
(<= 0 (skip-chars-forward "bBoOxX"))))))

(defun evil-numbers/search-and-replace (look-back skip-back search-forward inc base)
"When looking back at `LOOK-BACK' skip chars `SKIP-BACK'backwards and replace number incremented by `INC' in `BASE' and return non-nil."
Expand All @@ -159,8 +189,9 @@ decimal: [0-9]+, e.g. 42 or 23"
(replace-match (evil-numbers/format (+ inc (string-to-number (match-string 1) base))
(length (match-string 1))
base))
;; Moves point one position back to conform with Vim
(forward-char -1)
;; Moves point one position back to conform with Vim
(unless evil-numbers-dont-move-backward-to-match-vim
(forward-char -1))
t))

(defun evil-numbers/format (num width base)
Expand Down