on master help sign in
Split helix_core::find_root and helix_loader::find_local_config_dirs (#3929)
888f4feRiccardo Binetti
helix-core/src/lib.rs+36−4
@@ -46,10 +46,42 @@ pub fn find_first_non_whitespace_char(line: RopeSlice) -> Option<usize> {
46/// * Git repository root if no marker detected
46/// * Git repository root if no marker detected
47/// * Top-most folder containing a root marker if not git repository detected
47/// * Top-most folder containing a root marker if not git repository detected
48/// * Current working directory as fallback
48/// * Current working directory as fallback
49−pub fn find_root(root: Option<&str>, root_markers: &[String]) -> Option<std::path::PathBuf> {
49+pub fn find_root(root: Option<&str>, root_markers: &[String]) -> std::path::PathBuf {
50+ let current_dir = std::env::current_dir().expect("unable to determine current directory");
51+
52+ let root = match root {
53+ Some(root) => {
54+ let root = std::path::Path::new(root);
55+ if root.is_absolute() {
56+ root.to_path_buf()
57+ } else {
58+ current_dir.join(root)
59+ }
60+ }
61+ None => current_dir.clone(),
62+ };
63+
64+ let mut top_marker = None;
65+ for ancestor in root.ancestors() {
50− helix_loader::find_root_impl(root, root_markers)
66+ if root_markers
51− .first()
67+ .iter()
52− .cloned()
68+ .any(|marker| ancestor.join(marker).exists())
69+ {
70+ top_marker = Some(ancestor);
71+ }
72+
73+ if ancestor.join(".git").is_dir() {
74+ // Top marker is repo root if not root marker was detected yet
75+ if top_marker.is_none() {
76+ top_marker = Some(ancestor);
77+ }
78+ // Don't go higher than repo if we're in one
79+ break;
80+ }
81+ }
82+
83+ // Return the found top marker or the current_dir as fallback
84+ top_marker.map_or(current_dir, |a| a.to_path_buf())
53}
85}
54
86
55pub use ropey::{str_utils, Rope, RopeBuilder, RopeSlice};
87pub use ropey::{str_utils, Rope, RopeBuilder, RopeSlice};
helix-loader/src/lib.rs+5−21
@@ -59,7 +59,7 @@ pub fn config_dir() -> PathBuf {
59}
59}
60
60
61pub fn local_config_dirs() -> Vec<PathBuf> {
61pub fn local_config_dirs() -> Vec<PathBuf> {
62− let directories = find_root_impl(None, &[".helix".to_string()])
62+ let directories = find_local_config_dirs()
63 .into_iter()
63 .into_iter()
64 .map(|path| path.join(".helix"))
64 .map(|path| path.join(".helix"))
65 .collect();
65 .collect();
@@ -90,32 +90,16 @@ pub fn log_file() -> PathBuf {
90 cache_dir().join("helix.log")
90 cache_dir().join("helix.log")
91}
91}
92
92
93−pub fn find_root_impl(root: Option<&str>, root_markers: &[String]) -> Vec<PathBuf> {
93+pub fn find_local_config_dirs() -> Vec<PathBuf> {
94 let current_dir = std::env::current_dir().expect("unable to determine current directory");
94 let current_dir = std::env::current_dir().expect("unable to determine current directory");
95 let mut directories = Vec::new();
95 let mut directories = Vec::new();
96
96
97− let root = match root {
98− Some(root) => {
99− let root = std::path::Path::new(root);
100− if root.is_absolute() {
101− root.to_path_buf()
102− } else {
103− current_dir.join(root)
104− }
105− }
106− None => current_dir,
107− };
108−
109− for ancestor in root.ancestors() {
97+ for ancestor in current_dir.ancestors() {
110− // don't go higher than repo
111 if ancestor.join(".git").is_dir() {
98 if ancestor.join(".git").is_dir() {
112− // Use workspace if detected from marker
113 directories.push(ancestor.to_path_buf());
99 directories.push(ancestor.to_path_buf());
100+ // Don't go higher than repo if we're in one
114 break;
101 break;
115− } else if root_markers
102+ } else if ancestor.join(".helix").is_dir() {
116− .iter()
117− .any(|marker| ancestor.join(marker).exists())
118− {
119 directories.push(ancestor.to_path_buf());
103 directories.push(ancestor.to_path_buf());
120 }
104 }
121 }
105 }
helix-lsp/src/client.rs+3−8
@@ -34,7 +34,7 @@ pub struct Client {
34 pub(crate) capabilities: OnceCell<lsp::ServerCapabilities>,
34 pub(crate) capabilities: OnceCell<lsp::ServerCapabilities>,
35 offset_encoding: OffsetEncoding,
35 offset_encoding: OffsetEncoding,
36 config: Option<Value>,
36 config: Option<Value>,
37− root_path: Option<std::path::PathBuf>,
37+ root_path: std::path::PathBuf,
38 root_uri: Option<lsp::Url>,
38 root_uri: Option<lsp::Url>,
39 workspace_folders: Vec<lsp::WorkspaceFolder>,
39 workspace_folders: Vec<lsp::WorkspaceFolder>,
40 req_timeout: u64,
40 req_timeout: u64,
@@ -74,9 +74,7 @@ impl Client {
74
74
75 let root_path = find_root(None, root_markers);
75 let root_path = find_root(None, root_markers);
76
76
77− let root_uri = root_path
78− .clone()
79− .and_then(|root| lsp::Url::from_file_path(root).ok());
77+ let root_uri = lsp::Url::from_file_path(root_path.clone()).ok();
80
78
81 // TODO: support multiple workspace folders
79 // TODO: support multiple workspace folders
82 let workspace_folders = root_uri
80 let workspace_folders = root_uri
@@ -281,10 +279,7 @@ impl Client {
281 workspace_folders: Some(self.workspace_folders.clone()),
279 workspace_folders: Some(self.workspace_folders.clone()),
282 // root_path is obsolete, but some clients like pyright still use it so we specify both.
280 // root_path is obsolete, but some clients like pyright still use it so we specify both.
283 // clients will prefer _uri if possible
281 // clients will prefer _uri if possible
284− root_path: self
285− .root_path
286− .clone()
287− .and_then(|path| path.to_str().map(|path| path.to_owned())),
282+ root_path: self.root_path.to_str().map(|path| path.to_owned()),
288 root_uri: self.root_uri.clone(),
283 root_uri: self.root_uri.clone(),
289 initialization_options: self.config.clone(),
284 initialization_options: self.config.clone(),
290 capabilities: lsp::ClientCapabilities {
285 capabilities: lsp::ClientCapabilities {
helix-term/src/commands.rs+3−2
@@ -2225,8 +2225,9 @@ fn append_mode(cx: &mut Context) {
2225}
2225}
2226
2226
2227fn file_picker(cx: &mut Context) {
2227fn file_picker(cx: &mut Context) {
2228− // We don't specify language markers, root will be the root of the current git repo
2228+ // We don't specify language markers, root will be the root of the current
2229+ // git repo or the current dir if we're not in a repo
2229− let root = find_root(None, &[]).unwrap_or_else(|| PathBuf::from("./"));
2230+ let root = find_root(None, &[]);
2230 let picker = ui::file_picker(root, &cx.editor.config());
2231 let picker = ui::file_picker(root, &cx.editor.config());
2231 cx.push_layer(Box::new(overlayed(picker)));
2232 cx.push_layer(Box::new(overlayed(picker)));
2232}
2233}