diff --git a/src/uu/comm/comm.md b/src/uu/comm/comm.md new file mode 100644 index 000000000..91f4467d4 --- /dev/null +++ b/src/uu/comm/comm.md @@ -0,0 +1,13 @@ +# comm + +``` +comm [OPTION]... FILE1 FILE2 +``` + +Compare two sorted files line by line. + +When FILE1 or FILE2 (not both) is -, read standard input. + +With no options, produce three-column output. Column one contains +lines unique to FILE1, column two contains lines unique to FILE2, +and column three contains lines common to both files. diff --git a/src/uu/comm/src/comm.rs b/src/uu/comm/src/comm.rs index c14717df2..3bc45b6a5 100644 --- a/src/uu/comm/src/comm.rs +++ b/src/uu/comm/src/comm.rs @@ -13,13 +13,12 @@ use std::io::{self, stdin, BufRead, BufReader, Stdin}; use std::path::Path; use uucore::error::FromIo; use uucore::error::UResult; -use uucore::format_usage; +use uucore::{format_usage, help_about, help_usage}; use clap::{crate_version, Arg, ArgAction, ArgMatches, Command}; -static ABOUT: &str = "Compare two sorted files line by line"; -static LONG_HELP: &str = ""; -const USAGE: &str = "{} [OPTION]... FILE1 FILE2"; +const ABOUT: &str = help_about!("comm.md"); +const USAGE: &str = help_usage!("comm.md"); mod options { pub const COLUMN_1: &str = "1"; @@ -160,7 +159,6 @@ pub fn uu_app() -> Command { Command::new(uucore::util_name()) .version(crate_version!()) .about(ABOUT) - .after_help(LONG_HELP) .override_usage(format_usage(USAGE)) .infer_long_args(true) .arg( diff --git a/src/uu/dirname/dirname.md b/src/uu/dirname/dirname.md new file mode 100644 index 000000000..f08c1c4c9 --- /dev/null +++ b/src/uu/dirname/dirname.md @@ -0,0 +1,12 @@ +# dirname + +``` +dirname [OPTION] NAME... +``` + +Strip last component from file name + +## After Help + +Output each NAME with its last non-slash component and trailing slashes +removed; if NAME contains no /'s, output '.' (meaning the current directory). diff --git a/src/uu/dirname/src/dirname.rs b/src/uu/dirname/src/dirname.rs index bebdd4d36..687aaa550 100644 --- a/src/uu/dirname/src/dirname.rs +++ b/src/uu/dirname/src/dirname.rs @@ -9,13 +9,11 @@ use clap::{crate_version, Arg, ArgAction, Command}; use std::path::Path; use uucore::display::print_verbatim; use uucore::error::{UResult, UUsageError}; -use uucore::format_usage; +use uucore::{format_usage, help_about, help_section, help_usage}; -const ABOUT: &str = "Strip last component from file name"; -const USAGE: &str = "{} [OPTION] NAME..."; -const LONG_USAGE: &str = "\ - Output each NAME with its last non-slash component and trailing slashes \n\ - removed; if NAME contains no /'s, output '.' (meaning the current directory)."; +const ABOUT: &str = help_about!("dirname.md"); +const USAGE: &str = help_usage!("dirname.md"); +const AFTER_HELP: &str = help_section!("after help", "dirname.md"); mod options { pub const ZERO: &str = "zero"; @@ -26,7 +24,7 @@ mod options { pub fn uumain(args: impl uucore::Args) -> UResult<()> { let args = args.collect_lossy(); - let matches = uu_app().after_help(LONG_USAGE).try_get_matches_from(args)?; + let matches = uu_app().after_help(AFTER_HELP).try_get_matches_from(args)?; let separator = if matches.get_flag(options::ZERO) { "\0" diff --git a/util/size-experiment.py b/util/size-experiment.py new file mode 100644 index 000000000..8acacf9d1 --- /dev/null +++ b/util/size-experiment.py @@ -0,0 +1,90 @@ +import subprocess +from itertools import product +import shutil +import os +from collections import defaultdict +from pprint import pprint + +# Set to false if you've only changed the analysis and do not want to recompile +# the binaries. +RECOMPILE = True + +STRIP_VALS = ["none", "debuginfo", "symbols"] +PANIC_VALS = ["unwind", "abort"] +OPT_LEVEL_VALS = [3, "s", "z"] +LTO_VALS = ["off", "thin", "fat"] + + +def config(name, val): + return ["--config", f"profile.release.{name}={val!r}"] + + +sizes = {} + +for (strip, panic, opt, lto) in product( + STRIP_VALS, PANIC_VALS, OPT_LEVEL_VALS, LTO_VALS +): + if RECOMPILE: + cmd = [ + "cargo", + "build", + "--release", + "--features=unix", + *config("strip", strip), + *config("panic", panic), + *config("opt-level", opt), + *config("lto", lto), + ] + print("RUN:", " ".join(cmd)) + res = subprocess.call(cmd) + + shutil.copyfile( + "target/release/coreutils", + "-".join(["coreutils", strip, panic, str(opt), lto]), + ) + print(res) + + sizes[(strip, panic, opt, lto)] = os.path.getsize( + "-".join(["coreutils", strip, panic, str(opt), lto]) + ) + +changes_absolute = defaultdict(list) +changes_percent = defaultdict(list) + + +def with_val_at_idx(val, idx, other): + other = list(other) + other.insert(idx, val) + return tuple(other) + + +def collect_diff(idx, name): + all_params = [STRIP_VALS, PANIC_VALS, OPT_LEVEL_VALS, LTO_VALS] + vals = all_params.pop(idx) + for other in product(*all_params): + baseline = sizes[with_val_at_idx(vals[0], idx, other)] + for val in vals[1:]: + changes = sizes[with_val_at_idx(val, idx, other)] - baseline + changes_absolute[f"{name}={val}"].append(changes) + changes_percent[f"{name}={val}"].append(changes / baseline * 100) + + +collect_diff(0, "strip") +collect_diff(1, "panic") +collect_diff(2, "opt-level") +collect_diff(3, "lto") + + +def analyze(l): + return f"MIN: {float(min(l)):.3}, AVG: {float(sum(l)/len(l)):.3}, MAX: {float(max(l)):.3}" + + +print("Absolute changes") +pprint({k: analyze(v) for k, v in changes_absolute.items()}) +print() +print("Percent changes") +pprint({k: analyze(v) for k, v in changes_percent.items()}) + +print() +print(changes_percent["opt-level=s"]) +print(changes_percent["opt-level=z"])