tasks: Expose captured variables to ContextProvider (#12134)
This PR changes the interface of ContextProvider, allowing it to inspect *all* variables set so far during the process of building `TaskVariables`. This makes it possible to capture e.g. an identifier in tree-sitter query, process it and then export it as a task variable. Notably, the list of variables includes captures prefixed with leading underscore; they are removed after all calls to `build_context`, but it makes it possible to capture something and then conditionally preserve it (and perhaps modify it). Release Notes: - N/A
This commit is contained in:
parent
ba9449692e
commit
58796a8480
15 changed files with 212 additions and 201 deletions
|
@ -3024,6 +3024,7 @@ impl BufferSnapshot {
|
|||
tags.sort_by_key(|(range, _)| range == &maximum_range);
|
||||
let split_point = tags.partition_point(|(range, _)| range != &maximum_range);
|
||||
let (extra_captures, tags) = tags.split_at(split_point);
|
||||
|
||||
let extra_captures = extra_captures
|
||||
.into_iter()
|
||||
.map(|(range, name)| {
|
||||
|
|
|
@ -58,9 +58,7 @@ use std::{
|
|||
};
|
||||
use syntax_map::{QueryCursorHandle, SyntaxSnapshot};
|
||||
use task::RunnableTag;
|
||||
pub use task_context::{
|
||||
BasicContextProvider, ContextProvider, ContextProviderWithTasks, RunnableRange,
|
||||
};
|
||||
pub use task_context::{ContextProvider, RunnableRange};
|
||||
use theme::SyntaxTheme;
|
||||
use tree_sitter::{self, wasmtime, Query, QueryCursor, WasmStore};
|
||||
|
||||
|
@ -1016,7 +1014,7 @@ impl Language {
|
|||
for (ix, name) in query.capture_names().iter().enumerate() {
|
||||
if *name == "run" {
|
||||
run_capture_index = Some(ix as u32);
|
||||
} else if !name.starts_with('_') {
|
||||
} else {
|
||||
runnable_tags.insert(ix as u32, RunnableTag(name.to_string().into()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
use std::{ops::Range, path::Path};
|
||||
use std::ops::Range;
|
||||
|
||||
use crate::{Location, Runnable};
|
||||
|
||||
use anyhow::Result;
|
||||
use collections::HashMap;
|
||||
use gpui::AppContext;
|
||||
use task::{TaskTemplates, TaskVariables, VariableName};
|
||||
use text::{BufferId, Point, ToPoint};
|
||||
use task::{TaskTemplates, TaskVariables};
|
||||
use text::BufferId;
|
||||
|
||||
pub struct RunnableRange {
|
||||
pub buffer_id: BufferId,
|
||||
|
@ -22,7 +22,7 @@ pub trait ContextProvider: Send + Sync {
|
|||
/// Builds a specific context to be placed on top of the basic one (replacing all conflicting entries) and to be used for task resolving later.
|
||||
fn build_context(
|
||||
&self,
|
||||
_worktree_abs_path: Option<&Path>,
|
||||
_variables: &TaskVariables,
|
||||
_location: &Location,
|
||||
_cx: &mut AppContext,
|
||||
) -> Result<TaskVariables> {
|
||||
|
@ -33,100 +33,4 @@ pub trait ContextProvider: Send + Sync {
|
|||
fn associated_tasks(&self) -> Option<TaskTemplates> {
|
||||
None
|
||||
}
|
||||
|
||||
// Determines whether the [`BasicContextProvider`] variables should be filled too (if `false`), or omitted (if `true`).
|
||||
fn is_basic(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// A context provided that tries to provide values for all non-custom [`VariableName`] variants for a currently opened file.
|
||||
/// Applied as a base for every custom [`ContextProvider`] unless explicitly oped out.
|
||||
pub struct BasicContextProvider;
|
||||
|
||||
impl ContextProvider for BasicContextProvider {
|
||||
fn is_basic(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn build_context(
|
||||
&self,
|
||||
worktree_abs_path: Option<&Path>,
|
||||
location: &Location,
|
||||
cx: &mut AppContext,
|
||||
) -> Result<TaskVariables> {
|
||||
let buffer = location.buffer.read(cx);
|
||||
let buffer_snapshot = buffer.snapshot();
|
||||
let symbols = buffer_snapshot.symbols_containing(location.range.start, None);
|
||||
let symbol = symbols.unwrap_or_default().last().map(|symbol| {
|
||||
let range = symbol
|
||||
.name_ranges
|
||||
.last()
|
||||
.cloned()
|
||||
.unwrap_or(0..symbol.text.len());
|
||||
symbol.text[range].to_string()
|
||||
});
|
||||
|
||||
let current_file = buffer
|
||||
.file()
|
||||
.and_then(|file| file.as_local())
|
||||
.map(|file| file.abs_path(cx).to_string_lossy().to_string());
|
||||
let Point { row, column } = location.range.start.to_point(&buffer_snapshot);
|
||||
let row = row + 1;
|
||||
let column = column + 1;
|
||||
let selected_text = buffer
|
||||
.chars_for_range(location.range.clone())
|
||||
.collect::<String>();
|
||||
|
||||
let mut task_variables = TaskVariables::from_iter([
|
||||
(VariableName::Row, row.to_string()),
|
||||
(VariableName::Column, column.to_string()),
|
||||
]);
|
||||
|
||||
if let Some(symbol) = symbol {
|
||||
task_variables.insert(VariableName::Symbol, symbol);
|
||||
}
|
||||
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);
|
||||
}
|
||||
if let Some(worktree_path) = worktree_abs_path {
|
||||
task_variables.insert(
|
||||
VariableName::WorktreeRoot,
|
||||
worktree_path.to_string_lossy().to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
Ok(task_variables)
|
||||
}
|
||||
}
|
||||
|
||||
/// A ContextProvider that doesn't provide any task variables on it's own, though it has some associated tasks.
|
||||
pub struct ContextProviderWithTasks {
|
||||
templates: TaskTemplates,
|
||||
}
|
||||
|
||||
impl ContextProviderWithTasks {
|
||||
pub fn new(definitions: TaskTemplates) -> Self {
|
||||
Self {
|
||||
templates: definitions,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ContextProvider for ContextProviderWithTasks {
|
||||
fn associated_tasks(&self) -> Option<TaskTemplates> {
|
||||
Some(self.templates.clone())
|
||||
}
|
||||
|
||||
fn build_context(
|
||||
&self,
|
||||
worktree_abs_path: Option<&Path>,
|
||||
location: &Location,
|
||||
cx: &mut AppContext,
|
||||
) -> Result<TaskVariables> {
|
||||
BasicContextProvider.build_context(worktree_abs_path, location, cx)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue