Имя пользователя:
Пароль:  
Помощь | Регистрация | Забыли пароль?  

Показать сообщение отдельно

Старожил


Сообщения: 415
Благодарности: 257

Профиль | Отправить PM | Цитировать


Вложения
Тип файла: zip cmdcolor.zip
(2.1 Kb, 80 просмотров)

Решил немного расцветить вывод своего скрипта, отметив ошибки, предупреждения и сообщения от различных потоков цветом. Поиск выдал эту тему. Но решение товарища Diskretor (он же - Dragokas, ежели не ошибаюсь?) имеет ряд недостатков, которые заставили меня поискать другой выход. Это и использование временного файла, и запрет на концевые пробелы и спецсимволы. Поэтому после продолжительного сидения над блокнотом, написал вот такую штуку:
Код: Выделить весь код
@Echo Off
SetLocal EnableDelayedExpansion
:: Inquisitor, 2013
:: Использованы следующие материалы:
:: Быстрое получение длины строки: CyberMuesli, http://forum.oszone.net/showpost.php?p=2164186
:: Получение 0x08: jeb, http://www.dostips.com/forum/viewtopic.php?p=6827#p6827
:: Идея передачи нескольких параметров: Diskretor, http://forum.oszone.net/post-2201046-7.html


Echo.
Call :EchoColor 00 "        "
Call :EchoColor 0D "My Little Cmd" /n
Call :EchoColor 00 "       "
Call :EchoColor D0 "Coding is Magic" /n
Echo.
Echo          Simple demo:
Call :EchoColor 0A "  Text 0123 \>|</&^:;.,*-+=" /n
Call :EchoColor 08 "  -[" 6C " R " 2E " a " 1A " i " 5B " n " 79 " b " 3D " o " F4 " w " 08 "]-" /n
Pause&Exit



:EchoColor [%1=Color %2="Text" %3=/n (CRLF, optional)] (Support multiple arguments at once)
:: Вывод цветного текста. Ограничения - не выводится восклицательный знак, остальные спецсимволы разрешены.
:: Работа с более, чем одним набором параметров
If Not Defined multiple If Not "%~4"=="" (
	Call :EchoWrapper %*
	Set multiple=
	Exit /B
)
SetLocal EnableDelayedExpansion
If Not Defined BkSpace Call :EchoColorInit
:: Экранирование входящего текста от обратных и прямых слэшей, чистка некоторых символов.
Set "$Text=%~2"
Set "$Text=.%BkSpace%!$Text:\=.%BkSpace%\..\%BkSpace%%BkSpace%%BkSpace%!"
Set "$Text=!$Text:/=.%BkSpace%/..\%BkSpace%%BkSpace%%BkSpace%!"
Set "$Text=!$Text:"=\"!"
Set "$Text=!$Text:^^=^!"
:: Если XP, выводим обычный текст.
If "%isXP%"=="true" (
	<nul Set /P "=.!BkSpace!%~2"
	GoTo :unsupported
)
:: Подаем текст на stdout, не создавая временных файлов и используя трюк с путём.
:: В случае неудачи (проблемный\слишком длинный путь?) выводим текст as is, без расцветки.
:: Если результирующая длина строки (плюс уже имеющиеся там символы) превышает ширину консоли, то вывод тоже будет неудачным. Но получить текущую позицию каретки программно нельзя.
PushD "%~dp0"
2>nul FindStr /R /P /A:%~1 "^-" "%$Text%\..\%~nx0" nul
If !ErrorLevel! GTR 0 <nul Set /P "=.!BkSpace!%~2"
PopD
:: Убираем путь, имя файла и дефис с помощью рассчитаного ранее количества символов.
For /L %%A In (1,1,!BkSpaces!) Do <nul Set /P "=!BkSpace!"
:unsupported
:: Выводим CRLF, если указан третий аргумент.
If /I "%~3"=="/n" Echo.
EndLocal
GoTo :EOF

:EchoWrapper
:: Обработка аргументов поочерёдно
SetLocal EnableDelayedExpansion
:NextArg
Set multiple=true
:: Ох уж это удвоение "^" при передаче аргументов...
Set $Text=
Set $Text=%2
Set "$Text=!$Text:^^^^=^!"
If Not "%~3"=="" If /I Not "%~3"=="/n" (
	Shift&Shift
	Call :EchoColor %1 !$Text!
	GoTo :NextArg
) Else (
	Shift&Shift&Shift
	Call :EchoColor %1 !$Text! %3
	GoTo :NextArg
)
If "%~3"=="" Call :EchoColor %1 !$Text!
EndLocal
GoTo :EOF


:EchoColorInit
:: Отрабатывающая при первом запуске родительской функции инициализация нужных переменных
:: Важно! Под XP, в силу реализации тамошнего findstr, 0x08 в путях не работает, заменяясь на точку. Отключаем цветной вывод для XP.
For /F "tokens=2 delims=[]" %%A In ('Ver') Do (For /F "tokens=2,3 delims=. " %%B In ("%%A") Do (If "%%B"=="5" Set isXP=true))
:: Получаем комбинацию "0x08 0x20 0x08" с помощью prompt
For /F "tokens=1 delims=#" %%A In ('"Prompt #$H# & Echo On & For %%B In (1) Do rem"') Do Set "BkSpace=%%A"
:: Рассчитываем требуемое количество символов для подавления всего, кроме выводимого текста
Set ScriptFileName=%~nx0
Call :StrLen ScriptFileName
Set /A "BkSpaces=!strLen!+6"
GoTo :EOF

:StrLen [%1=VarName (not VALUE), ret !strLen!]
:: Получение длины строки
Set StrLen.S=A!%~1!
Set StrLen=0
For /L %%P In (12,-1,0) Do (
	Set /A "StrLen|=1<<%%P"
	For %%I In (!StrLen!) Do If "!StrLen.S:~%%I,1!"=="" Set /A "StrLen&=~1<<%%P"
)
GoTo :EOF

:: Эта строка должна быть последней и не оканчиваться на CRLF.
-
Спецсимволы разрешены все (кроме "!" и "%"), временные файлы не создаются - использован трюк с путём. Но есть и минусы: если конец выведенной строки близок к границе окна, строка может отобразиться некорректно. Самый важный и большой недостаток - не работает под XP (реализация findstr в XP символы 0x08 в пути отображает точками, соответственно, удалить внутри пути, не c конца строки, ничего нельзя).
Тестировалось на Win 7 (x86\x64), Win Server 2008r2. Под XP цветной вывод просто отключается автоматически.


Последний раз редактировалось Anonymоus, 06-10-2013 в 22:22. Причина: Добавлен скрипт во вложении

Это сообщение посчитали полезным следующие участники:

Отправлено: 01:23, 07-09-2013 | #8