Skip to content

Implement a User-Facing Command-Line Interface (CLI) #11

@TKanX

Description

@TKanX

Description:

This task marks a major milestone in transitioning cheq from a core library into a fully-featured, standalone scientific tool. The goal is to build a robust and user-friendly Command-Line Interface (CLI) that exposes the power of the cheq solver directly to end-users. This will enable researchers, students, and engineers to perform charge equilibration calculations without writing any code, using standard molecular file formats.

The implementation will be a new binary target within the cheq crate, located at src/bin/cheq/. It will leverage the clap crate for state-of-the-art argument parsing and will be architected with a strong separation of concerns: CLI definition, I/O handling, and application logic will reside in distinct modules to ensure maintainability and testability. The CLI will support reading from both files and standard input (stdin), making it highly composable within Unix-style pipelines.

Tasks:

  • Phase 1: Project Scaffolding and CLI Definition

    • Add clap (version = "4.0", with derive feature) and thiserror to the [dependencies] section in Cargo.toml.
    • Create a new binary target in Cargo.toml: [[bin]] name = "cheq" path = "src/bin/main.rs".
    • Create the new directory structure: src/bin/.
    • Create src/bin/cli.rs and define the Cli struct using clap::Parser.
    • Arguments & Options:
      • input: A required positional argument for the input XYZ file path. Special value - should be supported for stdin.
      • -o, --output <PATH>: An optional path for the output file. Defaults to stdout.
      • -f, --format <FORMAT>: An optional output format. Define an enum OutputFormat with variants Pretty, Xyz, Csv, Json. Default to Pretty.
      • -c, --charge <CHARGE>: An optional total system charge, defaulting to 0.0.
      • -p, --params <PATH>: An optional path to a custom TOML parameter file.
      • -v, --verbose: An optional flag to enable verbose logging (e.g., SCF iterations).
      • Advanced solver options: --tolerance, --max-iter, --lambda for fine-tuning.
  • Phase 2: I/O Module Implementation (io.rs)

    • Create src/bin/io.rs.
    • XYZ Parsing: Implement read_xyz(input_path: &str) -> Result<(Vec<cheq::Atom>, String), CliError>.
      • Handle both file paths and the special - stdin identifier.
      • Correctly parse element symbols or atomic numbers from the first column.
      • Store and return the comment line for later use.
      • Return a custom CliError::XyzParse on format errors.
    • Output Formatting: Implement a dispatcher write_results(...).
      • write_pretty_table: Formats a human-readable, aligned table to a Write buffer.
      • write_xyz_charged: Writes a standard XYZ file with an additional fifth column for the computed charges.
      • write_csv: Writes a CSV file with header atomic_number,x,y,z,charge.
      • write_json: Serializes the results (including input atoms and computed charges) into a structured JSON format.
  • Phase 3: Application Logic and Error Handling (main.rs, error.rs)

    • Create src/bin/main.rs as the application entry point.
    • Create src/bin/error.rs and define a top-level CliError enum using thiserror.
      • It should wrap std::io::Error, cheq::CheqError, and define custom variants like XyzParse.
    • In main.rs, implement the main workflow:
      • Parse arguments using Cli::parse().
      • Load parameters: Use the custom file if provided via --params, otherwise use cheq::get_default_parameters().
      • Configure SolverOptions from CLI arguments.
      • Instantiate QEqSolver.
      • Call io::read_xyz to get atom data.
      • Call solver.solve(...) with the atoms and total charge.
      • On success, call io::write_results.
      • On failure, gracefully print the CliError to stderr and exit with a non-zero status code.
  • Phase 4: End-to-End and Integration Testing

    • Create integration tests (e.g., in a tests/cli.rs file).
    • Test Basic Invocation: Run cheq tests/data/water.xyz and check for a successful exit code and valid-looking pretty-table output.
    • Test Output Formats:
      • Run cheq tests/data/co.xyz --format xyz and verify the output is a valid 3-line XYZ file with a fifth column.
      • Run cheq tests/data/methane.xyz --format csv --charge 1 and parse the CSV output to confirm headers and correct total charge sum.
    • Test I/O Redirection:
      • Test piping: cat tests/data/water.xyz | cheq -.
      • Test output to file: cheq tests/data/water.xyz -o temp.txt, then read and verify temp.txt.
    • Test Custom Parameters: Create a minimal custom params.toml, run cheq ... --params custom.toml, and assert the calculated charges differ from the default run.
    • Test Error Scenarios:
      • Run cheq non_existent_file.xyz and check for a file-not-found error message and non-zero exit code.
      • Run cheq malformed.xyz and check for a parsing error.
      • Run cheq molecule_with_unknown_element.xyz and check that the ParameterNotFound error from the core library is propagated correctly.

Metadata

Metadata

Assignees

Labels

Projects

Status

Done

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions