giovedì 27 dicembre 2012

Script COLORATI! - Livello AVANZATO

Ciao a tutti, oggi tratterò un argomento che sta a cuore a molti "scriptomani": come utilizzare i COLORI negli script BATCH (DOS, command line, command prompt, linea di comando, insomma...).

L'utilizzo dei colori è un annosa questione... i metodi proposti hanno tutti quanti qualche compromesso a cui attenersi (ad esempio due punti nella parola colorata, cicli di codice incomprensibile da includere e chi più ne ha più ne metta).

Oggi, per voi, ho messo insieme una cosa MAGICA! Uno script che permette di definire il colore e lo sfondo (potremmo chiamarla evidenziazione) di ciascuna parola di un messaggio che si vuole scrivere a schermo, includendo UNA SOLA RIGA DI CODICE all'interno del vostro script: la chiamata al mio, passandogli le parole come parametro (fino a 9 parole per riga, che mi sembra PIU' CHE SUFFICIENTE).

MA VOLETE METTERE richiedere un'azione ad un utente così:

con richiedergliela COSI' ?!?!?!?!?!?!?:




Allora cominciamo?
Ecco lo script:



@echo off
Setlocal EnableDelayedExpansion
REM setlocal enableextensions

set dstdir=c:\tmpColorDirtoDelete
IF EXIST %dstdir% goto errExist
@mkdir %dstdir%
@cd %dstdir%
set count=0

REM DEFINISCO IL CARATTERE BACKSPACE!
set "$Defines=$BS"    & set "$Details=Create $ESC Ascii-0x1B-27, Expansion insensitive"
   for /f "delims=#" %%a in (

      '"prompt #$H# &echo on &for %%b in (1) do rem"'

   ) do (
      set "%$Defines%=%%a"
      set "%$Defines%=!$BS:~0,1!"
   )


FOR %%a IN (%*) DO (
 FOR /F "usebackq delims=# tokens=1,*" %%b IN ('%%a') DO (
    REM echo %%b sara' di colore %%c
    set /A count=!count!+1
    set nomefile=%%b
    IF %%c.==. (
        set colore=07
    ) ELSE (
    set colore=%%c
    )
    REM SET /P ".=" %%b
    SET /P ".=%$BS% " <nul >%%b
    REM echo !count!>%%b
    REM echo FINDSTR /A:%%c /C:"!count!" /S "%%b"
    REM more %%b
 )
 REM FINE INNER FOR
    REM echo FINDSTR /A:!colore! /C:"!count!" /S "!nomefile!"
    FINDSTR /A:!colore! /C:" " /S "!nomefile!"
    REM goto end
)
REM FINE OUTER FOR
echo.




REM ERROR HANDLING
goto chiusura
:errExist
echo La directory temporanea %dstdir% esiste già. Rimuoverla prima di continuare o cambiare il percorso nel batch.
goto end

:chiusura

:pulizia
cd..
rd /S /Q %dstdir%

:end
 
Si, lo so che è ARABO OSTROGOTO, ma salvandolo in un file ColoraStringa.bat, potrete inviare messaggi colorati dalla stessa cartella semplicemente così:


REM MessaggioColorato
@echo OFF
cls
call ColoraStringa.bat ATTENZIONE#0c Inserisci una cosa variabile#0f
set /P Variabilezz=:

echo %Variabilezz% 
come vedete ho specificato "#xy" per ogni parola che va colorata. Dove x è il colore di SFONDO e y è il colore del TESTO. Potete vedere i codici colore semplicemente digitando "color /?" dal prompt dei comandi.
Che ne dite? Una magia, eh?
Commentiamo insieme questa bellezza: 
 

 
 
@echo off
Setlocal EnableDelayedExpansion
 
Qui dico allo script di non scrivere i comandi dati a schermo e di utilizzare l'espansione delle variabili nei cicli for... OK, l'espansione delle variabili nei cicli for è spiegata brevemente qui .
 


set dstdir=c:\tmpColorDirtoDelete
IF EXIST %dstdir% goto errExist
@mkdir %dstdir%
@cd %dstdir%
set count=0
 
