From 5adaeeaa3bed7f3022cc11d03eeb1b3426d7c200 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Fri, 25 Jan 2019 05:51:39 +0100 Subject: [PATCH] Terminal: Support setting the window title using Xterm escape sequences. Use this in the /bin/sh prompt to keep the window title in sync with the shell's working directory. :^) --- Terminal/Terminal.cpp | 49 +++++++++++++++++++++++++++++++++++++++++++ Terminal/Terminal.h | 8 +++++++ Userland/sh.cpp | 4 +++- 3 files changed, 60 insertions(+), 1 deletion(-) diff --git a/Terminal/Terminal.cpp b/Terminal/Terminal.cpp index 467f63608d7..a4a00df443a 100644 --- a/Terminal/Terminal.cpp +++ b/Terminal/Terminal.cpp @@ -356,6 +356,24 @@ void Terminal::escape$J(const Vector& params) } } +void Terminal::execute_xterm_command() +{ + bool ok; + unsigned value = parseUInt(String((const char*)m_xterm_param1.data(), m_xterm_param1.size()), ok); + if (ok) { + switch (value) { + case 0: + set_window_title(String((const char*)m_xterm_param2.data(), m_xterm_param2.size())); + break; + default: + notImplemented(); + break; + } + } + m_xterm_param1.clear_with_capacity(); + m_xterm_param2.clear_with_capacity(); +} + void Terminal::execute_escape_sequence(byte final) { auto paramparts = String((const char*)m_parameters.data(), m_parameters.size()).split(';'); @@ -437,9 +455,31 @@ void Terminal::on_char(byte ch) case ExpectBracket: if (ch == '[') m_escape_state = ExpectParameter; + else if (ch == ']') + m_escape_state = ExpectXtermParameter1; else m_escape_state = Normal; return; + case ExpectXtermParameter1: + if (ch != ';') { + m_xterm_param1.append(ch); + return; + } + m_escape_state = ExpectXtermParameter2; + return; + case ExpectXtermParameter2: + if (ch != '\007') { + m_xterm_param2.append(ch); + return; + } + m_escape_state = ExpectXtermFinal; + // fall through + case ExpectXtermFinal: + m_escape_state = Normal; + if (ch == '\007') + execute_xterm_command(); + return; + case ExpectParameter: if (is_valid_parameter_character(ch)) { m_parameters.append(ch); @@ -640,6 +680,15 @@ void Terminal::invalidate_window(const Rect& a_rect) } } +void Terminal::set_window_title(const String& title) +{ + int rc = gui_set_window_title(m_window_id, title.characters(), title.length()); + if (rc < 0) { + perror("gui_set_window_title"); + exit(1); + } +} + void Terminal::set_in_active_window(bool b) { if (m_in_active_window == b) diff --git a/Terminal/Terminal.h b/Terminal/Terminal.h index 151a610ae33..3c8f6a2a1fa 100644 --- a/Terminal/Terminal.h +++ b/Terminal/Terminal.h @@ -26,6 +26,7 @@ private: void put_character_at(unsigned row, unsigned column, byte ch); void invalidate_cursor(); void invalidate_window(const Rect& = Rect()); + void set_window_title(const String&); void escape$A(const Vector&); void escape$B(const Vector&); @@ -88,6 +89,7 @@ private: Attribute& attribute_at(word row, word column); void execute_escape_sequence(byte final); + void execute_xterm_command(); enum EscapeState { Normal, @@ -95,10 +97,16 @@ private: ExpectParameter, ExpectIntermediate, ExpectFinal, + + ExpectXtermParameter1, + ExpectXtermParameter2, + ExpectXtermFinal, }; EscapeState m_escape_state { Normal }; Vector m_parameters; Vector m_intermediates; + Vector m_xterm_param1; + Vector m_xterm_param2; byte* m_horizontal_tabs { nullptr }; bool m_belling { false }; diff --git a/Userland/sh.cpp b/Userland/sh.cpp index d94113ab21e..38976a27515 100644 --- a/Userland/sh.cpp +++ b/Userland/sh.cpp @@ -26,8 +26,10 @@ static void prompt() { if (g->uid == 0) printf("# "); - else + else { + printf("\033]0;%s@%s:%s\007", g->username.characters(), g->hostname, g->cwd.characters()); printf("\033[31;1m%s\033[0m@\033[37;1m%s\033[0m:\033[32;1m%s\033[0m$> ", g->username.characters(), g->hostname, g->cwd.characters()); + } fflush(stdout); }