mirror of
https://github.com/lights0123/n-link.git
synced 2024-12-22 18:25:27 +00:00
Added download
and ls
, formatted cli.rs
This commit is contained in:
parent
fd6d7d87b6
commit
cdd06cb3e6
|
@ -1,10 +1,10 @@
|
|||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
use std::io::{Read, Write};
|
||||
use std::path::PathBuf;
|
||||
use std::{fs::File, path::Path};
|
||||
|
||||
use clap::Clap;
|
||||
use indicatif::{ProgressBar, ProgressStyle};
|
||||
use libnspire::{PID, PID_CX2, VID};
|
||||
use libnspire::{dir::EntryType, PID, PID_CX2, VID};
|
||||
|
||||
#[derive(Clap, Debug)]
|
||||
#[clap(author, about, version)]
|
||||
|
@ -16,11 +16,12 @@ struct Opt {
|
|||
#[derive(Clap, Debug)]
|
||||
enum SubCommand {
|
||||
Upload(Upload),
|
||||
Download(Download),
|
||||
Mkdir(Mkdir),
|
||||
Rmdir(Rmdir),
|
||||
Ls(Ls),
|
||||
/// View license information
|
||||
License,
|
||||
// Download(Download),
|
||||
}
|
||||
|
||||
/// Upload files to the calculator
|
||||
|
@ -33,30 +34,37 @@ struct Upload {
|
|||
dest: String,
|
||||
}
|
||||
|
||||
// Create a directory
|
||||
/// Download files from the calculator
|
||||
#[derive(Clap, Debug)]
|
||||
struct Download {
|
||||
/// Files to download
|
||||
#[clap(required = true)]
|
||||
files: Vec<String>,
|
||||
/// Destination path
|
||||
#[clap(required = true, parse(from_os_str))]
|
||||
dest: PathBuf,
|
||||
}
|
||||
|
||||
/// Create a directory
|
||||
#[derive(Clap, Debug)]
|
||||
struct Mkdir {
|
||||
#[clap(required = true)]
|
||||
path: String
|
||||
path: String,
|
||||
}
|
||||
|
||||
// Delete a directory
|
||||
/// Delete a directory
|
||||
#[derive(Clap, Debug)]
|
||||
struct Rmdir {
|
||||
#[clap(required = true)]
|
||||
path: String
|
||||
path: String,
|
||||
}
|
||||
|
||||
// /// Download files from the calculator
|
||||
// #[derive(Clap, Debug)]
|
||||
// struct Download {
|
||||
// /// Files to download
|
||||
// #[clap(required = true)]
|
||||
// files: Vec<String>,
|
||||
// /// Destination path
|
||||
// #[clap(parse(from_os_str))]
|
||||
// dest: PathBuf,
|
||||
// }
|
||||
/// List the contents of a directory
|
||||
#[derive(Clap, Debug)]
|
||||
struct Ls {
|
||||
#[clap(required = true)]
|
||||
path: String,
|
||||
}
|
||||
|
||||
fn get_dev() -> Option<libnspire::Handle<rusb::GlobalContext>> {
|
||||
rusb::devices()
|
||||
|
@ -106,8 +114,7 @@ pub fn run() -> bool {
|
|||
if dest.ends_with('/') {
|
||||
dest.remove(dest.len() - 1);
|
||||
}
|
||||
let res = handle
|
||||
.write_file(&format!("{}/{}", dest, name), &buf, &mut |remaining| {
|
||||
let res = handle.write_file(&format!("{}/{}", dest, name), &buf, &mut |remaining| {
|
||||
bar.set_position((buf.len() - remaining) as u64)
|
||||
});
|
||||
|
||||
|
@ -125,6 +132,67 @@ pub fn run() -> bool {
|
|||
eprintln!("Couldn't find any device");
|
||||
}
|
||||
}
|
||||
SubCommand::Download(Download { dest, files }) => {
|
||||
if let Some(handle) = get_dev() {
|
||||
for file in files {
|
||||
let attr = handle.file_attr(&file);
|
||||
match attr {
|
||||
Ok(attr) => {
|
||||
let path = Path::new(&file);
|
||||
let dest_path = Path::join(&dest, path.file_name().unwrap().to_str().unwrap());
|
||||
match File::create(dest_path) {
|
||||
Ok(mut dest_file) => {
|
||||
let mut buf = vec![0u8; attr.size() as usize];
|
||||
|
||||
let bar = ProgressBar::new(buf.len() as u64);
|
||||
bar.set_style(ProgressStyle::default_bar().template("{spinner:.green} {msg} [{elapsed_precise}] [{bar:40.cyan/blue}] {bytes}/{total_bytes} ({bytes_per_sec}, {eta})"));
|
||||
bar.set_message(&format!(
|
||||
"Download {}",
|
||||
path.file_name().unwrap().to_str().unwrap()
|
||||
));
|
||||
bar.enable_steady_tick(100);
|
||||
|
||||
let len = buf.len();
|
||||
|
||||
let res = handle.read_file(&file, &mut buf, &mut |remaining| {
|
||||
bar.set_position((len - remaining) as u64);
|
||||
});
|
||||
|
||||
match res {
|
||||
Ok(_) => {
|
||||
bar.set_message("Writing file to disk");
|
||||
|
||||
match dest_file.write_all(&buf) {
|
||||
Ok(_) => {
|
||||
bar.finish_with_message("Transfer completed");
|
||||
}
|
||||
Err(error) => {
|
||||
bar.abandon_with_message(&format!(
|
||||
"Failed to write file to disk: {}",
|
||||
error
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(error) => {
|
||||
bar.abandon_with_message(&format!("Failed to transfer file: {}", error))
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(error) => {
|
||||
eprintln!("Failed to open destination file: {}", error);
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(error) => {
|
||||
eprintln!("Failed to read file info: {}", error);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
eprintln!("Couldn't find any device");
|
||||
}
|
||||
}
|
||||
SubCommand::Mkdir(Mkdir { path }) => {
|
||||
if let Some(handle) = get_dev() {
|
||||
match handle.create_dir(&path) {
|
||||
|
@ -153,6 +221,27 @@ pub fn run() -> bool {
|
|||
eprintln!("Couldn't find any device");
|
||||
}
|
||||
}
|
||||
SubCommand::Ls(Ls { path }) => {
|
||||
if let Some(handle) = get_dev() {
|
||||
match handle.list_dir(&path) {
|
||||
Ok(dir_list) => {
|
||||
for i in 0..dir_list.len() {
|
||||
let item = dir_list.get(i).unwrap();
|
||||
let mut item_name = String::from(item.name().to_str().unwrap());
|
||||
if item.entry_type() == EntryType::Directory {
|
||||
item_name += "/";
|
||||
}
|
||||
println!("{}", item_name);
|
||||
}
|
||||
}
|
||||
Err(error) => {
|
||||
eprintln!("Failed to list directory: {}", error);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
eprintln!("Couldn't find any device");
|
||||
}
|
||||
}
|
||||
SubCommand::License => {
|
||||
println!("{}", include_str!("../../LICENSE"));
|
||||
println!(include_str!("NOTICE.txt"), env!("CARGO_PKG_REPOSITORY"));
|
||||
|
|
Loading…
Reference in a new issue