Path: | docs/AdHoc |
Last Update: | Mon Jun 04 14:34:35 +0400 2007 |
Первоначальная схема работы RuCodeGen, когда на Ruby создается DSL-скрипт, который запускается как отдельная утилита, и который в результате генерирует один или несколько файлов, оказалась не всегда удобной. В частности, вот несколько ситуаций, в которых создавать отдельный DSL-скрипт в отдельном Ruby-файле не удобно:
Например, было бы удобно определить где-нибудь шаблон для новых C++ файлов конкретного проекта после чего запустить отдельную (уже созданную кем-то утилиту) и получить готовый C++ файл. Например, запуская что-нибудь вроде:
rcgtool cpp-new-file -o my/project/header.hpp
получать файл my/project/header.hpp вида:
/* * Copyright (C) 2007 ... * ... */ /*! * \since v.3.4.6 * \file my/project/header.hpp * \brief <DESCRIBE YOUR FILE HERE!> */ #if !defined( MY_PROJECT_HEADER_HPP ) #define MY_PROJECT_HEADER_HPP #endif
Или же вставка сниппетов в редактируемый в каком-нибудь редакторе код. В частности, в редакторе VIM, который позволяет передавать на вход внешней утилите выделенный фрагмент текста, а затем заменять этот фрагмент на результат работы утилиты. Тогда, например, можно написать в VIM строку:
namespace my::project::details
выделить ее, ввести команду:
:'<,'>!rcgtool cpp-open-ns
после чего выделенная строка будет заменена на:
namespace my { namespace project { namespace details { } /* namespace details */ } /* namespace project */ } /* namespace my */
Т.е. после некоторого времени использования RuCodeGen 0.1.0 и 0.2.0 стало понятно, что необходимо поддерживать "неожиданные", или как их принято называть ad-hoc, генераторы. Начало этой поддержки было сделано в версии RuCodeGen 0.3.0.
Принцип работы ad-hoc генератора состоит в том, что RuCodeGen включает в себя небольшую утилиту rcgtool, которая получает имя генерирующего шаблона и набор параметров для этого шаблона. Утилита rcgtool ищет шаблон среди известных ей каталогов и, если шаблон найден, запускает его на выполнение как отдельный ruby-скрипт. При этом скрипту шаблона передается заданный пользователем набор параметров.
Таким образом, каждый ad-hoc шаблон представляет из себя автономную ruby-программу, а rcgtool является всего лишь запускателем таких программ.
Поскольку шаблон является самостоятельной программой, он может выполнять любые действия:
Соответственно, ad-hoc шаблон может выводить результаты своей работы в:
Формат:
RuCodeGen Ad-Hoc generation runner Usage: rcgtool [<options>] template-name [<template-options>] -h, --help Show this message -I, --include-path PATH Additional path to looking for templates -l, --list Show list of available templates
где используются параметры:
По умолчанию rcgtool ищет шаблоны в каталоге ../lib/rucodegen/adhoc/templates относительно того каталога, в котором находится исходный файл rcgtool из состава RuCodeGen. Т.е., по умолчанию, rcgtool ищет шаблоны в составе инсталляции RuCodeGen. Параметр -I позволяет расширить список каталогов для поиска шаблонов.
Параметр template-name должен указывать имя ad-hoc шаблона. Следующие после template-name необязательные параметры template-options утилитой rcgtool не обрабатываются а передаются в ad-hoc шаблон.
Пока поддержка ad-hoc шаблонов находится в самом начальном состоянии. Поэтому в версии 0.3.0 доступен только один шаблон:
Например:
rcgtool cpp-open-ns -n my::project
приведет к печати на стандартный поток вывода:
namespace my { namespace project { } /* namespace project */ } /* namespace my */
Так же cpp-open-ns может получать имя пространства имен со стандартного ввода:
echo "my::project" | rcgtool cpp-open-ns
или
echo "namespace my::project" | rcgtool cpp-open-ns
что приведет к такому же результату.
Возможность считывать данные со стандартного ввода позволяет использовать cpp-open-ns из редактора VIM с помошью команды :!<cmd>.
Ad-hoc шаблон — это ruby-файл с именем g.rb, который располагается в подкаталоге с именем шаблона. Например, шаблон cpp-open-ns, реализован в виде файла cpp-open-ns/g.rb.
Содержимое файла g.rb загружается в ruby-интерпритатор, исполняющий скрипт rcgtool, с помощью директивы require. Соответственно, g.rb должен быть написан так, чтобы он самостоятельно выполнял свою работу. Никаких обратных вызовов или точек входа. Т.е. g.rb должен быть самостоятельной программой, которую можно запустить на выполнение и без rcgtool.
Если скрипту g.rb необходимы аргументы командной строки, то он может использовать ARGV, т.к. rcgtool к этому времени удаляет из ARGV все собственные аргументы.