Небольшая коллекция самописных классов и процедур на REXX
Автор:
Источник: OS2.ru
Дата: 10.02.2001
Предлагаю вашему вниманию небольшую коллекцию самописных классов и процедур (20 Kb). Не судите сторого -- все это я сначала писал для себя, и только потом мне пришла в голову идея вынести все это на суд общественности.
config.class | |
---|---|
.config |
класс для чтения конфигурационных файлов. |
progress.class | |
.roller |
класс для отображения индикатора активности в виде вращающейся палочки. |
.slider |
класс для отображения индикатора активности в виде предложеном IBM'ом. :) |
.progressbar |
класс для чтения конфигурауционных файлов. |
sems.class | |
.event |
класс для чтения конфигурауционных файлов. |
.mutex |
класс для чтения конфигурауционных файлов. |
works.procs | |
подборка процедур. |
CONFIG.CLASS
В этом файле содержится только один класс:
.config
Представляет собой достаточно умную читалку текстовых конфигов, выполненую в виде класса языка Object REXX. Поддерживает макроопределения, вложения файлов, значения по умолчанию для директив. Класс содержит следующие методы:
~new(filename,keys) |
инициализирует класс для чтения конфигурационного файла с заданным именем.
|
||||
~read |
cчитывает файл и возвращает структуру values, содержащую информацию из конфига. |
||||
~show |
выводит на экран информацию о считаных данных. Представляет ценность только во время отладки. |
||||
~getfilename |
возвращает имя конфига, подлежащего чтению. |
||||
~getvalues |
возвращает структуру values, содержащую информацию из конфига. |
||||
~requires |
предназначен для переопределения. Вызывается в том случае, если в конфиге не найдена хотя бы одна директива, помеченная как requiers По умолчанию выдает сообщение и вызывает ~abort. |
||||
~invalid |
предназначен для переопределения. Вызывается в том случае, если в в конфиге найдена директива, не указанная в keys По умолчанию выдает сообщение и вызывает ~abort. |
||||
~abort(message) |
выводит на экран сообщение message и выходит из скрипта. |
||||
~filenotfound |
предназначен для переопределения. Вызывается если не найден файл для чтения. По умолчанию выводит на экран сообщение message и вызывает ~abort. |
||||
~include |
не трогайте его. Вызывается при нахождении директивы #include. |
||||
~setting |
опять же не трогайте его. Вызывается при нахождении правильной директивы. |
||||
~setmethod |
и его не трогайте. Он простой и позволяет переопределять методы. |
Методы ~read и ~getvalues возвращают структуру values, которая является классом .directory индексы которого соответствуют директивам, а значения полей, являются либо строками (для single), либо массивами строк (для multi).
метод ~new принимает структуру keys, которая также является классом .directory, индексами которого являются имена директив, а значениями параметры:
single | multi | |
optional |
директива не обязательна, причем если директива попадается несколько раз, будет использовано последнее значение. Кроме того, через ':' можно указать значение по умолчанию. |
директива не обязательна, причем если директива попадается несколько раз, будет заведен массив со всеми значениями. Кроме того, через ':' можно указать несколько значений по умолчанию, разделенных ';' |
requied |
директива обязательна, причем если директива попадается несколько раз, будет использовано последнее значение. |
директива обязательна, причем если директива попадается несколько раз, будет заведен массив со всеми значениями. |
Например:
keys = .directory~new
keys~key1 = 'single,required'
keys~key2 = 'single,optional:default for key2'
keys~key3 = 'multi,required'
keys~key4 = 'multi,optional:default1 for key4;default2 for key4'
keys~key5 = 'single,optional'
keys~key6 = 'multi,optional'
Из конфигурационного файла будет прочитано следующее:
- key1
- будет прочитано последнее из указанных значений, причем если не попадется ни одного значения, работа скрипта будет остановлена.
- key2
-
будет прочитано последнее из указанных значений, причем если не попадется ни одного значения, будет установлено значение '
default for key2
' - key3
- будут считаны в массив все значения, причем если не попадется ни одного значения, работа скрипта будет остановлена.
- key4
-
будут считаны в массив все значения, причем если не попадется ни одного значения, будут установлены значения '
default1 for key4
' и 'default2 for key4
'
Если попадется хотя бы одно значение, то все значения по умолчанию будут проигнорированы. - key5 и key6
- в принципе, аналогично key2/key4, но параметр по умолчанию отсутствует. Для key5 будет установлена пустая строка, а для key6 -- массив без элементов.
Кроме того, в конфигурационном файле поддерживаются следующие директивы:
#DEFINE name [argument] |
определяет name. Если указан аргумент, то можно выполнить его макроподстановку. Для этого нужно указать name в угловых скобках. |
#UNDEF name |
отменяет определение для name |
#IFDEF name ... #END |
читает находящееся между #IFDEF и #END только если name определено. |
#IFNDEF name ... #END |
читает находящееся между #IFDEF и #END только если name НЕ определено. |
#INCLUDE filename |
"включает" файл filename в текущий файл. Вложенность не ограничена. |
PROGRESS.CLASS
В этом файле содержатся сразу 3 класса: .roller, .slider и .progressbar
К сожалению, классы писались в разное время и для разных целей, и потому не стандартизированы. Конечно их стоило бы наследовать от одного и того же абстрактного суперкласса, но переделывать все это мне что-то не хочется. Может быть, в следующий раз... :)
Эти классы представляют собой 3 растпространенных индикатора того, что в программе что-то происходит.
- .roller
- представляет собой крутящуюся палочку.
- .slider
- представляет собой индикатор предложеный IBM'ом. В системе он выводится при установке, в момент поиска p'n'p. По-моему неплохая альтернатива для: "Если ваш винчестер длительное время не подает признаков жизни..." (с)
- .progressbar
- ну тут комментарии излишни. Этот индикатор попадается решительно везде, где только можно.
Теперь подробнее:
.roller
Имеет следующие методы:
~new(symbols,speed) | инициализирует класс.
|
||||
~show |
выводит некую информацию о классе. Полезен только при отладке. |
||||
~start |
запускает индикатор, после чего тот крутится до вызова метода ~stop. |
||||
~stop |
останавливает индикатор. |
Индикатор не зависит от хода выполнения основной программы. В этом смысле он пригоден скорее для развлечения пользователя, чем для определения, не повис ли скрипт. С другой стороны, покажите мне повисший скрипт на Rexx'е... :)
Индикатор сам определяет текущую (на момент ~start) позицию курсора на экране, и крутится в ней. Поэтому выводить что-либо на экран в процессе вращения индикатора лучше не надо.
.slider
Имеет следующие методы:
~new(len,speed) | инициализирует класс.
|
||||
~show | выводит некую информацию о классе. Полезен только при отладке. | ||||
~start | запускает индикатор, после чего тот крутится до вызова метода ~stop. | ||||
~stop | останавливает индикатор. |
Как и .roller, .slider не зависит от хода выполнения основной программы.
И так же как и для roller'а, не стоит выводить ничего на экран, пока индикатор рисует себя.
На самом деле, я знаю как это все исправить, и сделать очень удобно, но... в следующий раз. :)
.progressbar
Имеет следующие методы:
~new(start,max,len) | инициализирует класс.
|
||||||
~step | переходит к следующему значению некоторой величины. Заметьте: не к следующему проценту, а именно к следующему значению величины. | ||||||
~stepto | переходит к заданному значению некоторой величины. | ||||||
~stop | останавливает индикатор. |
Что такое "некоторая величина"? Например, Вам нужно скопировать 5 файлов. Тогда создание класса будет выглядеть следующим образом:
p = .progressbar~new(0,5,50)
Имеем:
- значение 0%:
- 0 фалов скопировано.
- значение 100%:
- 5 фалов скопировано.
- размеры:
- на индикатор отведено 50 символов по горизонтали. Учтите, что по вертикали .progressbar занимает 2 строки.
При этом метод ~step будет изменять показания прогрессбара на 20%.
Если Вы хотите вывести показания для момента завершения копирования 3-го файла, вызывайте:
p~stepto(3)
Как Вы, наверное, догадались, при использовании этого индикатора тоже не стоит ничего выводить на экран.
SEMS.CLASS
Этот файл содержит два крайне полезных, на мой взгляд, класса: .mutex и .event.
Из названий, думаю, понятно, что это обертки для системных семафоров, которые настолько упрощают работу с ними, что делают ее даже проще, чем работу с файлами-флагами.
.event
Содержит следующие методы:
~new(name) | инициализирует класс. name задает имя семафора. |
~post | постит семафор. |
~reset | сбрасывает семафор. |
~query | возвращает .true, если семафор запощен. |
~wait | ожидает, пока семафор будет запощен. |
~defaultname | возвращает информацию о семафоре в формате name (handle) state |
Очень удобно использовать этот класс для организации общения между скриптами или между скриптом и программой, понимающей семафоры, например с T-Mail'ом.
.mutex
Содержит следующие методы:
~new(name) | инициализирует класс. name задает имя семафора. |
~request | захватывает семафор. |
~release | отпускает семафор. |
~defaultname | возвращает информацию о семафоре в формате name (handle) |
Класс незаменим при организации совместного доступа скриптов (или нитей выполнения в скриптах) к каким-либо объектам. Например, у меня этот класс регулирует доступ к почтовой базе:
s = .mutex~new('\sem32\msgbase.sem')
s~request
...
...
s~release
Класс полностью гарантирует, что фрагмент, заключеный между ~request и ~release, будет выплняться в одиночестве, и все остальные (естественно, кто пытается выполнить ~request для семафора с тем же именем) будут дожидаться вызова ~release в скрипте, выполнившем ~request.
Класс полностью исключает ситуацию, которая вполне возможна с файлами-флагами, когда два скрипта, одновременно ждущие пропадения одного и того же флага, одновременно же определяют его пропадение.
Кроме того, класс успешно борется с ситуацией, когда скрипт выполнил ~request и по каким либо причинам не смог выполнить ~release. Такой "зомбированый" семафор автоматически будет пересоздан.
works.procs
Это сборник полезных, на мой взгляд, процедур. Ничего сложного, но удобно.
makepath(path) |
создает путь path, опускаясь вниз по дереву. |
log(file,string) |
записывает строку string в файл file, предваряя ее датой и временем. Удобно для ведения логов. |
setenv(var,val) |
аналогична стандартной функции value, но с фиксированым третьим параметром: 'OS2ENVIRONMENT'. |
arcmail(filename) |
возвращяет .true, если filename является правильным именем arcmail-пакета (это из FTN). |
datebase(date,format) |
возвращает количество дней между 01.01.0001 и указанной датой. format задает формат, в котором указана дата. По умолчанию 'N'. |
datedest(date1,date2,format) |
возвращает количество дней между датами. format задает формат, в котором указаны даты. По умолчанию 'N'. |
dateago(date,format) |
возвращает количество дней, прошедших с указанной даты. format задает формат, в котором указана дата. По умолчанию 'N'. |
Стоит заметить, что функции datebase, datedest и dateago в общем-то потеряли смысл при выходе Object REXX'а. Но вот в некоторых моих скриптах они используются, а потому были переписаны под ORexx и оставлены "для удобства". |
|
TimeBase_M(time) |
возвращает количество минут, прошедших от полночи. Время принимается в 24-х часовом формате hh:mm:ss. |
TimeBase_S(time) |
возвращает количество секунд, прошедших от полночи. Время принимается в 24-х часовом формате hh:mm:ss. |
Про эти две функции можно сказать то же самое, что и про date*. |
|
arrinsert(arr1,index,arr2) |
Возвращает массив, получившийся в результате вставки arr2 в arr1 с позиции index. |
expandaddress(address,default) |
Преобразует частично заданный адрес в полный, подставляя недостающие части из default. (это из FTN). |
YesNo(Q) |
возвращяет .true, если Q является утвердительным ответом ('Yes' или 'Да'). |
matchaddr(address,mask) |
возвращает .true, если address попадает в маску mask. Поддерживаются символы '*' -- все что угодно и '!' -- отрицание. (это из FTN). |
match(word,mask) |
возвращает .true, если word попадает в маску mask. Поддерживаются символы '*' -- все что угодно и '!' -- отрицание. |
FileCopy(source,dest) |
копирует файл из source в dest. Не мудрствуя лукаво, пользуется командой copy. |
FileMove(source,dest) |
перемещает файл из source в dest. Не мудрствуя лукаво, пользуется командой mov. mov.exe лежит тут же... |
Abort(message) |
выводит на экран message и останавливает работу скрипта. |
QSort(array) |
сортирует массив Array. Название говорит обо всем. |
Color(color) |
устанавливает текущий цвет символов. |
Если у Вас возникнут какие-нибудь глобальные идеи по поводу этих скриптов, или Вы захотите указать мне на мои ошибки, или Вы чего-то не поймете, то пишите мне.