forked from Crockan/MercuryToolbox
chore(release): prepare public source release
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
[package]
|
||||
name = "hitsnip"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
license.workspace = true
|
||||
authors.workspace = true
|
||||
readme.workspace = true
|
||||
publish.workspace = true
|
||||
description = "Merge search hits into compact, AI-friendly snippets."
|
||||
keywords.workspace = true
|
||||
categories.workspace = true
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
codeindex = { path = "../codeindex" }
|
||||
common = { path = "../common", default-features = false }
|
||||
lexopt.workspace = true
|
||||
serde.workspace = true
|
||||
serde_json.workspace = true
|
||||
|
||||
[dev-dependencies]
|
||||
assert_cmd.workspace = true
|
||||
predicates.workspace = true
|
||||
tempfile.workspace = true
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,5 @@
|
||||
//! Binary entry point for `hitsnip`.
|
||||
|
||||
fn main() {
|
||||
std::process::exit(hitsnip::main_entry());
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
//! Integration tests for the `hitsnip` command.
|
||||
|
||||
use std::fs;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::str;
|
||||
|
||||
use assert_cmd::Command;
|
||||
use predicates::prelude::*;
|
||||
use tempfile::{TempDir, tempdir};
|
||||
|
||||
const SAMPLE_RS: &str = "reading/sample.rs";
|
||||
|
||||
fn cargo_command() -> Command {
|
||||
Command::cargo_bin("hitsnip").expect("binary")
|
||||
}
|
||||
|
||||
fn workspace_root() -> PathBuf {
|
||||
PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
||||
.join("..")
|
||||
.join("..")
|
||||
.canonicalize()
|
||||
.expect("workspace root")
|
||||
}
|
||||
|
||||
fn fixture(path: &str) -> PathBuf {
|
||||
workspace_root().join("fixtures").join(path)
|
||||
}
|
||||
|
||||
fn temp_file(name: &str, contents: impl AsRef<[u8]>) -> (TempDir, PathBuf) {
|
||||
let dir = tempdir().expect("tempdir");
|
||||
let path = dir.path().join(name);
|
||||
fs::write(&path, contents).expect("fixture");
|
||||
(dir, path)
|
||||
}
|
||||
|
||||
fn pwsh_command(script: impl AsRef<str>) -> Command {
|
||||
let mut command = Command::new("pwsh");
|
||||
command
|
||||
.arg("-NoProfile")
|
||||
.arg("-Command")
|
||||
.arg(script.as_ref());
|
||||
command
|
||||
}
|
||||
|
||||
fn ps_quote(value: impl std::fmt::Display) -> String {
|
||||
format!("'{}'", value.to_string().replace('\'', "''"))
|
||||
}
|
||||
|
||||
fn relative_to_workspace(path: &Path) -> String {
|
||||
path.strip_prefix(workspace_root())
|
||||
.expect("path within workspace")
|
||||
.display()
|
||||
.to_string()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn merges_rg_hits_into_compact_text_snippets() {
|
||||
let mut command = cargo_command();
|
||||
command
|
||||
.current_dir(workspace_root())
|
||||
.arg("--context")
|
||||
.arg("1")
|
||||
.arg("--max-gap")
|
||||
.arg("1")
|
||||
.write_stdin(std::fs::read_to_string(fixture("hits/rg-output.txt")).expect("fixture"))
|
||||
.assert()
|
||||
.success()
|
||||
.stdout(predicate::str::contains(
|
||||
"path=fixtures\\reading\\sample.rs lines=17:27 hits=3",
|
||||
))
|
||||
.stdout(predicate::str::contains("hit_lines=18,22,26"))
|
||||
.stdout(predicate::str::contains("18: pub fn run"))
|
||||
.stdout(predicate::str::contains(
|
||||
"path=fixtures\\reading\\sample.cs lines=8:10 hits=1",
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn accepts_explicit_hit_arguments_and_emits_json() {
|
||||
let sample = fixture(SAMPLE_RS);
|
||||
let hit_a = format!("{}:18", sample.display());
|
||||
let hit_b = format!("{}:26:9", sample.display());
|
||||
|
||||
let mut command = cargo_command();
|
||||
command
|
||||
.arg("--json")
|
||||
.arg("--context")
|
||||
.arg("0")
|
||||
.arg("--max-gap")
|
||||
.arg("10")
|
||||
.arg(&hit_a)
|
||||
.arg(&hit_b)
|
||||
.assert()
|
||||
.success()
|
||||
.stdout(predicate::str::contains("\"start_line\":18"))
|
||||
.stdout(predicate::str::contains("\"end_line\":26"))
|
||||
.stdout(predicate::str::contains("\"hit_count\":2"))
|
||||
.stdout(predicate::str::contains("\"hit_lines\":[18,26]"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn supports_powershell_pipeline_for_hit_lines() {
|
||||
let binary = assert_cmd::cargo::cargo_bin("hitsnip");
|
||||
let sample = relative_to_workspace(&fixture(SAMPLE_RS));
|
||||
let script = format!(
|
||||
"{},{} | & {} --context 0 --max-gap 0 --json",
|
||||
ps_quote(format!("{sample}:18")),
|
||||
ps_quote(format!("{sample}:26")),
|
||||
ps_quote(binary.display())
|
||||
);
|
||||
|
||||
let mut command = pwsh_command(script);
|
||||
command
|
||||
.current_dir(workspace_root())
|
||||
.assert()
|
||||
.success()
|
||||
.stdout(predicate::str::contains(
|
||||
"\"path\":\"fixtures\\\\reading\\\\sample.rs\"",
|
||||
))
|
||||
.stdout(predicate::str::contains("\"selected\"").not());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn utf8_bom_source_file_does_not_pollute_first_snippet_line() {
|
||||
let (_dir, source) = temp_file("bom.rs", "\u{feff}fn main() {}\nfn helper() {}\n");
|
||||
|
||||
let mut command = cargo_command();
|
||||
command
|
||||
.arg("--context")
|
||||
.arg("0")
|
||||
.arg(format!("{}:1", source.display()))
|
||||
.assert()
|
||||
.success()
|
||||
.stdout(predicate::str::contains("1: fn main() {}"))
|
||||
.stdout(predicate::str::contains("\u{feff}fn main").not());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalid_utf8_source_file_reports_read_error() {
|
||||
let (_dir, source) = temp_file("invalid-utf8.rs", [0x66, 0x80, 0x0A]);
|
||||
|
||||
let mut command = cargo_command();
|
||||
command
|
||||
.arg("--context")
|
||||
.arg("0")
|
||||
.arg(format!("{}:1", source.display()))
|
||||
.assert()
|
||||
.failure()
|
||||
.stderr(predicate::str::contains("failed to read"))
|
||||
.stderr(predicate::str::contains("invalid-utf8.rs"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn help_includes_rg_and_powershell_examples() {
|
||||
let mut command = cargo_command();
|
||||
command
|
||||
.arg("--help")
|
||||
.assert()
|
||||
.success()
|
||||
.stdout(predicate::str::contains("rg -nH"))
|
||||
.stdout(predicate::str::contains("ConvertFrom-Json"))
|
||||
.stdout(predicate::str::contains("--max-gap"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn help_puts_rg_nh_before_pathless_rg_examples() {
|
||||
let mut command = cargo_command();
|
||||
let output = command
|
||||
.arg("--help")
|
||||
.assert()
|
||||
.success()
|
||||
.get_output()
|
||||
.stdout
|
||||
.clone();
|
||||
let help = str::from_utf8(&output).expect("help is utf8");
|
||||
let rg_nh = help.find("rg -nH").expect("rg -nH example");
|
||||
let rg_n_pathless = help
|
||||
.find("rg -n \"Mode::\"")
|
||||
.expect("pathless rg -n example");
|
||||
assert!(
|
||||
rg_nh < rg_n_pathless,
|
||||
"the safest rg -nH example should appear before pathless rg -n"
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user