termux-language-server icon indicating copy to clipboard operation
termux-language-server copied to clipboard

Support for neovim/nvim-lspconfig

Open powerman opened this issue 1 year ago • 15 comments

While recommended configuration for Neovim at https://termux-language-server.readthedocs.io/en/latest/resources/configure.html#neovim works it's inconvenient to use together with lspconfig. I propose to add lspconfig support for termux-language-server.

I've already implemented and tested most of it (I've no idea is it exist and if yes then how to detect a "root dir" for Android Termux and ArchLinux projects, so I leave a TODO comment there). Probably needs some polishing and then you can make a couple PRs:

  1. Add server configuration file to https://github.com/neovim/nvim-lspconfig/tree/master/lua/lspconfig/server_configurations
  2. Add mapping between lspconfig's name "termux_ls" and mason's name "termux-language-server" to https://github.com/williamboman/mason-lspconfig.nvim/blob/main/lua/mason-lspconfig/mappings/server.lua

Here is setup I've used for testing.

  1. ~/.config/nvim/lua/lspconfig/server_configurations/termux_ls.lua:
local util = require 'lspconfig.util'

return {
    default_config = {
        cmd = { 'termux-language-server' },
        filetypes = {
            -- Android Termux
            'sh.build', -- build.sh
            'sh.subpackage', -- *.subpackage.sh
            -- ArchLinux/Windows Msys2
            'sh.PKGBUILD', -- PKGBUILD
            'sh.install', -- *.install
            'sh.makepkg.conf', -- makepkg.conf
            -- Gentoo
            'sh.ebuild', -- *.ebuild
            'sh.eclass', -- *.eclass
            'sh.make.conf', -- /etc/make.conf, /etc/portage/make.conf
            'sh.color.map', -- /etc/portage/color.map
            -- Zsh
            'sh.mdd', -- *.mdd
        },
        root_dir = function(fname)
            local gentoo_repo = util.root_pattern 'profiles/repo_name'(fname)
            -- TODO: Root detection for Termux and ArchLinux?
            return gentoo_repo or util.find_git_ancestor(fname)
        end,
        single_file_support = true,
    },
    docs = {
        description = [[
Termux is a language server for some specific bash scripts.

You can install termux-language-server using mason or follow the instructions here: https://termux-language-server.readthedocs.io/en/latest/resources/install.html

The file types are not detected automatically, you can register them manually (see below) or override the filetypes:

```lua
vim.filetype.add {
  extension = {
    -- ArchLinux/Windows Msys2
    install = 'sh.install',
    -- Gentoo
    ebuild = 'sh.ebuild',
    eclass = 'sh.eclass',
    -- Zsh
    mdd = 'sh.mdd',
  },
  filename = {
    -- Android Termux
    ['build.sh'] = 'sh.build',
    -- ArchLinux/Windows Msys2
    ['PKGBUILD'] = 'sh.PKGBUILD',
    ['makepkg.conf'] = 'sh.makepkg.conf',
  },
  pattern = {
    -- Android Termux
    ['.*%.subpackage%.sh'] = 'sh.subpackage',
    -- Gentoo
    ['.*/etc/make%.conf'] = 'sh.make.conf',
    ['.*/etc/portage/make%.conf'] = 'sh.make.conf',
    ['.*/etc/portage/color%.map'] = 'sh.color.map',
  },
}
```
]],
    },
}
  1. Somewhere else in my configs:
    vim.filetype.add {
        extension = {
            -- ArchLinux/Windows Msys2
            install = 'sh.install',
            -- Gentoo
            ebuild = 'sh.ebuild',
            eclass = 'sh.eclass',
            -- Zsh
            mdd = 'sh.mdd',
        },
        filename = {
            -- Android Termux
            ['build.sh'] = 'sh.build',
            -- ArchLinux/Windows Msys2
            ['PKGBUILD'] = 'sh.PKGBUILD',
            ['makepkg.conf'] = 'sh.makepkg.conf',
        },
        pattern = {
            -- Android Termux
            ['.*%.subpackage%.sh'] = 'sh.subpackage',
            -- Gentoo
            ['.*/etc/make%.conf'] = 'sh.make.conf',
            ['.*/etc/portage/make%.conf'] = 'sh.make.conf',
            ['.*/etc/portage/color%.map'] = 'sh.color.map',
        },
    }
  1. At beginning of lspconfig setup (adding our config because it's not supported officially yet):
            local configs = require 'lspconfig.configs'
            if not configs['termux_ls'] then
                configs['termux_ls'] = require 'lspconfig/server_configurations/termux_ls'
            end
            local server = require 'mason-lspconfig.mappings.server'
            server.lspconfig_to_package['termux_ls'] = 'termux-language-server'
            server.package_to_lspconfig['termux-language-server'] = 'termux_ls'

That's it, the rest of setup is usual for lspconfig.

powerman avatar Jul 15 '24 20:07 powerman

It looks like related to https://github.com/termux/termux-language-server/discussions/10?

Freed-Wu avatar Jul 15 '24 22:07 Freed-Wu

It looks like related to #10?

Yes, it is! I was happy to see it's already supported by Mason, it was a pleasant surprise. In theory Mason support is not required to use lspconfig, but in practice everyone depends on Mason, so without it we'll need some hacks and non-standard setup.

powerman avatar Jul 15 '24 23:07 powerman

Mason also does not work particularly well on Termux itself, so it would be nice to have official instuctions for setting up termux-language-server with lspconfig.

TomJo2000 avatar Jul 15 '24 23:07 TomJo2000

Mason also does not work particularly well on Termux itself

Not sure I understand what you mean. If there are issues with using Mason itself then all you need to use lspconfig (as shown above) without Mason is to make sure your nvim config won't call some mason plugin (e.g mason itself or 'williamboman/mason-lspconfig.nvim' or 'WhoIsSethDaniel/mason-tool-installer.nvim') to install termux-language-server (e.g. with 'termux_ls' item inside 'ensure_installed' list).

Of course, in this case you'll have to install termux-language-server manually.

powerman avatar Jul 15 '24 23:07 powerman

If there are issues with using Mason itself then all you need to use lspconfig (as shown above) without Mason is to make sure your nvim config won't call some mason plugin

Am aware. https://github.com/TomJo2000/.dotfiles/blob/478ea851ddde95861388111b1f4f034336588399/.config/nvim/lua/plugins/init.lua#L82-L122

TomJo2000 avatar Jul 15 '24 23:07 TomJo2000

3. At beginning of lspconfig setup (adding our config because it's not supported officially yet):
            local configs = require 'lspconfig.configs'
            if not configs['termux_ls'] then
                configs['termux_ls'] = require 'lspconfig/server_configurations/termux_ls'
            end
            local server = require 'mason-lspconfig.mappings.server'
            server.lspconfig_to_package['termux_ls'] = 'termux-language-server'
            server.package_to_lspconfig['termux-language-server'] = 'termux_ls'

@powerman What file do I add this segment to? I'm trying to get this to work for me. I'm an AUR maintainer, looking to get initiated as an official Arch packager.

txtsd avatar Nov 05 '24 04:11 txtsd

@txtsd You can see my complete config with this snippet here: https://github.com/search?q=repo%3Apowerman%2Fconfig.nvim+termux&type=code

powerman avatar Nov 05 '24 06:11 powerman

@powerman I used the relevant bits and incorporated it in my lazyvim setup, but it shows my entire PKGBUILD as an error.

2024-11-05-16:10:39:44:327516431-960x1052_grim

Is this something you're familiar with?

txtsd avatar Nov 05 '24 10:11 txtsd

Nope. If Neovim LSP works but show unexpected issues in your sources then open a separate issue about this.

powerman avatar Nov 05 '24 11:11 powerman

Thanks for this example config!

I'm just wondering if it wouldn't be a better approach to check with nvim-lspconfig's contribution guidelines and then just make a pull request directly over there. This server seems pretty stable by now, and even Mason supports it.

On another note, does this server even need a root_dir? It doesn't seem like workspaceFolders, rootUri or rootPath are ever utilized. Or is such a feature on the roadmap? Maybe @Freed-Wu can answer this.

gwuen avatar Nov 17 '24 01:11 gwuen

Thanks for the guide! I've been looking for a way to set this up for PKGBUILD projects.

I'm wondering how it might be possible to combine functionality with bash_ls? If I add "sh.PKGBUILD" to my filetypes for that server, it will initialize alongside termux_ls when I open a PKGBUILD file, but we will get a lot of invalid shellcheck diagnostics showing up for "unused" and "unassigned" variables. image

I understand that this is simply due to the fact that bash_ls does not understand that makepgk will deal with those correctly under the hood, but I am hoping there is a simple way to automatically dismiss these types of warnings, while retaining the utilities that bash_ls and shellcheck offer. Maybe there is a function we can pass for bashls.settings.bashIde.shellCheckArguments that will do the job.

a-priestley avatar Dec 27 '24 14:12 a-priestley

I'm wondering how it might be possible to combine functionality with bash_ls

termux-language-server doesn't call shellcheck. bash-language-server call it. this is a feature request of shellcheck. https://github.com/koalaman/shellcheck/issues/1843

Freed-Wu avatar Dec 27 '24 14:12 Freed-Wu

termux-language-server doesn't call shellcheck. bash-language-server call it. this is a feature request of shellcheck. koalaman/shellcheck#1843

Ahh, good news that it's a desired feature.

I was referring to the shellcheck integration exposed via bash-language-server. After some experimentation, I found that we can do something like the following in our config:

	bashls = {
		filetypes = { "bash", "sh", "sh.PKGBUILD" },
		settings = {
			bashIde = {
				shellcheckArguments = "-e SC2034",
                                ...
			},
		},
	},

Which will disable certain checks from shellcheck. I will play around with it a bit more to conditionally disable checks for only PKGBUILD files.

a-priestley avatar Dec 27 '24 15:12 a-priestley

We can add a dedicated config for any filetype that termux_ls handles, in this case PKGBUILD:

if not configs["bashls_pkgbuild"] then
	configs["bashls_pkgbuild"] = {
		default_config = {
			cmd = { "bash-language-server", "start" },
			filetypes = {
				-- ArchLinux/Windows Msys2
				"sh.PKGBUILD", -- PKGBUILD
			},
			settings = {
				bashIde = {
					shellcheckArguments = "-e SC2034,SC2154"
				},
			},
			root_dir = util.root_pattern(".git"),
			single_file_support = true,
		},
	}
end

Configure the mappings:

server_mappings.lspconfig_to_package["bashls_pkgbuild"] = "bash-language-server"
server_mappings.package_to_lspconfig["bash-language-server"] = "bashls_pkgbuild"

mason-lspconfig setup table:

bashls_pkgbuild = {},

a-priestley avatar Dec 27 '24 16:12 a-priestley

About how to make shellcheck ignore some warning of PKGBUILD, we can discuss in https://github.com/koalaman/shellcheck/issues/1843

Freed-Wu avatar Dec 27 '24 17:12 Freed-Wu

https://github.com/neovim/nvim-lspconfig/pull/3947

polyzen avatar Jul 13 '25 15:07 polyzen

  • Closed by https://github.com/neovim/nvim-lspconfig/pull/3947

TomJo2000 avatar Jul 13 '25 16:07 TomJo2000