0

Trying to write some logger enhancements I'd like to deal with ANSI codes interpretation, and it seems that it's not working with the standard io.putstring method neither with print I wonder there is a way to do something such as

echo -e "\u001B[31mSome_red_txt" in bash

Seems other languages can do it but I can't in Eiffel.

Pipo
  • 4,653
  • 38
  • 47

2 Answers2

3

Using ANSI codes interpretation, you can do

print ("%/27/[31mSome_red_txt%N")
print ("%/27/[1;31mbold red text%/27/[0m%N")

You may check for existing C libraries like ncurses. Note it will not work on Windows console, as now it does not support ANSI code anymore, so you need to use the Windows API.

Jocelyn
  • 693
  • 5
  • 8
  • 1
    May I suggest you to add some comment about escaping characters with Eiffel which was my error trying to get it working with `\001B` – Pipo Oct 18 '18 at 16:52
3

To complement Jocelyn's answer, the same ANSI code sequences can be used on Windows with recent update by making sure the console is initialized to handle the sequences:

    -- Make sure the console is allocated in a non-console application.
io.output.end_of_file.do_nothing
    -- Set console to terminal mode.
initialize_terminal
    -- Use ANSI codes to color text.
print ("%/27/[31mSome_red_txt")

where

initialize_terminal
    external "C inline"
    alias "[
        #ifdef EIF_WINDOWS
            {
                HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
                if (hOut == INVALID_HANDLE_VALUE) return;
                DWORD dwMode = 0;
                if (!GetConsoleMode(hOut, &dwMode)) return;
                dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
                SetConsoleMode(hOut, dwMode);
            }
        #endif
    ]"
    end

After such initialization, print statements work the same on Windows and Linux.

If output can go not only to the console, but also to a file, a pipe, etc., error status of setting the terminal mode on Windows console can be recorded in the external feature and used later to avoid outputting ANSI sequences in such cases.

Alexander Kogtenkov
  • 5,770
  • 1
  • 27
  • 35
  • Based on Alexander's answer. I built quickly a quick and dirty example. See https://gist.github.com/jocelyn/c2a211315898639fc65c3108343a950b (tested on Windows and Debian) – Jocelyn Oct 18 '18 at 12:58
  • What about the case of ssh from MS's windows to Unix or form Unix to MS`s Windows (is that possible)? – ctrl-alt-delor Nov 22 '18 at 20:42
  • @ctrl-alt-delor `ssh` uses standard input and output, so there should be no specific issues. – Alexander Kogtenkov Nov 22 '18 at 21:48
  • Expect the program will see that it is running on Unix, and not set up the colour on the MS-Windows terminal. (Does the MS-Windows support any standards, to allow this to happen.) – ctrl-alt-delor Nov 23 '18 at 07:49
  • @ctrl-alt-delor A program that wants to use escape sequences also checks what kind of standard output it is attached to, whether it is a terminal or something else, and uses the escape sequences only when they are supported. For example, the environment variable `TERM` can be used to pass the information about capabilities of the terminal, shells have their own mechanisms to enable colored output, etc. – Alexander Kogtenkov Nov 23 '18 at 11:29
  • @AlexanderKogtenkov Yes you see, my point, and how it needs to be done. However, this is not what your program does. (or am I wrong?) – ctrl-alt-delor Nov 23 '18 at 11:38
  • @ctrl-alt-delor The question is about a possibility to do colored output, when the output is known to go to a terminal. How to detect whether the output indeed goes to a terminal is a different question. – Alexander Kogtenkov Nov 23 '18 at 11:55
  • @ctrl-alt-delor OK, I missed your point. Indeed, the result of functions `GetConsoleMode` and `SetConsoleMode` can be used to see whether terminal facilities (such as colored output) are supported by the associated output stream on Windows. Similar functionality [exists](https://stackoverflow.com/questions/1061575/detect-in-c-if-outputting-to-a-terminal) on Linux. Some other means should be used to do it when output generated on one machine is to be displayed on another. – Alexander Kogtenkov Nov 23 '18 at 12:18
  • You will never know what machine it is displayed on until run time. So you need to write code to do that. I know it can be done, on Unixes. But don't know about MS, or the cmd terminal. – ctrl-alt-delor Nov 23 '18 at 12:20