aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonas Maier <>2026-05-24 09:47:29 +0200
committerJonas Maier <>2026-05-24 09:47:29 +0200
commit36cbfcaafcb8a3b1c47650439531a35c99b203ea (patch)
tree975b49ab8893a1ec1069d0a775f1703576247dd3
parent7cd15fe67ca0118520dcc4e9e189d513b0375e10 (diff)
downloadpish-36cbfcaafcb8a3b1c47650439531a35c99b203ea.tar.gz
terminal prompt from ps1 module now
-rw-r--r--src/lib.rs46
-rw-r--r--src/ps1.rs11
-rw-r--r--src/run/mod.rs14
3 files changed, 48 insertions, 23 deletions
diff --git a/src/lib.rs b/src/lib.rs
index 6ecbe83..c2b4a4a 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -45,6 +45,7 @@ use crate::ctrlc::CtrlC;
use crate::history::HistoryEntry;
use crate::line::Line;
use crate::parse::{Block, ExpString, Parse, PostExpansion};
+use crate::ps1::Prompt;
macro_rules! print {
($($x:tt)*) => {{
@@ -112,24 +113,26 @@ pub struct Session {
ascii_keybinds: HashMap<BString, parse::Command<PostExpansion>>,
debug_keystrokes: bool,
- loud: bool,
/// n before end of history.len()
/// 0 == not checking history
history_visit: usize,
highlighter: syntax_highlighting::Highlighter,
+ prompt: Prompt,
}
impl Session {
pub fn new_noninteractive() -> Self {
+ let mut vars = run::Vars::default();
+ let prompt = Prompt::new(&mut vars);
+
Self {
raw: None,
line: Line::new(),
history: Vec::new(),
prev_path: b".".into(),
builtins: HashMap::new(),
- vars: run::Vars::default(),
funs: HashMap::new(),
aliases: run::Aliases::new(),
socket_running: None,
@@ -138,9 +141,10 @@ impl Session {
ti_keybinds: HashMap::new(),
ascii_keybinds: HashMap::new(),
debug_keystrokes: false,
- loud: false,
history_visit: 0,
highlighter: syntax_highlighting::Highlighter::new(),
+ prompt,
+ vars,
}
}
}
@@ -183,17 +187,14 @@ fn pretty_cwd() -> BString {
}
impl Session {
- fn prompt(_this: Arc<Mutex<Self>>) -> BString {
- todo!("replace with ps1 module");
- }
-
fn prompt_clear(&mut self) {
self.line.clear_prompt().unwrap();
self.history_visit = 0;
}
fn reprint_prompt(this: Arc<Mutex<Self>>) {
- io::stdout().write_all(&Self::prompt(this.clone())).unwrap();
+ let prompt = this.lock().unwrap().prompt.prompt().to_vec();
+ io::stdout().write_all(&prompt).unwrap();
let mut this = this.lock().unwrap();
this.line.display_pre();
this.line.display_post(b"");
@@ -271,6 +272,23 @@ impl Session {
}
}
+ fn reevaluate_prompt_inner(&mut self) -> bool {
+ if self.prompt.requires_update(&self.vars) {
+ self.prompt.load_prompt(&mut self.vars);
+ true
+ } else {
+ false
+ }
+ }
+
+ fn reevaluate_prompt(se: Arc<Mutex<Session>>) {
+ if se.lock().unwrap().reevaluate_prompt_inner() {
+ let mut prompt = se.lock().unwrap().prompt.clone();
+ prompt.eval_prompt(se.clone());
+ se.lock().unwrap().prompt = prompt;
+ }
+ }
+
fn try_submit_command(session: Arc<Mutex<Session>>) {
let mut se = session.lock().unwrap();
let line = se.line.into_bytes();
@@ -291,7 +309,14 @@ impl Session {
se.history_visit = 0;
se.line.dump();
drop(se);
- run::run(session.clone(), parsed);
+
+ let status_string = run::run(session.clone(), parsed);
+ if !status_string.is_empty() {
+ println!("{status_string}");
+ }
+ Self::reevaluate_prompt(session.clone());
+ Self::reprint_prompt(session);
+ let _ = std::io::stdout().lock().flush();
}
}
@@ -371,7 +396,8 @@ pub fn event_loop() {
let session = Arc::new(Mutex::new(se));
exec_rc_file(session.clone());
- session.lock().unwrap().loud = true;
+ Session::reevaluate_prompt(session.clone());
+
Session::reprint_prompt(session.clone());
completion::populate_path_cache(session.clone());
diff --git a/src/ps1.rs b/src/ps1.rs
index 05b5886..38beebb 100644
--- a/src/ps1.rs
+++ b/src/ps1.rs
@@ -5,7 +5,7 @@ use crate::parse::{ExpString, Parse};
use crate::run::{Vars, WatchId};
use crate::{BString, Session, bstr};
-pub const PROMPT_VAR: &str = "PROMPT";
+pub const PROMPT_VAR: &bstr = b"PROMPT";
#[allow(unused)]
const DEFAULT_PROMPT_VALUE_DEBUG: &bstr = b"dev [$CWD_PRETTY]# ";
@@ -19,6 +19,7 @@ pub const DEFAULT_PROMPT_VALUE: &bstr = DEFAULT_PROMPT_VALUE_DEBUG;
#[cfg(not(debug_assertions))]
pub const DEFAULT_PROMPT_VALUE: &bstr = DEFAULT_PROMPT_VALUE_RELEASE;
+#[derive(Clone)]
pub struct Prompt {
watch_var: WatchId,
watch_content: Option<WatchId>,
@@ -28,8 +29,12 @@ pub struct Prompt {
impl Prompt {
pub fn new(vars: &mut Vars) -> Self {
+ if vars.lookup(PROMPT_VAR).is_none() {
+ vars.set(PROMPT_VAR.to_owned(), DEFAULT_PROMPT_VALUE.to_owned());
+ }
+
Self {
- watch_var: vars.watch(vec![PROMPT_VAR.as_bytes().to_vec()]),
+ watch_var: vars.watch(vec![PROMPT_VAR.to_vec()]),
watch_content: None,
parsed: None,
cached_prompt: None,
@@ -45,7 +50,7 @@ impl Prompt {
pub fn load_prompt(&mut self, vars: &mut Vars) {
if vars.pop_dirty(&self.watch_var) {
let prompt = vars
- .lookup(PROMPT_VAR.as_bytes())
+ .lookup(PROMPT_VAR)
.map(Cow::into_owned)
.unwrap_or_else(|| DEFAULT_PROMPT_VALUE.to_vec());
let parsed = parse_prompt(prompt);
diff --git a/src/run/mod.rs b/src/run/mod.rs
index dc715b1..a2a6cb1 100644
--- a/src/run/mod.rs
+++ b/src/run/mod.rs
@@ -614,20 +614,14 @@ pub fn run_quiet(
exec.exec_loop(cmd, &mut [c1, c2])
}
-pub fn run(se: Arc<Mutex<Session>>, parsed: Ast<PreExpansion>) {
+pub fn run(se: Arc<Mutex<Session>>, parsed: Ast<PreExpansion>) -> String {
se.lock().unwrap().raw_disable();
let result = exec(se.clone(), parsed);
se.lock().unwrap().raw_enable();
- if se.lock().unwrap().loud {
- let status_string = match result {
- Ok(_) => String::new(),
- Err(e) => format!("{}\r\n", e.error_message()),
- };
-
- print!("\r{status_string}");
- Session::reprint_prompt(se);
- let _ = std::io::stdout().lock().flush();
+ match result {
+ Ok(_) => String::new(),
+ Err(e) => format!("{}", e.error_message()),
}
}