Neovim + Telescope и разные раскладки клавиатуры

Опубликовано 02.12.2024 в OpenBSD

Анализировал тут в очередной раз свои незамысловатые потребности в области редактирования текстовых файлов (подобный анализ в этой и смежных областях я люблю, могу и практикую регулярно). Нашел следующие паттерны, причиняющие мне определенное неудобство:

  1. открытие файла, расположение и/или название которого я помню достаточно смутно (положим, где-то там когда-то я настраивал автовключение проверки орфографии для различных типов файлов, но где? помню только, что там присутствовало слово 'after' в пути...)

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

  3. то же самое с поиском по справочному руководству Neovim: часто я весьма смутно ощущаю как сформулировать, что именно я там хочу найти?

Ну а очертив таким образом текущие потребности и исходя из рационального, никогда не подводящего меня принципа "я не являюсь уникальной снежинкой и нитакусиком, всё, что я выдумал - уже приходило в голову сотням и тысячам людей до меня" - я, разумеется легко нагуглил этот ваш великий и ужасный telescope.nvim: плагин для Neovim, который из коробки умеет все перечисленное и еще многое, многое, МНОГОЕ-МНОГОЕ другое!

Про сам Telescope, его возможности, кастомизируемость и области потенциального применения - я тут распространяться не буду, ибо у меня нет лишнего года времени и трех-четырех клавиатур, которые можно стереть в процессе освещения этой бесконечной темы. Упомяну лишь, что нужные оному телескопу для работы утилиты ripgrep и fd присутствуют в пакетной базе OpenBSD и могут быть установлены, как обычно, через doas pkg_add ripgrep fd. Ну а сам Telescope и его зависимости - см. по ссылке выше.

Я лучше о другом расскажу. Не так давно я писал, как добавил в Neovim функцию переключения раскладки на латиницу при выходе из режима вставки в командный режим, а при возвращении обратно в режим вставки, соответственно, функцию восстановления ранее использовавшейся раскладки. Штука эта до того удобная, что стала для меня уже чем-то самим собой разумеющимся - и именно поэтому мне поначалу показалось неудобным работать с Telescope.

Неудобство вот в чем: предположим, ввожу я текст на русском языке (да вот хоть бы этот) и выхожу из режима вставки в "нормальный" командный режим чтобы что-нибудь там поизучать через этот самый Telescope. При выходе у меня прикапывается специально мною разработанной методом копипейст-программирования функцией на lua русская раскладка - ведь я печатал по-русски?

И вот я топчу <leader>+ff (в моем случае в качестве этой самой магической клавиши <leader> я использую пробел:

-- use Space as <leader> key 
vim.g.mapleader = " "
-- Telescope search hotkeys
local builtin = require('telescope.builtin')
vim.keymap.set('n', '<leader>ff', builtin.find_files, { desc = 'Telescope find files' })
vim.keymap.set('n', '<leader>fg', builtin.live_grep, { desc = 'Telescope live grep' })
vim.keymap.set('n', '<leader>fb', builtin.buffers, { desc = 'Telescope buffers' })
vim.keymap.set('n', '<leader>fh', builtin.help_tags, { desc = 'Telescope help tags' })

предо мной открывается всплывающее окно Telescope (ну, в терминологии neovim окно, конечно), где я по умолчанию нахожусь в строке ввода символов для поиска... в режиме ввода! А соответственно, упомянутая ранее lua-функция, обнаружив переход в режим ввода, восстановила последнюю использовавшуюся раскладку - русскую, которая мне в Telescope-то как раз нафиг и не сдалась.

Это нужно исправить, заодно доказав, что даже презренный гуманитарий способен писать пусть говнокод, но таки рабочий говнокод на языке lua. Итак, вот доработанный файл myxkbswitch.lua: манипуляции с сохранением/восстановлением раскладки НЕ применяются теперь для окна Telescope, но остаются работоспособными для прочих окон:

local M = {}
-- nvim_create_autocmd shortcut
local autocmd = vim.api.nvim_create_autocmd

-- needs "xkb-switch" or "xkb-switch-i3" app to be installed 
local xkb_switch_lib = '/usr/local/lib/libxkbswitch.so'

-- get current layout
local function get_current_layout()
    return vim.fn.libcall(xkb_switch_lib, 'Xkb_Switch_getXkbLayout', '')
end

-- get the "filetype" option for active buffer
local function get_current_filetype()
    return vim.api.nvim_buf_get_option(0, "filetype")
end

-- for first use after nvim has been started 
local saved_layout = get_current_layout()

function M.setup()
    -- When leaving Insert Mode:
    -- 1. Save the current layout (but NOT for Telescope menu)
    -- 2. Switch to the US layout
    autocmd(
        'InsertLeave',
        {
            pattern = "*",
            callback = function()
                vim.schedule(function()
                    current_filetype = get_current_filetype()
                    if current_filetype ~= 'TelescopePrompt' then
                        saved_layout = get_current_layout()
                    end
                    vim.fn.libcall(xkb_switch_lib, 'Xkb_Switch_setXkbLayout', 'us')
                end)
            end
        }
    )

    -- When entering Insert Mode:
    -- 1. Switch to the previously saved layout (if it is NOT Telescope window!)
    autocmd(
        'InsertEnter',
        {
            pattern = "*",
            callback = function()
                vim.schedule(function()
                    current_filetype = get_current_filetype() 
                    if current_filetype ~= 'TelescopePrompt' then 
                            vim.fn.libcall(xkb_switch_lib, 'Xkb_Switch_setXkbLayout', saved_layout) 
                    end
                end)
            end
        }
    )


end

return M

И оно даже работает как нужно. Ну, если не забыть вписать require('myxkbswitch').setup() куда-нибудь в init.lua.

P.S. А чтобы Telescope искал по скрытым файлам (по умолчанию не ищет) в тот же init.lua можно прописать вот это:

-- Telescope options
require('telescope').setup {
    pickers = {
        find_files = {
            hidden = true -- show hidden files while file search
        }
    }
}

P.P.S. Чтоб два раза не вставать: заодно сделал еще одно микроулучшение своего юзер ыкспириенса: я время от времени пользуюсь терминалом прямо внутри текстового редактора (открываю командой :term, хоткея не назначал в силу редкости использования) и давно хотел сделать так, чтобы а) терминал открывался сразу в режиме ввода (дефолтное поведение не такое - нужно сначала нажатием i войти в режим ввода), и б) чтобы в терминале не применялась проверка орфографии (а по умолчанию она там за каким-то фигом применяется если включено для всего редактора). Короче, это делается так:

vim.api.nvim_create_autocmd({ "BufWinEnter", "WinEnter", "TermOpen" }, {
  pattern = "term://*",
  callback = function()
    vim.cmd.startinsert()
    vim.cmd.setlocal "nospell"
  end,
})