From 5372793a49567dcba7315bf8e7bc5a1cab2d5a76 Mon Sep 17 00:00:00 2001 From: 魏曹先生 <1992414357@qq.com> Date: Wed, 18 Mar 2026 22:49:50 +0800 Subject: Add support for reading from stdin and improve error messages --- src/bin/jvn.rs | 50 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) (limited to 'src/bin/jvn.rs') diff --git a/src/bin/jvn.rs b/src/bin/jvn.rs index 062eab8..fd01431 100644 --- a/src/bin/jvn.rs +++ b/src/bin/jvn.rs @@ -1,4 +1,8 @@ -use std::{ops::Deref, process::exit}; +use std::{ + ops::Deref, + path::{Path, PathBuf}, + process::exit, +}; use cli_utils::legacy::{display::md, env::current_locales, levenshtein_distance}; use just_enough_vcs_cli::{ @@ -23,6 +27,7 @@ use just_progress::{ }; use log::{LevelFilter, error, info, trace, warn}; use rust_i18n::{set_locale, t}; +use tokio::io::AsyncReadExt; rust_i18n::i18n!("resources/locales/jvn", fallback = "en"); @@ -115,6 +120,18 @@ async fn main() { info!("{}", t!("verbose.user_input", command = args.join(" "))); + // Read pipe inpuit + let (stdin_path, stdin_data) = match read_all_from_stdin().await { + Ok((path, data)) => { + if data.is_empty() { + (None, None) + } else { + (path, Some(data)) + } + } + Err(_) => (None, None), + }; + // Build process future let args_clone = args.clone(); let process_future = jv_cmd_process( @@ -124,6 +141,8 @@ async fn main() { confirmed, args: args.clone(), lang, + stdin_path, + stdin_data, }, renderer_override, ); @@ -198,6 +217,35 @@ async fn main() { } } +/// Read path or raw information from standard input +async fn read_all_from_stdin() -> tokio::io::Result<(Option, Vec)> { + if atty::is(atty::Stream::Stdin) { + return Ok((None, Vec::new())); + } + + let mut stdin = tokio::io::stdin(); + let mut buffer = Vec::new(); + + stdin.read_to_end(&mut buffer).await?; + + if buffer.is_empty() { + return Ok((None, Vec::new())); + } + + let path = if let Ok(input_str) = String::from_utf8(buffer.clone()) { + let trimmed = input_str.trim(); + if !trimmed.is_empty() && Path::new(trimmed).exists() { + Some(PathBuf::from(trimmed)) + } else { + None + } + } else { + None + }; + + Ok((path, buffer)) +} + fn handle_no_matching_command_error(args: Vec) { let mut similar_nodes: Vec = Vec::new(); for node in jv_cmd_nodes() { -- cgit