Go bindings for libghostty-vt.
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 213 lines 7.5 kB view raw
1package libghostty 2 3// Key encoder — encodes key events into terminal escape sequences. 4// Wraps the C APIs from key/encoder.h. 5 6/* 7#include <ghostty/vt.h> 8*/ 9import "C" 10 11import "unsafe" 12 13// KeyEncoder encodes key events into terminal escape sequences, 14// supporting both legacy encoding and the Kitty Keyboard Protocol. 15// It maintains mutable encoding options and is not safe for concurrent 16// use. 17// 18// Basic usage: 19// 1. Create an encoder with NewKeyEncoder. 20// 2. Configure options with SetOpt* methods or SetOptFromTerminal. 21// 3. Create key events, encode them with Encode, and free them. 22// 4. Free the encoder with Close when done. 23// 24// C: GhosttyKeyEncoder 25type KeyEncoder struct { 26 ptr C.GhosttyKeyEncoder 27} 28 29// KittyKeyFlags is a bitmask of Kitty keyboard protocol flags. 30// C: GhosttyKittyKeyFlags 31type KittyKeyFlags uint8 32 33const ( 34 // KittyKeyDisabled disables the Kitty keyboard protocol (all flags off). 35 KittyKeyDisabled KittyKeyFlags = C.GHOSTTY_KITTY_KEY_DISABLED 36 37 // KittyKeyDisambiguate enables disambiguating escape codes. 38 KittyKeyDisambiguate KittyKeyFlags = C.GHOSTTY_KITTY_KEY_DISAMBIGUATE 39 40 // KittyKeyReportEvents enables reporting key press and release events. 41 KittyKeyReportEvents KittyKeyFlags = C.GHOSTTY_KITTY_KEY_REPORT_EVENTS 42 43 // KittyKeyReportAlternates enables reporting alternate key codes. 44 KittyKeyReportAlternates KittyKeyFlags = C.GHOSTTY_KITTY_KEY_REPORT_ALTERNATES 45 46 // KittyKeyReportAll reports all key events including those normally 47 // handled by the terminal. 48 KittyKeyReportAll KittyKeyFlags = C.GHOSTTY_KITTY_KEY_REPORT_ALL 49 50 // KittyKeyReportAssociated reports associated text with key events. 51 KittyKeyReportAssociated KittyKeyFlags = C.GHOSTTY_KITTY_KEY_REPORT_ASSOCIATED 52 53 // KittyKeyAll enables all Kitty keyboard protocol flags. 54 KittyKeyAll KittyKeyFlags = C.GHOSTTY_KITTY_KEY_ALL 55) 56 57// OptionAsAlt determines whether the macOS "option" key is treated as 58// "alt". 59// 60// C: GhosttyOptionAsAlt 61type OptionAsAlt int 62 63const ( 64 // OptionAsAltFalse means the option key is not treated as alt. 65 OptionAsAltFalse OptionAsAlt = C.GHOSTTY_OPTION_AS_ALT_FALSE 66 67 // OptionAsAltTrue means the option key is treated as alt. 68 OptionAsAltTrue OptionAsAlt = C.GHOSTTY_OPTION_AS_ALT_TRUE 69 70 // OptionAsAltLeft means only the left option key is treated as alt. 71 OptionAsAltLeft OptionAsAlt = C.GHOSTTY_OPTION_AS_ALT_LEFT 72 73 // OptionAsAltRight means only the right option key is treated as alt. 74 OptionAsAltRight OptionAsAlt = C.GHOSTTY_OPTION_AS_ALT_RIGHT 75) 76 77// KeyEncoderOption identifies an encoder configuration option for use 78// with SetOpt. 79// 80// C: GhosttyKeyEncoderOption 81type KeyEncoderOption int 82 83const ( 84 // KeyEncoderOptCursorKeyApplication sets DEC mode 1: cursor key 85 // application mode (value: bool). 86 KeyEncoderOptCursorKeyApplication KeyEncoderOption = C.GHOSTTY_KEY_ENCODER_OPT_CURSOR_KEY_APPLICATION 87 88 // KeyEncoderOptKeypadKeyApplication sets DEC mode 66: keypad key 89 // application mode (value: bool). 90 KeyEncoderOptKeypadKeyApplication KeyEncoderOption = C.GHOSTTY_KEY_ENCODER_OPT_KEYPAD_KEY_APPLICATION 91 92 // KeyEncoderOptIgnoreKeypadWithNumlock sets DEC mode 1035: ignore 93 // keypad with numlock (value: bool). 94 KeyEncoderOptIgnoreKeypadWithNumlock KeyEncoderOption = C.GHOSTTY_KEY_ENCODER_OPT_IGNORE_KEYPAD_WITH_NUMLOCK 95 96 // KeyEncoderOptAltEscPrefix sets DEC mode 1036: alt sends escape 97 // prefix (value: bool). 98 KeyEncoderOptAltEscPrefix KeyEncoderOption = C.GHOSTTY_KEY_ENCODER_OPT_ALT_ESC_PREFIX 99 100 // KeyEncoderOptModifyOtherKeysState2 sets xterm modifyOtherKeys 101 // mode 2 (value: bool). 102 KeyEncoderOptModifyOtherKeysState2 KeyEncoderOption = C.GHOSTTY_KEY_ENCODER_OPT_MODIFY_OTHER_KEYS_STATE_2 103 104 // KeyEncoderOptKittyFlags sets Kitty keyboard protocol flags 105 // (value: KittyKeyFlags bitmask). 106 KeyEncoderOptKittyFlags KeyEncoderOption = C.GHOSTTY_KEY_ENCODER_OPT_KITTY_FLAGS 107 108 // KeyEncoderOptMacOSOptionAsAlt sets the macOS option-as-alt 109 // setting (value: OptionAsAlt). 110 KeyEncoderOptMacOSOptionAsAlt KeyEncoderOption = C.GHOSTTY_KEY_ENCODER_OPT_MACOS_OPTION_AS_ALT 111 112 // KeyEncoderOptBackarrowKeyMode sets backarrow key mode (value: bool). 113 // When false (default), backspace emits 0x7f; when true, 0x08. 114 KeyEncoderOptBackarrowKeyMode KeyEncoderOption = C.GHOSTTY_KEY_ENCODER_OPT_BACKARROW_KEY_MODE 115) 116 117// NewKeyEncoder creates a new key encoder with default options. 118// The encoder must be freed with Close when no longer needed. 119func NewKeyEncoder() (*KeyEncoder, error) { 120 var ptr C.GhosttyKeyEncoder 121 if err := resultError(C.ghostty_key_encoder_new(nil, &ptr)); err != nil { 122 return nil, err 123 } 124 return &KeyEncoder{ptr: ptr}, nil 125} 126 127// Close frees the underlying key encoder handle. After this call, 128// the encoder must not be used. 129func (enc *KeyEncoder) Close() { 130 C.ghostty_key_encoder_free(enc.ptr) 131} 132 133// SetOptBool sets a boolean encoder option. Use this for options 134// that accept a bool value (most encoder options). 135func (enc *KeyEncoder) SetOptBool(opt KeyEncoderOption, val bool) { 136 v := C.bool(val) 137 C.ghostty_key_encoder_setopt(enc.ptr, C.GhosttyKeyEncoderOption(opt), unsafe.Pointer(&v)) 138} 139 140// SetOptKittyFlags sets the Kitty keyboard protocol flags on the 141// encoder. 142func (enc *KeyEncoder) SetOptKittyFlags(flags KittyKeyFlags) { 143 v := C.GhosttyKittyKeyFlags(flags) 144 C.ghostty_key_encoder_setopt(enc.ptr, C.GHOSTTY_KEY_ENCODER_OPT_KITTY_FLAGS, unsafe.Pointer(&v)) 145} 146 147// SetOptOptionAsAlt sets the macOS option-as-alt behavior on the 148// encoder. 149func (enc *KeyEncoder) SetOptOptionAsAlt(val OptionAsAlt) { 150 v := C.GhosttyOptionAsAlt(val) 151 C.ghostty_key_encoder_setopt(enc.ptr, C.GHOSTTY_KEY_ENCODER_OPT_MACOS_OPTION_AS_ALT, unsafe.Pointer(&v)) 152} 153 154// SetOptFromTerminal reads the terminal's current modes and flags and 155// applies them to the encoder's options. This sets cursor key 156// application mode, keypad mode, alt escape prefix, modifyOtherKeys 157// state, and Kitty keyboard protocol flags from the terminal state. 158// 159// Note that the macOS option-as-alt option cannot be determined from 160// terminal state and is reset to OptionAsAltFalse by this call. Use 161// SetOptOptionAsAlt afterward if needed. The caller must serialize 162// access to both the encoder and the terminal during this call. 163func (enc *KeyEncoder) SetOptFromTerminal(t *Terminal) { 164 C.ghostty_key_encoder_setopt_from_terminal(enc.ptr, t.ptr) 165} 166 167// Encode encodes a key event into a terminal escape sequence and 168// returns the result as a byte slice. Not all key events produce 169// output (e.g. unmodified modifier keys); in that case, a nil slice 170// and nil error are returned. 171func (enc *KeyEncoder) Encode(event *KeyEvent) ([]byte, error) { 172 // Most escape sequences fit in 128 bytes. Try with a stack buffer 173 // first; fall back to a larger heap allocation if needed. 174 var buf [128]byte 175 var outLen C.size_t 176 result := C.ghostty_key_encoder_encode( 177 enc.ptr, 178 event.ptr, 179 (*C.char)(unsafe.Pointer(&buf[0])), 180 C.size_t(len(buf)), 181 &outLen, 182 ) 183 184 if result == C.GHOSTTY_SUCCESS { 185 if outLen == 0 { 186 return nil, nil 187 } 188 out := make([]byte, outLen) 189 copy(out, buf[:outLen]) 190 return out, nil 191 } 192 193 if result == C.GHOSTTY_OUT_OF_SPACE { 194 // outLen contains the required buffer size. 195 dynBuf := make([]byte, outLen) 196 var written C.size_t 197 if err := resultError(C.ghostty_key_encoder_encode( 198 enc.ptr, 199 event.ptr, 200 (*C.char)(unsafe.Pointer(&dynBuf[0])), 201 outLen, 202 &written, 203 )); err != nil { 204 return nil, err 205 } 206 if written == 0 { 207 return nil, nil 208 } 209 return dynBuf[:written], nil 210 } 211 212 return nil, &Error{Result: Result(result)} 213}