Batch Text animation?

2 Antworten

demo.cmd

@echo off
for /f "delims=;" %%a in ('"echo prompt $H;|cmd /k"') do set "BS=%%a"

set "string=          "hallo huhu"   Beispiel Blubb Blubb Blubb"

for /f delims^=^ eol^= %%a in ('"cmd /u /c echo:%string%|find /v """') do (
    set/p "=.%BS%%%a" <nul
    pathping localhost /q 1 /p 100 >nul
    rem Alternative für Pathping: for /l %%. in (1,1,2000) do (call )
)
echo:
pause

Hintergrund der "Geschichte":

cmd /u /c echo: ... startet intern eine neue Instanz von cmd mit UCS-2 le -unterstützung und gibt einen String aus.

  • In einem UCS-2-Text wird Zeichen mit einem Wert unter 255 (ASCII-Zeichen) ein 0-wert vorangestellt (aus einem A mit dem 8bit-Hexwert 41 wird damit der 16bit-Hexwert 0041)
  • in normalen ASCII-Texten wird ein solcher einfacher 0-Wert jedoch als Stringende angesehen. Damit wird jeder einzelne Buchstabe beim Übergang von unserem "gewaltsam" Erzwungenen 16Bitmodus in den 8bitmodus zu einem eigenen String und auch einzeln der Laufvariable %%a übergeben.
  • Umlaute etc funktionieren mit diesem Trick nicht!

Die "Mogelei" mit der Backspacevariable:

  • Bei set /p folgt normalerweise nach dem Gleichheitszeichen ein Pronpt (Fragetext) dieser beginnt am linken Rand einer Zeile oder am ende des vorherigen Strings (wenn kein Zeilenvorschub erfolgte) und duldet keine Leerzeichen am Anfang. das kann man verhindern indem ein anderes Zeichen (Punkt) an den Anfang schreibt
set/p "=  Text" <nul  &rem  Leerzeichen  werden Entfernt
set/p "=.  Text" <nul &rem  Leerzeichen  bleiben erhalten
  • Nur muss man den Punkt wieder Loswerden. Das macht ein Backspace-Zeichen (ASCII 08) (Rückwärtslöschen)
  • Das Backspace läst sich jedoch nicht mit der Tastatur in einen Code eingeben und speichern, also muss man es in Batch wieder mal mit einem Trick erzeugen. ...und in der %BS% Variable speichern.

Im Gegensatz zu ping hat pathping eine Granularität von Millisekunden.

Sollte pathping nicht funktionieren, kannst du ersatzweise eine Bremsschleife verwenden

for /l %%. in (1,1,2000) do (call ) &rem 2000 ist die Anzahl der Leerläufe nichts wird getan

... das war die Einfache variante... jetz lasse ich meine Show laufen:

gosttyper_color.cmd

@echo off
chcp 65001 >nul
setlocal enableDelayedExpansion


call :initAnsi
call :initMacro


  rem Farbtabelle für den Regenbogen definieren
set "Regenbogen=,52,88,124,160,196,202,208,214,220,226,190,154,118,82,46,41,36,31,26,21,20,55,53,"
  rem Regenbogen Spiegeln (letzte Farbe zuerst) (auch Variablennamen unterliegen der Kreativität XD)
for %%a in (%Regenbogen%) do (set "negobnegeR=,%%a!negobnegeR!")


  rem mach nen Schmetteling draus
set "RegenbogenBfly=%Regenbogen%%negobnegeR%"


set "ShadesOfGray=237 238 239 240 241 242 243 244 245 246 247 248 249"
for %%a in (%ShadesOfGray%) do (set "notShadesOfGray=,%%a!notShadesOfGray%!")
  rem mach nen Schmetteling draus
set "SoGrayBfly=%ShadesOfGray%%notShadesOfGray%"
set "NightBlue=17"
set "OrangeWave=202 208 214 220 214 208"


  rem initilisiere für die angegebene Farbtabelle jeweils  ein Array mit den Escape seqenzen für 
  rem Hintergrund Fabtabelle.B und Vordergrund Fabtabelle.F
for %%a in (RegenbogenBfly , ShadesOfGray , SoGrayBfly , NightBlue , OrangeWave) do ( call :initANSI_ColorArray %%~a)
)


