Repository navigation
feat(core): 回复光标位置报告 DSR 6n (#28) #224
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| #include "terminal.hpp" | ||
| #include <cstdio> | ||
| #include <stdexcept> | ||
| #include <string> | ||
|
|
||
| namespace { | ||
| void require(bool condition, const char* message) { | ||
| if (!condition) throw std::runtime_error(message); | ||
| } | ||
| } // namespace | ||
|
|
||
| int main() { | ||
| using termforge::ParseMode; | ||
| using termforge::Parser; | ||
| Parser parser(5, 10, 10, ParseMode::recovery); | ||
| require(parser.take_replies().empty(), "no replies before any query"); | ||
| parser.feed("ab"); | ||
| parser.feed("\x1b[6n"); | ||
| const auto replies = parser.take_replies(); | ||
| require(replies.size() == 1 && replies[0] == "\x1b[1;3R", "cursor report mismatch"); | ||
| require(parser.take_replies().empty(), "replies were not drained"); | ||
| parser.feed("\x1b[2;7H"); | ||
| parser.feed("\x1b[6n"); | ||
| const auto moved = parser.take_replies(); | ||
| require(moved.size() == 1 && moved[0] == "\x1b[2;7R", "moved cursor report mismatch"); | ||
| // An unimplemented report must stay unimplemented instead of being faked. | ||
| parser.feed("\x1b[5n"); | ||
| require(parser.take_replies().empty(), "unsupported report produced a reply"); | ||
| std::puts("cursor reply contracts passed"); | ||
| return 0; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -867,6 +867,12 @@ class ShellWindow { | |
| trace_offset_ += bytes.size(); | ||
| } | ||
| parser_.feed(bytes); batch += bytes.size(); | ||
| #ifndef TERMFORGE_CANDIDATE_CORE | ||
| // Query replies (for example a cursor position report) go back to the | ||
| // same bounded input queue as keyboard bytes, so ordering and | ||
| // backpressure stay identical for the child. | ||
| for (const auto& reply : parser_.take_replies()) input_.send(reply); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When a query arrives during an active paste or while the input queue is full, Useful? React with 👍 / 👎. |
||
| #endif | ||
| #ifdef TERMFORGE_CANDIDATE_CORE | ||
| route_terminal_events(); | ||
| #endif | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the confirmed C++/Qt/fixed-ConPTY product configuration,
src/qt/terminal_session.hpp::poll()feeds this sameParserbut never callstake_replies(); the only reply consumer added here is in the legacy Win32 shell. Consequently, a child issuingCSI 6nin the Qt application still receives no response, and repeated queries now accumulate reply strings indefinitely in the session's parser. Drain and send replies from the Qt session's output-consumption path as well, with an explicit policy for input rejection. This also follows AGENTS.md's requirement to implement the confirmed Qt product route.AGENTS.md reference: AGENTS.md:L5-L6
Useful? React with 👍 / 👎.