Skip to content

Commit 22836f0

Browse files
committed
Callbacks working again.
1 parent 63b6485 commit 22836f0

File tree

2 files changed

+96
-32
lines changed

2 files changed

+96
-32
lines changed

examples/simple.rs

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ extern crate menu;
22

33
use menu::*;
44
use pancurses::{endwin, initscr, noecho, Input};
5+
use std::fmt::Write;
56

67
const FOO_ITEM: Item<Output> = Item {
78
item_type: ItemType::Callback {
@@ -102,34 +103,39 @@ fn main() {
102103
endwin();
103104
}
104105

105-
fn enter_root(_menu: &Menu<Output>) {
106-
println!("In enter_root");
106+
fn enter_root(_menu: &Menu<Output>, context: &mut Output) {
107+
writeln!(context, "In enter_root").unwrap();
107108
}
108109

109-
fn exit_root(_menu: &Menu<Output>) {
110-
println!("In exit_root");
110+
fn exit_root(_menu: &Menu<Output>, context: &mut Output) {
111+
writeln!(context, "In exit_root").unwrap();
111112
}
112113

113-
fn select_foo<'a>(_menu: &Menu<Output>, _item: &Item<Output>, input: &str, _context: &mut Output) {
114-
println!("In select_foo: {}", input);
114+
fn select_foo<'a>(_menu: &Menu<Output>, _item: &Item<Output>, args: &[&str], context: &mut Output) {
115+
writeln!(context, "In select_foo. Args = {:?}", args).unwrap();
115116
}
116117

117-
fn select_bar<'a>(_menu: &Menu<Output>, _item: &Item<Output>, input: &str, _context: &mut Output) {
118-
println!("In select_bar: {}", input);
118+
fn select_bar<'a>(_menu: &Menu<Output>, _item: &Item<Output>, args: &[&str], context: &mut Output) {
119+
writeln!(context, "In select_bar. Args = {:?}", args).unwrap();
119120
}
120121

121-
fn enter_sub(_menu: &Menu<Output>) {
122-
println!("In enter_sub");
122+
fn enter_sub(_menu: &Menu<Output>, context: &mut Output) {
123+
writeln!(context, "In enter_sub").unwrap();
123124
}
124125

125-
fn exit_sub(_menu: &Menu<Output>) {
126-
println!("In exit_sub");
126+
fn exit_sub(_menu: &Menu<Output>, context: &mut Output) {
127+
writeln!(context, "In exit_sub").unwrap();
127128
}
128129

129-
fn select_baz<'a>(_menu: &Menu<Output>, _item: &Item<Output>, input: &str, _context: &mut Output) {
130-
println!("In select_baz: {}", input);
130+
fn select_baz<'a>(_menu: &Menu<Output>, _item: &Item<Output>, args: &[&str], context: &mut Output) {
131+
writeln!(context, "In select_baz: Args = {:?}", args).unwrap();
131132
}
132133

133-
fn select_quux<'a>(_menu: &Menu<Output>, _item: &Item<Output>, input: &str, _context: &mut Output) {
134-
println!("In select_quux: {}", input);
134+
fn select_quux<'a>(
135+
_menu: &Menu<Output>,
136+
_item: &Item<Output>,
137+
args: &[&str],
138+
context: &mut Output,
139+
) {
140+
writeln!(context, "In select_quux: Args = {:?}", args).unwrap();
135141
}

src/lib.rs

Lines changed: 74 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
#![no_std]
22

3-
type MenuCallbackFn<T> = fn(menu: &Menu<T>);
4-
type ItemCallbackFn<T> = fn(menu: &Menu<T>, item: &Item<T>, args: &str, context: &mut T);
3+
type MenuCallbackFn<T> = fn(menu: &Menu<T>, context: &mut T);
4+
type ItemCallbackFn<T> = fn(menu: &Menu<T>, item: &Item<T>, args: &[&str], context: &mut T);
55

6+
#[derive(Debug)]
67
/// Describes a parameter to the command
78
pub enum Parameter<'a> {
89
Mandatory(&'a str),
@@ -24,6 +25,7 @@ where
2425
parameters: &'a [Parameter<'a>],
2526
},
2627
Menu(&'a Menu<'a, T>),
28+
_Dummy,
2729
}
2830

