diff options
author | Tom Hubrecht <github@mail.hubrecht.ovh> | 2024-05-28 11:19:08 +0200 |
---|---|---|
committer | Tom Hubrecht <github@mail.hubrecht.ovh> | 2024-05-29 09:54:47 +0200 |
commit | 81bdf8d2d672e135e68745e6975ad5edafadf13a (patch) | |
tree | 3a571a94b17c0436ac586f01384308a687b86ee4 /src/libutil | |
parent | 6fd6795bc4faed644c5f3abafdcb21638a119342 (diff) |
util.{hh,cc}: Split out terminal.{hh,cc}
Change-Id: I9de2296b4012d50f540124001d54d6ca3be4c6da
Diffstat (limited to 'src/libutil')
-rw-r--r-- | src/libutil/error.cc | 1 | ||||
-rw-r--r-- | src/libutil/logging.cc | 1 | ||||
-rw-r--r-- | src/libutil/meson.build | 2 | ||||
-rw-r--r-- | src/libutil/signals.cc | 1 | ||||
-rw-r--r-- | src/libutil/suggestions.cc | 4 | ||||
-rw-r--r-- | src/libutil/terminal.cc | 104 | ||||
-rw-r--r-- | src/libutil/terminal.hh | 40 | ||||
-rw-r--r-- | src/libutil/util.cc | 96 | ||||
-rw-r--r-- | src/libutil/util.hh | 25 |
9 files changed, 152 insertions, 122 deletions
diff --git a/src/libutil/error.cc b/src/libutil/error.cc index fe73ffc56..f780aabef 100644 --- a/src/libutil/error.cc +++ b/src/libutil/error.cc @@ -1,6 +1,7 @@ #include "environment-variables.hh" #include "error.hh" #include "position.hh" +#include "terminal.hh" #include <iostream> #include <optional> diff --git a/src/libutil/logging.cc b/src/libutil/logging.cc index 8e4828be4..731d1034d 100644 --- a/src/libutil/logging.cc +++ b/src/libutil/logging.cc @@ -4,6 +4,7 @@ #include "config.hh" #include "source-path.hh" #include "position.hh" +#include "terminal.hh" #include <atomic> #include <nlohmann/json.hpp> diff --git a/src/libutil/meson.build b/src/libutil/meson.build index 01b3e24b7..c890911e9 100644 --- a/src/libutil/meson.build +++ b/src/libutil/meson.build @@ -30,6 +30,7 @@ libutil_sources = files( 'source-path.cc', 'suggestions.cc', 'tarfile.cc', + 'terminal.cc', 'thread-pool.cc', 'url.cc', 'url-name.cc', @@ -90,6 +91,7 @@ libutil_headers = files( 'suggestions.hh', 'sync.hh', 'tarfile.hh', + 'terminal.hh', 'thread-pool.hh', 'topo-sort.hh', 'types.hh', diff --git a/src/libutil/signals.cc b/src/libutil/signals.cc index 41fdc9dc8..c0e66f6ed 100644 --- a/src/libutil/signals.cc +++ b/src/libutil/signals.cc @@ -2,6 +2,7 @@ #include "util.hh" #include "error.hh" #include "sync.hh" +#include "terminal.hh" #include <thread> diff --git a/src/libutil/suggestions.cc b/src/libutil/suggestions.cc index 9510a5f0c..63dcf84b5 100644 --- a/src/libutil/suggestions.cc +++ b/src/libutil/suggestions.cc @@ -1,7 +1,9 @@ #include "suggestions.hh" #include "ansicolor.hh" -#include "util.hh" +#include "terminal.hh" + #include <algorithm> +#include <ostream> namespace nix { diff --git a/src/libutil/terminal.cc b/src/libutil/terminal.cc new file mode 100644 index 000000000..b58331d04 --- /dev/null +++ b/src/libutil/terminal.cc @@ -0,0 +1,104 @@ +#include "terminal.hh" +#include "environment-variables.hh" +#include "sync.hh" + +#include <sys/ioctl.h> +#include <unistd.h> + +namespace nix { + +bool shouldANSI() +{ + return isatty(STDERR_FILENO) + && getEnv("TERM").value_or("dumb") != "dumb" + && !(getEnv("NO_COLOR").has_value() || getEnv("NOCOLOR").has_value()); +} + +std::string filterANSIEscapes(std::string_view s, bool filterAll, unsigned int width) +{ + std::string t, e; + size_t w = 0; + auto i = s.begin(); + + while (w < (size_t) width && i != s.end()) { + + if (*i == '\e') { + std::string e; + e += *i++; + char last = 0; + + if (i != s.end() && *i == '[') { + e += *i++; + // eat parameter bytes + while (i != s.end() && *i >= 0x30 && *i <= 0x3f) e += *i++; + // eat intermediate bytes + while (i != s.end() && *i >= 0x20 && *i <= 0x2f) e += *i++; + // eat final byte + if (i != s.end() && *i >= 0x40 && *i <= 0x7e) e += last = *i++; + } else { + if (i != s.end() && *i >= 0x40 && *i <= 0x5f) e += *i++; + } + + if (!filterAll && last == 'm') + t += e; + } + + else if (*i == '\t') { + i++; t += ' '; w++; + while (w < (size_t) width && w % 8) { + t += ' '; w++; + } + } + + else if (*i == '\r' || *i == '\a') + // do nothing for now + i++; + + else { + w++; + // Copy one UTF-8 character. + if ((*i & 0xe0) == 0xc0) { + t += *i++; + if (i != s.end() && ((*i & 0xc0) == 0x80)) t += *i++; + } else if ((*i & 0xf0) == 0xe0) { + t += *i++; + if (i != s.end() && ((*i & 0xc0) == 0x80)) { + t += *i++; + if (i != s.end() && ((*i & 0xc0) == 0x80)) t += *i++; + } + } else if ((*i & 0xf8) == 0xf0) { + t += *i++; + if (i != s.end() && ((*i & 0xc0) == 0x80)) { + t += *i++; + if (i != s.end() && ((*i & 0xc0) == 0x80)) { + t += *i++; + if (i != s.end() && ((*i & 0xc0) == 0x80)) t += *i++; + } + } + } else + t += *i++; + } + } + + return t; +} + +static Sync<std::pair<unsigned short, unsigned short>> windowSize{{0, 0}}; + +void updateWindowSize() +{ + struct winsize ws; + if (ioctl(2, TIOCGWINSZ, &ws) == 0) { + auto windowSize_(windowSize.lock()); + windowSize_->first = ws.ws_row; + windowSize_->second = ws.ws_col; + } +} + + +std::pair<unsigned short, unsigned short> getWindowSize() +{ + return *windowSize.lock(); +} + +} diff --git a/src/libutil/terminal.hh b/src/libutil/terminal.hh new file mode 100644 index 000000000..43df5bd70 --- /dev/null +++ b/src/libutil/terminal.hh @@ -0,0 +1,40 @@ +#pragma once +///@file + +#include <limits> +#include <string> + +namespace nix { + +/** + * Determine whether ANSI escape sequences are appropriate for the + * present output. + */ +bool shouldANSI(); + +/** + * Truncate a string to 'width' printable characters. If 'filterAll' + * is true, all ANSI escape sequences are filtered out. Otherwise, + * some escape sequences (such as colour setting) are copied but not + * included in the character count. Also, tabs are expanded to + * spaces. + */ +std::string filterANSIEscapes(std::string_view s, + bool filterAll = false, + unsigned int width = std::numeric_limits<unsigned int>::max()); + +/** + * Recalculate the window size, updating a global variable. Used in the + * `SIGWINCH` signal handler. + */ +void updateWindowSize(); + +/** + * @return the number of rows and columns of the terminal. + * + * The value is cached so this is quick. The cached result is computed + * by `updateWindowSize()`. + */ +std::pair<unsigned short, unsigned short> getWindowSize(); + +} diff --git a/src/libutil/util.cc b/src/libutil/util.cc index 97d53ca63..63d9e5248 100644 --- a/src/libutil/util.cc +++ b/src/libutil/util.cc @@ -1436,83 +1436,6 @@ void ignoreException(Verbosity lvl) } catch (...) { } } -bool shouldANSI() -{ - return isatty(STDERR_FILENO) - && getEnv("TERM").value_or("dumb") != "dumb" - && !(getEnv("NO_COLOR").has_value() || getEnv("NOCOLOR").has_value()); -} - -std::string filterANSIEscapes(std::string_view s, bool filterAll, unsigned int width) -{ - std::string t, e; - size_t w = 0; - auto i = s.begin(); - - while (w < (size_t) width && i != s.end()) { - - if (*i == '\e') { - std::string e; - e += *i++; - char last = 0; - - if (i != s.end() && *i == '[') { - e += *i++; - // eat parameter bytes - while (i != s.end() && *i >= 0x30 && *i <= 0x3f) e += *i++; - // eat intermediate bytes - while (i != s.end() && *i >= 0x20 && *i <= 0x2f) e += *i++; - // eat final byte - if (i != s.end() && *i >= 0x40 && *i <= 0x7e) e += last = *i++; - } else { - if (i != s.end() && *i >= 0x40 && *i <= 0x5f) e += *i++; - } - - if (!filterAll && last == 'm') - t += e; - } - - else if (*i == '\t') { - i++; t += ' '; w++; - while (w < (size_t) width && w % 8) { - t += ' '; w++; - } - } - - else if (*i == '\r' || *i == '\a') - // do nothing for now - i++; - - else { - w++; - // Copy one UTF-8 character. - if ((*i & 0xe0) == 0xc0) { - t += *i++; - if (i != s.end() && ((*i & 0xc0) == 0x80)) t += *i++; - } else if ((*i & 0xf0) == 0xe0) { - t += *i++; - if (i != s.end() && ((*i & 0xc0) == 0x80)) { - t += *i++; - if (i != s.end() && ((*i & 0xc0) == 0x80)) t += *i++; - } - } else if ((*i & 0xf8) == 0xf0) { - t += *i++; - if (i != s.end() && ((*i & 0xc0) == 0x80)) { - t += *i++; - if (i != s.end() && ((*i & 0xc0) == 0x80)) { - t += *i++; - if (i != s.end() && ((*i & 0xc0) == 0x80)) t += *i++; - } - } - } else - t += *i++; - } - } - - return t; -} - - constexpr char base64Chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; std::string base64Encode(std::string_view s) @@ -1630,25 +1553,6 @@ std::pair<std::string_view, std::string_view> getLine(std::string_view s) ////////////////////////////////////////////////////////////////////// -static Sync<std::pair<unsigned short, unsigned short>> windowSize{{0, 0}}; - - -void updateWindowSize() -{ - struct winsize ws; - if (ioctl(2, TIOCGWINSZ, &ws) == 0) { - auto windowSize_(windowSize.lock()); - windowSize_->first = ws.ws_row; - windowSize_->second = ws.ws_col; - } -} - - -std::pair<unsigned short, unsigned short> getWindowSize() -{ - return *windowSize.lock(); -} - rlim_t savedStackSize = 0; diff --git a/src/libutil/util.hh b/src/libutil/util.hh index 151da25b9..1ce7e8312 100644 --- a/src/libutil/util.hh +++ b/src/libutil/util.hh @@ -726,23 +726,6 @@ constexpr char treeLast[] = "└───"; constexpr char treeLine[] = "│ "; constexpr char treeNull[] = " "; -/** - * Determine whether ANSI escape sequences are appropriate for the - * present output. - */ -bool shouldANSI(); - -/** - * Truncate a string to 'width' printable characters. If 'filterAll' - * is true, all ANSI escape sequences are filtered out. Otherwise, - * some escape sequences (such as colour setting) are copied but not - * included in the character count. Also, tabs are expanded to - * spaces. - */ -std::string filterANSIEscapes(std::string_view s, - bool filterAll = false, - unsigned int width = std::numeric_limits<unsigned int>::max()); - /** * Base64 encoding/decoding. @@ -841,14 +824,6 @@ struct MaintainCount /** - * @return the number of rows and columns of the terminal. - */ -std::pair<unsigned short, unsigned short> getWindowSize(); - -void updateWindowSize(); - - -/** * Used in various places. */ typedef std::function<bool(const Path & path)> PathFilter; |