d-examples/source/examples/shell/ospinner.d

109 lines
2.7 KiB
D
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

module examples.shell.ospinner;
import std.stdio;
import core.thread;
import core.time;
import core.stdc.signal : signal, SIGINT;
import core.stdc.stdio : fprintf;
import core.stdc.stdlib : exit;
// Обработчик сигнала Ctrl+C
extern (C) void handleCtrlC(int sig) nothrow @nogc
{
// Используем fprintf для вывода в stderr
fprintf(core.stdc.stdio.stderr, "\033[?25h\r\033[KInterrupted!\n");
exit(0);
}
// Абстрактный базовый класс для команд
private abstract class Command
{
private string message = "Processing..."; // Сообщение для спиннера
private string name = "Default command"; // Наименование команды
private immutable dchar[] spinner = [
'⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'
]; // Символы спиннера
// Абстрактный метод, который должны реализовать наследники
protected abstract void execute();
this(string commandName)
{
name = commandName;
}
// Метод для запуска команды с анимацией спиннера
final void run()
{
ulong i = 0;
bool taskCompleted = false;
// Создаём поток для выполнения команды
auto worker = new Thread({
try
{
execute(); // Выполняем логику команды
}
catch (Exception e)
{
stderr.writefln("Error: %s", e.msg);
}
taskCompleted = true;
});
// Скрываем курсор
write("\033[?25l");
stdout.flush();
// Запускаем задачу
worker.start();
// Цикл анимации спиннера
while (!taskCompleted)
{
writef("\r%s: %s %c", name, message, spinner[i]);
stdout.flush();
i = (i + 1) % spinner.length;
Thread.sleep(dur!("msecs")(100));
}
// Ждём завершения потока
worker.join();
// Восстанавливаем курсор и очищаем строку
writef("\033[?25h\r\033[K%s: Done!\n", name);
}
// Метод для установки пользовательского сообщения
void setMessage(string msg)
{
message = msg;
}
}
// Пример команды с выводом
private class LongRunningCommand : Command
{
this(string commandName)
{
super(commandName);
}
override void execute()
{
Thread.sleep(dur!("seconds")(5)); // Имитация работы
}
}
void oSpinnerShell()
{
// Устанавливаем обработчик для SIGINT (Ctrl+C)
signal(SIGINT, &handleCtrlC);
// Создаём команду
auto cmd = new LongRunningCommand("Test");
cmd.setMessage("Working on task...");
writeln("Running with spinner:");
cmd.run();
}