2931
/// Menu Item
@@ -71,7 +73,7 @@ where
7173
{
7274
pub fn new(menu: &'a Menu<'a, T>, buffer: &'a mut [u8], context: &'a mut T) -> Runner<'a, T> {
7375
if let Some(cb_fn) = menu.entry {
74-
cb_fn(menu);
76+
cb_fn(menu, context);
7577
}
7678
let mut r = Runner {
7779
menus: [Some(menu), None, None, None],
@@ -156,9 +158,19 @@ where
156158
self.print_help(&item);
157159
}
158160
if self.depth != 0 {
159-
writeln!(self.context, "* exit - leave this menu.").unwrap();
161+
let item = Item {
162+
command: "exit",
163+
help: Some("leave this menu"),
164+
item_type: ItemType::_Dummy,
165+
};
166+
self.print_help(&item);
160167
}
161-
writeln!(self.context, "* help - print this help text").unwrap();
168+
let item = Item {
169+
command: "help",
170+
help: Some("show this help"),
171+
item_type: ItemType::_Dummy,
172+
};
173+
self.print_help(&item);
162174
Outcome::CommandProcessed
163175
} else if command_line == "exit" && self.depth != 0 {
164176
if self.depth == self.menus.len() {
@@ -179,7 +191,8 @@ where
179191
ItemType::Callback {
180192
function,
181193
parameters,
182-
} => self.call_function(
194+
} => Self::call_function(
195+
self.context,
183196
function,
184197
parameters,
185198
menu,
@@ -190,6 +203,9 @@ where
190203
self.depth += 1;
191204
self.menus[self.depth] = Some(m);
192205
}
206+
ItemType::_Dummy => {
207+
unreachable!();
208+
}
193209
}
194210
found = true;
195211
break;
@@ -214,7 +230,7 @@ where
214230
match item.item_type {
215231
ItemType::Callback { parameters, .. } => {
216232
if !parameters.is_empty() {
217-
write!(self.context, "* {}", item.command).unwrap();
233+
write!(self.context, "{}", item.command).unwrap();
218234
for param in parameters.iter() {
219235
match param {
220236
Parameter::Mandatory(name) => {
@@ -233,11 +249,14 @@ where
233249
}
234250
}
235251
} else {
236-
write!(self.context, "* {}", item.command).unwrap();
252+
write!(self.context, "{}", item.command).unwrap();
237253
}
238254
}
239255
ItemType::Menu(_menu) => {
240-
write!(self.context, "* {}", item.command).unwrap();
256+
write!(self.context, "{}", item.command).unwrap();
257+
}
258+
ItemType::_Dummy => {
259+
write!(self.context, "{}", item.command).unwrap();
241260
}
242261
}
243262
if let Some(help) = item.help {
@@ -247,14 +266,53 @@ where
247266
}
248267

249268
fn call_function(
250-
&self,
251-
_function: ItemCallbackFn<T>,
252-
_parameters: &[Parameter],
253-
_parent_menu: &Menu<T>,
254-
_item: &Item<T>,
255-
_command: &str,
269+
context: &mut T,
270+
callback_function: ItemCallbackFn<T>,
271+
parameters: &[Parameter],
272+
parent_menu: &Menu<T>,
273+
item: &Item<T>,
274+
command: &str,
256275
) {
257-
276+
let mandatory_parameter_count = parameters
277+
.iter()
278+
.filter(|p| match p {
279+
Parameter::Mandatory(_) => true,
280+
_ => false,
281+
})
282+
.count();
283+
if command.len() >= item.command.len() {
284+
// Maybe arguments
285+
let mut argument_buffer: [&str; 16] = [""; 16];
286+
let mut argument_count = 0;
287+
let mut positional_arguments = 0;
288+
for (slot, arg) in argument_buffer
289+
.iter_mut()
290+
.zip(command[item.command.len()..].split_whitespace())
291+
{
292+
*slot = arg;
293+
argument_count += 1;
294+
if !arg.starts_with("--") {
295+
positional_arguments += 1;
296+
}
297+
}
298+
if positional_arguments >= mandatory_parameter_count {
299+
callback_function(
300+
parent_menu,
301+
item,
302+
&argument_buffer[0..argument_count],
303+
context,
304+
);
305+
} else {
306+
writeln!(context, "Error: Insufficient arguments given").unwrap();
307+
}
308+
} else {
309+
// Definitely no arguments
310+
if mandatory_parameter_count == 0 {
311+
callback_function(parent_menu, item, &[], context);
312+
} else {
313+
writeln!(context, "Error: Insufficient arguments given").unwrap();
314+
}
315+
}
258316
}
259317
}
260318

0 commit comments

Comments
 (0)