Motto

В тихом саду здравомыслия
Пусть на вас постоянно падают
кокосовые орехи пробужденности.
Чогьям Трунгпа РИНПОЧЕ


Версия для мобильного


четверг, 14 июля 2011 г.

Перевод Live templates Revisited

Это перевод поста Кэри Дженсена “Live templates Revisited”. Кэри также является автором новой книги Delphi in Depth: ClientDataSet. По адресу http://www.jensendatasystems.com/cdsbook/ вы можете найти дополнительную информацию об этой книге и заказать её.

This post contains translation of Cary Jensen’s article “Live Templates Revisited”. Cary is also the author of the new book Delphi in Depth: ClientDataSet. For more information about this book and links to order, please visit http://www.jensendatasystems.com/cdsbook/.

Ещё раз о живых шаблонах

Хотя шаблоны кода были в Delphi со времён 4й версии Delphi, они были очень простыми по сравнению с новой функцией живых шаблонов, впервые появившейся в Delphi 2006. Живые шаблоны предоставляют возможность делать вставку кода ещё более интеллектуальной, а также позволяют осуществлять интерактивную навигацию по изменяемым частям шаблона. Если вы ещё не используете их, то сейчас самое время рассмотреть их повнимательнее.

Рассмотрим вставленный шаблон показанный на следующем рисунке. Этот шаблон был создан путем выполнения шаблона forb, который вставляет цикл с блоками begin .. end.

Живой шаблон forb

Обратите внимание, что переменная итерации I подсвечена. Это позволит вам при желании быстро изменить имя переменной. Например, многие разработчики Delphi используют строчную переменную i в качестве переменной цикла (хотя Delphi сам по себе не чувствителен к регистру).

Вы также можете заметить, что I, а также 0 и List.Count окружены рамочкой. Эти области текста (в рамочке) являют собой точки синхронизации живого шаблона. После изменения I на i, нажмите Tab или Shift-Tab для перемещения между точками синхронизации шаблона. Во время перемещений, вы можете заметить, что подсказки (hints) изменяются, чтобы отобразить описание выбранной точки.

На следующем рисунке показан тот же живой шаблон, что и на предыдущем рисунке но уже после того, как курсор переведён к третьей изменяемой части.

Живой шаблон forb: курсор на элементе List.count

Многие живые шаблоны, таких как например шаблон forb, также поддерживают интеллектуальную вставку кода, или активные сценарии. С активными сценариями, код выполняется когда вы вставляете шаблон или взаимодействуете с шаблоном, условно выполняя одну или несколько задач для вас. В случае с шаблоном forb, если функция, в которую вы вставляете этот шаблон не содержит объявления переменной цикла, эта переменная будет объявлена за вас, как только вы нажмёте клавишу Tab после прохода по всем точкам синхронизации. Следующий фрагмент демонстрирует, как будет выглядеть изначально пустой метод после выполнения активного сценария, ассоциированного с живым шаблоном forb.

Живой шаблон forb: выполнен

Запуск живых шаблонов

Delphi содержит в себе большое количество стандартных живых шаблонов для каждой из установленных персоналий (Delphi, C++, XML и т. д.). Эти шаблоны могут быть вызваны по требованию или автоматически, в зависимости от настроек самого шаблона, а также от настроек Delphi.

Независимо от настроек шаблона, вы можете вызвать живой шаблон по требованию путём позиционирования курсора в редакторе, где вы хотите разместить живой шаблон и нажатия Ctrl-J. Delphi ответит на это, отображением меню Insert Template, как показано на следующем рисунке. Выберите шаблон, который хотите вставить из этого меню и нажмите Enter.

Список живых шаблонов в редакторе кода Delphi

Кроме того, вы можете ввести первые буквы названия шаблона (в оригинале - template shortcut name) перед тем как нажать Ctrl-J. Если введённые символы будут соответствовать названию только одного шаблона, этот шаблон будет выбран и вставлен, без отображения меню Insert Template. Если введённым символам будет соответствовать два или более названия шаблона, то появится меню Insert Template, которое однако будет содержать только те названия шаблонов, которые соответствуют введённым символам. В этом случае вам достаточно будет выбрать нужный шаблон и нажать Enter.

