2008-10-01 Useless Reversing Of Lines

Instead of offering something useful from my Emacs init file, let me offer a tiny piece of code the like we’d waste time on while reading [EmacsChannel ​#emacs]. It is in fact so useless that I won’t even bother to post it on the EmacsWiki. I find these little examples are useful for people trying to learn EmacsLisp, however.

EmacsWiki

How to do this transformation:

I like it    ti ekil I
(the pony) → (ynop eht)

Note:

1. The characters in a line are reversed.

2. Matching parenthesis are mirrored.

3. The order of lines remains unchanged.

Here’s the code:

(defun reverse-chars-in-region (start end)
  "Reverse the region character by character without reversing lines.
Use `reverse-region' to reverse the lines in the region."
  (interactive "r")
  (let ((str (buffer-substring start end)))
    (delete-region start end)
    (dolist (line (split-string str "\n"))
      (let ((chars (mapcar (lambda (c)
			     (or (matching-paren c)
				 c))
			   (reverse (append line nil)))))
	(when chars
	  (apply 'insert chars))
	(newline)))))

Interesting stuff used:

1. (interactive “r”) to fill start and end

2. split-string to split the string into a list of substrings

3. (append line nil) to split the line into a list of characters

4. matching-paren to translate ( into ) and the other way around

​#Emacs

Comments

(Please contact me if you want to remove your comment.)

hello alex,

in a more recursive style one could use something like :

(defun matching-char (char swap)
  (or (cdr (assoc char swap))
      (car (rassoc char swap))
      char))

(defun recrev (string &optional swap)
  (let* ((l (substring string -1 nil))
	 (c (matching-char l swap))
	 (s (substring string 0 -1)))
    (concat c (if (eq (length s) 1) (matching-char s swap)
		(recrev s swap)))))

then use it with

(recrev "(the pony)" '(("(" . ")")))   --->   "(ynop eht)"

– paul.r 2008-10-01 13:51 UTC