1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
|
package ansi
import (
"strconv"
"strings"
)
// StatusReport represents a terminal status report.
type StatusReport interface {
// StatusReport returns the status report identifier.
StatusReport() int
}
// ANSIStatusReport represents an ANSI terminal status report.
type ANSIStatusReport int //nolint:revive
// StatusReport returns the status report identifier.
func (s ANSIStatusReport) StatusReport() int {
return int(s)
}
// DECStatusReport represents a DEC terminal status report.
type DECStatusReport int
// StatusReport returns the status report identifier.
func (s DECStatusReport) StatusReport() int {
return int(s)
}
// DeviceStatusReport (DSR) is a control sequence that reports the terminal's
// status.
// The terminal responds with a DSR sequence.
//
// CSI Ps n
// CSI ? Ps n
//
// If one of the statuses is a [DECStatus], the sequence will use the DEC
// format.
//
// See also https://vt100.net/docs/vt510-rm/DSR.html
func DeviceStatusReport(statues ...StatusReport) string {
var dec bool
list := make([]string, len(statues))
seq := "\x1b["
for i, status := range statues {
list[i] = strconv.Itoa(status.StatusReport())
switch status.(type) {
case DECStatusReport:
dec = true
}
}
if dec {
seq += "?"
}
return seq + strings.Join(list, ";") + "n"
}
// DSR is an alias for [DeviceStatusReport].
func DSR(status StatusReport) string {
return DeviceStatusReport(status)
}
// RequestCursorPositionReport is an escape sequence that requests the current
// cursor position.
//
// CSI 6 n
//
// The terminal will report the cursor position as a CSI sequence in the
// following format:
//
// CSI Pl ; Pc R
//
// Where Pl is the line number and Pc is the column number.
// See: https://vt100.net/docs/vt510-rm/CPR.html
const RequestCursorPositionReport = "\x1b[6n"
// RequestExtendedCursorPositionReport (DECXCPR) is a sequence for requesting
// the cursor position report including the current page number.
//
// CSI ? 6 n
//
// The terminal will report the cursor position as a CSI sequence in the
// following format:
//
// CSI ? Pl ; Pc ; Pp R
//
// Where Pl is the line number, Pc is the column number, and Pp is the page
// number.
// See: https://vt100.net/docs/vt510-rm/DECXCPR.html
const RequestExtendedCursorPositionReport = "\x1b[?6n"
// RequestLightDarkReport is a control sequence that requests the terminal to
// report its operating system light/dark color preference. Supported terminals
// should respond with a [LightDarkReport] sequence as follows:
//
// CSI ? 997 ; 1 n for dark mode
// CSI ? 997 ; 2 n for light mode
//
// See: https://contour-terminal.org/vt-extensions/color-palette-update-notifications/
const RequestLightDarkReport = "\x1b[?996n"
// CursorPositionReport (CPR) is a control sequence that reports the cursor's
// position.
//
// CSI Pl ; Pc R
//
// Where Pl is the line number and Pc is the column number.
//
// See also https://vt100.net/docs/vt510-rm/CPR.html
func CursorPositionReport(line, column int) string {
if line < 1 {
line = 1
}
if column < 1 {
column = 1
}
return "\x1b[" + strconv.Itoa(line) + ";" + strconv.Itoa(column) + "R"
}
// CPR is an alias for [CursorPositionReport].
func CPR(line, column int) string {
return CursorPositionReport(line, column)
}
// ExtendedCursorPositionReport (DECXCPR) is a control sequence that reports the
// cursor's position along with the page number (optional).
//
// CSI ? Pl ; Pc R
// CSI ? Pl ; Pc ; Pv R
//
// Where Pl is the line number, Pc is the column number, and Pv is the page
// number.
//
// If the page number is zero or negative, the returned sequence won't include
// the page number.
//
// See also https://vt100.net/docs/vt510-rm/DECXCPR.html
func ExtendedCursorPositionReport(line, column, page int) string {
if line < 1 {
line = 1
}
if column < 1 {
column = 1
}
if page < 1 {
return "\x1b[?" + strconv.Itoa(line) + ";" + strconv.Itoa(column) + "R"
}
return "\x1b[?" + strconv.Itoa(line) + ";" + strconv.Itoa(column) + ";" + strconv.Itoa(page) + "R"
}
// DECXCPR is an alias for [ExtendedCursorPositionReport].
func DECXCPR(line, column, page int) string {
return ExtendedCursorPositionReport(line, column, page)
}
// LightDarkReport is a control sequence that reports the terminal's operating
// system light/dark color preference.
//
// CSI ? 997 ; 1 n for dark mode
// CSI ? 997 ; 2 n for light mode
//
// See: https://contour-terminal.org/vt-extensions/color-palette-update-notifications/
func LightDarkReport(dark bool) string {
if dark {
return "\x1b[?997;1n"
}
return "\x1b[?997;2n"
}
|