Skip to content

Commit

Permalink
use much faster regexp for ansi coloring
Browse files Browse the repository at this point in the history
ansispan function adapted from mmalecki/ansispan

The easiest way to see how slow the old way was is to create a very large traceback (e.g. max recursion), which bring everything to a screeching halt (even future page loads, if the output is saved).  Now a max recursion error draws in a second or two.

closes ipython#3198
  • Loading branch information
minrk committed Apr 19, 2013
1 parent 7b81790 commit dee800a
Showing 1 changed file with 29 additions and 17 deletions.
46 changes: 29 additions & 17 deletions IPython/frontend/html/notebook/static/js/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -158,12 +158,34 @@ IPython.utils = (function (IPython) {

//Map from terminal commands to CSS classes
var ansi_colormap = {
"30":"ansiblack", "31":"ansired",
"32":"ansigreen", "33":"ansiyellow",
"34":"ansiblue", "35":"ansipurple","36":"ansicyan",
"37":"ansigrey", "01":"ansibold"
"01":"ansibold",
"30":"ansiblack",
"31":"ansired",
"32":"ansigreen",
"33":"ansiyellow",
"34":"ansiblue",
"35":"ansipurple",
"36":"ansicyan",
"37":"ansigrey"
};

function ansispan(str) {
// ansispan function adapted from github.com/mmalecki/ansispan (MIT License)
Object.keys(ansi_colormap).forEach(function(ansi) {
var span = '<span class="' + ansi_colormap[ansi] + '">';

//
// `\033[Xm` == `\033[0;Xm` sets foreground color to `X`.
//
str = str.replace(
new RegExp('\033\\[([01];)?' + ansi + 'm', 'g'), span
);
});

str = str.replace(/\033\[([01]|39|22)?m/g, '</span>');
return str;
};

// Transform ANSI color escape codes into HTML <span> tags with css
// classes listed in the above ansi_colormap object. The actual color used
// are set in the css file.
Expand All @@ -179,19 +201,9 @@ IPython.utils = (function (IPython) {
// all ANSI codes that do not end with "m".
var ignored_re = /(?=(\033\[[\d;=]*[a-ln-zA-Z]{1}))\1(?!m)/g;
txt = txt.replace(ignored_re, "");

while (re.test(txt)) {
var cmds = txt.match(re)[1].split(";");
closer = opened?"</span>":"";
opened = cmds.length > 1 || cmds[0] != 0;
var rep = [];
for (var i in cmds)
if (typeof(ansi_colormap[cmds[i]]) != "undefined")
rep.push(ansi_colormap[cmds[i]]);
opener = rep.length > 0?"<span class=\""+rep.join(" ")+"\">":"";
txt = txt.replace(re, closer + opener);
}
if (opened) txt += "</span>";

// color ansi codes
txt = ansispan(txt);
return txt;
}

Expand Down

0 comments on commit dee800a

Please sign in to comment.