added a command line flag and associated code to support dumb terminals#99
added a command line flag and associated code to support dumb terminals#99aperotte wants to merge 3 commits intoroot-project:masterfrom
Conversation
|
Thanks, Adler!
I was hoping for textinput to only print that new character. That's what I expected it to do - instead of re-writing the whole line. Can you find out / remind us why it prints everything again and again when adding a single character? If we manage to fix that (i.e. only add that new character) then we don't need a flag at all - everything will work, magically :-) |
|
I'll take a look! However, I do think it's still a better user experience if the input is not echoed at all on these dumb terminals because the input will already be there and would be duplicated if there is any printing on user input. |
|
Let's step back for a second: when I run What do you have? |
|
Yes, unfortunately, term is not the subshell that the other emacs tools are built on (comint, for example). I believe that the tools are built on eshell which is why the interactive cling mode that I am working on for emacs has the noisy echo. |
|
Ah that's great! textinput already checks for |
|
Yes, that makes sense! I'll look into that. |
|
Any news? I really like your patch, and changing this to be |
|
I've been swamped, but I will work on it very soon |
…l type and respond appropriately when type is dumb
|
Sorry for the delay. I pushed an update to my fork that removes the flag and detects when terminal type is "dumb". However, since I had to make the change to TerminalDisplay, this may affect Windows as well (which I didn't test). Since TerminalDisplay has a fTerm field that holds the terminal type as a string, I set it to "win" in the subclass TerminalDisplayWin |
Axel-Naumann
left a comment
There was a problem hiding this comment.
Very nice, thanks a lot! That's much better! I'd still move some of the interfaces around, to make this even more transparent / simple. Could you address the comments?
| } | ||
|
|
||
| InvocationOptions::InvocationOptions(int argc, const char* const* argv) : | ||
|
|
There was a problem hiding this comment.
Can you remove the changes in this file from this PR?
| new UITabCompletion(m_MetaProcessor->getInterpreter()); | ||
| TI.SetCompletion(Completion); | ||
| if (D->GetTERM() && strstr(D->GetTERM(), "dumb")) { | ||
| TI.SetIsDumbTerm(true); |
There was a problem hiding this comment.
Can't this be done inside textinput itself? See below...
| void DisplayInfo(const std::vector<std::string>& Options); | ||
| bool IsTTY() const { return fIsTTY; } | ||
| void SetTERM(const char* TERM) { fTERM = TERM; }; | ||
| const char* GetTERM() { return fTERM; }; |
There was a problem hiding this comment.
These interfaces (nor the data member) should not be needed, see below. Instead we'd need an IsDumb().
| namespace textinput { | ||
| TextInput::TextInput(Reader& reader, Display& display, | ||
| const char* HistFile /* = 0 */): | ||
| fIsDumbTerm(false), |
There was a problem hiding this comment.
Isn't that a property of the TerminalDisplay? I'd prefer to have the interface there.
| TerminalConfigUnix::Get().TIOS()->c_lflag |= ECHOCTL|ECHOKE|ECHOE; | ||
| #endif | ||
| const char* TERM = getenv("TERM"); | ||
| SetTERM(TERM); |
There was a problem hiding this comment.
If TERM is "dumb", the dumb flag on the TerminalDisplay base should be set.
| if (!fIsDumbTerm) { | ||
| // Signal displays that the input got taken. | ||
| std::for_each(fContext->GetDisplays().begin(), fContext->GetDisplays().end(), | ||
| std::mem_fun(&Display::NotifyResetInput)); |
There was a problem hiding this comment.
The if should test the display of the current iteration: if it's dumb, don't call NotifyResetInput..
| if ((*iR)->ReadInput(nRead, in)) { | ||
| ProcessNewInput(in, R); | ||
| DisplayNewInput(R, OldCursorPos); | ||
| if (!IsDumbTerm()) { |
There was a problem hiding this comment.
I'd move that if into DisplayNewInput, testing the dumbness of the display.
| void SetIsDumbTerm(bool isDumbTerm) { fIsDumbTerm = isDumbTerm; } | ||
|
|
||
| protected: | ||
| bool fIsDumbTerm; // whether this is a dumb terminal or not |
There was a problem hiding this comment.
These should all be moved to TerminalDisplay.
|
I will take a look, thanks for the comments. |
|
@Axel-Naumann Hello, I'd love this to get merged. C++ is definitely not my thing but I'm learning it, would you be open to accept the requested changes and possibly give me some advice on the way? |
|
Hi, apologies, but I had to stop working on this pull request because of other responsibilities. I would also love to see this completed if @rilerez or @lazywithclass has some time to work on the refactoring and new conflicts. |
|
Has there been any progress? If not, I'm happy to give it a go, but I might need some pointers to get started. |
|
I think this repo is just a mirror, consider moving your PR here instead: https://github.com/root-project/root/pulls (subdirectory interpreter/cling). Thanks! |
Emacs and other subshells that manage their own input result in noisy output at the cling interpreter. More specifically, entering "int x = 5;" at the prompt will result in the interpreter recursively printing the input adding one character each time - "iinintint int xint x int x =int x = int x = 5int x = 5;int x = 5;". This seems to be because cling cannot control the cursor location in dumb terminals and therefore cannot update the text at the prompt with each new character. It instead prints each update.
Subshells such as those in emacs, manage user input until a newline and then send the input to the underlying process. The output of the underlying process is echoed in the subshell. Because this shell is managed and cling does not have as much control, this results in noisy output.
This pull request adds a command line flag to indicate whether this is a dumb terminal. If so, it does not update the content of the terminal on each input character and does not add a newline (since the dumb terminal would add its own). This is implemented as a member variable of the TextInput class.