Repository: atuinsh/atuin (language: rust)

Issue:
In Atuin UI interprets backspace as literal ^h
Opening the Atuin UI and pressing the backspace key writes an h to the input. To delete the previous character I need to press ctrl+backspace.

I assume it has to do with backspace, `^H`, being interpreted as the literal `^H` in some way, hence why ctrl "cancels out" the `^`.

I can reproduce in:
 - [cool-retro-terminal](https://github.com/Swordfish90/cool-retro-term)
 - xterm
 
OS: Arch linux
Atuin version: 18.0.1


Discussion / hints:
I was actually wondering if this behavior of ignoring Ctrl in unprocessed Ctrl+Letter is intended or not.

As for the backspace key, there are variations among terminals about how the backspace key is transmitted in the terminal-to-application stream. Some terminals use <kbd>C-?</kbd> (`\x7F`) and some terminals use <kbd>C-h</kbd> (`\x08`). I'm not sure whether `ratatui`/`crossterm` tries to resolve this variation, but if that is the case, maybe this can be a `ratatui`/`crossterm` issue.

**edit**: `crossterm` is translating the binary representation to the key information. However, <kbd>backspace</kbd> seems to be assumed to be always `^?` [here](https://github.com/crossterm-rs/crossterm/blob/99fe255f33f774f04c09755572503349c915112b/src/event/sys/unix/parse.rs#L560). In the past, I surveyed which terminal sends which code for <kbd>backspace</kbd> and <kbd>C-backspace</kbd> keys as summarized [here](https://github.com/akinomyoga/ble.sh/wiki/Manual-%C2%A73-Key-Binding#user-content-sec-kspecs-ret). Most terminals send `^?` for the backspace key. Terminology, Solaris console, Minix console, RLogin, and Poderosa send `^H` for <kbd>backspace</kbd>.
Thanks for the info :pray:, first of all.
 Wouldn't this be an issue in any TUI using those libs? I've used other programs that use ratatui/crossterm, like [gitui](https://github.com/extrawurst/gitui) and they behave as expected.
I tested atuin in the kitty terminal emulator and it works fine there.
> Wouldn't this be an issue in any TUI using those libs?

I think so.

> like [gitui](https://github.com/extrawurst/gitui) and they behave as expected.

Thanks for the information. `gitui` seems to resolve the issue at the application level [here](https://github.com/extrawurst/gitui/blob/598cc778d4e4d0449cc4383a6870a9e19fc4c64d/src/components/textinput.rs#L277-L288). ...But wait, this code seems to be just introduced last week in https://github.com/extrawurst/gitui/pull/2051 [`6915df9`](https://github.com/extrawurst/gitui/pull/2051/commits/6915df9e7476115270cbabe8abecfe9076d3f400). Maybe this is unrelated.
It's not an easy thing, I think. I temporarily resolved this with:

```rust
XTerm.VT100.Translations: #override\n\
        <KeyPress> BackSpace: string(0x7f)
```

in my `~/.Xresources` for I was too lazy to find some proper way. There is also very good description/explanation about the `backspace` stuff in the [`xterm(1)`](https://www.mankier.com/1/xterm#Resources-Application_Resources) manual and on [TLDP](https://tldp.org/HOWTO/Keyboard-and-Console-HOWTO-5.html).

-----

UPDATE: The solution for XTerm is far from ideal for several reasons (e.g., it breaks recent versions of Vim etc.) so I would beg for fixing it in `atuin`, please. Thank you.

-----

UPDATE 2: It seems that on my system the issue can be resolved with:

```rust
XTerm.VT100.backarrowKey: false
XTerm.VT100.backarrowKeyIsErase: false
```

Perhaps it helps somebody too...
I'm on Kali Linux 2024.1
QTerminal 1.4.0

I have same problem with backspace being replaced by 'h' and Ctrl+h working as backspace
Ideally, this kind of handling should be resolved at the lower level of `crossterm`, but I guess it would be hard to expect `crossterm` to implement it properly. To properly implement it, one needs to prepare a list of the behavior of every terminal, and one also needs to identify the terminal it connects to.

An easy solution is to assign the same feature to all of <kbd>C-h</kbd>, <kbd>C-?</kbd>, <kbd>backspace</kbd>, and <kbd>C-backspace</kbd>, whose representations are mixed with one another depending on the terminal. (**P.S.** This is actually the solution `ble.sh` takes.)


Fix patch:
diff --git a/atuin/src/command/client/search/interactive.rs b/atuin/src/command/client/search/interactive.rs
index f74be6433fa..a12479641eb 100644
--- a/atuin/src/command/client/search/interactive.rs
+++ b/atuin/src/command/client/search/interactive.rs
@@ -379,6 +379,21 @@ impl State {
             KeyCode::Backspace => {
                 self.search.input.back();
             }
+            KeyCode::Char('h' | '?') if ctrl => {
+                // Depending on the terminal, [Backspace] can be transmitted as
+                // \x08 or \x7F.  Also, [Ctrl+Backspace] can be transmitted as
+                // \x08 or \x7F or \x1F.  On the other hand, [Ctrl+h] and
+                // [Ctrl+?] are also transmitted as \x08 or \x7F by the
+                // terminals.
+                //
+                // The crossterm library translates \x08 and \x7F to C-h and
+                // Backspace, respectively.  With the extended keyboard
+                // protocol enabled, crossterm can faithfully translate
+                // [Ctrl+h] and [Ctrl+?] to C-h and C-?.  There is no perfect
+                // solution, but we treat C-h and C-? the same as backspace to
+                // suppress quirks as much as possible.
+                self.search.input.back();
+            }
             KeyCode::Delete if ctrl => self
                 .search
                 .input


Test patch: