Leave region selected after emacs operation - emacs

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

Related

how to update evaluation result comments of Emacs Lisp forms easilly

Say I have this code which shows usage examples of mapcar
(mapcar #'1+ (list 10 20 30)) ; ⇒ (11 21 31)
(mapcar (lambda (it)
(* 2 it))
(list 0 1 2 3))
;; ⇒ (0 2 4 6)
(require cl-lib)
(cl-mapcar #'+
'(1 2 3)
'(10 20 30))
;; ⇒ (11 22 33)
I may be keeping that code somewhere written so that I can use it on a tutorial or so that whenever I forget how mapcar works, I can quickly read the code.
Now suppose I want to update some of the examples in the code. For example, I may change (list 0 1 2 3) in the second example to some other list. Right after I change the example, the corresponding result comment is then outdated. The result comment need to be updated as well. So I evaluate the form, copy the result, and replace the old result in the comment with new result. Is there a package I can use to help me do that all easily and less tediously? This is a different problem than problems that the litable or ielm package solve because this is simply about updating existing example code.
Right now what I use is:
(defun my-insert-eval-last-sexp ()
(interactive)
(let ((beg (point)))
(let ((current-prefix-arg '(4)))
(call-interactively 'eval-last-sexp))
(goto-char beg)
(if (looking-back ")")
(insert " ; "))
(insert "⇒ ")
(move-end-of-line 1)))
which still isn't enough because it simply adds the result comment rather than updating an old one, and has a bug of odd stuff getting inserted when the form evaluates to a number:
(+ 1 2)
;; ⇒ 3 (#o3, #x3)
Well, I'm not sure I want to encourage this kind of thing ;-), but this will get you a little closer to what you are trying to do, IIUC:
(defun my-insert-eval-last-sexp ()
(interactive)
(let ((this-command 'eval-print-last-sexp))
(save-excursion (eval-last-sexp-1 t)))
(when (looking-back ")") (insert " ; "))
(insert "⇒ ")
(move-end-of-line 1))
You don't need to save point and then explicitly go back to it --- use save-excursion.
You don't need to bind the prefix arg and call the command interactively. Just call it (or its helper function) directly, passing the arg you want.
You need to tweak the behavior to prevent it from thinking this is the second occurrence of the command, which is what causes it to print the octal etc. number info. The let binding does that (but is an ugly little hack).
Respective thing your function does is implemented in org-mode, i.e. org-babel.
See in Info, Org Mode, 14 Working with source code

emacs lisp and c-mode: when am I in a comment region

I'd like to search for regular expressions within a c/c++ buffer, but I want to avoid expression matching a comment region. Is there a way using the c mode to know if a bunch of text is within a comment region (or a point is within a comment region)?
The way to figure that out is with syntax-ppss which works in C/C++ and most major modes. E.g. (null (nth 8 (syntax-ppss))) will be non-nil if and only if you're not within a string-or-comment.
(defun re-search-forward-not-in-comment (regexp)
"Search forward first regexp not inside a comment. "
(interactive
(list (read-from-minibuffer "Regexp: ")))
(while (and (re-search-forward regexp nil t 1)
(and (nth 8 (syntax-ppss))(nth 4 (syntax-ppss))))))

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.

Shift a region or line in emacs

I'm looking for a way in emacs to shift text to the right or to the left by n spaces. A similar functionality that it in vim << or >>. It should work on a region or if no region is selected on a current line and not move the cursor from its current location.
The solution from EmacsWiki does not work very well as the M-x indent-rigidly since it somewhat remembers the last region used and shifts that one instead. The closest seems to be the one here but I did not managed to make it work. I'm not a lisp developer so it's difficult to modify the code. I will appreciate any help.
Thanks!
You could select the region then C-u C-x <tab> will shift 4 spaces. You can type a number after C-u to change 4 to anything else.
Maybe this works the way you want.
(defun shift-text (distance)
(if (use-region-p)
(let ((mark (mark)))
(save-excursion
(indent-rigidly (region-beginning)
(region-end)
distance)
(push-mark mark t t)
(setq deactivate-mark nil)))
(indent-rigidly (line-beginning-position)
(line-end-position)
distance)))
(defun shift-right (count)
(interactive "p")
(shift-text count))
(defun shift-left (count)
(interactive "p")
(shift-text (- count)))
To achieve this I usually do a trick:
activate CUA mode
go to the beginning of line
C-RET, now if you move the cursor you should see a rectangular red region
Move the cursor down the lines and type space until you've obtained the correct shifting.
This can be done also programmatically in some way (in the same way).
EDIT:
I've just read the article in emacs wiki, it's the same solution except for the CUA mode that is infinitely more powerful than the "common" rectanguar selection (since it's visual).
As I use Evil (with Spacemacs), the Vim-like region shifting is already implemented in visual mode with S-v and </> properly.
I'm mostly using hybrid-mode though, and when it's active I also want to be able to shift the region, preferrably by the current language's shift-width.
To achieve this, here's an implementation that re-uses evil's shifting, but does it "properly" in hybrid-mode.
(defun jj/shift-text (beg end shift-block-fun shift-line-fun)
"shift text in region or line using evil like S-v with < and > do in Vim.
It takes special care of preserving or even extending the region to the moved text lines."
(if (use-region-p)
(progn
(let ((point-at-end (< (mark) (point))))
;; fix up current region end to grab the whole line
(if point-at-end
(end-of-line)
(beginning-of-line))
;; then fix up the other region end
(exchange-point-and-mark)
(if point-at-end
(beginning-of-line)
(end-of-line))
;; restore mark-point order
(exchange-point-and-mark)
(let ((linebeg (if point-at-end (mark) (point)))
(lineend (if point-at-end (point) (mark))))
;; shift the text
(save-mark-and-excursion
(funcall shift-block-fun linebeg lineend)
;; "In Transient Mark mode, every buffer-modifying primitive sets deactivate-mark"
;; but we wanna keep it active :)
(setq deactivate-mark nil)))))
(funcall shift-line-fun 1)))
(defun jj/shift-left (beg end)
(interactive "r")
(jj/shift-text beg end #'evil-shift-left #'evil-shift-left-line))
(defun jj/shift-right (beg end)
(interactive "r")
(jj/shift-text beg end #'evil-shift-right #'evil-shift-right-line))
and where your keybindings are defined:
;; text shifting. evil-normal-state-map has these anyway.
(define-key evil-hybrid-state-map (kbd "M-<") #'jj/shift-left)
(define-key evil-hybrid-state-map (kbd "M->") #'jj/shift-right)

(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.