Вступление


Сегодня я хочу привести небольшой обзор-туториал темплейтов в ИСР от Jetbrains. Приведенные ниже примеры будут реализованы на Java в Intellij IDEA, но механизм создания одинаков и для других языков и продуктов компании. Думаю все программирующие в данной IDE пользовались встроенными шаблонами. Например когда вы пишете fori, нажимаете TAB или ENTER и у вас появляется цикл for в котором нужно указать имя переменной и условие, а остальной код генерируется за вас.

for (int i = 0; i < ; i++) {   
                               
}    

Или же знакомый всем java-программистам sout -> System.out.println(). Так вот, в Intellij есть поддержка создания своих шаблонов кода. На удивление не нашёл практически никакой инфы на русском и довольно мало на английском(благо есть неплохая документация) когда наткнулся на эту фичу, хотя это сильно ускоряет и помогает в разработке. И сейчас когда дошли руки решил написать небольшую статью об этом. Возможно опытным программистам она мало чем поможет, они и сами смогут разобраться во всём или же уже давно это юзают, но для всех остальных считаю вполне подойдёт. Итак приступим.

Создание шаблона


Для начала сделаем простой пример, к примеру константу логгера. Заходим в Settings -> Editor -> Live Templates. Здесь есть возможность просмотреть уже готовые группы шаблонов и создать свою — нажав на плюсик в правой части панели. Также можно создать отдельный шаблон, тогда он добавится в группу user. После нажатия у вас снизу появится окошко, в котором нужно ввести аббревиатуру, описания и собственно сам текст шаблона. Также будет предупреждающая надпись "No applicable context" и кнопка Define рядом, кликнув на которую мы увидим список возможных контекстов — HTML, XML, Java, Javascript, CSS и тд. У некоторых есть подпункты, например в Java это возможность использовать шаблон в методе, в комментарии, на уровне класса, где то ещё или везде сразу. Выберем для примера весь пакет Java.

В качестве аббревиатуры напишем log, в качестве теста вот такую вот строку:

private static final Logger LOGGER = Logger.getLogger($CLASS_NAME$.class.getName());

Далее жмём на кнопку которая находится в правой части — Edit variables. В открывшемся окошке видим таблицу с одной записью — CLASS_NAME, которая соответствует переменной которую мы указали в тексте файла в качестве имени класса. У нее есть поля Expression, Default value, Skip if defined. Первое поле это селект в котором нам предлагаются всевозможные значения которые можно подставить. Второе это просто строка в которой мы можем написать что угодно взяв это в кавычки. Ну а третье поле предлагает нам пропустить редактирование переменной если она задана в одном из первых свойств. В нашем случае нам понадобится значение селекта className() из поля Expression. При желании можно выбрать пропуск редактирования. Жмём OK, после Apply и можно проверять. Создаём класс с любым именем, пишем внутри log, нажимает TAB и вуаля — у нас есть логгер у которого к вместо CLASS_NAME имя текущего класса.

Пример:

public class CodeTemplates {
    private static final Logger LOGGER = Logger.getLogger(CodeTemplates.class.getName());
}

Особенности и возможности:


1. При создании шаблонов есть ключевая переменная $END$ указывающая на то где будет находиться курсор когда вы создадите шаблон (По умолчанию в конце кода шаблона).

System.out.println($END$);

2. Вторая ключевая переменная это $SELECTION$. Если она присутствует в вашем шаблоне, то он будет появляться в меню Surround With(Ctrl+Alt+T). Это нужно если хотите заключить ваш код в обёртку.

System.out.println("$SELECTION$");

Т е допустим у вас есть слово или предложение, например TEST — вы ставите курсор в конец слова, нажимаете Ctrl+Alt+T и среди шаблонов можете выбрать свой, и тогда получится:

System.out.println("TEST");

P.S.: для блока кода или текста, достаточно его сначала выделить.

3. Некоторые из расширений в Extentions могут принимать в аргументы значения различных типов, в том числе другие расширения. Чтобы было понятнее приведу пример. Возможно многие знакомы с аннотацией JPA Table, в которую можно среди прочего передавать имя таблицы соответствующей данному классу(сущности). Обычно имена таблицы и класса совпадают, с различием лишь в том что className становится CLASS_NAME. Шаблон для создания данной аннотации будет примерно таким:

@Table(name = "$TABLE NAME$")

