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(); }