Подсветка SQL в исходном коде в Neovim

Постановка задачи copy

Задача: настроить в исходном коде (Go/Python/ваш_любимый_язык) подсветку синтаксиса внутри строковых переменных, содержащих SQL-запросы.

В качестве референса я выбрал реализацию аналогичной задачи в IDE JetBrains.

Подзадачи:

  1. Подсветка синтаксиса SQL
  2. Выделение фона для всего запроса

Результат copy

До

before

После

after

Реализация для Go copy

Директория ~/config/nvim:

.
├── lua/...
└── queries
    └── go
        ├── highlights.scm
        └── injections.scm

injections.scm:

; extends

([
  (interpreted_string_literal_content)
  (raw_string_literal_content)
] @injection.content
 (#match? @injection.content "(SELECT|select|INSERT|insert|UPDATE|update|DELETE|delete).+(FROM|from|INTO|into|VALUES|values|SET|set).*(WHERE|where|GROUP BY|group by)?")
(#set! injection.language "sql"))

highlights.scm:

; extends

([
  (interpreted_string_literal_content)
  (raw_string_literal_content)
] @sql.queries
(#match? @sql.queries "(SELECT|select|INSERT|insert|UPDATE|update|DELETE|delete).+(FROM|from|INTO|into|VALUES|values|SET|set).*(WHERE|where|GROUP BY|group by)?")
)

Объяснение copy

injections.scm copy

В этом файле описываются инъекции (интеграции, внедрения) одного языка в другой.

При помощи выражения

[
  (interpreted_string_literal_content)
  (raw_string_literal_content)
] @injection.content

Мы выбираем содержимое объекта raw_string_literal_content (в Go строки являются этим объектом)

Затем проверяем, что выражение содержит одно из ключевых слов SQL:

(#match? @injection.content "(SELECT|select|INSERT|insert|UPDATE|update|DELETE|delete).+(FROM|from|INTO|into|VALUES|values|SET|set).*(WHERE|where|GROUP BY|group by)?")

И если это так, устанавливаем для выбранного содержимого язык SQL:

(#set! injection.language "sql"))

Подробнее о том, как это устроено, можно узнать в видео “Подсветим SQL, где бы он ни был!” (“Куда войти?”).

highlights.scm copy

В этом файле опишем дополнительные правила для выделения фона SQL-запроса.

Аналогично инструкциям из injections.scm найдем все raw_string_literal_content, содержащие ключевые слова SQL. И установим им highlight-группу @sql.queries (название может быть произвольным).

Далее необходимо задать цвета для группы @sql.queries. Реализация зависит от того, как именно в вашем конфиге задаются правила для highlight-групп. В моём случае - при помощи плагина NvChad/base46, поэтому я добавил в конфиг своей цветовой тему следующую строку:

local mix_col = require("base46.colors").mix

M.polish_hl = {
  -- ...
  treesitter = {
    -- ...
    ["@sql.queries"] = { bg = mix_col("#20A969", M.base_30.black, 87) },
  },
}

mix_col - вспомогательная функция для объединения двух цветов в заданной пропорции. В данном случае при помощи неё удается достичь эффекта полупрозрачного выделения засчет смешивания зелёного цвета и цвета фона.

Источники copy

читайте также