Я писал программу командной строки, которая будет иметь строку состояния, во многом как wget.
Основная проблема, с которой я сталкиваюсь: как я удаляю то, что я уже отправил в stdout/stderr?
Я имел на идее: используйте символ клавиши Backspace '\b' и сотрите вывод, который я отправил. Это - лучший способ? Действительно ли это - единственный путь? Существует ли лучший путь?
PS: Я не хочу использовать что-либо как ncurses. Простой C.
Спасибо
Править:
Я могу также подняться и/или вниз? Пример: у Меня есть 10 строк вывода, я хочу изменить 3-ю строку от Doing ABC
кому: ABC: Done
. Как я могу сделать это?
Кроме того, кто-либо может отправить больше деталей о том, каковы символы VT102? Каковы его возможности? Отправьте хорошие ссылки на это, если у Вас есть кто-либо.
Спасибо
Используйте '\ r', чтобы вернуться в начало строки и, возможно, переписать всю строку.
Ищите управляющие последовательности VT102 - это последовательности символов ESC ... для управления вашим терминалом.
Основные управляющие символы форматирования - это возврат (\ b), табуляция (\ t), новая строка (\ n) и возврат каретки (\ r ). Если вам нужно больше, вы можете использовать escape-последовательности ANSI X3.64 / ISO / IEC 6429 / ECMA-48 ; по крайней мере подмножество VT100 распознается большинством современных терминалов и эмуляторов. Преимущество использования ncurses заключается в том, что он будет искать возможности вашего конкретного терминала, и поэтому он будет работать, даже если ваш терминал использует другой набор управляющих последовательностей.
Вы должны помнить, что что касается обычных подпрограмм stdio, stdout
- это просто поток байтов без присущих характеристик отображения ; это зависит от целевого устройства, которым может быть что угодно, от обычного терминала в стиле VT100 до терминала для печатных копий, листового принтера и плоттера и т. д.
IMO, вам гораздо лучше использовать библиотеку вроде ncurses
, чем пытаться собрать свой собственный код управления дисплеем с escape-кодами VT100, даже для относительно простой задачи вроде это. Я знаю, что вы хотите придерживаться "старого доброго Си", но эта задача выходит за рамки старого доброго Си.
Небольшое изменение вашего собственного решения:
Вы также можете напечатать возврат каретки ( \ r
), который вернет вас в начало строки.
Профилировщик Hibernate Profiler может генерировать динамические отчеты из статистики времени выполнения Hibernate. Генерируются различные предупреждения, такие как предупреждение о SELECT N + 1.
Его можно использовать в системе непрерывной интеграции.
-121--4481922-Я держу свои приложения на краю 2,3, но поскольку в 3 году есть много фундаментальных изменений в Rails, я, вероятно, установлю бета-версию, поработаю над их преобразованием и надеюсь быть готовым к моменту выхода в качестве стабильного.
Я также рад, что есть много времени перед RailsConf, так что я действительно могу познакомиться с новыми функциями Rails 3 и не буду чувствовать себя потерянным/перегруженным там.
-121--3653480-Это индикатор прогресса для bash.
function gauge()
{
progress="$1"
total="$2"
width=`tput cols`
let gwidth=width-7
if [ "$total" == "0" ]; then
percent=100
else
set +e
let percent=progress*100/total;
set -e
fi
set +e
let fillcount=percent*gwidth/100
let nofillcount=gwidth-fillcount
set -e
fill="";
if [ "$fillcount" -gt "0" ]; then
for i in `seq $fillcount`; do
fill="$fill""|"
done
fi;
nofill=""
if [ "$nofillcount" -gt "0" ]; then
for i in `seq $nofillcount`; do
nofill="$nofill"" ";
done
fi
echo -e -n "\r[""$fill""$nofill""] ""$percent""%";
}
О индикаторе прогресса: что-то вроде этого?
#include <stdio.h>
#include <unistd.h>
typedef enum
{
false=0,
true=!false
} bool;
typedef struct
{
/* Start delimiter (e.g. [ )*/
char StartDelimiter;
/* End Delimiter (e.g. ] )*/
char EndDelimiter;
/* Central block (e.g. = )*/
char Block;
/* Last block (e.g. > ) */
char CurBlock;
/* Width of the progress bar (in characters) */
unsigned int Width;
/* Maximum value of the progress bar */
double Max;
/* True if we have to print also the percentage of the operation */
bool PrintPercentage;
/* True if the bar must be redrawn;
note that this must be just set to false before the first call, the function then will change it by itself. */
bool Update;
} ProgressBarSettings;
/* Prints/updates the progress bar */
void PrintProgressBar(double Pos, ProgressBarSettings * Settings);
/* Inits the settings of the progress bar to the default values */
void DefaultProgressBar(ProgressBarSettings * Settings);
int main()
{
int i;
/* Init the bar settings */
ProgressBarSettings pbs;
DefaultProgressBar(&pbs);
pbs.Max=200;
pbs.Width=60;
printf("Progress: ");
/* Show the empty bar */
PrintProgressBar(0,&pbs);
for(i=0;i<=pbs.Max;i++)
{
/* Wait 50 msec */
usleep(50000);
/* Update the progress bar */
PrintProgressBar(i,&pbs);
}
puts(" Done");
return 0;
}
/* Inits the settings of the progress bar to the default values */
void DefaultProgressBar(ProgressBarSettings * Settings)
{
Settings->StartDelimiter='[';
Settings->EndDelimiter=']';
Settings->Block='=';
Settings->CurBlock='>';
Settings->PrintPercentage=true;
Settings->Update=false;
Settings->Max=100;
Settings->Width=40;
}
/* Prints/updates the progress bar */
void PrintProgressBar(double Pos, ProgressBarSettings * Settings)
{
/* Blocks to print */
unsigned int printBlocks=(unsigned int)(Settings->Width*Pos/Settings->Max);
/* Counter */
unsigned int counter;
/* If we are updating an existing bar...*/
if(Settings->Update)
{
/* ... we get back to its first character to rewrite it... */
for(counter=Settings->Width+2+(Settings->PrintPercentage?5:0);counter;counter--)
putchar('\b');
}
else
Settings->Update=true; /* next time we'll be updating it */
/* Print the first delimiter */
putchar(Settings->StartDelimiter);
/* Reset the counter */
counter=Settings->Width;
/* Print all the blocks except the last; in the meantime, we decrement the counter, so in the end we'll have
the number of spaces to fill the bar */
for(;printBlocks>1;printBlocks--,counter--)
putchar(Settings->Block);
/* Print the last block; if the operation ended, use the normal block, otherwise the one for the last block */
putchar((Settings->Max==Pos)?Settings->Block:Settings->CurBlock);
/* Another block was printed, decrement the counter */
counter--;
/* Fill the rest of the bar with spaces */
for(;counter;counter--)
putchar(' ');
/* Print the end delimiter */
putchar(Settings->EndDelimiter);
/* If asked, print also the percentage */
if(Settings->PrintPercentage)
printf(" %3d%%",(int)(100*Pos/Settings->Max));
/* Flush the output buffer */
fflush(stdout);
};
Обратите внимание: unistd.h и usleep - это просто симулирование прогресса операции, сам индикатор прогресса использует стандартную библиотеку. Его единственное предположение о выходном потоке заключается в том, что \b фактически попадает в предыдущий написанный символ. Я успешно пробовал его на Windows и Linux (с gnome-терминалом), не знаю, корректно ли он работает с некоторыми терминальными эмуляторами. Извините за излишнее количество комментариев, я написал его для другого форума, где мне нужно было прагматично объяснить каждую строчку кода новичку на Си.
Также есть возможность использовать Ncurses , который является библиотекой для текстового пользовательского интерфейса. , где такое поведение должно иметь некоторую поддержку. Однако для чего-то вроде этого это может быть излишним.