aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Benjamin Barenblat <bbarenblat@gmail.com>2021-12-26 15:57:13 -0500
committerGravatar Benjamin Barenblat <bbarenblat@gmail.com>2021-12-26 15:57:13 -0500
commit4590204701232f3bee50daf69a0d3e62b026c648 (patch)
tree5d7ad9da3f97f51b37b6331b8c57d02030c21280
parent56f7d79efdc8ad26f5e8e5508eb616144f04fea3 (diff)
goldfishterm: Don’t hard-code std::cout/STDOUT_FILENOHEADmain
Make terminal-handling code purer by requiring the user pass TERM, a termios struct, and an appropriate ostream rather than querying them from the environment. This eliminates some error-handling code and makes duplicate syscalls less likely.
-rw-r--r--goldfishterm/internal/emit.cc8
-rw-r--r--goldfishterm/simple.cc34
-rw-r--r--goldfishterm/simple.h18
-rw-r--r--src/ui/terminal/line.cc10
4 files changed, 26 insertions, 44 deletions
diff --git a/goldfishterm/internal/emit.cc b/goldfishterm/internal/emit.cc
index 2cc7609..608aa3c 100644
--- a/goldfishterm/internal/emit.cc
+++ b/goldfishterm/internal/emit.cc
@@ -14,15 +14,9 @@
#include "goldfishterm/internal/emit.h"
-#include <errno.h>
-#include <stdint.h>
-#include <unistd.h>
-
#include <memory>
-#include <system_error>
-#include <vector>
+#include <ostream>
-#include "third_party/abseil/absl/strings/string_view.h"
#include "third_party/abseil/absl/time/clock.h"
#include "third_party/abseil/absl/types/span.h"
diff --git a/goldfishterm/simple.cc b/goldfishterm/simple.cc
index 88ceef0..0afa08f 100644
--- a/goldfishterm/simple.cc
+++ b/goldfishterm/simple.cc
@@ -14,9 +14,7 @@
#include "goldfishterm/simple.h"
-#include <stdlib.h>
#include <termios.h>
-#include <unistd.h>
#include <stdexcept>
#include <vector>
@@ -33,22 +31,6 @@ namespace {
using ::goldfishterm_internal::InterpretStringCapability;
using ::goldfishterm_internal::InterpretStringCapabilityInput;
-termios StdoutTermios() {
- termios tty;
- if (tcgetattr(STDOUT_FILENO, &tty) < 0) {
- throw std::system_error(errno, std::system_category(), "tcgetattr");
- }
- return tty;
-}
-
-absl::string_view TerminalNameFromEnvironment() {
- const char* name = getenv("TERM");
- if (name == nullptr) {
- throw std::runtime_error("TERM unset");
- }
- return name;
-}
-
StringCapability CursorVisibilityCapability(CursorVisibility v) {
switch (v) {
case CursorVisibility::kInvisible:
@@ -64,14 +46,12 @@ StringCapability CursorVisibilityCapability(CursorVisibility v) {
} // namespace
-SimpleTerminalOutput::SimpleTerminalOutput()
- : SimpleTerminalOutput(StdoutTermios()) {}
-
-SimpleTerminalOutput::SimpleTerminalOutput(const termios& tty)
- : terminfo_(
- TerminfoEntry::FromSystemDatabase(TerminalNameFromEnvironment())) {
- baud_ = cfgetospeed(&tty);
-}
+SimpleTerminalOutput::SimpleTerminalOutput(absl::string_view terminal_name,
+ const termios& tty,
+ std::ostream& out)
+ : terminfo_(TerminfoEntry::FromSystemDatabase(terminal_name)),
+ baud_(cfgetospeed(&tty)),
+ out_(out) {}
void SimpleTerminalOutput::SetCursorVisibility(CursorVisibility v) {
return Emit(CursorVisibilityCapability(v));
@@ -86,7 +66,7 @@ void SimpleTerminalOutput::Emit(
std::move(parameters), /*baud=*/baud_,
/*lines_affected=*/1))
.terms,
- std::cout);
+ out_);
}
} // namespace goldfishterm
diff --git a/goldfishterm/simple.h b/goldfishterm/simple.h
index 48a7789..0228749 100644
--- a/goldfishterm/simple.h
+++ b/goldfishterm/simple.h
@@ -17,7 +17,7 @@
#include <termios.h>
-#include <iostream>
+#include <ostream>
#include <vector>
#include "goldfishterm/internal/string_capability.h"
@@ -33,15 +33,14 @@ enum class CursorVisibility {
kVeryVisible,
};
-// Looks up escape sequences for the terminal described in the TERM environment
-// variable, and allows sending those escape sequences to standard output.
+// Looks up escape sequences for the specified terminal and allows sending those
+// escape sequences to the specified ostream.
//
-// This class is thread-safe, provided you don't mutate the TERM environment
-// variable while its constructor is running.
+// This class is thread-safe.
class SimpleTerminalOutput final {
public:
- explicit SimpleTerminalOutput();
- explicit SimpleTerminalOutput(const termios&);
+ explicit SimpleTerminalOutput(absl::string_view terminal_name, const termios&,
+ std::ostream&);
SimpleTerminalOutput(const SimpleTerminalOutput&) noexcept = default;
SimpleTerminalOutput& operator=(const SimpleTerminalOutput&) noexcept =
@@ -49,9 +48,9 @@ class SimpleTerminalOutput final {
SimpleTerminalOutput(SimpleTerminalOutput&&) noexcept = default;
SimpleTerminalOutput& operator=(SimpleTerminalOutput&&) noexcept = default;
- void Write(absl::string_view s) { std::cout.write(s.data(), s.size()); }
+ void Write(absl::string_view s) { out_.write(s.data(), s.size()); }
- void Flush() { std::cout.flush(); }
+ void Flush() { out_.flush(); }
// Rings the bell. On some terminals, this may flash the screen instead.
void Beep() { Emit(StringCapability::kBell); }
@@ -74,6 +73,7 @@ class SimpleTerminalOutput final {
TerminfoEntry terminfo_;
int baud_;
+ std::ostream& out_;
};
} // namespace goldfishterm
diff --git a/src/ui/terminal/line.cc b/src/ui/terminal/line.cc
index 962b692..e668b28 100644
--- a/src/ui/terminal/line.cc
+++ b/src/ui/terminal/line.cc
@@ -16,6 +16,7 @@
#include <errno.h>
#include <signal.h>
+#include <stdlib.h>
#include <sys/ioctl.h>
#include <termios.h>
#include <unistd.h>
@@ -78,7 +79,14 @@ TerminalLine::TerminalLine() {
}
EnterRawMode();
- tty_ = std::make_unique<goldfishterm::SimpleTerminalOutput>(current_termios_);
+
+ const char* terminal_name = getenv("TERM");
+ if (terminal_name == nullptr) {
+ // Fall back to a minimal subset of the ANSI capabilities.
+ terminal_name = "ansi-mini";
+ }
+ tty_ = std::make_unique<goldfishterm::SimpleTerminalOutput>(
+ terminal_name, current_termios_, std::cout);
sigwinch_watcher_ = std::thread([this] {
sigset_t sigwinch = SigsetContaining(SIGWINCH);