Skip to content

Commit 2fa9f50

Browse files
authored
feat: sorting kv and regex filtering (#81)
- Sorting support for envx --kv (i spend a lot of time in this mode since it's not viewable but fits all our keys on screen) <img width="614" height="186" alt="image" src="https://github.com/user-attachments/assets/dba58185-10b3-46a4-a684-a7fd82b22e2e" /> - Filtering support (grep has been unreliable for finding things and it makes sense to have a first-class filter argument) <img width="179" height="218" alt="image" src="https://github.com/user-attachments/assets/66825c6f-46ea-4f70-a774-e7b8b25ab227" />
1 parent 6cdf498 commit 2fa9f50

2 files changed

Lines changed: 38 additions & 10 deletions

File tree

src/commands/unset.rs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,20 +29,29 @@ pub async fn command(args: Args, config: &mut Config) -> Result<()> {
2929
false => Some(Choice::try_project(args.project_id, &key).await?),
3030
};
3131

32-
let variable = match args.variable {
33-
Some(v) => v,
32+
let variables = match args.variable {
33+
Some(v) => vec![v],
3434
None => {
35-
let variables = if let Some(project_id) = project_id {
35+
let mut variables = if let Some(project_id) = project_id {
3636
SDK::get_variables(&project_id, &key).await?
3737
} else {
3838
SDK::get_all_variables(&key).await?
3939
};
4040

41-
prompt::prompt_options("Select variable to delete", variables)?.id
41+
variables.sort_by(|a, b| a.value.key.cmp(&b.value.key));
42+
prompt::prompt_multi_options(
43+
"Select variables to delete:",
44+
variables,
45+
)?
46+
.into_iter()
47+
.map(|v| v.id)
48+
.collect()
4249
}
4350
};
4451

45-
SDK::delete_variable(&variable, &key).await?;
52+
for variable in &variables {
53+
SDK::delete_variable(variable, &key).await?;
54+
}
4655

4756
Ok(())
4857
}

src/commands/variables.rs

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,27 @@ use crate::utils::{
33
btreemap::ToBTreeMap, choice::Choice, config::Config,
44
magic_variables::get_variables_magic, table::Table,
55
};
6+
use regex::Regex;
67
/// Get all environment variables for the current configured directory
78
#[derive(Parser)]
89
pub struct Args {
9-
#[clap(short, long)]
10+
#[arg(short, long)]
1011
project_id: Option<String>,
1112

13+
/// Filter variables by regex syntax
14+
#[arg(short, long)]
15+
filter: Option<String>,
16+
1217
/// Output as JSON - JSON has the highest precedence and will override other output formats
13-
#[clap(long)]
18+
#[arg(long)]
1419
json: bool,
1520

1621
/// Output as a list of key=value pairs
17-
#[clap(long)]
22+
#[arg(long)]
1823
kv: bool,
1924

2025
/// Output all variables (this project only)
21-
#[clap(short, long, default_value_t = false)]
26+
#[arg(short, long, default_value_t = false)]
2227
all: bool,
2328
}
2429

@@ -29,10 +34,24 @@ pub async fn command(args: Args, config: &mut Config) -> Result<()> {
2934
let key = key.unlock(&config.primary_key_password()?);
3035
let project_id = Choice::try_project(args.project_id, &key).await?;
3136

32-
let kvpairs = get_variables_magic(&project_id, &key, args.all).await?;
37+
let mut kvpairs = get_variables_magic(&project_id, &key, args.all).await?;
38+
if let Some(filter) = &args.filter {
39+
let re = Regex::new(filter)?;
40+
kvpairs.retain(|kv| re.is_match(&kv.key));
41+
if !matches!(mode, Mode::Json) {
42+
for kv in &mut kvpairs {
43+
kv.key = re
44+
.replace_all(&kv.key, |caps: &regex::Captures| {
45+
format!("{}", caps[0].red().bold())
46+
})
47+
.to_string();
48+
}
49+
}
50+
}
3351

3452
match mode {
3553
Mode::KV => {
54+
kvpairs.sort_by(|a, b| a.key.cmp(&b.key));
3655
kvpairs.iter().for_each(|kv| println!("{}", kv));
3756
}
3857
Mode::Json => {

0 commit comments

Comments
 (0)