WIP: Add a setting to visually redact enviroment variables (#7124)
Release Notes: - Added bash syntax highlighting to `.env` files. - Added a `private_files` setting for configuring which files should be considered to contain environment variables or other sensitive information. - Added a `redact_private_values` setting to add or remove censor bars over variable values in files matching the `private_files` patterns. -(internal) added a new `redactions.scm` query to our language support, allowing different config file formats to indicate where environment variable values can be identified in the syntax tree, added this query to `bash`, `json`, `toml`, and `yaml` files. --------- Co-authored-by: Nathan <nathan@zed.dev>
This commit is contained in:
parent
5333eff0e4
commit
f98d636203
23 changed files with 330 additions and 32 deletions
|
@ -383,6 +383,9 @@ pub trait File: Send + Sync {
|
|||
|
||||
/// Converts this file into a protobuf message.
|
||||
fn to_proto(&self) -> rpc::proto::File;
|
||||
|
||||
/// Return whether Zed considers this to be a dotenv file.
|
||||
fn is_private(&self) -> bool;
|
||||
}
|
||||
|
||||
/// The file associated with a buffer, in the case where the file is on the local disk.
|
||||
|
@ -2877,6 +2880,43 @@ impl BufferSnapshot {
|
|||
})
|
||||
}
|
||||
|
||||
/// Returns anchor ranges for any matches of the redaction query.
|
||||
/// The buffer can be associated with multiple languages, and the redaction query associated with each
|
||||
/// will be run on the relevant section of the buffer.
|
||||
pub fn redacted_ranges<'a, T: ToOffset>(
|
||||
&'a self,
|
||||
range: Range<T>,
|
||||
) -> impl Iterator<Item = Range<usize>> + 'a {
|
||||
let offset_range = range.start.to_offset(self)..range.end.to_offset(self);
|
||||
let mut syntax_matches = self.syntax.matches(offset_range, self, |grammar| {
|
||||
grammar
|
||||
.redactions_config
|
||||
.as_ref()
|
||||
.map(|config| &config.query)
|
||||
});
|
||||
|
||||
let configs = syntax_matches
|
||||
.grammars()
|
||||
.iter()
|
||||
.map(|grammar| grammar.redactions_config.as_ref())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
iter::from_fn(move || {
|
||||
let redacted_range = syntax_matches
|
||||
.peek()
|
||||
.and_then(|mat| {
|
||||
configs[mat.grammar_index].and_then(|config| {
|
||||
mat.captures
|
||||
.iter()
|
||||
.find(|capture| capture.index == config.redaction_capture_ix)
|
||||
})
|
||||
})
|
||||
.map(|mat| mat.node.byte_range());
|
||||
syntax_matches.advance();
|
||||
redacted_range
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns selections for remote peers intersecting the given range.
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub fn remote_selections_in_range(
|
||||
|
|
|
@ -453,6 +453,7 @@ pub struct LanguageQueries {
|
|||
pub embedding: Option<Cow<'static, str>>,
|
||||
pub injections: Option<Cow<'static, str>>,
|
||||
pub overrides: Option<Cow<'static, str>>,
|
||||
pub redactions: Option<Cow<'static, str>>,
|
||||
}
|
||||
|
||||
/// Represents a language for the given range. Some languages (e.g. HTML)
|
||||
|
@ -623,6 +624,7 @@ pub struct Grammar {
|
|||
pub(crate) error_query: Query,
|
||||
pub(crate) highlights_query: Option<Query>,
|
||||
pub(crate) brackets_config: Option<BracketConfig>,
|
||||
pub(crate) redactions_config: Option<RedactionConfig>,
|
||||
pub(crate) indents_config: Option<IndentConfig>,
|
||||
pub outline_config: Option<OutlineConfig>,
|
||||
pub embedding_config: Option<EmbeddingConfig>,
|
||||
|
@ -664,6 +666,11 @@ struct InjectionConfig {
|
|||
patterns: Vec<InjectionPatternConfig>,
|
||||
}
|
||||
|
||||
struct RedactionConfig {
|
||||
pub query: Query,
|
||||
pub redaction_capture_ix: u32,
|
||||
}
|
||||
|
||||
struct OverrideConfig {
|
||||
query: Query,
|
||||
values: HashMap<u32, (String, LanguageConfigOverride)>,
|
||||
|
@ -1303,6 +1310,7 @@ impl Language {
|
|||
indents_config: None,
|
||||
injection_config: None,
|
||||
override_config: None,
|
||||
redactions_config: None,
|
||||
error_query: Query::new(&ts_language, "(ERROR) @error").unwrap(),
|
||||
ts_language,
|
||||
highlight_map: Default::default(),
|
||||
|
@ -1359,6 +1367,11 @@ impl Language {
|
|||
.with_override_query(query.as_ref())
|
||||
.context("Error loading override query")?;
|
||||
}
|
||||
if let Some(query) = queries.redactions {
|
||||
self = self
|
||||
.with_redaction_query(query.as_ref())
|
||||
.context("Error loading redaction query")?;
|
||||
}
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
|
@ -1589,6 +1602,22 @@ impl Language {
|
|||
Ok(self)
|
||||
}
|
||||
|
||||
pub fn with_redaction_query(mut self, source: &str) -> anyhow::Result<Self> {
|
||||
let grammar = self.grammar_mut();
|
||||
let query = Query::new(&grammar.ts_language, source)?;
|
||||
let mut redaction_capture_ix = None;
|
||||
get_capture_indices(&query, &mut [("redact", &mut redaction_capture_ix)]);
|
||||
|
||||
if let Some(redaction_capture_ix) = redaction_capture_ix {
|
||||
grammar.redactions_config = Some(RedactionConfig {
|
||||
query,
|
||||
redaction_capture_ix,
|
||||
});
|
||||
}
|
||||
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
fn grammar_mut(&mut self) -> &mut Grammar {
|
||||
Arc::get_mut(self.grammar.as_mut().unwrap()).unwrap()
|
||||
}
|
||||
|
|
|
@ -1059,7 +1059,7 @@ impl<'a> SyntaxMapMatches<'a> {
|
|||
.position(|later_layer| key < later_layer.sort_key())
|
||||
.unwrap_or(self.active_layer_count - 1);
|
||||
self.layers[0..i].rotate_left(1);
|
||||
} else {
|
||||
} else if self.active_layer_count != 0 {
|
||||
self.layers[0..self.active_layer_count].rotate_left(1);
|
||||
self.active_layer_count -= 1;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue