summaryrefslogtreecommitdiffstats
path: root/sq/build.rs
blob: d6dcf539d8eccf8c565006eda9e6c4fcfd255acd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
use std::env;
use std::fs;
use std::io::Write;
use std::path::Path;
use clap_complete::Shell;
use anyhow::Result;

pub mod sq_cli {
    include!("src/sq_cli/mod.rs");
}

fn main() {
    println!("cargo:rerun-if-changed=build.rs");

    // Generate subplot tests.
    subplot_build::codegen(Path::new("sq.subplot"))
        .expect("failed to generate code with Subplot");

    let mut sq = sq_cli::build();

    // Dump help output of all commands and subcommands, for inclusion in docs
    dump_help(sq.clone()).unwrap();

    // Generate shell completions
    let outdir = match env::var_os("CARGO_TARGET_DIR") {
        None => return,
        Some(outdir) => outdir,
    };

    fs::create_dir_all(&outdir).unwrap();

    for shell in &[Shell::Bash, Shell::Fish, Shell::Zsh, Shell::PowerShell,
                   Shell::Elvish] {
        let path = clap_complete::generate_to(*shell, &mut sq, "sq", &outdir).unwrap();
        println!("cargo:warning=completion file is generated: {:?}", path);
    };
}

fn dump_help(mut cmd: clap::Command) -> Result<()> {
    cmd = cmd.term_width(80);
    cmd.build();
    let mut sink = fs::File::create("sq-usage.md")?;

    writeln!(sink, "A command-line frontend for Sequoia.")?;
    writeln!(sink)?;
    writeln!(sink, "# Usage")?;
    dump_help_inner(&mut sink, &mut cmd, "##")
}

fn dump_help_inner(
    sink: &mut dyn Write,
    cmd: &mut clap::Command,
    heading: &str,
) -> Result<()> {
    writeln!(sink)?;

    let mut buffer = Vec::new();
    let _ = cmd.write_long_help(&mut buffer);
    let help = std::str::from_utf8(buffer.as_slice())?;

    writeln!(sink, "```text")?;
    for line in help.trim_end().split('\n').skip(1) {
        if line.is_empty() {
            writeln!(sink)?;
        } else {
            writeln!(sink, "{}", line.trim_end())?;
        }
    }
    writeln!(sink, "```")?;

    // Recurse.
    for subcommand in cmd
        .get_subcommands_mut()
        .filter(|sc| sc.get_name() != "help")
    {
        writeln!(sink)?;
        let heading_name = subcommand
            // cmd.build() in dump_help makes sure every subcommand has a display_name
            .get_display_name()
            .unwrap()
            .replace('-', " ");
        writeln!(sink, "{} Subcommand {}", heading, heading_name)?;

        dump_help_inner(sink, subcommand, &format!("{}#", heading))?;
    }

    Ok(())
}