109 lines
2.7 KiB
D
109 lines
2.7 KiB
D
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();
|
||
}
|