Feature Request: Increment/Decrement Number #106

Closed
milkypostman opened this Issue Nov 10, 2011 · 6 comments

Comments

Projects
None yet
5 participants
Contributor

milkypostman commented Nov 10, 2011

I think this is a worthwhile addition. Maybe not.

(global-set-key (kbd "C-c +") 'esk-increment-number-at-point)
(global-set-key (kbd "C-c -") 'esk-decrement-number-at-point)


(defun esk-increment-number-at-point ()
  (interactive)
  (skip-chars-backward "0123456789")
  (or (looking-at "[0123456789]+")
      (error "No number at point"))
  (replace-match (number-to-string (1+ (string-to-number (match-string 0))))))

(defun esk-decrement-number-at-point ()
  (interactive)
  (skip-chars-backward "0123456789")
  (or (looking-at "[0123456789]+")
      (error "No number at point"))
  (replace-match (number-to-string (1- (string-to-number (match-string 0))))))

bbatsov commented Feb 26, 2012

I don't know about ESK, but I'm definitely adding this to Prelude. :-)

Contributor

DarwinAwardWinner commented Feb 26, 2012

Maybe call it "increment-integer-at-point" to be more technically correct?

Contributor

milkypostman commented Feb 26, 2012

Yes we should do that. And allow = instead of + and allow repeatedly pressing +/= to keep increasing or decreasing.

On Feb 26, 2012, at 15:14, Ryan Thompsonreply@reply.github.com wrote:

Maybe call it "increment-integer-at-point" to be more technically correct?


Reply to this email directly or view it on GitHub:
#106 (comment)

Contributor

DarwinAwardWinner commented Feb 27, 2012

Also, there's some bad edge cases here. Think about what happens when you decrement a zero, and then increment it. You would expect to get zero, but I expect you will get -2 instead. First, you decrement 0 and get -1. Then you increment the 1 and get 2, which together with the minus sign yields -2.

Here's a version that seems to work on all integers. First, I implement (thing-at-point 'integer) to work on all integers, negative or not, then I use it to implement the increment function, then I use that to implement the decrement function. Note that both take numeric prefix args to increment/decrement by more than one, so you can increment by 10 by doing C-1 C-0 M-x esk-increment-integer-at-point.

(require 'thingatpt)

(defun thing-at-point-goto-end-of-integer ()
  "Go to end of integer at point"
  (let ((inhibit-changing-match-data t))
    ;; Skip over optional sign
    (when (looking-at "[+-]")
      (forward-char 1))
    ;; Skip over digits
    (skip-chars-forward "[[:digit:]]")
    ;; Check for at least one digit
    (unless (looking-back "[[:digit:]]")
      (error "No integer here"))))
(put 'integer 'beginning-op 'thing-at-point-goto-end-of-integer)

(defun thing-at-point-goto-beginning-of-integer ()
  "Go to end of integer at point"
  (let ((inhibit-changing-match-data t))
    ;; Skip backward over digits
    (skip-chars-backward "[[:digit:]]")
    ;; Check for digits and optional sign
    (unless (looking-at "[+-]?[[:digit:]]")
      (error "No integer here"))
    ;; Skip backward over optional sign
    (when (looking-back "[+-]")
        (backward-char 1))))
(put 'integer 'beginning-op 'thing-at-point-goto-beginning-of-integer)

(defun thing-at-point-bounds-of-integer-at-point ()
  (save-excursion
    (let (beg end)
      (thing-at-point-goto-beginning-of-integer)
      (setq beg (point))
      (thing-at-point-goto-end-of-integer)
      (setq end (point))
      (cons beg end))))
(put 'integer 'bounds-of-thing-at-point 'thing-at-point-bounds-of-integer-at-point)

(defun thing-at-point-integer-at-point ()
  (let ((bounds (bounds-of-thing-at-point 'integer)))
    (string-to-int (buffer-substring (car bounds) (cdr bounds)))))
(put 'integer 'thing-at-point 'thing-at-point-integer-at-point)

(defun esk-increment-integer-at-point (&optional inc)
  "Increment integer at point by one.

With numeric prefix arg, increment the integer by that amount."
  (interactive "p")
  (let ((inc (or inc 1))
        (n (thing-at-point 'integer))
        (bounds (bounds-of-thing-at-point 'integer)))
    (delete-region (car bounds) (cdr bounds))
    (insert (int-to-string (+ n inc)))))

(defun esk-decrement-integer-at-point (&optional dec)
  "Decrement integer at point by one.

With numeric prefix arg, decrement the integer by that amount."
  (interactive "p")
  (esk-increment-integer-at-point (- (or dec 1))))

A simpler and (I think) more robust implementation of this could be done using replace-regexp as illustrated here.

Owner

technomancy commented Feb 12, 2014

Thanks, but the starter kit is currently deprecated; please see the readme on the v3 branch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment