Browse Source

Working on the cursive TUI

typed
Weird Constructor 11 months ago
parent
commit
6cbe73acba
  1. 7
      rustfmt.toml
  2. 257
      src/stdlib/cursive.rs
  3. 10
      src/vval.rs

7
rustfmt.toml

@ -1,5 +1,2 @@
max_width=80
newline_style="Unix"
edition="2018"
brace_style="SameLineWhere"
disable_all_formatting=true
use_small_heuristics = "Max"
use_field_init_shorthand = true

257
src/stdlib/cursive.rs

@ -2,116 +2,267 @@
// This is a part of WLambda. See README.md and COPYING for details.
#[allow(unused_imports)]
use crate::{VVal, Env, StackAction};
use crate::compiler::*;
#[allow(unused_imports)]
use crate::vval::{VValFun, VValUserData};
#[allow(unused_imports)]
use std::rc::Rc;
use crate::{Env, StackAction, VVal};
#[allow(unused_imports)]
use std::cell::RefCell;
#[allow(unused_imports)]
use crate::compiler::*;
use std::rc::Rc;
#[cfg(feature = "cursive")]
use cursive::view::IntoBoxedView;
#[cfg(feature = "cursive")]
use cursive::views::{BoxedView, Button, Dialog, LinearLayout, Panel, TextView};
#[cfg(feature = "cursive")]
use cursive::{direction::Orientation, traits::Nameable, Cursive, CursiveExt};
#[cfg(feature="cursive")]
use cursive::{Cursive, CursiveExt};
#[cfg(feature="cursive")]
use cursive::view::{IntoBoxedView};
#[cfg(feature="cursive")]
use cursive::views::{BoxedView, Button};
macro_rules! call_callback {
($cursive: ident, $cb: ident, $env: ident) => {{
let cursive_ptr: *mut Cursive = $cursive;
#[cfg(feature="cursive")]
let api = CursiveAPI::new(cursive_ptr);
{
if $cb.is_some() {
match $cb.call(&mut $env.borrow_mut(), &[VVal::new_usr(api.clone())]) {
Ok(_) => (),
Err(e) => {
$cursive.add_layer(
Dialog::around(TextView::new(format!("Error in callback: {}", e)))
.button("Quit", |s| s.quit()),
);
}
}
}
}
if !api.this_is_the_only_strong_ref() {
$cursive.add_layer(
Dialog::around(TextView::new(format!(
"You must never store $<CursiveAPI> from a callback: {}",
$cb.s()
)))
.button("Quit", |s| s.quit()),
);
}
}};
}
#[cfg(feature = "cursive")]
#[derive(Clone)]
struct CursiveAPI {
ptr: Rc<*mut Cursive>,
}
impl CursiveAPI {
pub fn new(ptr: *mut Cursive) -> Self {
Self { ptr: Rc::new(ptr) }
}
pub fn this_is_the_only_strong_ref(&self) -> bool {
Rc::strong_count(&self.ptr) == 1
}
}
#[cfg(feature = "cursive")]
impl VValUserData for CursiveAPI {
fn s(&self) -> String {
format!("$<CursiveAPI>")
}
fn as_any(&mut self) -> &mut dyn std::any::Any {
self
}
fn clone_ud(&self) -> Box<dyn VValUserData> {
Box::new(self.clone())
}
fn call_method(&self, key: &str, env: &mut Env) -> Result<VVal, StackAction> {
let argv = env.argv();
match key {
"msg" => {
if argv.len() < 1 || argv.len() > 2 {
return Err(StackAction::panic_str(
"$<CursiveAPI>.msg([callback], text) expects 1 or 2 arguments".to_string(),
None,
env.argv(),
));
}
let cb = if argv.len() > 1 { argv.v_(0) } else { VVal::None };
let text = if argv.len() > 1 { argv.v_(1) } else { argv.v_(0) };
let denv = Rc::new(RefCell::new(env.derive()));
let cursive: &mut Cursive = unsafe { &mut **self.ptr };
cursive.add_layer(Dialog::around(TextView::new(&text.s_raw())).button("Ok", move |s| {
s.pop_layer();
call_callback!(s, cb, denv);
}));
Ok(VVal::None)
}
"quit" => {
if argv.len() != 0 {
return Err(StackAction::panic_str(
"$<CursiveAPI>.quit() expects 0 arguments".to_string(),
None,
env.argv(),
));
}
unsafe { (**self.ptr).quit() }
Ok(VVal::None)
}
_ => Err(StackAction::panic_str(
format!("$<CursiveAPI> unknown method called: {}", key),
None,
env.argv(),
)),
}
}
}
#[cfg(feature = "cursive")]
#[derive(Clone)]
struct CursiveHandle {
cursive: Rc<RefCell<Cursive>>,
}
#[cfg(feature="cursive")]
#[cfg(feature = "cursive")]
impl CursiveHandle {
pub fn new() -> Self {
Self {
cursive: Rc::new(RefCell::new(Cursive::new())),
}
Self { cursive: Rc::new(RefCell::new(Cursive::new())) }
}
}
#[cfg(feature="cursive")]
fn vv2view(v: &VVal) -> Result<Box<(dyn cursive::View + 'static)>, String> {
macro_rules! wrap_named {
($view: expr, $define: ident) => {
if $define.v_k("name").is_some() {
$view.with_name($define.v_s_rawk("name")).into_boxed_view()
} else {
$view.into_boxed_view()
}
};
}
#[cfg(feature = "cursive")]
fn vv2view(v: &VVal, env: &mut Env) -> Result<Box<(dyn cursive::View + 'static)>, String> {
let typ = v.v_(0);
let define = v.v_(1);
match &typ.s_raw()[..] {
"button" => {
Ok(Button::new(define.v_s_rawk("label"), |s| s.quit()).into_boxed_view())
"hbox" => {
let mut ll = LinearLayout::new(Orientation::Horizontal);
define.with_iter(|it| {
for (v, _) in it {
ll.add_child(vv2view(&v, env)?);
}
Ok::<(), String>(())
})?;
Ok(ll.into_boxed_view())
}
"vbox" => {
let mut ll = LinearLayout::new(Orientation::Vertical);
define.with_iter(|it| {
for (v, _) in it {
ll.add_child(vv2view(&v, env)?);
}
Ok::<(), String>(())
})?;
Ok(ll.into_boxed_view())
}
"panel" => {
let (define, child) = (define.v_(0), define.v_(1));
let mut pnl = Panel::new(BoxedView::new(vv2view(&child, env)?));
if define.v_k("title").is_some() {
pnl.set_title(define.v_s_rawk("title"));
}
Ok(pnl.into_boxed_view())
}
_ => {
Err(format!("Unknown view type: '{}'", typ.s()))
"button" => {
let cb = define.v_k("cb");
let denv = Rc::new(RefCell::new(env.derive()));
let view = Button::new(define.v_s_rawk("label"), move |s| call_callback!(s, cb, denv));
Ok(wrap_named!(view, define))
}
_ => Err(format!("Unknown view type: '{}'", typ.s())),
}
}
#[cfg(feature="cursive")]
#[cfg(feature = "cursive")]
impl VValUserData for CursiveHandle {
fn s(&self) -> String {
format!("$<Cursive>")
}
fn as_any(&mut self) -> &mut dyn std::any::Any { self }
fn as_any(&mut self) -> &mut dyn std::any::Any {
self
}
fn clone_ud(&self) -> Box<dyn VValUserData> {
Box::new(self.clone())
}
fn call_method(&self, key: &str, env: &mut Env) -> Result<VVal, StackAction> {
let argv = env.argv_ref();
let argv = env.argv();
match key {
"add_layer" => {
if argv.len() != 1 {
return
Err(StackAction::panic_str(
"$<Cursive>.add_layer(view) expects 1 argument".to_string(),
None,
env.argv()))
return Err(StackAction::panic_str(
"$<Cursive>.add_layer(view) expects 1 argument".to_string(),
None,
env.argv(),
));
}
match vv2view(&argv[0]) {
match vv2view(&argv.v_(0), env) {
Ok(v) => {
self.cursive.borrow_mut().add_layer(v);
Ok(VVal::None)
},
Err(e) => {
Err(StackAction::panic_str(
format!("$<Cursive>.add_layer(view) expects proper view definition: {}", e),
None,
env.argv()))
},
}
Err(e) => Err(StackAction::panic_str(
format!("$<Cursive>.add_layer(view) expects proper view definition: {}", e),
None,
env.argv(),
)),
}
}
"run" => {
if argv.len() != 0 {
return
Err(StackAction::panic_str(
"$<Cursive>.run() expects 0 arguments".to_string(),
None,
env.argv()))
return Err(StackAction::panic_str(
"$<Cursive>.run() expects 0 arguments".to_string(),
None,
env.argv(),
));
}
self.cursive.borrow_mut().run();
Ok(VVal::None)
},
_ => {
Err(StackAction::panic_str(
format!("$<Cursive> unknown method called: {}", key),
None,
env.argv()))
},
}
_ => Err(StackAction::panic_str(
format!("$<Cursive> unknown method called: {}", key),
None,
env.argv(),
)),
}
}
}
#[allow(unused_variables)]
pub fn add_to_symtable(st: &mut SymbolTable) {
#[cfg(feature="cursive")]
st.fun("cursive:new", |env: &mut Env, _argc: usize| {
Ok(VVal::new_usr(CursiveHandle::new()))
}, Some(0), Some(0), false);
#[cfg(feature = "cursive")]
st.fun(
"cursive:new",
|env: &mut Env, _argc: usize| Ok(VVal::new_usr(CursiveHandle::new())),
Some(0),
Some(0),
false,
);
}

10
src/vval.rs

@ -982,15 +982,15 @@ impl Env {
UnwindAction::RestoreLoopInfo(li) =>
format!("loinf(uws:{},sp:{})", li.uw_depth, li.sp),
UnwindAction::RestoreAccum(_fun, _val) =>
("raccm".to_string()),
"raccm".to_string(),
UnwindAction::RestoreSelf(_slf) =>
("rslf".to_string()),
"rslf".to_string(),
UnwindAction::RestoreIter(_i) =>
("ritr".to_string()),
"ritr".to_string(),
UnwindAction::FunctionCall(argc, old_bp, local_size) =>
format!("fcal({},{},{})", argc, old_bp, local_size),
UnwindAction::Null =>
("nul".to_string()),
"nul".to_string(),
};
if !s.is_empty() {
@ -5446,7 +5446,7 @@ impl VVal {
VVal::Bol(b) => if *b { 1 } else { 0 },
VVal::Syn(s) => s.syn() as i64,
VVal::Int(i) => *i,
VVal::Flt(f) => (*f as i64),
VVal::Flt(f) => *f as i64,
VVal::Pair(b) => b.0.i(),
VVal::Lst(l) => l.borrow().len() as i64,
VVal::Map(l) => l.borrow().len() as i64,

Loading…
Cancel
Save