mhayashi1120 / Emacs-wgrep

Writable grep buffer and apply the changes to files

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

request for a hook to deal with read-only files

emacs18 opened this issue · comments

wgrep is wonderful, but it does not seem to handle read-only files too well.
I would like to propose adding a hook of some sorts to wgrep to deal
with files that are read-only due to it being under version control systems
that require a "check out" step to make it writable.
The hook would be called when wgrep detects that a file is read-only.

Let me illustrate my point via a temporary solution that I came up with.

(defun my--advice-p4-edit-as-needed (file)
  "Call \\[p4-edit] for FILE if it is under perforce version
control and it has not yet been checked out."
  ;; (p4-current-client) is used to tell whether the file is a perforce
  ;; file or not.
  (when (and (not (file-writable-p file))
             (fboundp 'p4-current-client)
             (p4-current-client))
    (with-current-buffer (find-file-noselect file) (p4-edit))))

(advice-add 'wgrep-get-file-buffer :before #'my--advice-p4-edit-as-needed)

What this does is to execute code above whenever wgrep-get-file-buffer
is called. If the file is read-only and it is under perforce, then
p4-edit is called on it to do "check out" which will make the file
writable.

If a hook variable was available in wgrep, then I probably could have
used it instead of using advice.

Thanks for a very useful package.

I don't think wgrep-begin-edit-buffer-hook will work, because it is too late. Here is the relevant call sequence:

| wgrep-finish-edit
  |--> wgrep-compute-transaction
  |----> wgrep-transaction-editing-list
  ...
  |------> wgrep-get-file-buffer
  ...
  |--> wgrep-commit-buffer

Note that wgrep-get-file-buffer is called before wgrep-commit-buffer.
As shown in the definition of wgrep-get-file-buffer below, error is
signaled if the file is writable, i.e., error is generated before even getting to
the new hook that you added.

(defun wgrep-get-file-buffer (file)
  (unless (file-exists-p file)
    (signal 'wgrep-error (list "File does not exist.")))
  (unless (file-writable-p file)
    (signal 'wgrep-error (list "File is not writable.")))
  (or (get-file-buffer file)
      (find-file-noselect file)))

Oh, I see.
Move `file-writable-p' check after the new hook.

You may need to change p4-edit' function to letbuffer-read-only' nil.