///usr/bin/env jbang "$0" "$@" ; exit $?
//DEPS org.codejive.miniterm:miniterm${miniterm.ffm:}:${miniterm.version:0.2.0}
//DEPS org.codejive.miniterm:ansiparser:${miniterm.version:0.2.0}
//DEPS org.codejive.miniterm:termcap:${miniterm.version:0.2.0}
package examples;
import java.io.IOException;
import org.codejive.miniterm.Terminal;
import org.codejive.miniterm.ansiparser.AnsiReader;
import org.codejive.miniterm.termcap.TermCaps;
import org.codejive.miniterm.termcap.TermProber;
public class PrintKittyKB {
// ANSI helpers
private static final String CSI = "\033[";
public static void main(String[] args) {
try (Terminal terminal = Terminal.create()) {
terminal.enableRawMode();
// Detect terminal capabilities
TermCaps caps = TermProber.probe(terminal, () -> terminal.read(500));
System.out.println("Terminal capabilities:");
System.out.println(" Kitty keyboard support: " + caps.kittyKeyboard());
System.out.println();
if (!caps.kittyKeyboard()) {
System.out.println("Warning: Terminal does not report Kitty keyboard support.");
System.out.println("Attempting to enable anyway (some terminals support it without reporting).");
System.out.println();
}
// Query terminal for Kitty keyboard protocol support
System.out.println("Querying terminal for Kitty keyboard protocol...");
TermCaps.queryKittyKeyboard(terminal);
// Try to read the response
AnsiReader reader = new AnsiReader(() -> terminal.read(500));
String response = reader.read();
if (response != null && TermCaps.isKittyKeyboardResponse(response)) {
System.out.println("Terminal responded: " + escape(response));
System.out.println("Kitty keyboard protocol is supported!");
} else {
System.out.println("No response received (timeout or not supported).");
}
System.out.println();
// Enable Kitty keyboard protocol with flags:
// 1 = Disambiguate escape codes
// 2 = Report event types (press, release, repeat)
// 4 = Report alternate keys
// Combined: 7 = Full enhancement
int flags = 7;
System.out.println("Enabling Kitty keyboard protocol with flags: " + flags);
System.out.println(" 1 = Disambiguate escape codes");
System.out.println(" 2 = Report event types (press, release, repeat)");
System.out.println(" 4 = Report alternate keys");
System.out.println();
TermCaps.pushKittyKeyboard(terminal, flags);
System.out.println();
System.out.println("Press keys to see enhanced keyboard events.");
System.out.println("Try: letters (plain text), Ctrl+Shift+A, Alt+Shift+B, arrow keys.");
System.out.println("(Press Ctrl+C to exit)");
System.out.println();
System.out.println(String.format("%-40s | %-30s | %s", "Raw", "Hex", "Type"));
System.out.println(String.format("%-40s-+-%-30s-+-%s",
"-".repeat(40), "-".repeat(30), "-".repeat(30)));
try {
String token;
while ((token = reader.read()) != null) {
if (token.isEmpty()) continue;
// Check for Ctrl+C (raw byte 3 or Kitty protocol CSI 99;5u)
if (!token.startsWith("\033") && token.length() == 1 && token.charAt(0) == 3) {
break;
}
// Check for Kitty-encoded Ctrl+C: CSI 99;5u (ESC[99;5u)
if ((CSI + "99;5u").equals(token)) {
break;
}
// Print the event details on a single line
String type = analyzeToken(token);
System.out.println(String.format("%-40s | %-30s | %s",
escape(token), toHex(token), type));
}
} finally {
// Restore original keyboard protocol
TermCaps.popKittyKeyboard(terminal);
}
} catch (IOException e) {
e.printStackTrace();
}
}
private static String analyzeToken(String token) {
if (token == null || token.isEmpty()) {
return "Empty";
}
// Check for Kitty keyboard protocol sequences
// Format: CSI