0

moving point command: next-line, previous-line, forward-char, backward-char, etc.

How to omit Ctrl key in read-only-mode?

How can I combine with read-only-mode-hook to automatically enable keybind when opening a file with read-only permissions?

  • Here is an example written Anton Johansson: by github.com/antonj/.emacs.d/blob/master/aj/… . Calling toggle-read-only will trigger his modifications assuming they have been evaluated prior thereto. Inasmuch as I knew what to look for after typing M-x find-function RET read-only-mode and perusing the code in simple.el, I Googled: emacs "read-only-mode" keymap. The link mentioned in this comment was just the first search result, so feel free to look at other results. – lawlist Sep 18 at 21:41
  • @lawlist The method of using Anton Johansson is not convenient. When opening a read-only buffer, you need to execute the M-x toggle-read-only RET keybind twice to take effect. And toggle-read-only is obsolete and should be replaced with read-only-mode. – dongli si Sep 18 at 23:13
  • As you become more proficient in Emacs, you can find examples that do things similar to what you want, and then you can modify them to suit your needs. I realize you are just starting out and this might seem daunting, but seeing what makes it tick and trying out new things is often a helpful learning experience. Sometimes you will get lucky and find something exactly on-point, but more often than not, you may need to create a custom solution that best suits your needs for a given project. – lawlist Sep 19 at 3:24
1

The following minor-mode wo-ctrl-c-mode frees all active keybindings from the control modifier insofar there are no other modifiers such as meta or shift and the resulting key-binding is not already occupied.

That minor mode is activated along with read-only-mode and when opening files without write-permission with find-file.

At least in Emacs 26.2 one needs to treat find-file separately since that function (more exactly find-file-noselect) sets the buffer-read-only flag directly and not through the function read-only-mode.

(defun wo-ctrl-c-map ()
  "Return a keymap freeing keys from control-modifier."
  (let ((newmap (make-sparse-keymap)))
    (mapc
     (lambda (map)
       (map-keymap
        (lambda (event binding)
          (let ((basic-event (vector (event-basic-type event))))
            (when (and (equal (event-modifiers event) '(control))
                       (equal (key-binding basic-event) #'self-insert-command)
                       (null (lookup-key newmap basic-event)))
              (define-key newmap basic-event binding))))
        map))
     (current-active-maps))
    newmap))

(defvar-local wo-ctrl-c-mode-active nil
  "If `wo-ctrl-c-mode' is active it sets this variable to a non-nil value.
This is a protection against consecutive calls of (wo-ctrl-c-mode 1).
The value is actually a list containing the original local map as element.")

(define-minor-mode wo-ctrl-c-mode
  "Bind all keys with control modifier also directly."
  :lighter " α"
  (if wo-ctrl-c-mode
      (unless wo-ctrl-c-mode-active ;;< protection against two consecutive calls of (wo-ctrl-c-mode 1)
    (setq wo-ctrl-c-mode-active (list (current-local-map)))
    (let ((map (wo-ctrl-c-map)))
      (set-keymap-parent map (car wo-ctrl-c-mode-active))
      (use-local-map map)))
    (when wo-ctrl-c-mode-active
      (use-local-map (car wo-ctrl-c-mode-active))
      (setq wo-ctrl-c-mode-active nil))))

(defun wo-ctrl-c-when-read-only ()
  "Activate `wo-ctrl-c-mode' when buffer is read-only."
  (if buffer-read-only
      (wo-ctrl-c-mode)
    (wo-ctrl-c-mode -1)))

(add-hook 'read-only-mode-hook #'wo-ctrl-c-when-read-only)

;; `find-file-noselect' sets `buffer-read-only' directly:
(add-hook 'find-file-hook #'wo-ctrl-c-when-read-only)

Tested with
emacs-version: GNU Emacs 26.2 (build 2, i686-pc-linux-gnu, GTK+ Version 3.22.30) of 2019-04-12

  • eval your lisp , result is "Wrong type argument: listp, wo-ctrl-c-map" – dongli si Sep 21 at 8:54
  • @donglisi Sorry about that. I added the quote at '(wo-ctrl-c-mode) afterwards. When I tested it again wo-ctrl-c-mode-map was already defined, the :keymap expression was not evaluated, and this caused the test to be wrongly positive. (I should have tested with a newly started emacs -Q instance). I've re-worked the solution such that it does not use the minor mode map but the local keymap. That improves using the minor mode for multiple buffers in read-only-mode. If one switches off wo-ctrl-c-mode the original local mode map is restored. – Tobias Sep 21 at 22:45

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.