use qem::{Document, LiteralSearchQuery, TextPosition, TextSelection, ViewportRequest};
use std::env;
use std::path::PathBuf;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut args = env::args_os().skip(1);
let input = args
.next()
.map(PathBuf::from)
.ok_or("usage: cargo run --example typed_editing -- <input> [output]")?;
let output = args.next().map(PathBuf::from);
let mut doc = Document::open(&input)?;
print_viewport(&doc, "before edits");
let title_selection = doc.clamp_selection(TextSelection::new(
TextPosition::new(0, 0),
TextPosition::new(0, 12),
));
let selected = doc.read_selection(title_selection);
println!(
"selection: {:?}..{:?}, exact={}, text={:?}",
title_selection.anchor(),
title_selection.head(),
selected.is_exact(),
selected.text()
);
let cursor = doc.try_replace_selection(title_selection, "[qem-demo] ")?;
println!("replace cursor: {:?}", cursor);
let cut_selection = doc.clamp_selection(TextSelection::new(
TextPosition::new(2, 0),
TextPosition::new(2, 8),
));
let cut = doc.try_cut_selection(cut_selection)?;
println!(
"cut text: {:?}, changed={}, cursor={:?}",
cut.text(),
cut.edit().changed(),
cut.edit().cursor()
);
let sample =
doc.read_text(doc.text_range_between(TextPosition::new(0, 0), TextPosition::new(2, 32)));
println!("sample after edits: {:?}", sample.text());
let query = LiteralSearchQuery::new("qem").ok_or("empty literal query")?;
if let Some(found) = doc.find_next_query(&query, TextPosition::new(0, 0)) {
println!(
"found literal match: {:?}..{:?} -> {:?}",
found.start(),
found.end(),
doc.read_text(found.range()).text()
);
if let Some(previous) = doc.find_prev_query(&query, found.end()) {
println!(
"previous literal match at-or-before {:?}: {:?}..{:?}",
found.end(),
previous.start(),
previous.end()
);
}
}
print_viewport(&doc, "after edits");
let maintenance = doc.maintenance_status();
if let Some(stats) = maintenance.fragmentation_stats() {
println!(
"fragmentation: pieces={}, avg_bytes={:.1}, small_ratio={:.3}",
stats.piece_count(),
stats.average_piece_bytes(),
stats.fragmentation_ratio()
);
}
println!(
"maintenance action: {}",
maintenance.recommended_action().as_str()
);
if let Some(recommendation) = maintenance.compaction_recommendation() {
println!("compaction recommended: {:?}", recommendation.urgency());
}
let idle_outcome = doc.run_idle_compaction()?;
if idle_outcome.is_compacted() {
println!("idle maintenance compacted the piece table");
} else if idle_outcome.is_forced_pending() {
println!("idle maintenance left a forced compaction pending for save/operator action");
}
if let Some(output) = output {
doc.save_to(&output)?;
println!("saved copy: {}", output.display());
}
Ok(())
}
fn print_viewport(doc: &Document, label: &str) {
println!("{label}:");
let viewport = doc.read_viewport(ViewportRequest::new(0, 5).with_columns(0, 120));
for row in viewport.rows() {
println!(
"{:>8}: [{}] {}",
row.line_number(),
if row.is_exact() { "=" } else { "~" },
row.text()
);
}
}