mle
mle copied to clipboard
Buffers are written to the current working directory
Not sure if this is considered a bug or not but I think it's odd.
Given a directory structure like follows
~/example $ tree
.
└── subdir
1 directory, 0 files
If I write a file named test.txt
in the root directory and then do C-b
and enter the subdir
directory, followed by switching to test.txt
buffer by doing C-\
and hitting C-s
again. The file is now saved into the subdir
directory as a new file, not to the original location.
Good call @KevinSjoberg. This behavior feels natural to me only because I know under the hood that browsing (C-b
) into a directory is a plain chdir(2)
call which changes the cwd of the entire process. However I agree the example you give feels wrong.
Some potential solutions...
-
Every time
buffer_t.path
is set,realpath(3)
it intobuffer_t.path_absolute
and use that for all file operations. Save-as would be a little more complicated because we'd have to build a new absolute path. -
Maintain a dirfd for each buffer and use
openat(2)
instead offopen(3)
when saving the file. Maybe more elegant than above but has the downside of costing an fd for each open buffer which potentially runs us into system rlimit if you have a lot of buffers open. -
Similar to above, maintain a cwd string for each buffer and
chdir(2)
before all file operations ifbuffer_t.cwd != getcwd()
. Does not cost an fd but feels bad.
Any other ideas? Leaning toward option 1.
Since you are saving files using (original) file names (as opposed to original file descriptor), option 1. seems to be the most sensible among your propositions.
But relying on the realpath() invoked only at the opening time would introduce potential mismatches, eg there could be a symbolic link somewhere on the path that changes after opening.
In 3253070 I implemented a 4th option not described above:
Avoid chdir
entirely and maintain a bview_t.browse_path
variable used by cmd_browse
. When entering a directory via cmd_browse
, we append to browse_path
. Right before executing tree
we cd into browse_path
. That happens in a forked shell so the cwd of the editor process is unchanged. When selecting a file via cmd_browse
, we prepend browse_path
.
The downside is that file paths can get kind of verbose if you're using cmd_browse
to go up and down directories. For example if I repeatedly browse into a subdir a
followed by going up a directory, then finally open a file, the path will look like a/../a/../a/../a/../a/../test
.
Surely there's a way to collapse a relative path into its most succinct form, but I don't see anything in libc that does exactly that. (Please share if I'm missing something.) realpath
ing everything with some sort of display logic to only show the portion after cwd is another option, however it may be tricky to get right with symlinks. Leaving it alone for the time being.
I would write a simple "shortener" for those paths, you would avoid getting over MAX_PATH for some cases then.
I also see nohing in standard C lib for that.