Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
[#15](https://github.com/dschafer/qsolve/issues/15) to be solved without
forcing chains.

### Changed

- Make `--file-type=auto` use recognized image extensions to select image parsing.

### Fixed

- Give out-of-range values passed to bitset-backed sets consistent, descriptive panics.
- Return an error instead of panicking when an image contains no detectable grid.
- Calculate queen and X pixel ratios against the inspected image area.
- Preserve spaces used as blank markers at the edges of partial-state grids.
- Restore the terminal cursor when animation exits with an error.

## [1.0.0] - 2025-04-23

Expand Down
15 changes: 12 additions & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,9 +157,9 @@ fn queens_file_from_path(path_args: &PathCli) -> Result<QueensFile> {
#[cfg(feature = "image")]
FileType::Image => QueensFile::try_from_image_file(&path_args.path),
#[cfg(feature = "image")]
FileType::Auto => QueensFile::try_from_text_file(&path_args.path)
.or_else(|_| QueensFile::try_from_image_file(&path_args.path)),
#[cfg(not(feature = "image"))]
FileType::Auto if image::ImageFormat::from_path(&path_args.path).is_ok() => {
QueensFile::try_from_image_file(&path_args.path)
}
FileType::Auto => QueensFile::try_from_text_file(&path_args.path),
}?;
if path_args.clear {
Expand Down Expand Up @@ -245,6 +245,14 @@ fn print_animated_iter_item(
Ok(())
}

struct CursorGuard;

impl Drop for CursorGuard {
fn drop(&mut self) {
let _ = execute!(std::io::stdout(), Show);
}
}

/// Top-level entry point for the animate subcommand.
fn animate(
path_args: &PathCli,
Expand All @@ -262,6 +270,7 @@ fn animate(
let _ = execute!(std::io::stdout(), Show);
std::process::exit(130);
})?;
let _cursor_guard = CursorGuard;
execute!(stdout, Hide)?;

for solve_iter_item in solve_iter(solve_state, solve_args.strategy, &heuristics) {
Expand Down
19 changes: 19 additions & 0 deletions tests/command_line_runs.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use assert_cmd::prelude::*;
#[cfg(feature = "image")]
use std::fs;
use std::process::Command;

#[test]
Expand Down Expand Up @@ -44,6 +46,23 @@ fn print_fails_on_bad_file() -> Result<(), Box<dyn std::error::Error>> {
Ok(())
}

#[cfg(feature = "image")]
#[test]
fn auto_uses_extension_to_select_parser() -> Result<(), Box<dyn std::error::Error>> {
let path = std::env::temp_dir().join(format!(
"qsolve-text-with-image-extension-{}.png",
std::process::id()
));
fs::write(&path, "wwww\nwkkk\nrrrr\nbbbb")?;

let mut cmd = Command::cargo_bin("qsolve")?;
cmd.arg("print").arg(&path);
cmd.assert().failure();

fs::remove_file(path)?;
Ok(())
}

#[cfg(feature = "image")]
#[test]
fn print_accepts_image_file_type() -> Result<(), Box<dyn std::error::Error>> {
Expand Down
Loading