vim-rooter icon indicating copy to clipboard operation
vim-rooter copied to clipboard

Multiple sets of patterns

Open casey opened this issue 4 years ago • 9 comments

Thanks for the great plugin!

I mostly program in Rust, and adding Cargo.toml to g:rooter_patterns usually works to find the correct project root when working in rust projects.

However, Rust supports workspaces with directories with Cargo.toml files. In this case, sometimes vim-rooter will stop at a Cargo.toml file in a subdirectory.

In such cases, I'd rather vim-rooter use the location of the .git directory to find the project root.

I was thinking about how vim-rooter might support this, and one possibility is to to allow setting g:rooter_patterns to multiple sets of patterns, which would be checked in order.

In my this case, I would use the following configuration:

let g:rooter_patterns = [['.git/'], ['Cargo.toml']]

vim-rooter would first search for a .git directory, and only if that failed search for a Cargo.toml file.

I think this would be a pretty simple change. A new configuration option, g:rooter_pattern_groups. If it was unset, it would default to [g:rooter_patterns], for backwards compatibility. And the implementation would be an additional for loop around the main for loop in plugin/rooter.vim.

casey avatar Aug 04 '21 08:08 casey

What does the directory structure of a workspace(s) look like?

airblade avatar Aug 04 '21 08:08 airblade

It's pretty flexible, but a few layouts might be:

Cargo.toml
crate-a/Cargo.toml
crate-b/Cargo.toml

Or:

Cargo.toml
crates/a/Cargo.toml
crates/b/Cargo.toml

casey avatar Aug 04 '21 08:08 casey

I've never used Rust. Do those layouts show the project root directory with the crates being workspaces? Or Is each example a workspace? If the latter, please could you show where workspaces sit in relation to the project root.

Presumably you can't just use .git because the workspaces have their own .git directories?

airblade avatar Aug 04 '21 11:08 airblade

Each example is a workspace, with the top Cargo.toml being the crate root, and a and b being sub-crates in the workspace.

Usually workspaces have .git directories, but sometimes they don't.

casey avatar Aug 04 '21 17:08 casey

Hmm, so is a workspace the root of a project? Or does the root of a project contain workspaces?

airblade avatar Aug 04 '21 19:08 airblade

A workspaces is usually at the root of a project, and it contains one or more crates.

A real-world example is here. The repo is a workspace, and the root Cargo.toml is here. There are also sub-crates with their own Cargo.tomls, like this one or this one.

casey avatar Aug 04 '21 20:08 casey

Thanks for explaining further.

Would you expect to see a Cargo.lock at the top level only?

If not, these patterns work for me:

let g:rooter_patterns = ['!../Cargo.toml', '!../../Cargo.toml', 'Cargo.toml']

Your suggestion of an extra loop changes the algorithm from breadth-first to depth-first. If I'm going to do that I'd prefer an explicit option and to keep the patterns as a simple list.

airblade avatar Aug 05 '21 09:08 airblade

Would you expect to see a Cargo.lock at the top level only?

You would expect to see a Cargo.lcok at the top level, but a Cargo.lock file doesn't exist when a project is initialized, only when it's first built. Also, library crates don't check the Cargo.lock file into version control, so it will be missing upon first check-out.

let g:rooter_patterns = ['!../Cargo.toml', '!../../Cargo.toml', 'Cargo.toml']

That's a good idea, I'll do that.

Your suggestion of an extra loop changes the algorithm from breadth-first to depth-first. If I'm going to do that I'd prefer an explicit option and to keep the patterns as a simple list.

I understand the reluctance to do so, although the advantage of a list of lists is that it has extra flexibility in that it combines breadth first and depth first searches. And if it's possible to check if an item is a list or a list of lists, it could still retain the existing behavior by default when it's just a list of strings.

casey avatar Aug 06 '21 01:08 casey

In my this case, I would use the following configuration:

let g:rooter_patterns = [['.git/'], ['Cargo.toml']]

vim-rooter would first search for a .git directory, and only if that failed search for a Cargo.toml file.

I met similar situation. Android use repo to manage code, I hope it search .repo firstly, only when .repo doesn't exist, search .git. Looks like your

let g:rooter_patterns = [['.repo'], ['.git']]

Freed-Wu avatar Sep 06 '23 06:09 Freed-Wu