8

Is there any tool that translates text with ANSI code to text-like output? tput cap names or the like?

Reason for the inquiry is that I would like to use script or the like and view the resulting file without having to decipher ANSI sequences. I know some, but not all, and a textual output would be easier to read.

In most cases I can look at source code for script or program that produces the ANSI text, but would be nice if there was a "debug" like tool.

The best would likely be C ? variable names, i.e.:

^[[K    ->   <clr_eol>

Know I can write a script for it ... for example:

sed 's/$/<newline>/' rec001.txt | \
sed 's/\x07/\n<bell>/g' | \
sed 's/\x1b\[K/\n<clr_eol>/g' | \
sed 's/\x1b\[?12l\x1b\[?25h/\n<cursor_normal>/g' | \
sed 's/\x1b\[\([0-9]\+\);\([0-9]\+\)H/\n<cursor_position(\1, \2)>/g' | \
sed 's/\x1b\[?1049h/\n<enter_ca_mode>/g' | \
sed 's/\x1b\[?25l/\n<cursor_invisible>/g' | \
sed 's/\x0d/<CR>/g' | \
...

which is part of a quick test I did on a Irssi recording.

But wondering if there are any existing tool for the job.

As a side note we have aha, Ansi HTML adapter, which converts ANSI to HTML. But that is not the adapter I am looking for.


1
  • do you have the complete script of those sed commands?
    – Rainb
    Commented Dec 17, 2020 at 9:40

2 Answers 2

5

Someone might suggest a program. It is not a trivial problem to do well:

  • "ANSI sequences" are standardized in ECMA-48,
  • some of your examples (such as the cursor appearance and enter_ca_mode) are not in the standard,
  • some such as the enter_ca_mode 1049 code have variations (\E7\E[?47h). If a program relies on a terminal description, only one of the variations will be recognized,
  • some of the sequences are parameterized, which means that a program has to either have the rules built-in, or able to transform terminal capabilities such as \E[%i%p1%d;%p2%dH into an regular expression that can be matched against the inputs.

Given all of that, if someone suggests a program, it more likely will not solve those aspects, but simply be a terminal emulator without the display.

0
0

If you want just the ANSI cursor movement you can easily create an interpreter using NPM module node-ansiparser. I used the same module for my JavaScript library: jQuery Terminal, where I parse and process ANSI escapes and overtyping (output of man command).

You can take a look at how I used the parser on GitHub unix_formatting.js (the file includes the ansi-parser). You can try to modify the code to only process text and ignore the colors (the jQuery Terminal formatting syntax). It should not be that hard.

If you want something quick you can create a script that will just process the file and strip the formatting that is used by jQuery Terminal. Here is a quick hack that does the trick (but you probably be better modifying the unix_formatting.js file and remove everything that is not needed).

To start with jQuery Terminal use this:

mkdir ansi-text
cd ansi-text
npm init -y # you need nodeJS installed
npm install jquery.terminal

then create this file in same directory:

ansi-text.js

#!/usr/bin/env node
// mock jQuery that is not actually required
const $ = global.$ = global.jQuery = {
    fn: {
        extend: function(obj) {
            Object.assign(global.jQuery.fn, obj);
        }
    },
    extend:  Object.assign
};

global.navigator = {
    userAgent: 'Node'
};

require('jquery.terminal')(global, global.$);
require('jquery.terminal/js/unix_formatting')(global, global.$);

read_stdin().then(function(buff) {
    const str = buff.toString();
    const formatted = $.terminal.apply_formatters(str);
    console.log($.terminal.strip(formatted));
});

function read_stdin() {
    return new Promise((resolve) => {
        const buff = [];

        process.stdin.on('data', data => {
            buff.push(data);
        }).on('end', () => {
            var len = buff.map(x => x.length).reduce((acc, e) => acc + e);
            resolve(Buffer.concat(buff, len));
        });
    });
}

You can then create testing script:

test.sh

tput cup 2 3;
echo HELLO;
tput cup 5 20;
echo WORLD;

And you can see that it works using:

unbuffer ./test.sh | ./ansi-text.js

Output:

kuba@jcubic:~/projects/jcubic/ansi-text$ unbuffer test.sh | ./ansi-text.js 


   HELLO


                    WORLD

kuba@jcubic:~/projects/jcubic/ansi-text$ 

unbuffer will make the script think that it's TTY (it's part of expect).

The JS code doesn't handle the width of the terminal but it can be easily added after you transform ANSI escapes. To split the output use: $.terminal.split_equal(string, cols) but you probably can use something simpler since you don't need to handle jQuery Terminal formatting, that is the main purpose of the function.

0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .