[Из песочницы] Интеграция ClangFormat и Notepad++

ClangFormat является одним из лучших инструментов для автоматического форматирования исходных кодов на языках C, C++, Java, JavaScript, Objective-C, C#. Существуют плагины для популярных сред разработки (IDE), но часто нужно быстро отформатировать файл или часть файла с исходным кодом без запуска громоздкой IDE, поэкспериментировать с настройками форматирования и разными версиями ClangFormat с возможностью быстрой отмены изменений. Использовать для этих целей консольную версию ClangFormat неудобно. Возможным решением является вызов ClangFormat из текстового редактора. На официальном сайте описаны способы интеграции с редакторами Vim, Emacs и некоторыми другими, но по интеграции с Notepad++ информации нет. Далее приводится несложная инструкция применительно к Notepad++ (для Windows).

Исходные требования


  • форматирование файла, открытого в Notepad++, при помощи ClangFormat;
  • форматирование выделенного фрагмента в файле;
  • отмена изменений;
  • переключение стиля (набора правил) форматирования;
  • переключение на другую версию ClangFormat;
  • по возможности использование стандартных средств, без пересборки ClangFormat и без написания нового плагина для Notepad++.


Установка и настройка


1. Если Notepad++ еще не установлен, скачиваем и устанавливаем его


https://notepad-plus-plus.org

2. В Notepad++ устанавливаем плагин NppExec


NppExec позволяет вызывать сторонние приложения из Notepad++ и взаимодействовать с компонентами библиотеки Scintilla, на основе которой написан Notepad++.

Plugins –> Plugin Admin... –> NppExec –> Install
Notepad++ перезапустится, после чего появится каталог /plugins/NppExec/ и пункт меню Plugins –> NppExec

3. Скачиваем исполняемый файл ClangFormat


Для этого на странице https://llvm.org/builds/ находим и скачиваем установочный файл для Windows, например LLVM-X.X.X-rYYYYYY-win64.exe. Весь пакет можно не устанавливать, достаточно архиватором извлечь файл clang-format.exe. Можно использовать 7-zip: удаляем у файла расширение .exe, открываем файл при помощи 7-zip и извлекаем из подкаталога bin/ файл clang-format.exe. Помещаем файл clang-format.exe в каталог /plugins/NppExec/clang-format/.

4. Добавляем конфигурационные файлы для ClangFormat


Конфигурационные файлы должны иметь название .clang-format или _clang-format. В них содержится набор правил (стилей) форматирования, формат которых описан в руководстве ClangFormat Style Options.

Для примера используем файлы из проектов Linux Kernel и Qt.

Скачанные с GitHub файлы .clang-format помещаем в соответствующие каталоги:
/plugins/NppExec/clang-format/LINUX_KERNEL/
/plugins/NppExec/clang-format/QT/

5. Создаем скрипт для NppExec


Открываем окно редактирования и запуска скриптов NppExec Plugins –> NppExec –> Execute... или нажимаем F6. Копируем и вставляем в окно приведенный ниже текст скрипта и сохраняем скрипт под названием clang-format кнопкой Save....

Скрипт NppExec
// Hide console
NPP_CONSOLE 0

//------------------------------------------------------------------------------
// Uncomment a line to select a style
//set style = LINUX_KERNEL
set style = QT
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
set clangformatexe = $(CWD)\plugins\NppExec\clang-format\clang-format.exe
set clangformatcfgdir = $(CWD)\plugins\NppExec\clang-format
set tmpdir = $(SYS.TEMP)
set clangformatcfgfile = $(clangformatcfgdir)\$(style)\.clang-format
set srcfiletmp = $(tmpdir)\~src.tmp
//------------------------------------------------------------------------------

cmd.exe /c if exist "$(clangformatexe)" (exit 0) else (exit 1)
if $(EXITCODE) != 0 then
    NPP_CONSOLE 1
    echo ERROR: "$(clangformatexe)" not found
    exit
endif

cmd.exe /c if exist "$(clangformatcfgfile)" (exit 0) else (exit 1)
if $(EXITCODE) != 0 then
    NPP_CONSOLE 1
    echo ERROR: "$(clangformatcfgfile)" not found
    exit
endif

