Печать строки в java-консоли (обратная сторона '\n')

предисловие

Я видел некоторые вопросы, связанные с этим на других языках, и провел довольно много исследований по этому вопросу. Во-первых, прежде чем мы начнем спускаться по кроличьей норе, я должен описать, почему я это делаю. Я довольно печатаю двоичное дерево, и я нашел способ сделать это, который, я думаю, никто не нашел (не могу найти его в Интернете, где я искал вечно). Это решает много проблем, связанных с пробелами и конфликтами, и я, вероятно, предоставлю это как ответ на вопросы довольно печати Btree позже. В любом случае, важной частью выполнения вышеизложенного является возможность перемещения строки (курсора) на одну строку вверх. Я также согласен на перемещение каретки на одну строку вверх.

Я сделал три РЕДАКТИРОВАНИЯ на этот вопрос под названием "Редактировать 1-3" в нижней части.

Моя конкретная версия Windows (может быть уместна): Windows 10 v1607 Сборка ОС: 14393.2035

Эта проблема??

Проблема в том, что это легко сделать с помощью управляющих символов ANSI

Экранирующие коды ANSI: https://en.wikipedia.org/wiki/ANSI_escape_code

С "\ 033 [A" - это конкретный код, который я хочу реализовать (он возник из вопроса о перемещении на одну строку вверх в python).

Эта проблема

Так что проблема решена правильно? О нет, даже близко. Проблема, по-видимому, в Windows было это "" "замечательное" "" обновление, которое могло сломать все, что связано с ANSI/консолью. Ниже приведены ссылки на вопрос по этому вопросу, но с другими требованиями ANSI, однако основная проблема та же.

Как напечатать цвет в консоли, используя System.out.println?

tl: dr По какой-то причине он не работает для Windows, вам нужна большая библиотека, чтобы сделать это или что-то еще.

Тогда я попытался провести глубокое исследование самого обновления и выяснить, почему это происходит с Windows (конечно), и меня привели к этому.

Основная причина проблемы Windows: https://github.com/Microsoft/WSL/issues/1173

tl; dr: В основном, обновление изменило настройку по умолчанию для cmd.exe, который является консолью по умолчанию, которую использует java. Изменилось то, как настройки консоли для кодов ANSI обрабатываются для "дочерних приложений" AKA java (вещи, которые используют консоль, но не являются самой консолью). По умолчанию До обновления дочерние приложения унаследовали стандартную консоль, в которой должен был быть включен ANSI. ТЕПЕРЬ (потому что очевидно, что предыдущий дефолт сломал вещи), они изменили его так, чтобы дочерние приложения НЕ наследовали настройки по умолчанию от консоли. Это означает, что java должен эффективно сам устанавливать этот режим консоли, если java хочет включить ANSI. Очевидно, что для выполнения команды java существует множество библиотек, но из хорошо доступных есть некоторые проблемы. Во-первых, они требуют maven, а я не хочу maven, также мне не нравится, когда НУЖНА миллион дополнительных библиотек, чтобы сделать что-то очень простое, и это добавляет к числу вещей, на которые опирается мой код (что плохо). Поэтому я стараюсь избегать простых решений, таких как "просто использовать JANSI" для setConsoleMode для ANSI.

Что я пробовал после этого

после того, как я прочитал/понял, что попытался зайти в редактор реестра и попытаться изменить настройки консоли по умолчанию (cmd.exe), чтобы всегда включать ANSI даже для дочерних приложений (AKA java). Это было предложено в обсуждении GitHub, но, к моему удивлению, конкретная обстановка даже не была для меня. (он должен был находиться в компьютере → HKEY_CUURENT_USER → консоль между "TrimLeadingZeros" и "WindowAlpha").

Попробуй 2

Поскольку я не мог редактировать настройки консоли без больших библиотек, полных вещей, которые мне не нужны, я попытался мыслить нестандартно и бездельничать в настройках Java. Я обнаружил, где именно Java устанавливает консоль, и обнаружил, что могу изменить этот параметр, чтобы использовать другую консоль в Java. Я недавно установил git и знал, что git bash доступен, поэтому я попробовал это, используя приведенный ниже вопрос (и google в целом) в качестве отправной точки.

https://superuser.com/info/1196463/start-sh-exe-bash-with-given-path

