Skip to content

Conversation

@Tucchhaa
Copy link
Contributor

@Tucchhaa Tucchhaa commented Jan 27, 2026

This PR changes to the layout of Python Console in pilot.

How it looked before:
image

How it looks now:
image

Multiline commands support:
image

Comment on lines +116 to +124
connect(
m_history_edit->document(),
&QTextDocument::contentsChanged,
this,
[this]()
{
const int newHeight = calcHeightToFitContents(m_history_edit);
m_history_edit->setMinimumHeight(newHeight);
});
Copy link
Contributor Author

Choose a reason for hiding this comment

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

set minHeight to history editor so that it would fill all free space in scrollArea if there's some

Comment on lines +125 to +133
connect(
m_command_edit->document(),
&QTextDocument::contentsChanged,
this,
[this, commandEditMinHeight]()
{
const int newHeight = std::max(calcHeightToFitContents(m_command_edit), commandEditMinHeight);
m_command_edit->setFixedHeight(newHeight);
});
Copy link
Contributor Author

Choose a reason for hiding this comment

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

set fixedHeight to commandEdit so that it is big enough to contain all the text, but doesn't stretch if scrollArea has free space

Comment on lines 172 to 177
std::string const command = m_command_edit->toPlainText().trimmed().toStdString();

if (command.length() == 0)
{
return;
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

added trimmed(), so that user wouldn't execute empty command

Comment on lines 147 to 148
printCommandStdout(m_python_redirect.stdout_string());
printCommandStderr(m_python_redirect.stderr_string());
Copy link
Contributor Author

Choose a reason for hiding this comment

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

printCommandStderr and printCommandStdout were duplicates of writeToHistory so I removed them

Copy link
Collaborator

Choose a reason for hiding this comment

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

Personally, I think we should keep them into two functions or a single function with different arguments to distinguish stdout and stderr, which is helpful when we give different color for them.

Copy link
Member

Choose a reason for hiding this comment

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

I don't know. Sending the log through a unified API is good. But it's bad to combine stdout and stderr.

It's hard to decide, so we should not change it right now. Please keep the old code.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, I can bring these functions back. But how about I mark output of stderr with red color?

Copy link
Contributor Author

@Tucchhaa Tucchhaa Jan 31, 2026

Choose a reason for hiding this comment

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

So I've tried to mark stderr with red color and here's what I got:
image

I have added stdout: and stderr: strings to distinguish outputs of printCommandStdout and printCommandStderr.

As you can see when an exception occurs both stdout and stderr have something to output.

Should we mark both of them with red color or only stderr? Or should we just postpone this and keep the old behavior?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, I think I will keep the old behavior for now

Comment on lines 245 to -250
QTextCursor cursor = m_history_edit->textCursor();
cursor.movePosition(QTextCursor::End);
m_history_edit->setTextCursor(cursor);
m_history_edit->insertPlainText(QString::fromStdString(data));
cursor.movePosition(QTextCursor::End);
m_history_edit->setTextCursor(cursor);
Copy link
Contributor Author

@Tucchhaa Tucchhaa Jan 27, 2026

Choose a reason for hiding this comment

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

Looks like we just need to set cursor before we write to the editor since it's read-only editor

setCommand(QString::fromStdString(command_to_show));
}

void RPythonConsoleDockWidget::navigateCommand(int offset)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

this function contained a bug, when not yet executed command couldn't be restored after navigating to past commands and back to the not yet executed command. So I have fixed the bug and simplified the function.

Copy link
Member

Choose a reason for hiding this comment

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

Good catch. I didn't notice it behaved incorrectly that way.

Comment on lines +182 to +183
const auto formatted_command = std::format("[{}] {}\n\n", m_last_command_serial, command);
writeToHistory(formatted_command);
Copy link
Contributor Author

@Tucchhaa Tucchhaa Jan 27, 2026

Choose a reason for hiding this comment

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

this is an equivalent replacement of printCommandHistory() function

Comment on lines +53 to +54
const bool is_first_line_focused = cursor.blockNumber() == 0;
const bool is_last_line_focused = cursor.blockNumber() == document()->blockCount() - 1;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

need this so that navigation between lines of a past command is possible

@Tucchhaa Tucchhaa marked this pull request as ready for review January 27, 2026 06:42
@Tucchhaa Tucchhaa marked this pull request as draft January 27, 2026 06:43
@Tucchhaa Tucchhaa marked this pull request as ready for review January 28, 2026 03:12
Copy link
Collaborator

@tigercosmos tigercosmos left a comment

Choose a reason for hiding this comment

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

It's recommended to write something in the PR description. Attaching some screenshots is also helpful as it's a GUI change.

