command line - mac - Cómo animar la línea de comando?
que es cli en informatica (8)
Siempre me he preguntado cómo las personas actualizan una línea anterior en una línea de comando. un gran ejemplo de esto es cuando se usa el comando wget en Linux. Crea una especie de barra de carga ASCII que se ve así:
[======>] 37%
y, por supuesto, la barra de carga se mueve y el porcentaje cambia, pero no forma una nueva línea. No puedo encontrar la manera de hacer esto. ¿Alguien me puede apuntar en la dirección correcta?
Aquí está la respuesta para su pregunta ... (Python)
def disp_status(timelapse, timeout):
if timelapse and timeout:
percent = 100 * (float(timelapse)/float(timeout))
sys.stdout.write("progress : ["+"*"*int(percent)+" "*(100-int(percent-1))+"]"+str(percent)+" %")
sys.stdout.flush()
stdout.write("/r /r")
Como continuación de la respuesta de Greg , aquí hay una versión extendida de su función que le permite mostrar mensajes de varias líneas; simplemente pase una lista o tupla de las cadenas que desea mostrar / actualizar.
def status(msgs):
assert isinstance(msgs, (list, tuple))
sys.stdout.write(''''.join(msg + ''/n'' for msg in msgs[:-1]) + msgs[-1] + (''/x1b[A'' * (len(msgs) - 1)) + ''/r'')
sys.stdout.flush()
Nota: Solo he probado esto usando un terminal de Linux, por lo que su kilometraje puede variar en los sistemas basados en Windows.
El secreto es imprimir solamente / r en lugar de / n o / r / n en el y de la línea.
se llama retorno de carro y mueve el cursor al inicio de la línea
/ n se llama alimentación de línea y mueve el cursor en la siguiente línea En la consola. Si solo usa / r sobrescribe la línea escrita anteriormente. Entonces, primero escribe una línea como la siguiente:
[ ]
luego agrega un letrero para cada tic
/r[= ]
/r[== ]
...
/r[==========]
y así. Puedes usar 10 caracteres, cada uno representa un 10%. Además, si desea mostrar un mensaje cuando haya terminado, no olvide agregar también suficientes caracteres blancos para sobrescribir los signos iguales escritos previamente así:
/r[done ]
Hay dos formas en que sé hacer esto:
- Usa el carácter de escape de retroceso (''/ b'') para borrar tu línea
- Utilice el paquete de
curses
, si su lenguaje de programación de elección tiene enlaces para ello.
Y Google reveló los códigos de escape ANSI , que parecen ser una buena manera. Como referencia, aquí hay una función en C ++ para hacer esto:
void DrawProgressBar(int len, double percent) {
cout << "/x1B[2K"; // Erase the entire current line.
cout << "/x1B[0E"; // Move to the beginning of the current line.
string progress;
for (int i = 0; i < len; ++i) {
if (i < static_cast<int>(len * percent)) {
progress += "=";
} else {
progress += " ";
}
}
cout << "[" << progress << "] " << (static_cast<int>(100 * percent)) << "%";
flush(cout); // Required.
}
PowerShell tiene un cmdlet Write-Progress que crea una barra de progreso dentro de la consola que puede actualizar y modificar a medida que se ejecuta su secuencia de comandos.
Si usa un lenguaje de scripting podría usar el comando "tput cup" para hacer esto ... PS Esto es algo de Linux / Unix solo por lo que sé ...
Una forma de hacerlo es actualizar varias veces la línea de texto con el progreso actual. Por ejemplo:
def status(percent):
sys.stdout.write("%3d%%/r" % percent)
sys.stdout.flush()
Tenga en cuenta que usé sys.stdout.write
lugar de print
(esto es Python) porque la print
imprime automáticamente "/ r / n" (carriage-return new-line) al final de cada línea. Solo quiero el retorno de carro que devuelve el cursor al inicio de la línea. Además, el flush()
es necesario porque, de forma predeterminada, sys.stdout
solo sys.stdout
su salida después de una nueva línea (o después de que se llena el buffer).
a continuación está mi respuesta, use las Consoles(Windows) API de Consoles(Windows) , codificación de C.
/*
* file: ProgressBarConsole.cpp
* description: a console progress bar Demo
* author: lijian <[email protected]>
* version: 1.0
* date: 2012-12-06
*/
#include <stdio.h>
#include <windows.h>
HANDLE hOut;
CONSOLE_SCREEN_BUFFER_INFO bInfo;
char charProgress[80] =
{"================================================================"};
char spaceProgress = '' '';
/*
* show a progress in the [row] line
* row start from 0 to the end
*/
int ProgressBar(char *task, int row, int progress)
{
char str[100];
int len, barLen,progressLen;
COORD crStart, crCurr;
GetConsoleScreenBufferInfo(hOut, &bInfo);
crCurr = bInfo.dwCursorPosition; //the old position
len = bInfo.dwMaximumWindowSize.X;
barLen = len - 17;//minus the extra char
progressLen = (int)((progress/100.0)*barLen);
crStart.X = 0;
crStart.Y = row;
sprintf(str,"%-10s[%-.*s>%*c]%3d%%", task,progressLen,charProgress, barLen-progressLen,spaceProgress,50);
#if 0 //use stdand libary
SetConsoleCursorPosition(hOut, crStart);
printf("%s/n", str);
#else
WriteConsoleOutputCharacter(hOut, str, len,crStart,NULL);
#endif
SetConsoleCursorPosition(hOut, crCurr);
return 0;
}
int main(int argc, char* argv[])
{
int i;
hOut = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(hOut, &bInfo);
for (i=0;i<100;i++)
{
ProgressBar("test", 0, i);
Sleep(50);
}
return 0;
}