From a389db173b8b6f38c8330ddecf00023c72c8ee86 Mon Sep 17 00:00:00 2001 From: Andy Freeland Date: Thu, 25 Mar 2021 21:06:08 -0700 Subject: Generate completions with `miniserve --print-completions ` This patch adds a `--print-completions` option to generate shell completion files at runtime. This ensures the completions are always up to date. Fixes #377. --- src/args.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'src/args.rs') diff --git a/src/args.rs b/src/args.rs index 909a88f..d6cfc69 100644 --- a/src/args.rs +++ b/src/args.rs @@ -21,7 +21,7 @@ const ROUTE_ALPHABET: [char; 16] = [ about, global_settings = &[structopt::clap::AppSettings::ColoredHelp], )] -struct CliArgs { +pub struct CliArgs { /// Be verbose, includes emitting access logs #[structopt(short = "v", long = "verbose")] verbose: bool, @@ -131,6 +131,10 @@ struct CliArgs { /// Hide version footer #[structopt(short = "F", long = "hide-version-footer")] hide_version_footer: bool, + + /// Generate completion file for a shell + #[structopt(long = "print-completions", value_name = "shell")] + pub print_completions: Option, } /// Checks wether an interface is valid, i.e. it can be parsed into an IP address @@ -205,9 +209,7 @@ pub fn parse_header(src: &str) -> Result { } /// Parses the command line arguments -pub fn parse_args() -> crate::MiniserveConfig { - let args = CliArgs::from_args(); - +pub fn parse_args(args: CliArgs) -> crate::MiniserveConfig { let interfaces = if !args.interfaces.is_empty() { args.interfaces } else { -- cgit v1.2.3 From 26b0a519d226f555674db481f3a3cd2fc52a9961 Mon Sep 17 00:00:00 2001 From: Sven-Hendrik Haase Date: Sun, 28 Mar 2021 21:16:39 +0200 Subject: Refactor and separate out arg handling and config handling --- src/args.rs | 107 ++++++++++++------------------------------------------------ 1 file changed, 21 insertions(+), 86 deletions(-) (limited to 'src/args.rs') diff --git a/src/args.rs b/src/args.rs index d6cfc69..169b56f 100644 --- a/src/args.rs +++ b/src/args.rs @@ -1,7 +1,6 @@ use bytes::Bytes; use http::header::{HeaderMap, HeaderName, HeaderValue}; -use port_check::free_local_port; -use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; +use std::net::IpAddr; use std::path::PathBuf; use structopt::StructOpt; @@ -9,11 +8,6 @@ use crate::auth; use crate::errors::ContextualError; use crate::renderer; -/// Possible characters for random routes -const ROUTE_ALPHABET: [char; 16] = [ - '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 'a', 'b', 'c', 'd', 'e', 'f', -]; - #[derive(StructOpt)] #[structopt( name = "miniserve", @@ -24,22 +18,22 @@ const ROUTE_ALPHABET: [char; 16] = [ pub struct CliArgs { /// Be verbose, includes emitting access logs #[structopt(short = "v", long = "verbose")] - verbose: bool, + pub verbose: bool, /// Which path to serve #[structopt(name = "PATH", parse(from_os_str))] - path: Option, + pub path: Option, /// The name of a directory index file to serve, like "index.html" /// /// Normally, when miniserve serves a directory, it creates a listing for that directory. /// However, if a directory contains this file, miniserve will serve that file instead. #[structopt(long, parse(from_os_str), name = "index_file")] - index: Option, + pub index: Option, /// Port to use #[structopt(short = "p", long = "port", default_value = "8080")] - port: u16, + pub port: u16, /// Interface to listen on #[structopt( @@ -48,7 +42,7 @@ pub struct CliArgs { parse(try_from_str = parse_interface), number_of_values = 1, )] - interfaces: Vec, + pub interfaces: Vec, /// Set authentication. Currently supported formats: /// username:password, username:sha256:hash, username:sha512:hash @@ -59,19 +53,19 @@ pub struct CliArgs { parse(try_from_str = parse_auth), number_of_values = 1, )] - auth: Vec, + pub auth: Vec, /// Generate a random 6-hexdigit route #[structopt(long = "random-route")] - random_route: bool, + pub random_route: bool, /// Do not follow symbolic links #[structopt(short = "P", long = "no-symlinks")] - no_symlinks: bool, + pub no_symlinks: bool, /// Show hidden files #[structopt(short = "H", long = "hidden")] - hidden: bool, + pub hidden: bool, /// Default color scheme #[structopt( @@ -81,7 +75,7 @@ pub struct CliArgs { possible_values = &renderer::THEME_SLUGS, case_insensitive = true, )] - color_scheme: String, + pub color_scheme: String, /// Default color scheme #[structopt( @@ -91,46 +85,46 @@ pub struct CliArgs { possible_values = &renderer::THEME_SLUGS, case_insensitive = true, )] - color_scheme_dark: String, + pub color_scheme_dark: String, /// Enable QR code display #[structopt(short = "q", long = "qrcode")] - qrcode: bool, + pub qrcode: bool, /// Enable file uploading #[structopt(short = "u", long = "upload-files")] - file_upload: bool, + pub file_upload: bool, /// Enable overriding existing files during file upload #[structopt(short = "o", long = "overwrite-files")] - overwrite_files: bool, + pub overwrite_files: bool, /// Enable tar archive generation #[structopt(short = "r", long = "enable-tar")] - enable_tar: bool, + pub enable_tar: bool, /// Enable zip archive generation /// /// WARNING: Zipping large directories can result in out-of-memory exception /// because zip generation is done in memory and cannot be sent on the fly #[structopt(short = "z", long = "enable-zip")] - enable_zip: bool, + pub enable_zip: bool, /// List directories first #[structopt(short = "D", long = "dirs-first")] - dirs_first: bool, + pub dirs_first: bool, /// Shown instead of host in page title and heading #[structopt(short = "t", long = "title")] - title: Option, + pub title: Option, /// Set custom header for responses #[structopt(long = "header", parse(try_from_str = parse_header), number_of_values = 1)] - header: Vec, + pub header: Vec, /// Hide version footer #[structopt(short = "F", long = "hide-version-footer")] - hide_version_footer: bool, + pub hide_version_footer: bool, /// Generate completion file for a shell #[structopt(long = "print-completions", value_name = "shell")] @@ -208,65 +202,6 @@ pub fn parse_header(src: &str) -> Result { Ok(header_map) } -/// Parses the command line arguments -pub fn parse_args(args: CliArgs) -> crate::MiniserveConfig { - let interfaces = if !args.interfaces.is_empty() { - args.interfaces - } else { - vec![ - IpAddr::V6(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)), - IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), - ] - }; - - let random_route = if args.random_route { - Some(nanoid::nanoid!(6, &ROUTE_ALPHABET)) - } else { - None - }; - - // Generate some random routes for the favicon and css so that they are very unlikely to conflict with - // real files. - let favicon_route = nanoid::nanoid!(10, &ROUTE_ALPHABET); - let css_route = nanoid::nanoid!(10, &ROUTE_ALPHABET); - - let default_color_scheme = args.color_scheme; - let default_color_scheme_dark = args.color_scheme_dark; - - let path_explicitly_chosen = args.path.is_some() || args.index.is_some(); - - let port = match args.port { - 0 => free_local_port().expect("no free ports available"), - _ => args.port, - }; - - crate::MiniserveConfig { - verbose: args.verbose, - path: args.path.unwrap_or_else(|| PathBuf::from(".")), - port, - interfaces, - auth: args.auth, - path_explicitly_chosen, - no_symlinks: args.no_symlinks, - show_hidden: args.hidden, - random_route, - favicon_route, - css_route, - default_color_scheme, - default_color_scheme_dark, - index: args.index, - overwrite_files: args.overwrite_files, - show_qrcode: args.qrcode, - file_upload: args.file_upload, - tar_enabled: args.enable_tar, - zip_enabled: args.enable_zip, - dirs_first: args.dirs_first, - title: args.title, - header: args.header, - hide_version_footer: args.hide_version_footer, - } -} - #[rustfmt::skip] #[cfg(test)] mod tests { -- cgit v1.2.3 From 531c9e0351035b23ae0c6088807358338c20b974 Mon Sep 17 00:00:00 2001 From: Sven-Hendrik Haase Date: Sun, 28 Mar 2021 21:19:27 +0200 Subject: Print supported shells for completions in help command --- src/args.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/args.rs') diff --git a/src/args.rs b/src/args.rs index 169b56f..81e49dc 100644 --- a/src/args.rs +++ b/src/args.rs @@ -127,7 +127,7 @@ pub struct CliArgs { pub hide_version_footer: bool, /// Generate completion file for a shell - #[structopt(long = "print-completions", value_name = "shell")] + #[structopt(long = "print-completions", value_name = "shell", possible_values = &structopt::clap::Shell::variants())] pub print_completions: Option, } -- cgit v1.2.3 From 2bae301ed8efcf4239849a45b94cdc42e398b905 Mon Sep 17 00:00:00 2001 From: Dean Li Date: Sun, 11 Apr 2021 11:00:16 +0800 Subject: Separate tar archive and tar flags It used to have one flag (-r) to enable both tar archive and tar. Now it has two flags [ -r: for tar, -g: for tar archive]. Related to #451 --- src/args.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/args.rs') diff --git a/src/args.rs b/src/args.rs index 81e49dc..bf30254 100644 --- a/src/args.rs +++ b/src/args.rs @@ -99,10 +99,14 @@ pub struct CliArgs { #[structopt(short = "o", long = "overwrite-files")] pub overwrite_files: bool, - /// Enable tar archive generation + /// Enable tar generation #[structopt(short = "r", long = "enable-tar")] pub enable_tar: bool, + /// Enable tar archive generation + #[structopt(short = "g", long = "enable-tar-archive")] + pub enable_tar_archive: bool, + /// Enable zip archive generation /// /// WARNING: Zipping large directories can result in out-of-memory exception -- cgit v1.2.3 From c9506c72ff368867982d138a686648fa302b116d Mon Sep 17 00:00:00 2001 From: Dean Li Date: Sun, 18 Apr 2021 11:22:52 +0800 Subject: Change naming of uncompressed/compressed tarballs Use following terminology: uncompressed tarballs => `uncompressed tar archives` compressed ones => `gz-compressed tar archives` --- src/args.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/args.rs') diff --git a/src/args.rs b/src/args.rs index bf30254..819618f 100644 --- a/src/args.rs +++ b/src/args.rs @@ -99,13 +99,13 @@ pub struct CliArgs { #[structopt(short = "o", long = "overwrite-files")] pub overwrite_files: bool, - /// Enable tar generation + /// Enable uncompressed tar archive generation #[structopt(short = "r", long = "enable-tar")] pub enable_tar: bool, - /// Enable tar archive generation - #[structopt(short = "g", long = "enable-tar-archive")] - pub enable_tar_archive: bool, + /// Enable gz-compressed tar archive generation + #[structopt(short = "g", long = "enable-tar-gz")] + pub enable_tar_gz: bool, /// Enable zip archive generation /// -- cgit v1.2.3