execute();
if (event->modifiers() & Qt::ShiftModifier)
{
this->insertPlainText("\n");
Copy link
Collaborator

Choose a reason for hiding this comment

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

Question: what happens on Windows?

Copy link
Member

Choose a reason for hiding this comment

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

Good question. @Tucchhaa , if you don't have time/environment to test for the behaviors on Windows, make a guess.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't have Windows environment. But I'm pretty sure it behaves the same as on MacOS, since Qt is not OS specific.

I asked chatgpt about it and told the same thing.

Copy link
Member

Choose a reason for hiding this comment

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

Good to know that the code is based a guess. Line ending on Windows, Mac, and Linux are \r\n (CR LF), \r (CR), and \n (LF). That is a concern. But I agree that if \n works on Mac. We can have the fingers cross before some nice people point out issues on Windows.

Let's avoid using AI tools as a reference. They do not have credibility. (Using them and studying yourself is fine.)

}
}
else if (Qt::Key_Up == event->key())
else if (Qt::Key_Up == event->key() && is_first_line_focused)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Could you describe what is the behaviour difference before and after and is the difference expected?

Copy link
Member

Choose a reason for hiding this comment

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

A quick description suffices.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This code is needed to make navigation in multiline command more convenient in case when there are previous commands.

Suppose we don't have is_first_line_focused, here's what will happen in a simple user case:

  1. User executes any command, e.g.: a = 9

  2. Then user writes this multiline command, but he doesn't executes it yet:

b = 10
c = 11
print(a + b + c)
  1. Since user just typed it, the focus is on the last line. Then user realizes that the value of c is incorrect and he wants to change it to 12

  2. So user presses arrow up to focus the second line c = 11, but instead of moving focus up, navigate function will be called which will change the value of command editor to previous command, which is a = 9

With is_first_line_focused this behavior is prevented. And so pilot's command editor behaves just like any other terminal. The similar reason why we need is_last_line_focused

Copy link
Member

Choose a reason for hiding this comment

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

Thank you. Very clear elaboration.

Comment on lines 147 to 148
printCommandStdout(m_python_redirect.stdout_string());
printCommandStderr(m_python_redirect.stderr_string());
Copy link
Collaborator

Choose a reason for hiding this comment

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

Personally, I think we should keep them into two functions or a single function with different arguments to distinguish stdout and stderr, which is helpful when we give different color for them.

Copy link
Member

@yungyuc yungyuc left a comment

Choose a reason for hiding this comment

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

Nice work. Some comments:

  • Add summary in the opening PR comment block. (Just edit it.) Include some screenshots of the new UI. It would be good to also include screenshots of the old UI to make a comparison.
  • Keep the old printCommandStdout and printCommandStderr before we have a better idea for how to handle the text logging.

After the discussion converges and the code can be finalized, commits should be squashed because the overall change is straight-forward. Formatting should not use distinct commits.

Refactoring may use distinct commits, although for this PR, it does not matter. Do what you like.

But before the PR is close to merging, feel free to stack commits.

execute();
if (event->modifiers() & Qt::ShiftModifier)
{
this->insertPlainText("\n");
Copy link
Member

Choose a reason for hiding this comment

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

Good question. @Tucchhaa , if you don't have time/environment to test for the behaviors on Windows, make a guess.

}
}
else if (Qt::Key_Up == event->key())
else if (Qt::Key_Up == event->key() && is_first_line_focused)
Copy link
Member

Choose a reason for hiding this comment

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

A quick description suffices.

{
setWidget(new QWidget);
widget()->setLayout(new QVBoxLayout);
m_scroll_area->setWidgetResizable(true);
Copy link
Member

Choose a reason for hiding this comment

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

I like the use of a scroll area. @Tucchhaa do you think it stands a chance to be extended to be a rich-text editor (in the future)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Depends on what you consider a rich-text editor :)

For me, I think we would need to add the following features:

  • Syntax highlighting for command editor and history editor. it can be implemented using QSyntaxHighlighter and it seems not too difficult to implement.

  • Suggestion popup-list in command editor that will be shown when user types a variable or function name. This can be challenging to implement but still possible in my opinion.

With these features pilot's console will be very similar to browser's console and pretty convenient to use.

However we can go further and implement jupyter notebook-like editor. Since QTextEdit supports HTML (tables, hyperlinks even images can be inserted into the editor), it seems that this feature is feasible

Copy link
Member

Choose a reason for hiding this comment

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

Making it like a terminal (emulator) or jupyter notebook like editor will be fantastic. We can talk more about it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Maybe I could create an issue with the action plan of step-by-step development of rich-text editor?

Like :
Step 1: implement syntax highlighting in command editor and history editor
Step 2: implement suggestion popup-list
Step 3: Research possibility of jupyter-notebook like implementation.

And each step with some implementation details (like usage of QSyntaxHighlighter)

What do you think?

Copy link
Member

Choose a reason for hiding this comment

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

Maybe I could create an issue with the action plan of step-by-step development of rich-text editor?

Like :
Step 1: implement syntax highlighting in command editor and history editor
Step 2: implement suggestion popup-list
Step 3: Research possibility of jupyter-notebook like implementation.

And each step with some implementation details (like usage of QSyntaxHighlighter)

What do you think?

It will be fantastic. Please go ahead.

