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

Can't bind Ctrl-Tab to anything #2868

Open
ghost opened this issue Jul 16, 2023 · 5 comments
Open

Can't bind Ctrl-Tab to anything #2868

ghost opened this issue Jul 16, 2023 · 5 comments

Comments

@ghost
Copy link

ghost commented Jul 16, 2023

I was trying to bind Ctrl-Tab to NextTab, but it wasn't working, I tested it a it more and I can't seem to bind Ctrl-Tab to anything. Is this a reserved shortcut? I didn't find anything in the docs about it. I tried Ctrl-Tab CtrlTab and Ctrl-tab and none worked.

Specifications

Commit hash: ceaa143
OS: Manjaro
Terminal: Xfce Terminal

@237dmitry
Copy link

CtrlTab is not in the list of possible keys (keybindings)

Up
Down
Right
Left
UpLeft
UpRight
DownLeft
DownRight
Center
PageUp
PageDown
Home
End
Insert
Delete
Help
Exit
Clear
Cancel
Print
Pause
Backtab
F1
F2
F3
F4
F5
F6
F7
F8
F9
F10
F11
F12
F13
F14
F15
F16
F17
F18
F19
F20
F21
F22
F23
F24
F25
F26
F27
F28
F29
F30
F31
F32
F33
F34
F35
F36
F37
F38
F39
F40
F41
F42
F43
F44
F45
F46
F47
F48
F49
F50
F51
F52
F53
F54
F55
F56
F57
F58
F59
F60
F61
F62
F63
F64
CtrlSpace
Ctrl-a
Ctrl-b
Ctrl-c
Ctrl-d
Ctrl-e
Ctrl-f
Ctrl-g
Ctrl-h
Ctrl-i
Ctrl-j
Ctrl-k
Ctrl-l
Ctrl-m
Ctrl-n
Ctrl-o
Ctrl-p
Ctrl-q
Ctrl-r
Ctrl-s
Ctrl-t
Ctrl-u
Ctrl-v
Ctrl-w
Ctrl-x
Ctrl-y
Ctrl-z
CtrlLeftSq
CtrlBackslash
CtrlRightSq
CtrlCarat
CtrlUnderscore
Backspace
OldBackspace
Tab
Esc
Escape
Enter

@ghost
Copy link
Author

ghost commented Jul 17, 2023

CtrlTab is not in the list of possible keys (keybindings)

Up
...
Tab
Esc
Escape
Enter

Thanks, is Ctrl-Tab not passed through by the terminal? I noticed that it just does the "Tab" action, so does the program only see the Tab key?

Also I noticed another issue, when using "IndetnLine", it only works if the cursor is at the start of a line. Is this intended? Normally indent line would just add a tab at the start of the line, regardless of where the cursor is, but if the cursor is in the middle of the line it just inserts a tab there (correction, OutdentLine works, IndentLine does not, see edit below)

Edit: Just looked at the code in actions.go, and it almost seems like the desired behaviour is reversed for IndentLine. The IndentLine function checks if there is a selection, and if so, it does nothing (returns false), otherwise, it indents. However, if I select something, then it does work, it will indent the whole line, whereas if I don't, it just inserts a tab at the cursor. Outdent Line does the opposite, it un-indents if no selection, and does nothing when something is selected.

Edit2: Previously I was mapping IndentLine to Ctrl-I, I've now mapped it to Ctrl-E and it does work. Is there a bug with Ctrl-I?

Edit3: If I change this:

"CtrlI":          tcell.KeyCtrlI

in bindings.go to this:

"CtrlI":          tcell.KeyCtrlJ,

Then pressing ctrl-j will work, so it seems like the issue is that ctrl-i is not actually getting sent to the program. Pressing Ctrl-I after this change still does the inserting-a-tab thing, and I noticed in my terminal if I press ctrl-i it autocompletes, just like tab does. Is Ctrl-I just a reserved shortcut maybe?

I've testing this in Xfce4-Terminal, Alacritty, Suckless Terminal (st) and Kitty, all show the same behaviour.

I don't think it has anything to do with IndentLine, as if I map Ctrl-i to DeleteLine, it also doesn't work, and still inserts a tab at the cursor.

I think micro uses tcell v2 for handling keyboard inputs, and using this tcell demo program: https://github.com/gdamore/tcell/blob/main/_demos/mouse.go

