[vim/vim] feature: &autochroot (Issue #16070)

57 views
Skip to first unread message

Enno

unread,
Nov 16, 2024, 8:48:03 AM11/16/24
to vim/vim, Subscribed

Currently &autochdir changes the current working directory to that of the opened file.
At least equally useful would be a variant to change to that of its Git root (next parent directory containing a .gitfolder) instead (as it's often the project root directory).
There are many plug-ins to this end, but a built-in option can achieve this more robustly.
In fact, some plug-ins, say LSPs, implicitly assume that Vim is opened in the project root dir to work fine;
such an option would make them work more reliably (though of course final duty is on the plug-in author).

If that sounds sensible and need arise, then root markers of other version control systems such as Bazaar, Mercurial, ... could be taken into account.


Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/16070@github.com>

Christian Brabandt

unread,
Nov 17, 2024, 10:27:40 AM11/17/24
to vim/vim, Subscribed

Honestly, I am not sure this belongs into Vim. It sounds like a good use-case for a plugin.


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/16070/2481315903@github.com>

Shougo

unread,
Nov 17, 2024, 10:37:25 AM11/17/24
to vim/vim, Subscribed

This option might be useful, but like the autochdir option, it may conflict with the behavior of plugins, so it needs to be considered.


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/16070/2481319311@github.com>

Enno

unread,
Nov 17, 2024, 3:06:47 PM11/17/24
to vim/vim, Subscribed

Fair enough, it's hard to make it reliable, though it's a problem being solved again and again.

It would be more convenient to prepare a function to calculate the root directory rather than automatically changing the current directory.

This sounds like a great milestone.

I guess we can agree on this being a common use case to operate on a file with respect to its project dir, often the git root dir.

like the autochdir option, it may conflict with the behavior of plugins, so it needs to be considered.

Plug-ins can only set them by autocmd's. Too late if other autocmd's rely on the current work dir being the project root, leading to involved workarounds like postponing them to BufWinEnter ++once events.

I deemed this early firing to be an advantage of autochdir.


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/16070/2481512540@github.com>

Enno

unread,
Nov 19, 2024, 2:06:55 PM11/19/24
to vim/vim, Subscribed

a function to calculate the root directory

What about finddir('.git', getcwd(-1)..';') for starters?


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/16070/2486522061@github.com>

Shougo

unread,
Nov 19, 2024, 7:38:20 PM11/19/24
to vim/vim, Subscribed

Yes. But it should be implemented by core?


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/16070/2487051233@github.com>

Enno

unread,
Nov 19, 2024, 9:52:59 PM11/19/24
to vim/vim, Subscribed

Maybe a documentation entry about finddir('.git', expand('%')..';') will suffice to a great extent, as @chrisbra seems to prefer.

The implementation of the same functionality of fugitive.vim, which should be rather robust due to its larger user base,

https://github.com/tpope/vim-fugitive/blob/320b18fba2a4f2fe3c8225c778c687e0d2620384/plugin/fugitive.vim#L18

https://github.com/tpope/vim-fugitive/blob/320b18fba2a4f2fe3c8225c778c687e0d2620384/plugin/fugitive.vim#L18

plus helper functions, is more complicated though.

Yes. But it should be implemented by core?

Again I deemed the

early firing to be an advantage of &autochdir

in comparison to autocmd BufNew * ..., say.
Why does &autochdir exist if the same could be achieved by autocmds?


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/16070/2487235520@github.com>

Shougo

unread,
Nov 19, 2024, 10:53:10 PM11/19/24
to vim/vim, Subscribed

I don't know why autochdir exists...
I don't use the option, because it breaks other plugins behavior.


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/16070/2487338394@github.com>

Enno

unread,
Nov 19, 2024, 11:07:14 PM11/19/24
to vim/vim, Subscribed

Maybe @inkarkat has an idea (as suggest his replies at the exchange platforms)?


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/16070/2487364255@github.com>

Ingo Karkat

unread,
Nov 20, 2024, 4:01:16 AM11/20/24
to vim/vim, Subscribed

It would be more convenient to prepare a function to calculate the root directory rather than automatically changing the current directory. However, since detecting the root directory is inherently a difficult process, I'm not sure if it should be implemented in the core.

Although the vast majority today uses Git, I agree that this shouldn't be the only supported system. Under the premise that an 'autochroot' option is more robust than the current :autocmd-based plugin solutions (which I tend to agree with, although I'd like to see concrete proof of problems with the current approach), I would turn this into 'autochrootfunc'; i.e. a user-supplied function that is invoked and then returns the root directory (or empty string to disable). There could be a default $VIMRUNTIME/autoload/autochrootfunc/git.vim implementation, but users would be free to supply their own.


What about finddir('.git', expand('%')..';') for starters?

Better invoke git rev-parse --show-toplevel; it is possible to move the .git metadata away and there are subtle differences when Git submodules are used. (There's also git rev-parse --show-superproject-working-tree, and people may have different preferences as to what they consider their project root directory, reinforcing my point above that this needs to be configurable.)

I have written VcsRoot.vim for me (it's not yet a published plugin, but I've put it up on GitHub now); it supports lookup for Git, Mercurial, and Subversion so far.


I don't know why autochdir exists...

I mostly use a single instance of GVIM as a kind of IDE. I have multiple projects opened (usually in separate tab pages). The notion of addressing everything relative to the directory where Vim was launched doesn't make sense there, whereas opening files relative to the one that's currently active works really well. Most other GUI applications default to the previously used directory on File > Open (which is similar (though not identical) to 'autochdir'), so it's understandable that there's demand for such an option. I have set it, too.

So my Vim's native commands use file-relative addressing, which works very well for me; it's likely I'll open another Java file from the same package or another test, and there's no need to duplicate a possibly deep project hierarchy all the time. For those cases where I'll have to navigate to a completely different part of the project, I have :RootEdit, :RootSplit, etc., provided by my SpecialFileLocations.vim plugin (which relies on VcsRoot.vim for the root detection). The other client of VcsRoot.vim is my :RootTerminal command.


I don't use the option, because it breaks other plugins behavior.

Like the 'selection' option, this indeed has the potential to negatively affect plugins that are ignorant of it. I have submitted patches to all the plugins that I'm using. Once people are aware of it, it's not a big issue. I don't think this is an argument against a new 'autochroot', as 'autochdir' already exists, and if a plugin correctly handles the latter, the other should work, too.


I personally like 'autochdir' so much that I endured the few bits of plugin trouble that came with enabling it. I'd certainly give a 👍 to an 'autochroot' option (as long as it's extensible and not limited to Git), although I probably wouldn't enable it for myself. I prefer file-relative addressing with root-relative addressing supplied by my plugins.

If there's indeed demand for project-relative addressing, the discussed new option would be the best approach, as it's both more robust and also more discoverable than an external plugin. If that gets the related 'autochdir' out of its niche and increases awareness of plugin authors that they can't rely on a static current directory, I'd see this as a benefit overall.


Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/16070/2487945700@github.com>

Enno

unread,
Nov 20, 2024, 4:47:43 AM11/20/24
to vim/vim, Subscribed

I'd like to see concrete proof of problems with the current approach

For example, language servers (LS) use the current working directory on launch. This rather ought not to be $HOME (too many files to scan). Instead, mostly intended is a project root. Using autocmd's, one has to ensure they're fired in order. Of course one can solve this per plug-in, but since it's a common problem (for example, many LS plug-ins), how about a common solution?

git rev-parse --show-toplevel; it is possible to move the .git metadata away and there are subtle differences when Git submodules are used. (There's also git rev-parse --show-superproject-working-tree, and people may have different preferences as to what they consider their project root directory,

For starters, I thought of a simple criterion; usually submodules do not use .git folder markers. This is entering a rabbit hole. But to let the user decide, setting a .root marker should be possible.

whereas opening files relative to the one that's currently active works really well

Likely the files one opens are hierarchically close to the one opened, so that having the file's directory as a relative starting point is convenient.

I think the question was why the need for an option &autochdir was identified, when there are simple BufNew/Read autocmd's to, superficially, the same end.


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/16070/2488097870@github.com>

Ingo Karkat

unread,
Nov 20, 2024, 5:24:44 AM11/20/24
to vim/vim, Subscribed

I think the question was why the need for an option &autochdir was identified, when there are simple BufNew/Read autocmd's to, superficially, the same end.

Oh, I still remember that. Old versions of the help mentioned it:

'autochdir' 'acd'       boolean (default off)
                        {only available when compiled with the
                        |+netbeans_intg| or |+sun_workshop| feature}
        [...] This option is provided for
        backward compatibility with the Vim released with Sun ONE Studio 4
        Enterprise Edition.

So it was used for integration with a particular IDE, bound to special feature flags, not as a general-use feature. There's some more information in the history:

Sun Visual WorkShop has an "Editor of Choice" feature designed to let users
debug using their favorite editors. For the 6.0 release we have added support
for gvim. A workshop debug session will have a debugging window and an editor
window (possibly others as well). The user can do many debugging operations
from the editor window, minimizing the need to switch from window to window.

The version of vim shipped with Sun Visual WorkShop 6 (also called Forte
Developer 6) is vim 5.3. The features in this release are much more reliable
than the vim/gvim shipped with Visual WorkShop. VWS users wishing to use vim
as their editor should compile these sources and install them in their
workshop release tree.

I think they could have solved this via autocmds back then; I'd guess it was simply easier for the core Vim developers of the time to do this directly in the C code (i.e. their area of expertise)?!

However, around the same time (Vim 5.7), related plugins (CD.vim) appeared and VimTip 101 documented a simple autocmd for doing this. I myself also relied on autocmds as a fallback, as many distribution-provided Vim versions didn't have 'autochdir' compiled in (and I only started compiling Vim with custom features much later). That changed over time (the binary size difference became less of an issue), and Vim 8.1.0763 dropped the Sun Workshop support and turned 'autochdir' into a normal option.


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/16070/2488181936@github.com>

Enno

unread,
Nov 20, 2024, 5:50:17 AM11/20/24
to vim/vim, Subscribed

Okay, so these reads as if autocmds suffice; there is no inherent need of an option. As mentioned above, I deemed it crucial for ensuring the correct triggering order


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/16070/2488243715@github.com>

Enno

unread,
Nov 20, 2024, 6:24:45 AM11/20/24
to vim/vim, Subscribed

Maybe it still could be so as :help runtimepath reads, for example on Linux or Macos,

					Unix:  "$HOME/.vim or
						$XDG_CONFIG_HOME/vim,
						$VIM/vimfiles,
						$VIMRUNTIME,
						$VIM/vimfiles/after,
						$HOME/.vim/after"

So these autocmd's must be set by the user (and not by a built-in $VIMRUNTIME file, say) as soon somewhere at the beginning of her vimrc to ensure others can rely on the current work dir suitably set.


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/16070/2488320468@github.com>

Ingo Karkat

unread,
Nov 20, 2024, 6:35:37 AM11/20/24
to vim/vim, Subscribed

Assuming there's demand for this feature, I would not use autocmds. With the proposed new option, plugins can check :if &autochroot (and then presumably do counteractions like saving and restoring the current directory if necessary). A solution based on conventions and :autocmd would be much more difficult to detect.

A home-grown customization (with autocmds) can adapt to or even monkey-patch misbehaving plugins. With a built-in feature, plugins should observe and behave. What to use should be based on how much demand there is for the feature.


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/16070/2488343107@github.com>

ubaldot

unread,
Feb 6, 2025, 12:27:18 PMFeb 6
to vim/vim, Subscribed

FWIW, in my .vimrc I have the following:

def GoToGitRoot()
  # Change dir to the current buffer location and if you are in a git repo,
  # then change dir to the git repo root.
  exe $'cd {expand('%:p:h')}'
  var git_root = system('git rev-parse --show-toplevel')
  # v:shell_error does not work in Windows, it returns 0
  if v:shell_error == 0 && g:os != "Windows"
    exe $'cd {git_root}'
  endif
  pwd
enddef
noremap cd <scriptcmd>GoToGitRoot()<cr>

Perhaps such GoToGitRoot() function could be invoked from an autocmd.


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/16070/2640534731@github.com>

Enno

unread,
Feb 7, 2025, 12:59:06 AMFeb 7
to vim/vim, Subscribed

Yes, this seems so recurrent / common a problem with so many vimscript work arounds that in practice with the advent of Git it seems to me the more useful option than &autochdir.


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/16070/2642011667@github.com>

ubaldot

unread,
Feb 7, 2025, 5:45:35 AMFeb 7
to vim/vim, Subscribed

Yes, this seems so recurrent / common a problem with so many vimscript work arounds that in practice with the advent of Git it seems to me the more useful option than &autochdir.

Yeah, I think the better is to keep Vim as general as possible and with less ties as possible to any specific external tool for which we have no control. In the future git may be replaced with something else, yet we would have to maintain a git-related feature only for retro-compatibility reasons. Not a smart move. External tools are better handled via plugins IMHO.


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/16070/2642565018@github.com>

Enno

unread,
Feb 7, 2025, 6:11:02 AMFeb 7
to vim/vim, Subscribed

I think this was addressed by @inkarkat 's &autochrootfunc take.


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/16070/2642614568@github.com>

Gary Johnson

unread,
Feb 7, 2025, 9:58:13 AMFeb 7
to reply+ACY5DGBRAMU4OMAJLQ...@reply.github.com, vim...@googlegroups.com
On 2025-02-07, ubaldot (Vim Github Repository) wrote:
> Yes, this seems so recurrent / common a problem with so many vimscript work
> arounds that in practice with the advent of Git it seems to me the more
> useful option than &autochdir.
>
> Yeah, I think the better is to keep Vim as general as possible and with less
> ties as possible to any specific external tool for which we have no control. In
> the future git may be replaced with something else, yet we would have to
> maintain a git-related feature only for retro-compatibility reasons. Not a
> smart move. External tools are better handled via plugins IMHO.

I agree.

Even considering only git, if your project has submodules, the
meaning of "project root" is ambiguous: do you mean the root of the
current submodule or the top-level root of the entire project?
Which you want depends on the situation.

I've been working for years on a plugin that would allow Vim to know
the root directory of whatever project it was in, whether using git,
some other VCS, or no VCS. It's not easy to get the rules right,
and I still have a file of exceptions to those rules.

Regards,
Gary

vim-dev ML

unread,
Feb 7, 2025, 9:58:48 AMFeb 7
to vim/vim, vim-dev ML, Your activity


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/16070/2643177045@github.com>

Enno

unread,
Feb 7, 2025, 10:49:59 AMFeb 7
to vim/vim, vim-dev ML, Comment

Yes, the VCS project folder detection is up to the user. The opening post for this reason suggested &autochrootfunc to look for the next parent directory containing a .git folder to avoid the ambiguity with submodules, but if one prefers submodules, then this could, for example, be set in a local vimrc in the project root.

This issue is rather about a reliable hook, as &autochdir provides, then getting the rules for every VCS right. Other than maybe documenting a few sensible suggestions for Git (it is still rather popular) this is indeed best left to plug-ins.


Reply to this email directly, view it on GitHub.

You are receiving this because you commented.Message ID: <vim/vim/issues/16070/2643298998@github.com>

Maxim Kim

unread,
Feb 7, 2025, 5:14:59 PMFeb 7
to vim/vim, vim-dev ML, Comment

If this is to be implemented in core (which I support), not only dir but also file marks need to be taken into account.

https://github.com/habamax/.vim/blob/master/plugin/prjroot.vim#L3-L4

This issue is rather about a reliable hook, as &autochdir provides, then getting the rules for every VCS right

I would still expect to have defaults that cover basic most used scenarious.


Reply to this email directly, view it on GitHub.

You are receiving this because you commented.Message ID: <vim/vim/issues/16070/2644225954@github.com>

Enno

unread,
Feb 8, 2025, 3:30:05 AMFeb 8
to vim/vim, vim-dev ML, Comment

So taking @habamax 's code, would it be as easy as autochroot=SetProjectRoot and then adding a do_autochroot variant of

https://github.com/vim/vim/blob/a6d5778d9b14d6c194d23f01c8ddfdcdc08c7974/src/buffer.c#L2042

that calls a variant of

https://github.com/vim/vim/blob/a6d5778d9b14d6c194d23f01c8ddfdcdc08c7974/src/misc2.c#L1978

with new_dir[MAXPATHL] supplied by the output of autochroot


Reply to this email directly, view it on GitHub.

You are receiving this because you commented.Message ID: <vim/vim/issues/16070/2644721491@github.com>

Maxim Kim

unread,
Feb 8, 2025, 4:34:33 AMFeb 8
to vim/vim, vim-dev ML, Comment

Is it worth it? If I have the func I can call it from autocmd, which I already do.


Reply to this email directly, view it on GitHub.

You are receiving this because you commented.Message ID: <vim/vim/issues/16070/2644747916@github.com>

Ingo Karkat

unread,
Feb 8, 2025, 5:27:47 AMFeb 8
to vim/vim, vim-dev ML, Comment

Is it worth it? If I have the func I can call it from autocmd, which I already do.

See #16070 (comment)


Reply to this email directly, view it on GitHub.

You are receiving this because you commented.Message ID: <vim/vim/issues/16070/2644831694@github.com>

Maxim Kim

unread,
Feb 8, 2025, 5:33:29 AMFeb 8
to vim/vim, vim-dev ML, Comment

Eventually plugin author would take into account that cwd could be not something expected and do all sort of guards. Having to check autochroot option would be a tiny fraction of it anyways.


Reply to this email directly, view it on GitHub.

You are receiving this because you commented.Message ID: <vim/vim/issues/16070/2644855202@github.com>

D. Ben Knoble

unread,
Feb 9, 2025, 5:51:55 PMFeb 9
to vim/vim, vim-dev ML, Comment

We've already mentioned git rev-parse --show-toplevel (and --show-superproject-working-tree), and there's a few others. But I need to clear up a common misconception: searching for a directory named .git is not robust enough:

  • GIT_DIR, --git-dir, GIT_WORK_TREE, and --work-tree can all influence where the repository is considered to be rooted.
  • Submodules (and worktrees) typically contain a .git file that points to the actual GIT_DIR for that submodule (which is typically nested in the GIT_DIR for the superproject) via the "gitfile" mechanism (see git help repository-layout).

So you really ought to use git rev-parse for robustness, or port Fugitive's helpers (which avoid the subprocess by implementing most of what Git: checking a bunch of environment variables, scanning upwards for .git, then branching based on what kind of file it is, etc.).


Reply to this email directly, view it on GitHub.

You are receiving this because you commented.Message ID: <vim/vim/issues/16070/2646636909@github.com>

Maxim Kim

unread,
Feb 9, 2025, 5:57:16 PMFeb 9
to vim/vim, vim-dev ML, Comment

I didn't suggest to use .git directory, I was more about the non-git related projects which might be denoted by Makefile, go.mod, .whatever files.


Reply to this email directly, view it on GitHub.

You are receiving this because you commented.Message ID: <vim/vim/issues/16070/2646638584@github.com>

D. Ben Knoble

unread,
Feb 9, 2025, 6:20:40 PMFeb 9
to vim/vim, vim-dev ML, Comment

I didn't suggest to use .git directory, I was more about the non-git related projects which might be denoted by Makefile, go.mod, .whatever files.

Certainly—this wasn't directed at your reply in particular, and I could have been clearer about that.


Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you commented.Message ID: <vim/vim/issues/16070/2646649099@github.com>

Reply all
Reply to author
Forward
0 new messages