From 5a968cdecfa07055df48081e2175e81686547c05 Mon Sep 17 00:00:00 2001 From: Your Name Date: Wed, 19 Jan 2022 20:27:30 +0100 Subject: [PATCH] Added color support and screen functions. --- include/AnsiTerminal.hpp | 30 +++++ include/Display.hpp | 26 ++++ src/Display.cpp | 50 ++++++- src/main.cpp | 282 ++++++++++++++++++++++++--------------- 4 files changed, 279 insertions(+), 109 deletions(-) create mode 100644 include/AnsiTerminal.hpp diff --git a/include/AnsiTerminal.hpp b/include/AnsiTerminal.hpp new file mode 100644 index 0000000..c1ab36e --- /dev/null +++ b/include/AnsiTerminal.hpp @@ -0,0 +1,30 @@ +#ifndef H_AnsiTerminal +#define H_AnsiTerminal + +// The following are UBUNTU/LINUX, and MacOS ONLY terminal color codes. +#define C_RESET "\033[0m" // Reset formatting +#define C_BOLD "\033[1m" // Bold font +#define C_UNDERLINE "\033[4m" // Underline font +#define C_INVERT_FG_BG "\033[7m" // Inverse background and foregroung colors + +// Foreground +#define C_BLACK_F "\033[30m" // Black +#define C_RED_F "\033[31m" // Red +#define C_GREEN_F "\033[32m" // Green +#define C_YELLOW_F "\033[33m" // Yellow +#define C_BLUE_F "\033[34m" // Blue +#define C_MAGENTA_F "\033[35m" // Magenta +#define C_CYAN_F "\033[36m" // Cyan +#define C_WHITE_F "\033[37m" // White + +// Background +#define C_BLACK_B "\033[40m" // Black +#define C_RED_B "\033[41m" // Red +#define C_GREEN_B "\033[42m" // Green +#define C_YELLOW_B "\033[43m" // Yellow +#define C_BLUE_B "\033[44m" // Blue +#define C_MAGENTA_B "\033[45m" // Magenta +#define C_CYAN_B "\033[46m" // Cyan +#define C_WHITE_B "\033[47m" // White + +#endif diff --git a/include/Display.hpp b/include/Display.hpp index abb0270..b241a3f 100644 --- a/include/Display.hpp +++ b/include/Display.hpp @@ -2,11 +2,14 @@ #define H_Display #include +#include #include #include //ioctl() and TIOCGWINSZ #include // for STDOUT_FILENO +#include + class Display { public: @@ -15,6 +18,27 @@ class Display unsigned int Rows() const; unsigned int Cols() const; + /// Returns a constant reference to a given line of the screen. + std::string const& GetLine(unsigned int i) const; + + /// Sets the line i to str. /!\ Warning : the line will be truncated at its max length of Cols(). + void SetLine(unsigned int i, std::string const& str); + + /// Get reference to "pixel" at row i, column j. + char & GetPixel(unsigned int i, unsigned int j); + + /// Clears all the screen lines stored within the object and recreates new empty lines of the right size. + void ClearScreenLines(); + + /// Draws all the screen lines stored within the object. You must call ClearScreen() in order to draw in-place. + void DrawScreenLines(); + + /// Updates the screen size stored internally. + void UpdateScreenSize(); + + /// Highlights the line i by inverting its colors (black on white background). + void HighlightLine(unsigned int i, bool highlight); + /// Returns a winsize structure with size.ws_row is the number of rows, size.ws_col is the number of columns. static winsize GetTerminalSize(); @@ -24,6 +48,8 @@ class Display protected: unsigned int screenRows;// lines;// #include #include +#include using std::cout; using std::cerr; using std::endl; +void runTests(int argc, char *argv[]); + int main(int argc, char *argv[]) { if(argc > 1) - { - if(0) - {// stat test - cout << "Reading '" << argv[1] << "'\n"; - struct stat s; - PRINT_VAR(stat(argv[1], &s)); - PRINT_VAR(s.st_mode); - PRINT_VAR(s.st_mode & S_IFMT); - PRINT_VAR((s.st_mode & S_IFMT) == S_IFLNK);// symbolic link - PRINT_VAR((s.st_mode & S_IFMT) == S_IFREG);// regular file - PRINT_VAR((s.st_mode & S_IFMT) == S_IFDIR);// folder - PRINT_VAR(s.st_size); - PRINT_VAR(s.st_blksize); - PRINT_VAR(s.st_blocks); - PRINT_VAR(s.st_blocks*512);// Size on disk, in bytes - } - if(0) - {// test GetNodeName() - PRINT_VAR(TreeNodeDiskUsage("/some/path/to/victory.tar.gz").GetNodeName()); - PRINT_VAR(TreeNodeDiskUsage("/some/path/to/a/folder").GetNodeName()); - PRINT_VAR(TreeNodeDiskUsage("/some/path/to/a/folder/").GetNodeName()); - PRINT_VAR(TreeNodeDiskUsage("/").GetNodeName()); - PRINT_VAR(TreeNodeDiskUsage(".").GetNodeName()); - PRINT_VAR(TreeNodeDiskUsage("..").GetNodeName()); - PRINT_VAR(TreeNodeDiskUsage("/a").GetNodeName()); - PRINT_VAR(TreeNodeDiskUsage("/a/b/c//////////").GetNodeName()); - PRINT_VAR(TreeNodeDiskUsage("/a///b//c/").GetNodeName()); - } - if(0) - {// test GetNodePath() - PRINT_VAR(TreeNodeDiskUsage("/a/b/c//////////").GetNodePath()); - PRINT_VAR(TreeNodeDiskUsage("/a///b//c/").GetNodePath()); - PRINT_VAR(TreeNodeDiskUsage("////a///b//c/").GetNodePath()); - PRINT_VAR(TreeNodeDiskUsage(" /a/b/c ").GetNodePath()); - PRINT_VAR(TreeNodeDiskUsage(" /a/b/c/// ").GetNodePath()); - PRINT_VAR(TreeNodeDiskUsage(" \\this\\\\is/sparta/// ").GetNodePath()); - PRINT_VAR(TreeNodeDiskUsage(" \\this\\\\is/sparta/with spaces// ").GetNodePath()); - } - if(0) - {// basic tree building and printing test - TreeNodeDiskUsage tree(argv[1]); - tree.BuildTree(); - tree.PrintTree(); - cout << "\n\n"; - PRINT_VAR(tree.GetTotalSize()); - PRINT_VAR(tree.GetTotalSizeOnDisk()); - cout << "\n\n"; - tree.PrintTree(0); - tree.PrintTree(1); - tree.PrintTree(2); - } - if(0) - {// terminal display functions test - Display d; - PRINT_VAR(d.Rows()); - PRINT_VAR(d.Cols()); - - d.ClearScreen(); - cout << "coucou !\n"; - } - //if(0) - {// progress bar test - // unsigned int width, unsigned int current, unsigned int total, char fillChar = 219, bool showPercentage = true - PRINT_VAR(GenerateProgressBar(20, 0, 100, false)); - PRINT_VAR(GenerateProgressBar(20, 25, 100,false)); - PRINT_VAR(GenerateProgressBar(20, 50, 100, false)); - PRINT_VAR(GenerateProgressBar(20, 75, 100, false)); - PRINT_VAR(GenerateProgressBar(20, 100, 100, false)); - PRINT_VAR(GenerateProgressBar(50, 666, 1000, false)); - - PRINT_VAR(GenerateProgressBar(20, 0, 100, true)); - PRINT_VAR(GenerateProgressBar(20, 25, 100, true)); - PRINT_VAR(GenerateProgressBar(20, 50, 100, true)); - PRINT_VAR(GenerateProgressBar(20, 75, 100, true)); - PRINT_VAR(GenerateProgressBar(20, 100, 100, true)); - PRINT_VAR(GenerateProgressBar(50, 666, 1000, true)); - PRINT_VAR(GenerateProgressBar(50, 1666, 1000, true)); - PRINT_VAR(GenerateProgressBar(50, 42, 0, true)); - PRINT_VAR(GenerateProgressBar(50, 0, 0, true)); - - PRINT_VAR(GenerateProgressBar(50, 333, 1000, true, "#")); - } - //if(0) - {// test output - PRINT_VAR(Bytes2HumanReadable(123ULL, true)); - PRINT_VAR(Bytes2HumanReadable(1234ULL, true)); - PRINT_VAR(Bytes2HumanReadable(1234567ULL, true)); - PRINT_VAR(Bytes2HumanReadable(1234567890ULL, true)); - PRINT_VAR(Bytes2HumanReadable(1234567890123ULL, true)); - PRINT_VAR(Bytes2HumanReadable(1234567890123456ULL, true)); - PRINT_VAR(Bytes2HumanReadable(1234567890123456789ULL, true)); - cout << "\n"; - PRINT_VAR(Bytes2HumanReadable(123ULL, false)); - PRINT_VAR(Bytes2HumanReadable(1234ULL, false)); - PRINT_VAR(Bytes2HumanReadable(1234567ULL, false)); - PRINT_VAR(Bytes2HumanReadable(1234567890ULL, false)); - PRINT_VAR(Bytes2HumanReadable(1234567890123ULL, false)); - PRINT_VAR(Bytes2HumanReadable(1234567890123456ULL, false)); - PRINT_VAR(Bytes2HumanReadable(1234567890123456789ULL, false)); - cout << "\n"; - PRINT_VAR(Bytes2HumanReadable(1073741824ULL, true)); - PRINT_VAR(Bytes2HumanReadable(1073741824ULL, false)); - PRINT_VAR(Bytes2HumanReadable(1000000000ULL, true)); - PRINT_VAR(Bytes2HumanReadable(1000000000ULL, false)); - - } - } + runTests(argc, argv); else cerr << "Error : No path given !\n"; return 0; } + +void runTests(int /* argc */, char *argv[]) +{ + if(0) + {// stat test + cout << "Reading '" << argv[1] << "'\n"; + struct stat s; + PRINT_VAR(stat(argv[1], &s)); + PRINT_VAR(s.st_mode); + PRINT_VAR(s.st_mode & S_IFMT); + PRINT_VAR((s.st_mode & S_IFMT) == S_IFLNK);// symbolic link + PRINT_VAR((s.st_mode & S_IFMT) == S_IFREG);// regular file + PRINT_VAR((s.st_mode & S_IFMT) == S_IFDIR);// folder + PRINT_VAR(s.st_size); + PRINT_VAR(s.st_blksize); + PRINT_VAR(s.st_blocks); + PRINT_VAR(s.st_blocks*512);// Size on disk, in bytes + } + if(0) + {// test GetNodeName() + PRINT_VAR(TreeNodeDiskUsage("/some/path/to/victory.tar.gz").GetNodeName()); + PRINT_VAR(TreeNodeDiskUsage("/some/path/to/a/folder").GetNodeName()); + PRINT_VAR(TreeNodeDiskUsage("/some/path/to/a/folder/").GetNodeName()); + PRINT_VAR(TreeNodeDiskUsage("/").GetNodeName()); + PRINT_VAR(TreeNodeDiskUsage(".").GetNodeName()); + PRINT_VAR(TreeNodeDiskUsage("..").GetNodeName()); + PRINT_VAR(TreeNodeDiskUsage("/a").GetNodeName()); + PRINT_VAR(TreeNodeDiskUsage("/a/b/c//////////").GetNodeName()); + PRINT_VAR(TreeNodeDiskUsage("/a///b//c/").GetNodeName()); + } + if(0) + {// test GetNodePath() + PRINT_VAR(TreeNodeDiskUsage("/a/b/c//////////").GetNodePath()); + PRINT_VAR(TreeNodeDiskUsage("/a///b//c/").GetNodePath()); + PRINT_VAR(TreeNodeDiskUsage("////a///b//c/").GetNodePath()); + PRINT_VAR(TreeNodeDiskUsage(" /a/b/c ").GetNodePath()); + PRINT_VAR(TreeNodeDiskUsage(" /a/b/c/// ").GetNodePath()); + PRINT_VAR(TreeNodeDiskUsage(" \\this\\\\is/sparta/// ").GetNodePath()); + PRINT_VAR(TreeNodeDiskUsage(" \\this\\\\is/sparta/with spaces// ").GetNodePath()); + } + if(0) + {// basic tree building and printing test + TreeNodeDiskUsage tree(argv[1]); + tree.BuildTree(); + tree.PrintTree(); + cout << "\n\n"; + PRINT_VAR(tree.GetTotalSize()); + PRINT_VAR(tree.GetTotalSizeOnDisk()); + cout << "\n\n"; + tree.PrintTree(0); + tree.PrintTree(1); + tree.PrintTree(2); + } + if(0) + {// terminal display functions test + Display d; + PRINT_VAR(d.Rows()); + PRINT_VAR(d.Cols()); + + d.ClearScreen(); + cout << "coucou !\n"; + } + if(0) + {// progress bar test + // unsigned int width, unsigned int current, unsigned int total, char fillChar = 219, bool showPercentage = true + PRINT_VAR(GenerateProgressBar(20, 0, 100, false)); + PRINT_VAR(GenerateProgressBar(20, 25, 100,false)); + PRINT_VAR(GenerateProgressBar(20, 50, 100, false)); + PRINT_VAR(GenerateProgressBar(20, 75, 100, false)); + PRINT_VAR(GenerateProgressBar(20, 100, 100, false)); + PRINT_VAR(GenerateProgressBar(50, 666, 1000, false)); + + PRINT_VAR(GenerateProgressBar(20, 0, 100, true)); + PRINT_VAR(GenerateProgressBar(20, 25, 100, true)); + PRINT_VAR(GenerateProgressBar(20, 50, 100, true)); + PRINT_VAR(GenerateProgressBar(20, 75, 100, true)); + PRINT_VAR(GenerateProgressBar(20, 100, 100, true)); + PRINT_VAR(GenerateProgressBar(50, 666, 1000, true)); + PRINT_VAR(GenerateProgressBar(50, 1666, 1000, true)); + PRINT_VAR(GenerateProgressBar(50, 42, 0, true)); + PRINT_VAR(GenerateProgressBar(50, 0, 0, true)); + + PRINT_VAR(GenerateProgressBar(50, 333, 1000, true, "#")); + } + if(0) + {// test output + PRINT_VAR(Bytes2HumanReadable(123ULL, true)); + PRINT_VAR(Bytes2HumanReadable(1234ULL, true)); + PRINT_VAR(Bytes2HumanReadable(1234567ULL, true)); + PRINT_VAR(Bytes2HumanReadable(1234567890ULL, true)); + PRINT_VAR(Bytes2HumanReadable(1234567890123ULL, true)); + PRINT_VAR(Bytes2HumanReadable(1234567890123456ULL, true)); + PRINT_VAR(Bytes2HumanReadable(1234567890123456789ULL, true)); + cout << "\n"; + PRINT_VAR(Bytes2HumanReadable(123ULL, false)); + PRINT_VAR(Bytes2HumanReadable(1234ULL, false)); + PRINT_VAR(Bytes2HumanReadable(1234567ULL, false)); + PRINT_VAR(Bytes2HumanReadable(1234567890ULL, false)); + PRINT_VAR(Bytes2HumanReadable(1234567890123ULL, false)); + PRINT_VAR(Bytes2HumanReadable(1234567890123456ULL, false)); + PRINT_VAR(Bytes2HumanReadable(1234567890123456789ULL, false)); + cout << "\n"; + PRINT_VAR(Bytes2HumanReadable(1073741824ULL, true)); + PRINT_VAR(Bytes2HumanReadable(1073741824ULL, false)); + PRINT_VAR(Bytes2HumanReadable(1000000000ULL, true)); + PRINT_VAR(Bytes2HumanReadable(1000000000ULL, false)); + + } + //if(0) + {// test screen functions + Display d; + PRINT_VAR(d.Rows()); + PRINT_VAR(d.Cols()); + PRINT_VAR(d.GetLine(0)); + PRINT_VAR(d.GetLine(0).size()); + + d.GetPixel(5,5) = '#'; + d.GetPixel(6,6) = '#'; + d.GetPixel(7,7) = '#'; + d.GetPixel(20,50) = '#'; + + d.SetLine(4, "Coucou !"); + d.SetLine(10, "------------------------- Coucou ! ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------"); + d.SetLine(11, "------------------------- Inverted -------------------------"); + d.HighlightLine(11, true); + d.SetLine(12, " That's normal, bro. Really !"); + + Display::ClearScreen(); + d.DrawScreenLines(); + + PRINT_VAR(d.GetLine(12).size()); + d.HighlightLine(12, true); + PRINT_VAR(d.GetLine(12).size()); + d.HighlightLine(12, true); + PRINT_VAR(d.GetLine(12).size()); + d.HighlightLine(12, false); + PRINT_VAR(d.GetLine(12).size()); + PRINT_VAR(d.GetLine(12)); + PRINT_VAR(std::string(C_INVERT_FG_BG).size()); + } + if(0) + {// test terminal colors + cout << C_BLUE_F << "blue" << "\n"; + cout << C_CYAN_F << "cyan" << "\n"; + cout << C_YELLOW_F << "yellow" << "\n"; + cout << C_WHITE_F << "white" << "\n"; + cout << C_RED_F << "red" << "\n"; + cout << C_GREEN_F << "green" << "\n"; + cout << C_BLACK_F << "black" << "\n"; + cout << C_RESET << "Normal" << "\n"; + cout << C_BOLD << "Bold text." << C_RESET << " Normal text." << "\n"; + + cout << C_BLUE_B << C_YELLOW_F << "Hard on the eyes..." << C_RESET << "\n"; + cout << C_UNDERLINE << "underlined" << C_RESET << "\n"; + cout << C_INVERT_FG_BG << "inverted" << C_RESET << "\n"; + + cout << "\n\n"; + + {// Nice color table + int i, j, n; + for (i = 0; i < 11; i++) { + for (j = 0; j < 10; j++) { + n = 10 * i + j; + if (n > 107) break; + printf("\033[%dm %3d\033[m", n, n); + } + printf("\n"); + } + } + } +} \ No newline at end of file