Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Detect workspace root using language markers #1370

Merged
merged 4 commits into from
Dec 31, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 30 additions & 6 deletions helix-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,14 @@ pub fn find_first_non_whitespace_char(line: RopeSlice) -> Option<usize> {
line.chars().position(|ch| !ch.is_whitespace())
}

/// Find `.git` root.
pub fn find_root(root: Option<&str>) -> Option<std::path::PathBuf> {
/// Find project root.
///
/// Order of detection:
/// * Top-most folder containing a root marker in current git repository
/// * Git repostory root if no marker detected
amousset marked this conversation as resolved.
Show resolved Hide resolved
/// * Top-most folder containing a root marker if not git repository detected
/// * Current working directory as fallback
pub fn find_root(root: Option<&str>, root_markers: Vec<String>) -> Option<std::path::PathBuf> {
amousset marked this conversation as resolved.
Show resolved Hide resolved
let current_dir = std::env::current_dir().expect("unable to determine current directory");

let root = match root {
Expand All @@ -52,16 +58,34 @@ pub fn find_root(root: Option<&str>) -> Option<std::path::PathBuf> {
current_dir.join(root)
}
}
None => current_dir,
None => current_dir.clone(),
};

let mut top_marker = None;
for ancestor in root.ancestors() {
// TODO: also use defined roots if git isn't found
for marker in &root_markers {
if ancestor.join(marker).exists() {
top_marker = Some(ancestor);
break;
}
}
// don't go higher than repo
if ancestor.join(".git").is_dir() {
return Some(ancestor.to_path_buf());
// Use workspace if detected from marker
if top_marker.is_some() {
return top_marker.map(|a| a.to_path_buf());
} else {
return Some(ancestor.to_path_buf());
}
amousset marked this conversation as resolved.
Show resolved Hide resolved
}
}
None

// In absence of git repo, use workspace if detected
if top_marker.is_some() {
top_marker.map(|a| a.to_path_buf())
} else {
Some(current_dir)
}
}

pub fn runtime_dir() -> std::path::PathBuf {
Expand Down
6 changes: 5 additions & 1 deletion helix-lsp/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ pub struct Client {
pub(crate) capabilities: OnceCell<lsp::ServerCapabilities>,
offset_encoding: OffsetEncoding,
config: Option<Value>,
root_markers: Vec<String>,
}

impl Client {
Expand All @@ -39,6 +40,7 @@ impl Client {
cmd: &str,
args: &[String],
config: Option<Value>,
root_markers: Vec<String>,
amousset marked this conversation as resolved.
Show resolved Hide resolved
id: usize,
) -> Result<(Self, UnboundedReceiver<(usize, Call)>, Arc<Notify>)> {
let process = Command::new(cmd)
Expand Down Expand Up @@ -68,6 +70,7 @@ impl Client {
capabilities: OnceCell::new(),
offset_encoding: OffsetEncoding::Utf8,
config,
root_markers,
};

Ok((client, server_rx, initialize_notify))
Expand Down Expand Up @@ -225,7 +228,8 @@ impl Client {

pub(crate) async fn initialize(&self) -> Result<lsp::InitializeResult> {
// TODO: delay any requests that are triggered prior to initialize
let root = find_root(None).and_then(|root| lsp::Url::from_file_path(root).ok());
let root = find_root(None, self.root_markers.clone())
.and_then(|root| lsp::Url::from_file_path(root).ok());

if self.config.is_some() {
log::info!("Using custom LSP config: {}", self.config.as_ref().unwrap());
Expand Down
1 change: 1 addition & 0 deletions helix-lsp/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,7 @@ impl Registry {
&config.command,
&config.args,
language_config.config.clone(),
language_config.roots.clone(),
id,
)?;
self.incoming.push(UnboundedReceiverStream::new(incoming));
Expand Down
3 changes: 2 additions & 1 deletion helix-term/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3026,7 +3026,8 @@ fn command_mode(cx: &mut Context) {
}

fn file_picker(cx: &mut Context) {
let root = find_root(None).unwrap_or_else(|| PathBuf::from("./"));
// We don't specify language markers, root will be the root of the current git repo
let root = find_root(None, vec![]).unwrap_or_else(|| PathBuf::from("./"));
let picker = ui::file_picker(root, &cx.editor.config);
cx.push_layer(Box::new(picker));
}
Expand Down
2 changes: 1 addition & 1 deletion languages.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name = "rust"
scope = "source.rust"
injection-regex = "rust"
file-types = ["rs"]
roots = []
roots = ["Cargo.toml", "Cargo.lock"]
auto-format = true
comment-token = "//"
language-server = { command = "rust-analyzer" }
Expand Down