Created
October 29, 2012 23:45
-
-
Save mythagel/3977405 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* highlight.cpp | |
* | |
* Created on: Nov 23, 2011 | |
* Author: mythagel | |
* | |
* A quickly hacked up console text highlighting tool. | |
* | |
* g++ -O3 highlight.cpp -static -o highlight | |
* | |
* License: Public Domain. | |
*/ | |
#include <map> | |
#include <iostream> | |
#include <string> | |
#include <cstring> | |
#include <cstdlib> | |
#include <cstdio> | |
#include <unistd.h> | |
#include <fstream> | |
#include <regex.h> | |
#include <utility> | |
#include <vector> | |
// Terminal colour code adapted from http://tldp.org/LDP/LGNET/65/padala.html | |
static const int RESET = 0; | |
static const int BRIGHT = 1; | |
static const int DIM = 2; | |
static const int UNDERLINE = 3; | |
static const int BLINK = 4; | |
static const int REVERSE = 7; | |
static const int HIDDEN = 8; | |
static const int NONE = -1; | |
static const int BLACK = 0; | |
static const int RED = 1; | |
static const int GREEN = 2; | |
static const int YELLOW = 3; | |
static const int BLUE = 4; | |
static const int MAGENTA = 5; | |
static const int CYAN = 6; | |
static const int WHITE = 7; | |
void textcolor(int attr, int fg, int bg); | |
std::string clr(int attr, int fg, int bg); | |
std::pair<std::string::size_type, std::string::size_type> regex_bounds(const std::string& value, const std::string& pattern); | |
struct Colour | |
{ | |
int colour; | |
int attr; | |
Colour() | |
: colour(RED), attr(BRIGHT) | |
{ | |
} | |
Colour(int c, int a) | |
: colour(c), attr(a) | |
{ | |
} | |
}; | |
int main(int argc, char* argv[]) | |
{ | |
std::map<std::string, Colour> Highlights; | |
int CurrentAttr = BRIGHT; | |
int CurrentColour = RED; | |
for(int i = 1; i < argc; ++i) | |
{ | |
Highlights[argv[i]] = Colour(CurrentColour++, CurrentAttr); | |
if(CurrentColour > CYAN) | |
{ | |
CurrentColour = RED; | |
++CurrentAttr; | |
} | |
if(CurrentAttr > REVERSE) | |
CurrentAttr = BRIGHT; | |
} | |
for(std::map<std::string, Colour>::const_iterator it = Highlights.begin(); it != Highlights.end(); ++it) | |
{ | |
std::string set_str = clr(it->second.attr, it->second.colour, NONE); | |
std::string clr_str = clr(RESET, 0, 0); | |
fprintf(stdout, "Highlighting: %s%s%s\n", set_str.c_str(), it->first.c_str(), clr_str.c_str()); | |
} | |
std::string line; | |
while(getline(std::cin, line)) | |
{ | |
// TODO overlapping colours | |
for(std::map<std::string, Colour>::const_iterator it = Highlights.begin(); it != Highlights.end(); ++it) | |
{ | |
std::pair<std::string::size_type, std::string::size_type> bounds = regex_bounds(line, it->first); | |
if(bounds.first != std::string::npos) | |
{ | |
std::string set_str = clr(it->second.attr, it->second.colour, NONE); | |
std::string clr_str = clr(RESET, 0, 0); | |
line.insert(bounds.first, set_str); | |
line.insert(bounds.second+set_str.size(), clr_str); | |
} | |
} | |
fprintf(stdout, "%s\n", line.c_str()); | |
} | |
return 0; | |
} | |
void textcolor(int attr, int fg, int bg) | |
{ | |
fprintf(stderr, "%s", clr(attr, fg, bg).c_str()); | |
} | |
std::string clr(int attr, int fg, int bg) | |
{ | |
char command[13]; | |
/* Command is the control command to the terminal */ | |
if(attr == RESET) | |
snprintf(command, 13, "%c[%d;;m", 0x1B, attr); | |
else | |
{ | |
if(bg == NONE) | |
snprintf(command, 13, "%c[%d;%dm", 0x1B, attr, fg + 30); | |
else | |
snprintf(command, 13, "%c[%d;%d;%dm", 0x1B, attr, fg + 30, bg + 40); | |
} | |
return command; | |
} | |
std::pair<std::string::size_type, std::string::size_type> regex_bounds(const std::string& value, const std::string& pattern) | |
{ | |
std::pair<std::string::size_type, std::string::size_type> result_bounds = std::make_pair(std::string::npos, std::string::npos); | |
regex_t *regex; | |
regex = (regex_t *) malloc(sizeof(regex_t)); | |
memset(regex, '\0', sizeof(regex_t)); | |
int res = regcomp(regex, pattern.c_str(), 0); | |
if(res != 0) | |
{ | |
size_t length; | |
char *buffer; | |
length = regerror (res, regex, NULL, 0); | |
buffer = (char *)malloc(length); | |
regerror (res, regex, buffer, length); | |
fprintf(stderr, "Pattern '%s' is Invalid: %s\n", pattern.c_str(), buffer); | |
free(buffer); | |
regfree(regex); | |
return result_bounds; | |
} | |
size_t no_sub = regex->re_nsub+1; | |
regmatch_t *result; | |
result = (regmatch_t *) malloc(sizeof(regmatch_t) * no_sub); | |
memset(result, '\0', sizeof(regmatch_t)); | |
if(regexec(regex, value.c_str(), no_sub, result, 0)==0) | |
{ | |
regoff_t lower(value.size()); | |
regoff_t upper(0); | |
for(unsigned int i = 0; i < no_sub; ++i) | |
{ | |
if(result[i].rm_so < lower) | |
lower = result[i].rm_so; | |
if(result[i].rm_eo > upper) | |
upper = result[i].rm_eo; | |
} | |
result_bounds = std::make_pair(lower, upper); | |
} | |
free(result); result = NULL; | |
regfree(regex); | |
free(regex); regex = NULL; | |
return result_bounds; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment