shell fully configurable

This commit is contained in:
Ava Apples Affine 2023-03-23 11:52:36 -07:00
parent 1ce5fd3454
commit a711b32730
Signed by: affine
GPG key ID: 3A4645B8CF806069
4 changed files with 117 additions and 29 deletions

View file

@ -395,8 +395,12 @@ Errors during configuration are non-terminal. In such a case any defaults which
*** Configuration Values
- CFG_RELISH_POSIX (default false): when true, enables POSIX style job control.
- CFG_RELISH_ENV (default true): when true, interpreter's variable table and environment variable table are kept in sync.
- CFG_RELISH_PROMPT (default (echo "λ ")): A *function* definition which is called in order to output the prompt for each loop of the REPL.
This function will be reloaded each REPL loop and will be called by the interpreter with no arguments.
- CFG_RELISH_L_PROMPT (default 'λ'): a function that is called with no arguments to output the left hand of the prompt
- CFG_RELISH_R_PROMPT (default ''): a function that is called with no arguments to output the right hand of the prompt
- CFG_RELISH_PROMPT_DELIMITER (default '>'): a function that is called with no arguments to output the delimiter separating prompt from user input
*** Prompt design
For an example of prompt design see file:snippets/mood-prompt.rls
*** Further configuration
Further configuration can be done by loading scripts that contain more functions and data to evaluate.
@ -477,12 +481,16 @@ Note: this section will not show the status of each item unless you are viewing
Note: this section only tracks the state of incomplete TODO items. Having everything on here would be cluttered.
** TODO Pre-alpha tasks
- Shell prompt is fully configurable (History, L, R, and Delim)
- paths function
- add-path function
- Shell module
- Only loadable via POSIX config var
- Overload Load function to hook into this lib
- arg processor because these are control flow
- Process launching with environment variables
- "flag" function
- "switch" function
- "with" function (load with)
- Optional form of process which allows fd redirecting
- Background processes (bg function)
- Foreground process TTY (fg function)
@ -492,6 +500,9 @@ Note: this section only tracks the state of incomplete TODO items. Having everyt
- make const all the error messages
** TODO alpha tasks
- History length configurable
- Search delim configurable
- Escape sequences in strings
- Rename to Flesh
- master branch -> main branch
- Create a dedicated community channel on matrix.sunnypup.io

15
snippets/mood-prompt.rls Normal file
View file

@ -0,0 +1,15 @@
#!/bin/relish
(def __mood 'current mood' ':3')
(def CFG_RELISH_L_PROMPT 'mood left prompt'
() (concat "(" __mood ")" ))
(def CFG_RELISH_R_PROMPT 'mood right prompt'
() 'call set-mood to change prompt')
(def CFG_RELISH_PROMPT_DELIMITER 'mood prompt delim'
() '>')
(def set-mood 'set the little ascii face in your prompt'
(mood) (set (q __mood) mood))

View file

