Interaction between transient-mark-mode and cua-mode?

173 views Asked by At

I'm writing some custom functions to move the point in specific ways, and I'm running into issues to manage the mark & region properly. For illustration purposes, here are a few lines of codes which don't do much really, they merely bind the [home] key to a custom function that checks if the mark is already active or not - if not it temporarily enables transient-mark and sets the mark. In all cases it then calls 'beginning-of-line' as you expect.

(defmacro setq-local (var val)
  (list 'set (list 'make-local-variable (list 'quote var)) val))

(defun my-beginning-of-line ()
  (interactive)

 (message "entering my-beginning-of-line: transient-mark-mode = %s" transient-mark-mode)

  ; Straight from "handle-shift-selection" in emacs 25.2
 (unless (and mark-active (eq (car-safe transient-mark-mode) 'only))
    (setq-local transient-mark-mode (cons 'only (unless (eq transient-mark-mode 'lambda) transient-mark-mode)))
    (push-mark nil nil t))

  (beginning-of-line)

  (message "exiting my-beginning-of-line: transient-mark-mode = %s\n" transient-mark-mode))

(global-set-key   [home]           'my-beginning-of-line)

So now let's consider two scenarios:

  1. [home] - any non-shifted cursor motion keys - [home]
  2. [home] - any shifted cursor motion keys - [home]

In emacs 24.4 and later versions, everything behaves as I expect:

  1. The first occurence of [home] temporarily enables transient-mark (transient-mark-mode = (only . OLDVAL). The mark is then deactivated by any unshifted cursor motion command, and transient-mark-mode is restored to OLDVAL as can be observed in the subsequent invocation of [home]
  2. The difference is that the shifted cursor motion keys leave the mark active and transient-mark temporarily enabled. On the last occurence of [home] it can still be observed that transient-mark-mode = (only . OLDVAL) when entering my custom function

Now, in emacs 24.3 and earlier versions, I still get the same behaviour when cua-mode is disabled. But when cua-mode is enabled, something that I don't understand is going on in scenario #2. In this case there seems to be some interaction, and that something (CUA ?) deactivates the mark and restores transient-mark-mode to OLDVAL. Can anyone explain what happens, and possibly even better, how to write my custom function so that it has the desired behaviour in all circumstances ? (emacs 24 or 25, cua-mode enabled or not)

1

There are 1 answers

0
DaveC On

I believe I have the beginning of an answer. There are two problems apparently.

The first one has to do with the implementation of cua--post-command-handler-1 in emacs 24.3 and earlier, which contains this:

  ;; Disable transient-mark-mode if rectangle active in current buffer.
  (if (not (window-minibuffer-p (selected-window)))
      (setq transient-mark-mode (and (not cua--rectangle)
                     (if cua-highlight-region-shift-only
                     (not cua--explicit-region-start)
                       t))))

The second problem is general to 'cua-mode': when enabled it seems to change 'shift-select-mode' to 'nil' (in emacs 24.3 and earlier). Manually forcing 'shift-select-mode' to t after enabling cua-mode does not seem to be a viable option though, as the usual shift-selection (without my custom [home] involved at all) is completely screwed up in this case.

Although I can vaguely understand why things don't work, I am still totally unclear how to write custom functions in my .emacs that can work with versions 24.3 as well as 24.4