2

How can I define a key to cancel selection only when I'm selecting something? Because I use this key to do other thing in global-mode-map.. Is there any specific mode for mark and selecting something? I just tried something like this but it didn't help.

(add-hook 'transient-mark-mode-hook
      (lambda()
        (local-set-key "a" 'deactivate-mark);;keyboard-quit also cant work
        (message "hello")
        )
      )
Yu Su
  • 111
  • 4

2 Answers2

3

The transient-mark-mode-hook is called when you enter/leave the Transient Mark Mode, which is enabled by default starting from Emacs 23. Only when it's enabled, setting the mark will activate it and highlight the region.

You could try the following code.

(defconst my-alist
  `((mark-active
     ,@(let ((m (make-sparse-keymap)))
         (define-key m (kbd "h") (lambda() (interactive) (message "hello")))
         (define-key m (kbd "q") (lambda() (interactive) (deactivate-mark)))
         (define-key m (kbd "s") (lambda() (interactive) (message (buffer-substring (point) (mark)))))
         m))))

(add-to-list 'emulation-mode-map-alists 'my-alist)
  • wow!!you're so cool, i never thought that i can get an answer here, – Yu Su Oct 24 '17 at 18:04
  • it works with other single keys, but not works with my "C-", im using this as a leader key in Evil Insert State, can you solve this? :D – Yu Su Oct 24 '17 at 18:14
  • Could you make sure that `my-alist` is the first element in `emulation-mode-map-alist`?. If not, you can try to move `my-alist` to the front of the `emulation-mode-map-alist` so only text properties can override the keymap now. For example: `(push 'my-alist emulation-mode-map-alists)` – heartnheart Oct 24 '17 at 18:35
  • you're right, my-alist is not the first element in emulation-mode-map-alist,i tried your (push xxxxx), but it didnt work, i tried this, (setq emulation-mode-map-alists (cons 'my-alist emulation-mode-map-alists)), still didnt work. – Yu Su Oct 24 '17 at 18:43
  • From the [evil-guide](https://github.com/noctuid/evil-guide), evil is trying to be top on that alist. So this method won't work for those keys already defined. Then as evil always gets the highest precedence, you can define keys in evil mode directly based on the state of region. – heartnheart Oct 24 '17 at 19:17
  • (define-key evil-insert-state-map (kbd "C-") (lambda () (interactive) (if (region-active-p) (message "Highligh mode") (message "evil mode") ))) – heartnheart Oct 24 '17 at 19:19
  • really appreciate for your help. your suggestion on evil doesnt work since C-SPC im using is as the evil-leader key. i worked out by temporarily turn off the evil, lol. – Yu Su Oct 24 '17 at 19:30
1

You can test whether there is an active selection of text using function region-active-p. C-h f region-active-p tells you:

region-active-p is a compiled Lisp function in simple.el.

(region-active-p)

Return non-nil if Transient Mark mode is enabled and the mark is active.

Some commands act specially on the region when Transient Mark mode is enabled. Usually, such commands should use use-region-p instead of this function, because use-region-p also checks the value of use-empty-active-region.

And C-h f use-region-p tells you:

use-region-p is a compiled Lisp function in simple.el.

(use-region-p)

Return t if the region is active and it is appropriate to act on it. This is used by commands that act specially on the region under Transient Mark mode.

The return value is t if Transient Mark mode is enabled and the mark is active; furthermore, if ‘use-empty-active-region’ is nil, the region must not be empty. Otherwise, the return value is nil.

For some commands, it may be appropriate to ignore the value of use-empty-active-region; in that case, use region-active-p.

So you would use one of these functions to test whether there is an active selection. If so then you can call quit (or whatever you want), and if not you can do what you would otherwise normally do.

BTW, it is a good idea to use a named command in a hook, instead of using an anonymous function (aka lambda form). (For one thing, it makes it easier to remove the function from the hook.)

Drew
  • 75,699
  • 9
  • 109
  • 225
  • Thanks. your idea seems to bind the key to test if a region is active first, then quit.But in my situation,im also using this key to do many other things.so ,if possible, i want to bind it to the specific text-selection mode map(if exists ,lol) – Yu Su Oct 24 '17 at 17:03