Третий раз это очарование?

Я не мог заставить эту чертову вещь работать. Он не возвращал никаких ошибок и не делал ничего нового, как вообще. Он даже был установлен "для текущего проекта", так что он должен был сделать что-то другое, когда я запустил свой проект, нет? Я считаю, что отчасти проблема заключается в том, что моя корневая папка git является винтовой (не в программных файлах). Вероятно, это связано с тем, что компьютер, который я использую, является рабочим компьютером, и, возможно, некоторые настройки там влияют на то, где был установлен git, я не знаю, но я знаю, что когда я менял консоли, я пробовал этот путь:

C:\Users\abbotts1\AppData\Local\Programs\Git\Bin\bash.exe

Я также попробовал:

C:\Users\abbotts1\AppData\Local\Programs\Git\bash.exe

а также

C:\Users\abbotts1\AppData\Local\Programs\Git\Bin\sh.exe

а также

"C:\Users\abbotts1\AppData\Local\Programs\Git\bin\sh.exe" --login -i

И после каждой смены консоли я пробовал этот код:

public class ExpressionEvaluator {

    public static void main(String[] args) {
        System.out.println("1");
        System.out.println("\033[A");
        System.out.println("2");
    }
}

И я всегда получал:

1

Extra Line здесь

2

Как на выходе. Если я удалил попытку ANSI println "переместить курсор вверх", я получил:

1

2

То, что я хотел, было:

2

1

(суть в том, что я могу свободно двигаться вверх по линии)

Я также попытался заставить их печатать заявления, и это тоже не сработало.

Так что теперь я в конце концов

Так вот, что я хочу, ответ что-то вроде:

  1. Ненавязчивый способ изменить настройку cmd.exe, чтобы позволить дочерним приложениям, таким как java, использовать ANSI BY DEFAULT при запуске

  2. ИЛИ ненавязчивая библиотека, которая не требует maven и миллиона других вещей для включения ANSI, чтобы я мог запустить ANSI в java на консоли и получить желаемый результат

  3. ИЛИ программный обходной путь, который позволяет мне эффективно печатать одну строку без всей этой вещи ANSI

  4. ИЛИ помогите настроить консоль IntelliJ, чтобы я мог использовать другую консоль и использовать ANSI для печати одной строки

Для решения очевидных проблем

Так как 1 и 4 - вопросы суперпользователя, а 2 - "Мне нужна библиотека", а оффтоп я больше говорю о пункте 3 здесь. Если для этого нет обходного пути, и ответ один из оффтопов, просто скажите мне, что обходного пути нет. Я не знаю, как еще задать этот вопрос, поскольку это "специфическая для программирования проблема", у него просто есть много решений, некоторые из которых не относятся к теме, потому что они не являются программными решениями. Если единственный ответ - "решение здесь не по теме", тогда я пойду и спрошу в соответствующем месте. Дайте мне знать, если я должен удалить этот вопрос, когда я пойду, чтобы задать его где-то еще.

То, что я думаю, может работать на тему часть этого

Поскольку тема 3 здесь, я расскажу, что я думаю:

Может быть, я мог бы создать какую-то систему для печати только в определенные массивы вместо перемещения линий вверх и вниз (т.е. Иметь массив для представления линий, проходить по дереву и вместо перемещения линий вверх и вниз, просто переключая массив для печати в). Я не считаю это очень эффективным, и это своего рода пустая трата массивов и вычислительной мощности, но если это решение, я готов это услышать. Это все, что я могу "придумать", но большая часть того, что я пробовал, - это заставить ANSI работать.

Для дальнейшего использования:

Как правильно задавать эти вопросы с помощью нескольких не относящихся к теме решений/вопросов решения? Лучше просто не спрашивать их вообще? Являются ли решения, включающие вопросы, вопросом хамелеона? Я не чувствую, что навлекаю мета-эффект на себя.

Редактировать 1: где я до сих пор:

Я перепробовал всю вещь git bash снова, и это был процесс. Фактический путь git bash в терминале должен быть в кавычках с последующими аргументами --login -i. Пример:

C:\Git\bin\sh.exe --login -i

Этот параметр для терминала Java. Затем вы должны установить переменную среды Windows с именем PATH для вашего java JDK. Перейдите к переменным среды вашего пути (для этого есть миллион и одно видео на YouTube) и установите новую переменную с именем PATH для вашего JDK. Пример:

