feat: add completions (#97)

This commit is contained in:
sigoden 2022-07-06 12:11:00 +08:00 committed by GitHub
parent 140a360e37
commit 76e967fa59
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 75 additions and 14 deletions

26
Cargo.lock generated
View file

@ -234,6 +234,15 @@ dependencies = [
"textwrap",
]
[[package]]
name = "clap_complete"
version = "3.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ead064480dfc4880a10764488415a97fdd36a4cf1bb022d372f02e8faf8386e1"
dependencies = [
"clap",
]
[[package]]
name = "clap_lex"
version = "0.2.4"
@ -289,9 +298,9 @@ dependencies = [
[[package]]
name = "crypto-common"
version = "0.1.3"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8"
checksum = "5999502d32b9c48d492abe66392408144895020ec4709e549e840799f3bb74c0"
dependencies = [
"generic-array",
"typenum",
@ -379,6 +388,7 @@ dependencies = [
"base64",
"chrono",
"clap",
"clap_complete",
"diqwest",
"futures",
"headers",
@ -1087,9 +1097,9 @@ dependencies = [
[[package]]
name = "once_cell"
version = "1.12.0"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225"
checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1"
[[package]]
name = "opaque-debug"
@ -1431,9 +1441,9 @@ dependencies = [
[[package]]
name = "regex"
version = "1.5.6"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d83f127d94bdbcda4c8cc2e50f6f84f4b611f69c902699ca385a39c3a75f9ff1"
checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b"
dependencies = [
"aho-corasick",
"memchr",
@ -1448,9 +1458,9 @@ checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
[[package]]
name = "regex-syntax"
version = "0.6.26"
version = "0.6.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64"
checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
[[package]]
name = "remove_dir_all"

View file

@ -12,6 +12,7 @@ keywords = ["static", "file", "server", "webdav", "cli"]
[dependencies]
clap = { version = "3", default-features = false, features = ["std", "wrap_help"] }
clap_complete = "3"
chrono = "0.4"
tokio = { version = "1", features = ["rt-multi-thread", "macros", "fs", "io-util", "signal"]}
tokio-util = { version = "0.7", features = ["io-util"] }

View file

@ -1,4 +1,5 @@
use clap::{AppSettings, Arg, ArgMatches, Command};
use clap::{value_parser, AppSettings, Arg, ArgMatches, Command};
use clap_complete::{generate, Generator, Shell};
#[cfg(feature = "tls")]
use rustls::{Certificate, PrivateKey};
use std::env;
@ -11,7 +12,7 @@ use crate::auth::AuthMethod;
use crate::tls::{load_certs, load_private_key};
use crate::BoxResult;
fn app() -> Command<'static> {
pub fn build_cli() -> Command<'static> {
let app = Command::new(env!("CARGO_CRATE_NAME"))
.version(env!("CARGO_PKG_VERSION"))
.author(env!("CARGO_PKG_AUTHORS"))
@ -118,6 +119,13 @@ fn app() -> Command<'static> {
Arg::new("render-spa")
.long("render-spa")
.help("Serve SPA(Single Page Application)"),
)
.arg(
Arg::new("completions")
.long("completions")
.value_name("shell")
.value_parser(value_parser!(Shell))
.help("Print shell completion script for <shell>"),
);
#[cfg(feature = "tls")]
@ -138,8 +146,8 @@ fn app() -> Command<'static> {
app
}
pub fn matches() -> ArgMatches {
app().get_matches()
pub fn print_completions<G: Generator>(gen: G, cmd: &mut Command) {
generate(gen, cmd, cmd.get_name().to_string(), &mut std::io::stdout());
}
#[derive(Debug)]

View file

@ -10,7 +10,7 @@ mod utils;
#[macro_use]
extern crate log;
use crate::args::{matches, Args};
use crate::args::{build_cli, print_completions, Args};
use crate::server::{Request, Server};
#[cfg(feature = "tls")]
use crate::tls::{TlsAcceptor, TlsStream};
@ -19,6 +19,7 @@ use std::net::{IpAddr, SocketAddr, TcpListener as StdTcpListener};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use clap_complete::Shell;
use futures::future::join_all;
use tokio::net::TcpListener;
use tokio::task::JoinHandle;
@ -37,7 +38,14 @@ async fn main() {
async fn run() -> BoxResult<()> {
logger::init().map_err(|e| format!("Failed to init logger, {}", e))?;
let args = Args::parse(matches())?;
let cmd = build_cli();
let matches = cmd.get_matches();
if let Some(generator) = matches.get_one::<Shell>("completions") {
let mut cmd = build_cli();
print_completions(*generator, &mut cmd);
return Ok(());
}
let args = Args::parse(matches)?;
let args = Arc::new(args);
let running = Arc::new(AtomicBool::new(true));
let handles = serve(args.clone(), running.clone())?;

View file

@ -1,3 +1,5 @@
//! Run file server with different args
mod fixtures;
mod utils;

32
tests/cli.rs Normal file
View file

@ -0,0 +1,32 @@
//! Run cli with different args, not starting a server
mod fixtures;
use assert_cmd::prelude::*;
use clap::ValueEnum;
use clap_complete::Shell;
use fixtures::Error;
use std::process::Command;
#[test]
/// Show help and exit.
fn help_shows() -> Result<(), Error> {
Command::cargo_bin("dufs")?.arg("-h").assert().success();
Ok(())
}
#[test]
/// Print completions and exit.
fn print_completions() -> Result<(), Error> {
// let shell_enums = EnumValueParser::<Shell>::new();
for shell in Shell::value_variants() {
Command::cargo_bin("dufs")?
.arg("--completions")
.arg(shell.to_string())
.assert()
.success();
}
Ok(())
}