ErichDonGubler / termion

A bindless library for controlling terminals/TTY.
MIT License
4 stars 1 forks source link

Windows - Step 2 - Add color and Style support #3

Open mattmccarty opened 6 years ago

mattmccarty commented 6 years ago

The next thing we should implement is color support because it's the easiest and will provide atleast some functionality to WIndows users. Microsoft just updated their console to support ANSI codes, so we should provide a backup for people using a version of windows that doesn't support it (if the are using the default Windows console). Any version of Windows that is less than '10.0.10586' will need to return these backup color options.

The exception (maybe) is for 3rd party console applications (i.e: Console2/ConsoleZ, ConEmu, Cygwin, MingW, etc). These applications have supported ANSI color codes forever. We will need to determine the console type. If the console is cmd.exe (the default Windows console) then we need to check the version of windows and act accordingly. I need to test this theory though.

Here is an example of a couple of non-ansi standard enums that we could use:

#[cfg(target_os = "windows")]
#[derive(Clone, Debug, PartialEq, Eq)]
#[repr(u16)]
#[allow(dead_code)]
enum Win32ForegroundColor {
    BLACK,
    DARKBLUE      = (winapi::FOREGROUND_BLUE) as u16,
    DARKGREEN     = (winapi::FOREGROUND_GREEN) as u16,
    DARKCYAN      = (winapi::FOREGROUND_GREEN | winapi::FOREGROUND_BLUE) as u16,
    DARKRED       = (winapi::FOREGROUND_RED) as u16,
    DARKMAGENTA   = (winapi::FOREGROUND_RED | winapi::FOREGROUND_BLUE) as u16,
    DARKYELLOW    = (winapi::FOREGROUND_RED | winapi::FOREGROUND_GREEN) as u16,
    DARKGRAY      = (winapi::FOREGROUND_RED | winapi::FOREGROUND_GREEN | winapi::FOREGROUND_BLUE) as u16,
    GRAY          = (winapi::FOREGROUND_INTENSITY) as u16,
    BLUE          = (winapi::FOREGROUND_INTENSITY | winapi::FOREGROUND_BLUE) as u16,
    GREEN         = (winapi::FOREGROUND_INTENSITY | winapi::FOREGROUND_GREEN) as u16,
    CYAN          = (winapi::FOREGROUND_INTENSITY | winapi::FOREGROUND_GREEN |winapi:: FOREGROUND_BLUE) as u16,
    RED           = (winapi::FOREGROUND_INTENSITY | winapi::FOREGROUND_RED) as u16,
    MAGENTA       = (winapi::FOREGROUND_INTENSITY | winapi::FOREGROUND_RED | winapi::FOREGROUND_BLUE) as u16,
    YELLOW        = (winapi::FOREGROUND_INTENSITY | winapi::FOREGROUND_RED | winapi::FOREGROUND_GREEN) as u16,
    WHITE         = (winapi::FOREGROUND_INTENSITY | winapi::FOREGROUND_RED | winapi::FOREGROUND_GREEN | winapi::FOREGROUND_BLUE) as u16
}

#[cfg(target_os = "windows")]
#[derive(Clone, Debug, PartialEq, Eq)]
#[repr(u16)]
#[allow(dead_code)]
enum Win32BackgroundColor {
    BLACK,
    DARKBLUE      = (winapi::BACKGROUND_BLUE) as u16,
    DARKGREEN     = (winapi::BACKGROUND_GREEN) as u16,
    DARKCYAN      = (winapi::BACKGROUND_GREEN | winapi::BACKGROUND_BLUE) as u16,
    DARKRED       = (winapi::BACKGROUND_RED) as u16,
    DARKMAGENTA   = (winapi::BACKGROUND_RED | winapi::BACKGROUND_BLUE) as u16,
    DARKYELLOW    = (winapi::BACKGROUND_RED | winapi::BACKGROUND_GREEN) as u16,
    DARKGRAY      = (winapi::BACKGROUND_RED | winapi::BACKGROUND_GREEN | winapi::BACKGROUND_BLUE) as u16,
    GRAY          = (winapi::BACKGROUND_INTENSITY) as u16,
    BLUE          = (winapi::BACKGROUND_INTENSITY | winapi::BACKGROUND_BLUE) as u16,
    GREEN         = (winapi::BACKGROUND_INTENSITY | winapi::BACKGROUND_GREEN) as u16,
    CYAN          = (winapi::BACKGROUND_INTENSITY | winapi::BACKGROUND_GREEN |winapi:: BACKGROUND_BLUE) as u16,
    RED           = (winapi::BACKGROUND_INTENSITY | winapi::BACKGROUND_RED) as u16,
    MAGENTA       = (winapi::BACKGROUND_INTENSITY | winapi::BACKGROUND_RED | winapi::BACKGROUND_BLUE) as u16,
    YELLOW        = (winapi::BACKGROUND_INTENSITY | winapi::BACKGROUND_RED | winapi::BACKGROUND_GREEN) as u16,
    WHITE         = (winapi::BACKGROUND_INTENSITY | winapi::BACKGROUND_RED | winapi::BACKGROUND_GREEN | winapi::BACKGROUND_BLUE) as u16
}

My thoughts are to have a new colors.rsmodule in src/sys/windows and return the color spaces accordingly. This will require some reconfigurations of the src/colors.rsmodule either way.

ErichDonGubler commented 6 years ago

colors.rb

src/colors.rb

You're a Ruby guy, huh? ;)

mattmccarty commented 6 years ago

haha! I Just realized that I did that. I'm an 'everything' guy, so it gets hard to keep things straight sometimes. My fingers type faster than I think.

mattmccarty commented 6 years ago

We should probably also include clearing the screen in this issue.

ErichDonGubler commented 6 years ago

The exception (maybe) is for 3rd party console applications (i.e: Console2/ConsoleZ, ConEmu, Cygwin, MingW, etc). These applications have supported ANSI color codes forever. We will need to determine the console type. If the console is cmd.exe (the default Windows console) then we need to check the version of windows and act accordingly. I need to test this theory though.

@mcgoo's rebased implementation doesn't even try to detect alternative terminal emulators right now -- any suggestions on how to actually detect this?

mattmccarty commented 6 years ago

Terminal detection is almost impossible in linux. I've tried. With windows I know we can detect cygwin, but we may not be able to detect the others. We need to find out. If we can't then we need to figure out an implementation that works across the board.

mattmccarty commented 6 years ago

Lets just make sure ansi color support is working for Windows 10. Supporting non-ansi consoles looks like it will be a great deal of work, so that functionality should probably be implemented at a later time (if it's really needed).

My thoughts are to create an attr.rs file in sys/windows like unix has and implement the get_terminal_attr, set_terminal_attr, raw_terminal_attr. We can then enable ansi support through set_terminal_attr. This will keep it consistent with other operating systems.

ErichDonGubler commented 6 years ago

@mattmccarty: This task might already be done, since styling and colors already works for other ANSI platforms. Is there any work actually left with this task?