Skip to content

Commit fc89769

Browse files
committed
infocmp -C: translate %{K}%+%c and escape %+ arguments standalone
Add the %{K}%+%c -> %+<char K> translation (add-constant, emit-as-char), mirroring the existing %'X'%+%c form. The %+ argument is a single character escaped on its own (caret for control bytes), independent of the surrounding value's caret-vs-octal length test -- so adm20's cm renders \E=%i%r%+^_%+^_ (caret), matching ncurses, while a literal control byte like a980's al \016 still follows the length heuristic (octal). Termcap (-C) content 66.3% -> 66.4%. terminfo -1 100%; tests green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CbiPgWC3PHKmrTNvZzXcWQ
1 parent b74bdf6 commit fc89769

1 file changed

Lines changed: 31 additions & 1 deletion

File tree

crates/ncurses-tools/src/bin/infocmp.rs

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -379,9 +379,39 @@ fn try_translate(v: &[u8], islong: bool) -> Option<String> {
379379
r_pending = false;
380380
}
381381
out.push_str("%+");
382-
tc_escape_byte(&mut out, v[i + 2], islong, v.get(i + 3).copied());
382+
// The `%+` argument is a standalone char, escaped on its own (caret for control),
383+
// independent of the surrounding value's caret-vs-octal length.
384+
tc_escape_byte(&mut out, v[i + 2], false, None);
383385
i += 8;
384386
}
387+
// `%{K}%+%c` (add a constant, emit as char) -> termcap `%+<char K>`, like the `%'X'`
388+
// form above (e.g. `%p1%{24}%+%c` -> `%+^X`).
389+
Some(b'{') => {
390+
let mut j = i + 2;
391+
while j < v.len() && v[j].is_ascii_digit() {
392+
j += 1;
393+
}
394+
if j == i + 2
395+
|| v.get(j) != Some(&b'}')
396+
|| v.get(j + 1) != Some(&b'%')
397+
|| v.get(j + 2) != Some(&b'+')
398+
|| v.get(j + 3) != Some(&b'%')
399+
|| v.get(j + 4) != Some(&b'c')
400+
{
401+
return None;
402+
}
403+
let k: u32 = std::str::from_utf8(&v[i + 2..j]).ok()?.parse().ok()?;
404+
if k > 0xff {
405+
return None;
406+
}
407+
if r_pending {
408+
out.push_str("%r");
409+
r_pending = false;
410+
}
411+
out.push_str("%+");
412+
tc_escape_byte(&mut out, k as u8, false, None);
413+
i = j + 5;
414+
}
385415
// A `%` before a byte that is not a real parameter operator is copied through verbatim,
386416
// exactly as _nc_infotocap does -- it only fails (marking the cap `..`) on genuine
387417
// parameter/conditional/stack ops. This covers exotic printer codes (`%z`, `%y`, `%}`,

0 commit comments

Comments
 (0)