Автоматический вызов доступен, если и живой шаблон и Delphi настроены соответствующим образом. Автоматическое завершение доступно для тех живых шаблонов, которые содержат в своём определении атрибут invoke="auto", и когда когда в Delphi в диалоговом окне Options включены флажки Code templates completion и Auto complete на закладке Code Insight. Вы можете открыть это диалоговое окно, через пункты Tools->Options главного меню Delphi.

Настройка автодополнения живых шаблонов

В случае с автоматическим вызовом живого шаблона, вставка шаблона сработает когда вы введёте сокращённое название шаблона и нажмёте Tab или пробел. Например, если вы введёте forb и нажмёте Tab, живой шаблон forb тут же будет вставлен в ваш код в месте расположения курсора.

Живые шаблоны также отображаются в меню завершения кода (Code completion menu), которое можно вызвать, нажав Ctrl+Пробел. Шаблоны всегда появляются в конце этого списка.

Вы также можете вызывать живые шаблоны из панели Templates, показанной на следующем рисунке. Для отображения панели шаблонов, выберите View | Templates в главном меню Delphi.

Панель Templates

Все стандартные шаблоны, поставляемые с Delphi, определены в XML файлах. Вы можете редактировать эти XML, если вы хотите изменить содержание или поведение шаблона. Чтобы изменить один из стандартных шаблонов, выберите шаблон в панели Templates и затем нажмите кнопку Edit на тулбаре панели Templates. На следующем рисунке показан живой шаблон case в редакторе кода.

Редактирование живого шаблона case

Живой шаблон case является хорошим примером для изучения, так как он включает в себя точки, подсказки, текст, описание, автора и элементы сценария (script).

Части живого шаблона

Корневым элементом живого шаблона является элемент codetemplate. Элемент Codetemplate имеет два атрибута, XMLNS и version, которые определяют пространство имен XML и версию, соответственно. Элемент Codetemplate имеет один дочерний элемент, названный template.

Элемент template может состоять из четырех атрибутов. Атрибут name является обязательным и определяет уникальное имя шаблона для указанного языка.

Остальные атрибуты являются необязательными. Используйте surround = "True", чтобы определить "окружающий" шаблон, который может окружить блок кода. Используйте invoke= чтобы определить тип вызова для шаблона. Допустимые значения для invoke: “auto”, “manual” и “none”(по умолчанию).

Установите атрибут invoke в "auto" или “manual”, чтобы вставлять шаблон, набирая его имя и нажимая клавишу. Для auto шаблонов вы можете использовать клавишу Пробел или Tab, а для manual шаблонов используйте клавишу Tab. Вне зависимости от типа вызова, вы можете ввести название шаблона и вставить его нажав Ctrl+О или нажать Ctrl+Пробед и выбрать шаблон из списка.

Последний атрибут, InPlace = "True", определяет расширение шаблона. Неясно, что из себя представляет расширение шаблона, поскольку этот атрибут, кажется, не используется.

Элементы шаблона point, description и author - это дочерние и необязательные элементы шаблона. Когда используется один или более элемент point, то они позволяют определить пользовательские точки синхронизации в коде вашего шаблона. Каждая точка синхронизации может включать в себя элемент text, определяющий значение по умолчанию, и элемент hint, в котором описана подсказка для этой точки.

Точки, также как и элемент code, могут также содержать атрибут script, который ссылается на активный сценарий. Активные сценарии будут описаны далее в этой публикации.

Элемент description обеспечивает описание шаблона, которое появляется в контекстном меню и диалоговом окне Templates. Элемент author идентифицирует автора шаблона.

