Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(v2) Use KeyMsg/MouseMsg interfaces #1111

Merged
merged 7 commits into from
Aug 30, 2024
Merged

(v2) Use KeyMsg/MouseMsg interfaces #1111

merged 7 commits into from
Aug 30, 2024

Conversation

aymanbagabas
Copy link
Member

@aymanbagabas aymanbagabas commented Aug 22, 2024

This replaces KeyMsg and MouseMsg with interfaces that catch their respective types. For example, both KeyPressMsg and KeyReleaseMsg implement KeyMsg. Same goes for MouseClickMsg, MouseReleaseMsg, etc, they all implement MouseMsg. This makes it possible to switch on the interface type to catch all events of the same input message type.

New API:

// KeyMsg represents a key event. This can be either a key press or a key
// release event.
type KeyMsg interface {
	fmt.Stringer

	// Key returns the underlying key event.
	Key() Key
}


// Key represents a Key press or release event. It contains information about
// the Key pressed, like the runes, the type of Key, and the modifiers pressed.
// There are a couple general patterns you could use to check for key presses
// or releases:
//
//	// Switch on the string representation of the key (shorter)
//	switch msg := msg.(type) {
//	case KeyPressMsg:
//	    switch msg.String() {
//	    case "enter":
//	        fmt.Println("you pressed enter!")
//	    case "a":
//	        fmt.Println("you pressed a!")
//	    }
//	}
//
//	// Switch on the key type (more foolproof)
//	switch msg := msg.(type) {
//	case KeyMsg:
//	    // catch both KeyPressMsg and KeyReleaseMsg
//	    switch key := msg.Key(); key.Code {
//	    case KeyEnter:
//	        fmt.Println("you pressed enter!")
//	    default:
//	        switch key.Text {
//	        case "a":
//	            fmt.Println("you pressed a!")
//	        }
//	    }
//	}
//
// Note that [Key.Text] will be empty for special keys like [KeyEnter],
// [KeyTab], and for keys that don't represent printable characters like key
// combos with modifier keys. In other words, [Key.Text] is populated only for
// keys that represent printable characters shifted or unshifted (like 'a',
// 'A', '1', '!', etc.).
type Key struct {
	// Text contains the actual characters received. This usually the same as
	// [Key.Code]. When [Key.Text] is non-empty, it indicates that the key
	// pressed represents printable character(s).
	Text string

	// Mod represents modifier keys, like [ModCtrl], [ModAlt], and so on.
	Mod KeyMod

	// Code represents the key pressed. This is usually a special key like
	// [KeyTab], [KeyEnter], [KeyF1], or a printable character like 'a'.
	Code rune

	// ShiftedCode is the actual, shifted key pressed by the user. For example,
	// if the user presses shift+a, or caps lock is on, [Key.ShiftedCode] will
	// be 'A' and [Key.Code] will be 'a'.
	//
	// In the case of non-latin keyboards, like Arabic, [Key.ShiftedCode] is the
	// unshifted key on the keyboard.
	//
	// This is only available with the Kitty Keyboard Protocol or the Windows
	// Console API.
	ShiftedCode rune

	// BaseCode is the key pressed according to the standard PC-101 key layout.
	// On international keyboards, this is the key that would be pressed if the
	// keyboard was set to US PC-101 layout.
	//
	// For example, if the user presses 'q' on a French AZERTY keyboard,
	// [Key.BaseCode] will be 'q'.
	//
	// This is only available with the Kitty Keyboard Protocol or the Windows
	// Console API.
	BaseCode rune

	// IsRepeat indicates whether the key is being held down and sending events
	// repeatedly.
	//
	// This is only available with the Kitty Keyboard Protocol or the Windows
	// Console API.
	IsRepeat bool
}


// MouseMsg represents a mouse message. This is a generic mouse message that
// can represent any kind of mouse event.
type MouseMsg interface {
	fmt.Stringer

	// Mouse returns the underlying mouse event.
	Mouse() Mouse
}

// Mouse represents a Mouse message. Use [MouseMsg] to represent all mouse
// messages.
//
// The X and Y coordinates are zero-based, with (0,0) being the upper left
// corner of the terminal.
//
//	// Catch all mouse events
//	switch msg := msg.(type) {
//	case MouseMsg:
//	    m := msg.Mouse()
//	    fmt.Println("Mouse event:", m.X, m.Y, m)
//	}
//
//	// Only catch mouse click events
//	switch msg := msg.(type) {
//	case MouseClickMsg:
//	    fmt.Println("Mouse click event:", msg.X, msg.Y, msg)
//	}
type Mouse struct {
	X, Y   int
	Button MouseButton
	Mod    KeyMod
}

TODO: update examples (in a separate PR)

@bashbunni bashbunni added this to the v2.0.0 milestone Aug 23, 2024
@aymanbagabas aymanbagabas changed the base branch from master to v2-exp August 23, 2024 19:16
@aymanbagabas aymanbagabas marked this pull request as ready for review August 23, 2024 20:27
Copy link
Member

@bashbunni bashbunni left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are some magic numbers in there too that the linter picked up. The changes look good though, stoked to have kitty keyboard support 🚀

key.go Outdated Show resolved Hide resolved
key.go Show resolved Hide resolved
key.go Outdated Show resolved Hide resolved
key.go Outdated Show resolved Hide resolved
key.go Outdated Show resolved Hide resolved
key.go Outdated Show resolved Hide resolved
key.go Outdated Show resolved Hide resolved
key.go Outdated Show resolved Hide resolved
key.go Outdated Show resolved Hide resolved
key.go Outdated Show resolved Hide resolved
@aymanbagabas aymanbagabas force-pushed the v2-msg-interface branch 2 times, most recently from e1d239f to 45f800f Compare August 28, 2024 14:23
@aymanbagabas aymanbagabas mentioned this pull request Aug 28, 2024
8 tasks
@aymanbagabas aymanbagabas force-pushed the v2-msg-interface branch 2 times, most recently from 361ec9a to 5508557 Compare August 28, 2024 15:44
@aymanbagabas aymanbagabas merged commit 8a75439 into v2-exp Aug 30, 2024
24 of 30 checks passed
@aymanbagabas aymanbagabas deleted the v2-msg-interface branch August 30, 2024 15:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants