[GH-ISSUE #925] [question/bug] Trying to understand key events better #675

Closed
opened 2026-03-04 01:06:57 +03:00 by kerem · 3 comments
Owner

Originally created by @dkyanakiev on GitHub (Nov 30, 2023).
Original GitHub issue: https://github.com/rivo/tview/issues/925

Hi,

Hopefully this is a good format to ask a question..
I've been toying around with the library after some inspiration from a few similar TUIs and wanted to try and build my own.
For the most part it's great and I manage to figure out all the issues I have, except one.

The Enter key.. no matter what I do to configure my inputs .. the moment I hit enter - my app goes back to the main table that is shown when starting the app.

I've tried modifying the keyEnter to return nil, to just print out log messages..
It would do what it's supposed to do + still return me to my Home Screen . Example: https://github.com/dkyanakiev/vaul7y/blob/feature/improvments/view/policy.go#L49
On tables that don't even have the enter key configured in the events the result is the same.

I've tried looking for similar issues but I can't seem to find anything even close to my issue.
Thanks in advance

Originally created by @dkyanakiev on GitHub (Nov 30, 2023). Original GitHub issue: https://github.com/rivo/tview/issues/925 Hi, Hopefully this is a good format to ask a question.. I've been toying around with the library after some inspiration from a few similar TUIs and wanted to try and build my own. For the most part it's great and I manage to figure out all the issues I have, except one. The Enter key.. no matter what I do to configure my inputs .. the moment I hit enter - my app goes back to the main table that is shown when starting the app. I've tried modifying the keyEnter to return nil, to just print out log messages.. It would do what it's supposed to do + still return me to my Home Screen . Example: https://github.com/dkyanakiev/vaul7y/blob/feature/improvments/view/policy.go#L49 On tables that don't even have the enter key configured in the events the result is the same. I've tried looking for similar issues but I can't seem to find anything even close to my issue. Thanks in advance
kerem closed this issue 2026-03-04 01:06:57 +03:00
Author
Owner

@dkyanakiev commented on GitHub (Nov 30, 2023):

I actually found the issue I believe
Adding a code snippet

func (v *View) InputMainCommands(event *tcell.EventKey) *tcell.EventKey {
	if event == nil {
		return event
	}
	switch event.Key() {
	case tcell.KeyEnter:
		v.logger.Debug().Msg("Enter pressed")
		v.Layout.Container.SetFocus(v.state.Elements.TableMain)
		v.logger.Debug().Msgf("Focus set to %s", v.state.Elements.TableMain.GetTitle())
	case tcell.KeyCtrlM:
		v.Watcher.Unsubscribe()
		v.Mounts()
	case tcell.KeyCtrlP:
		v.VPolicy()
		// Needs editing
		// case tcell.KeyCtrlJ:
		// 	v.SecretObject()
	}

	return event
}

I tried to modify the keyEnter to see what's happening exactly and noticed that the IDE is complaining, and then I saw it

duplicate case tcell.KeyCtrlM (constant 13 of type tcell.Key) in expression switch (see details)compiler[DuplicateCase](https://pkg.go.dev/golang.org/x/tools/internal/typesinternal#DuplicateCase)
inputs.go(40, 7): duplicate case tcell.KeyCtrlM (constant 13 of type tcell.Key) in expression switch
inputs.go(36, 7): previous case (this error)

Does this mean there is a bug with what id each key is mapped to?

<!-- gh-comment-id:1833802844 --> @dkyanakiev commented on GitHub (Nov 30, 2023): I actually found the issue I believe Adding a code snippet ``` func (v *View) InputMainCommands(event *tcell.EventKey) *tcell.EventKey { if event == nil { return event } switch event.Key() { case tcell.KeyEnter: v.logger.Debug().Msg("Enter pressed") v.Layout.Container.SetFocus(v.state.Elements.TableMain) v.logger.Debug().Msgf("Focus set to %s", v.state.Elements.TableMain.GetTitle()) case tcell.KeyCtrlM: v.Watcher.Unsubscribe() v.Mounts() case tcell.KeyCtrlP: v.VPolicy() // Needs editing // case tcell.KeyCtrlJ: // v.SecretObject() } return event } ``` I tried to modify the keyEnter to see what's happening exactly and noticed that the IDE is complaining, and then I saw it ``` duplicate case tcell.KeyCtrlM (constant 13 of type tcell.Key) in expression switch (see details)compiler[DuplicateCase](https://pkg.go.dev/golang.org/x/tools/internal/typesinternal#DuplicateCase) inputs.go(40, 7): duplicate case tcell.KeyCtrlM (constant 13 of type tcell.Key) in expression switch inputs.go(36, 7): previous case (this error) ``` Does this mean there is a bug with what id each key is mapped to?
Author
Owner

@moson-mo commented on GitHub (Dec 2, 2023):

Does this mean there is a bug with what id each key is mapped to?

Not really a bug. Some key combos are overlapping.
(e.g. try CTRL+m in the terminal -> Same as if you'd press ENTER😉)

See
github.com/gdamore/tcell@8a50441ee1/key.go (L384)
https://unix.stackexchange.com/questions/533759/why-are-ctrl-m-and-return-keys-the-same-r-char

<!-- gh-comment-id:1837113133 --> @moson-mo commented on GitHub (Dec 2, 2023): > Does this mean there is a bug with what id each key is mapped to? Not really a bug. Some key combos are overlapping. (e.g. try <kbd>CTRL</kbd>+<kbd>m</kbd> in the terminal -> Same as if you'd press <kbd>ENTER</kbd>😉) See https://github.com/gdamore/tcell/blob/8a50441ee1fd29b18a4a7d51e98423a17ec8ef4c/key.go#L384 https://unix.stackexchange.com/questions/533759/why-are-ctrl-m-and-return-keys-the-same-r-char
Author
Owner

@FJuedesOrcl commented on GitHub (Dec 7, 2023):

If you want to "reserve" a key for your own purpose, you must assign "nil" to the event after you have processed your code, like for example

func (v *View) InputMainCommands(event *tcell.EventKey) *tcell.EventKey {
  switch event.Key() {
    case tcell.KeyEnter:
      // do your actions for the ENTER key
      event = nil
    } // END case
    // …
  } // END switch
  return event
} // END InputMainCommands

This way your KeyHandler acts like a filter and disables the default functionality, like for example CTRL-C exits the program. If you want to use the Key-Combination CTRL-C for something else like Copy you need to filter this key-event from the event loop.
It is possible to stack Key-Handlers:
For example you have an InputField in a Form in an Application.
When the InputField has the focus, for every keystroke this happens:

  1. The custom event-handler for the InputField is called.
  2. When the returned event is not nil, the default event-handler InputField is called.
  3. When the returned event is not nil, the custom event-handler for the Form is called.
  4. When the returned event is not nil, the default event-handler for the Form is called.
  5. When the returned event is not nil, the custom event-handler for the Application is called.
  6. When the returned event is not nil, the default event-handler for the Application is called.

Sometimes you can shoot yourself in the foot due to this. I had assigned a functionality to the Plus and the Minus keys in the custom event-handler for my Application and discovered that i wasn't able to enter the plus or minus sign into an InputField anymore.

<!-- gh-comment-id:1846064476 --> @FJuedesOrcl commented on GitHub (Dec 7, 2023): If you want to "reserve" a key for your own purpose, you must assign "nil" to the event after you have processed your code, like for example ``` func (v *View) InputMainCommands(event *tcell.EventKey) *tcell.EventKey { switch event.Key() { case tcell.KeyEnter: // do your actions for the ENTER key event = nil } // END case // … } // END switch return event } // END InputMainCommands ``` This way your KeyHandler acts like a filter and disables the default functionality, like for example CTRL-C exits the program. If you want to use the Key-Combination CTRL-C for something else like Copy you need to filter this key-event from the event loop. It is possible to stack Key-Handlers: For example you have an InputField in a Form in an Application. When the InputField has the focus, for every keystroke this happens: 1. The custom event-handler for the InputField is called. 2. When the returned event is not nil, the default event-handler InputField is called. 3. When the returned event is not nil, the custom event-handler for the Form is called. 4. When the returned event is not nil, the default event-handler for the Form is called. 5. When the returned event is not nil, the custom event-handler for the Application is called. 6. When the returned event is not nil, the default event-handler for the Application is called. Sometimes you can shoot yourself in the foot due to this. I had assigned a functionality to the Plus and the Minus keys in the custom event-handler for my Application and discovered that i wasn't able to enter the plus or minus sign into an InputField anymore.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/tview#675
No description provided.