aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib.rs')
-rw-r--r--src/lib.rs101
1 files changed, 69 insertions, 32 deletions
diff --git a/src/lib.rs b/src/lib.rs
index cf57cee..2af7e08 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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());