ChatGPT解决这个技术问题 Extra ChatGPT

Emacs and symbolic links

Say I have a symbolic link at /home/.bashrc that points to an actual .bashrc file somewhere else: /some/other/path/.bashrc that is under a git repository.

If I open /home/.bashrc in Emacs, it prompts me with:

Symbolic link to Git-controlled source file; follow link? (y or n)

I usually type y, since I want to edit the actual file. However, later on, if I do buffer-file-name Emacs returns /some/other/path/.bashrc, and not /home/.bashrc).

I would like Emacs to remember that the way I accessed this file was through a symbolic link.

In other words, I would like my symbolic links to be transparent to Emacs. Part of the reason is because I have several Emacs macros that depend on the path of the current file, and these macros think that I am working with a file located in /some/other/path and not in /home/.

How can I do this?


D
Daniel Ralston

When it prompts with

Symbolic link to Git-controlled source file; follow link? (y or n)

type n. Instead of following the symlink and directly opening the file that the symlink points to, emacs will use the symlink itself, as you desire.

A warning: doing this prevents emacs' version control features from detecting and interacting with the repository at the destination, if there is one.

If you'd like to change the default behaviour, check out the documentation of the vc-follow-symlinks customization variable. (C-h v vc-follow-symlinks)


If I answer 'no' and edit the file via the link, git status will correctly show that the file is modified, and shows the correct diff. What is this "bypasses the version control system"?
It means Emacs VC support will not be available: specific information like state and version and available actions/shortcuts.
S
ShreevatsaR

Just for completeness, for someone who has a question about

Symbolic link to Git-controlled source file; follow link? (y or n)

but doesn't necessarily want what the OP wants, this is the documentation from C-h v vc-follow-symlinks (as of my Emacs version — look up your own Emacs for details):

vc-follow-symlinks is a variable defined in vc-hooks.el. Its value is ask Documentation: What to do if visiting a symbolic link to a file under version control. Editing such a file through the link bypasses the version control system, which is dangerous and probably not what you want. If this variable is t, VC follows the link and visits the real file, telling you about it in the echo area. If it is `ask', VC asks for confirmation whether it should follow the link. If nil, the link is visited and a warning displayed. You can customize this variable.

The upshot is that to avoid being prompted each time, you can in your .emacs set either

(setq vc-follow-symlinks t)

to always follow the symlink (and edit the "actual" file directly), or

(setq vc-follow-symlinks nil)

to always edit the file as if it's at the symlink itself (this seems to work ok — it won't delete the symlink or anything — but it won't let you use version-control related stuff on the file). I prefer the former (unlike the OP).


R
Radon Rosborough

If you don't know or care about Emacs' vc package, just do

(setq vc-handled-backends nil)

which entirely disables vc as well as this annoying message about following symbolic links.

Then, you'll probably want to customize find-file-visit-truename depending on whether or not you want finding a file to follow symlinks or not.


A
Arne

If you have a use-case like I have, where I want to access only certain files with hotkeys without asking, you can use the file-truename function which resolves all symbolic links in the file and therefor prevents the annoying question without changing the default for everything else.

(global-set-key (kbd "<f7>") (lambda () (interactive)
  (find-file (file-truename user-init-file))))

Why not just let-bind find-file-visit-truename?
You mean (let ((find-file-visit-truename t)) (find-file user-init-file))? Well three reasons. First, it uses the dynamic scoping rules of elisp (I don't like that feature therefore I want to avoid it if I can). (find-file (file-truename user-init-file)) is at least as simple as the let bind. And last but not least, I did not know about find-file-sisit-truename.
Those are all perfectly reasonable reasons. I don't think you should be avoiding dynamic scoping, however. Use cases like this are exactly the reason why dynamic scoping is useful. Note, by the way, that even if you enable lexical scoping, then declared variables will still be dynamically scoped, allowing you to gain the full advantage of dynamic scoping without any of the downsides.