嗯。调试时总发现自己打印的调试信息太过普通、单调,于是乎……
Notice
要在终端实现字体的特殊样式,通常通过使用特殊的控制字符来实现,而不是通过某语言本身的功能来实现。
在大多数终端中,可以使用 ANSI 转义序列来设置字体的颜色。ANSI 转义序列是一系列以 ESC 开头的字符,用于控制文本终端的属性,包括颜色、格式和光标位置等。ANSI 转义序列以 \033[ 开头,后跟属性代码,以设置不同的终端属性。
请注意,不同的终端可能对 ANSI 转义序列的支持程度不同。大多数 Unix/Linux 终端和 Windows 上的一些控制台仿真器(如 ConEmu、Cygwin 和 Windows Terminal)都支持 ANSI 转义序列。
Color
包括前景色和背景色。前景色指的是字体本身的颜色,背景色指的是字体的背景颜色。
一些常见颜色:黑色、红色、绿色、黄色、蓝色、洋红色、青色、白色。
先来看一下效果:
#define
见名知意,不再赘述。
#define ANSI_COLOR_RESET "\x1b[0m" // 重置
#define ANSI_COLOR_BLACK "\033[30m" // 前景色
#define ANSI_COLOR_RED "\x1b[31m"
#define ANSI_COLOR_GREEN "\x1b[32m"
#define ANSI_COLOR_YELLOW "\x1b[33m"
#define ANSI_COLOR_BLUE "\x1b[34m"
#define ANSI_COLOR_MAGENTA "\x1b[35m"
#define ANSI_COLOR_CYAN "\x1b[36m"
#define ANSI_COLOR_WHITE "\033[37m"
#define ANSI_BG_BLACK "\x1b[40m" // 背景色
#define ANSI_BG_RED "\x1b[41m"
#define ANSI_BG_GREEN "\x1b[42m"
#define ANSI_BG_YELLOW "\x1b[43m"
#define ANSI_BG_BLUE "\x1b[44m"
#define ANSI_BG_MAGENTA "\x1b[45m"
#define ANSI_BG_CYAN "\x1b[46m"
#define ANSI_BG_WHITE "\x1b[47m"
#define ANSI_COLOR_BRIGHT_BLACK "\x1b[90m" // 前景亮色
#define ANSI_COLOR_BRIGHT_RED "\x1b[91m"
#define ANSI_COLOR_BRIGHT_GREEN "\x1b[92m"
#define ANSI_COLOR_BRIGHT_YELLOW "\x1b[93m"
#define ANSI_COLOR_BRIGHT_BLUE "\x1b[94m"
#define ANSI_COLOR_BRIGHT_MAGENTA "\x1b[95m"
#define ANSI_COLOR_BRIGHT_CYAN "\x1b[96m"
#define ANSI_COLOR_BRIGHT_WHITE "\x1b[97m"
#define ANSI_BG_BRIGHT_BLACK "\x1b[100m" // 背景亮色
#define ANSI_BG_BRIGHT_RED "\x1b[101m"
#define ANSI_BG_BRIGHT_GREEN "\x1b[102m"
#define ANSI_BG_BRIGHT_YELLOW "\x1b[103m"
#define ANSI_BG_BRIGHT_BLUE "\x1b[104m"
#define ANSI_BG_BRIGHT_MAGENTA "\x1b[105m"
#define ANSI_BG_BRIGHT_CYAN "\x1b[106m"
#define ANSI_BG_BRIGHT_WHITE "\x1b[107m"
Example
#include <iostream>
// 有的宏定义没有用到,但懒得删掉了 ×_×
#define ANSI_COLOR_BLACK "\033[30m"
#define ANSI_COLOR_RED "\x1b[31m"
#define ANSI_COLOR_GREEN "\x1b[32m"
#define ANSI_COLOR_YELLOW "\x1b[33m"
#define ANSI_COLOR_BLUE "\x1b[34m"
#define ANSI_COLOR_MAGENTA "\x1b[35m"
#define ANSI_COLOR_CYAN "\x1b[36m"
#define ANSI_COLOR_WHITE "\033[37m"
#define ANSI_COLOR_RESET "\x1b[0m"
#define ANSI_BG_BLACK "\x1b[40m"
#define ANSI_BG_RED "\x1b[41m"
#define ANSI_BG_GREEN "\x1b[42m"
#define ANSI_BG_YELLOW "\x1b[43m"
#define ANSI_BG_BLUE "\x1b[44m"
#define ANSI_BG_MAGENTA "\x1b[45m"
#define ANSI_BG_CYAN "\x1b[46m"
#define ANSI_BG_WHITE "\x1b[47m"
#define ANSI_COLOR_BRIGHT_RED "\x1b[91m"
#define ANSI_COLOR_BRIGHT_GREEN "\x1b[92m"
#define ANSI_COLOR_BRIGHT_YELLOW "\x1b[93m"
#define ANSI_COLOR_BRIGHT_BLUE "\x1b[94m"
#define ANSI_COLOR_BRIGHT_MAGENTA "\x1b[95m"
#define ANSI_COLOR_BRIGHT_CYAN "\x1b[96m"
#define ANSI_COLOR_BRIGHT_WHITE "\x1b[97m"
#define ANSI_BG_BRIGHT_BLACK "\x1b[100m"
int main() {
std::cout << "\033[31mThis text will be red. \033[0m" << std::endl;
std::cout << "\x1b[33mThis text will be yellow. \033[0m" << std::endl;
std::cout << ANSI_COLOR_RED << ANSI_BG_YELLOW << "Hello, world!" << ANSI_COLOR_RESET << std::endl;
std::cout << ANSI_BG_GREEN << ANSI_BG_MAGENTA << "¡Hola, mundo!" << ANSI_COLOR_RESET << std::endl;
std::cout << ANSI_BG_YELLOW << ANSI_BG_CYAN << "Hallo, welt!" << ANSI_COLOR_RESET << std::endl;
std::cout << ANSI_COLOR_BRIGHT_BLUE << "Your future will be bright!" << ANSI_COLOR_RESET << std::endl;
std::cout << ANSI_COLOR_BLUE << "Your future will be bright!" << ANSI_COLOR_RESET << std::endl;
std::cout << ANSI_COLOR_WHITE << "This is white. " << ANSI_COLOR_RESET << std::endl;
std::cout << ANSI_COLOR_BRIGHT_WHITE << "This is bright white. " << ANSI_COLOR_RESET << std::endl;
std::cout << ANSI_COLOR_WHITE << ANSI_BG_BRIGHT_BLACK << "BrightBlack. " << ANSI_COLOR_RESET << std::endl;
std::cout << ANSI_COLOR_WHITE << ANSI_BG_BLACK << "Black. " << ANSI_COLOR_RESET << std::endl;
return 0;
}
outcome
实现效果如下:
ROS_INFO
那么如何使用 ROS_INFO 来输出彩色字体呢?
// 创建一个字符串流
std::stringstream ss;
// 向字符串流中添加需要的信息和 ANSI 转义序列
ss << "\x1b[31m\x1b[43m" << "Hello, world!" << "\x1b[0m";
// 使用 ROS_INFO 输出字符串流中的内容
ROS_INFO("%s", ss.str().c_str());
以上代码来自 GPT。但保险起见,在向流中添加信息和转义序列时,尤其需要反复使用同一字符串流时,最好先执行以下操作:
ss.str("");
Bold & Underline
#define
见名知意,不再赘述。
#define ANSI_BOLD_ON "\x1b[1m"
#define ANSI_BOLD_OFF "\x1b[22m"
#define ANSI_UNDERLINE_ON "\x1b[4m"
#define ANSI_UNDERLINE_OFF "\x1b[24m"
#define ANSI_COLOR_RESET "\x1b[0m"
Example
#include <iostream>
// ANSI 转义序列,用于设置字体加粗和取消加粗
#define ANSI_BOLD_ON "\x1b[1m"
#define ANSI_BOLD_OFF "\x1b[22m"
// ANSI 转义序列,用于设置下划线和取消下划线
#define ANSI_UNDERLINE_ON "\x1b[4m"
#define ANSI_UNDERLINE_OFF "\x1b[24m"
// ANSI 转义序列,用于重置终端颜色
#define ANSI_COLOR_RESET "\x1b[0m"
int main() {
// 输出加粗文字
std::cout << ANSI_BOLD_ON << "Bold Text" << ANSI_COLOR_RESET << std::endl;
// 输出带下划线的文字
std::cout << ANSI_UNDERLINE_ON << "Underlined Text" << ANSI_COLOR_RESET << std::endl;
return 0;
}
outcome
实现效果如下:
ROS_INFO
同上。
Other styles
#define
见名知意,不再赘述。
#define ANSI_BLINK_ON "\x1b[5m" // 开启闪烁
#define ANSI_BLINK_OFF "\x1b[25m" // 关闭闪烁
#define ANSI_REVERSE_ON "\x1b[7m" // 开启反显
#define ANSI_REVERSE_OFF "\x1b[27m" // 关闭反显
#define ANSI_HIDDEN_ON "\x1b[8m" // 开启隐藏
#define ANSI_HIDDEN_OFF "\x1b[28m" // 关闭隐藏
#define ANSI_STRIKETHROUGH "\x1b[9m" // 开启删除线
#define ANSI_STRIKETHROUGH "\x1b[99m" // 关闭删除线
#define ANSI_RESET "\x1b[0m"
Example
#include <iostream>
// ANSI 转义序列,用于设置终端效果
#define ANSI_BLINK_ON "\x1b[5m" // 开启闪烁
#define ANSI_BLINK_OFF "\x1b[25m" // 关闭闪烁
#define ANSI_REVERSE_ON "\x1b[7m" // 开启反显
#define ANSI_REVERSE_OFF "\x1b[27m" // 关闭反显
#define ANSI_HIDDEN_ON "\x1b[8m" // 开启隐藏
#define ANSI_HIDDEN_OFF "\x1b[28m" // 关闭隐藏
#define ANSI_STRIKETHROUGH "\x1b[9m" // 开启删除线
// ANSI 转义序列,用于重置终端效果
#define ANSI_RESET "\x1b[0m"
int main() {
// 闪烁效果
std::cout << ANSI_BLINK_ON << "Blinking Text" << ANSI_RESET << std::endl;
std::cout << ANSI_BLINK_OFF << "No Blinking Text" << ANSI_RESET << std::endl;
// 反显效果
std::cout << ANSI_REVERSE_ON << "Reversed Text" << ANSI_RESET << std::endl;
std::cout << ANSI_REVERSE_OFF << "No Reversed Text" << ANSI_RESET << std::endl;
// 隐藏效果
std::cout << ANSI_HIDDEN_ON << "Hidden Text" << ANSI_RESET << std::endl;
std::cout << ANSI_HIDDEN_OFF << "No Hidden Text" << ANSI_RESET << std::endl;
// 删除线效果
std::cout << ANSI_STRIKETHROUGH << "Strikethrough Text" << ANSI_RESET << std::endl;
return 0;
}
outcome
实现效果如下:
ROS_INFO
#include <ros/ros.h>
#include <sstream>
// 自定义的打印函数,用于在ROS_INFO中使用特定标记实现效果
void customInfo(const std::string& message) {
std::cout << message << std::endl;
}
int main(int argc, char** argv) {
ros::init(argc, argv, "example_node");
ros::NodeHandle nh;
// 创建一个字符串流
std::stringstream ss;
// 向字符串流中添加需要的信息,并使用特定标记来表示效果
ss << "[blink]Hello, world![/blink] ";
ss << "[reverse]Reversed Text[/reverse] ";
ss << "[hidden]Hidden Text[/hidden] ";
ss << "[strikethrough]Strikethrough Text[/strikethrough]";
// 使用自定义的打印函数打印信息
customInfo(ss.str());
ros::spin();
return 0;
}
Combination
以上(并不互相冲突的)诸多效果可组合使用。略。