// Copy $(clangformatcfgfile) to $(tmpdir)\.clang-format if their temestamps are different
cmd.exe /v /c " for %i in ("$(clangformatcfgfile)") do set date1="%~ti" && for %i in ("$(tmpdir)\.clang-format") do set date2="%~ti" && if not "!date1!"=="!date2!" ( echo !date1! != !date2! && echo COPYING $(clangformatcfgfile) to $(tmpdir)\ && copy "$(clangformatcfgfile)" "$(tmpdir)\" /Y )"
if $(EXITCODE) != 0 then
    NPP_CONSOLE 1
    echo ERROR copying "$(clangformatcfgfile)" to "$(tmpdir)"
    exit
endif

// Get selected text length
sci_sendmsg SCI_GETSELTEXT

// If nothing is selected - select the current line
if $(MSG_RESULT) == 1 then
    sci_sendmsg SCI_VCHOMEWRAP
    sci_sendmsg SCI_LINEENDWRAPEXTEND
endif

// Save selected text to $(srcfiletmp)
sel_saveto "$(srcfiletmp)" :a

cmd.exe /c if exist "$(srcfiletmp)" (exit 0) else (exit 1)
if $(EXITCODE) != 0 then
    NPP_CONSOLE 1
    echo ERROR: "$(srcfiletmp)" not found
    exit
endif

// Run ClangFormat
$(clangformatexe) -i -style=file "$(srcfiletmp)"
if $(EXITCODE) != 0 then
    NPP_CONSOLE 1
    echo ERROR running "$(clangformatexe)"
    exit
endif

// Replace selected text with $(srcfiletmp)
sel_loadfrom "$(srcfiletmp)"

// Delete $(srcfiletmp) file
cmd.exe /c del "$(srcfiletmp)"


После запуска скрипт на основе выбранного стиля форматирования, заданного в переменной style, выбирает нужный файл .clang-format, проверяет дату его изменения и при необходимости копирует его во временный каталог. Туда же во временный файл копируется выделенный фрагмент исходного кода, после чего запускается clang-format.exe. Отформатированный фрагмент копируется обратно в окно Notepad++. Затем временный файл удаляется.

В ClangFormat нет возможности указать путь к конфигурационному файлу .clang-format. ClangFormat будет искать его в каталоге форматируемого файла и, если не найдет, перейдет к поиску в родительских каталогах. После окончания работы скрипта файл .clang-format останется во временном каталоге для того, чтобы не выполнять его копирование при каждом запуске форматирования.

На всех этапах работы скрипта выполняется проверка на ошибки, и при их возникновении открывается консольное окно NppExec, в которое выводится сообщение.

6. В Notepad++ добавляем новый пункт меню для запуска скрипта


Открываем Plugins –> NppExec –> Advanced Options..., в выпадающем списке Associated script выбираем название скрипта clang-format и нажимаем на кнопку Add/Modify.

Перезапускаем Notepad++, после чего появится пункт меню Plugins –> NppExec –> clang-format.

image

7. В Notepad++ настраиваем клавиатурную комбинацию для запуска скрипта


Будем использовать комбинацию Ctrl + I по аналогии с QtCreator. Открываем Settings –> Shortcut Mapper.

По умолчанию комбинация Ctrl + I занята, поэтому нужно ее освободить кнопкой Clear во вкладке Main Menu (строка 38 Split Lines в текущей версии Notepad++). После этого во вкладке Plugin commands присваиваем комбинацию Ctrl + I скрипту clang-format.

Готово, можем пользоваться!

Инструкция по использованию


Открываем файл с исходным кодом в Notepad++, выделяем нужный фрагмент или весь текст и нажимаем Ctrl + I. Если ничего не выделять, то будет отформатирована текущая строка.

image

Для отмены изменений используем стандартные средства редактора (Ctrl + Z).
Для изменения правил форматирования редактируем конфигурационные файлы .clang-format в каталоге /plugins/NppExec/clang-format/
Если нужно использовать другую версию ClangFormat, то изменяем в скрипте путь к исполняемому файлу
set clangformat = "\path\to\clang-format.exe"
Для выбора другого стиля форматирования нажимаем F6 и в тексте скрипта clang-format выбираем нужный стиль путем раскомментирования одной из строк
set style = STYLE_NAME.

Все необходимые файлы находятся в архиве.

Удачного форматирования!

© Habrahabr.ru