Добавлен новый модуль демонстрации объектно-ориентированного подхода к созданию анимации спиннера в консоли

This commit is contained in:
Alexander Zhirov 2025-05-16 01:35:01 +03:00
parent 45f2985d21
commit 16c77dc28d
Signed by: alexander
GPG key ID: C8D8BE544A27C511
6 changed files with 129 additions and 11 deletions

View file

@ -0,0 +1,109 @@
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();
}