rem Aufruf:  verzögerung  FarbeTabelleB/F ode  =für Default  "Text  "
%#__gostType% 0 NightBlue.B         ".so geht man mit ""Gänsefüßchen"" & $$ um und ..."
%#__gostType% 0 NightBlue.B         "... so macht man ein   Ausrufezeichen $x  ....."
%#__gostType% 0 NightBlue.B         """..?.+.*.~.§.@.µ.€.|.<.>.&.=.$p.$x.$$..........."""
%#__gostType% 2000 OrangeWave.F     "...$$x=$x.,.$$p=$p.,.$$$=$$.,.""""="".................."
%#__gostType% 2000 OrangeWave.b     "...$$x=$x.,.$$p=$p.,.$$$=$$.,.""""="".................."
%#__gostType% 2000 =                "......................I......................."
%#__gostType% 2000 =                "....................like......................"
%#__gostType% 2000 =                "..................Scripting. ................."
%#__gostType% 0    RegenbogenBfly.B "......................I......................."
%#__gostType% 1000 RegenbogenBfly.B "....................like......................"
%#__gostType% 4000 RegenbogenBfly.B "..............Background Colors..............."
%#__gostType% 8000 SoGrayBfly.B     "..............    some Gray    ..............."
%#__gostType% 2000 RegenbogenBfly.F "......................I......................."
%#__gostType% 2000 RegenbogenBfly.F "....................like......................"
%#__gostType% 2000 RegenbogenBfly.F "..............Foreground Colors..............."
%#__gostType% 20000 ShadesOfGray.F  "..............    more Gray    ..............."


echo ende...
pause
exit /b


:::::: Helper Routines ::::::


:initANSI_ColorArray  %1 VarName Colortable
set ".cIndex=0"
for %%a in (!%1!) do (
      rem Arrays mit Farbsequenzen anlegen BackGround und ForeGround
    set "CArray.%1.F.!.cIndex!=%ESC%[38;5;%%am"
    set "CArray.%1.B.!.cIndex!=%ESC%[48;5;%%am"
    set /a ".cIndex+=1"
)
set "%1.F.cIndex=%.cIndex%"
set "%1.B.cIndex=%.cIndex%"
exit /b


:initMacro
  rem als estes  wird  der else-Zweig aufgelöst beim aufruf  des Macros  folgen die Argumente dem set argv=
  rem im zweiten Schritt wird argv aufgelöst und  die belegten Variablen getunnelt (wegen evt Sonderzeichen)
set #__gostType=for %%. in (1 2) do^
    if %%.==2 (^
        for /f "tokens=1,2*" %%a in ("^!argv^!") do (^
            set __StringToSplit=%%~c^&^
            call :draw __StringToSplit %%~a %%~b^
        )^
    ) else set argv=
exit /b


:initAnsi
  rem  prüfe  ob Escape-Sequenzen  erlaubt sind (Windows 10 v1903)
  rem nur der !!!DWord!!!-Wert ForceV2=0 deaktiviert, alles andere erlaubt Escapesequenzen (ansonsten scheinen ANSISequenzen inzwischen by default unterstützt zu werden)
for /f "tokens=3 delims=." %%a in ('ver') do (
    if %%a geq 18362 (reg query "HKCU\Console" /v "ForceV2"|find "REG_DWORD    0x0">nul && (
            echo Neue Consolenfunktionen  sind ausgeschaltet!) || goto :initAnsiVars
    ) else ( echo Benötige Windows 10 ab Version 1903)
)
timeout 5 >nul
exit /b
)
:initAnsiVars
  rem erzeuge ESC-Zeichen (ASCII 27)
for /f %%. in ('"echo prompt $E|cmd"') do set "ESC=%%."
  rem Cursormacros:
set "saveCursorPos=%ESC%7"
set "loadCursorPos=%ESC%8"
set "CursOff=%ESC%[?25l"
set "CursOn=%ESC%[?25h"

set "resetColor=%ESC%[0m"

  rem Cursor unsichtbar machen
echo %saveCursorPos%%CursOff%
exit /b


::::::  subroutines   :::::


:draw
set "lastColorIndex=-1
set "%~1=!%~1:""="!"
  rem Stringlänge-1 ermitteln
