Kitty Graphics Protocol in OCaml
terminal graphics ocaml
1(*--------------------------------------------------------------------------- 2 Copyright (c) 2025 Anil Madhavapeddy. All rights reserved. 3 SPDX-License-Identifier: ISC 4 ---------------------------------------------------------------------------*) 5 6(** Tmux Passthrough Support 7 8 Support for passing graphics protocol escape sequences through tmux 9 to the underlying terminal emulator. 10 11 {2 Background} 12 13 When running inside tmux, graphics protocol escape sequences need to be 14 wrapped in a DCS (Device Control String) passthrough sequence so that 15 tmux forwards them to the actual terminal (kitty, wezterm, ghostty, etc.) 16 rather than interpreting them itself. 17 18 The passthrough format is: 19 - Prefix: [ESC P tmux ;] 20 - Content with all ESC characters doubled 21 - Suffix: [ESC] 22 23 {2 Requirements} 24 25 For tmux passthrough to work: 26 - tmux version 3.3 or later 27 - [allow-passthrough] must be enabled in tmux.conf: 28 {v set -g allow-passthrough on v} 29 30 {2 Usage} 31 32 {[ 33 if Kgp.Tmux.is_active () then 34 let wrapped = Kgp.Tmux.wrap graphics_command in 35 print_string wrapped 36 else 37 print_string graphics_command 38 ]} *) 39 40val is_active : unit -> bool 41(** Detect if we are running inside tmux. 42 43 Returns [true] if the [TMUX] environment variable is set, 44 indicating the process is running inside a tmux session. *) 45 46val wrap : string -> string 47(** Wrap an escape sequence for tmux passthrough. 48 49 Takes a graphics protocol escape sequence and wraps it in the 50 tmux DCS passthrough format: 51 - Adds [ESC P tmux ;] prefix 52 - Doubles all ESC characters in the content 53 - Adds [ESC] suffix 54 55 If not running inside tmux, returns the input unchanged. *) 56 57val wrap_always : string -> string 58(** Wrap an escape sequence for tmux passthrough unconditionally. 59 60 Like {!wrap} but always applies the wrapping, regardless of 61 whether we are inside tmux. Useful when you want to pre-generate 62 tmux-compatible output. *) 63 64val write_wrapped : Buffer.t -> string -> unit 65(** Write a wrapped escape sequence directly to a buffer. 66 67 More efficient than {!wrap_always} when building output in a buffer, 68 as it avoids allocating an intermediate string. *)