2

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?

3

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?

1
  • 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
    Nov 28 '19 at 18:41
0

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)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.