And pressing various Ctrl+Key combinations, they all show up correctly except 4:

  • Ctrl+M shows up as Return
  • Ctrl+I shows up as Tab
  • Ctrl+Z does show up, but it also backgrounds the program
  • Ctrl+H shows up as Backspace

I'm not sure if there is a way to change this in tcell.

Sorry for all the edits, I can create a separate bug report for this if you like?

@dmaluka
Copy link
Collaborator

dmaluka commented Jul 17, 2023

Thanks, is Ctrl-Tab not passed through by the terminal? I noticed that it just does the "Tab" action, so does the program only see the Tab key?

It is passed by the terminal as Tab, i.e. both Tab and Ctrl-Tab are passed as the same character, so micro is not able to distinguish between them.

Please read the sections Binding raw escape sequences and Final notes in micro's help keybindings. (I was about to write a detailed explanation and a rant on why we love Unix terminal architecture, and then noticed that both are already written in those help sections.)

Summarizing, to make Ctrl-Tab work, you'd need to:

  1. Use a terminal which allows to bind keys to custom escape sequences (afaict Xfce Terminal is not one of such terminals), and configure this terminal to bind Ctrl-Tab to some custom escape sequence.
  2. In micro, bind this escape sequence to the needed action.

This is described in help keybindings in the paragraph However, some terminals do allow you to....

Also, as mentioned in the last paragraph of help keybindings, in micro you can always run the raw command and see which character or escape sequence is received by micro when you press the given key.

Also I noticed another issue, when using "IndetnLine", it only works if the cursor is at the start of a line.

This is because Ctrl-I is treated as Tab, as you've noticed, so IndentLine is not executed at all. But if you're at the start of a line and you insert a tab character, the result is the same as if IndentLine was executed.

However, if I select something, then it does work, it will indent the whole line, whereas if I don't, it just inserts a tab at the cursor.

Hah, that's because Tab by default is bound to Autocomplete|IndentSelection|InsertTab, which means: if possible, autocomplete; if not but possible to indent a selection (i.e. if there is a selection), indent it; if not, simply insert a tab.

Then pressing ctrl-j will work, so it seems like the issue is that ctrl-i is not actually getting sent to the program. Pressing Ctrl-I after this change still does the inserting-a-tab thing, and I noticed in my terminal if I press ctrl-i it autocompletes, just like tab does. Is Ctrl-I just a reserved shortcut maybe?

It is getting sent, but it is getting sent, again, as the same character as Tab, for historical reasons.

This is another reason why we love Unix terminals.

If you're interested why exactly Ctrl-I and Tab are sent the same way: Tab is an ASCII character with code 9 (see man ascii), and "I" is the 9th letter of the alphabet. Ctrl+letter keys are historically sent as a single byte with value equal to the number of the letter in the alphabet, and ASCII characters are sent "as is". So both Tab and Ctrl-I are sent as a byte of value 9.

For the same reason Ctrl-M and Enter work the same way (Enter aka Return character is an ASCII character 13).

Excited?

I'm not sure if there is a way to change this in tcell.

This can be only fixed in the terminal. Tcell, like micro, is on the receiving side, not on the sending side. If the terminal presents two different keys as the same character, micro or tcell can do nothing about that.

Fixing it in the terminal means overriding the standard (annoying) terminal binding for Ctrl-I, Ctrl-M etc with a non-standard one (remember, in micro you also need to correspondingly bind the same non-standard character sequence to the action), and breaking backward compatibility, which is why no one does that by default (or hardly does at all).

@kovidgoyal
Copy link

FYI, nowadays lots of editors support the kitty keyboard protocol, vim, neovim, dte, emacs, kakoune, helix to name some. it fixes all these issues and many more, out of the box. https://sw.kovidgoyal.net/kitty/keyboard-protocol/

@dmaluka
Copy link
Collaborator

dmaluka commented Jul 18, 2023

@kovidgoyal Looks interesting, thanks. (I recall I might have seen this specification a few years ago, when it probably had far fewer implementations than it does now...)

The thread discussing adding support for this protocol to tcell (thus potentially to micro): gdamore/tcell#500

The remaining fundamental issue is how many terminals do support it. Looks like only 3 so far, but let's see how well it proliferates in the future.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants