mirror of
https://github.com/denisidoro/navi
synced 2024-11-25 04:50:21 +00:00
8725654a74
Fixes #645
86 lines
2.3 KiB
Rust
86 lines
2.3 KiB
Rust
use crate::config::CONFIG;
|
|
use anyhow::Result;
|
|
use std::fmt::Debug;
|
|
use std::io::{self, Read};
|
|
use std::process::Command;
|
|
use thiserror::Error;
|
|
|
|
pub const EOF: &str = "NAVIEOF";
|
|
|
|
#[derive(Debug)]
|
|
pub enum Shell {
|
|
Bash,
|
|
Zsh,
|
|
Fish,
|
|
Elvish,
|
|
}
|
|
|
|
#[derive(Error, Debug)]
|
|
#[error("Failed to spawn child process `bash` to execute `{command}`")]
|
|
pub struct ShellSpawnError {
|
|
command: String,
|
|
#[source]
|
|
source: anyhow::Error,
|
|
}
|
|
|
|
impl ShellSpawnError {
|
|
pub fn new<SourceError>(command: impl Into<String>, source: SourceError) -> Self
|
|
where
|
|
SourceError: std::error::Error + Sync + Send + 'static,
|
|
{
|
|
ShellSpawnError {
|
|
command: command.into(),
|
|
source: source.into(),
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn out() -> Command {
|
|
let words_str = CONFIG.shell();
|
|
let mut words_vec = shellwords::split(&words_str).expect("empty shell command");
|
|
let mut words = words_vec.iter_mut();
|
|
let first_cmd = words.next().expect("absent shell binary");
|
|
let mut cmd = Command::new(&first_cmd);
|
|
cmd.args(words);
|
|
let dash_c = if words_str.contains("cmd.exe") { "/c" } else { "-c" };
|
|
cmd.arg(dash_c);
|
|
cmd
|
|
}
|
|
|
|
pub fn widget_last_command() -> Result<()> {
|
|
let mut text = String::new();
|
|
io::stdin().read_to_string(&mut text)?;
|
|
|
|
let replacements = vec![("||", "ග"), ("|", "ඛ"), ("&&", "ඝ")];
|
|
|
|
let parts = shellwords::split(&text).unwrap_or_else(|_| text.split('|').map(|s| s.to_string()).collect());
|
|
|
|
for p in parts {
|
|
for (pattern, escaped) in replacements.clone() {
|
|
if p.contains(pattern) && p != pattern && p != format!("{}{}", pattern, pattern) {
|
|
let replacement = p.replace(pattern, escaped);
|
|
text = text.replace(&p, &replacement);
|
|
}
|
|
}
|
|
}
|
|
|
|
let mut extracted = text.clone();
|
|
|
|
for (pattern, _) in replacements.clone() {
|
|
let mut new_parts = text.rsplit(pattern);
|
|
if let Some(extracted_attempt) = new_parts.next() {
|
|
if extracted_attempt.len() <= extracted.len() {
|
|
extracted = extracted_attempt.to_string();
|
|
}
|
|
}
|
|
}
|
|
|
|
for (pattern, escaped) in replacements.clone() {
|
|
text = text.replace(&escaped, pattern);
|
|
extracted = extracted.replace(&escaped, pattern);
|
|
}
|
|
|
|
println!("{}", extracted.trim_start());
|
|
|
|
Ok(())
|
|
}
|