nesting_techniques/
nesting-techniques.rs

1/*!
2This example demonstrates more complex nesting techniques.
3*/
4
5#[derive(Default)]
6struct Foo {
7	int: i32,
8	float: f32,
9	string: String,
10}
11
12// Demonstrate how to create pseudo 'on change' callbacks by aliasing the properties as actions
13// Specify before or after on change by changing the order in which they are listed to the visitor
14impl Foo {
15	fn before_int_changed(&mut self, _args: &str, writer: &mut dyn cvar::IWrite) {
16		self.string = self.int.to_string();
17		let _ = writeln!(writer, "Before int is changed!");
18	}
19	fn after_float_changed(&mut self, _args: &str, writer: &mut dyn cvar::IWrite) {
20		self.string = self.float.to_string();
21		let _ = writeln!(writer, "After float has changed!");
22	}
23}
24
25impl cvar::IVisit for Foo {
26	fn visit(&mut self, f: &mut dyn FnMut(&mut dyn cvar::INode)) {
27		f(&mut cvar::Action("int", |args, writer| self.before_int_changed(args, writer)));
28		f(&mut cvar::Property("int", &mut self.int, &0));
29		f(&mut cvar::Property("float", &mut self.float, &0.0));
30		f(&mut cvar::Action("float", |args, writer| self.after_float_changed(args, writer)));
31		f(&mut cvar::Property("string", &mut self.string, &String::new()));
32	}
33}
34
35// Demonstrate how to create pseudo hierarchy allowing to inject nodes in a deeper nested namespace
36// It is not possible to inject a node in a parent, this would also clash with Rust's borrowing rules
37#[derive(Default)]
38struct Nested {
39	boolean: bool,
40	foo: Foo,
41}
42
43impl cvar::IVisit for Nested {
44	fn visit(&mut self, f: &mut dyn FnMut(&mut dyn cvar::INode)) {
45		f(&mut cvar::Property("foo.bool", &mut self.boolean, &false));
46		f(&mut cvar::List("foo", &mut self.foo));
47	}
48}
49
50fn main() {
51	let mut nested = Nested::default();
52
53	// This property appears nested but is set in the parent context
54	cvar::console::set_value(&mut nested, "foo.bool", &true, &mut cvar::NullWriter);
55	assert!(nested.boolean);
56
57	println!("Hit enter to list all the cvars and their values.");
58	println!("Assign value to cvar with `<name> <value>`.");
59
60	loop {
61		// Read input from stdin
62		let mut line = String::new();
63		if read_line(&mut line) {
64			break;
65		}
66
67		// Crude command line parsing
68		let (path, args) = split_line(&line);
69		cvar::console::poke(&mut nested, path, args, &mut cvar::IoWriter::stdout());
70	}
71}
72
73// Reads a line from stdin and return true if there was a break
74pub fn read_line(line: &mut String) -> bool {
75	use std::io;
76	print!(">>> ");
77	let _ = io::Write::flush(&mut io::stdout());
78	return io::stdin().read_line(line).is_err() || line.is_empty();
79}
80
81pub fn split_line(line: &str) -> (&str, Option<&str>) {
82	let line = line.trim_start();
83	let path = line.split_ascii_whitespace().next().unwrap_or("");
84	let args = &line[path.len()..].trim();
85	(path, if args.len() == 0 { None } else { Some(args) })
86}