Qui definisco una directory temporanea (che verrà creata e cancellata da ogni esecuzione dello script. Dico che, se esiste, lo script deve terminare con il messaggio definito più avanti. Se non esiste, la creo (mkdir) mi ci sposto dentro (cd) imposto un contatore a 0 (per futuri sviluppi, come ad esempio lo shifting per accettare infiniti parametri). 
 
 
REM DEFINISCO IL CARATTERE BACKSPACE!
set "$Defines=$BS" & set "$Details=Create $ESC Ascii-0x1B-27, Expansion insensitive"
   for /f "delims=#" %%a in (

      '"prompt #$H# &echo on &for %%b in (1) do rem"'

   ) do (
      set "%$Defines%=%%a"
      set "%$Defines%=!$BS:~0,1!"
   ) 

Qui definisco il carattere speciale "BackSpace" che ci servirà per eliminare il carattere ":" che altrimenti sarebbe presente alla fine di ogni parola del messaggio, vedere più avanti. Ok, faccio un po' un giro, ma è il modo più veloce che ho trovato ( Credits: qui THANK YOU dbenham !!!!)


FOR %%a IN (%*) DO (
 FOR /F "usebackq delims=# tokens=1,*" %%b IN ('%%a') DO (
    
    set /A count=!count!+1
    set nomefile=%%b
    IF %%c.==. (
        set colore=07
    ) ELSE (
    set colore=%%c
    )
    
    SET /P ".=%$BS% " <nul >%%b
     )
 REM FINE INNER FOR
    
    FINDSTR /A:!colore! /C:" " /S "!nomefile!"
    REM goto end
)
REM FINE OUTER FOR
echo.
 
Qui è il bello della cosa. Guardando qui ( THANK YOU GrellesLicht28 ) ho scoperto che è possibile colorare le parole con un ingegnoso trucco: usare il comando FINDSTR per colorare il nome del file nella ricerca sui file, e far apparire più stringhe sulla stessa riga.

Ovviamente non ho resistito alla tentazione di immetterlo in un ciclo FOR per tutti gli argomenti passati.... (quella è solo farina del mio sacco).

Quindi creo 2 cicli FOR, il primo cicla per ogni parametro passato al batch: (%*) vuol dire tutti i parametri.
Il secondo FOR prende il parametro in questione (gli viene passato un parametro alla volta) e separa la parte prima di '#' da quella dopo, chè è il colore (delims =  #), mettendo la prima nella variabile %%b e la seconda in %%c (come ho spiegato altrove).

Aumento il contatore ad ogni ciclo ( set /A count=!count!+1 ).

Imposto il nome del file da creare e poi ricercare.

Imposto il colore e, se non è passato alcun colore per quella parola, lo imposto al colore standard della shell (07).

Faccio il "trucco" del SET per scrivere sulla stessa riga ( SET /P ".=%$BS% " %%b ), impostando però il carattere da aggiungere in fondo alla parola come carattere backspace (cancella 1 carattere all'indietro), per togliermi dalle scatole i fastidiosi 2 punti che il comando successivo mi lascia. L'output del SET lo "sparo" dentro il file (%%b)

FINALMENTE uso FINDSTR per cercare uno spazio vuoto all'interno del file che ha come NOME DEL FILE la parola che vogliamo stampare a schermo, impostando (con l'opzione /A) come dovrà essere colorato il nome del file (che ripeto E' la parola che vogliamo stampare a schermo).
( FINDSTR /A:!colore! /C:" " /S "!nomefile!"  )

Contorto (chi mi conosce sa che, per me, questo livello di contorsione è nulla), ma funziona!!!!! e ALLA GRANDE!

Provate a richiamare il batch aprendo una shell e spostandovi nella cartella dove è salvato, poi scrivendo ColoraStringa.bat pippo#0c e' ROSSO#0c

Se vi è stato utile questo articolo o semplicemente vi è piaciuto, commentate, commentate commentate!

Buon divertimento!

8 commenti:

  1. Non funziona! Mi dice di dover eliminare "tmpColorDirtoDelete", la elimino, eseguo di nuovo il file che contiene il mio programma + il tuo trucchetto ma non mostra più niente.

    RispondiElimina
    Risposte
    1. Ciao, ora riscarico il codice e riprovo.
      Che sistema operativo hai?

      Elimina
    2. Trovato l'errore:
      ho corretto la riga 35 in
      SET /P ".=%$BS% " %%b

      era erroneamente riportata così online:
      SET /P ".=%$BS% " %%b

      Probabilmente un errore nel copia-incolla. :-)

      Adesso se copi e incolli il codice dall'articolo funziona.

      Elimina
    3. Ehm... non riesco a correggere la stringa. Probabilmente il motore di blogspot me la modifica...

      la stringa corretta da impostare è questa:
      SET /P ".=%$BS% " < nul >%%b

      Elimina
    4. OK, sono riuscito. il codice nell'articolo adesso è giusto.
      Ho provato a copiarlo e incollarlo e funziona. :-)

      Elimina
  2. fantastico, bel progetto. ma se volessi scrivere due parole colorate attaccate? senza lo spazio in mezzo intendo per esempio
    GIALLO#0eVERDE#0a

    RispondiElimina
  3. Ciao! Grazie mille.
    Ho fatto alcune prove e confermo che con questo sistema è possibile colorare solo singole parole.
    :-)

    RispondiElimina

I commenti sono soggetti a moderazione, prima di essere pubblicati.

Qualsiasi contenuto illecito, immorale o che io ritenga (arbitrariamente) offensivo od inappropriato, verrà cancellato.