argh instead of getopts
This commit is contained in:
parent
e15b79750b
commit
421969c3da
|
@ -49,7 +49,9 @@ Released on FIXME: ??
|
|||
- Fixed broken input cursor when typing UTF8 characters (tui-realm 0.3.2)
|
||||
- Fixed save bookmark dialog: you could switch out from dialog with `<TAB>`
|
||||
- Dependencies:
|
||||
- Added `argh 0.1.5`
|
||||
- Added `open 1.7.0`
|
||||
- Removed `getopts`
|
||||
- Updated `rand` to `0.8.4`
|
||||
- Updated `textwrap` to `0.14.2`
|
||||
- Updated `tui-realm` to `0.4.3`
|
||||
|
|
53
Cargo.lock
generated
53
Cargo.lock
generated
|
@ -51,6 +51,35 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "argh"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2e7317a549bc17c5278d9e72bb6e62c6aa801ac2567048e39ebc1c194249323e"
|
||||
dependencies = [
|
||||
"argh_derive",
|
||||
"argh_shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "argh_derive"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60949c42375351e9442e354434b0cba2ac402c1237edf673cac3a4bf983b8d3c"
|
||||
dependencies = [
|
||||
"argh_shared",
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "argh_shared"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a61eb019cb8f415d162cb9f12130ee6bbe9168b7d953c17f4ad049e4051ca00"
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.0.1"
|
||||
|
@ -402,15 +431,6 @@ dependencies = [
|
|||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getopts"
|
||||
version = "0.2.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5"
|
||||
dependencies = [
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.1.16"
|
||||
|
@ -433,6 +453,15 @@ dependencies = [
|
|||
"wasi 0.10.0+wasi-snapshot-preview1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
|
||||
dependencies = [
|
||||
"unicode-segmentation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hkdf"
|
||||
version = "0.10.0"
|
||||
|
@ -519,9 +548,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
|||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.97"
|
||||
version = "0.2.98"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "12b8adadd720df158f4d70dfe7ccc6adb0472d7c55ca83445f6a5ab3e36f8fb6"
|
||||
checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790"
|
||||
|
||||
[[package]]
|
||||
name = "libssh2-sys"
|
||||
|
@ -1327,6 +1356,7 @@ dependencies = [
|
|||
name = "termscp"
|
||||
version = "0.6.0"
|
||||
dependencies = [
|
||||
"argh",
|
||||
"bitflags",
|
||||
"bytesize",
|
||||
"chrono",
|
||||
|
@ -1335,7 +1365,6 @@ dependencies = [
|
|||
"dirs",
|
||||
"edit",
|
||||
"ftp4",
|
||||
"getopts",
|
||||
"hostname",
|
||||
"keyring",
|
||||
"lazy_static",
|
||||
|
|
|
@ -27,6 +27,7 @@ name = "termscp"
|
|||
path = "src/main.rs"
|
||||
|
||||
[dependencies]
|
||||
argh = "0.1.5"
|
||||
bitflags = "1.2.1"
|
||||
bytesize = "1.0.1"
|
||||
chrono = "0.4.19"
|
||||
|
@ -35,7 +36,6 @@ crossterm = "0.19.0"
|
|||
dirs = "3.0.1"
|
||||
edit = "0.1.3"
|
||||
ftp4 = { version = "4.0.2", features = [ "secure" ] }
|
||||
getopts = "0.2.21"
|
||||
hostname = "0.3.1"
|
||||
keyring = { version = "0.10.1", optional = true }
|
||||
lazy_static = "1.4.0"
|
||||
|
|
129
src/main.rs
129
src/main.rs
|
@ -26,7 +26,7 @@ const TERMSCP_VERSION: &str = env!("CARGO_PKG_VERSION");
|
|||
const TERMSCP_AUTHORS: &str = env!("CARGO_PKG_AUTHORS");
|
||||
|
||||
// Crates
|
||||
extern crate getopts;
|
||||
extern crate argh;
|
||||
#[macro_use]
|
||||
extern crate bitflags;
|
||||
#[macro_use]
|
||||
|
@ -38,7 +38,7 @@ extern crate magic_crypt;
|
|||
extern crate rpassword;
|
||||
|
||||
// External libs
|
||||
use getopts::{Matches, Options};
|
||||
use argh::FromArgs;
|
||||
use std::env;
|
||||
use std::path::PathBuf;
|
||||
use std::time::Duration;
|
||||
|
@ -64,6 +64,38 @@ enum Task {
|
|||
ImportTheme(PathBuf),
|
||||
}
|
||||
|
||||
#[derive(FromArgs)]
|
||||
#[argh(description = "
|
||||
where positional can be: [protocol://user@address:port:wrkdir] [local-wrkdir]
|
||||
|
||||
Please, report issues to <https://github.com/veeso/termscp>
|
||||
Please, consider supporting the author <https://www.buymeacoffee.com/veeso>")]
|
||||
struct Args {
|
||||
#[argh(switch, short = 'c', description = "open termscp configuration")]
|
||||
config: bool,
|
||||
#[argh(option, short = 'P', description = "provide password from CLI")]
|
||||
password: Option<String>,
|
||||
#[argh(switch, short = 'q', description = "disable logging")]
|
||||
quiet: bool,
|
||||
#[argh(option, short = 't', description = "import specified theme")]
|
||||
theme: Option<String>,
|
||||
#[argh(
|
||||
option,
|
||||
short = 'T',
|
||||
default = "10",
|
||||
description = "set UI ticks; default 10ms"
|
||||
)]
|
||||
ticks: u64,
|
||||
#[argh(switch, short = 'v', description = "print version")]
|
||||
version: bool,
|
||||
// -- positional
|
||||
#[argh(
|
||||
positional,
|
||||
description = "protocol://user@address:port:wrkdir local-wrkdir"
|
||||
)]
|
||||
positional: Vec<String>,
|
||||
}
|
||||
|
||||
struct RunOpts {
|
||||
address: Option<String>,
|
||||
port: u16,
|
||||
|
@ -93,34 +125,15 @@ impl Default for RunOpts {
|
|||
}
|
||||
|
||||
fn main() {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
//Program CLI options
|
||||
let mut run_opts: RunOpts = RunOpts::default();
|
||||
//Process options
|
||||
let mut opts = Options::new();
|
||||
opts.optflag("c", "config", "Open termscp configuration");
|
||||
opts.optflag("q", "quiet", "Disable logging");
|
||||
opts.optopt("t", "theme", "Import specified theme", "<path>");
|
||||
opts.optopt("P", "password", "Provide password from CLI", "<password>");
|
||||
opts.optopt("T", "ticks", "Set UI ticks; default 10ms", "<ms>");
|
||||
opts.optflag("v", "version", "");
|
||||
opts.optflag("h", "help", "Print this menu");
|
||||
let matches: Matches = match opts.parse(&args[1..]) {
|
||||
Ok(m) => m,
|
||||
Err(f) => {
|
||||
println!("{}", f.to_string());
|
||||
let args: Args = argh::from_env();
|
||||
// Parse args
|
||||
let mut run_opts: RunOpts = match parse_args(args) {
|
||||
Ok(opts) => opts,
|
||||
Err(err) => {
|
||||
eprintln!("{}", err);
|
||||
std::process::exit(255);
|
||||
}
|
||||
};
|
||||
// Parse args
|
||||
if let Err(err) = parse_run_opts(&mut run_opts, matches) {
|
||||
if let Some(err) = err {
|
||||
eprintln!("{}", err);
|
||||
} else {
|
||||
print_usage(opts);
|
||||
}
|
||||
std::process::exit(255);
|
||||
}
|
||||
// Setup logging
|
||||
if run_opts.log_enabled {
|
||||
if let Err(err) = logging::init() {
|
||||
|
@ -141,65 +154,43 @@ fn main() {
|
|||
std::process::exit(rc);
|
||||
}
|
||||
|
||||
/// ### print_usage
|
||||
/// ### parse_args
|
||||
///
|
||||
/// Print usage
|
||||
fn print_usage(opts: Options) {
|
||||
let brief = String::from(
|
||||
"Usage: termscp [options]... [protocol://user@address:port:wrkdir] [local-wrkdir]",
|
||||
);
|
||||
print!("{}", opts.usage(&brief));
|
||||
println!("\nPlease, report issues to <https://github.com/veeso/termscp>");
|
||||
println!("Please, consider supporting the author <https://www.buymeacoffee.com/veeso>")
|
||||
}
|
||||
|
||||
/// ### parse_run_opts
|
||||
///
|
||||
/// Parse run options; in case something is wrong returns the error message
|
||||
fn parse_run_opts(run_opts: &mut RunOpts, opts: Matches) -> Result<(), Option<String>> {
|
||||
// Help
|
||||
if opts.opt_present("h") {
|
||||
return Err(None);
|
||||
}
|
||||
/// Parse arguments
|
||||
/// In case of success returns `RunOpts`
|
||||
/// in case something is wrong returns the error message
|
||||
fn parse_args(args: Args) -> Result<RunOpts, String> {
|
||||
let mut run_opts: RunOpts = RunOpts::default();
|
||||
// Version
|
||||
if opts.opt_present("v") {
|
||||
return Err(Some(format!(
|
||||
if args.version {
|
||||
return Err(format!(
|
||||
"termscp - {} - Developed by {}",
|
||||
TERMSCP_VERSION, TERMSCP_AUTHORS,
|
||||
)));
|
||||
));
|
||||
}
|
||||
// Setup activity?
|
||||
if opts.opt_present("c") {
|
||||
if args.config {
|
||||
run_opts.task = Task::Activity(NextActivity::SetupActivity);
|
||||
}
|
||||
// Logging
|
||||
if opts.opt_present("q") {
|
||||
if args.quiet {
|
||||
run_opts.log_enabled = false;
|
||||
}
|
||||
// Match password
|
||||
if let Some(passwd) = opts.opt_str("P") {
|
||||
if let Some(passwd) = args.password {
|
||||
run_opts.password = Some(passwd);
|
||||
}
|
||||
// Match ticks
|
||||
if let Some(val) = opts.opt_str("T") {
|
||||
match val.parse::<usize>() {
|
||||
Ok(val) => run_opts.ticks = Duration::from_millis(val as u64),
|
||||
Err(_) => {
|
||||
return Err(Some(format!("Ticks is not a number: '{}'", val)));
|
||||
}
|
||||
}
|
||||
}
|
||||
run_opts.ticks = Duration::from_millis(args.ticks);
|
||||
// @! extra modes
|
||||
if let Some(theme) = opts.opt_str("t") {
|
||||
if let Some(theme) = args.theme {
|
||||
run_opts.task = Task::ImportTheme(PathBuf::from(theme));
|
||||
}
|
||||
// @! Ordinary mode
|
||||
// Check free args
|
||||
let extra_args: Vec<String> = opts.free;
|
||||
// Remote argument
|
||||
if let Some(remote) = extra_args.get(0) {
|
||||
if let Some(remote) = args.positional.get(0) {
|
||||
// Parse address
|
||||
match utils::parser::parse_remote_opt(remote) {
|
||||
match utils::parser::parse_remote_opt(remote.as_str()) {
|
||||
Ok(host_opts) => {
|
||||
// Set params
|
||||
run_opts.address = Some(host_opts.hostname);
|
||||
|
@ -211,19 +202,19 @@ fn parse_run_opts(run_opts: &mut RunOpts, opts: Matches) -> Result<(), Option<St
|
|||
run_opts.task = Task::Activity(NextActivity::FileTransfer);
|
||||
}
|
||||
Err(err) => {
|
||||
return Err(Some(format!("Bad address option: {}", err)));
|
||||
return Err(format!("Bad address option: {}", err));
|
||||
}
|
||||
}
|
||||
}
|
||||
// Local directory
|
||||
if let Some(localdir) = extra_args.get(1) {
|
||||
if let Some(localdir) = args.positional.get(1) {
|
||||
// Change working directory if local dir is set
|
||||
let localdir: PathBuf = PathBuf::from(localdir);
|
||||
if let Err(err) = env::set_current_dir(localdir.as_path()) {
|
||||
return Err(Some(format!("Bad working directory argument: {}", err)));
|
||||
return Err(format!("Bad working directory argument: {}", err));
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
Ok(run_opts)
|
||||
}
|
||||
|
||||
/// ### read_password
|
||||
|
|
Loading…
Reference in a new issue