How do I prevent emacs from resolving directory symlinks in paths? - emacs

I have a project, call it 'foobar', that when I checkout has all its source in the folder "foobar/foobar". Because the top level foobar directory contains nothing except for the inner foobar directory, it's pointless, but that's how things were originally checked into the project and it's outside my control. This has the unfortunate effect of making paths longer and harder to read, so I rename the toplevel foobar to "foobar-checkout" and then make a symlink called "foobar" that links to "foobar-checkout/foobar". This way I can open "foobar/source.c" instead of "foobar/foobar/source.c".
This works for when I'm in the shell, and when I first open the file in emacs, but after that emacs will resolve the symlink. So if I have source.c open and I press Ctrl+x Ctrl+f to open a new file, the path it lists is "foobar-checkout/foobar/" rather than "foobar/". Is there a way to get emacs to not resolve the symlink so I can enjoy the shorter path?

I've just tried this on GNU Emacs 22.2.1, and it doesn't seem to resolve my symlinks. Is it possible that the resolving of symlinks is not vanilla emacs behavior and is rather something unintentionally introduced with a file opening module, such as ffap.el?
Either way, I couldn't test my idea, but it occured to me that you might override file-symlink-p, described currently as:
file-symlink-p is a built-in function in `C source code'.
(file-symlink-p FILENAME)
Return non-nil if file FILENAME is the name of a symbolic link.
The value is the link target, as a string.
Otherwise it returns nil.
This function returns t when given the name of a symlink that
points to a nonexistent file.
If you modify that to always return nil, perhaps emacs won't resolve the symlinks:
(defun file-symlink-p (FILENAME)
nil)
Of course, this will probably break some other stuff, but maybe it's worth a shot.

You might like to use directory-abbrev-alist or maybe vc-follow-symlinks.

Related

Path with a folder named tilde(~) can't be recognized by load-file in emacs

I have a folder /var/~/. In config .emacs I wanna load some files from this folder.
I try to use (load-file "/var/~/foobar.el"), but emacs alerts File error: Cannot open load file, ~/foobar.el.
Furthermore I couldn't even open the files under this folder with c-x c-f. In minibuffer the path will auto be redirected to my home.
How could I load files in that folder?
You need to rename your directory.
load-file is a simple wrapper around load, which passes the given file name through substitute-in-file-name. From the docstring of substitute-in-file-name (emphasis mine):
Substitute environment variables referred to in FILENAME. `$FOO' where FOO is an environment variable name means to substitute
the value of that variable. The variable name should be terminated
with a character not a letter, digit or underscore; otherwise, enclose
the entire variable name in braces.
If `/~' appears, all of FILENAME through that `/' is discarded. If `//' appears, everything up to and including the first of those `/' is discarded.
In other words, substitute-in-file-name throws away everything before /~, turning /var/~/foo.el into ~/foo.el.
I completely fail to see any reason in this behaviour, but it is what it is, and you cannot (easily) work around it, so renaming is your best way out of this dilemma.
It's a reasonable thing to do, anyway. Using ~ as directory name is bad idea on Unix systems generally, not just for Emacs alone.
lunaryorn explained your problem well, and I agree with his suggestion that not using ~ in file paths is the best solution. However, If you can't rename these paths for whatever reason, I believe you can work around substitute-in-file-name by loading a relative file path as documented here.
Basically, you need to add nil to your load-path variable, then set your default-directory variable to the troublesome path, finally then load the file using a relative name. e.g.:
; adding nil causes load to also search your 'default-directory'
(setq load-path (append '(nil) load-path))
(setq default-directory "/tmp/~/")
(load "foobar.el")
Note that if you suspect the file name might exist (be loaded from) elsewhere in your load-path you would need to ensure the file you want is first in the load-path.
See How programs do loading.

Emacs bookmark and accessing across different local path

When I bookmark a File in emacs, it has the full-path C:/WindowPath/CommanPath/File I can access the same directory from Linux with /LinuxPath/CommanPath/File. But, when I try to bookmark in one OS and access in other OS, the file-path are different and I cannot access the same file from M-x list-bookmark interface. How I can resolve this? Please note that the 'CommanPath' is same for both OS.
Is there something in bookmark library that I can use? If that is not the case, then how should I create shortcuts so it can work seamlessly in both OS, or for that matter in any path ?
Thanks.
Hm. How does Emacs find the same file starting with different absolute file names on different OS's? If you can track that down then you can likely make the bookmark code do the same thing. The bookmark just saves the absolute file name in the form of the OS you were using at the time you created the bookmark. Giving that to Emacs to find should be no different from giving it to find-file, which you say works.
(That is, I think that's what you're saying: you can type the Windows form of the file name at C-x C-f when on Linux and it just works, and vice versa.)
The basic file-finding function is find-file-noselect, but all it seems to do in this regard is (abbreviate-file-name (expand-file-name FILENAME)), which would not be sufficient if given FILENAME as an absolute name from the wrong file system.
If you cannot figure out how to code this generally, you might be able to use directory-abbrev-alist to make your own explicit correspondence between the two directory prefixes. Dunno.
Interesting question.

Emacs and cscope with multiple directories

How do I set up cscope in Emacs when my source code lives in multiple directories?
Say I have several paths for my C++ project:
/path/to/my/code (and subdirectories)
/path/to/other/code (and subdirectories)
/path/to/static/linking/include/files (and subdirectories)
/path/to/static/linking/lib/files' (and subdirectories)
I would like to use xcscope to navigate/look up symbols in my code and the library that I am linking to.
The instructions for xcscope.el say that I should first run C-c s (Cscope->Create list and index) at /path/to/my/code, but I am then confused about how I to have the other paths indexed by cscope.
The documentation says I should go to the other directories and run cscope -b, but what I am supposed to do after that?
I looked at the cscope.files file that C-c s built. I think I am supposed to add my other paths to this file, but this file includes a list of source code files (not directories).
Do I have to manually edit cscope.files to add every single file that I want to index that is outside of my project's root directory?
The documentation is confusing.
I got one sol'n from http://cscope.sourceforge.net/large_projects.html. Still confusing.
cscope.files is aptly named. It is NOT directories. It is files, only files. Which is as daunting as it sounds. What if you have hundreds of files. Then you have to write hundreds of lines, one per file, into cscope.files. No joke.
Automate it with some scripting. E.g., on linux, use bash scripts and redirection (>,>>,|) operators to select and filter files from any and all directories into that cscope.files.
What about the directory where cscope.files resides? IF you don't include those files, it'll only find them when you open your project (in emacs, but probably applicable to any IDE) in that source directory. So, include them, too, for easy opening of your project from anywhere.
The option "recursive/-R" seems obvious to send to cscope-indexer. Nope, not with many root directories. Does nothing (probably could do something with scripts or elisp or who knows). Just feed those files, absolute path, into cscope.files. And you might have to make sure you have only one cscope.files per project. Don't split them up relative to each diretory. Or maybe you can, something to look into.
Remember, include the /path/to/each/file/ before the file if you want cscope.files to point to it from anywhere. cscope isn't "smart", it's dumb, it just takes directions for where to look and it won't know where to look for "filename", without knowing where it is. You're just asking it to call locate filename, which it can't do anyway, when you give it a lonely filename without a dir path outside of the directory that a particular cscope.files resides.
I hope there's a way to use xcscope inside emacs, just adding directories which it will catalog and index, as the xcscope docs and emacs menu suggest. But I didn't succeed in making it work that way.
Wouldn't a soft link (ln -s) work? Worked for me.

Handle parallel build error correctly in emacs compilation mode

When I'm using M-x compile to do parallel compilation with make -jn for a multi (level) dir project, when I got an error, I can't get to the correct place with next-error stuff. Emacs always goes to wrong directory for the problematic file. But I have no problem if I just do it without -jn.
next-error uses the text output of your compilation to determine where to go. But with parallel compilation, this text output can be corrupted, and even if it is not corrupted it can and often is ambiguous (think of one task compiling foo/bar and the other task compiling toto/titi, and the output looking like "entering directory foo; entering directory toto; error in bar:20; error in titi:69").
I can only think of the following ways to solve this problem:
structure your make files so that you never change directory (so all the file names are relative to the same current working directory).
change your make files so as to pass absolute file names to your compiler, so all the file names in error messages are absolute.
hack Emacs's compile.el so that when looking for "bar", it fetches it in all the directories that have been mentioned before.
This last change would probably be a good one (i.e. patch welcome), but note that it would still bump into problems if "bar" exists in both "foo" and "toto".
The other two changes can also still bump into problems because the output can also end up looking like "Entering directory foEntering directory toto; o;"; and I don't know what can be done to avoid this problem.

Can you Edit .jar/archive contents inline with emacs

I know you can navigate the contents of an archive with emacs. Is there a way you can edit those files in place and write the archive transparently?. Currently, I navigate into the archive, write the file to a temp directory, and the use the java jar command to add the file back into the archive. Its a little bit of pain.
P.S. I know there are few use cases where you'd want to do this, but I've inherited a platform that I can't readily modify where I have to cope with this limitation in the short term.
Yes, it just works. Did you try it?
I grabbed a jar file that contained a text file and some java code that would print it out. I edited the txt file within the .jar and saved the text file. It did exactly what I would expect.
EDIT- When saving the archive make sure you use C-x C-s
In emacs-23.2 (not 23.1 or 23.3) this doesn't "just work" on Windows due to a bug. Instead it just writes caution: filename not matched: "<internal path>.
One solution is to simply upgrade to 23.3.
To fix the bug in emacs-23.2, open $EMACS_HOME/lisp/arc-mode.el and replace:
(if (equal (car archive-zip-extract) "unzip")
(shell-quote-argument name)
name)
with:
name
and recompile:
M-x byte-compile-file $EMACS_HOME/lisp/arc-mode.el
This answer comes from the original emacs bug report.