diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..423cfbf --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,16 @@ +name: Публикация релиза + +on: + release: + types: + - published + workflow_dispatch: + +jobs: + release: + uses: autumn-library/workflows/.github/workflows/release.yml@v1 + with: + oscript_version: stable + package_mask: "progbar-*.ospx" + secrets: + PUSH_TOKEN: ${{ secrets.PUSH_TOKEN }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..55aeeb8 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,19 @@ +name: Тестирование + +on: + push: + pull_request: + workflow_dispatch: + +jobs: + test: + strategy: + fail-fast: false + matrix: + oscript_version: ['stable', 'dev'] + uses: autumn-library/workflows/.github/workflows/test.yml@v1 + with: + oscript_version: ${{ matrix.oscript_version }} + test_engine: oneunit + test_dir_paths: tests + build_package: true diff --git a/.gitignore b/.gitignore index 305913c..562f619 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ *.ospx +oscript_modules diff --git a/packagedef b/packagedef index db70ebb..b5a5a02 100644 --- a/packagedef +++ b/packagedef @@ -1,7 +1,10 @@  Описание.Имя("progbar") - .Версия("1.3") + .Версия("1.4") + .ВерсияСреды("2.0.0") .ВключитьФайл("src") .ВключитьФайл("LICENSE") .ВключитьФайл("lib.config") .ВключитьФайл("readme.md") + + .РазработкаЗависитОт("asserts", "1.6.2") diff --git "a/src/\320\237\321\200\320\276\320\263\321\200\320\265\321\201\321\201\320\221\320\260\321\200.os" "b/src/\320\237\321\200\320\276\320\263\321\200\320\265\321\201\321\201\320\221\320\260\321\200.os" index 275aeb4..c51bbad 100644 --- "a/src/\320\237\321\200\320\276\320\263\321\200\320\265\321\201\321\201\320\221\320\260\321\200.os" +++ "b/src/\320\237\321\200\320\276\320\263\321\200\320\265\321\201\321\201\320\221\320\260\321\200.os" @@ -21,6 +21,9 @@ Перем СтрокаЗаполненногоБара; Перем ЦветБара; +Перем КурсорУправляем; +Перем ВыводВозможен; + /////////////////////////////////////////////////////////////////////////////// // Начать @@ -36,7 +39,17 @@ Процедура Начать(КоличествоШагов, Подсказка = "", ВыводитьПроценты = ИСТИНА, ВыводитьНомерИКоличество = ИСТИНА, ВыводитьВремя = ИСТИНА) Экспорт - ЦветТекстаКонсоли = Консоль.ЦветТекста; + Попытка + + ЦветТекстаКонсоли = Консоль.ЦветТекста; + + Исключение + + // цвет текста недоступен там же, где и остальная консоль: рисовать будет нечем + ЦветТекстаКонсоли = ЦветКонсоли.White; + ВыводВозможен = Ложь; + + КонецПопытки; ТекстПодсказки = Подсказка; НадоВыводитьПроценты = ВыводитьПроценты; НадоВыводитьНомерИКоличество = ВыводитьНомерИКоличество; @@ -90,12 +103,49 @@ КонецЕсли; Если Подсказка <> Неопределено Тогда - + ТекстПодсказки = Подсказка; - + КонецЕсли; - - Консоль.ВидимостьКурсора(Ложь); + + Длительность = ТекущаяДата() - ДатаНачала; + + Нарисовать(); + +КонецПроцедуры // СделатьШаг + +// Нарисовать +// Рисует строку прогресса, если консоль это позволяет. +// +// Управление курсором работает только в живой консоли: при перенаправленном выводе +// позиция курсора недоступна (на Windows - "The handle is invalid"), а в сборке окна +// нет вовсе и его ширина равна нулю. Прогресс-бар - украшение, и из-за него работа +// падать не должна: если рисовать нельзя, бар молча замолкает до конца прогона, +// а счётчик шагов и длительность продолжают считаться. +// +Процедура Нарисовать() + + Если Не ВыводВозможен Тогда + + Возврат; + + КонецЕсли; + + Попытка + + НарисоватьСтроку(); + + Исключение + + ВыводВозможен = Ложь; + + КонецПопытки; + +КонецПроцедуры // Нарисовать() + +Процедура НарисоватьСтроку() + + СкрытьКурсор(Ложь); Консоль.КурсорЛево = 0; Для Ит = 1 По Консоль.Ширина - 1 Цикл @@ -103,7 +153,7 @@ КонецЦикла; Консоль.КурсорЛево = 0; - + Если ЗначениеЗаполнено(ТекстПодсказки) Тогда Консоль.ЦветТекста = ЦветКонсоли.Green; @@ -127,17 +177,15 @@ СтрокаНеЗаполненногоПрогресса = Сред(СтрокаПустогоБара, Позиция); Консоль.Вывести(СтрШаблон("%1 |%2%3| ", Значек, СтрокаЗаполненногоПрогресса, СтрокаНеЗаполненногоПрогресса)); - + Если НадоВыводитьПроценты Тогда - + Консоль.ЦветТекста = ЦветКонсоли.Yellow; Консоль.Вывести("" + Цел(ПоследнийШаг / КоличествоШаговПрогресса * 100) + "% "); - + КонецЕсли; - - Длительность = ТекущаяДата() - ДатаНачала; - Если НадоВыводитьВремя Тогда + Если НадоВыводитьВремя Тогда ДлительностьСтрока = ВремяВСтроку(Длительность); Прогноз = (Длительность * КоличествоШаговПрогресса) / ПоследнийШаг - Длительность; @@ -149,22 +197,37 @@ КонецЕсли; - Консоль.ВидимостьКурсора(Истина); + СкрытьКурсор(Истина); Консоль.ЦветТекста = ЦветТекстаКонсоли; - -КонецПроцедуры // СделатьШаг + +КонецПроцедуры // НарисоватьСтроку() // Завершить // Завершает вывод строки прогресс бара // Процедура Завершить() Экспорт - + Инициализирован = Ложь; Длительность = ТекущаяДата() - ДатаНачала; - Консоль.ВидимостьКурсора(Истина); - Консоль.ЦветТекста = ЦветТекстаКонсоли; - Консоль.ВывестиСтроку(""); - + + Если Не ВыводВозможен Тогда + + Возврат; + + КонецЕсли; + + Попытка + + СкрытьКурсор(Истина); + Консоль.ЦветТекста = ЦветТекстаКонсоли; + Консоль.ВывестиСтроку(""); + + Исключение + + ВыводВозможен = Ложь; + + КонецПопытки; + КонецПроцедуры // Завершить // ДлительностьВыполнения @@ -248,6 +311,37 @@ КонецФункции // ВремяВСтроку() +// СкрытьКурсор +// Управляет видимостью курсора там, где это поддерживается. +// +// Консоль.ВидимостьКурсора возвращает прежнее значение курсора, а для этого читает +// Console.CursorVisible - свойство, чтение которого существует только на Windows. +// На Linux и macOS вызов выбрасывает PlatformNotSupportedException, и прогресс-бар +// падал на первом же шаге. Курсор там просто остаётся видимым. +// +// Параметры: +// Видимость - Булево - Истина, если курсор должен быть виден +// +Процедура СкрытьКурсор(Знач Видимость) + + Если Не КурсорУправляем Тогда + + Возврат; + + КонецЕсли; + + Попытка + + Консоль.ВидимостьКурсора(Видимость); + + Исключение + + КурсорУправляем = Ложь; + + КонецПопытки; + +КонецПроцедуры // СкрытьКурсор() + Функция ЗаполнитьБар(СимволШаблона, Длина = 50); МассивСимволов = Новый Массив; @@ -263,5 +357,7 @@ Инициализирован = ЛОЖЬ; Длительность = 0; +КурсорУправляем = ИСТИНА; +ВыводВозможен = ИСТИНА; ЦветБара = ЦветКонсоли.Magenta; УстановитьСимволыБара(); diff --git a/tests/oscript.cfg b/tests/oscript.cfg new file mode 100644 index 0000000..4101683 --- /dev/null +++ b/tests/oscript.cfg @@ -0,0 +1 @@ +lib.additional=../oscript_modules diff --git "a/tests/\320\237\321\200\320\276\320\263\321\200\320\265\321\201\321\201\320\221\320\260\321\200.os" "b/tests/\320\237\321\200\320\276\320\263\321\200\320\265\321\201\321\201\320\221\320\260\321\200.os" new file mode 100644 index 0000000..45a0701 --- /dev/null +++ "b/tests/\320\237\321\200\320\276\320\263\321\200\320\265\321\201\321\201\320\221\320\260\321\200.os" @@ -0,0 +1,85 @@ +#Использовать asserts +#Использовать ".." + +// Тесты прогресс-бара. +// +// Рисование проверяется наравне с остальным: в сборке вывод перенаправлен в файл, +// и бар должен переживать это на любой операционной системе. + +Функция Бар() + Возврат Новый ПрогрессБар(); +КонецФункции + +&Тест +Процедура ШагБезИнициализацииВыбрасываетИсключение() Экспорт + + Попытка + Бар().СделатьШаг(); + Исключение + ИнформацияОбОшибке = ИнформацияОбОшибке(); + КонецПопытки; + + Ожидаем.Что(ИнформацияОбОшибке).Не_().ЭтоНеопределено(); + Ожидаем.Что(СтрНайти(ИнформацияОбОшибке.Описание, "не инициализирован")).Больше(0); + +КонецПроцедуры + +&Тест +Процедура ОтрицательноеЧислоШаговВыбрасываетИсключение() Экспорт + + Попытка + Бар().Начать(-1); + Исключение + ИнформацияОбОшибке = ИнформацияОбОшибке(); + КонецПопытки; + + Ожидаем.Что(ИнформацияОбОшибке).Не_().ЭтоНеопределено(); + +КонецПроцедуры + +&Тест +Процедура ДлительностьВыполненияЧитаетсяВЧисленномВиде() Экспорт + + Ожидаем.Что(Бар().ДлительностьВыполнения()).Равно(0); + +КонецПроцедуры + +&Тест +Процедура ДлительностьВыполненияЧитаетсяВПредставлении() Экспорт + + Ожидаем.Что(Бар().ДлительностьВыполнения(Истина)).Равно("0с"); + +КонецПроцедуры + +&Тест +Процедура ШагиДоходятДоКонцаБара() Экспорт + + // Регрессия: на Linux и macOS первый же шаг падал с PlatformNotSupportedException - + // видимость курсора там прочитать нельзя + + ПрогрессБар = Бар(); + ПрогрессБар.Начать(3, "Проба"); + + Для Сч = 1 По 3 Цикл + ПрогрессБар.СделатьШаг(); + КонецЦикла; + + ПрогрессБар.Завершить(); + + Ожидаем.Что(ПрогрессБар.ДлительностьВыполнения()).БольшеИлиРавно(0); + +КонецПроцедуры + +&Тест +Процедура СимволыИЦветБараНастраиваются() Экспорт + + ПрогрессБар = Бар(); + ПрогрессБар.УстановитьСимволыБара(".", "#"); + ПрогрессБар.УстановитьЦветБара(ЦветКонсоли.Blue); + ПрогрессБар.Начать(2, "Проба"); + ПрогрессБар.СделатьШаг(); + ПрогрессБар.Завершить(); + + Ожидаем.Что(ПрогрессБар.ДлительностьВыполнения()).БольшеИлиРавно(0); + +КонецПроцедуры