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

added a command line flag and associated code to support dumb terminals #99

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

aperotte
Copy link

@aperotte aperotte commented Feb 5, 2017

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.

@Axel-Naumann
Copy link
Member

Thanks, Adler!

therefore cannot update the text at the prompt with each new character. It instead prints each update.

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 :-)

@aperotte
Copy link
Author

aperotte commented Feb 8, 2017

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.

@Axel-Naumann
Copy link
Member

Let's step back for a second: when I run M-x term in emacs and then start cling, the prompt without your patch seems to work fine. I have this as TERM:

$ echo $TERM
eterm-color

What do you have?

@aperotte
Copy link
Author

aperotte commented Feb 9, 2017

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.

Welcome to the Emacs shell

~ $ echo $TERM
dumb
~ $ 

@Axel-Naumann
Copy link
Member

Ah that's great! textinput already checks for $TERM (in TerminalDisplayUnix.cpp) - can we switch to dumb mode for a dumb TERM instead of adding an extra flag?

@aperotte
Copy link
Author

aperotte commented Feb 9, 2017

Yes, that makes sense! I'll look into that.

@Axel-Naumann
Copy link
Member

Any news? I really like your patch, and changing this to be $TERM sensitive sounds like a small-ish change?

@aperotte
Copy link
Author

I've been swamped, but I will work on it very soon

@aperotte
Copy link
Author

aperotte commented Mar 5, 2017

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

Copy link
Member

@Axel-Naumann Axel-Naumann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

@@ -145,9 +145,11 @@ void CompilerOptions::Parse(int argc, const char* const argv[],
}

InvocationOptions::InvocationOptions(int argc, const char* const* argv) :

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you remove the changes in this file from this PR?

@@ -98,6 +98,9 @@ namespace cling {
UITabCompletion* Completion =
new UITabCompletion(m_MetaProcessor->getInterpreter());
TI.SetCompletion(Completion);
if (D->GetTERM() && strstr(D->GetTERM(), "dumb")) {
TI.SetIsDumbTerm(true);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't this be done inside textinput itself? See below...

@@ -40,6 +40,8 @@ namespace textinput {
void Detach();
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; };
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These interfaces (nor the data member) should not be needed, see below. Instead we'd need an IsDumb().

@@ -31,6 +31,7 @@
namespace textinput {
TextInput::TextInput(Reader& reader, Display& display,
const char* HistFile /* = 0 */):
fIsDumbTerm(false),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't that a property of the TerminalDisplay? I'd prefer to have the interface there.

@@ -119,6 +119,7 @@ namespace textinput {
TerminalConfigUnix::Get().TIOS()->c_lflag |= ECHOCTL|ECHOKE|ECHOE;
#endif
const char* TERM = getenv("TERM");
SetTERM(TERM);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The if should test the display of the current iteration: if it's dumb, don't call NotifyResetInput..

@@ -124,7 +127,9 @@ namespace textinput {
|| (*iR)->HaveBufferedInput()) {
if ((*iR)->ReadInput(nRead, in)) {
ProcessNewInput(in, R);
DisplayNewInput(R, OldCursorPos);
if (!IsDumbTerm()) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These should all be moved to TerminalDisplay.

@aperotte
Copy link
Author

I will take a look, thanks for the comments.

@lazywithclass
Copy link

@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?

@aperotte
Copy link
Author

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.

@rileylev
Copy link

Has there been any progress? If not, I'm happy to give it a go, but I might need some pointers to get started.

@ferdymercury
Copy link
Contributor

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!

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

Successfully merging this pull request may close these issues.

None yet

5 participants