Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 14 additions & 46 deletions modules/terminal/src/cpp/AdvancedTerminal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -191,38 +191,6 @@ injectNewlineIntoInput()
#endif
}
//=============================================================================
static void
writeStdoutUtf8(const std::string& msg)
{
#ifdef _WIN32
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
if (handle != nullptr && handle != INVALID_HANDLE_VALUE) {
std::wstring wide = utf8_to_wstring(msg);
DWORD written = 0;
WriteConsoleW(handle, wide.c_str(), static_cast<DWORD>(wide.size()), &written, nullptr);
return;
}
#endif
std::cout << msg;
std::cout.flush();
}
//=============================================================================
static void
writeStderrUtf8(const std::string& msg)
{
#ifdef _WIN32
HANDLE handle = GetStdHandle(STD_ERROR_HANDLE);
if (handle != nullptr && handle != INVALID_HANDLE_VALUE) {
std::wstring wide = utf8_to_wstring(msg);
DWORD written = 0;
WriteConsoleW(handle, wide.c_str(), static_cast<DWORD>(wide.size()), &written, nullptr);
return;
}
#endif
std::cerr << msg;
std::cerr.flush();
}
//=============================================================================
} // namespace
//=============================================================================
std::wstring
Expand All @@ -239,7 +207,6 @@ AdvancedTerminal::getTextLine(const std::wstring& prompt, bool bIsInput)
atPrompt = false;
return L"\n";
}

const char* line = repl->input(promptUtf8);
if (line == nullptr || line[0] == 0) {
atPrompt = false;
Expand Down Expand Up @@ -305,19 +272,19 @@ AdvancedTerminal::getTerminalHeight()
void
AdvancedTerminal::outputMessage(const std::wstring& msg)
{
std::string _msg = wstring_to_utf8(msg);
if (atPrompt) {
writeStdoutUtf8("\n");
atPrompt = false;
}

outputMessage(_msg);
outputMessage(wstring_to_utf8(msg));
}
//=============================================================================
void
AdvancedTerminal::outputMessage(const std::string& msg)
{
writeStdoutUtf8(msg);
if (atPrompt) {
std::cout << "\n";

atPrompt = false;
}
std::cout << msg;
std::cout.flush();
this->diary.writeMessage(msg);
}
//=============================================================================
Expand All @@ -331,10 +298,11 @@ void
AdvancedTerminal::errorMessage(const std::string& msg)
{
if (atPrompt) {
writeStdoutUtf8("\n");
std::cout << "\n";
atPrompt = false;
}
writeStderrUtf8(msg);
std::cerr << msg;
std::cerr.flush();
this->diary.writeMessage(msg);
}
//=============================================================================
Expand All @@ -348,11 +316,11 @@ void
AdvancedTerminal::warningMessage(const std::string& msg)
{
if (atPrompt) {
writeStdoutUtf8("\n");
std::cout << "\n";
atPrompt = false;
}
writeStdoutUtf8(msg);
this->diary.writeMessage(msg);
std::cout << msg;
std::cout.flush();
}
//=============================================================================
void
Expand Down
3 changes: 3 additions & 0 deletions modules/terminal/src/cpp/replxx/src/replxx_impl.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -856,6 +856,9 @@ Replxx::ReplxxImpl::input(std::string const& prompt)

/// Always render from beginning of current line. It's to prevent garbage inputs during
/// starting up.
if (!_terminal.is_at_beginning_of_the_line()) {
dprintf(_out_fd, "\n");
}
_terminal.jump_cursor(0, 0);
_asyncPrompt.clear();
_updatePrompt = false;
Expand Down
64 changes: 64 additions & 0 deletions modules/terminal/src/cpp/replxx/src/terminal.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -891,6 +891,70 @@ Terminal::jump_cursor(int xPos_, int yOffset_)
#endif
}

#if defined(_WIN32)
bool
Terminal::is_at_beginning_of_the_line(void)
{
CONSOLE_SCREEN_BUFFER_INFO inf;
HANDLE consoleOut(
_consoleOut != INVALID_HANDLE_VALUE ? _consoleOut : GetStdHandle(STD_OUTPUT_HANDLE));
if (!GetConsoleScreenBufferInfo(consoleOut, &inf)) {
return false;
}
return (inf.dwCursorPosition.X == 0);
}
#else
bool
Terminal::is_at_beginning_of_the_line(void)
{
// Request cursor position report (DSR) and parse response: ESC [ row ; col R
const char request[] = "\033[6n";
write8(request, sizeof(request) - 1);

fd_set rfds;
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 200000; // 200 ms

std::string resp;
int fd = _in_fd;
char buf[32];

while (true) {
FD_ZERO(&rfds);
FD_SET(fd, &rfds);
int ret = select(fd + 1, &rfds, nullptr, nullptr, &tv);
if (ret <= 0) {
break; // timeout or error
}
ssize_t n = read(fd, buf, sizeof(buf));
if (n <= 0) {
break;
}
resp.append(buf, buf + n);
if (resp.find('R') != std::string::npos) {
break;
}
// small additional delay for more data
tv.tv_sec = 0;
tv.tv_usec = 50000; // 50ms
}

size_t p1 = resp.find('[');
size_t p2 = resp.find('R');
if (p1 == std::string::npos || p2 == std::string::npos || p2 <= p1) {
return false;
}
std::string inside = resp.substr(p1 + 1, p2 - p1 - 1);
size_t sep = inside.find(';');
if (sep == std::string::npos) {
return false;
}
int col = atoi(inside.c_str() + sep + 1);
return (col == 1); // DSR is 1-based
}
#endif

#ifdef _WIN32
void
Terminal::set_cursor_visible(bool visible_)
Expand Down
2 changes: 2 additions & 0 deletions modules/terminal/src/cpp/replxx/src/terminal.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ public:
jump_cursor(int, int);
void
set_cursor_visible(bool);
bool
is_at_beginning_of_the_line(void);
#ifndef _WIN32
int
read_verbatim(char32_t*, int);
Expand Down