Skip to content

Embed URL

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
/*
* 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
Something went wrong with that request. Please try again.