forked from lix-project/lix
util.{hh,cc}: Split out terminal.{hh,cc}
Change-Id: I9de2296b4012d50f540124001d54d6ca3be4c6da
This commit is contained in:
parent
6fd6795bc4
commit
81bdf8d2d6
|
@ -1,6 +1,7 @@
|
|||
#include "markdown.hh"
|
||||
#include "util.hh"
|
||||
#include "finally.hh"
|
||||
#include "terminal.hh"
|
||||
|
||||
#include <sys/queue.h>
|
||||
#include <lowdown.h>
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "fetchers.hh"
|
||||
#include "finally.hh"
|
||||
#include "fetch-settings.hh"
|
||||
#include "terminal.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "english.hh"
|
||||
#include "signals.hh"
|
||||
#include "eval.hh"
|
||||
#include "terminal.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "sync.hh"
|
||||
#include "store-api.hh"
|
||||
#include "names.hh"
|
||||
#include "terminal.hh"
|
||||
|
||||
#include <atomic>
|
||||
#include <map>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "environment-variables.hh"
|
||||
#include "error.hh"
|
||||
#include "position.hh"
|
||||
#include "terminal.hh"
|
||||
|
||||
#include <iostream>
|
||||
#include <optional>
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "config.hh"
|
||||
#include "source-path.hh"
|
||||
#include "position.hh"
|
||||
#include "terminal.hh"
|
||||
|
||||
#include <atomic>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "util.hh"
|
||||
#include "error.hh"
|
||||
#include "sync.hh"
|
||||
#include "terminal.hh"
|
||||
|
||||
#include <thread>
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
#include "suggestions.hh"
|
||||
#include "ansicolor.hh"
|
||||
#include "util.hh"
|
||||
#include "terminal.hh"
|
||||
|
||||
#include <algorithm>
|
||||
#include <ostream>
|
||||
|
||||
namespace nix {
|
||||
|
||||
|
|
104
src/libutil/terminal.cc
Normal file
104
src/libutil/terminal.cc
Normal file
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
40
src/libutil/terminal.hh
Normal file
40
src/libutil/terminal.hh
Normal file
|
@ -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();
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
@ -840,14 +823,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.
|
||||
*/
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "util.hh"
|
||||
#include "types.hh"
|
||||
#include "terminal.hh"
|
||||
|
||||
#include <limits.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
|
Loading…
Reference in a new issue