3

When reading user input using getline(cin, mystrvar), some control keys don't work.

Example:

User input: abc^[[Dd
Text: abd
User input: asc
Read bytes: 7
#0: 97
#1: 98
#2: 99
#3: 27
#4: 91
#5: 68
#6: 100

I typed a, b, c, then left arrow and d. "Text:" apparently writes (cout) the first three characters, then sets the pointer to the left and overwrites the c. "asc" is a simple function that prints the length (mystrvar.size()) and ascii values.

When calling "stty -ctlecho" (system(...)), I am able to use the left arrow key, but it isn't limited to my input (I can overwrite "User input: ") plus the control codes are still being sent to my program.

This does not happen on Windows - I can use the arrow keys (even up/down for history) normally.

What's wrong here?

Edit: I'm mostly using Fedora 15. There doesn't seem to be any difference between lxterminal, terminal, xterm, konsole, gnome-terminal (as terminal) or bash, ksh, tcsh (as shell).

basic6
  • 3,643
  • 3
  • 42
  • 47

5 Answers5

2

How those keys work is a property of your terminal, not of the c++ program. The program gets the input line buffered, and your terminal is responsible for assembling that line.

PlasmaHH
  • 15,673
  • 5
  • 44
  • 57
  • So I have to somehow configure the terminal? How would I do that? – basic6 Sep 09 '11 at 12:40
  • 1
    @basic6 `rlwrap` is a simple tool that enables `readline` functionality. Maybe it's available for your platform. – Luc Danton Sep 09 '11 at 12:54
  • @basic6: Since I don't even know what terminal you are using, I have not the slightest idea. It would have to be an additional question anyways. And possibly not on SO, and possibly only after reading the fine manual of the terminal. – PlasmaHH Sep 09 '11 at 14:09
  • @Luc Danton Yes, it works with rlwrap. But that's not really a solution. I'm working on a program for friends - do I have to tell them "it works on Windows, but if you use the Linux version, you have to install and start some other program first, because the Linux terminal doesn't handle the arrow keys right"...? To me it looks like an error (/misbehavior) in the terminal/shell. – basic6 Sep 09 '11 at 14:21
  • @PlasmaHH I've tried lxterminal, terminal, xterm, konsole, gnome-terminal. They all behave the same. Does this not happen on your machine (assuming you're using Linux)? – basic6 Sep 09 '11 at 14:37
  • 1
    @basic6: I honestly have no idea, since I don't seem to use programs that ask users in this way for input, they all use command line arguments. But I would not be surprised if this is the case, after all, the libreadline exists for a reason. – PlasmaHH Sep 09 '11 at 15:08
  • @basic6 It's not like you will distribute the same executable for both Windows and Linux. It's customary to either distribute separate packages for each OS (where it's not unheard of for the Linux version to provide a script to do all the scaffolding -- which could include using `rlwrap`), or failing that the sources that will build those packages. – Luc Danton Sep 09 '11 at 16:39
1

Although it shouldn't have anything to do with the program (that receives the stdin), I've found a workaround, which requires a slightly different behavior of the program:

#include <readline/readline.h>
#include <readline/history.h>

string blah()
{
    string str;

    cout << "User input (readline): ";

    char *inp_c = readline(""); //Instead of getline()

    str = (const char *)(inp_c); //Because C strings stink

    //...

    return str;
}

This works. I couldn't compile it on Windows though. error: readline/readline.h: No such file or directory Apparently this isn't a standard header, so I have to get/install it first.

If anyone knows a better way, please let me know !

basic6
  • 3,643
  • 3
  • 42
  • 47
0

PlasmaHH is right, how those keys are handled depends on the terminal. But not only : The shell interpreter also plays its part.

So an easy suggestion : use "bash", which handle those keys correctly by default (on my machine at last ;-)

Just launch "bash" and retry.

Offirmo
  • 18,962
  • 12
  • 76
  • 97
  • I've already tried that (and ksh) - doesn't seem to make any difference (I'm mostly using Fedora, if it makes a difference). – basic6 Sep 09 '11 at 14:08
  • It can also depend on how you started the program, when using exec it will stomp over the shell process... chances are that he is using putty to connect to some linux system and everythign is being messed up there – PlasmaHH Sep 09 '11 at 14:11
  • I'm not using PuTTY (or any other remote connection). – basic6 Sep 09 '11 at 14:28
0

OK, another try then.

who do you think is providing you the inline editing feature ? (ability to go back, delete, etc. before pressing enter)

Not your program, of course. So it has to be another program. Which one ? Since it's not the shell, would say the console you are using. It looks like windows cmd prompt provide this feature. Linux console should provide it as well, but it may have been deactivated or a packet is needed.

You say you are not using a remote connection. But what console are you using ? Try "konsole" (kde console) or other variants your system may have.

If there is no program to interpret those special keys, they are just appended into the input buffer...

Offirmo
  • 18,962
  • 12
  • 76
  • 97
  • Yes, I got that. What I don't know is how to tell the terminal to interpret those control keys instead of sending them to my program. And what I don't get is why they're sent to the program anyway. I can use BACKSPACE, but I cannot go back and use DELETE, so inline editing only works partly. It doesn't make sense to me - either send everything to the program or interpret the control keys. And the latter should be default. Please correct me if I'm wrong. Oh and I've tried konsole - same thing. – basic6 Sep 09 '11 at 15:15
  • Well, now that you tried them, I'm out of suggestion... I star the question, interested if someone find the answer... – Offirmo Sep 09 '11 at 15:24
0

Tried rlfe on Pop!OS / Ubuntu. Worked for me.

My solution: https://stackoverflow.com/a/76418140/19585456

dwq
  • 11
  • 3