|
|
|
@ -18,6 +18,7 @@ use anyhow::{Context, Result};
|
|
|
|
|
|
|
|
|
|
use crate::{error::Error, log::*};
|
|
|
|
|
|
|
|
|
|
#[allow(dead_code)]
|
|
|
|
|
fn log_output_mode(mode: Console::CONSOLE_MODE) {
|
|
|
|
|
// Characters written by the WriteFile or WriteConsole function or echoed by the ReadFile or
|
|
|
|
|
// ReadConsole function are parsed for ASCII control sequences, and the correct action is
|
|
|
|
@ -122,8 +123,8 @@ fn setup_stdout() -> Result<()> {
|
|
|
|
|
unsafe {
|
|
|
|
|
let handle = stdout_handle()?;
|
|
|
|
|
if Console::GetConsoleMode(handle, &mut mode).as_bool() {
|
|
|
|
|
debug!("Stdout details:");
|
|
|
|
|
log_output_mode(mode);
|
|
|
|
|
// debug!("Stdout details:");
|
|
|
|
|
// log_output_mode(mode);
|
|
|
|
|
} else {
|
|
|
|
|
return Err(Error::last_error().into());
|
|
|
|
|
}
|
|
|
|
@ -143,58 +144,61 @@ fn newline(stdout: HANDLE) -> Result<()> {
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn eval(line: String) -> Result<()> {
|
|
|
|
|
let parts: Vec<&str> = line.split_whitespace().collect();
|
|
|
|
|
if parts.len() == 0 {
|
|
|
|
|
return Ok(());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let cmd = parts[0];
|
|
|
|
|
match cmd {
|
|
|
|
|
fn eval(cmd: String, args: Vec<&str>) -> Result<bool> {
|
|
|
|
|
match cmd.as_str() {
|
|
|
|
|
"pwd" => {
|
|
|
|
|
let pb = std::env::current_dir()?;
|
|
|
|
|
println!("{}", pb.as_path().as_os_str().to_str().unwrap());
|
|
|
|
|
return Ok(());
|
|
|
|
|
return Ok(true);
|
|
|
|
|
}
|
|
|
|
|
"cd" => {
|
|
|
|
|
let cwd = std::env::current_dir()?;
|
|
|
|
|
if parts.len() > 1 {
|
|
|
|
|
let target = cwd.join(parts[1]);
|
|
|
|
|
if args.len() > 0 {
|
|
|
|
|
let target = cwd.join(args[0]);
|
|
|
|
|
std::env::set_current_dir(target)?;
|
|
|
|
|
return Ok(());
|
|
|
|
|
}
|
|
|
|
|
return Ok(true);
|
|
|
|
|
}
|
|
|
|
|
"printenv" => {
|
|
|
|
|
if parts.len() > 1 {
|
|
|
|
|
let name = parts[1];
|
|
|
|
|
if args.len() > 0 {
|
|
|
|
|
let name = args[0];
|
|
|
|
|
match std::env::var(name) {
|
|
|
|
|
Ok(val) => println!("{}", val),
|
|
|
|
|
Err(e) => println!("ERROR {}", e),
|
|
|
|
|
Ok(val) => {
|
|
|
|
|
println!("{}", val);
|
|
|
|
|
return Ok(true);
|
|
|
|
|
}
|
|
|
|
|
Err(e) => {
|
|
|
|
|
println!("ERROR {}", e);
|
|
|
|
|
return Ok(false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
println!("which variable you fucking dork");
|
|
|
|
|
return Ok(false);
|
|
|
|
|
}
|
|
|
|
|
return Ok(());
|
|
|
|
|
}
|
|
|
|
|
"which" => {
|
|
|
|
|
if parts.len() > 1 {
|
|
|
|
|
if args.len() > 0 {
|
|
|
|
|
let path = std::env::var("path").unwrap();
|
|
|
|
|
let dirs: Vec<&str> = path.split(";").collect();
|
|
|
|
|
for d in dirs {
|
|
|
|
|
let dir = std::path::Path::new(d);
|
|
|
|
|
let fname = dir.join(parts[1]).with_extension("exe");
|
|
|
|
|
let fname = dir.join(args[0]).with_extension("exe");
|
|
|
|
|
if fname.exists() && fname.is_file() {
|
|
|
|
|
println!("{}", fname.to_str().unwrap());
|
|
|
|
|
return Ok(());
|
|
|
|
|
return Ok(true);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
println!("not found: {}", parts[1]);
|
|
|
|
|
return Ok(());
|
|
|
|
|
println!("not found: {}", args[0]);
|
|
|
|
|
return Ok(false);
|
|
|
|
|
} else {
|
|
|
|
|
println!("what do you want to look for?");
|
|
|
|
|
return Ok(false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
"tail" => {
|
|
|
|
|
if parts.len() > 1 {
|
|
|
|
|
let fname = parts[1];
|
|
|
|
|
if args.len() > 0 {
|
|
|
|
|
let fname = args[0];
|
|
|
|
|
let stdout = stdout_handle()?;
|
|
|
|
|
match File::options().read(true).open(fname) {
|
|
|
|
|
Ok(mut f) => {
|
|
|
|
@ -218,37 +222,40 @@ fn eval(line: String) -> Result<()> {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Err(e) => { println!("failed to open file: {}", e); }
|
|
|
|
|
Err(e) => {
|
|
|
|
|
println!("failed to open file: {}", e);
|
|
|
|
|
return Err(e.into());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
println!("need a file name");
|
|
|
|
|
return Ok(false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
"echo" => {
|
|
|
|
|
let rest: Vec<&str> = parts[1..].to_vec();
|
|
|
|
|
println!("{:?}", rest);
|
|
|
|
|
println!("{}", args.join(" "));
|
|
|
|
|
return Ok(true);
|
|
|
|
|
}
|
|
|
|
|
_ => {
|
|
|
|
|
let mut proc = std::process::Command::new(cmd);
|
|
|
|
|
if parts.len() > 1 {
|
|
|
|
|
let args = parts[1..].to_vec();
|
|
|
|
|
if args.len() > 0 {
|
|
|
|
|
proc.args(args);
|
|
|
|
|
}
|
|
|
|
|
match proc.spawn() {
|
|
|
|
|
Ok(mut child) => {
|
|
|
|
|
if let Err(e) = child.wait() {
|
|
|
|
|
println!("error: {}", e)
|
|
|
|
|
println!("error: {}", e);
|
|
|
|
|
return Err(e.into());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Err(e) => {
|
|
|
|
|
println!("error: {}", e)
|
|
|
|
|
println!("error: {}", e);
|
|
|
|
|
return Ok(false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return Ok(());
|
|
|
|
|
return Ok(true);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// println!("Error: no such command: {}", cmd);
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn main() -> Result<()> {
|
|
|
|
@ -270,8 +277,8 @@ fn main() -> Result<()> {
|
|
|
|
|
let mut input = input::Reader::new()?;
|
|
|
|
|
|
|
|
|
|
prompt.print()?;
|
|
|
|
|
info!("» enter");
|
|
|
|
|
loop {
|
|
|
|
|
// debug!("----------------------------------------");
|
|
|
|
|
match input.next()? {
|
|
|
|
|
input::Event::Key(event) => {
|
|
|
|
|
if event.down {
|
|
|
|
@ -286,8 +293,20 @@ fn main() -> Result<()> {
|
|
|
|
|
|
|
|
|
|
if event.code == key::ENTER {
|
|
|
|
|
newline(stdout)?;
|
|
|
|
|
if let Err(e) = eval(line.pop()) {
|
|
|
|
|
let s = line.pop();
|
|
|
|
|
let parts: Vec<&str> = s.split_whitespace().collect();
|
|
|
|
|
if parts.len() > 0 {
|
|
|
|
|
let cmd = parts[0].to_string();
|
|
|
|
|
let args = if parts.len() > 1 { parts[1..].to_vec() } else { vec![] };
|
|
|
|
|
debug!("◇ {}", cmd.clone());
|
|
|
|
|
match eval(cmd.clone(), args) {
|
|
|
|
|
Ok(true) => info!("▷ {}", cmd),
|
|
|
|
|
Ok(false) => warn!("▷ {}", cmd),
|
|
|
|
|
Err(e) => {
|
|
|
|
|
error!("▷ {}: {}", cmd, e);
|
|
|
|
|
println!("error: {}", e);
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
prompt.print()?;
|
|
|
|
|
continue;
|
|
|
|
@ -321,7 +340,7 @@ fn main() -> Result<()> {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if event.ctrl && event.code == key::D {
|
|
|
|
|
debug!("⎈ d: exit");
|
|
|
|
|
info!("» exit");
|
|
|
|
|
unsafe {
|
|
|
|
|
CloseHandle(stdout);
|
|
|
|
|
}
|
|
|
|
@ -381,6 +400,7 @@ fn main() -> Result<()> {
|
|
|
|
|
warn!("‽ {}", event);
|
|
|
|
|
}
|
|
|
|
|
input::Event::Left => {
|
|
|
|
|
debug!("⛬ ←");
|
|
|
|
|
if line.back() {
|
|
|
|
|
unsafe {
|
|
|
|
|
let text = "\x1b[D"; // lol this sucks
|
|
|
|
@ -389,6 +409,7 @@ fn main() -> Result<()> {
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
input::Event::Right => {
|
|
|
|
|
debug!("⛬ →");
|
|
|
|
|
if line.forward() {
|
|
|
|
|
unsafe {
|
|
|
|
|
let text = "\x1b[C"; // lol this sucks
|
|
|
|
@ -396,8 +417,12 @@ fn main() -> Result<()> {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
input::Event::Up => {},
|
|
|
|
|
input::Event::Down => {},
|
|
|
|
|
input::Event::Up => {
|
|
|
|
|
debug!("⛬ ↑");
|
|
|
|
|
},
|
|
|
|
|
input::Event::Down => {
|
|
|
|
|
debug!("⛬ ↓");
|
|
|
|
|
},
|
|
|
|
|
input::Event::Home => {},
|
|
|
|
|
input::Event::End => {},
|
|
|
|
|
input::Event::Focus(true) => {},
|
|
|
|
|