Created
July 21, 2016 15:52
-
-
Save capitalist/4ce1bc673a3653e0ffff33350479ce12 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(defvar rotate-text-rotations | |
'( | |
("true" "false") | |
("def" "defp") | |
("if" "else" "unless") | |
("yes" "no")) | |
"List of text rotation sets.") | |
(defun rotate-region (beg end) | |
"Rotate all matches in `rotate-text-rotations' between point and mark." | |
(interactive "r") | |
(let ((regexp (rotate-convert-rotations-to-regexp | |
rotate-text-rotations)) | |
(end-mark (copy-marker end))) | |
(save-excursion | |
(goto-char beg) | |
(while (re-search-forward regexp (marker-position end-mark) t) | |
(let* ((found (match-string 0)) | |
(replace (rotate-next found))) | |
(replace-match replace)))))) | |
(defun rotate-string (string &optional rotations) | |
"Rotate all matches in STRING using associations in ROTATIONS. | |
If ROTATIONS are not given it defaults to `rotate-text-rotations'." | |
(let ((regexp (rotate-convert-rotations-to-regexp | |
(or rotations rotate-text-rotations))) | |
(start 0)) | |
(while (string-match regexp string start) | |
(let* ((found (match-string 0 string)) | |
(replace (rotate-next | |
found | |
(or rotations rotate-text-rotations)))) | |
(setq start (+ (match-end 0) | |
(- (length replace) (length found)))) | |
(setq string (replace-match replace nil t string)))) | |
string)) | |
(defun rotate-next (string &optional rotations) | |
"Return the next element after STRING in ROTATIONS." | |
(let ((rots (rotate-get-rotations-for | |
string | |
(or rotations rotate-text-rotations)))) | |
(if (> (length rots) 1) | |
(error (format "Ambiguous rotation for %s" string)) | |
(if (< (length rots) 1) | |
;; If we get this far, this should not occur: | |
(error (format "Unknown rotation for %s" string)) | |
(let ((occurs-in-rots (member string (car rots)))) | |
(if (null occurs-in-rots) | |
;; If we get this far, this should *never* occur: | |
(error (format "Unknown rotation for %s" string)) | |
(if (null (cdr occurs-in-rots)) | |
(caar rots) | |
(cadr occurs-in-rots)))))))) | |
(defun rotate-get-rotations-for (string &optional rotations) | |
"Return the string rotations for STRING in ROTATIONS." | |
(remq nil (mapcar (lambda (rot) (if (member string rot) rot)) | |
(or rotations rotate-text-rotations)))) | |
(defun rotate-convert-rotations-to-regexp (rotations) | |
(regexp-opt (rotate-flatten-list rotations))) | |
(defun rotate-flatten-list (list-of-lists) | |
"Flatten LIST-OF-LISTS to a single list. | |
Example: | |
(rotate-flatten-list '((a b c) (1 ((2 3))))) | |
=> (a b c 1 2 3)" | |
(if (null list-of-lists) | |
list-of-lists | |
(if (listp list-of-lists) | |
(append (rotate-flatten-list (car list-of-lists)) | |
(rotate-flatten-list (cdr list-of-lists))) | |
(list list-of-lists)))) | |
(defun rotate-word-at-point () | |
"Rotate word at point based on sets in `rotate-text-rotations'." | |
(interactive) | |
(let ((bounds (bounds-of-thing-at-point 'word)) | |
(opoint (point))) | |
(when (consp bounds) | |
(let ((beg (car bounds)) | |
(end (copy-marker (cdr bounds)))) | |
(rotate-region beg end) | |
(goto-char (if (> opoint end) end opoint)))))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment