
Послесловие
По большому счету единственной незакрытой темой в рубрике "Про Vim" осталась тема об альтернативе Conqueror of Completion для Neovim в Lua исполнении. Причиной перерыва между данной и предыдущей статьей в рубрике стало отсутствие необходимости в этой самой альтернативе. Ну или вернее причина может быть и была: во-первых - что бы удовлетворить любопытство, во-вторых - CoC действительно кажется громоздким и достаточно сложным внутри. Вариант на Lua мне бы дался легче, если бы захотелось что-то в нем подшаманить. Наверное.
С другой стороны, функционально связка CoC + PhpActor относительно плотно покрывает все современные сценарии разработки в не очень навороченных проектах. CoC прекрасно различает вставки HTML, CSS, JavaScript, SQL прямо в одном PHP файле, PhpActor ловко орудует с autoload путями, отлавливает хитрые ошибки, достаточно резво подсказывает сигнатуры, ищет референсы и дает свободно скакать по декларациям.
Тем не менее последний проект, над которым мне приходится трудиться в последнее время, явно не входит в число простых или даже средних. Это достаточно серьезная и разветвленная кодовая база с достаточным количеством зависимостей и, прямо скажем, непростой структурой. И тут некоторые функции начали отваливаться и подтормаживать.
В первую очередь стала спотыкаться диагностика. Мало того что языковой сервер стал подъедать память, иногда он просто стал вылетать без видимых на то оснований.
Во-вторых, при быстром перемещении по коду и вовсе редактор стал вставлять какие-то непонятные символы в исходный код. Что просто никак не совместимо с профессиональным производством.
Сразу необходимо сказать, что вариант с Neovim (Lua) не решил всех проблем. При этом появились другие. Как выяснилось позже, виноват в этом был скорее не Vim и CoC, а сам LSP PhpActor. В деталях выяснить причины такой деградации пока не удается, и следует также сразу отметить, что и замена LSP на варианты Intelephence или Psalm не оказалась выходом из ситуации.
Psalm, как оказалось, годен исключительно в качестве дополнительной диагностической утилиты, с задачами которой мне лично хватает с головой PHP Stan. А Intelephence, для активации многих необходимых функций требует покупную лицензию, которую из нашей страны приобрести решительно невозможно. Да и подумалось не нужно, раз так.
А подумалось, что можно восполнить недостающие функции отдельными плагинами и приспособлениями. Так вот о них подробнее.
Языковой сервер
Intelephence, по крайней мере в урезанном виде, показывает себя пока лучше, чем PhpActor в части производительности и ресурсоемкости. Устанавливается сервер при наличии npm тривиально:
npm i intelephense -g
И добавляется в Neovim посредством специального плагина nvim-lspconfig. И вспомогательного cmp-nvim-lsp, который подмешивает результаты автодополнения к результатам родного omnifunc. В моем случае настройка языковых серверов выделена в репозитории в отдельный файл ~/.config/nvim/lua/plugins/nvim-lspconfig.lua, на содержимом которого, наверное, не стоит подробно останавливаться. Приведу здесь только кусок, который касается непосредственно Intelephence:
-- import lspconfig plugin safely local lspconfig_status, lspconfig = pcall(require, "lspconfig") if not lspconfig_status then return end -- import cmp-nvim-lsp plugin safely local cmp_nvim_lsp_status, cmp_nvim_lsp = pcall(require, "cmp_nvim_lsp") if not cmp_nvim_lsp_status then return end -- enable keybinds only for when lsp server available local on_attach = require("plugins.handlers").on_attach -- used to enable autocompletion (assign to every lsp server config) local capabilities = cmp_nvim_lsp.default_capabilities() ... lspconfig.intelephense.setup({ capabilities = capabilities, filetypes = { "php" }, on_attach = on_attach, settings = { intelephense = { files = { maxSize = 5000000, }, }, }, on_init = function(client) client.server_capabilities.documentFormattingProvider = false end, }) ...
Здесь последовательно говорится о том, что нужно подтянуть два плагина: lspconfig - для активации сервера, cmp_nvim_lsp - для интеграции автодополнения. Затем идет инструкция добавления дополнительных горячих клавиш, только в случае если мы имеем дело с файлом, для которого требуется языковой сервер. Эти сочетания вынесены в отдельный файл .config/nvim/lua/plugins/handlers.lua. (Не спрашивайте зачем, тоже где-то подсек). Объявляются для удобства две локальные переменные on_attach и capabilities. Ну, и, собственно, подключается LSP сервер, если тип файла совпадает с указанным.
Дополнительные настройки и отключение форматирования это мои текущие настройки. Для форматирования, например, я использую PHP Code Style Fixer, о котором ниже.
Рефакторинг
Главными функциями, недостающими для полноценной работы с кодом в урезанном Intelephence, является отсутствие поддержки переименования и навигации по декларациям. И если второе полноценно решается альтернативными средствами навигации по коду, то в части переименования переменных и выделения каких-то блоков кода в функции и литералы, и наоборот внедрения их обратно в код, я столкнулся с определенными проблемами.
Во-первых, единственный плагин, который удалось отыскать для рефакторинга, существенно устарел, и вряд ли он подходит для современного кода полностью. После добавления его, например, при помощи Packer, появляется несколько функций частично закрывающих мои потребности.
... use("adoy/vim-php-refactoring-toolbox") ...
В целом, в простых ситуациях, неудобств от устаревания пока не обнаружено, и наиболее частые применения функционируют. Однако, всё же неприятно осознавать, что проект мертвый и что следующая версия языка может сделать плагин совершенно бесполезным.
Со стандартной раскладкой плагина можно соглашаться или нет. Я был не согласен, так как пытаюсь подобрать свой семантический подход к сочетаниям клавиш в целом. Что бы отключить родную схему следует установить переменную vim.g.vim_php_refactoring_use_default_mapping в значение 0 где-нибудь при запуске. Мой вариант находится в файле ~/.config/nvim/lua/plugins/php-refactoring-toolbox.lua и вызывается из ~/config/nvim/ftplugin/php.lua.
navigator.lua
По дороге пришлось поменять и GUI плагин навигации и автодополнения, поскольку lspsaga также перестал поддерживаться и в целом доставлял некие неудобства постоянной сменой API. В отличии от функций рефакторинга тут специфика языка не сильно влияет и выбора плагинов чуть больше. Остановился на ray-x/navigator.lua, который помимо, собственно передвижения по тегам, интегрируются с nvim-lspconfig. В вызов Packer добавляем:
... use("ray-x/guihua.lua") use({ "ray-x/navigator.lua", requires = { { "ray-x/guihua.lua", run = "cd lua/fzy && make" }, { "neovim/nvim-lspconfig" }, }, }) ...
Затем, важно отключить конфигурацию LSP ранее настроенного с помощью nvim-lspconfig сервера, так как плагин пытается самостоятельно настроить доступ к серверу. Что в моей конфигурации находится в ~/.config/nvim/lua/plugins/navigator.lua
-- import x-ray/navigator safely local nav_status, nav = pcall(require, "navigator") if not nav_status then return end nav.setup({ lsp = { disable_lsp = { "lua_ls", "intelephense", }, }, })
Далее можно было упомянуть всякие дополнительные штучки-дрючки, украшательства, но они общие для всех языковых серверов и немного мимо темы данной статьи. Поэтому к услугам читателя, собственно репозиторий, где это все настроено и работает.
Подсветка синтаксиса
Что касается подсветки, необходимый и достаточный функционал обеспечивается здесь глобально плагином к tree-sitter и не нуждается в дополнительной настройке. Для чего в файле ~/.config/nvim/lua/plugins.lua добавлена инструкция:
... -- tree sitter use({ "nvim-treesitter/nvim-treesitter", run = function() require("nvim-treesitter.install").update({ with_sync = true }) end, }) ...
Форматирование
Единственное, о чем следует упомянуть напоследок это функция форматирования, которую я в Intelephence отключил. Во-первых, она почему-то не настраивается совсем никак, или может я не нашел как это сделать. Во-вторых, в моих текущих проектах используется PHP Code Style Fixer, который работает отдельно, и который в общем-то не надо во что бы то ни стало встраивать в редактор. Но, если у вас похожая ситуация, то следующий плагин вам тоже может пригодиться.
Это тоже брошенный проект, тем не менее, альтернатив ему я пока не нашел. А скорее пока и не искал. Называется он null-ls и на самом деле, тоже является неким аналогом Lspconfig, но работает с отдельными функциями, такими как диагностика, форматирование и действия с кодом. На него тоже можно накрутить всяких других полезностей, которые не входят в состав основного языкового сервера. А в частности форматирование. Добавим к плагинам:
... -- formatting use({ "jose-elias-alvarez/null-ls.nvim", config = function() require("null-ls").setup() end, requires = { "nvim-lua/plenary.nvim" }, }) ...
И вызовем из ~/.config/nvim/init.lua файл настроек ~/.config/nvim/lua/plugins/null-ls.lua следующего содержания:
-- import null-ls plugin safely local setup, null_ls = pcall(require, "null-ls") if not setup then return end -- for conciseness local formatting = null_ls.builtins.formatting -- to setup formatters local diagnostics = null_ls.builtins.diagnostics -- to setup linters null_ls.setup({ sources = { formatting.stylua, formatting.google_java_format, diagnostics.eslint, formatting.phpcsfixer.with({ command = "./tools/php-cs-fixer/vendor/bin/php-cs-fixer" }), }, timeout = 100000, timeout_ms = 100000, debug = false, })
