@@ -39,8 +39,14 @@ pub fn find_first_non_whitespace_char(line: RopeSlice) -> Option<usize> {
3939 line.chars().position(|ch| !ch.is_whitespace())
4040}
4141
42−/// Find `.git` root.
43−pub fn find_root(root: Option<&str>) -> Option<std::path::PathBuf> {
42+/// Find project root.
43+///
44+/// Order of detection:
45+/// * Top-most folder containing a root marker in current git repository
46+/// * Git repostory root if no marker detected
47+/// * Top-most folder containing a root marker if not git repository detected
48+/// * Current working directory as fallback
49+pub fn find_root(root: Option<&str>, root_markers: &[String]) -> Option<std::path::PathBuf> {
4450 let current_dir = std::env::current_dir().expect("unable to determine current directory");
4551
4652 let root = match root {
@@ -52,16 +58,30 @@ pub fn find_root(root: Option<&str>) -> Option<std::path::PathBuf> {
5258 current_dir.join(root)
5359 }
5460 }
55− None => current_dir,
61+ None => current_dir.clone(),
5662 };
5763
64+ let mut top_marker = None;
5865 for ancestor in root.ancestors() {
59− // TODO: also use defined roots if git isn't found
66+ for marker in root_markers {
67+ if ancestor.join(marker).exists() {
68+ top_marker = Some(ancestor);
69+ break;
70+ }
71+ }
72+ // don't go higher than repo
6073 if ancestor.join(".git").is_dir() {
61− return Some(ancestor.to_path_buf());
74+ // Use workspace if detected from marker
75+ return Some(top_marker.unwrap_or(ancestor).to_path_buf());
6276 }
6377 }
64− None
78+
79+ // In absence of git repo, use workspace if detected
80+ if top_marker.is_some() {
81+ top_marker.map(|a| a.to_path_buf())
82+ } else {
83+ Some(current_dir)
84+ }
6585}
6686
6787pub fn runtime_dir() -> std::path::PathBuf {