Cargo.lock 🔗
@@ -7695,6 +7695,7 @@ dependencies = [
"lsp",
"node_runtime",
"parking_lot",
+ "pathdiff",
"postage",
"prettier",
"pretty_assertions",
Piotr Osiewicz created
Release Notes:
- Added ZED_RELATIVE_FILE (path to current file relative to worktree
root) and ZED_DIRNAME (path to the directory containing current file)
task variables.
Cargo.lock | 1
Cargo.toml | 1
crates/project/Cargo.toml | 1
crates/project/src/task_inventory.rs | 40 +++++++++++++++++++----------
crates/task/src/lib.rs | 10 ++++++-
crates/tasks_ui/src/lib.rs | 6 ++++
docs/src/tasks.md | 2 +
7 files changed, 45 insertions(+), 16 deletions(-)
@@ -7695,6 +7695,7 @@ dependencies = [
"lsp",
"node_runtime",
"parking_lot",
+ "pathdiff",
"postage",
"prettier",
"pretty_assertions",
@@ -305,6 +305,7 @@ once_cell = "1.19.0"
ordered-float = "2.1.1"
palette = { version = "0.7.5", default-features = false, features = ["std"] }
parking_lot = "0.12.1"
+pathdiff = "0.2"
profiling = "1"
postage = { version = "0.5", features = ["futures-traits"] }
pretty_assertions = "1.3.0"
@@ -44,6 +44,7 @@ log.workspace = true
lsp.workspace = true
node_runtime.workspace = true
parking_lot.workspace = true
+pathdiff.workspace = true
postage.workspace = true
prettier.workspace = true
worktree.workspace = true
@@ -549,20 +549,6 @@ impl ContextProvider for BasicContextProvider {
if !selected_text.trim().is_empty() {
task_variables.insert(VariableName::SelectedText, selected_text);
}
- if let Some(path) = current_file {
- task_variables.insert(VariableName::File, path.clone());
-
- let path = Path::new(&path);
-
- if let Some(filename) = path.file_name().and_then(|f| f.to_str()) {
- task_variables.insert(VariableName::Filename, String::from(filename));
- }
-
- if let Some(stem) = path.file_stem().and_then(|s| s.to_str()) {
- task_variables.insert(VariableName::Stem, String::from(stem));
- }
- }
-
let worktree_abs_path = buffer
.file()
.map(|file| WorktreeId::from_usize(file.worktree_id()))
@@ -577,6 +563,32 @@ impl ContextProvider for BasicContextProvider {
VariableName::WorktreeRoot,
worktree_path.to_string_lossy().to_string(),
);
+ if let Some(full_path) = current_file.as_ref() {
+ let relative_path = pathdiff::diff_paths(full_path, worktree_path);
+ if let Some(relative_path) = relative_path {
+ task_variables.insert(
+ VariableName::RelativeFile,
+ relative_path.to_string_lossy().into_owned(),
+ );
+ }
+ }
+ }
+
+ if let Some(path_as_string) = current_file {
+ let path = Path::new(&path_as_string);
+ if let Some(filename) = path.file_name().and_then(|f| f.to_str()) {
+ task_variables.insert(VariableName::Filename, String::from(filename));
+ }
+
+ if let Some(stem) = path.file_stem().and_then(|s| s.to_str()) {
+ task_variables.insert(VariableName::Stem, stem.into());
+ }
+
+ if let Some(dirname) = path.parent().and_then(|s| s.to_str()) {
+ task_variables.insert(VariableName::Dirname, dirname.into());
+ }
+
+ task_variables.insert(VariableName::File, path_as_string);
}
Ok(task_variables)
@@ -124,9 +124,13 @@ impl ResolvedTask {
pub enum VariableName {
/// An absolute path of the currently opened file.
File,
- /// the currently opened filename.
+ /// A path of the currently opened file (relative to worktree root).
+ RelativeFile,
+ /// The currently opened filename.
Filename,
- /// stem (filename without extension) of the currently opened file.
+ /// The path to a parent directory of a currently opened file.
+ Dirname,
+ /// Stem (filename without extension) of the currently opened file.
Stem,
/// An absolute path of the currently opened worktree, that contains the file.
WorktreeRoot,
@@ -165,6 +169,8 @@ impl std::fmt::Display for VariableName {
match self {
Self::File => write!(f, "{ZED_VARIABLE_NAME_PREFIX}FILE"),
Self::Filename => write!(f, "{ZED_VARIABLE_NAME_PREFIX}FILENAME"),
+ Self::RelativeFile => write!(f, "{ZED_VARIABLE_NAME_PREFIX}RELATIVE_FILE"),
+ Self::Dirname => write!(f, "{ZED_VARIABLE_NAME_PREFIX}DIRNAME"),
Self::Stem => write!(f, "{ZED_VARIABLE_NAME_PREFIX}STEM"),
Self::WorktreeRoot => write!(f, "{ZED_VARIABLE_NAME_PREFIX}WORKTREE_ROOT"),
Self::Symbol => write!(f, "{ZED_VARIABLE_NAME_PREFIX}SYMBOL"),
@@ -261,6 +261,8 @@ mod tests {
task_variables: TaskVariables::from_iter([
(VariableName::File, "/dir/rust/b.rs".into()),
(VariableName::Filename, "b.rs".into()),
+ (VariableName::RelativeFile, "rust/b.rs".into()),
+ (VariableName::Dirname, "/dir/rust".into()),
(VariableName::Stem, "b".into()),
(VariableName::WorktreeRoot, "/dir".into()),
(VariableName::Row, "1".into()),
@@ -279,6 +281,8 @@ mod tests {
task_variables: TaskVariables::from_iter([
(VariableName::File, "/dir/rust/b.rs".into()),
(VariableName::Filename, "b.rs".into()),
+ (VariableName::RelativeFile, "rust/b.rs".into()),
+ (VariableName::Dirname, "/dir/rust".into()),
(VariableName::Stem, "b".into()),
(VariableName::WorktreeRoot, "/dir".into()),
(VariableName::Row, "1".into()),
@@ -298,6 +302,8 @@ mod tests {
task_variables: TaskVariables::from_iter([
(VariableName::File, "/dir/a.ts".into()),
(VariableName::Filename, "a.ts".into()),
+ (VariableName::RelativeFile, "a.ts".into()),
+ (VariableName::Dirname, "/dir".into()),
(VariableName::Stem, "a".into()),
(VariableName::WorktreeRoot, "/dir".into()),
(VariableName::Row, "1".into()),
@@ -45,6 +45,8 @@ These variables allow you to pull information from the current editor and use it
- `ZED_ROW`: current line row
- `ZED_FILE`: absolute path of the currently opened file (e.g. `/Users/my-user/path/to/project/src/main.rs`)
- `ZED_FILENAME`: filename of the currently opened file (e.g. `main.rs`)
+- `ZED_DIRNAME`: absolute path of the currently opened file with file name stripped (e.g. `/Users/my-user/path/to/project/src`)
+- `ZED_RELATIVE_FILE`: path of the currently opened file, relative to `ZED_WORKTREE_ROOT` (e.g. `src/main.rs`)
- `ZED_STEM`: stem (filename without extension) of the currently opened file (e.g. `main`)
- `ZED_SYMBOL`: currently selected symbol; should match the last symbol shown in a symbol breadcrumb (e.g. `mod tests > fn test_task_contexts`)
- `ZED_SELECTED_TEXT`: currently selected text