How to round all the numbers in a region? - emacs

I am editing a latex file, and there are too many decimal places in one of my tables. If I want to round all the numbers in a table (or a region) to tenths or hundredths, what can I do?
I googled and found some lisp functions, like
(format "%0.2f" 1.2345)
(round 1.2)
etc, but I do not know how to apply them to all the numbers in a region. Thanks.

You can perform this task without having to write a dedicated Elisp function, using query-replace-regexp interactively:
C-M-%[0-9]+\.[0-9]+RET\,(format "%0.2f" \#&)RET
The \,(...) in the replacement text means to interpolate the result of calling the parenthesized Lisp expression, and \#& means "whatever the entire pattern matched, converted to a number."

For me that's a common use case: search something in the region and do something with the matched text.
So there's a useful code snippet here: http://wikemacs.org/wiki/Emacs_Lisp_Cookbook#Scripted_Use
I just had to convert the matched string to an int with string-to-number.
Adapt my regexp to your needs.
That't the function I ended up with:
(defun my-round-nb (start end)
"round the nb of the region."
(interactive "r")
(save-restriction
(narrow-to-region start end)
(goto-char 1)
(let ((case-fold-search nil))
(while (search-forward-regexp "\\([0-9]+\\.[0-9]+\\)" nil t)
(replace-match (format "%0.2f" (string-to-number (match-string 1)))
)))))
my doc: http://wikemacs.org/wiki/Category:Emacs_Lisp

Related

How to define whole line comment syntax in Emacs?

I want the sequence // to start a comment when it is at the beginning of a line. But inside of a line it should not start any comments.
// this is a comment
This is a URL: http://example.com
Is it possible?
I'd do it this way:
(defvar my-foo-mode-syntax-table
(let ((st (make-syntax-table)))
;; Add other entries appropriate for my-foo-mode.
(modify-syntax-entry ?/ ". 12" st)
(modify-syntax-entry ?\n "> " st)
st))
(defvar my-foo-font-lock-keywords
;; Add other rules appropriate for my-foo-mode.
())
(define-derived-mode my-foo-mode nil "My-Foo"
(setq-local font-lock-keywords '(my-foo-font-lock-keywords))
;; Add other settings appropriate for my-foo-mode.
(setq-local syntax-propertize-function
(syntax-propertize-rules ("./\\(/+\\)" (1 ".")))))
Notice: No need for any special font-lock rule since font-lock automatically highlights comments for you, based on the syntax-tables.
You can do this by writing a syntax-propertize-function
I have written an example major mode that shows this below.
Emacs built in parsing will call your syntax-propertize-function so that it can manually set the syntax-table text property on lines starting with //.
(define-derived-mode my-syntax-test-mode fundamental-mode
"A major mode where // denotes a comment but only if it is at the beginning of a line."
:syntax-table (make-syntax-table)
(setq mode-name "my syntax test")
;; our mode will use `apply-my-custom-syntax-table-appropriately' to manually set
;; the syntax-table text property on lines starting with //"
(setq syntax-propertize-function 'apply-my-custom-syntax-table-appropriately)
;; change `comment-dwim` to handle this type of comments correctly
(local-set-key [remap comment-dwim] 'my-comment-dwim))
(defvar my-custom-syntax-table
;; syntax table where // starts a comment and \n ends it
(let ((table (make-syntax-table)))
(modify-syntax-entry ?/ "< 1" table)
(modify-syntax-entry ?/ "< 2" table)
(modify-syntax-entry ?\n "> " table)
table))
(defun apply-my-custom-syntax-table-appropriately (beg end)
(save-excursion
(save-restriction
(widen)
(goto-char beg)
;; for every line between points BEG and END
(while (and (not (eobp)) (< (point) end))
(beginning-of-line)
;; if it starts with a //
(when (looking-at "^//")
;; remove current syntax-table property
(remove-text-properties (1- (line-beginning-position))
(1+ (line-end-position))
'(syntax-table))
;; set syntax-table property to our custom one
;; for the whole line including the beginning and ending newlines
(add-text-properties (1- (line-beginning-position))
(1+ (line-end-position))
(list 'syntax-table my-custom-syntax-table)))
(forward-line 1)))))
(defun my-comment-dwim (arg)
(interactive "*P")
(require 'newcomment)
(save-excursion
(let ((comment-start "//") (comment-end "")
(comment-column 0)
;; don't indent comments
(comment-style 'plain))
;; create the region containing current line if there is no active region
(unless (use-region-p)
(end-of-line)
(push-mark (line-beginning-position))
(setq mark-active t))
(comment-dwim nil))))
Answer: Use regexps
Short and simple
(define-derived-mode my-foo-mode prog-mode "My-Foo"
(setq-local font-lock-keywords t)
(setq-local syntax-propertize-function
(syntax-propertize-rules
((rx line-start (* whitespace) (group "//")) (1 "<"))
((rx (group "\n")) (1 ">")))))
That is all you need, but read on if you'd like to know more.
Explanation
This is based on #stefan's excellent solution which uses syntax-propertize-function to add to a syntax-table. While simpler isn't always better, #stefan's answer does more than what the original question asked for, so I've created this answer for people who only need a small hint or who just want to modify an existing mode.
It turns out directly manipulating a syntax table is unnecessary since the function syntax-propertize-rules makes it easy to map from regular expressions to syntax classes. For example, the syntax class < means "start of comment" and > means "end of comment". (See the Emacs lisp manual.)
I set font-lock-keywords to t as that is the minimum needed to enable syntax highlighting. If you are editing an existing mode, it likely already sets that variable and will not need to be changed.
And, finally, I use Emacs' rx function because it makes regular expressions sane in Lisp. (If you like Lisp, regular expressions, and sanity, I highly recommend using rx.)
About syntax-propertize-rules
I was going to link to the documentation for syntax-propertize-rules, but the Emacs manual does not (as of Emacs 28.1) even mention it. Until that gets remedied, I'll paste here the builtin documentation from C-hf:
syntax-propertize-rules is a Lisp macro in ‘syntax.el’.
(syntax-propertize-rules &rest RULES)
Probably introduced at or before Emacs version 24.1.
Make a function that applies RULES for use in
‘syntax-propertize-function’. The function will scan the buffer,
applying the rules where they match. The buffer is scanned a single
time, like "lex" would, rather than once per rule.
Each RULE can be a symbol, in which case that symbol’s value should
be, at macro-expansion time, a precompiled set of rules, as returned
by ‘syntax-propertize-precompile-rules’.
Otherwise, RULE should have the form (REGEXP HIGHLIGHT1 ...
HIGHLIGHTn), where REGEXP is an expression (evaluated at time of
macro-expansion) that returns a regexp, and where HIGHLIGHTs have the
form (NUMBER SYNTAX) which means to apply the property SYNTAX to the
chars matched by the subgroup NUMBER of the regular expression, if
NUMBER did match. SYNTAX is an expression that returns a value to
apply as ‘syntax-table’ property. Some expressions are handled
specially:
if SYNTAX is a string, then it is converted with ‘string-to-syntax’;
if SYNTAX has the form (prog1 EXP . EXPS) then the value returned by EXP will be applied to the buffer before running EXPS and if EXP is
a string it is also converted with ‘string-to-syntax’. The SYNTAX
expression is responsible to save the ‘match-data’ if needed for
subsequent HIGHLIGHTs. Also SYNTAX is free to move point, in which
case RULES may not be applied to some parts of the text or may be
applied several times to other parts.
Note: back-references in REGEXPs do not work.

Leave region selected after emacs operation

My question builds on this answer by Trey Jackson to this question from SyntaxT3rr0r.
Trey proposes the following function for incrementing each two-digit number in the selected region of an Emacs buffer.
(defun add-1-to-2-digits (b e)
"add 1 to every 2 digit number in the region"
(interactive "r")
(goto-char b)
(while (re-search-forward "\\b[0-9][0-9]\\b" e t)
(replace-match (number-to-string (+ 1 (string-to-int (match-string 0)))))))
I would like to use this function for my own purposes. However, I would like to increment the numbers many times successively. The problem with the function, in its current form, is that before each invocation, I have to select the region again with my mouse.
My question is: How can Trey's function be modified so that it leaves the region selected after invocation? (My ultimate aim is to assign this function to a keyboard shortcut (something like ctrl+↑) so that I if I keep the ctrl and ↑ keys held down, all the two-digit numbers in my selected region will continuously increase.)
By the way, I am aware of this answer by Brian Campbell, which suggests using exchange-point-and-mark to re-select a previously-selected region. However, I tried that, and it doesn't seem to help in this instance.
Here's your function modified to use let (deactivate-mark) wrapped inside save-excursion as suggested in the answer user event_jr linked to:
https://stackoverflow.com/a/11080667/903943
(defun add-1-to-2-digits (b e)
"add 1 to every 2 digit number in the region"
(interactive "r")
(save-excursion
(let (deactivate-mark)
(goto-char b)
(while (re-search-forward "\\b[0-9][0-9]\\b" e t)
(replace-match (number-to-string (+ 1 (string-to-int (match-string 0)))))))))
You need to bind deactivate-mark to prevent it from being set see:
https://stackoverflow.com/a/11080667/903943
manual: http://www.gnu.org/software/emacs/manual/html_node/elisp/The-Mark.html#index-deactivate_002dmark-2801

How to kill a quoted string at point in emacs?

I would like to kill a quoted string in a source file
without having to mark the beginning of the string and kill-region,
but just by placing the point anywhere inside the quoted string and pressing a shortcut.
I tried to write a function in elisp for this, but I figured out that the file
would need to be parsed from the beginning up to point to determine whether the point is inside quoted string, and to find the bounds of the quoted string(also handle the \")...
But the file is already parsed by font-lock.
So now I can find out if I'm inside quoted string:
(defun inside-quoted-string? ()
(interactive)
(print (find 'font-lock-doc-face (text-properties-at (point)))))
But how do I get the bounds of the string?
font-lock knows it, since it nicely highlights it in blue, but how do I get it?
Edit:
Thanks for the answers. I came up with this code that does
exactly what I wanted - move code around without selecting region or even
moving to beginning of code.
(defun kill-at-point ()
"Kill the quoted string or the list that includes the point"
(interactive)
(let ((p (nth 8 (syntax-ppss))))
(if (eq (char-after p) ?\")
(progn
(goto-char p)
(kill-sexp))
(progn
(up-list)
(let ((beg (point)))
(backward-list)
(kill-region beg (point)))))))
(global-set-key (kbd "C-,") 'kill-at-point)
Any suggestions to improve it are welcome.
Rather than rely on font-lock, you can use the underlying parser's data. The start of the string around point (if any) is available as (nth 8 (syntax-ppss)). You can then use (forward-sexp 1) to jump over the string to find its end.
You can find the bounds of a property with previous-property-change and next-property-change. For example:
(defun kill-by-property (arg)
(interactive "d")
(kill-region
(previous-property-change arg nil (point-min))
(next-property-change arg nil (point-max))))
Building off of Stefan's suggestion of using syntax-ppss, the following should do the trick
(defun kill-string ()
(interactive)
(let ((string-start (nth 8 (syntax-ppss))))
(goto-char string-start)
(kill-sexp)))
It uses (nth 8 (syntax-ppss)) to find the beginning of the string, jumps there, then uses the built-in kill-sexp to kill the s-expression at point (in this case, the string we want gone). No need at all for any kind of region calculation on your part.

Emacs should set the second character of a word in lower case

In most cases I'm writing german texts. Most words start with an uppercase letter followed by lower case letters. Sometimes I'm typing too fast and also the second letter of a word is typed upper case. To work around this issue I asked myself if it is poosible to write a function which automatically changes the case of the second letter. Optional this should only happen if the third and following are in lower case. Do you know if this is possible and do you have any suggestions?
Here's an 'always on' version that fixes as you type. It will let you type all uppercase words, but as soon as it detects mixed case it will capitalize.
(defun blah (s e l)
(let ((letter (string-to-char (word-before-point))))
(if (and (eq letter (upcase letter))
(not (eq (char-before) (upcase (char-before)))))
(capitalize-word -1))))
(add-to-list 'after-change-functions 'blah)
Here's a command that will convert to lowercase the second letter of each word if the first letter is uppercase and all other letters in the word are lowercase:
(defun fix-double-uppercase-at-start-of-words ()
(interactive)
(let ((case-fold-search nil))
(save-match-data
(while (re-search-forward "\\b\\([[:upper:]]\\)\\([[:upper:]]\\)\\([[:lower:]]*\\)\\b" nil t)
(replace-match (concat (match-string 1)
(downcase (match-string 2))
(match-string 3))
t)))))
The command will work on all words from the current cursor position to the (visible) end of the buffer.
You could setup a minor mode mapping all upcase characters to special input function.
See:
http://gist.github.com/516242

(re)number numbered lists in emacs (muse)

suppose I have a text list in emacs like this:
a
b
c
...
d
Is there a way to assign numbers to those items in Emacs, by selecting the region? End results should look like:
1. a
2. b
3. c
j. ...
n. d
Thanks.
The way I do this, which may not be optimal, is to use regex search and replace. This, of course, requires that you be able to define a regex to match the start of the lines you want numbers on. Taking your example, I'd use a search regex like this:
\([a-z]\)
note the capturing brackets, we'll need that first letter soon. And a replace regex like this:
\#. \1
where:
\# is a special form which is replaced, by Emacs, by the right number (though see the warning below);
. writes a stop; and
\1 writes a space and the captured group.
WARNING: Emacs will number your items 0, 1, 2, .... Until someone posts to tell us how to start at 1, I always insert a dummy 0th element before the edit, then delete it.
You can use the Emacs Keyboard Macro Counter.
Put the cursor one line ABOVE your list.
Start a macro: F3
Insert the counter value: C-x C-k C-i. A 0 will appear
Insert the DOT and a space: .
Move the cursor to the next line
Stop the macro: F4
Select your list
M-x apply-macro-to-region-lines
You can delete the 0 you added on the top and enjoy :)
NOTE: This will create a numbered list. It will not use letters.
A much simpler way is to use the CUA library's advanced rectangle editing commands. CUA is included in Emacs (at least 23.1, I think it's in earlier versions as well), so there isn't any new code to get.
You can use cua-set-rectangle-mark (bound to C-Return by default) to start a rectangle, and then use cua-sequence-rectangle to insert increasing values. It also gives you control over the format and starting value, so there is a lot of flexibility.
As an aside, CUA is primarily designed to make Emacs operate more like standard text editors (with C-c for copy, C-v for paste, etc), but it also includes some unrelated niceties, like rectangle editing. Don't ask me why :). If you want to use the rectangle editing without enabling the CUA keybindings (which is what I do), set cua-enable-cua-keys to nil, which can be done via customize.
(defun number-region (start end)
(interactive "r")
(let* ((count 1)
(indent-region-function (lambda (start end)
(save-excursion
(setq end (copy-marker end))
(goto-char start)
(while (< (point) end)
(or (and (bolp) (eolp))
(insert (format "%d. " count))
(setq count (1+ count)))
(forward-line 1))
(move-marker end nil)))))
(indent-region start end)))
Here's some elisp code to do it; would be easy to customize if you like tinkering.
This will number the current region (unless it is already numbered), and also the last line binds to the M-n keys. You could use a function key "[F6]" as needed.
Modified to take a format string to use. The default is 1. but you could do something like %d) to get a bracket instead of a . and so on.
(defun number-region(fmt)
(interactive "sFormat : ")
(if (or (null fmt) (= 0 (length fmt)))
(setf fmt "%d. "))
(save-excursion
(save-restriction
(narrow-to-region (point) (mark))
(goto-char (point-min))
(let ((num 1))
(while (> (point-max) (point))
(if (null (number-at-point))
(insert (format fmt num)))
(incf num)
(forward-line))))))
(global-set-key "\M-n" 'number-region)
Not a direct answer to your question, but if you find yourself manipulating numbered lists frequently, you may want to look into org-mode. In particular, the section on plain lists.