Расстановка запятых

Что чаще всего нужно программисту от форматирования? Расстановка отступов? Или может быть разбиение списков параметров по вертикали? Следование каким-то конвенциям стиля? А вот и нет. Мне, как программисту, жутко не хватает программы, которая бы расставляла за меня запятые. Ну, или удаляла оттуда там где их быть не должно. На данный момент я так понимаю, можно воспользоваться каким-нибудь онлайн-сервисом или, в лучшем случае, как-то подцепиться к API. Есть на этот счет пара вариантов типа https://text.ru/api-check, https://sinoni.men/ или https://languagetool.org/ru/.

Однако, понятно, это всё ограничено и недешево. Да и это скорее эдакие линтеры, которые могут достаточно хорошо предположить и указать на явные ошибки. Про линтеры отдельный разговор. Вот бы было здорово сделать локальный LSP сервер для русского языка? Как вам идея для стартапа? Я провел достаточно много времени с экспериментами над грамматическим и морфологическим разбором предложений на русском языке. Была даже попытка прикоснуться к лингвистическим корпусам и нейронным сетям. Не могу сказать, что эксперименты закончились чем-то примечательным. Однако могу утверждать, что до определенной степени такую затею вполне можно воплотить даже в одного. Всё зависит лишь от желаемой точности и универсальности продукта. Если, положа руку на сердце, оценить, то как пишут даже вполне грамотные люди, то достичь уровня десятого класса средней школы уже было бы большим делом. Если текст состоит не из помеси трех языков, топонимов, имен древнеегипетских богов и сложносочиненных оборотов, коих большинство, то каких-нибудь 90% точности при расстановке запятых и двоеточий хватило бы за глаза.

Но это такое так - лирическое отступление. Мечты. А теперь о наших баранах.

coc-sql

В результате упражнений сделанных в предыдущей статье Vim теперь умеет во всякое, в том числе и в автоматическое форматирование. А форматировать я хочу SQL запросы и исходники на PL/SQL, то бишь процедуры, скрипты и прочий DDL. Так вот, если у стандартного форматировщика с запросами всё еще не очень плохо, то с остальным что-то у разработчика расширения явно не заладилось. Кому-то может хватить и форматирования исключительно запросов. По умолчанию ~/.vim/coc.vim добавляет сочетание <leader>lf для всех подключенных LSP и садит на него команду форматирования выделенной области. Я решил, что добавить сочетание для форматирования всего буфера будет не лишним.

nmap <leader>lF <Plug>(coc-format)

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

Родной форматировщик sql-formatter имеет ряд настраиваемых опций, которые можно положить в coc-settings.json как глобально, так и локально для определенного проекта. Я положил конфигурацию с полным перечнем опций в репозиторий на GitHub. В нем так же можно подключить и настроить линтер, который, так же как и форматировщик почему-то не умеет в процедуры и скрипты - только запросы. По этому я его тут же отключил. Запросы мне проверять незачем - они либо работают, либо нет.

Поэтому я недолго думая отправился искать альтернативное расширение, может быть даже ограниченное одним только PL/SQL. И не нашел. Что до сих пор для меня кажется удивительным. Но, как гласит одна древняя китайская мудрость: Дорогу молодым! Пришлось наскоро пилить собственный вариант.

formatprg

Vim не был бы Vim-ом если бы не умел что-то и без плагинов когда дело касается манипуляций с текстом. А как назвать форматирование если не манипуляцией над текстом. Во-первых, есть встроенная команда :filter которая либо запускает встроенную функцию, либо скармливает в stdin внешней программе, указанной в опции equalprg, диапазон либо выделение, и вставляет обратно результат из stdout. Но её принято использовать для каких-то функций типа сортировки, подсчета слов и всякого стандартного из арсенала POSIX.

