package ui

import (
	
	
	

	
	
)

// Key represents a single keyboard input, typically assembled from a escape
// sequence.
type Key struct {
	Rune rune
	Mod  Mod
}

// K constructs a new Key.
func ( rune,  ...Mod) Key {
	var  Mod
	for ,  := range  {
		 |= 
	}
	return Key{, }
}

// Default is used in the key binding table to indicate a default binding.
var Default = Key{DefaultBindingRune, 0}

// Mod represents a modifier key.
type Mod byte

// 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.
	Shift Mod = 1 << iota
	// Alt is the alt modifier, traditionally known as the meta modifier.
	Alt
	Ctrl
)

const functionKeyOffset = 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.
	DefaultBindingRune rune = iota - functionKeyOffset

	F1
	F2
	F3
	F4
	F5
	F6
	F7
	F8
	F9
	F10
	F11
	F12

	Up
	Down
	Right
	Left

	Home
	Insert
	Delete
	End
	PageUp
	PageDown

	// 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.
var keyNames = 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 {
	return hash.DJB(uint32(.Rune), uint32(.Mod))
}

func ( Key) (int) string {
	return "(edit:key " + parse.Quote(.String()) + ")"
}

func ( Key) () string {
	var  bytes.Buffer

	if .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.
var modifierByName = 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 | SingleRune
func ( string) (Key, error) {
	var  Key

	// Parse modifiers.
	for {
		 := strings.IndexAny(, "+-")
		if  == -1 {
			break
		}
		 := [:]
		if ,  := modifierByName[];  {
			.Mod |= 
			 = [+1:]
		} else {
			return Key{}, fmt.Errorf("bad modifier: %s", parse.Quote())
		}
	}

	if len() == 1 {
		.Rune = rune([0])
		if .Rune < 0x20 {
			if .Mod&Ctrl != 0 {
				return Key{}, 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
			} else if .Rune == 'J' {
				.Mod &= ^Ctrl
				.Rune = Enter
			}
		}
		return , nil
	}

	// Is this is a symbolic key name, such as `Enter`, we recognize?
	for ,  := range keyNames {
		if  ==  {
			.Rune = 
			return , nil
		}
	}

	return Key{}, fmt.Errorf("bad key: %s", parse.Quote())
}

// Keys implements sort.Interface.
type Keys []Key

func ( Keys) () int      { return len() }
func ( Keys) (,  int) { [], [] = [], [] }
func ( Keys) (,  int) bool {
	return [].Mod < [].Mod ||
		([].Mod == [].Mod && [].Rune < [].Rune)
}