Skip to content

Commit

Permalink
Add ability to take glob patterns from stdin
Browse files Browse the repository at this point in the history
as requested in issue solidiquis#51

This adds a new (hidden) flag `--stdin` to indicate that `et` should
take input from stdin. Since the naming convention is to use `-` for
this, we replace the args `-` with `--stdin` before we hand them over
to Clap.

Example usage:
```shell
$ touch hello.rs helLo.rs HELlo.rs
$  fd -e rs '^hel[lL]o' | et -
           erdtree
     0   B ├─ hello.rs
     0   B └─ helLo.rs
```
  • Loading branch information
jhscheer committed Apr 3, 2023
1 parent 2fb0cae commit a618a7a
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 4 deletions.
17 changes: 15 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@
)]
use clap::CommandFactory;
use render::{context::Context, tree::Tree};
use std::{io::stdout, process::ExitCode};
use std::{
io::{stdout, BufRead},
process::ExitCode,
};

/// Filesystem operations.
mod fs;
Expand All @@ -44,7 +47,17 @@ fn main() -> ExitCode {
}

fn run() -> Result<(), Box<dyn std::error::Error>> {
let ctx = Context::init()?;
let mut ctx = Context::init()?;

if ctx.stdin {
let mut stdin_lines = std::io::stdin()
.lock()
.lines()
.filter_map(|s| s.ok())
.filter(|l| !l.is_empty())
.collect::<Vec<String>>();
ctx.glob.append(&mut stdin_lines);
}

if let Some(shell) = ctx.completions {
clap_complete::generate(shell, &mut Context::command(), "et", &mut stdout().lock());
Expand Down
13 changes: 11 additions & 2 deletions src/render/context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ pub struct Context {

/// Include or exclude files using glob patterns
#[arg(short, long)]
glob: Vec<String>,
pub glob: Vec<String>,

/// Include or exclude files using glob patterns; case insensitive
#[arg(long)]
Expand Down Expand Up @@ -128,13 +128,22 @@ pub struct Context {
/// Don't read configuration file
#[arg(long)]
pub no_config: bool,

/// Take input from Stdin
#[arg(long, hide = true)]
pub stdin: bool,
}

impl Context {
/// Initializes [Context], optionally reading in the configuration file to override defaults.
/// Arguments provided will take precedence over config.
pub fn init() -> Result<Self, Error> {
let user_args = Self::command().args_override_self(true).get_matches();
let mut args: Vec<_> = std::env::args().collect();
crate::utils::detect_stdin(&mut args);

let user_args = Self::command()
.args_override_self(true)
.get_matches_from(args);

let no_config = user_args.get_one("no_config").map_or(false, bool::clone);

Expand Down
18 changes: 18 additions & 0 deletions src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,21 @@ where
.filter(|item| set.insert(item.to_owned()))
.collect::<Vec<T>>()
}

/// Follow the naming convention and use "-" to specify a Standard Input.
/// Retain "-" from [`args`] and add "--stdin" if necessary.
pub fn detect_stdin(args: &mut Vec<String>) {
let dash = String::from("-");
let stdin_flag = String::from("--stdin");

let mut is_stdin = false;
args.retain(|e| {
if *e == dash {
is_stdin = true
};
*e != dash
});
if is_stdin && !args.contains(&stdin_flag) {
args.push(stdin_flag)
}
}

0 comments on commit a618a7a

Please sign in to comment.