When transposing words, the cursor moves to the end of the word, how can the cursor be kept at the same location relative to the word?
2 Answers
What about
(defun ideasman42-transpose-words (arg) (interactive "*p") (let ((chars-to-word-end (let ((point (point))) (if (or ; cases to behave like plain transpose-words. (looking-at "\\>") (looking-at "\\(?:[ \t]*\n\\)*[ \t]*\\<") ) 0 (save-excursion (forward-word) (- (point) point)))))) (transpose-words arg) (backward-char chars-to-word-end))) as a start?
- I was hoping to avoid duplicating logic to delimit the word under the cursor, any mismatch in logic between this and forward-word's logic will cause bugs.ideasman42– ideasman422019-11-28 18:41:37 +00:00Commented Nov 28, 2019 at 18:41
This can be done by getting the boundaries under the cursor from thing-at-point, then using them to set the cursor after transposing the word.
Unlike regular transpose-word.
- The cursor stays on the same character of the word.
- When there is no word to transpose with, the cursor doesn't move and a message is printed.
(defun transpose-words--impl (arg) (let ((bounds (bounds-of-thing-at-point 'word))) (when bounds (let* ((pt-init (point)) (pt-end-of-word (cdr bounds)) (pt-offset (- pt-init pt-end-of-word)) (pt-transpose (save-excursion ;; Without this, the first character will move the previous word. (goto-char pt-end-of-word) (if (condition-case err (progn (transpose-words arg) t) (message err)) (+ (point) pt-offset) nil)))) (when pt-transpose (goto-char pt-transpose)))))) (defun transpose-words-backward () (interactive) (transpose-words--impl -1)) (defun transpose-words-forward () (interactive) (transpose-words--impl 1)) Use with evil mode for eg:
(define-key evil-normal-state-map (kbd "C-M-l") 'transpose-words-forward) (define-key evil-normal-state-map (kbd "C-M-h") 'transpose-words-backward)