rail_lang/v1/corelib/
display.rs1use std::fmt::Display;
2use std::io::{self, Stdout, Write};
3
4use crate::v1::rail_machine::{RailDef, RailType, RailVal};
5
6pub fn builtins() -> Vec<RailDef<'static>> {
7 vec![
8 printer("p", "Consumes one value and prints it.", &|a| {
9 print_or_die(|out| out.write_fmt(format_args!("{}", a)))
10 }),
11 printer(
12 "pl",
13 "Consumes one value, prints it, and prints a newline.",
14 &|a| print_or_die(|out| out.write_fmt(format_args!("{}\n", a))),
15 ),
16 RailDef::contextless("nl", "Prints a newline.", &[], &[], || {
17 print_or_die(|out| out.write(b"\n"))
18 }),
19 RailDef::on_state_noerr(
20 "status",
21 "Prints the current status of the program.",
22 &[],
23 &[],
24 |state| {
25 print_or_die(|out| out.write_fmt(format_args!("{}\n", state.stack)));
26 state
27 },
28 ),
29 RailDef::contextless(
30 "clear",
31 "When invoked in a terminal context, clears the screen.",
32 &[],
33 &[],
34 || clearscreen::clear().expect("Unable to clear screen"),
35 ),
36 ]
37}
38
39fn printer<'a, P>(name: &str, description: &str, p: &'a P) -> RailDef<'a>
40where
41 P: Fn(&dyn Display) + 'a,
42{
43 RailDef::on_state_noerr(name, description, &[RailType::A], &[], move |quote| {
44 let (a, quote) = quote.pop();
45 match a {
46 RailVal::String(a) => p(&a),
47 _ => p(&a),
48 }
49 quote
50 })
51}
52
53fn print_or_die<P, T>(p: P)
54where
55 P: Fn(&mut Stdout) -> io::Result<T>,
56{
57 let res = p(&mut io::stdout());
58 if res.is_err() {
59 std::process::exit(1);
60 }
61}