@(echo !%~1!)>"%temp%\%~n0.len"
for %%a in ("%temp%\%~n0.len?") do set /a "%~1.maxIndex=%%~za-3"
for /l %%. in (0,1,!%~1.maxIndex!) do (
    set Char=!char!!%~1:~%%.,1!
      rem kommt ein Platzhalter:
    if "!char!" neq "$" (
          rem für ein Ausrufezeichen?
        if /i "!char!"=="$X" set "char=^!"
        if /i "!char!"=="$P" set "char=%%"
        if    "!char!"=="$$" set "char=$"
        set /a "lastColorIndex+=1 , __cNr=lastColorIndex %% %3.cIndex" 2>nul
          rem Fabnummer in den als Laufvariable in den Arrayindex mogeln... (!array!index !! geht nicht)
        for %%. in ("!__cNr!") do (
            echo:%loadCursorPos%!CArray.%~3.%%~.!!char!%saveCursorPos%
        )
          rem Bremsschleife
        for /l %%. in (1,1,%~2)  do (call)
        set "char="
    )
)
echo:%resetColor%%saveCursorPos%
exit /b

...wie's Funktioniert? alles im Code Kommentiert 😅 (sonst wäre ich beim schreiben Irre geworden 😵)

So schön das alles ist. Textausgabe in Batch kann nur mit jeder Menge Tricks beherscht werden. steck nicht allzuviel Energie in einen strebenden Gaul. Batch hat nicht mehr viel Zukunft.

Ich empfehle Dir auf Powershell umzusatteln, bevor Batch Dir das Hirn wegbrutzelt.

Obige Demo in powershell:

Demo.ps1

$Text='          "hallo huhu"   Beispiel Blubb Blubb Blubb'
$Text -split $Null| ForEach-Object {
    Write-Host $_ -NoNewline
    Start-Sleep -Milliseconds 50
}
''
pause

..das geht aber auch kurz und schmerzlos:

'          "hallo huhu"   Beispiel Blubb Blubb Blubb'-split ''|%{Write-Host $_ -n;sleep -m 50}

Woher ich das weiß:eigene Erfahrung – Ich mach das seit 30 Jahren

Hallo,

Ja klar, es ist möglich, in einem Batch-Programm Text animiert von links nach rechts erscheinen zu lassen, indem Du einfach Zeichen des Texts nacheinander ausgibst.

zum beispel:

@echo off

setlocal enabledelayedexpansion

:: Text, der animiert angezeigt werden soll

set "text=Hallo, Welt!"

(für Hallo, Welt! gibst du dann deinen text ein)

:: Jedes Zeichen des Texts nacheinander anzeigen

for /l %%i in (0,1,%stringlength%) do (

  call echo|set /p=!text:~%%i,1!

  ping localhost -n 2 > nul

)

echo.

pause

Hierbei wird die ping-Anweisung als Ersatz für einen Sleep-Befehl verwendet, um eine kurze Verzögerung zwischen dem Anzeigen jedes Zeichens zu erzeugen. Es gibt viele verschiedene Wege, um in einem Batch-Script eine Pause einzulegen, aber ping ist ein einfacher Trick, der oft verwendet wird.

Du kannst auch effekte wie Einblendeffekt, Laufschrift oder einen blinkenden text programmieren, ist natürlich etwas komplexer aber machbar

Woher ich das weiß:Hobby – Programmierer

JulianOnFire  22.08.2023, 13:54

ping localhost -n 2 > nul oder einfach ping -n 2 > nul wartet in etwa 2 Sekunden (-n 2) und führt die Batchdatei dann weiter aus. Das kannst du dann so lange einstellen wie du willst. Ich weiß gar nicht ob es da eine Grenze gibt

Erzesel  22.08.2023, 17:53

Hast Du mal probiert ob Dein Code Funktioniert?

geht natürlich nicht!

..wo hast Du %stringlength% definiert? (...und wie ermittelst Du die Länge eines Strings in Batch?) ...und wie gehst Du mit Leerzeichen im Text um (die werde von set/p gefressen)? weshalb call echo mit pipe, stat nul-Input?

prima falsch abgeschrieben! Applaus.

JulianOnFire  22.08.2023, 18:30
@Erzesel

Das war ein Beispielcode du irsel. Hat bei mir funktioniert. Er hätte es nur umändern müssen

JulianOnFire  22.08.2023, 18:46
@Erzesel

@echo off

setlocal enabledelayedexpansion

:: Text, der animiert angezeigt werden soll

set "text=Hallo, Welt!"

:: Länge des Texts berechnen

set "length=0"

for /l %%A in (12,-1,0) do (

  set /a "length|=1<<%%A"

  for %%B in (!length!) do if "!text:~%%B,1!"=="" set /a "length&=~1<<%%A"

)