C:\Program Files\Java\jdk-10.0.1\bin

Этот вопрос:

Как я могу заставить gitbash найти команду javac?

Проходит через этот процесс экстенсивно

Tl; dr Вы должны установить переменную пути к Windows для того, чтобы git bash мог распознавать команды javac и java.

Как только это будет сделано, вам нужно будет запустить команды java и javac, как в любом терминале. Кстати, будьте осторожны, потому что пути в git bash требуют двух "\" обозначений вместо нормальных "\", поэтому путь к исходному каталогу может выглядеть следующим образом:

C:\IdeaProjects\Calculator\SRC\

Тогда вы просто запускаете:

javac ClassName.java

java ClassName

Но тогда он на самом деле не печатает вывод ANSI, он печатает необработанные управляющие символы. Кроме того, я обнаружил, что использовал escape-последовательность WRONG (у меня был неправильный номер для обозначения кнопки "esc", поскольку ключ "esc" представлен в виде некоторого числа, но у меня был неправильный шестнадцатеричный номер, который я использовал, например, x330 или что-то). Я также узнал, что запись такова:

'шестнадцатеричный номер ключа esc' + '[' + 'шестнадцатеричные значения параметра, разделенные запятыми'

так что это может выглядеть так:

\x1B [A

где фактические буквы и цифры являются шестнадцатеричными значениями (без очевидного 0x...), а первое экранирующее шестнадцатеричное значение содержит х (почему?). В любом случае, при запуске их в Java в виде строк вам нужно экранировать escape-символ (да?) С дополнительным '\', так что, например, код может выглядеть следующим образом:

System.out.println("\\\x1B [A");

Я только что заметил, что переполнение стека тоже ускользает, поэтому у меня на самом деле три "\", но для вас, ребята, он отображает только два "\", странно, верно? В любом случае вернемся к тому, что я говорил

НО ЕЩЕ, на самом деле выход не работает! Это где я нахожусь. Я сделал выше, и я на 99,9% знаю, что git bash установлен правильно и работает нормально, но когда я запускаю это:

public class ExpressionEvaluator {
    public static void main(String[] args) {
        System.out.println("1");
        System.out.println("\\x1B [A");
        System.out.println("2");
    }
}

Я получаю это в консоли Java (не Git Bash??):

1

\x1B [A

2

и это в git bash:

1

\x1B [A

2

Что я на самом деле хочу, это:

2

1

Поскольку escape-символ ANSI должен перемещать мой курсор/перевод строки/что угодно, на одну строку вверх. То же самое происходит, если я запускаю приведенный выше код, но вместо этого использую код ANSI: "\ x1B [F". Только сырой ANSI выводится. Я уверен, что git bash должен был быть "изначально осведомлен об ANSI", и я видел, как люди говорят это на веб-сайтах, поэтому я не знаю, почему он не работает.

И я до сих пор точно не знаю, являются ли это двумя отдельными выходами консоли или одинаковыми выходами консоли. Я действительно не могу сказать, поэтому, если кто-то захочет оставить комментарий, говорящий: "Да, это тот же манекен", я был бы признателен, потому что я не могу найти в Интернете точный источник, которым он является. Я думаю, что это не что иное, как настройка консоли в IntelliJ указывает на то, что это правда.

Я слышал слухи о переменной TERM, которую нужно установить или иным образом манипулировать в Windows. Я проверил себя, что он использует:

echo $ TERM

в Git Bash и я вернулся:

Cygwin

Так что я точно не знаю, хорошо это или плохо, потому что я буквально просмотрел все поисковые термины, которые вы можете придумать, и все они приводят к одной и той же базовой странице результатов для "git bash colors not working", и большинство из них задействовать windows 7 (не иметь его), установить maven/jansi (не хочу или не нужно в нем) или другой язык, не являющийся Java, и использовать другую IDE, не являющуюся IntelliJ. На некоторых страницах, в которых есть мои специфические требования, говорится что-то о TERM, которое должно быть xterm или что-то вроде xterm-256 или что-то для "цветного" вывода, что-то вроде этого. Я так незнаком с этим материалом, поэтому даже не знаю, с чего начать.

Слишком долго дайте нам д-р

Мне нужно знать, почему git bash печатает сырой ANSI, а не использует ANSI.

что я знаю

Я использую git bash с IntelliJ, 99,9% уверены, что мой путь задан правильно, я могу запустить свой класс java из git bash, я установил его в качестве терминала IntelliJ, и в настоящее время переменная windows TERM установлена на cygwin,

Что я не знаю

Я не знаю, каким должен быть TERM, и не могу найти его в Интернете, я не могу сказать, совпадает ли консоль IntelliJ, которая появляется, когда я нажимаю зеленую стрелку "run", с консолью git bash, и Я не могу понять, мешает ли мне что-то еще на самом деле интерпретировать ANSI.

Что мне нужно

Мне нужно простое объяснение, что-то прямо из r/ELI5 о том, что не так с git bash, если что-нибудь и как это исправить. Если это не может быть объяснено просто или нет ничего плохого, то, возможно, я попробую другой, предположительно, "изначально поддерживающий ANSI" терминал. Я думаю, что Powershell был еще один вариант, который был указан. Моя лучшая ставка в том, что переменная TERM должна быть чем-то другим, или git bash никогда изначально не был осведомлен о ANSI и не способен на него. Я видел другие вопросы с той же проблемой для цветов, но они исправлены для старых версий/разных языков и т.д., Или они на самом деле не работают. Мне еще предстоит найти хорошую страницу для "git bash output raw ANSI в IntelliJ", и я уже часами использую варианты этих точных слов. Все, что я могу получить, это долгие обсуждения на GitHub "ошибок", связанных с этим, и они меня смущают, не приводят к решениям, могут быть активными или просто не содержать никакого разрешения.

Редактировать 2

Проведя еще несколько исследований, я узнал, что мой предыдущий управляющий код был верным:

\033 [A

\X1B [A

должно быть похоже.

Я также узнал, что проблема заключается не в консоли, а в самой Windows. Теперь я знаю это, потому что я пытался скомпилировать и запустить cmd.exe, git bash и powershell. Чтобы изменить настройку по умолчанию, о которой говорилось ранее (консоли не поддерживают ANSI для дочерних приложений), вы должны ТОЧНО включить ее через саму программу, а не полагаться на консоль или что-то в этом роде.

ссылка на вопрос, который объясняет это в Python здесь:

Как использовать новую поддержку escape-последовательностей ANSI в консоли Windows 10?

ТЛ; др

Используемый ими метод называется getConsoleMode setConsoleMode и VIRTUALTERMINALPROCESSING. Очевидно, вам нужно использовать их, чтобы фактически установить режим консоли для поддержки ANSI. В настоящее время я не знаю, являются ли это те вещи, которые в Java спрятаны где-то или (вероятно) что-то, что должно быть добавлено в базовые библиотеки Java. Я собираюсь попытаться выяснить, как они на самом деле получают информацию ctypes из этого вопроса (похоже, что они импортируют, чтобы предъявить иск этим методам) и получить методы, которые мне нужны. Как только я это сделаю, я опубликую это как ответ, если один из вас не выяснит это раньше, чем я, и не сможет объяснить это лучше.

Очевидно, escape-последовательности работают нормально, если вы используете их только из консоли, но если вы используете "дочернее приложение", то они не работают. Так что, по крайней мере, теперь мы наверняка знаем причину проблемы.

Редактировать 3

Нашел это, что очень актуально, особенно в разделе последовательности виртуальных терминалов консоли (левая панель навигации):

https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences

Это то, что в нижней части имеет полное описание того, как разрешить консоли читать ANSI. По-видимому, для этого вообще не нужны библиотеки, но процесс для фактического изменения параметров консоли по умолчанию для использования кода, подобного этому, требует привилегий sysadmin, глубокого знания программных файлов и множества других вещей (по крайней мере, если вы раньше Обновление Windows 10 при изменении поддержки цвета). Теперь он все еще отключен по умолчанию, но может быть включен. Я еще не знаю, как попробовать ANSI с консоли напрямую. Я пробовал несколько

echo\x1B [(введите код ANSI здесь)

но ни одна из команд не работает в ЛЮБОМ терминале (cmd, git bash, powershell). Они просто возвращают сырой код

\x1B [(каким бы ни был код ANSI)

Я, очевидно, плохо знаком с консолью, поэтому, возможно, использую неправильную команду, если это так, не стесняйтесь просветить меня, но примеры, которые я видел, используют echo. В любом случае, я думал, что вызов ANSI напрямую из терминала должен был работать, так как он предположительно включен по умолчанию, а не дочерними приложениями (после обновления Windows 10), НО, может быть, это не так, может быть, он отключен по умолчанию, и даже если он включен, он все еще отключен для ребенка приложения (Java), если явно не изменено в указанном дочернем приложении (Java). Я собираюсь попытаться выяснить, возможно ли включить ANSI непосредственно с консоли, или нужно ли напрямую связать C-код с портом на Java или запустить в консоли только для работы. Проблема в том, что я не знаю, как получить импорт/включает в себя C-код и использовать его для кода в Java. Я предпочел бы не просто принимать кодированное "решение" в C и пытаться использовать его вместе с Java-кодом, я бы лучше перевел, понял его лучше и имел свой собственный код, который делает то же самое.

Мне сказали, что есть еще один вариант - ANSICON, который похож на плагин, который вы устанавливаете в консоли с флагом -i и который должен включать ANSI, по крайней мере, в консоли. я нашел это

https://community.liferay.com/blogs / -/blogs/enable-ansi-colors-in-windows-command-prompt

вышеизложенное объясняет этот процесс чуть более подробно.

Моя конкретная версия Windows и версия обновления

Еще одна вещь, которую я узнал, заключалась в том, что конкретная версия Windows 10, "обновление", которое изменило поведение консоли ANSI, было похоже на Windows 10 v1151 или что-то в этом роде. Я попытаюсь найти веб-страницу, чтобы получить ее напрямую, но в настоящее время у меня есть Windows 10 v1607, так что Я думаю, что я должен быть хорошим. В это была включена фактическая сборка ОС, которая у меня есть 14393.2035, и я думаю, что она была определена в качестве одного из промежуточных обновлений этого процесса в одной из моих предыдущих ссылок (я полагаю, что она со всей дискуссией GitHub об обновлении, вы можете найти это здесь: https://github.com/Microsoft/WSL/issues/1173). У меня есть рабочий компьютер, поэтому я не могу действительно выполнять обновления системы, потому что я не администратор, и я сомневаюсь, что ИТ-специалист позволил бы стажеру обновлять рабочие компьютеры.

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

Ответы

Ответ 1

Способ Python, на который вы ссылаетесь в "Edit 2" (fooobar.com/info/837759/...), просто вызывает специфичный для Windows нативный код (kernel32, который является непереносимым), чтобы "исправить" это. Я полагаю, что вы в порядке с этим и будете в порядке, если вы могли бы сделать это в Java (то есть вызывать kernel32, когда вы обнаруживаете Windows)...

Очень легкая библиотека для достижения того же в JNA Java I, которая имеет готовую оболочку для kernel32 (см.: https://java-native-access.github.io/jna/4.2.1/com/sun/jna/platform/win32/Kernel32.html)

Похоже, вы используете этот метод: https://java-native-access.github.io/jna/4.2.1/com/sun/jna/platform/win32/Wincon.html#SetConsoleMode-com.sun.jna. platform.win32.WinNT.HANDLE-int-

Надеюсь, что это работает для вас.

РЕДАКТИРОВАТЬ: технически вам нужен только jna.jar (см. начало здесь: https://github.com/java-native-access/jna/blob/master/www/GettingStarted.md), но я бы посоветовал вам также использовать jna-platform.jar, так что вам не нужно писать код, который генерирует сопоставления для kernel32 во время выполнения самостоятельно.

Дом для JNA: https://github.com/java-native-access/jna

Я думаю, что добавление 1 (или 2, если вы добавляете jna-платформу) jar файлов с очень конкретной областью действия (выполнение нативных вызовов без всех затрат на подготовку JNI) является достаточно легким. Вам не нужно генерировать какие-либо заголовки или что-либо менять в процессе компиляции. Это просто сработает, добавив эти фляги в ваш путь к классам.

Вы также должны уточнить в своем вопросе, что это касается Windows. Возможно, измените заголовок на "Печать строки в консоли java (обратное к \n") в Windows ", так как это действительно связано с проблемой конкретной платформы, которую вы хотите решить с помощью Java.