Skip to content

Commit fdd59dc

Browse files
thejpsterjonathanpallant
authored andcommitted
Clean up shell.
Each command is now a function.
1 parent b173f7b commit fdd59dc

File tree

1 file changed

+157
-115
lines changed

1 file changed

+157
-115
lines changed

examples/shell.rs

Lines changed: 157 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@
44
55
use std::io::prelude::*;
66

7-
use embedded_sdmmc::{Error, RawDirectory, RawVolume, VolumeIdx, VolumeManager};
7+
use embedded_sdmmc::{Error as EsError, RawDirectory, RawVolume, VolumeIdx, VolumeManager};
88

99
use crate::linux::{Clock, LinuxBlockDevice};
1010

11+
type Error = EsError<std::io::Error>;
12+
1113
mod linux;
1214

1315
struct VolumeState {
@@ -30,19 +32,149 @@ impl Context {
3032
s.path.clone()
3133
}
3234

33-
fn process_line(&mut self, line: &str) -> Result<(), Error<std::io::Error>> {
35+
/// Print some help text
36+
fn help(&mut self) -> Result<(), Error> {
37+
println!("Commands:");
38+
println!("\thelp -> this help text");
39+
println!("\t<volume>: -> change volume/partition");
40+
println!("\tstat -> print volume manager status");
41+
println!("\tdir [<path>] -> do a directory listing");
42+
println!("\tcd .. -> go up a level");
43+
println!("\tcd <path> -> change into directory <path>");
44+
println!("\tcat <path> -> print a text file");
45+
println!("\thexdump <path> -> print a binary file");
46+
println!("\tmkdir <path> -> create an empty directory");
47+
println!("\tquit -> exits the program");
48+
println!();
49+
println!("Paths can be:");
50+
println!();
51+
println!("\t* Bare names, like `FILE.DAT`");
52+
println!("\t* Relative, like `../SOMEDIR/FILE.DAT` or `./FILE.DAT`");
53+
println!("\t* Absolute, like `1:/SOMEDIR/FILE.DAT`");
54+
Ok(())
55+
}
56+
57+
/// Print volume manager status
58+
fn stat(&mut self) -> Result<(), Error> {
59+
println!("Status:\n{:#?}", self.volume_mgr);
60+
Ok(())
61+
}
62+
63+
/// Print a directory listing
64+
fn dir(&mut self) -> Result<(), Error> {
65+
let Some(s) = &self.volumes[self.current_volume] else {
66+
println!("That volume isn't available");
67+
return Ok(());
68+
};
69+
self.volume_mgr.iterate_dir(s.directory, |entry| {
70+
println!(
71+
"{:12} {:9} {} {} {:X?} {:?}",
72+
entry.name, entry.size, entry.ctime, entry.mtime, entry.cluster, entry.attributes
73+
);
74+
})?;
75+
Ok(())
76+
}
77+
78+
/// Change into <dir>
79+
///
80+
/// An arg of `..` goes up one level
81+
fn cd(&mut self, filename: &str) -> Result<(), Error> {
82+
let Some(s) = &mut self.volumes[self.current_volume] else {
83+
println!("This volume isn't available");
84+
return Ok(());
85+
};
86+
let d = self.volume_mgr.open_dir(s.directory, filename)?;
87+
self.volume_mgr.close_dir(s.directory)?;
88+
s.directory = d;
89+
if filename == ".." {
90+
s.path.pop();
91+
} else {
92+
s.path.push(filename.to_owned());
93+
}
94+
Ok(())
95+
}
96+
97+
/// print a text file
98+
fn cat(&mut self, filename: &str) -> Result<(), Error> {
99+
let Some(s) = &mut self.volumes[self.current_volume] else {
100+
println!("This volume isn't available");
101+
return Ok(());
102+
};
103+
let mut f = self
104+
.volume_mgr
105+
.open_file_in_dir(s.directory, filename, embedded_sdmmc::Mode::ReadOnly)?
106+
.to_file(&mut self.volume_mgr);
107+
let mut data = Vec::new();
108+
while !f.is_eof() {
109+
let mut buffer = vec![0u8; 65536];
110+
let n = f.read(&mut buffer)?;
111+
// read n bytes
112+
data.extend_from_slice(&buffer[0..n]);
113+
println!("Read {} bytes, making {} total", n, data.len());
114+
}
115+
if let Ok(s) = std::str::from_utf8(&data) {
116+
println!("{}", s);
117+
} else {
118+
println!("I'm afraid that file isn't UTF-8 encoded");
119+
}
120+
Ok(())
121+
}
122+
123+
/// print a binary file
124+
fn hexdump(&mut self, filename: &str) -> Result<(), Error> {
125+
let Some(s) = &mut self.volumes[self.current_volume] else {
126+
println!("This volume isn't available");
127+
return Ok(());
128+
};
129+
let mut f = self
130+
.volume_mgr
131+
.open_file_in_dir(s.directory, filename, embedded_sdmmc::Mode::ReadOnly)?
132+
.to_file(&mut self.volume_mgr);
133+
let mut data = Vec::new();
134+
while !f.is_eof() {
135+
let mut buffer = vec![0u8; 65536];
136+
let n = f.read(&mut buffer)?;
137+
// read n bytes
138+
data.extend_from_slice(&buffer[0..n]);
139+
println!("Read {} bytes, making {} total", n, data.len());
140+
}
141+
for (idx, chunk) in data.chunks(16).enumerate() {
142+
print!("{:08x} | ", idx * 16);
143+
for b in chunk {
144+
print!("{:02x} ", b);
145+
}
146+
for _padding in 0..(16 - chunk.len()) {
147+
print!(" ");
148+
}
149+
print!("| ");
150+
for b in chunk {
151+
print!(
152+
"{}",
153+
if b.is_ascii_graphic() {
154+
*b as char
155+
} else {
156+
'.'
157+
}
158+
);
159+
}
160+
println!();
161+
}
162+
Ok(())
163+
}
164+
165+
/// create a directory
166+
fn mkdir(&mut self, dir_name: &str) -> Result<(), Error> {
167+
let Some(s) = &mut self.volumes[self.current_volume] else {
168+
println!("This volume isn't available");
169+
return Ok(());
170+
};
171+
// make the dir
172+
self.volume_mgr.make_dir_in_dir(s.directory, dir_name)
173+
}
174+
175+
fn process_line(&mut self, line: &str) -> Result<(), Error> {
34176
if line == "help" {
35-
println!("Commands:");
36-
println!("\thelp -> this help text");
37-
println!("\t<volume>: -> change volume/partition");
38-
println!("\tdir -> do a directory listing");
39-
println!("\tstat -> print volume manager status");
40-
println!("\tcat <file> -> print a text file");
41-
println!("\thexdump <file> -> print a binary file");
42-
println!("\tcd .. -> go up a level");
43-
println!("\tcd <dir> -> change into <dir>");
44-
println!("\tmkdir <dir> -> create a directory called <dir>");
45-
println!("\tquit -> exits the program");
177+
self.help()?;
46178
} else if line == "0:" {
47179
self.current_volume = 0;
48180
} else if line == "1:" {
@@ -51,108 +183,18 @@ impl Context {
51183
self.current_volume = 2;
52184
} else if line == "3:" {
53185
self.current_volume = 3;
54-
} else if line == "stat" {
55-
println!("Status:\n{:#?}", self.volume_mgr);
56186
} else if line == "dir" {
57-
let Some(s) = &self.volumes[self.current_volume] else {
58-
println!("That volume isn't available");
59-
return Ok(());
60-
};
61-
self.volume_mgr.iterate_dir(s.directory, |entry| {
62-
println!(
63-
"{:12} {:9} {} {} {:X?} {:?}",
64-
entry.name,
65-
entry.size,
66-
entry.ctime,
67-
entry.mtime,
68-
entry.cluster,
69-
entry.attributes
70-
);
71-
})?;
72-
} else if let Some(arg) = line.strip_prefix("cd ") {
73-
let arg = arg.trim();
74-
let Some(s) = &mut self.volumes[self.current_volume] else {
75-
println!("This volume isn't available");
76-
return Ok(());
77-
};
78-
let d = self.volume_mgr.open_dir(s.directory, arg)?;
79-
self.volume_mgr.close_dir(s.directory)?;
80-
s.directory = d;
81-
if arg == ".." {
82-
s.path.pop();
83-
} else {
84-
s.path.push(arg.to_owned());
85-
}
86-
} else if let Some(arg) = line.strip_prefix("cat ") {
87-
let arg = arg.trim();
88-
let Some(s) = &mut self.volumes[self.current_volume] else {
89-
println!("This volume isn't available");
90-
return Ok(());
91-
};
92-
let mut f = self
93-
.volume_mgr
94-
.open_file_in_dir(s.directory, arg, embedded_sdmmc::Mode::ReadOnly)?
95-
.to_file(&mut self.volume_mgr);
96-
let mut data = Vec::new();
97-
while !f.is_eof() {
98-
let mut buffer = vec![0u8; 65536];
99-
let n = f.read(&mut buffer)?;
100-
// read n bytes
101-
data.extend_from_slice(&buffer[0..n]);
102-
println!("Read {} bytes, making {} total", n, data.len());
103-
}
104-
if let Ok(s) = std::str::from_utf8(&data) {
105-
println!("{}", s);
106-
} else {
107-
println!("I'm afraid that file isn't UTF-8 encoded");
108-
}
109-
} else if let Some(arg) = line.strip_prefix("hexdump ") {
110-
let arg = arg.trim();
111-
let Some(s) = &mut self.volumes[self.current_volume] else {
112-
println!("This volume isn't available");
113-
return Ok(());
114-
};
115-
let mut f = self
116-
.volume_mgr
117-
.open_file_in_dir(s.directory, arg, embedded_sdmmc::Mode::ReadOnly)?
118-
.to_file(&mut self.volume_mgr);
119-
let mut data = Vec::new();
120-
while !f.is_eof() {
121-
let mut buffer = vec![0u8; 65536];
122-
let n = f.read(&mut buffer)?;
123-
// read n bytes
124-
data.extend_from_slice(&buffer[0..n]);
125-
println!("Read {} bytes, making {} total", n, data.len());
126-
}
127-
for (idx, chunk) in data.chunks(16).enumerate() {
128-
print!("{:08x} | ", idx * 16);
129-
for b in chunk {
130-
print!("{:02x} ", b);
131-
}
132-
for _padding in 0..(16 - chunk.len()) {
133-
print!(" ");
134-
}
135-
print!("| ");
136-
for b in chunk {
137-
print!(
138-
"{}",
139-
if b.is_ascii_graphic() {
140-
*b as char
141-
} else {
142-
'.'
143-
}
144-
);
145-
}
146-
println!();
147-
}
148-
} else if let Some(arg) = line.strip_prefix("mkdir ") {
149-
let arg = arg.trim();
150-
let Some(s) = &mut self.volumes[self.current_volume] else {
151-
println!("This volume isn't available");
152-
return Ok(());
153-
};
154-
// make the dir
155-
self.volume_mgr.make_dir_in_dir(s.directory, arg)?;
187+
self.dir()?;
188+
} else if line == "stat" {
189+
self.stat()?;
190+
} else if let Some(dirname) = line.strip_prefix("cd ") {
191+
self.cd(dirname.trim())?;
192+
} else if let Some(filename) = line.strip_prefix("cat ") {
193+
self.cat(filename.trim())?;
194+
} else if let Some(filename) = line.strip_prefix("hexdump ") {
195+
self.hexdump(filename.trim())?;
196+
} else if let Some(dirname) = line.strip_prefix("mkdir ") {
197+
self.mkdir(dirname.trim())?;
156198
} else {
157199
println!("Unknown command {line:?} - try 'help' for help");
158200
}
@@ -178,7 +220,7 @@ impl Drop for Context {
178220
}
179221
}
180222

181-
fn main() -> Result<(), Error<std::io::Error>> {
223+
fn main() -> Result<(), Error> {
182224
env_logger::init();
183225
let mut args = std::env::args().skip(1);
184226
let filename = args.next().unwrap_or_else(|| "/dev/mmcblk0".into());

0 commit comments

Comments
 (0)