AdHoc

Path: docs/AdHoc
Last Update: Mon Jun 04 14:34:35 +0400 2007

AdHoc генерация

Введение

Первоначальная схема работы 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 шаблон может выводить результаты своей работы в:

  • какой-либо файл (с заранее определенным или заданным пользователем именем);
  • на стандартный поток вывода (актуально для сниппетов и VIM-а);
  • куда-либо еще.

Формат запуска rcgtool

Формат:

        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

где используются параметры:

-I, —include-path
дополнительные пути для поиска ad-hoc шаблонов.
-l, —list
указывает rcgtool отобразить список найденых шаблонов.

По умолчанию rcgtool ищет шаблоны в каталоге ../lib/rucodegen/adhoc/templates относительно того каталога, в котором находится исходный файл rcgtool из состава RuCodeGen. Т.е., по умолчанию, rcgtool ищет шаблоны в составе инсталляции RuCodeGen. Параметр -I позволяет расширить список каталогов для поиска шаблонов.

Параметр template-name должен указывать имя ad-hoc шаблона. Следующие после template-name необязательные параметры template-options утилитой rcgtool не обрабатываются а передаются в ad-hoc шаблон.

Готовые ad-hoc шаблоны

Пока поддержка ad-hoc шаблонов находится в самом начальном состоянии. Поэтому в версии 0.3.0 доступен только один шаблон:

cpp-open-ns
по имени C++ пространства имен генерирует фрагмент кода с открытием и закрытием этого пространства имен.

Например:

        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 шаблоны

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 все собственные аргументы.

[Validate]

Hosted by uCoz