Как вы можете использовать escape-коды vt100 в Java на Windows - PullRequest
0 голосов
/ 11 октября 2018

escape-коды vt100 - это мощный и популярный метод форматирования выходных данных (цвет, позиционирование, мигание, подчеркивание и т. Д.) На виртуальных терминалах, таких как xterm или konsole.См. https://en.wikipedia.org/wiki/ANSI_escape_code

Когда вы запускаете java-программу в xterm, konsole и т. Д. И System.out.print такие коды - например,

// print "Hello, World!" in red
System.out.print("\u001b[31mHello, World!");

java передает их в терминал без изменений, поэтому ониТерминалы интерпретируют коды и ведут себя так, как вы ожидаете.

Java-программы должны быть независимыми от платформы, однако, когда вы запускаете такую ​​программу из командной строки Windows, вы увидите распечатанные коды,как это:

☐[31mHello, World!

После поиска способа решения этой проблемы, я не смог найти простое решение или даже обсуждение этой темы.Большинство решений зависят от запуска вашей программы в другом консольном приложении или от включения в нее пользовательской консоли на основе Java.

Итак, как можно легко использовать форматированный текст vt100 в командной строке Windows по умолчанию?

1 Ответ

0 голосов
/ 11 октября 2018

Я не знаю, работает ли это на старых версиях Windows (приветствуются некоторые отзывы - я протестировал его на Windows 10), но я взял код из нижней части https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences и перевелэто к Java.

Это использует некоторые вызовы в kernel32.dll, поэтому мне пришлось включить Java Native Access (JNA).Для этого вам необходимо скачать jna-*version*.jar и jna-platform-*version*.jar из https://github.com/java-native-access/jna#download и включить их в ваш проект.

Затем добавьте следующие импорта:

import com.sun.jna.*;
import com.sun.jna.platform.win32.WinDef.*;
import com.sun.jna.platform.win32.WinNT.HANDLE;

И в начале вашей программы вы можете включить vt100, выполнив следующий код:

if(System.getProperty("os.name").startsWith("Windows"))
{
    // Set output mode to handle virtual terminal sequences
    Function GetStdHandleFunc = Function.getFunction("kernel32", "GetStdHandle");
    DWORD STD_OUTPUT_HANDLE = new DWORD(-11);
    HANDLE hOut = (HANDLE)GetStdHandleFunc.invoke(HANDLE.class, new Object[]{STD_OUTPUT_HANDLE});

    DWORDByReference p_dwMode = new DWORDByReference(new DWORD(0));
    Function GetConsoleModeFunc = Function.getFunction("kernel32", "GetConsoleMode");
    GetConsoleModeFunc.invoke(BOOL.class, new Object[]{hOut, p_dwMode});

    int ENABLE_VIRTUAL_TERMINAL_PROCESSING = 4;
    DWORD dwMode = p_dwMode.getValue();
    dwMode.setValue(dwMode.intValue() | ENABLE_VIRTUAL_TERMINAL_PROCESSING);
    Function SetConsoleModeFunc = Function.getFunction("kernel32", "SetConsoleMode");
    SetConsoleModeFunc.invoke(BOOL.class, new Object[]{hOut, dwMode});
}

С этого момента

System.out.print("\u001b[31mHello, World!");

выведет «Hello, World!»в красном, как и ожидалось.

...