;;; math-at-point.el --- Utilities for modifying numbers at point
;; Copyright (C) 2014 Nathaniel Flath
;; Author: Nathaniel Flath
;; URL: http://github.com/nflath/move-line
;; Version: 0.0.1
;; This file is not part of GNU Emacs.
;;; Commentary:
;; This file provides several utility functions for modifying the current
;; number at point. They are:
;; math-at-point-increment-number-decimal
;; math-at-point-increment-number-hexadecimal
;; math-at-point-increment-number-binary
;; math-at-point-mul
;;; Installation
;; To use this mode, put the following in your init.el:
;; (require 'math-at-point)
;;; 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 GNU Emacs; see the file COPYING. If not, write to the
;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.
;;; Code:
(defun math-at-point-increment-number-decimal (&optional arg)
"Increment the number forward from point by 'arg'."
(interactive "p*")
(save-excursion
(save-match-data
(let (inc-by field-width answer)
(setq inc-by (if arg arg 1))
(skip-chars-backward "0123456789")
(when (re-search-forward "[0-9]+" nil t)
(setq field-width (- (match-end 0) (match-beginning 0)))
(setq answer (+ (string-to-number (match-string 0) 10) inc-by))
(when (< answer 0)
(setq answer (+ (expt 10 field-width) answer)))
(replace-match (format (concat "%0" (int-to-string field-width) "d")
answer)))))))
(defun math-at-point-increment-number-hexadecimal (&optional arg)
"Increment the number forward from point by 'arg'."
(interactive "p*")
(save-excursion
(save-match-data
(let (inc-by field-width answer hex-format)
(setq inc-by (if arg arg 1))
(skip-chars-backward "0123456789abcdefABCDEF")
(when (re-search-forward "[0-9a-fA-F]+" nil t)
(setq field-width (- (match-end 0) (match-beginning 0)))
(setq answer (+ (string-to-number (match-string 0) 16) inc-by))
(when (< answer 0)
(setq answer (+ (expt 16 field-width) answer)))
(if (equal (match-string 0) (upcase (match-string 0)))
(setq hex-format "X")
(setq hex-format "x"))
(replace-match (format (concat "%0" (int-to-string field-width)
hex-format)
answer)))))))
(defun math-at-point-format-bin (val width)
"Convert a number to a binary string."
(let (result)
(while (> width 0)
(if (equal (mod val 2) 1)
(setq result (concat "1" result))
(setq result (concat "0" result)))
(setq val (/ val 2))
(setq width (1- width)))
result))
(defun math-at-point-increment-number-binary (&optional arg)
"Increment the number forward from point by 'arg'."
(interactive "p*")
(save-excursion
(save-match-data
(let (inc-by field-width answer)
(setq inc-by (if arg arg 1))
(skip-chars-backward "01")
(when (re-search-forward "[0-1]+" nil t)
(setq field-width (- (match-end 0) (match-beginning 0)))
(setq answer (+ (string-to-number (match-string 0) 2) inc-by))
(when (< answer 0)
(setq answer (+ (expt 2 field-width) answer)))
(replace-match (format-bin answer field-width)))))))
(defun math-at-point-mul (&optional arg)
"Multiply the number (in base 10 representation) at point.
Defaults to doubling the number."
(interactive "p*")
(if (looking-at "[-0-9.]+")
(let ((mul-by (if (= arg 1) 2 arg)))
(let ((num (car (read-from-string (buffer-substring (match-beginning 0) (match-end 0))))))
(delete-region (match-beginning 0) (match-end 0))
(insert (format "%f" (* num mul-by)))))))
(provide 'math-at-point)
;;; math-at-point.el ends here