14 #include <sys/ioctl.h>
15 #include <sys/types.h>
17 #include <boost/lexical_cast.hpp>
18 #include <boost/regex.hpp>
19 #include <boost/tokenizer.hpp>
21 #include <fmt/format.h>
27 : m_state(STATE_ESCAPE)
36 using Tokenizer = boost::tokenizer<boost::char_separator<char>>;
38 boost::char_separator<char> sep(
";");
39 Tokenizer tok(str, sep);
41 for(Tokenizer::iterator it = tok.begin(); it != tok.end(); ++it)
44 auto endptr =
const_cast<char*
>(it->c_str());
45 int code = strtoul(it->c_str(), &endptr, 10);
47 if(errno != 0 || *endptr != 0)
60 else if(code >= 30 && code <= 37)
61 m_fgColor = code - 30;
62 else if(code >= 40 && code <= 47)
63 m_bgColor = code - 40;
84 m_state = STATE_ESCAPE;
89 parseSetAttributes(m_buf);
90 m_state = STATE_ESCAPE;
95 if(m_buf.length() >= 16)
96 m_state = STATE_ESCAPE;
110 if(m_fgColor >= 0 && m_bgColor >= 0)
117 else if(m_bgColor >= 0)
128 char* overrideMode = getenv(
"ROSBAG_FANCY_COLOR_MODE");
129 const char* termOverride =
nullptr;
132 if(strcasecmp(overrideMode,
"truecolor") == 0)
134 termOverride =
"xterm-256color";
138 else if(strcasecmp(overrideMode,
"256colors") == 0)
140 termOverride =
"xterm-256color";
144 else if(strcasecmp(overrideMode,
"ansi") == 0)
151 fmt::print(stderr,
"Warning: Unknown ROSBAG_FANCY_COLOR_MODE value: '{}'\n", overrideMode);
157 if(getenv(
"KONSOLE_DBUS_SESSION"))
166 char* vte_version = getenv(
"VTE_VERSION");
167 if(vte_version && boost::lexical_cast<unsigned int>(vte_version) >= 3600)
175 if(setupterm(termOverride, STDOUT_FILENO, &ret) != OK)
177 fmt::print(
"Could not setup the terminal. Disabling all colors...\n");
186 int num_colors = tigetnum(
"colors");
191 const char* bgColor = tigetstr(
"setab");
192 if(bgColor && bgColor != (
char*)-1)
195 fmt::print(
"Your terminal does not support ANSI background!\n");
198 const char* fgColor = tigetstr(
"setaf");
199 if(fgColor && fgColor != (
char*)-1)
202 fmt::print(
"Your terminal does not support ANSI foreground!\n");
212 auto registerKey = [&](
const char* name,
SpecialKey key,
const std::string& fallback =
""){
213 char* code = tigetstr(name);
216 if(code && code !=
reinterpret_cast<char*
>(-1))
218 else if(!fallback.empty())
223 for(
int i = 0; i < 12; ++i)
235 registerKey(key_up,
SK_Up,
"\033[A");
236 registerKey(key_down,
SK_Down,
"\033[B");
237 registerKey(key_right,
SK_Right,
"\033[C");
238 registerKey(key_left,
SK_Left,
"\033[D");
251 putp(tigetstr(
"civis"));
259 putp(tigetstr(
"cnorm"));
264 int r = (rgb & 0xFF);
265 int g = (rgb >> 8) & 0xFF;
266 int b = (rgb >> 16) & 0xFF;
272 return 16 + 36 * r + 6 * g + b;
283 snprintf(buf,
sizeof(buf),
"\033[48;2;%d;%d;%dm", color & 0xFF, (color >> 8) & 0xFF, (color >> 16) & 0xFF);
301 snprintf(buf,
sizeof(buf),
"\033[38;2;%d;%d;%dm", color & 0xFF, (color >> 8) & 0xFF, (color >> 16) & 0xFF);
315 if(tcgetattr(STDIN_FILENO, &ios) == 0)
320 ios.c_lflag |= ICANON;
324 ios.c_lflag &= ~ECHO;
325 ios.c_lflag &= ~ICANON;
328 tcsetattr(STDIN_FILENO, TCSANOW, &ios);
390 putp(tparm(
m_upStr.c_str(), numLines));
401 if(ioctl(STDIN_FILENO, TIOCGWINSZ, &w) == 0)
403 *outColumns = w.ws_col;
416 snprintf(buf,
sizeof(buf),
"\033]30;%s\007", title.c_str());
420 snprintf(buf,
sizeof(buf),
"\033k%s\033\\", title.c_str());
426 fputs(
"\033]30;%d : %n\007", stdout);
429 fmt::print(
"\033k{}\033\\", backup);
448 if(read(STDIN_FILENO, &c, 1) != 1)
464 bool completeMatch =
false;
474 lastMatch = pair.second;
478 completeMatch =
true;
489 else if(completeMatch)