В Extentions выбираем capitalizeAndUnderscore(String), только вместо String уже сами прописываем className:

capitalizeAndUnderscore(className)

Пример:

@Table(name = "CODE_TEMPLATES")
public class CodeTemplates {
	...
}

PS:
В селекте поля Extentions можно прописать и свои значения, как в инпуте, но не вижу в этом смысла, ведь это можно сделать в поле Default value.

4. Также есть возможность импортировать(File -> Import Settings) и экспортировать(File -> Export Settings) шаблоны и другие настройки в виде jar-файлов. Т к шаблоны экспортируются в виде xml-файлов, то при желании можно зайти в директорию .IntelliJIdea$VERSION$/config/templates и добавить туда свой xml. При этом нужно чтобы в файле указывалась группа шаблонов, иначе вы не увидите их в списке. Если же не указывать группу, то отдельные шаблоны можно добавить в один из имеющихся уже файлов, как вариант — user.xml.
Пример user.xml c логером и Table:
<templateSet group="user">
  <template name="log" value="private static final Logger LOGGER = Logger.getLogger($CLASS_NAME$.class.getName());" description="Logger Template" toReformat="false" toShortenFQNames="true">
    <variable name="CLASS_NAME" expression="className()" defaultValue="" alwaysStopAt="true" />
    <context>
      <option name="JAVA_DECLARATION" value="true" />
    </context>
  </template>
  <template name="tb" value="@Table(name = "$TABLE_NAME$")" description="" toReformat="false" toShortenFQNames="true">
    <variable name="TABLE_NAME" expression="capitalizeAndUnderscore(className)" defaultValue="" alwaysStopAt="true" />
    <context>
      <option name="JAVA_CODE" value="true" />
    </context>
  </template>
</templateSet>


Заключение


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

P.S.: При желании можно писать свои собственные плагины для IDE, в том числе расширения для шаблонов.

Исправления или дополнения приветствуются.

Ссылка на официальную документацию: ТУТ
За дополнение спасибо justboris