Последний элемент code, описывает код, который вставляется шаблоном. Этот элемент имеет несколько атрибутов и секцию CDATA. Для Delphi шаблона, установите атрибут language в Delphi. Кроме того, определить разделитель (атрибут delimeter), который идентифицирует пользовательские и предопределённые точки синхронизации. Так как символ $, являющийся разделителем по умолчанию, в Delphi имеет особое значение, большинство разработчиков в качестве разделителя определяют символ | (вертикальная черта).

Сам код размещается в секции CDATA, между символами [ и ]]>. Этот код может содержать буквенные символы, символ перевода строки, а также точки синхронизации, как пользовательские так и предопределенные. В сегменте кода показанном в живом шаблоне case, строки |expression| и |cases| определяют позицию соответствующих точек синхронизации живого шаблона. Вы можете увидеть что эти точки, были определены ранее при объявлении шаблона (прим. переводчика. имеются в виду элементы point).

В дополнение к пользовательским точкам синхронизации, существуют три вида предопределенных точек. Это |surround|, |*| и |end|. Если ваш шаблон является окружающим шаблоном, вы включаете точку |surround| чтобы определить, куда будет помещён блок выделенного текста, по отношению к остальному шаблону. Точка |*|, указывает что всё что появляется в этой же строке должно быть размещено с отступом, равным величине определённой в диалоговом окне Options. Вы можете включить в ваш живой шаблон столько точек |*| сколько вам нужно.
Наконец, предопределённая точка |end| определяет, где окажется курсор после вставки живого шаблона. В вашем живом шаблоне может быть только по одной |surround| и |end| точке.

Пользовательские живые шаблоны

Хотя стандартные живые шаблоны, поставляемые с Delphi и являются чрезвычайно полезными, вам будет приятно узнать, что вы можете создавать свои собственные живые шаблоны.

Для создания пользовательского живого шаблона, выберите команду New на панели инструментов формы Templates. Кроме того, вы можете вызвать Мастера Шаблонов (Template Wizard) из Репозитория объектов (Object Repository). Для этого выберите File–>New->Other из главного меню Delphi. Затем выберите Template Wizards в ветке Other Files Репозитория объектов и нажмите ОК.

Новый шаблон будет показан в редакторе кода в виде XML документа, как показано на следующем рисунке. Если вы посмотрите на рисунок, обратите внимание, что новый шаблон отображает подсказку. Это потому, что новый пользовательский живой шаблон создается с помощью живого шаблона. Это не только раскрывает невероятную мощь живых шаблонов, но и сами подсказки значительно упрощают процесс создания новых живых шаблонов.

Подсказка в редактире живого шаблона

Чтобы закончить ваш пользовательский живой шаблон, заполните изменяемые части шаблона и добавьте свои собственные элементы, по мере необходимости определяя желаемые функции в вашем шаблоне.

В дополнение к подсказкам, которыми снабжает вас живой шаблон, рекомендуется также изучить стандартные живые шаблоны, поставляемые с Delphi для лучшего понимания возможностей написания собственных, первоклассных пользовательских живых шаблоны.

Окружающие Шаблоны

Окружающие (surround) шаблоны являются специальным подмножеством живых шаблонов, которые позволяют Вам быстро заключить или окружить, выделенный блок кода. Примерами окружающих шаблоны являются живые шаблоны forb, try, procedure и comment.

Например, представьте, что вы хотите заключить следующий выделенный код в блок try ... except в вашем Delphi проекте.

Окружающий шаблон. Выделенный текст перед вызовом.

После выделения нужного блока кода, выделите живой шаблон tryf в панели Templates, а затем выберите пункт Execute. Или как вариант, выделите блок кода, щелкните правой кнопкой мыши в редакторе, выберите Surround в появившемся контекстном меню, а затем выберите tryf.

Окружающий шаблон. Тот же текст после вызова.

Обратите внимание, что выделенный блок кода, был отделен отступом, делая полученный код более читабельным. Теперь вы готовы, чтобы вставить вызов метода TStringList.free в блок finally, обеспечивая уничтожение объекта после окончания работы с ним.

