package uiimport ()// Key represents a single keyboard input, typically assembled from a escape// sequence.typeKeystruct {RuneruneModMod}// K constructs a new Key.func ( rune, ...Mod) Key {varModfor , := range { |= }returnKey{, }}// Default is used in the key binding table to indicate a default binding.varDefault = Key{DefaultBindingRune, 0}// Mod represents a modifier key.typeModbyte// Values for Mod.const (// Shift is the shift modifier. It is only applied to special keys (e.g. // Shift-F1). For instance 'A' and '@' which are typically entered with the // shift key pressed, are not considered to be shift-modified.ShiftMod = 1 << iota// Alt is the alt modifier, traditionally known as the meta modifier.AltCtrl)constfunctionKeyOffset = 1000// Special negative runes to represent function keys, used in the Rune field// of the Key struct. This also has a few function names that are aliases for// simple runes. See keyNames below for mapping these values to strings.const (// DefaultBindingRune is a special value to represent a default binding.DefaultBindingRunerune = iota - functionKeyOffsetF1F2F3F4F5F6F7F8F9F10F11F12UpDownRightLeftHomeInsertDeleteEndPageUpPageDown// Function key names that are aliases for their ASCII representation.Tab = '\t'Enter = '\n'Backspace = 0x7f)// keyNames maps runes, whether simple or function, to symbolic key names.varkeyNames = map[rune]string{DefaultBindingRune: "Default",F1: "F1",F2: "F2",F3: "F3",F4: "F4",F5: "F5",F6: "F6",F7: "F7",F8: "F8",F9: "F9",F10: "F10",F11: "F11",F12: "F12",Up: "Up",Down: "Down",Right: "Right",Left: "Left",Home: "Home",Insert: "Insert",Delete: "Delete",End: "End",PageUp: "PageUp",PageDown: "PageDown",Tab: "Tab",Enter: "Enter",Backspace: "Backspace",}func ( Key) () string {return"edit:key"}func ( Key) ( interface{}) bool {return == }func ( Key) () uint32 {returnhash.DJB(uint32(.Rune), uint32(.Mod))}func ( Key) (int) string {return"(edit:key " + parse.Quote(.String()) + ")"}func ( Key) () string {varbytes.Bufferif .Mod&Ctrl != 0 { .WriteString("Ctrl-") }if .Mod&Alt != 0 { .WriteString("Alt-") }if .Mod&Shift != 0 { .WriteString("Shift-") }if , := keyNames[.Rune]; { .WriteString() } else {if .Rune >= 0 { .WriteRune(.Rune) } else {fmt.Fprintf(&, "(bad function key %d)", .Rune) } }return .String()}// modifierByName maps a name to an modifier. It is used for parsing keys where// the modifier string is first turned to lower case, so that all of C, c,// CTRL, Ctrl and ctrl can represent the Ctrl modifier.varmodifierByName = map[string]Mod{"S": Shift, "Shift": Shift,"A": Alt, "Alt": Alt,"M": Alt, "Meta": Alt,"C": Ctrl, "Ctrl": Ctrl,}// ParseKey parses a symbolic key. The syntax is://// Key = { Mod ('+' | '-') } BareKey//// BareKey = FunctionKeyName | SingleRunefunc ( string) (Key, error) {varKey// Parse modifiers.for { := strings.IndexAny(, "+-")if == -1 {break } := [:]if , := modifierByName[]; { .Mod |= = [+1:] } else {returnKey{}, fmt.Errorf("bad modifier: %s", parse.Quote()) } }iflen() == 1 { .Rune = rune([0])if .Rune < 0x20 {if .Mod&Ctrl != 0 {returnKey{}, fmt.Errorf("Ctrl modifier with literal control char: %q", .Rune) }// Convert literal control char to the equivalent canonical form; // e.g., "\e" to Ctrl-'[' and "\t" to Ctrl-I. .Mod |= Ctrl .Rune += 0x40 }// TODO(xiaq): The following assumptions about keys with Ctrl are not // checked with all terminals.if .Mod&Ctrl != 0 {// Keys with Ctrl as one of the modifiers and a single ASCII letter // as the base rune do not distinguish between cases. So we // normalize the base rune to upper case.if'a' <= .Rune && .Rune <= 'z' { .Rune += 'A' - 'a' }// Normalize Ctrl-I to Tab, Ctrl-J to Enter, and Ctrl-? to Backspace.if .Rune == 'I' { .Mod &= ^Ctrl .Rune = Tab } elseif .Rune == 'J' { .Mod &= ^Ctrl .Rune = Enter } }return , nil }// Is this is a symbolic key name, such as `Enter`, we recognize?for , := rangekeyNames {if == { .Rune = return , nil } }returnKey{}, fmt.Errorf("bad key: %s", parse.Quote())}// Keys implements sort.Interface.typeKeys []Keyfunc ( Keys) () int { returnlen() }func ( Keys) (, int) { [], [] = [], [] }func ( Keys) (, int) bool {return [].Mod < [].Mod || ([].Mod == [].Mod && [].Rune < [].Rune)}
The pages are generated with Goldsv0.2.8-preview. (GOOS=darwin GOARCH=arm64)