4

In most modern editors, after canceling a selection by a left/right motion, the cursor will be moved to the beginning/end of the previously-selected region correspondingly. Similarly, if we cancel a selection by a up/down motion, the cursor will be moved up/down one line from the beginning/end of the previously-selected region correspondingly.

Could we have the same behaviors in Emacs under shift-select-mode?

I tried to define my own movement function:

(bind-key* "M-l" (lambda (arg) (interactive "^p") (if (use-region-p) (goto-char (region-end)) (syntax-subword-forward arg)))) 

But it doesn't work. The goto-char never run even if I am selecting a region. Is it because I used (interactive "^p")? Any solution?

1
  • I very much prefer Emacs's behavior: I especially don't like it when a selection extends past the edge of the screen and a motion command brings me to the invislble end. But of course each to their own preference. In case anybody wants this and is not aware: you can switch to the other end of the selection with C-x C-x. Thus, in shift selection mode, an unshifted motion command exits the selection at the end that you've been focusing on (moving the cursor), and you press C-x C-x first to exit the selection at the other end. Commented Oct 7, 2017 at 9:42

2 Answers 2

3

You can probably do something like

(defvar my-old-region-bounds nil) (advice-add 'handle-shift-selection :around (lambda (orig-fun) (let ((was-active (region-active-p))) (funcall orig-fun) (when (and was-active (not (region-active-p))) (setq-local my-old-region-bounds (cons (point-marker) (mark-marker))) (add-hook 'post-command-hook #'my-move-to-old-region-bound))))) (defun my-move-to-old-region-bound () (remove-hook 'post-command-hook #'my-move-to-old-region-bound) (let ((bounds my-old-region-bounds)) (kill-local-variable 'my-old-region-bounds) (when bounds (when (funcall (cond ((> (point) (car bounds)) #'<) ((= (point) (car bounds)) #'=) (t #'>)) (point) (cdr bounds)) ;; We moved towards the other (old)boundary. (goto-char (cdr bounds)))))) 

Of course, this is guaranteed 100% untested.

Edited by AhLeung: I tested it, and it works for most motion functions.

1

I found a solution, feel free to comment / improve.

(advice-add 'handle-shift-selection :before (lambda () (setq-local was-active (region-active-p)))) (bind-key* "M-l" (lambda (arg) (interactive "^p") (if (and was-active (not (region-active-p))) (goto-char (region-end)) (syntax-subword-forward arg) ))) (bind-key* "M-h" (lambda (arg) (interactive "^p") (if (and was-active (not (region-active-p))) (goto-char (region-beginning)) (syntax-subword-backward arg) ))) 

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.