1

QUESTION:

How can I make an emacs command M-x sum-the-brackets that scans highlighted text for all occurrences of [ <number> u ] and [ <number>u ], and sums them?

EXAMPLE:

Selecting the text

Here is some text. [0.1u]
Here is some more text [0.2 u]
And here is some noise: 0.2

and running M-x sum-the-brackets should yield 0.3 in the mini-buffer.

0

3 Answers 3

2

You want to search for all instances of the regular expression \[ *\([-0-9.]+\) *u *\]:

(re-search-forward "\\[ *\\([-0-9.]+\\) *u *\\]" nil t)

and sum the matches:

(setq sum (+ sum (string-to-number (match-string 1))))

Since you want this to apply to the region only, you'll need to narrow-to-region and then restore the restriction using save-restriction.

Putting this all together, we get:

(defun my-sum (begin end)
  (interactive "r")
  (save-restriction
    (save-excursion
      (narrow-to-region begin end)
      (goto-char (point-min))
      (let ((sum 0))
        (while (re-search-forward "\\[ *\\([-0-9.]+\\) *u *\\]" nil t)
          (setq sum (+ sum (string-to-number (match-string 1)))))
        (message "%s" sum)
        sum))))
3

Using standard commands:

M-: (setq n 0) RET
C-M-% \[\([0-9.]+\) *u\] RET \,(prog1 \& (setq n (+ n \#1))) RET !
M-: n RET

Note: to get more information have a look at help for query-replace-regexp, prog1 and eval-expression

1
  • This is cool, I didn't know this replacement style is possible. I corrected your answer and made a remark about finding more help. Please review my edit to your answer.
    – jue
    Commented Jul 11, 2017 at 9:27
1

Here is the function you wished for.
I put some extra variables inside this function, so it is easier for you to enhance it.

(defun sum-the-brackets (begin end)
    "sums up values in brackets with style '[ FLOAT u ]'
For non interactive use BEGIN must be smaller then END.
If FLOAT is omitted bracket counts with value one
If FLOAT is '.' it counts as value 0
Whitespace inside the brackets is ignored"
    (interactive "r")
    (save-excursion
        (let ((n 0)       ; desired value
              (c 0)       ; counter
              (tmp nil)   ; string in bracket
              (tmpf 0))   ; value of string in bracket
            (goto-char begin)
            (while (search-forward-regexp "\\[ *\\([0-9]*\\.?[0-9]*\\) *\\(u *\\)\\]" end t)
                (setq c (1+ c))
                (setq tmp (match-string 1))
                (setq tmpf (if (string= "" tmp) 1                              
                               (string-to-number tmp)))
                (setq n (+ n tmpf)))
            (message "Sum-Value: %2.3f ; brackets counted: %d" n c))))

This function sums up following 6 brackets to value 3.6:

Here is some text. [0.1u]
Here is some more text [ 0.2 u]
count me with value zero point 3 [.3 u]
count me with value two [2 u]
count me with value one [u]
count me with zero [ . u ]
And here is some noise: 0.2

Note: politza answer is way more cool. :)

Note2: comments/edits on improvement of the code are very welcome, I did code this for practice and it took me a while. :)

Edit: the user "jch" changed the question. I will not update this answer because "jch" gave an answer which fits his edits and maybe someone else finds my answer useful.

4
  • 1. Is narrowing really necessary ? 2. Second argument of search-forward-regexp you gave is also the default. 3. It's always nice beeing able to use a command as function as well, i.e. use (begin end) arguments and setup interactive usage in the (interactive) spec appropriately.
    – politza
    Commented Jul 11, 2017 at 21:59
  • @politza many thanks for your constructive comment! I changed the code accordingly. Also I spotted, that the questioner wanted to evaluate [u].
    – jue
    Commented Jul 11, 2017 at 23:55
  • The apparent [u] in the orignal answer was a typo, due to some misquoted markup. I merely fixed the markup, which caused the spurious [u] to disapper. As to your answer — please keep it around, it's good to have multiple solutions written in different styles.
    – jch
    Commented Jul 13, 2017 at 18:44
  • You also wrote a good and correct answer, so there is no need to have a correct answer a second time. Besides, my original code, before my edit looks nearly the same like yours and I don't want to revert my code. Everything is fine! :)
    – jue
    Commented Jul 13, 2017 at 18:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.