Комментарии (13)


  1. volk0ff
    21.06.2018 18:49

    Спасибо за статью.

    Вот тут еще немного «ништяков» для phpStorm.
    (Не особо много, но некоторые весьма юзабельные)
    phpstorm.tips


  1. justboris
    21.06.2018 19:10

    А еще шаблоны можно экспортировать в xml-файл и расшарить где-нибудь.


    У меня вот таким образом выложены шаблоны для удобного написания import/export в Javascript.


    1. Dreyk
      22.06.2018 03:13

      у меня похожие
      im => import | from '|'
      imo => import { | } from '|'
      cso => const { | } from |


      1. justboris
        22.06.2018 10:38

        Хорошая идея про cso! Добавил себе такой шорткат тоже.


  1. Goodkat
    22.06.2018 00:00

    Кто-нибудь может подсказать удобные плагины для Bugzilla/Jira типа Mylyn для Eclipse и для Subversion/Git типа аналогичного для Eclipse?


    Перешёл год назад с Eclipse на JetBrains, всё стало удобнее и быстрее, кроме отвратительной работы дефолтных плагинов с багтрекером и VCS. Доходит до того, что открываю проект параллельно в Eclipse, чтобы открыть баг, посмотреть историю коммитов, а в конце работы закрыть баг и сделать коммит. Ну или в браузере и консоли, в простых случаях.


    1. immaculate
      22.06.2018 04:05
      +1

      А чем работа с Git не устраивает? Все есть: и diff, и blame, и push, и pull, и merge, и даже rebase. Все отлично интегрировано со средой. Уже несколько лет как можно в annotate посмотреть annotate на предыдущую версию кода.


      Что касается интеграции с багтрекером — мне это никогда не было нужно, не очень понимаю, зачем это может быть нужно.


      1. Goodkat
        22.06.2018 08:31

        Не устраивает, потому что неудобно.
        В Eclipse тыкаешь мышкой в файл или папку, и в окошке истории сразу видно историю коммитов для выделенного файла или всех файлов в выделенной папке на любом уровне вложенности. В JetBrains этого нет или я не нашёл — там можно в окошке истории как-то отфильтровать историю, но там показывается не всё и нельзя привязать фильтр к текущему выделенному файлу в дереве проекта.
        В Eclipse можно показывать имя последнего коммиттера и номер ревизии сразу в дереве проекта.
        В Eclipse подсвечивается папка, если в ней есть изменённый файл на любой глубине вложенности, а в JetBrains подсвечиваются только сами файлы.


        Багтрекер: в mylyn/eclipse можно в один клик переключаться между багами, причём контекcт будет тоже переключаться. Можно отфильтровать баги по любым критериям — проектам, срочности и т.п., и сохранить эти фильтры, а в JetBrains показывается просто весь список багов.


        IDE на то и IDE, что в неё всё нужное интегрированно. Так-то да, можно пользоваться багтрекером в браузере и проводником ОС для навигации по дереву проекта, а гитом в консоли.


        1. immaculate
          22.06.2018 08:59

          По поводу контроля версий, мне кажется, что это вопрос отчасти вкуса, отчасти привычки. Посмотреть все измененные файлы и историю в PyCharm можно в окне, открывающемся по Alt-9. И я уже давно привык к идеологии Git, что изменение — это не правка одного файла, как в Subversion, а changeset. И историю читаю и воспринимаю changeset'ами.


          Для просмотра истории чужих правок, я часто пользуюсь инструментами вне PyCharm, впрочем, например, tig.


          Это если из любопытства. А в работе реально неоценимая фишка PyCharm — при клике по левому полю можно включить Annotate (я даже забиндил на сочетание Ctrl-;), так что если при работе над файлом нужно понять почему и зачем в файле находится какой-то кусок кода, можно включить annotate и посмотреть кем, и когда он был изменен. Если непонятно, там же можно вызвать annotate для предыдущей версии, и так далее. Этой возможностью пользуюсь чаще всего (за исключением стандартных commit/push/pull/stash/rebase).


          Мне кажется, что это просто вопрос привычки. Я за свою жизнь столько различных редакторов и IDE сменил, что ни к чему стараюсь не цепляться. Только не выношу редакторы без эмуляции vim. Считаю, что vim — вершина эргономики для редактирования текстов, в PyCharm вседа стоит IdeaVIM.


          Про баги не совсем понял, тут в каждом проекте свой багтрекер, и свой workflow. Я в своей жизни пользовался и пользуюсь: GitHub Issues, Trello, Jira, Asana, и т.п. Как правило, мне хватает открытой вкладки в браузере, где открыта страница с текущей используемой системой.


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


        1. sabio
          22.06.2018 20:56

          История изменений для файла/папки в IDEA, конечно же, есть.
          В последнем EAP — это кнопка в виде часов на главном toolbar. Ну или Ctrl+Shift+A и 'show history'. Или через меню VCS Operations по Alt+`.


          Интеграция с баг-трекером (в т.ч. переключение контекста при смене тикета, а также изменение статуса тикета (на In Progress), создание новой ветки в VCS, трекинг потраченного времени) сделана в плагине Task Management:
          https://www.jetbrains.com/help/idea/managing-tasks-and-context.html


          1. Goodkat
            22.06.2018 21:17

            Есть, конечно же, но сделано крайне неудобно.
            В Eclipse я тыкаю в файл/папку в дереве проекта, окошко истории сразу обновляется. В IDEA нужно вручную вызывать историю.


            Сравните Task Managament c Mylyn — там и сохранённые запросы, и зависимости показываются, и отфильтровать можно как угодно:



            В IDEA это просто список багов для галочки, что он есть. Как мне там вывести только баги по одному проекту, только где статус FIXED, но не VERIFIED? Или все новые ещё не в работе? Или все, где исполнитель — я? А в Mylyn я сохранил несколько queries для этого, он мне удобно в одном окошке их показывает, со всеми вложенными зависимостями багов друг от друга.


    1. pyJIoH
      22.06.2018 12:37

      Ничего себе, а я наоборот. По двум разным проектам приходилось работать и в Идее и Эклипсе. Дак я не мог после идейной работы с гитом пользоваться egit'ом последнего. Ставил ставил рядом Идею как VCS клиент, создавал новые ветки и пушил только оттуда )


  1. sabio
    22.06.2018 21:04

    А ещё для каждого шаблона можно выбрать альтернативную "Expand with" клавишу.
    Мой любимый "альтернативный" шаблон: '+' и пробел после него внутри строки превращают "abc+|def" в "abc" + | + "def".


    Template text:
    " + $END$ + "


    1. sabio
      22.06.2018 21:08

      Ещё таким образом можно автоматически исправлять некоторые опечатки.
      Например, 'retrun' + пробел можно заменять на return $END$.