Skip to content

Instantly share code, notes, and snippets.

@jidaikobo-shibata
Last active June 27, 2019 06:47
Show Gist options
  • Save jidaikobo-shibata/b967d6a7441f85aa541d to your computer and use it in GitHub Desktop.
Save jidaikobo-shibata/b967d6a7441f85aa541d to your computer and use it in GitHub Desktop.
Emacs(Elisp): calculate region and insert. 選択範囲の数式を計算して、次の行にinsertします。数字が羅列されている場合は、加算します。数字や式と自然な文章が混在している場合は、数式のみを計算します。
;;; ------------------------------------------------------------
;;; 選択範囲を計算してバッファに出力
;; gist-description: Emacs(Elisp): calculate region and insert. 選択範囲の数式を計算して、次の行にinsertします。数字が羅列されている場合は、加算します。数字や式と自然な文章が混在している場合は、数式のみを計算します。
;; gist-id: b967d6a7441f85aa541d
;; gist-name: calculate-region-and-insert.el
;; gist-private: nil
(defun add-number-grouping (number &optional separator)
"Add commas to NUMBER and return it as a string.
Optional SEPARATOR is the string to use to separate groups.
It defaults to a comma."
(let ((num (number-to-string number))
(op (or separator ",")))
(while (string-match "\\(.*[0-9]\\)\\([0-9][0-9][0-9].*\\)" num)
(setq num (concat
(match-string 1 num) op
(match-string 2 num))))
num))
(defun calculate-region-and-insert (beg end)
"Calculate natural text of region and insert to current buffer. BEG, END."
(interactive "r")
(let* ((strings (if mark-active
(buffer-substring-no-properties beg end)
(read-string " Expression: " "")))
(is_num_format (string-match "," (buffer-substring-no-properties beg end)))
result)
;; 余計なものを取り払って計算の準備
(when mark-active
(with-temp-buffer
(insert strings)
(perform-replace "[\t,  ]+" "" nil t nil nil nil (point-min) (point-max))
(perform-replace "\n" "+" nil t nil nil nil (point-min) (point-max))
(perform-replace "[^0-9\\+\\*/\\(\\)^\\.-]" "+" nil t nil nil nil (point-min) (point-max))
(perform-replace "\\++" "+" nil t nil nil nil (point-min) (point-max))
(perform-replace "\\+$" "" nil t nil nil nil (point-min) (point-max))
(perform-replace "^\\++" "" nil t nil nil nil (point-min) (point-max))
(setq strings (buffer-substring-no-properties (point-min) (point-max))))
(goto-char end)
(end-of-line)
(newline))
(setq result (calc-eval strings))
;; カンマ整形されている計算式だったらカンマ区切りで返す
(when is_num_format (setq result (add-number-grouping (string-to-number result) ",")))
;; (calc-eval)は、小数点を含んだ式の場合、整数でも末尾にピリオドをつけるので抑止
(when (string-match "\\.$" result)
(setq result (substring result 0 (match-beginning 0))))
(insert result)))
(global-set-key (kbd "M-c") 'calculate-region-and-insert)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment