Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
20 changes: 18 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::path::Path;
use std::path::{Path, PathBuf};

use globset::{Glob, GlobMatcher};

Expand All @@ -8,6 +8,9 @@ pub struct EditorConfig {
root: bool,

sections: Vec<EditorConfigSection>,

/// The base directory for resolving absolute paths.
cwd: Option<PathBuf>,
}

impl EditorConfig {
Expand All @@ -18,6 +21,16 @@ impl EditorConfig {
pub fn sections(&self) -> &[EditorConfigSection] {
&self.sections
}

pub fn cwd(&self) -> Option<&Path> {
self.cwd.as_deref()
}

/// Sets the current working directory for resolving absolute paths.
pub fn with_cwd<P: AsRef<Path>>(mut self, cwd: P) -> Self {
self.cwd = Some(cwd.as_ref().to_path_buf());
self
}
}

/// <https://spec.editorconfig.org/index.html>
Expand Down Expand Up @@ -190,11 +203,14 @@ impl EditorConfig {
}
}

Self { root, sections }
Self { root, sections, cwd: None }
}

/// Resolve a given path and return the resolved properties.
/// If `cwd` is set, absolute paths will be resolved relative to `cwd`.
pub fn resolve(&self, path: &Path) -> EditorConfigProperties {
let path =
if let Some(cwd) = &self.cwd { path.strip_prefix(cwd).unwrap_or(path) } else { path };
let mut properties = EditorConfigProperties::default();
for section in &self.sections {
if section.matcher.as_ref().is_some_and(|matcher| matcher.is_match(path)) {
Expand Down
51 changes: 50 additions & 1 deletion tests/main.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::path::Path;
use std::path::{Path, PathBuf};

use editorconfig_parser::{
Charset, EditorConfig, EditorConfigProperties, EditorConfigProperty::Value, EndOfLine,
Expand Down Expand Up @@ -180,3 +180,52 @@ fn unset() {
let properties = editor_config.resolve(&path);
assert_eq!(properties, EditorConfigProperties::default());
}

#[test]
fn resolve_with_cwd() {
let editor_config = EditorConfig::parse(
"
[*]
indent_size = 2

[*.ts]
indent_size = 4

[src/**/*.ts]
indent_size = 8
",
)
.with_cwd("/project");

assert_eq!(editor_config.cwd(), Some(Path::new("/project")));

// Absolute path should be resolved relative to cwd
let properties = editor_config.resolve(Path::new("/project/file.ts"));
assert_eq!(properties.indent_size, Value(4));

let properties = editor_config.resolve(Path::new("/project/src/file.ts"));
assert_eq!(properties.indent_size, Value(8));

// Path not under cwd should still work (uses path as-is)
let properties = editor_config.resolve(Path::new("/other/file.ts"));
assert_eq!(properties.indent_size, Value(4));

// Relative path should work as before
let properties = editor_config.resolve(Path::new("file.ts"));
assert_eq!(properties.indent_size, Value(4));
}

#[test]
fn resolve_with_cwd_pathbuf() {
let cwd = PathBuf::from("/my/project");
let editor_config = EditorConfig::parse(
"
[*.rs]
indent_size = 4
",
)
.with_cwd(&cwd);

let properties = editor_config.resolve(&cwd.join("main.rs"));
assert_eq!(properties.indent_size, Value(4));
}