@ -28,22 +28,22 @@ use std::borrow::Cow;
use std::env;
#[derive(Clone)]
pub struct CustomPrompt<'a>(&'a str);
impl Prompt for CustomPrompt<'_> {
pub struct CustomPrompt(String, String, String);
impl Prompt for CustomPrompt {
fn render_prompt_left(&self) -> Cow<str> {
{
Cow::Owned(self.0.to_string())
Cow::Owned(self.0.to_owned())
}
}
fn render_prompt_right(&self) -> Cow<str> {
{
Cow::Owned(format!(""))
Cow::Owned(self.1.to_owned())
}
}
fn render_prompt_indicator(&self, _edit_mode: PromptEditMode) -> Cow<str> {
Cow::Owned("> ".to_string())
Cow::Owned(self.2.to_owned())
}
fn render_prompt_multiline_indicator(&self) -> Cow<str> {
@ -117,20 +117,7 @@ fn main() {
// repl :)
loop {
let s = *syms
.call_symbol(&"CFG_RELISH_PROMPT".to_string(), &Seg::new(), true)
.unwrap_or_else(|err: String| {
eprintln!("{}", err);
Box::new(Ctr::String("<prompt broken!>".to_string()))
});
let p_str: String;
if let Ctr::String(s) = s {
p_str = s;
} else {
p_str = s.to_string();
}
let readline_prompt = CustomPrompt(p_str.as_str());
let readline_prompt = make_prompt(&mut syms);
let user_doc = rl.read_line(&readline_prompt).unwrap();
match user_doc {
Signal::Success(line) => {
@ -156,3 +143,45 @@ fn main() {
}
}
}
fn make_prompt(syms: &mut SymTable) -> CustomPrompt {
let l_ctr = *syms
.call_symbol(&"CFG_RELISH_L_PROMPT".to_string(), &Seg::new(), true)
.unwrap_or_else(|err: String| {
eprintln!("{}", err);
Box::new(Ctr::String("<prompt broken!>".to_string()))
});
let r_ctr = *syms
.call_symbol(&"CFG_RELISH_R_PROMPT".to_string(), &Seg::new(), true)
.unwrap_or_else(|err: String| {
eprintln!("{}", err);
Box::new(Ctr::String("<prompt broken!>".to_string()))
});
let d_ctr = *syms
.call_symbol(&"CFG_RELISH_PROMPT_DELIMITER".to_string(), &Seg::new(), true)
.unwrap_or_else(|err: String| {
eprintln!("{}", err);
Box::new(Ctr::String("<prompt broken!>".to_string()))
});
let l_str: String;
let r_str: String;
let d_str: String;
if let Ctr::String(s) = l_ctr {
l_str = s;
} else {
l_str = l_ctr.to_string();
}
if let Ctr::String(s) = r_ctr {
r_str = s;
} else {
r_str = r_ctr.to_string();
}
if let Ctr::String(s) = d_ctr {
d_str = s;
} else {
d_str = d_ctr.to_string();
}
CustomPrompt(l_str, r_str, d_str)
}

View file

@ -25,8 +25,16 @@ use std::iter::FromIterator;
use std::env::{vars, var, current_dir};
use std::rc::Rc;
fn prompt_default_callback(_: &Seg, _: &mut SymTable) -> Result<Ctr, String> {
Ok(Ctr::Symbol("λ".to_string()))
fn l_prompt_default_callback(_: &Seg, _: &mut SymTable) -> Result<Ctr, String> {
Ok(Ctr::String("λ".to_string()))
}
fn r_prompt_default_callback(_: &Seg, _: &mut SymTable) -> Result<Ctr, String> {
Ok(Ctr::String(String::new()))
}
fn prompt_delimiter_default_callback(_: &Seg, _: &mut SymTable) -> Result<Ctr, String> {
Ok(Ctr::String(">".to_string()))
}
fn get_paths() -> Vec<String> {
@ -70,15 +78,40 @@ default value: 1 (set)
);
syms.insert(
"CFG_RELISH_PROMPT".to_string(),
"CFG_RELISH_L_PROMPT".to_string(),
Symbol {
name: String::from("default relish prompt"),
name: String::from("default relish left prompt"),
args: Args::None,
conditional_branches: false,
docs: "function called to output prompt. this function is called with no arguments.
default value (<lambda>)"
docs: "function called to output prompt on left hand. this function is called with no arguments."
.to_string(),
value: ValueType::Internal(Rc::new(prompt_default_callback)),
value: ValueType::Internal(Rc::new(l_prompt_default_callback)),
..Default::default()
},
);
syms.insert(
"CFG_RELISH_R_PROMPT".to_string(),
Symbol {
name: String::from("default relish right prompt"),
args: Args::None,
conditional_branches: false,
docs: "function called to output prompt on right hand. this function is called with no arguments."
.to_string(),
value: ValueType::Internal(Rc::new(r_prompt_default_callback)),
..Default::default()
},
);
syms.insert(
"CFG_RELISH_PROMPT_DELIMITER".to_string(),
Symbol {
name: String::from("default relish prompt delimiter"),
args: Args::None,
conditional_branches: false,
docs: "function called to output prompt delimiter. this function is called with no arguments."
.to_string(),
value: ValueType::Internal(Rc::new(prompt_delimiter_default_callback)),
..Default::default()
},
);