tantivy-cli 0.24.0

Command line interface for Tantivy, a search engine library.
use std::io::Write;

use clap::{Arg, Command};
mod commands;
pub mod timer;
use self::commands::*;

fn main() {
    env_logger::init();

    let index_arg = Arg::new("index")
        .short('i')
        .long("index")
        .value_name("directory")
        .help("Tantivy index directory filepath")
        .required(true);

    let cli_options = Command::new("Tantivy")
        .subcommand_required(true)
        .arg_required_else_help(true)
        .version(env!("CARGO_PKG_VERSION"))
        .author("Paul Masurel <paul.masurel@gmail.com>")
        .about("Tantivy Search Engine's command line interface.")
        .subcommand(
            Command::new("new")
                .about("Create a new index. The schema will be populated with a simple example schema")
                .arg(index_arg.clone())
        )
        .subcommand(
            Command::new("serve")
                .about("Start a server")
                .arg(index_arg.clone())
                .arg(Arg::new("host")
                    .long("host")
                    .value_name("host")
                    .help("host to listen to")
                    .default_value("localhost")
                    .value_parser(clap::value_parser!(String))
                )
                .arg(Arg::new("port")
                    .short('p')
                    .long("port")
                    .value_name("port")
                    .help("Port")
                    .default_value("3000")
                    .value_parser(clap::value_parser!(usize))
                )
        )
        .subcommand(
            Command::new("index")
                .override_help("Index files")
                .arg(index_arg.clone())
                .arg(Arg::new("file")
                    .short('f')
                    .long("file")
                    .value_name("file")
                    .help("File containing the documents to index."))
                .arg(Arg::new("num_threads")
                    .short('t')
                    .long("num_threads")
                    .value_name("num_threads")
                    .help("Number of indexing threads. By default num cores - 1 will be used")
                    .default_value("1")
                    .value_parser(clap::value_parser!(usize)))
                .arg(Arg::new("memory_size")
                    .short('m')
                    .long("memory_size")
                    .value_name("memory_size")
                    .help("Total memory_size in bytes. It will be split for the different threads.")
                    .default_value("1000000000")
                    .value_parser(clap::value_parser!(usize)))
                .arg(Arg::new("forcemerge")
                    .long("forcemerge")
                    .help("Merge all the segments at the end of indexing"))

                .arg(Arg::new("nomerge")
                    .long("nomerge")
                    .help("Do not merge segments"))
        )
        .subcommand(
            Command::new("search")
                .about("Search an index.")
                .arg(index_arg.clone())
                .arg(Arg::new("query")
                    .short('q')
                    .long("query")
                    .value_name("query")
                    .help("Query")
                    .required(true))
                .arg(Arg::new("aggregation")
                    .short('a')
                    .long("agg")
                    .value_name("agg")
                    .help("Aggregation request as JSON")
                    .required(false))
        )
        .subcommand(
            Command::new("inspect")
                .about("Inspect an index.")
                .arg(index_arg.clone())
        )
        .subcommand(
            Command::new("bench")
                .about("Run a benchmark on your index")
                .arg(index_arg.clone())
                .arg(Arg::new("queries")
                    .short('q')
                    .long("queries")
                    .value_name("queries")
                    .help("File containing queries (one per line) to run in the benchmark.")
                    .required(true))
                .arg(Arg::new("num_repeat")
                    .short('n')
                    .long("num_repeat")
                    .value_name("num_repeat")
                    .help("Number of times to repeat the benchmark.")
                    .default_value("1")
                    .value_parser(clap::value_parser!(usize)))
        )
        .subcommand(
            Command::new("merge")
                .about("Merge all the segments of an index")
                .arg(index_arg.clone())
        )
        .get_matches();

    let (subcommand, options) = cli_options.subcommand().unwrap();
    let run_cli = match subcommand {
        "new" => run_new_cli,
        "index" => run_index_cli,
        "serve" => run_serve_cli,
        "search" => run_search_cli,
        "inspect" => run_inspect_cli,
        "merge" => run_merge_cli,
        "bench" => run_bench_cli,
        _ => panic!("Subcommand {} is unknown", subcommand),
    };

    if let Err(ref e) = run_cli(options) {
        let stderr = &mut std::io::stderr();
        let errmsg = "Error writing to stderr";
        writeln!(stderr, "{}", e).expect(errmsg);
        std::process::exit(1);
    }
}