public
Last active

  • Download Gist
highlight.cpp
C++
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
/*
* 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;
}

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.