A discussion topic (in https://github.com/solvcon/modmesh/discussions) may be more suitable than an issue at the moment. It's up to you.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, I will do that in a week or so

Comment on lines 147 to 148
printCommandStdout(m_python_redirect.stdout_string());
printCommandStderr(m_python_redirect.stderr_string());
Copy link
Member

Choose a reason for hiding this comment

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

I don't know. Sending the log through a unified API is good. But it's bad to combine stdout and stderr.

It's hard to decide, so we should not change it right now. Please keep the old code.

setCommand(QString::fromStdString(command_to_show));
}

void RPythonConsoleDockWidget::navigateCommand(int offset)
Copy link
Member

Choose a reason for hiding this comment

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

Good catch. I didn't notice it behaved incorrectly that way.

@yungyuc yungyuc added the pilot GUI and visualization label Jan 30, 2026
@Tucchhaa Tucchhaa requested a review from tigercosmos January 31, 2026 05:55
Copy link
Member

@yungyuc yungyuc left a comment

Choose a reason for hiding this comment

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

Leave a global comment to request for a next review. No need to press the ready for review button. We do not pay attention to it.

}
}
else if (Qt::Key_Up == event->key())
else if (Qt::Key_Up == event->key() && is_first_line_focused)
Copy link
Member

Choose a reason for hiding this comment

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

Thank you. Very clear elaboration.

{
setWidget(new QWidget);
widget()->setLayout(new QVBoxLayout);
m_scroll_area->setWidgetResizable(true);
Copy link
Member

Choose a reason for hiding this comment

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

Making it like a terminal (emulator) or jupyter notebook like editor will be fantastic. We can talk more about it.

execute();
if (event->modifiers() & Qt::ShiftModifier)
{
this->insertPlainText("\n");
Copy link
Member

Choose a reason for hiding this comment

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

Good to know that the code is based a guess. Line ending on Windows, Mac, and Linux are \r\n (CR LF), \r (CR), and \n (LF). That is a concern. But I agree that if \n works on Mac. We can have the fingers cross before some nice people point out issues on Windows.

Let's avoid using AI tools as a reference. They do not have credibility. (Using them and studying yourself is fine.)

@Tucchhaa
Copy link
Contributor Author

Tucchhaa commented Feb 1, 2026

@yungyuc @tigercosmos I have brought back printCommandStdout and printCommandStderr. Can you review again, please?

Should I squash and force push commits to this PR? Or will the PR be squashed and merged?

@Tucchhaa Tucchhaa requested a review from yungyuc February 1, 2026 02:34
Copy link
Member

@yungyuc yungyuc left a comment

Choose a reason for hiding this comment

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

LGTM

@yungyuc @tigercosmos I have brought back printCommandStdout and printCommandStderr. Can you review again, please?

Thank you. This is a good summary. Requesting for a next review with a good summary like this benefits both the contributor and the reviewers. It helps the contributor to pro-actively pre-review before requesting, and the reviewers to know what to read.

All PRs should be carried out in this way. I did not document it in this repository but I should.

Should I squash and force push commits to this PR? Or will the PR be squashed and merged?

Yes, please squash and make a new commit or commits, because it's close to be merged. For a small PR like this (around 100 LoC), using one commit suffices, but might not hurt to use 2 or 3.

Do notify with a global comment after it's squashed and ready for the next review.

@Tucchhaa Tucchhaa force-pushed the issue_173 branch 2 times, most recently from e91666d to 46ae19b Compare February 2, 2026 03:08
@yungyuc
Copy link
Member

yungyuc commented Feb 2, 2026

@Tucchhaa I merged the CI-fixing PR #670 . Please rebase to pick it up.

@Tucchhaa
Copy link
Contributor Author

Tucchhaa commented Feb 2, 2026

@Tucchhaa I merged the CI-fixing PR #670 . Please rebase to pick it up.

@yungyuc thank you, I have rebased my PR

Copy link
Member

@yungyuc yungyuc left a comment

Choose a reason for hiding this comment

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

I have rebased my PR

CI is clean. Good to merge.

{
setWidget(new QWidget);
widget()->setLayout(new QVBoxLayout);
m_scroll_area->setWidgetResizable(true);
Copy link
Member

Choose a reason for hiding this comment

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

Maybe I could create an issue with the action plan of step-by-step development of rich-text editor?

Like :
Step 1: implement syntax highlighting in command editor and history editor
Step 2: implement suggestion popup-list
Step 3: Research possibility of jupyter-notebook like implementation.

And each step with some implementation details (like usage of QSyntaxHighlighter)

What do you think?

It will be fantastic. Please go ahead.

A discussion topic (in https://github.com/solvcon/modmesh/discussions) may be more suitable than an issue at the moment. It's up to you.

@yungyuc yungyuc merged commit c002d20 into solvcon:master Feb 2, 2026
14 checks passed
@yungyuc
Copy link
Member

yungyuc commented Feb 2, 2026

@Tucchhaa I forgot to ask you to update the commit with a summary of the change, but it's already merged. Please add good summary to each of your future commits. Do not use conventional/semantic commit messages, which are not suitable for the computing code.

@yungyuc yungyuc linked an issue Feb 2, 2026 that may be closed by this pull request
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pilot GUI and visualization

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support more than one line in the python input box

3 participants