Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 8 additions & 22 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,10 @@ use crate::utils::*;

use anyhow::{bail, Result};
use clap::Parser;
use inquire::validator::Validation;
use inquire::Text;
use is_terminal::IsTerminal;
use parking_lot::RwLock;
use simplelog::{format_description, ConfigBuilder, LevelFilter, SimpleLogger, WriteLogger};
use std::{env, io::stdin, process, sync::Arc};
use std::{env, process, sync::Arc};

#[tokio::main]
async fn main() -> Result<()> {
Expand Down Expand Up @@ -262,9 +260,6 @@ async fn shell_execute(
return Ok(());
}
if *IS_STDOUT_TERMINAL {
if cfg!(target_os = "macos") && !stdin().is_terminal() {
bail!("Unable to read the pipe for shell execution on MacOS")
}
let options = ["execute", "revise", "describe", "copy", "quit"];
let command = color_text(eval_str.trim(), nu_ansi_term::Color::Rgb(255, 165, 0));
let first_letter_color = nu_ansi_term::Color::Cyan;
Expand All @@ -275,34 +270,25 @@ async fn shell_execute(
.join(&dimmed_text(" | "));
loop {
println!("{command}");
let answer = Text::new(&format!("{prompt_text}:"))
.with_default("e")
.with_validator(
|input: &str| match matches!(input, "e" | "r" | "d" | "c" | "q") {
true => Ok(Validation::Valid),
false => Ok(Validation::Invalid(
"Invalid option, choice one of e, r, d, c or q".into(),
)),
},
)
.prompt()?;
let answer_char =
read_single_key(&['e', 'r', 'd', 'c', 'q'], 'e', &format!("{prompt_text}: "))?;

match answer.as_str() {
"e" => {
match answer_char {
'e' => {
debug!("{} {:?}", shell.cmd, &[&shell.arg, &eval_str]);
let code = run_command(&shell.cmd, &[&shell.arg, &eval_str], None)?;
if code == 0 && config.read().save_shell_history {
let _ = append_to_shell_history(&shell.name, &eval_str, code);
}
process::exit(code);
}
"r" => {
'r' => {
let revision = Text::new("Enter your revision:").prompt()?;
let text = format!("{}\n{revision}", input.text());
input.set_text(text);
return shell_execute(config, shell, input, abort_signal.clone()).await;
}
"d" => {
'd' => {
let role = config.read().retrieve_role(EXPLAIN_SHELL_ROLE)?;
let input = Input::from_str(config, &eval_str, Some(role));
if input.stream() {
Expand All @@ -325,7 +311,7 @@ async fn shell_execute(
println!();
continue;
}
"c" => {
'c' => {
set_text(&eval_str)?;
println!("{}", dimmed_text("✓ Copied the command."));
}
Expand Down
47 changes: 47 additions & 0 deletions src/utils/input.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
use anyhow::Result;
use crossterm::event::{self, Event, KeyCode, KeyEvent, KeyModifiers};
use crossterm::terminal::{disable_raw_mode, enable_raw_mode};
use std::io::{stdout, Write};

/// Reads a single character from stdin without requiring Enter
/// Returns the character if it's one of the valid options, or the default if Enter is pressed
pub fn read_single_key(valid_chars: &[char], default: char, prompt: &str) -> Result<char> {
print!("{prompt}");
stdout().flush()?;

enable_raw_mode()?;

let result = loop {
if let Ok(Event::Key(KeyEvent {
code, modifiers, ..
})) = event::read()
{
match code {
KeyCode::Char('c') if modifiers.contains(KeyModifiers::CONTROL) => {
break Err(anyhow::anyhow!("Interrupted"));
}
KeyCode::Char(c) => {
if valid_chars.contains(&c) {
break Ok(c);
}
// Invalid character, continue loop
}
KeyCode::Enter => {
break Ok(default);
}
_ => {
// Other keys are ignored, continue loop
}
}
}
};

disable_raw_mode()?;

// Print the chosen character and newline for clean output
if let Ok(chosen) = &result {
println!("{chosen}");
}

result
}
2 changes: 2 additions & 0 deletions src/utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ mod clipboard;
mod command;
mod crypto;
mod html_to_md;
mod input;
mod loader;
mod path;
mod render_prompt;
Expand All @@ -15,6 +16,7 @@ pub use self::clipboard::set_text;
pub use self::command::*;
pub use self::crypto::*;
pub use self::html_to_md::*;
pub use self::input::*;
pub use self::loader::*;
pub use self::path::*;
pub use self::render_prompt::render_prompt;
Expand Down
Loading