Use merge to merge arguments and configuration

This patch adds the merge dependency to automatically merge the
command-line arguments and the settings from the configuration file.
This means that we no longer have to manually maintain the Args::merge
function.
This commit is contained in:
Robin Krahl 2020-09-20 22:18:28 +02:00
parent 0bf2f15186
commit 225e19a024
No known key found for this signature in database
GPG Key ID: 8E9B0870524F69D8
5 changed files with 41 additions and 31 deletions

View File

@ -8,6 +8,9 @@ SPDX-License-Identifier: MIT
# Unreleased
- Remove suffix from duplicate members (e. g. from Deref implementations).
- Use the `merge` crate to merge the command-line arguments and the settings in
the configuration file.
- Add `merge` dependency in version 0.1.0.
## v0.3.0 (2020-09-11)

23
Cargo.lock generated
View File

@ -462,6 +462,26 @@ name = "matches"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "merge"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"merge_derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "merge_derive"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro-error 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "miniz_oxide"
version = "0.4.0"
@ -818,6 +838,7 @@ dependencies = [
"kuchiki 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
"markup5ever 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
"merge 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"pager 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1320,6 +1341,8 @@ dependencies = [
"checksum markup5ever 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aae38d669396ca9b707bfc3db254bc382ddb94f57cc5c235f34623a669a01dab"
"checksum markup5ever_rcdom 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f015da43bcd8d4f144559a3423f4591d69b8ce0652c905374da7205df336ae2b"
"checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
"checksum merge 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "10bbef93abb1da61525bbc45eeaff6473a41907d19f8f9aa5168d214e10693e9"
"checksum merge_derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "209d075476da2e63b4b29e72a2ef627b840589588e71400a25e3565c4f849d07"
"checksum miniz_oxide 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "be0f75932c1f6cfae3c04000e40114adf955636e19040f9c0a2c380702aa1c7f"
"checksum mio 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6e9971bc8349a361217a8f2a41f5d011274686bd4436465ba51730921039d7fb"
"checksum miow 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "07b88fb9795d4d36d62a012dfbf49a8f5cf12751f36d31a9dbe66d528e58979e"

View File

@ -22,6 +22,7 @@ html2text = "0.1.12"
kuchiki = "0.8.0"
log = "0.4.11"
markup5ever = "0.10.0"
merge = "0.1.0"
pager = "0.15.0"
serde_json = "1.0.56"
serde_tuple = "0.5.0"

View File

@ -4,6 +4,7 @@
use std::fs;
use std::path;
use merge::Merge;
use serde::Deserialize;
use structopt::StructOpt;
@ -22,10 +23,11 @@ use crate::viewer;
/// rusty-man tries to find an item that exactly matches the given keyword. If it doesnt find an
/// exact match, it reads the search indexes of all available sources and tries to find a partial
/// match.
#[derive(Debug, Default, Deserialize, StructOpt)]
#[derive(Debug, Default, Deserialize, Merge, StructOpt)]
#[serde(default)]
pub struct Args {
/// The keyword to open the documentation for, e. g. `rand_core::RngCore`
#[merge(skip)]
#[serde(skip)]
pub keyword: doc::Name,
@ -33,6 +35,7 @@ pub struct Args {
///
/// Typically, this is the path of a directory containing the documentation for one or more
/// crates in subdirectories.
#[merge(strategy = merge::vec::prepend)]
#[structopt(name = "source", short, long, number_of_values = 1)]
pub source_paths: Vec<String>,
@ -46,6 +49,7 @@ pub struct Args {
/// If this option is not set, rusty-man appends `$sysroot/share/doc/rust{,-doc}/html` and
/// `target/doc` to the list of sources if they exist. `$sysroot` is the output of `rustc
/// --print sysroot` or `/usr` if that command does not output a valid path.
#[merge(strategy = merge::bool::overwrite_false)]
#[structopt(long)]
pub no_default_sources: bool,
@ -54,10 +58,12 @@ pub struct Args {
/// Per default, rusty-man reads the search indexes of all sources and tries to find matching
/// items if there is no exact match for the keyword. If this option is set, the search
/// indexes are not read.
#[merge(strategy = merge::bool::overwrite_false)]
#[structopt(long)]
pub no_search: bool,
/// Show all examples for the item instead of opening the full documentation.
#[merge(strategy = merge::bool::overwrite_false)]
#[structopt(short, long)]
pub examples: bool,
@ -70,6 +76,7 @@ pub struct Args {
///
/// If this option is set, rusty-man reads the given configuration file instead. If this
/// option is set to "-", rusty-man does not read any configuration files.
#[merge(skip)]
#[structopt(short, long)]
#[serde(skip)]
pub config_file: Option<String>,
@ -79,13 +86,14 @@ pub struct Args {
pub viewer_args: ViewerArgs,
}
#[derive(Debug, Default, Deserialize, StructOpt)]
#[derive(Debug, Default, Deserialize, Merge, StructOpt)]
#[serde(default)]
pub struct ViewerArgs {
/// Disable syntax highlighting.
///
/// Per default, rusty-man tries to highlight Rust code snippets in its output if the rich text
/// viewer is selected. If this option is set, it renders the HTML representation instead.
#[merge(strategy = merge::bool::overwrite_false)]
#[structopt(long)]
pub no_syntax_highlight: bool,
@ -109,8 +117,8 @@ pub struct ViewerArgs {
///
/// Unless the --width option is set, rusty-man sets the width of the text output based on the
/// width of the terminal with the maximum width set with this optioj.
#[structopt(long, default_value = "100")]
pub max_width: usize,
#[structopt(long)]
pub max_width: Option<usize>,
}
impl Args {
@ -143,31 +151,6 @@ impl Args {
Ok(None)
}
}
fn merge(&mut self, mut args: Args) {
if !args.source_paths.is_empty() {
args.source_paths.append(&mut self.source_paths);
self.source_paths = args.source_paths;
}
if self.viewer.is_none() {
self.viewer = args.viewer;
}
if !self.no_default_sources {
self.no_default_sources = args.no_default_sources;
}
if !self.no_search {
self.no_search = args.no_search;
}
if !self.examples {
self.examples = args.examples;
}
if !self.viewer_args.no_syntax_highlight {
self.viewer_args.no_syntax_highlight = args.viewer_args.no_syntax_highlight;
}
if self.viewer_args.theme.is_none() {
self.viewer_args.theme = args.viewer_args.theme;
}
}
}
fn deserialize_viewer<'de, D>(d: D) -> Result<Option<Box<dyn viewer::Viewer>>, D::Error>

View File

@ -114,9 +114,9 @@ pub fn get_line_length(args: &args::ViewerArgs) -> usize {
if let Some(width) = args.width {
width
} else if let Ok((cols, _)) = crossterm::terminal::size() {
cmp::min(cols.into(), args.max_width)
cmp::min(cols.into(), args.max_width.unwrap_or(100))
} else {
args.max_width
args.max_width.unwrap_or(100)
}
}