runini
Давайте попробуем сейчас заняться более серьезной автоматизацией. Согласитесь, что не очень удобно пользоваться программой ge2exe из командной строки. Попробуем как-то облегчить этот процесс.
Пример 1
Пусть есть некий ini-файл, которые содержит информацию о программах на языке Gentee. Необходимо дать возможность пользователю выбрать программу из списка, откомпилировать ее и если необходимо создать EXE файл.
Опишем формат ini-файла с которым будем работать. Каждая секция будет обозначать одну программу и может иметь следующие поля:
Name - имя программы.
Src - .g файл программы.
Exe - создавать или нет exe файл ( 1 или 0 ).
Run - запускать или нет после компиляции.
Output - Если вы хотите дать конечному файлу другое имя или сохранить его в другой директории, то укажите его имя с путем здесь.
Обязательным является только поле Src.
[ID2]
Name = Square
Src = ..\square\square.1.g
Exe = 0
Вы можете сами изменять этот ini-файл как Вам угодно. В том числе, добавлять новые элементы. В качестве примера мы будем использовать файл runini.ini в поддиректории samples\runini.
Для работы с ini-файлом нам потребудется библиотека ini.g. Подключим ее с помощью команды include. Для упрощения мы подразумеваем, что наши примеры находятся в поддиректории samples и поэтому используем относительные пути. Если вы захотите перенести пример в другое место, то изменяйте пути на абсолютные.
include : $"..\..\lib\ini\ini.g"
Строка начинающаяся со знака '$' не имеет служебных символов, но распознает макросы. Такие строки удобно использовать для описания путей к файлам потому что не надо удваивать знак '\'.
Создадим две вспомогательные функции.
func uint openini( ini retini )
Функция openini будет считывать runini.ini файл и выдавать сообщение об ошибке в случае его отсутствия. Код ее можете посмотреть в исходном тексте.
func uint idaction( ini retini, str section )
Эта функция более важная. Она будет вызывать программы компиляции и создания exe файла. Первый параметр - объект типа ini, второй - имя секции-программы которую надо запустить.
Следующие операторы считывают значения полей.
retini.getvalue( section, "Src", src, "" )
if !*src
{
congetch("ID '\(section)' is not valid. Press any key...\n")
return 0
}
run = retini.getnum( section, "Run", 1 )
exe = retini.getnum( section, "Exe", 0 )
retini.getvalue( section, "Output", outname, "" )
Последний параметр в функциях getvalue и getnum определяет значение в случае отсутствия данного поля в ini-файле.
Код ниже формирует командные строки для запуска компилятора и ge2exe в зависимости от полученных опция из ini-файла. Запуск программ происходит с помощью функции process. Указание "." в качестве второго параметра при вызове process означает, что текущая директория будет рабочей директорией для gentee.exe и ge2exe.exe.
if exe
{
process( "..\\..\\exe\\gentee.exe -p samples \(src)", ".", &result )
src.fsetext( src, "ge" )
process( "..\\..\\exe\\ge2exe.exe \(src)", ".", &result )
deletefile( src )
src.fsetext( src, "exe" )
if run : process( src, ".", &result )
}
else : shell( src )
Сейчас рассмотрим тело главной функции, которая будет выводить список возможных программ и получать от пользователя имя выбранной программы.
ini tini
arrstr sections
str name src section
openini( tini )
tini.sections( sections )
while 1
{
print( "-----------\n" )
foreach cur, sections
{
tini.getvalue( cur, "Src", src, "" )
if !*src : continue
tini.getvalue( cur, "Name", name, src )
print( "\(cur)".fillspacer( 20 ) + name + "\n" )
}
print( "-----------\n" )
congetstr("Enter ID name (enter 0 to exit): ", section )
if section[0] == '0' : break
idaction( tini, section )
}
В начале считываем ini-файл и получаем список секций в виде массива строк. Далее выводим список программ в окно и запрашиваем у пользователя имя секции-программы. После этого вызываем функцию idaction с выбранным именем секции.
Более подробно разберем следующую строчку.
print( "\(cur)".fillspacer( 20 ) + name + "\n" )
Метод fillspacer дополняет строку пробелами до необходимой длины. Вы видите, что мы применяем метод не к переменной типа строка, а к строке в двойных кавычках. Это можно делать потому, что строка в двойных кавычках такой же объект как и переменная типа строка. Более того, мы можем применять методы и к функциям или методам возвращающим строки.
Например, данное выражение дополнит нашу строку десятью пробелами слева и доведет общую длину строки до 30 символов.
"ID: \(cur)".fillspacer( 20 ).fillspacel( 30 )
Упражнение 2
Напишите программу, которая используя runini.1.g может принимать имя секции-программы из командной строки и производить ее запуск. Если параметр командной строки не указан, то она должна работать как разобранная выше программа.У меня эта программа заняла 14 строк. Можете открыть runini.2.g и убедиться сами.