:: Jedes Zeichen des Texts nacheinander anzeigen

for /l %%i in (0,1,!length!) do (

  if "!text:~%%i,1!"==" " (

    <nul set /p "= "

  ) else (

    <nul set /p=!text:~%%i,1!

  )

  ping localhost -n 2 > nul

)

echo.

pause

  1. Die Stringlänge wird berechnet, indem die Bit-Shift-Technik verwendet wird, um die maximale Länge des Strings zu ermitteln.
  2. Bei der Verarbeitung von Leerzeichen wird

<nul set /p "= "

verwendet, um Leerzeichen korrekt zu behandeln.

3.Der Input

<nul

ersetzt den

echo
-Teil, um die Ausgabe ohne Zeilenumbruch zu erzeugen.

Erzesel  22.08.2023, 20:33
@JulianOnFire

Bist du Du dir sicher , das Deine Length-Methode den richtigen Wert ausgibt.

Hallo, Welt! hat 12 Zeichen! Deine Methode liefert 11.

Du musst mir nichts erklären , ich weiß selbst wo bei Dir der Hase im Pfeffer liegt. (die Methode rechnet schon richtig, aber benötigt "setlocal enabledelayedexpansion" und frist dadurch Ausrufezeichen. Deshalb würde ich mal sagen unzweckmäßig! Zudem ist die Methode wie Du sie konzipiert hast Laaangsam.

Das geht viel bequemer:

for /f "skip=1 delims=:" %%a in ('"(echo:%text%&echo:)|findstr /o $"') do set /a "length=%%a-3"

...ist aber auch nicht das Rennpferd.

Das schnellste (solange man nicht mit einem Diskettenlaufwerk arbeitet) ist einfach das schreiben des Textes in eine temporäre Datei und ermitteln der Dateigröße (minus Schutzquotes und Zeilenvorschub)

echo "%Text%">"%temp%\strLen.tmp"
for /f "tokens=*" %%a in ("%temp%\strLen.tmp") do set /a "length=%%~za - 4"
echo %length%
Bei der Verarbeitung von Leerzeichen wird <nul set /p "= "
verwendet, um Leerzeichen korrekt zu behandeln.

Nö geht nicht...

Das soll geschrieben werden:

Hallo, Welt!

Und das wird geschrieben:

Hallo,Welt
Hat bei mir funktioniert.

Wenn Du das verschlucken von Zeichen als korrekte Funktion tolerierst?

Sorry ich kanns mir nicht verkneifen : wenn du als Feuerwehrmann oder Sanitäter genauso "tolerant" arbeitest, würde ich im Ernstfall dann doch lieber auf Deine Anwesenheit verzichten 🤪

Ok, mir musst Du nichts über Batch erzählen.

JulianOnFire  22.08.2023, 20:59
@Erzesel

Du Vergleichst Notfallmedizin mit programmieren. Ist ja genau so wie Äpfel mit Birnen zu vergleichen. Das zeigt ja schon alles über dich...

Muss ich jetzt einfach so sagen : So Leute wie dich würde ich auch nicht gerne behandeln wollen. Das sind dann meistens die Leute, die mir was erzählen wollen, wenn wir 10 Minuten brauchen weil kein anderer rtw im Umkreis ist.

Nur weil du dich jetzt schlauer machen musst und dich in den Vordergrund stellen willst 😂😂. Was willst du mir denn erzählen?

Mein Code funktioniert wenn auch langsam. Für seine "privaten Zwecke" reicht es Herr Professor, Sorry!

Wie du deinen Rang als Experte mit so einer Art bekommen hast wundert mich auch.

Gut aber das Gute frage Team macht eben auch mal Fehler ☠️

Erzesel  22.08.2023, 21:20
@JulianOnFire
Ist ja genau so wie Äpfel mit Birnen zu vergleichen.

Du irrst... Wenn man eine Arbeit verrichtet, gleich welche, dann exakt.

Ich habe die Steuerung für eine chemische Industrieanlage entwickelt, da gibts keine Fehlertoleranz. PI mal Daumen oder wie Du es auszudrücken pflegst "privaten Zwecke"  und so eine Anlage fliegt in die Luft (mit allen Folgen)

Expertise erreicht man nicht für lobhudelei sondern auch dafür das man sich Kritik stellen kann und Lehren zieht und den Arsch in der Hose hat auch Kritik zu üben!