summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2019-01-25 05:51:39 +0100
committerAndreas Kling <awesomekling@gmail.com>2019-01-25 05:52:16 +0100
commit5adaeeaa3bed7f3022cc11d03eeb1b3426d7c200 (patch)
treefda28db007acd51b64112406838d44fd097b9a6f
parent5f14e22a31855465f251ad7eac014d7b46aab1b1 (diff)
downloadserenity-5adaeeaa3bed7f3022cc11d03eeb1b3426d7c200.zip
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. :^)
-rw-r--r--Terminal/Terminal.cpp49
-rw-r--r--Terminal/Terminal.h8
-rw-r--r--Userland/sh.cpp4
3 files changed, 60 insertions, 1 deletions
diff --git a/Terminal/Terminal.cpp b/Terminal/Terminal.cpp
index 467f63608d..a4a00df443 100644
--- a/Terminal/Terminal.cpp
+++ b/Terminal/Terminal.cpp
@@ -356,6 +356,24 @@ void Terminal::escape$J(const Vector<unsigned>& 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 151a610ae3..3c8f6a2a1f 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<unsigned>&);
void escape$B(const Vector<unsigned>&);
@@ -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<byte> m_parameters;
Vector<byte> m_intermediates;
+ Vector<byte> m_xterm_param1;
+ Vector<byte> m_xterm_param2;
byte* m_horizontal_tabs { nullptr };
bool m_belling { false };
diff --git a/Userland/sh.cpp b/Userland/sh.cpp
index d94113ab21..38976a2751 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);
}