diff --git a/apps/figcraft-cli/src/files.rs b/apps/figcraft-cli/src/files.rs index 29f8cd5b6..c4cc7d5f6 100644 --- a/apps/figcraft-cli/src/files.rs +++ b/apps/figcraft-cli/src/files.rs @@ -199,26 +199,33 @@ pub fn info(path: &str, as_json: bool) -> CliResult { return Ok(ExitCode::SUCCESS); } for n in ¬es { - eprintln!("note: {n}"); + eprintln!("note: {}", n.escape_debug()); } println!( "{} — {} ({} nodes, {} styles, {} variables, {} images)", - path, - doc.name, + path.escape_debug(), + doc.name.escape_debug(), doc.node_count(), doc.styles.len(), doc.variables.variables.len(), doc.images.len() ); for p in &pages { - println!("page {} \"{}\": {} nodes, {} top-level", p["id"], p["name"].as_str().unwrap_or(""), p["nodes"], p["topLevel"]); + println!("page {} \"{}\": {} nodes, {} top-level", p["id"], p["name"].as_str().unwrap_or("").escape_debug(), p["nodes"], p["topLevel"]); for f in p["frames"].as_array().into_iter().flatten() { - println!(" {} {} \"{}\" {}×{}", f["id"], f["type"].as_str().unwrap_or(""), f["name"].as_str().unwrap_or(""), f["width"], f["height"]); + println!( + " {} {} \"{}\" {}×{}", + f["id"], + f["type"].as_str().unwrap_or(""), + f["name"].as_str().unwrap_or("").escape_debug(), + f["width"], + f["height"] + ); } } for m in &missing { let layers = if m.layers == 1 { "text layer" } else { "text layers" }; - println!("missing font \"{}\": {} {layers} (drawn in a fallback font)", m.family, m.layers); + println!("missing font \"{}\": {} {layers} (drawn in a fallback font)", m.family.escape_debug(), m.layers); } Ok(ExitCode::SUCCESS) } @@ -438,7 +445,8 @@ pub fn run_script(script: &str, input: Option<&str>, out: Option<&str>) -> CliRe let cmd = steps.get(failed_at).map_or("", |step| step.command.as_str()); let i = failed_at; println!("{}", json!({"step": i, "command": cmd, "ok": false, "error": e.to_string(), "rolledBack": true})); - eprintln!("error: step {i} ({cmd}) failed: {e}"); + // Plugin-supplied text: escape terminal controls and line breaks. + eprintln!("error: step {i} ({}) failed: {}", cmd.escape_debug(), e.to_string().escape_debug()); eprintln!("the script's document changes were rolled back"); return Ok(ExitCode::from(1)); } diff --git a/crates/ui-egui/src/app/commands.rs b/crates/ui-egui/src/app/commands.rs index 93762e579..960291382 100644 --- a/crates/ui-egui/src/app/commands.rs +++ b/crates/ui-egui/src/app/commands.rs @@ -55,7 +55,8 @@ impl FigApp { /// Show command `id`'s error. pub(crate) fn failed(&mut self, id: &str, e: &figcraft_engine::EngineError) { let msg = e.to_string(); - log::warn!("{id}: {msg}"); + // A plugin's failure text may carry CR or terminal controls: log it escaped. + log::warn!("{id}: {}", msg.escape_debug()); self.show_error(msg); }