Если вы создаете свой собственный окружающий шаблон, они будут автоматически отображаться в контекстном меню Surround. В частности, контекстное меню Surround включает в себя любые пользовательские живые шаблоны, которые вы создали для текущей языковой персоналии, где атрибут surround имеет значение true.

Активные сценарии

Активные сценарии (на англ. scripts) представляют собой скомпилированные Delphi классы, которые могут реагировать на события вызванные во время работы с живым шаблоном. Многие шаблоны Delphi используют активные сценарии, в том числе и живой шаблон case, показанный ранее. Он вызывает активный сценарий PopulateCase. PopulateCase является одним из шести активных сценариев, которые поставляются вместе с Delphi. К сожалению, их исходный код недоступен.

Хотя это более сложный процесс, похожий на создание клавиатурных макросов, вы также можете создавать свои собственные активные сценарии и вызывать их из ваших живых шаблонов. Это можно сделать путем создания пакета времени разработки (design time package). Внутри этого пакета надо создать класс, который наследуется от TInterfacedObject и реализует интерфейс IOTACodeTemplateScriptEngine. Модуль (unit), в котором этот класс реализован должен использовать модули ToolsAPI и CodeTemplateAPI.

В этом новом классе, надо реализовать методы GetIDString, GetLanguage и Execute. Используйте GetIDString для того, чтобы вернуть уникальную строку, которая не будет использоваться каким-либо другим активным сценарием. Принято, что эта строка обычно включает в себя название вашей компании или акроним, за которым следует точка и название активного сценария. Эта строка не может содержать пробелов.

Используйте GetLanguage, чтобы вернуть название языка, который будет использоваться для идентификации вашего класса сценариев. Эта строка используется в элементе script, который указывает редактору использовать ваш класс для сценариев.

Наконец, надо реализовать метод Execute. В этот метод передается пять параметров, некоторые из которых могут быть равны nil для конкретного активного сценария.

  1. Первым параметром является объект, который реализует интерфейс IOTACodeTemplate. Этот объект предоставляет вам доступ к тексту, связанный с элементом сценария, который вызывает ваш скрипт.
  2. Вторым параметром является объект, который реализует IOTACodeTemplatePoint. Этот объект представляет текущую точку синхронизации запуска для сценария OnEnter или OnExit. Для OnValidate сценариев, данный объект равен nil.
  3. Третьим параметром является объект, реализующий интерфейс IOTASyncEditPoints. Используйте этот объект для изучения всех точек синхронизации в живом шаблоне. Опять же, данный объект будет равен nil для сценариев OnValidate, так как шаблон на самом деле ещё не существует.
  4. Четвертым параметром является объект, который реализует IOTACodeTemplateScript. Этот объект обеспечивает доступ к разделу CDATA кода элемента.
  5. Последний параметр является Boolean параметром. Используйте его для сценаря OnValidate, чтобы сообщить, что шаблон был успешно обработан.

В вашем активном сценарии, ваш метод execute должен изучить точки синхронизации и шаблон кода, чтобы определить, какие действия предпринять. Кроме того, поскольку вы используете модуль ToolsAPI в вашей строке uses, вы можете использовать объект BorlandIDEServices, чтобы получить доступ к ToolsAPI редактора, который позволяет вам читать, добавлять, удалять и изменять текст в редакторе.

Итоги

Живые шаблоны являются одной из малоизвестных жемчужин в Delphi. Хотя они и менее простые, чем их собратья code templates из ранних версий Delphi, живые шаблоны, всё же являются гораздо более мощным, и вполне стоят того, чтобы потратить свое время изучить их повнимательнее.


Ссылки по теме

2 комментария:

  1. Анонимный16 июля 2011 г., 11:29

    Спасибо, полезная статья. Открыл для себя всю мощь живых шаблонов и смысл заняться их дальнейшим изучением.

    ОтветитьУдалить
  2. мне понравилась статья! Автору спасибо

    ОтветитьУдалить

Постоянные читатели