DEV Community

WammKD
WammKD

Posted on

The Emacs Trick Which Will Save Your Time and Nerves

Alright; for those who read dev.to regularly, it may already be obvious that my title is derived from a particular other post (not to mention it being listed as one of the top 7 posts of the last week).

But it reminded me of a problem I'd run into oh so often when using Emacs (probably for anyone who uses a text editor), one that I'd recently found a very satisfying solution to.

For those who hadn't read the article, you may be doing some maintenance on some files; you'll probably notice immediately since you'll find that the file is read-only but, even if you give this no second thought and make it so you can edit the file, you'll be greeted, when you go to save, with

File apg.conf is write-protected; try to save anyway? (yes or no)
Enter fullscreen mode Exit fullscreen mode

And – if you think to yourself, "Yes! Of course I do!" and slam out a yes – you'll be greeted with

Doing chmod: Operation not permitted
Enter fullscreen mode Exit fullscreen mode

You need sudo but who wants to remember to do that every time?

Now, there's been a widespread, instant solution for, at least, as long as I've looked for a solution – it involves the incredible Tramp package and instantly invokes sudo when trying to save a file Emacs doesn't have permissions for.

Recently, I found that, once saved, subsequent saves warn the user that the file has recently been edited (from your past save) and are you sure you want to save?

Needless to say, this can become irritating quite quickly.

Enter a Second Solution!

Thankfully, there's a really simple solution and it gets invoked the second you turn off read-only mode instead of waiting all the way until you save: one single action indicating a desire to take responsibility for this file when you indicate you want to.

First, define some advice for read-only-mode (code gotten from this blog with slight tweaks from me):

(defadvice read-only-mode (after read-only-mode-sudo activate)
  "Find file as root if necessary."
  (when (and (buffer-file-name) (not (file-writable-p (buffer-file-name))))
    (let ((p (point)))
      (find-alternate-file (concat "/sudo:root@localhost:" buffer-file-name))
      (goto-char p))))
Enter fullscreen mode Exit fullscreen mode

This simply tells read-only-mode that, when activated, check that the buffer has a name and, if so, is the file not able to be written to.

If so, grab the point of the cursor, open a new file (really, the same file but with sudo via Tramp), and then go the point we saved since, reopening the file, the cursor would be at the beginning of the file, otherwise.

Simple enough.

However, I quickly found that I ran into a new problem – attempting to open a new file assumed that we should stay using sudo: definitely not an assumption I wanted made, by default, for other files.

So I whipped up a function to replace the find-file function (while using it to avoid departing from standard behavior too terribly):

(defun find-file-no-sudo ()
  (interactive)

  (find-file (read-file-name
               "Find file: "
               (if (string-match "^/sudo:root@localhost:" default-directory)
                   (substring default-directory 21)
                 default-directory))))
Enter fullscreen mode Exit fullscreen mode

Basically, – if there's the text necessary to use sudo via Tramp at the beginning – strip it out!

Now, to make sure we use this where we used the old function…

(global-set-key (kbd "C-x C-f") 'find-file-no-sudo)
Enter fullscreen mode Exit fullscreen mode

And that's it!

Throw all of the above in your init file and you're good to go.

Next time you find yourself with a file you wanted to edit but didn't open with sudo, just do C-x C-q and you'll prompted for your password; then edit to your heart's content.

Top comments (0)