Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Скриптовые языки администрирования Windows (http://forum.oszone.net/forumdisplay.php?f=102)
-   -   Расширение возможностей Echo (http://forum.oszone.net/showthread.php?t=201268)

Anonymоus 06-03-2011 13:33 1628519

Расширение возможностей Echo
 
Доброго времени суток, уважаемые.
Недавно понадобился мне в одном из скриптов вывод текстовой строки поверх предыдущей, после поисков в интернете было найдено несколько консольных утилит, позволяющих такое сделать. Но пораскинув немного мозгами, я решил обойтись без сторонних утилит, стандартными средствами командного процессора. Вот, решил выложить тут, авось кому еще пригодится. Критика тоже приветствуется.
Реализация подсмотрена здесь .
Возможности - вывод текста без переноса на другую строку, форматирование длинных строк, удаление строк, установка курсора в нужную позицию на строке, заполнение строкой нужной длинны, состоящей из пробелов, вывод текста поверх другого текста, имитация посимвольного плавного ввода текста ("печатная машинка"). Все (или почти все) показано в коротеньком демо, запускающемся при старте скрипта. Также наличествует встроенная справка по "командам".

Собственно, сам скрипт (кодировка 866):
Код:

@Echo Off
Rem Демо, показывающее основные возможности
Rem =======================================================
Title  libType - Demo
Call :libType echo "Пример вывода обычной текстовой строки."
Call :libType qwrite "Предыдущая строка была напечатана с использованием эффекта 'печатной машинки', а эта - нет."
Call :libType break
Call :libType write "А эта строка сейчас будет удалена. Нажмите любую кнопку..."
Pause>nul
Call :libType erase
Call :libType write "Также, можно выводить текст поверх другой строки:"
Call :Delay
Call :libType return 40
Call :libType echo "  НАПРИМЕР, ВОТ ТАК  "
Call :libType echo "Или выводить на экран недавно напечатанную строку"
Call :Delay
Call :libType echo
Call :libType echo
Call :libType write "Ну и конечно же, дописывать к строке"
Call :Delay
Call :libType echo ", как это происходит сейчас."
Call :libType break
Call :libType break
Call :libType autowidth "  Длинные строки можно выводить двумя способами - в первом на строки текст разбивает командный процессор, во втором случае, этим занимается скрипт, удобно разбивая текст на подстроки, помещающиеся по ширине в границы консоли, при желании можно задать отступы, как это видно в этом примере."
Call :libType break
Call :libType break
Call :libType write "Пример длинной строки 1: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin vel dolor non turpis varius tempus. Vestibulum quis posuere mauris. Vivamus ac libero at enim dapibus bibendum. Suspendisse feugiat ante sit amet dui tristique dignissim."
Call :libType break
Call :libType break
Call :libType autowidth "  Пример длинной строки 2: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin vel dolor non turpis varius tempus. Vestibulum quis posuere mauris. Vivamus ac libero at enim dapibus bibendum. Suspendisse feugiat ante sit amet dui tristique dignissim."
Call :libType break
Call :libType break
Call :libType qwrite "    Нажмите любую кнопку для перехода к справке..."
Pause>nul
Call :libType help
Exit
:Delay
ping -n 2 127.0.0.1>nul&Exit /B
Rem =======================================================

Rem Передача параметров функции при вызове из другого батника
Call :libType %*
Exit /B

:libType
Rem Обёртка, вызывающая нужные функции с передачей аргументов
Call :TCheckArguments %1
If %ErrorLevel% NEQ 0 GoTo THelp
Call :TCheckArguments %2
If %ErrorLevel% NEQ 0 GoTo UseSaved
:SaveLine
If /I "%~1"=="autowidth" Call :TMemorizeLastString %2 & Call :TAutoWidth %2
If /I "%~1"=="write" Call :TMemorizeLastString %2 & Call :TWrite %2
If /I "%~1"=="qwrite" Call :TMemorizeLastString %2 & Call :TQuickWrite %2
If /I "%~1"=="echo" Call :TMemorizeLastString %2 & Call :TEcho %2
If /I "%~1"=="return" Call :TReturn %2
If /I "%~1"=="blank" Call :TBlank %2
Exit /B
:UseSaved
If /I "%~1"=="help" Call :THelp
If /I "%~1"=="--help" Call :THelp
If /I "%~1"=="autowidth" Call :TAutoWidth "%$SavedString%"
If /I "%~1"=="write" Call :TWrite "%$SavedString%"
If /I "%~1"=="qwrite" Call :TQuickWrite "%$SavedString%"
If /I "%~1"=="echo" Call :TEcho "%$SavedString%"
If /I "%~1"=="break" Call :TBreakLine
If /I "%~1"=="return" Call :TReturn
If /I "%~1"=="blank" Call :TBlank
If /I "%~1"=="erase" Call :TEraseString
If /I "%~1"=="clear" Call :TClearLastString
Exit /B

:THelp
Rem Встроенная помошь
Cls
Echo.
Echo                                                    СИНТАКСИС ФУНКЦИИ :libType
Echo.
Echo  (call %~nx0 команда "текст") или (call %~nx0 команда)
Echo  любая введенная строка запоминается до ввода следующей
Echo.
Echo    call %~nx0 help (или --help)
Echo  Показать эту справку
Echo.
Echo    call %~nx0 echo "текст"
Echo  Вывод указанной строки текста с переводом строки в конце, дублирует работу echo.
Echo.
Echo    call %~nx0 echo
Echo  Вывод последней запомненной строки с переводом строки в конце, дублирует работу echo.
Echo.
Echo    call %~nx0 write "текст"
Echo  Вывод указанной строки текста
Echo.
Echo    call %~nx0 write
Echo  Вывод последней запомненной строки текста
Echo.
Echo  call %~nx0 qwrite "текст"
Echo  Быстрый вывод указанной строки текста
Echo.
Echo    call %~nx0 qwrite
Echo  Быстрый вывод последней запомненной строки текста
Echo.
Echo    call %~nx0 autowidth "текст"
Echo  Вывод указанной строки текста с принудительным разбиением по ширине консоли
Echo.
Echo    call %~nx0 autowidth
Echo  Вывод последней запомненной строки текста с принудительным разбиением по ширине консоли
Echo.
Echo    call %~nx0 break
Echo  Вставить перевод строки
Echo.
Echo    call %~nx0 erase
Echo  Стереть текущую строку и вернуть курсор к началу
Echo.
Echo    call %~nx0 return число
Echo  Возвратить курсор на n символов (действует только в пределах строки)
Echo.
Echo    call %~nx0 return
Echo  Возвратить курсор на начало последней запомненной строки текста (действует только в пределах строки)
Echo.
Echo    call %~nx0 blank число
Echo  Заполнить строку длинной n пробелами
Echo.
Echo    call %~nx0 blank
Echo  Заполнить последнюю запомненную строку пробелами
Echo.
Echo    call %~nx0 clear
Echo  Очистить запомненную строку
Echo.
Echo      Нажмите любую кнопку для продолжения...
Pause>nul
Echo.
Echo.
Exit /B     

:TWrite
Rem Посимвольный вывод с имитацией эффекта печатной машинки.
Rem В отличии от Echo, не переводит на новую строку в конце текста.
If Not Defined $Text Set $Text=%~1
If Not Defined $Text Exit /B
<nul Set /P $Text=%$Text:~0,1%
Ping -n 1 127.0.0.1>nul
Set $Text=%$Text:~1%
If Defined $Text (GoTo :TWrite) Else (Exit /B)

:TQuickWrite
Rem То же самое, что и TWrite, но без задержки
If Not Defined $Text Set $Text=%~1
If Not Defined $Text Exit /B
<nul Set /P $Text=%$Text:~0,1%
Set $Text=%$Text:~1%
If Defined $Text (GoTo :TQuickWrite) Else (Exit /B)

:TReturn
Rem Возврат курсора на заданное число символов в пределах строки
Rem Используется символ "" (0x08)
Call :TGetLenght "%$SavedString%"
Set genChars=%strLenght%
If Not "%1"=="" (Set genChars=%1)
If "%genChars%"=="" (Exit /B)
Set tmpString=
:genReturn
Set tmpString=%tmpString%
Set /A genChars-=1
If %genChars% LEQ 0 (
Call :TQuickWrite "%tmpString%"
Exit /B
) Else (
GoTo genReturn
)

:TBlank
Rem Вывод строки заданной длинны, заполненной пробелами
Rem Используется символ " " (0x20)
Call :TGetLenght "%$SavedString%"
Set genChars=%strLenght%
If Not "%1"=="" (Set genChars=%1)
If "%genChars%"=="" (Exit /B)
Set tmpString=
:genBlank
Set tmpString=%tmpString%
Set /A genChars-=1
If %genChars% LEQ 0 (
Call :TQuickWrite "%tmpString%"
Exit /B
) Else (
GoTo genBlank
)

:TEraseString
Rem Стирание предыдущего выведенного текста
Rem Эффективно только в пределах текущей строки
Call :TReturn
Call :TBlank
Call :TReturn
Exit /B

:TEcho
Rem Алиас для вывода текста и перевода строки. Аналогично Echo.
Call :TWrite %*
Call :TBreakLine
Exit /B

:TGetLenght
Rem Получение длины текстовой строки.
Set /A strLenght=0
Set $String=%~1
:charCounter
If "%$String%"=="" Exit /B
Set /A strLenght+=1
Set $String=%$String:~1%
GoTo charCounter

:TGetConsoleWidth
Rem Получение ширины консоли.
For /F "skip=4 tokens=1,2" %%v In ('mode con') Do (
Set /A conWidth=%%w
Exit /B
)

:TAutoWidth
Rem Форматирование длинных строк под ширину консоли с отступами по 1 символу по бокам.
SetLocal EnableDelayedExpansion
If "!tmpText!"=="" Set tmpText=%~1
Call :TGetConsoleWidth
Set /A conWidth-=2
:printString
Call :TGetLenght "!tmpText!"
If !strLenght! GTR %conWidth% (
Call :TWrite " !tmpText:~0,%conWidth%!"
Echo.
Set tmpText=!tmpText:~%conWidth%!
GoTo printString
) Else (
Call :TWrite " !tmpText!"
Set $tmpText=
)
EndLocal
Exit /B

:TBreakLine
Rem Перевод строки.
Echo.
Exit /B

:TMemorizeLastString
Rem Запоминание выводимой строки.
Set $SavedString=%~1
Exit /B

:TClearLastString
Rem Очистка запомненной строки.
Set $SavedString=
Exit /B

:TCheckArguments
Rem Проверка на наличие аргументов.
Set tmpVar=%~1
If "%tmpVar%"=="" (Exit /B 1) Else (Exit /B 0)


gora 06-03-2011 14:45 1628564

На Win 7 текст выводится без пробелов (и х86, и х64)

njg 27-07-2011 22:57 1721165

Просто шикарно выглядит!

Foreigner 27-07-2011 23:34 1721183

Вложений: 1
В cmd не хватает управляющих последовательностей (escape sequences). За чем их выпилили в NT-линейке не понятно. С их помощью все это делается чуть ли не в одну строчку. Хорошо что сторонние разработчики не оставили этого без внимания.
Давно и успешно пользуюсь ansicon

Vadim.Repin@vk 21-03-2021 15:26 2953552

Спасибо топикстартеру!!! Отличный скрипт.
Однако, начиная с Win7 мелкософты либо накосячили, либо намеренно начали триммировать слева строки при выводе через <nul set /p, в результате терялись пробелы.
Та же петрушка и в Win10

Придумал следующее решение:

Заменить в блоках :TWrite и :TQuickWrite
вывод <nul Set /P $Text=%$Text:~0,1% на условный через проверку:
IF "%$Text:~0,1%"==" " (<nul Set /p s=". ")ELSE (<nul Set /P $Text=%$Text:~0,1%) - т.е. строка начинается с точки, за ней следует BackSpace и только потом пробел.

Пример:
Код:

:TWrite
Rem Посимвольный вывод с имитацией эффекта печатной машинки.
Rem В отличии от Echo, не переводит на новую строку в конце текста.
If Not Defined $Text Set $Text=%~1
If Not Defined $Text Exit /B
::Начиная с Win7 просходит триммирование строки спереди, т.е. пробелы игнорируются, поэтому приходится изворачиваться
IF "%$Text:~0,1%"==" " (<nul Set /p s=". ")ELSE (<nul Set /P $Text=%$Text:~0,1%) 
Ping -n 1 127.0.0.1>nul
Set $Text=%$Text:~1%
If Defined $Text (GoTo :TWrite) Else (Exit /B)

:TQuickWrite
Rem То же самое, что и TWrite, но без задержки
If Not Defined $Text Set $Text=%~1
If Not Defined $Text Exit /B
::Начиная с Win7 просходит триммирование строки спереди, т.е. пробелы игнорируются, поэтому приходится изворачиваться
IF "%$Text:~0,1%"==" " (<nul Set /p s=". ")ELSE (<nul Set /P $Text=%$Text:~0,1%) 
Set $Text=%$Text:~1%
If Defined $Text (GoTo :TQuickWrite) Else (Exit /B)


alpap 21-03-2021 17:19 2953566

оно?
Код:

@echo off
for /f %%a in ('"prompt $H& for %%# in (1) do rem"') do set /p z="%%a                    Если нужны пробелы в начале: "
for /f %%a in ('"prompt $H& for %%# in (1) do rem"') do <nul set /p z="%%a                    Если нужны пробелы в начале"& echo:
pause


Vadim.Repin@vk 22-03-2021 01:16 2953596

Не знаю. Нет наверное. Команда Echo без проблем выводит пробелы в начале слова без дополнительных усилий.
А вот <nul Set /p s=" R" начиная с Win7 имеет глюк и выводит только голую R. Поэтому код с посимвольным выводом, например для имитации эффекта печатной машинке печатал всё без пробелов.

Вот я и придумал, как заставить напечатать голый пробел в строку при условии, что она этого не хочет делать ))))


Время: 02:00.

Время: 02:00.
© OSzone.net 2001-