Something went wrong. Try again.
Go bindings for libghostty-vt. pkg.go.dev/go.mitchellh.com/libghostty
ghostty
Something went wrong. Try again.
go-libghostty mods_string.go
3.8 kB · 133 lines
Go
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134package libghostty
import ( "encoding" "fmt" "strings")
// Compile-time assertions that Mods implements the standard text// marshaling interfaces.var ( _ encoding.TextMarshaler = Mods(0) _ encoding.TextUnmarshaler = (*Mods)(nil))
// Human-friendly string conversion for Mods bitmasks. Each set bit// is rendered using a snake_case name; multiple modifiers are joined// with "+". Parsing accepts "+" or "," as separators and supports// common aliases (cmd/command for super, opt/option for alt, control// for ctrl), matching the upstream Zig source's modifier alias list.
// modBitNames is the canonical ordered list of single-bit Mods values// and their snake_case names. The ordering controls the output of// String, which always renders bits in this fixed order so that// equivalent bitmasks produce identical strings.var modBitNames = []struct { bit Mods name string}{ {ModShift, "shift"}, {ModCtrl, "ctrl"}, {ModAlt, "alt"}, {ModSuper, "super"}, {ModCapsLock, "caps_lock"}, {ModNumLock, "num_lock"}, {ModShiftSide, "shift_side"}, {ModCtrlSide, "ctrl_side"}, {ModAltSide, "alt_side"}, {ModSuperSide, "super_side"},}
// modAliases lists alternate names accepted by FromString. The// canonical name for each modifier is in modBitNames.var modAliases = map[string]Mods{ "cmd": ModSuper, "command": ModSuper, "opt": ModAlt, "option": ModAlt, "control": ModCtrl,}
// String returns a human-friendly representation of the modifier// bitmask: each set bit is rendered as its snake_case name and bits// are joined with "+" in a stable canonical order. Returns "" if no// bits are set.//// Examples://// Mods(0).String() == ""// (ModShift | ModCtrl).String() == "shift+ctrl"// (ModShift | ModShiftSide).String() == "shift+shift_side"func (m Mods) String() string { if m == 0 { return "" } var parts []string for _, e := range modBitNames { if m&e.bit != 0 { parts = append(parts, e.name) } } return strings.Join(parts, "+")}
// MarshalText implements encoding.TextMarshaler. The output is the// same as String() so the type integrates with encoding/json and// other text-based encoders. An empty bitmask marshals to an empty// byte slice (i.e. JSON `""`).func (m Mods) MarshalText() ([]byte, error) { return []byte(m.String()), nil}
// UnmarshalText implements encoding.TextUnmarshaler. It parses a// "+" or "," separated list of modifier names and stores the// resulting bitmask in the receiver. Whitespace around tokens and// empty tokens are ignored. Recognized names are the canonical// snake_case names returned by String plus the upstream aliases// (cmd/command, opt/option, control). An empty input is valid and// produces a zero bitmask. Returns an error if any token is not// recognized.//// The receiver is overwritten, not OR'd into.func (m *Mods) UnmarshalText(text []byte) error { var out Mods if len(text) > 0 { // Normalize "," separators to "+" so we can split once. s := strings.ReplaceAll(string(text), ",", "+") for _, raw := range strings.Split(s, "+") { tok := strings.TrimSpace(raw) if tok == "" { continue } if alias, ok := modAliases[tok]; ok { out |= alias continue } matched := false for _, e := range modBitNames { if e.name == tok { out |= e.bit matched = true break } } if !matched { return fmt.Errorf("libghostty: unknown modifier %q", tok) } } } *m = out return nil}
// ParseMods returns the Mods value parsed from the given "+" or ","// separated list of modifier names. See Mods.UnmarshalText for the// accepted syntax and aliases.func ParseMods(s string) (Mods, error) { var m Mods if err := m.UnmarshalText([]byte(s)); err != nil { return 0, err } return m, nil}