А конкретно для форматирования предусмотрена еще одна встроенная приблуда вызываемая сочетанием gq. Она ровно так же как фильтр имеет свою пару опций formatexpr и formatprg действующих по похожему принципу. Первая опция, если она задана, вызывает некую внутреннюю команду, а formatprg - внешнюю программу, так же работающую со стандартными потоками ввода вывода. Рассмотренный coc.nvim в общем-то по умолчанию и устанавливает в formatexpr свою функцию. В этом можно убедиться вызвав :set formatexpr либо воспользовавшись, собственно, gqна выделении или на последующем движении.

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

SQLCli

И в очередной раз Oracle "не подвел". Oracle просто не сделал такую программу, и, судя по всему, не собирается. (Ведь все разработчики под Oracle должны работать с безобразными и гигантскими решениями сугубо от Oracle или Toad). Наименьшим из зол на данным момент оказался некий консольный вариант Oracle SQL Developer, который в отличие от SQL*Plus, хотя бы отдаленно пытается быть дружелюбным к пользователю. И в числе прочего имеет таки внутри себя функцию форматирования, работающую на механизме, используемом в SQL Developer.

Но, опять же, с нюансами. Во-первых, в него никаким образом нельзя подсунуть стандартный поток ввода. (Я по крайней мере не смог). Во-вторых, оказалось архисложно заставить его замолчать и не выводить ничего в вывод. Тем не менее с помощью говна и палок, удалось сделать обертку, которая приближенно напоминает искомый результат.

Назвал я её незатейливо sqlcl-formatter-wrapper и выложил на GitHub. Как и упоминалось, с ним я всё еще вожусь, и поэтому как положено ничего не оформлено. Вкратце нужно отдельно установить SQLCli либо взять путь установленного у вас SQL Developer. Затем просто куда-нибудь скачать исходники обертки:

$ git clone https://github.com/johnrembo/sqlcl-formatter-wrapper.git

И указать в скрипте sqlaf путь к бинарному sql (для SQL Developer это скорее всего /opt/sqldeveloper/sqldeveloper/bin/sql). Настройка Vim еще проще - у меня это выглядит как две дополнительные инструкции в файле ~/.vim/coc.vim.

autocmd FileType sql,plsql setlocal formatprg=~/src/sqlcl-formatter-wrapper/sqlaf
autocmd FileType sql,plsql setlocal formatexpr=

Вторая строка отключает форматировщик coc-sql, так как formatexpr имеет более высокий приоритет. Родное сочетание <leader>lf при этом будет работать так же как и раньше. А обертку можно будет вызывать отдельно с помощью стандартного gq.

Настраивается форматирование путем редактирования приложенного файла af.xml либо, опять же, можно взять его из SQL Developer, если он у вас есть, предварительно натыкав в нем мышкой нужные пункты.

Есть и известные болячки. Форматирует более или менее родной форматировщик не плохо, но всё-таки всё-равно не идеально. Не так как я это себе представляю. Но это уже моя личная боль. Так же SQLCli будучи java приложением запускается очень не мгновенно и жать форматирование чаще чем перед сохранением я бы не стал. Есть мысль запустить SQLCli отдельно в качестве некоего демона и кормить его в памяти, но руки пока не доходят.

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

И снова это скорее мечты, которые, как говорит еще одна китайская мудрость, не вредны. На чем сегодня позвольте откланяться. Далее будет некий перерыв, потому что с PHP и DAP я пока не сильно и сам разобрался. Как будут какие-то выходящие за рамки готовых решений обязательно отпишусь. А пока не теряйте, есть немало вещей о которых я пописываю и в основном своем бложике на злосчастном Дзене.

:noa :xa

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


  1. IvanLokh
    00.00.0000 00:00
    +2

    Расставлять запятые в VIM может LanguageTool можно установить локальный сервер или использовать свободный. Интеграция с VIM: https://github.com/dpelle/vim-LanguageTool


    1. Rembo123 Автор
      00.00.0000 00:00
      +1

      Хм. А вот это надо попробовать. Спасибо.