Skip to main content

max / audiofiles

copy: drop em-dashes from user-facing strings Mechanical AI-tell sweep across UI copy, hover text, log lines, and error messages: em-dash replaced with a colon, semicolon, or split sentence per context. No behavior change.
Author: Max Johnson <me@maxj.phd> · 2026-07-24 22:01 UTC
Commit: da5faf90268ed82bfee8e5995ff1562e58b74e8e
Parent: 239f0ce
13 files changed, +22 insertions, -23 deletions
@@ -286,7 +286,7 @@ pub(crate) fn trial_button_label(trial: Option<&super::license::TrialState>) ->
286 286 "Trial expired".to_string()
287 287 }
288 288 }
289 - None => "Start free trial — 30 days, no card".to_string(),
289 + None => "Start free trial: 30 days, no card".to_string(),
290 290 }
291 291 }
292 292
@@ -375,7 +375,7 @@ mod tests {
375 375 fn label_no_trial_offers_start() {
376 376 assert_eq!(
377 377 trial_button_label(None),
378 - "Start free trial — 30 days, no card"
378 + "Start free trial: 30 days, no card"
379 379 );
380 380 }
381 381
@@ -228,7 +228,7 @@ fn main() {
228 228 let test_suite_dir = samples_dir.join("test-suite");
229 229
230 230 println!("╔══════════════════════════════════════════════════════════════╗");
231 - println!("║ Audiofiles Analysis Pipeline — Benchmark Report ║");
231 + println!("║ Audiofiles Analysis Pipeline: Benchmark Report ║");
232 232 println!("╚══════════════════════════════════════════════════════════════╝");
233 233 println!();
234 234
@@ -181,7 +181,7 @@ impl BrowserState {
181 181 self.classifier.last_apply = Some(n);
182 182 self.refresh_selected_tags();
183 183 self.status = format!(
184 - "Rules applied — {n} sample{} updated",
184 + "Rules applied: {n} sample{} updated",
185 185 if n == 1 { "" } else { "s" }
186 186 );
187 187 }
@@ -426,8 +426,7 @@ impl BrowserState {
426 426 pub fn classifier_clear_head(&mut self) {
427 427 match self.backend.clear_classifier_head() {
428 428 Ok(()) => {
429 - self.status =
430 - "Trained model cleared — using nearest-neighbor matching.".to_string();
429 + self.status = "Trained model cleared. Using nearest-neighbor matching.".to_string();
431 430 }
432 431 Err(e) => self.status = format!("Could not clear model: {e}"),
433 432 }
@@ -606,7 +606,7 @@ impl BrowserState {
606 606 ForgeOvershoot::Trimmed { peak_dbfs, gain_db } => {
607 607 let _ = write!(
608 608 msg,
609 - " — true-peak +{:.1} dB trimmed {:.1} dB to avoid clipping",
609 + "; true-peak +{:.1} dB trimmed {:.1} dB to avoid clipping",
610 610 peak_dbfs,
611 611 gain_db.abs()
612 612 );
@@ -614,7 +614,7 @@ impl BrowserState {
614 614 ForgeOvershoot::Flagged { peak_dbfs } => {
615 615 let _ = write!(
616 616 msg,
617 - " — warning: true-peak +{peak_dbfs:.1} dB will clip (enable auto-trim in Settings to prevent)"
617 + "; warning: true-peak +{peak_dbfs:.1} dB will clip (enable auto-trim in Settings to prevent)"
618 618 );
619 619 }
620 620 }
@@ -620,7 +620,7 @@ fn draw_trained_head(ui: &mut egui::Ui, state: &mut BrowserState) {
620 620 ui.label(
621 621 egui::RichText::new(
622 622 "For large libraries, distil your tagged samples into a compact model so \
623 - auto-tagging runs much faster. Optional — auto-tagging works without it.",
623 + auto-tagging runs much faster. Optional: auto-tagging works without it.",
624 624 )
625 625 .small()
626 626 .color(theme::content_muted()),
@@ -630,7 +630,7 @@ fn draw_trained_head(ui: &mut egui::Ui, state: &mut BrowserState) {
630 630 Some(info) => {
631 631 ui.label(
632 632 egui::RichText::new(format!(
633 - "Active — {} tag{} from {} sample{}.",
633 + "Active: {} tag{} from {} sample{}.",
634 634 info.class_count,
635 635 if info.class_count == 1 { "" } else { "s" },
636 636 info.exemplar_count,
@@ -646,7 +646,7 @@ fn draw_trained_head(ui: &mut egui::Ui, state: &mut BrowserState) {
646 646 format!("No model yet. With {n} tagged samples, training is recommended.")
647 647 } else {
648 648 format!(
649 - "No model — nearest-neighbor matching is fast enough at {n} tagged \
649 + "No model: nearest-neighbor matching is fast enough at {n} tagged \
650 650 sample{}.",
651 651 if n == 1 { "" } else { "s" }
652 652 )
@@ -443,7 +443,7 @@ pub fn draw_file_list(
443 443 state.status = format!("Downloading {}...", node.node.name);
444 444 } else {
445 445 state.status =
446 - "Sync not ready — open the Sync panel first".to_string();
446 + "Sync not ready: open the Sync panel first".to_string();
447 447 }
448 448 }
449 449 } else {
@@ -573,7 +573,7 @@ fn draw_name_column(
573 573 #[cfg(any(target_os = "macos", target_os = "windows"))]
574 574 let resp = if !node.cloud_only && node.node.node_type == NodeType::Sample {
575 575 let hover = if os_drag_blocked {
576 - "Just dragged — ready again in a moment."
576 + "Just dragged. Ready again in a moment."
577 577 } else {
578 578 "Drag to Finder or DAW"
579 579 };
@@ -307,7 +307,7 @@ fn draw_batch_section(ui: &mut egui::Ui, state: &mut BrowserState) {
307 307 /// only; not built for this launch.
308 308 fn draw_foreshadow_section(ui: &mut egui::Ui) {
309 309 ui.label(
310 - egui::RichText::new("Plugin processing (CLAP/VST) — coming soon")
310 + egui::RichText::new("Plugin processing (CLAP/VST): coming soon")
311 311 .small()
312 312 .italics()
313 313 .color(theme::content_muted()),
@@ -204,7 +204,7 @@ pub fn draw_import_progress(ui: &mut egui::Ui, state: &mut BrowserState) {
204 204 if walking {
205 205 let _ = ui
206 206 .add_enabled(false, egui::Button::new("Cancel"))
207 - .on_disabled_hover_text("Scanning — cancel available once the scan completes.");
207 + .on_disabled_hover_text("Scanning. Cancel available once the scan completes.");
208 208 } else if ui.button("Cancel").clicked() {
209 209 state.cancel_import();
210 210 }
@@ -644,7 +644,7 @@ fn draw_adsr_controls(ui: &mut egui::Ui, state: &mut BrowserState) {
644 644 .small()
645 645 .color(theme::content_secondary()),
646 646 )
647 - .on_hover_text("Attack — time to reach full volume after key press");
647 + .on_hover_text("Attack: time to reach full volume after key press");
648 648 let slider = egui::Slider::new(&mut envelope.attack, 0.001..=5.0)
649 649 .logarithmic(true)
650 650 .max_decimals(3)
@@ -656,7 +656,7 @@ fn draw_adsr_controls(ui: &mut egui::Ui, state: &mut BrowserState) {
656 656 .small()
657 657 .color(theme::content_secondary()),
658 658 )
659 - .on_hover_text("Decay — time to fall from peak to sustain level");
659 + .on_hover_text("Decay: time to fall from peak to sustain level");
660 660 let slider = egui::Slider::new(&mut envelope.decay, 0.001..=5.0)
661 661 .logarithmic(true)
662 662 .max_decimals(3)
@@ -670,7 +670,7 @@ fn draw_adsr_controls(ui: &mut egui::Ui, state: &mut BrowserState) {
670 670 .small()
671 671 .color(theme::content_secondary()),
672 672 )
673 - .on_hover_text("Sustain — held volume level while the key is down (0 to 1)");
673 + .on_hover_text("Sustain: held volume level while the key is down (0 to 1)");
674 674 let slider = egui::Slider::new(&mut envelope.sustain, 0.0..=1.0).max_decimals(2);
675 675 ui.add(slider);
676 676
@@ -679,7 +679,7 @@ fn draw_adsr_controls(ui: &mut egui::Ui, state: &mut BrowserState) {
679 679 .small()
680 680 .color(theme::content_secondary()),
681 681 )
682 - .on_hover_text("Release — time to fade to silence after key release");
682 + .on_hover_text("Release: time to fade to silence after key release");
683 683 let slider = egui::Slider::new(&mut envelope.release, 0.001..=10.0)
684 684 .logarithmic(true)
685 685 .max_decimals(3)
@@ -252,7 +252,7 @@ fn draw_subscription_section(ui: &mut egui::Ui, state: &mut BrowserState, sync:
252 252 ui.add_space(theme::space::XS);
253 253 ui.label(
254 254 egui::RichText::new(
255 - "Annual is 2 months free — fewer Stripe fees, so we pass the savings on.",
255 + "Annual is 2 months free, so fewer Stripe fees, and we pass the savings on.",
256 256 )
257 257 .weak()
258 258 .size(11.0),
@@ -779,7 +779,7 @@ pub fn relocate_sample(
779 779
780 780 if computed != hash {
781 781 return Err(CoreError::Internal(format!(
782 - "hash mismatch: expected {hash}, got {computed} — this is a different file"
782 + "hash mismatch: expected {hash}, got {computed}; this is a different file"
783 783 )));
784 784 }
785 785
@@ -56,7 +56,7 @@ impl PluginRegistry {
56 56 // User plugin overrides another user plugin, warn about ambiguity
57 57 tracing::warn!(
58 58 device = %plugin.profile.name,
59 - "Multiple user plugins with the same device name — last one loaded wins"
59 + "Multiple user plugins with the same device name; last one loaded wins"
60 60 );
61 61 }
62 62 }
@@ -95,7 +95,7 @@ pub fn start_auth(client: &SyncKitClient) -> Result<AuthSession> {
95 95 // Parse GET /callback?code=X&state=Y or GET /?code=X&state=Y
96 96 if let Some((code, cb_state)) = parse_oauth_callback(&request) {
97 97 if cb_state != thread_expected_state {
98 - tracing::warn!("OAuth callback state mismatch — rejecting");
98 + tracing::warn!("OAuth callback state mismatch: rejecting");
99 99 let body = "<html><body><h1>Authentication failed</h1><p>CSRF state mismatch. Please try again.</p></body></html>";
100 100 let response = format!(
101 101 "HTTP/1.1 403 Forbidden\r\nContent-Type: text/html\r\nContent-Length: {}\r\nAccess-Control-Allow-Origin: *\r\nConnection: close\r\n\r\n{}",