diff --git a/services/shellchat/README.md b/services/shellchat/README.md
index 341fec838..5b576fd5f 100644
--- a/services/shellchat/README.md
+++ b/services/shellchat/README.md
@@ -12,3 +12,33 @@ Other facilities for handling system-level messages, such as menu configurations
and network events, have yet to be implemented. However, they will likely end up
with a demo in this application first.
+To make your own command, copy the `echo.rs` template or snag the one below, and put
+it in the services/shellchat/src/cmds/ directory:
+
+```Rust
+use crate::{ShellCmdApi, CommonEnv};
+use xous::String;
+
+#[derive(Debug)]
+pub struct Echo {
+}
+
+impl<'a> ShellCmdApi<'a> for Echo {
+ cmd_api!(echo); // inserts boilerplate for command API
+
+ fn process(&mut self, args: String::<1024>, _env: &mut CommonEnv) -> Result>, xous::Error> {
+ Ok(Some(rest))
+ }
+}
+```
+
+The "verb" is the name of your command, and it is the argument to the `cmd_api!()` macro.
+
+`process()` is your "main" function, and `args` is a string which contains the
+rest of the line that was typed into the chat, minus the verb used to identify
+your command (the arguments, as they may be, but not tokenized or parsed in
+any way). `env` contains some items in a common environment, for example, connections
+to the GAM, LLIO server or other resources required by your implementation.
+
+Once you've added your command to the directory, go to the `cmds.rs` file, and follow
+the four-step instructions embedded within the file, starting around line 40.
\ No newline at end of file
diff --git a/services/shellchat/src/cmds.rs b/services/shellchat/src/cmds.rs
index f0135dec6..b21da8449 100644
--- a/services/shellchat/src/cmds.rs
+++ b/services/shellchat/src/cmds.rs
@@ -1,10 +1,10 @@
use xous::String;
use core::fmt::Write;
-
+/////////////////////////// Common items to all commands
pub trait ShellCmdApi<'a> {
// user implemented:
// called to process the command with the remainder of the string attached
- fn process(&mut self, rest: String::<1024>, env: &mut CommonEnv) -> Result >, xous::Error>;
+ fn process(&mut self, args: String::<1024>, env: &mut CommonEnv) -> Result >, xous::Error>;
// created with cmd_api! macro
// checks if the command matches the current verb in question
@@ -28,41 +28,7 @@ macro_rules! cmd_api {
};
}
-
-/// extract the first token, as delimited by spaces
-/// modifies the incoming line by removing the token and returning the remainder
-/// returns the found token
-/// note: we don't have split() because of nostd
-pub fn tokenize(line: &mut String::<1024>) -> Option> {
- let mut token = String::<1024>::new();
- let mut retline = String::<1024>::new();
-
- let lineiter = line.as_str().unwrap().chars();
- let mut foundspace = false;
- let mut foundrest = false;
- for ch in lineiter {
- if ch != ' ' && !foundspace {
- token.push(ch).unwrap();
- } else if foundspace && foundrest {
- retline.push(ch).unwrap();
- } else if foundspace && ch != ' ' {
- // handle case of multiple spaces in a row
- foundrest = true;
- retline.push(ch).unwrap();
- } else {
- foundspace = true;
- // consume the space
- }
- }
- line.clear();
- write!(line, "{}", retline.as_str().unwrap()).unwrap();
- if token.len() > 0 {
- Some(token)
- } else {
- None
- }
-}
-
+/////////////////////////// Command shell integration
#[derive(Debug)]
pub struct CommonEnv {
llio: xous::CID,
@@ -71,18 +37,29 @@ pub struct CommonEnv {
gam: xous::CID,
}
-mod echo;
-use echo::*;
-mod test;
-use test::*;
-mod sleep;
-use sleep::*;
-mod sensors;
-use sensors::*;
+/*
+ To add a new command:
+ 0. ensure that the command implements the ShellCmdApi (above)
+ 1. mod/use the new command
+ 2. create an entry for the command's storage in the CmdEnv structure
+ 3. initialize the persistant storage here
+ 4. add it to the "commands" array in the dispatch() routine below
+
+ Side note: if your command doesn't require persistent storage, you could,
+ technically, generate the command dynamically every time it's called. Echo
+ demonstrates this.
+*/
+
+///// 1. add your module here, and pull its namespace into the local crate
+mod echo; use echo::*;
+mod test; use test::*;
+mod sleep; use sleep::*;
+mod sensors; use sensors::*;
#[derive(Debug)]
pub struct CmdEnv {
common_env: CommonEnv,
+ ///// 2. declare storage for your command here.
test_cmd: Test,
sleep_cmd: Sleep,
sensors_cmd: Sensors,
@@ -90,18 +67,6 @@ pub struct CmdEnv {
impl CmdEnv {
pub fn new(gam: xous::CID) -> CmdEnv {
let ticktimer_server_id = xous::SID::from_bytes(b"ticktimer-server").unwrap();
- /*
- To add a new command:
- - ensure that the command implements the ShellCmdApi
- - mod/use the new command (above)
- - create an entry for the command's storage in the CmdEnv structure
- - initialize the persistant storage here
- - add it to the "commands" array in the dispatch() routine below
-
- Side note: if your command doesn't require persistent storage, you could,
- technically, generate the command dynamically every time it's called. Echo
- demonstrates this.
- */
CmdEnv {
common_env: CommonEnv {
llio: xous_names::request_connection_blocking(xous::names::SERVER_NAME_LLIO).expect("CMD: can't connect to LLIO"),
@@ -109,6 +74,7 @@ impl CmdEnv {
ticktimer: xous::connect(ticktimer_server_id).unwrap(),
gam,
},
+ ///// 3. initialize your storage, by calling new()
test_cmd: Test::new(),
sleep_cmd: Sleep::new(),
sensors_cmd: Sensors::new(),
@@ -120,6 +86,7 @@ impl CmdEnv {
let mut echo_cmd = Echo {}; // this command has no persistent storage, so we can "create" it every time we call dispatch (but it's a zero-cost absraction so this doesn't actually create any instructions)
let commands: &mut [& mut dyn ShellCmdApi] = &mut [
+ ///// 4. add your command to this array, so that it can be looked up and dispatched
&mut echo_cmd,
&mut self.test_cmd,
&mut self.sleep_cmd,
@@ -161,4 +128,38 @@ impl CmdEnv {
Ok(None)
}
}
-}
\ No newline at end of file
+}
+
+/// extract the first token, as delimited by spaces
+/// modifies the incoming line by removing the token and returning the remainder
+/// returns the found token
+/// note: we don't have split() because of nostd
+pub fn tokenize(line: &mut String::<1024>) -> Option> {
+ let mut token = String::<1024>::new();
+ let mut retline = String::<1024>::new();
+
+ let lineiter = line.as_str().unwrap().chars();
+ let mut foundspace = false;
+ let mut foundrest = false;
+ for ch in lineiter {
+ if ch != ' ' && !foundspace {
+ token.push(ch).unwrap();
+ } else if foundspace && foundrest {
+ retline.push(ch).unwrap();
+ } else if foundspace && ch != ' ' {
+ // handle case of multiple spaces in a row
+ foundrest = true;
+ retline.push(ch).unwrap();
+ } else {
+ foundspace = true;
+ // consume the space
+ }
+ }
+ line.clear();
+ write!(line, "{}", retline.as_str().unwrap()).unwrap();
+ if token.len() > 0 {
+ Some(token)
+ } else {
+ None
+ }
+}
diff --git a/services/shellchat/src/cmds/echo.rs b/services/shellchat/src/cmds/echo.rs
index 226edefd1..8f64ddedd 100644
--- a/services/shellchat/src/cmds/echo.rs
+++ b/services/shellchat/src/cmds/echo.rs
@@ -8,7 +8,7 @@ pub struct Echo {
impl<'a> ShellCmdApi<'a> for Echo {
cmd_api!(echo); // inserts boilerplate for command API
- fn process(&mut self, rest: String::<1024>, _env: &mut CommonEnv) -> Result>, xous::Error> {
- Ok(Some(rest))
+ fn process(&mut self, args: String::<1024>, _env: &mut CommonEnv) -> Result >, xous::Error> {
+ Ok(Some(args))
}
}
\ No newline at end of file
diff --git a/services/shellchat/src/cmds/sensors.rs b/services/shellchat/src/cmds/sensors.rs
index 46e661bb6..286d85653 100644
--- a/services/shellchat/src/cmds/sensors.rs
+++ b/services/shellchat/src/cmds/sensors.rs
@@ -14,7 +14,7 @@ impl Sensors {
impl<'a> ShellCmdApi<'a> for Sensors {
cmd_api!(sensors);
- fn process(&mut self, _rest: String::<1024>, env: &mut CommonEnv) -> Result >, xous::Error> {
+ fn process(&mut self, _args: String::<1024>, env: &mut CommonEnv) -> Result >, xous::Error> {
use core::fmt::Write;
let mut ret = String::<1024>::new();
diff --git a/services/shellchat/src/cmds/sleep.rs b/services/shellchat/src/cmds/sleep.rs
index 96b5b1080..96cfd0942 100644
--- a/services/shellchat/src/cmds/sleep.rs
+++ b/services/shellchat/src/cmds/sleep.rs
@@ -13,7 +13,7 @@ impl Sleep {
impl<'a> ShellCmdApi<'a> for Sleep {
cmd_api!(sleep); // inserts boilerplate for command API
- fn process(&mut self, _rest: String::<1024>, env: &mut CommonEnv) -> Result >, xous::Error> {
+ fn process(&mut self, _args: String::<1024>, env: &mut CommonEnv) -> Result >, xous::Error> {
use core::fmt::Write;
let mut ret = String::<1024>::new();
diff --git a/services/shellchat/src/cmds/test.rs b/services/shellchat/src/cmds/test.rs
index 81464ccdd..71150a63b 100644
--- a/services/shellchat/src/cmds/test.rs
+++ b/services/shellchat/src/cmds/test.rs
@@ -16,7 +16,7 @@ impl Test {
impl<'a> ShellCmdApi<'a> for Test {
cmd_api!(test);
- fn process(&mut self, _rest: String::<1024>, _env: &mut CommonEnv) -> Result >, xous::Error> {
+ fn process(&mut self, _args: String::<1024>, _env: &mut CommonEnv) -> Result >, xous::Error> {
use core::fmt::Write;
self.state += 1;