About Vim – Neovim (Lua) PHP IDE

Afterword

By and large, the only open topic in the “About Vim” section was the topic about the Conqueror of Completion alternative for Neovim in Lua version. The reason for the break between this and the previous article in the section was the lack of need for this very alternative. Well, or rather, there may have been a reason: firstly, to satisfy curiosity, and secondly, CoC really seems bulky and quite complex inside. The Lua option would be easier for me if I wanted to cheat something in it. Maybe.

On the other hand, the CoC + PhpActor functional combination relatively tightly covers all modern development scenarios in not very sophisticated projects. CoC perfectly distinguishes HTML, CSS, JavaScript, SQL inserts directly in one PHP file, PhpActor deftly works with autoload paths, catches tricky errors, promptly suggests signatures, looks for references and allows you to freely jump through declarations.

However, the latest project I’ve been working on lately is definitely not one of the easy or even average ones. This is a fairly serious and extensive code base with a sufficient number of dependencies and, frankly speaking, a complex structure. And then some functions began to fall off and slow down.

First of all, diagnostics began to stumble. Not only did the language server begin to eat up memory, sometimes it simply began to crash for no apparent reason.

Secondly, when moving quickly through the code, the editor began to insert some strange symbols into the source code. Which is simply not compatible with professional production.

It must be said right away that the option with Neovim (Lua) did not solve all the problems. At the same time, others appeared. As it turned out later, it was not Vim and CoC that were to blame for this, but the LSP PhpActor itself. It is not yet possible to find out in detail the reasons for such degradation, and it should also be immediately noted that replacing LSP with variants Intelephence or Psalm was not a way out of the situation.

Psalm, as it turns out, is only suitable as an additional diagnostic utility, a task for which PHP Stan is sufficient for me personally. And Intelephence, to activate many of the necessary functions, requires a purchased license, which is absolutely impossible to purchase from our country. Yes, and I didn’t need to think about it, if that’s the case.

And I thought that it was possible to fill in the missing functions with separate plugins and devices. So here’s more about them.

Language server

Intelephence, at least in its stripped-down form, still shows itself better than PhpActor in terms of performance and resource intensity. The server is installed if available npm trivially:

npm i intelephense -g

And it is added to Neovim using a special plugin nvim-lspconfig. And auxiliary cmp-nvim-lspwhich mixes the results of autocompletion with the results of the native omnifunc. In my case, the language servers setting is highlighted in repositories to a separate file ~/.config/nvim/lua/plugins/nvim-lspconfig.lua, the contents of which are probably not worth dwelling on in detail. I will give here only a piece that relates directly to 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,
})

...

Here it is consistently said that you need to tighten up two plugins: lspconfig – to activate the server, cmp_nvim_lsp – to integrate auto-completion. Then comes the instruction to add additional hotkeys, only if we are dealing with a file that requires a language server. These combinations are placed in a separate file .config/nvim/lua/plugins/handlers.lua. (Don’t ask why, I also hooked it somewhere). For convenience, two local variables are declared on_attach And capabilities. Well, and, in fact, the LSP server connects if the file type matches the specified one.

Advanced settings and disabling formatting are my current settings. For formatting, for example, I use PHP Code Style Fixer, which is described below.

Refactoring

The main features missing to fully work with code in the stripped-down Intelephence are the lack of support for renaming and navigation through declarations. And if the second is fully solved by alternative means of navigating through the code, then in terms of renaming variables and separating some blocks of code into functions and literals, and vice versa, implementing them back into the code, I encountered certain problems.

Firstly, the only plugin that we were able to find for refactoring is significantly outdated, and it is unlikely that it is completely suitable for modern code. After adding it, for example, using Packer, several functions appear that partially cover my needs.

...
		use("adoy/vim-php-refactoring-toolbox")
...

In general, in simple situations, no inconvenience from obsolescence has yet been detected, and the most common applications function. However, it is still unpleasant to realize that the project is dead and that the next version of the language may make the plugin completely useless.

You can agree with the standard plugin layout or not. I disagreed because I’m trying to figure out my semantic approach to keyboard shortcuts in general. To disable the native scheme, set the variable vim.g.vim_php_refactoring_use_default_mapping in meaning 0 somewhere on startup. My version is in the file ~/.config/nvim/lua/plugins/php-refactoring-toolbox.lua and called from ~/config/nvim/ftplugin/php.lua.

navigator.lua

Along the way, I had to change the GUI plugin for navigation and auto-completion, because lspsaga also ceased to be supported and generally caused some inconvenience due to the constant change of API. Unlike the refactoring functions, the specifics of the language do not greatly influence here and the choice of plugins is slightly larger. Stopped at ray-x/navigator.luawhich, in addition to actually moving through tags, integrates with nvim-lspconfig. Add to the Packer call:

...		
        use("ray-x/guihua.lua")
		use({
			"ray-x/navigator.lua",
			requires = {
				{ "ray-x/guihua.lua", run = "cd lua/fzy && make" },
				{ "neovim/nvim-lspconfig" },
			},
		})
...

Next, it is important to disable the LSP configuration previously configured using nvim-lspconfig server, since the plugin tries to independently configure access to the server. What in my configuration is in ~/.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",
		},
	},
})

Further, we could mention all sorts of additional tricks and decorations, but they are common to all language servers and are a little beyond the topic of this article. Therefore, at the reader’s service, actually repositorywhere it’s all set up and working.

Syntax highlighting

As for the backlight, the necessary and sufficient functionality is provided here globally by a plugin for tree-sitter and does not require additional configuration. Why in the file ~/.config/nvim/lua/plugins.lua added instructions:

...
		-- tree sitter
		use({
			"nvim-treesitter/nvim-treesitter",
			run = function()
				require("nvim-treesitter.install").update({ with_sync = true })
			end,
		})
...

Formatting

The only thing worth mentioning at the end is the formatting function, which I disabled in Intelephence. Firstly, for some reason it can’t be configured at all, or maybe I haven’t found how to do it. Secondly, my current projects use PHP Code Style Fixer, which works separately, and which, in general, does not need to be built into the editor at all costs. But, if you have a similar situation, then the following plugin may also be useful to you.

This is also an abandoned project, however, I have not yet found any alternatives to it. Or rather, I haven’t looked for it yet. It’s called null-ls and in fact, it is also a kind of analogue of Lspconfig, but it works with separate functions, such as diagnostics, formatting and actions with code. You can also add all sorts of other useful things to it that are not included in the main language server. And in particular formatting. Let’s add to the plugins:

...
        -- formatting
        use({
            "jose-elias-alvarez/null-ls.nvim",
            config = function()
                require("null-ls").setup()
            end,
            requires = { "nvim-lua/plenary.nvim" },
        })
...

And we’ll call from ~/.config/nvim/init.lua settings file ~/.config/nvim/lua/plugins/null-ls.lua the following content:

-- 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,
})

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *