5

I end up looking at source files of packages I have installed fairly often and want to avoid accidentally editing them while I am viewing them. After looking at https://emacs.stackexchange.com/a/3681/767, I put together this:

(dir-locals-set-class-variables 'emacs '((nil . ((buffer-read-only . t) (show-trailing-whitespace . nil) (tab-width . 8) (eval . (whitespace-mode -1)))))) (dir-locals-set-directory-class (concat user-emacs-directory "elpa") 'emacs) (dir-locals-set-directory-class (locate-dominating-file (locate-library "winner") "lisp") 'emacs) 

This worked fine until I went to install a new package. At that point, the machinery kicks in to create autoloads and then fails to write them because they are considered to be read-only.

I suspect I could do something with defadvice but maybe my whole approach needs to be rethought. Has anyone else already solved this?

3
  • 1
    You can also use C-x C-q to change a buffer's read-only status. (And there's always undo ;-).) Commented Dec 17, 2018 at 18:27
  • 2
    Please M-x report-emacs-bug about the failure to install packages with such a config. Commented Dec 17, 2018 at 19:13
  • The package hardhat can help here, too. Commented Dec 21, 2018 at 21:39

3 Answers 3

3

I worked around this before by making an exception for autoloads. From my config:

(define-derived-mode emacs-lisp-autoloads-mode emacs-lisp-mode "Autoloads" "Marker mode for package autoloads files.") (add-to-list 'auto-mode-alist '("autoloads\\.el\\'" . emacs-lisp-autoloads-mode)) (add-to-list 'auto-mode-alist '("loaddefs\\.el\\'" . emacs-lisp-autoloads-mode)) (dir-locals-set-class-variables 'read-only '((nil . ((buffer-read-only . t))) ;; Keep autoloads writeable so we can update packages (emacs-lisp-autoloads-mode . ((buffer-read-only . nil))))) 

This defines a mode for autoloads and associates it with the typical file names. Then the dir-locals class sets the buffer to read-only, except for buffers in emacs-lisp-autoloads-mode. You can associate this 'read-only class with your elpa directory as you were doing before.

4

Adding following hack, which temporarily inhibits read-only-mode, is working for me:

(advice-add 'package-install-from-archive :around (lambda (orig-fun &rest args) (let ((inhibit-read-only t)) (apply orig-fun args)))) 

The full relevant config looks like:

(dir-locals-set-directory-class (concat user-emacs-directory "elpa") 'emacs) (dir-locals-set-directory-class (locate-dominating-file (locate-library "winner") "lisp") 'emacs) (advice-add 'package-install-from-archive :around (lambda (orig-fun &rest args) (let ((inhibit-read-only t)) (apply orig-fun args)))) 
3
  • What about just let-binding inhibit-read-only ? Commented Dec 18, 2018 at 0:56
  • Sounds even better than what I came up with. I’ll give it a try tomorrow! Commented Dec 18, 2018 at 1:43
  • inhibit-read-only worked great, I have updated the the answer with that, thank you! Commented Dec 18, 2018 at 16:28
0

I think your config is sound. Too bad it trips up package.el. While waiting for this to be fixed, you can try the following instead:

(add-hook 'find-file-hook #'my-find-file-tweaks) (defun my-find-file-tweaks () (when (and (file-in-directory-p buffer-file-name "~/.emacs.d/elpa") (not delay-mode-hooks)) (read-only-mode 1))) 

where the (not delay-mode-hooks) test is an ugly hack that tries to detect the case where package.el generates the autoloads.

1
  • I don't understand how this hack is intended to work, but I gave it a try and I got the same failure (about trying to modify a read-only buffer). Commented Dec 17, 2018 at 22:20

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.