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, Write};
|
||||||
use std::io::Read;
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
use std::{fs::File, path::Path};
|
||||||
|
|
||||||
use clap::Clap;
|
use clap::Clap;
|
||||||
use indicatif::{ProgressBar, ProgressStyle};
|
use indicatif::{ProgressBar, ProgressStyle};
|
||||||
use libnspire::{PID, PID_CX2, VID};
|
use libnspire::{dir::EntryType, PID, PID_CX2, VID};
|
||||||
|
|
||||||
#[derive(Clap, Debug)]
|
#[derive(Clap, Debug)]
|
||||||
#[clap(author, about, version)]
|
#[clap(author, about, version)]
|
||||||
|
@ -16,11 +16,12 @@ struct Opt {
|
||||||
#[derive(Clap, Debug)]
|
#[derive(Clap, Debug)]
|
||||||
enum SubCommand {
|
enum SubCommand {
|
||||||
Upload(Upload),
|
Upload(Upload),
|
||||||
|
Download(Download),
|
||||||
Mkdir(Mkdir),
|
Mkdir(Mkdir),
|
||||||
Rmdir(Rmdir),
|
Rmdir(Rmdir),
|
||||||
|
Ls(Ls),
|
||||||
/// View license information
|
/// View license information
|
||||||
License,
|
License,
|
||||||
// Download(Download),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Upload files to the calculator
|
/// Upload files to the calculator
|
||||||
|
@ -33,30 +34,37 @@ struct Upload {
|
||||||
dest: String,
|
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)]
|
#[derive(Clap, Debug)]
|
||||||
struct Mkdir {
|
struct Mkdir {
|
||||||
#[clap(required = true)]
|
#[clap(required = true)]
|
||||||
path: String
|
path: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete a directory
|
/// Delete a directory
|
||||||
#[derive(Clap, Debug)]
|
#[derive(Clap, Debug)]
|
||||||
struct Rmdir {
|
struct Rmdir {
|
||||||
#[clap(required = true)]
|
#[clap(required = true)]
|
||||||
path: String
|
path: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
// /// Download files from the calculator
|
/// List the contents of a directory
|
||||||
// #[derive(Clap, Debug)]
|
#[derive(Clap, Debug)]
|
||||||
// struct Download {
|
struct Ls {
|
||||||
// /// Files to download
|
#[clap(required = true)]
|
||||||
// #[clap(required = true)]
|
path: String,
|
||||||
// files: Vec<String>,
|
}
|
||||||
// /// Destination path
|
|
||||||
// #[clap(parse(from_os_str))]
|
|
||||||
// dest: PathBuf,
|
|
||||||
// }
|
|
||||||
|
|
||||||
fn get_dev() -> Option<libnspire::Handle<rusb::GlobalContext>> {
|
fn get_dev() -> Option<libnspire::Handle<rusb::GlobalContext>> {
|
||||||
rusb::devices()
|
rusb::devices()
|
||||||
|
@ -106,20 +114,80 @@ pub fn run() -> bool {
|
||||||
if dest.ends_with('/') {
|
if dest.ends_with('/') {
|
||||||
dest.remove(dest.len() - 1);
|
dest.remove(dest.len() - 1);
|
||||||
}
|
}
|
||||||
let res = handle
|
let res = handle.write_file(&format!("{}/{}", dest, name), &buf, &mut |remaining| {
|
||||||
.write_file(&format!("{}/{}", dest, name), &buf, &mut |remaining| {
|
bar.set_position((buf.len() - remaining) as u64)
|
||||||
bar.set_position((buf.len() - remaining) as u64)
|
});
|
||||||
});
|
|
||||||
|
|
||||||
match res {
|
match res {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
println!("Upload {}: Ok", dest);
|
println!("Upload {}: Ok", dest);
|
||||||
}
|
}
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
bar.abandon_with_message(&format!("Failed: {}", error));
|
bar.abandon_with_message(&format!("Failed: {}", error));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bar.finish();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bar.finish();
|
Err(error) => {
|
||||||
|
eprintln!("Failed to read file info: {}", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
eprintln!("Couldn't find any device");
|
eprintln!("Couldn't find any device");
|
||||||
|
@ -153,6 +221,27 @@ pub fn run() -> bool {
|
||||||
eprintln!("Couldn't find any device");
|
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 => {
|
SubCommand::License => {
|
||||||
println!("{}", include_str!("../../LICENSE"));
|
println!("{}", include_str!("../../LICENSE"));
|
||||||
println!(include_str!("NOTICE.txt"), env!("CARGO_PKG_REPOSITORY"));
|
println!(include_str!("NOTICE.txt"), env!("CARGO_PKG_REPOSITORY"));
|
||||||
|
|
Loading…
Reference in a new issue