diff options
Diffstat (limited to 'src/lib.rs')
| -rw-r--r-- | src/lib.rs | 101 |
1 files changed, 69 insertions, 32 deletions
@@ -8,7 +8,6 @@ use std::collections::HashMap; use std::ffi::OsStr; use std::fs::{self, File}; -use std::hash::Hash; use std::io::{self, Read, Write}; use std::os::unix::ffi::OsStrExt; use std::os::unix::io::AsRawFd; @@ -79,6 +78,18 @@ type BString = Vec<u8>; #[allow(non_camel_case_types)] type bstr = [u8]; +trait PushAll { + fn push_all(&mut self, other: &bstr); +} + +impl PushAll for BString { + fn push_all(&mut self, other: &bstr) { + for &c in other { + self.push(c); + } + } +} + pub struct Session { raw: Option<ScopedRawMode>, line: LineBuf, @@ -142,35 +153,60 @@ fn relative_path(root: &Path, target: &Path) -> Option<String> { } } -impl Session { - fn pretty_cwd_res(&self) -> io::Result<String> { - let dir = std::env::current_dir()?; - let mut s = if let Some(home_dir) = std::env::home_dir() { - if let Some(rela) = relative_path(&home_dir, &dir) { - format!("~{rela}") - } else { - dir.to_string_lossy().to_string() - } +fn pretty_cwd_res() -> io::Result<String> { + let dir = std::env::current_dir()?; + let mut s = if let Some(home_dir) = std::env::home_dir() { + if let Some(rela) = relative_path(&home_dir, &dir) { + format!("~{rela}") } else { dir.to_string_lossy().to_string() - }; - while s.ends_with("/") && s.len() > 1 { - s.remove(s.len() - 1); } - Ok(s) + } else { + dir.to_string_lossy().to_string() + }; + while s.ends_with("/") && s.len() > 1 { + s.remove(s.len() - 1); } + Ok(s) +} - fn pretty_cwd(&self) -> String { - self.pretty_cwd_res().unwrap_or_else(|_| String::new()) +fn pretty_cwd() -> String { + pretty_cwd_res().unwrap_or_else(|_| String::new()) +} + +impl Session { + fn load_unevaled_prompt(&self) -> BString { + match self.vars.get(&b"PROMPT"[..]) { + Some(prompt) => prompt.clone(), + None => { + let mut prompt = BString::new(); + if cfg!(debug_assertions) { + prompt.push_all(b"dev "); + } + prompt.push_all(b"[$CWD_PRETTY]# "); + prompt + } + } } - // TODO: prompt should be BString as well - fn prompt(&self) -> String { - #[cfg(debug_assertions)] - let dev = "dev "; - #[cfg(not(debug_assertions))] - let dev = ""; - format!("{dev}[{}]# ", self.pretty_cwd()) + fn prompt(this: Arc<Mutex<Self>>) -> BString { + let mut prompt = this.lock().unwrap().load_unevaled_prompt(); + let mut x = Vec::with_capacity(prompt.len() + 2); + x.push(b'"'); + x.append(&mut prompt); + x.push(b'"'); + let parsed = match crate::parse::ExpString::parse_from_bytes(&x) { + Ok(x) => x, + Err(e) => { + println!("{e:?}"); + return b"PARSE_ERROR$ ".to_vec(); + } + }; + let mut expander = run::Executor::new(this); + let Ok(expanded) = parsed.expand(&mut expander) else { + return b"EXEC_ERROR$ ".to_vec(); + }; + expanded } fn clear_prompt(&mut self) { @@ -187,10 +223,11 @@ impl Session { self.history_visit = 0; } - fn reprint_prompt(&self) { - print!("{}", self.prompt()); - self.line.display_pre(); - self.line.display_post(b""); + fn reprint_prompt(this: Arc<Mutex<Self>>) { + io::stdout().write_all(&Self::prompt(this.clone())).unwrap(); + let this = this.lock().unwrap(); + this.line.display_pre(); + this.line.display_post(b""); } fn display_historic_entry(&mut self) { @@ -372,7 +409,8 @@ impl Session { io::stdout().lock().write_all(&s.display).unwrap(); println!(); } - se.reprint_prompt(); + drop(se); + Self::reprint_prompt(session); } } @@ -400,9 +438,9 @@ impl Session { } } - fn screen_clear(&mut self) { + fn screen_clear(this: Arc<Mutex<Self>>) { clear_screen(); - self.reprint_prompt(); + Self::reprint_prompt(this); } fn raw_enable(&self) { @@ -461,8 +499,7 @@ pub fn event_loop() { exec_rc_file(session.clone()); session.lock().unwrap().loud = true; - - print!("{}", session.lock().unwrap().prompt()); + Session::reprint_prompt(session.clone()); completion::populate_path_cache(session.clone()); |
