Logo

dev-resources.site

for different kinds of informations.

PowerShell Development in Neovim

Published at
6/27/2024
Categories
powershell
neovim
wsl
Author
kas_m
Categories
3 categories in total
powershell
open
neovim
open
wsl
open
Author
5 person written this
kas_m
open
PowerShell Development in Neovim

Overview

I have been developing several PowerShell projects over the last year, solely in Neovim. Just recently I rebuilt my neovim config, and found a reliable way to get it configured.

The configuration uses Lazy package manager, I use several plugins, but for brevity I'll include only the configuration required to get the LSP and treesitter functionality. I use WSL with the default ubuntu distro, and use tmux for all my terminal needs.

The Configuration

Pre-Requisites

During my configuration process I ran into several errors that pointed me to missing packages in my fresh WSL install. I remember having to install all of these iteratively until my neovim was working smoothly.

  • Neovim (do not use ap-get, the stable repo contains a fairly old version. I just used the pre-built archive method from the repo, remember to do the Path command too.)
  • Lua
  • LuaRocks
  • PowerShell
  • A C Compiler (I installed gcc)
  • Python 3 (also sudo apt install python-is-python3 this made python3 run when using the python command, one of my plugins needed it apparently)
  • npm

These are all that I can remember running into, however there may be others, if during installation and configuration you see errors, please read them carefully as that’s how I found the above dependencies. A lot of the time I saw ‘x’ command not found, or ‘x’ not installed.

Set up Lazy

Set up whatever package manager you prefer, the configuration below can be modified to fit, I went with Lazy. The documentation has a starter example for how you can set it up.

Treesitter

Great News! I found a treesitter parser for PowerShell that was updated and functional and not over 5 years old! This is the repo: tree-sitter-powershell

I have a folder for my custom parsers in ~/.config/nvim/tsparsers, this is where I cloned the repo. Then I have a file in my ~/.config/nvim/lua/<pathToMyPluginFiles> called treesitter.lua. Here is how I have it set up:

return {
    'nvim-treesitter/nvim-treesitter',
    built = ':TSUpdate',
    config = function()
        require('nvim-treesitter.configs').setup({

            ensure_installed = {
                "vimdoc", "lua", "bash"
            },

            sync_install = false,

            auto_install = true,

            indent = {
                enable = true
            },

            highlight = {
                enable = true,

                additional_vim_regex_highlighting = false,
            },
        })

        local treesitter_parser_config = require('nvim-treesitter.parsers').get_parser_configs()
        treesitter_parser_config.powershell = {
            install_info = {
                url = "~/.config/nvim/tsparsers/tree-sitter-powershell",
                files = { "src/parser.c", "src/scanner.c" },
                branch = "main",
                generate_requires_npm = false,
                requires_generate_from_grammar = false,
            },
            filetype = "ps1",
        }

    end
}
Enter fullscreen mode Exit fullscreen mode

After sourcing the file, and restarting nvim, I had my syntax highlighting. Please note the path in the ‘url’ value and make sure it matches the path where you have the cloned tree-sitter-powershell repo.

LSP

For the LSP, my configuration is almost the same as ThePrimeagen’s with some changes to the auto-complete behaviour, and the added custom server for PowerShell. PowerShell Editor Services actually have some documentation in their repo that is very helpful, it’s not very detailed but gives enough to get neovim configured. So download a package from the Releases (NOT a clone of the repo, made that mistake instantly before I read the docs). I extracted the Zip into a folder ~/.config/nvim/customLsp, it doesn’t really matter what the folder is as long as you have a record of the path. Then in my lazy plugins I have the lsp.lua file set up as below:

return {
    'neovim/nvim-lspconfig',
    dependencies = {
        "williamboman/mason.nvim",
        "williamboman/mason-lspconfig.nvim",
        "hrsh7th/cmp-nvim-lsp",
        "hrsh7th/cmp-buffer",
        "hrsh7th/cmp-path",
        "hrsh7th/cmp-cmdline",
        "hrsh7th/nvim-cmp",
        "L3MON4D3/LuaSnip",
        "saadparwaiz1/cmp_luasnip",
        "j-hui/fidget.nvim",
        -- "rafamadriz/friendly-snippets",
    },

    config = function()
        local cmp = require('cmp')
        local cmp_lsp = require('cmp_nvim_lsp')
        local capabilities = vim.tbl_deep_extend(
            'force',
            {},
            vim.lsp.protocol.make_client_capabilities(),
            cmp_lsp.default_capabilities())

        require('fidget').setup({})
        require('mason').setup()
        require('mason-lspconfig').setup({
            ensure_installed = {},
            handlers = {
                function(server_name)
                    require('lspconfig')[server_name].setup {
                        capabilities = capabilities
                    }
                end,

                powershell_es = function()
                    local lspconfig = require('lspconfig')
                    lspconfig.powershell_es.setup{
                        bundle_path = '~/.config/nvim/customLsp',
                        on_attach = function(client, bufnr)
                            vim.api.nvim_buf_set_option(bufnr, 'omnifunc', 'v:lua.vim.lsp.omnifunc')
                        end,
                        settings = {powershell = { codeFormatting = { Preset = 'OTBS'} } }
                    }
                end
            }
        })

        -- require("luasnip.loaders.from_vscode").lazy_load()

        local cmp_select = { behavior = cmp.SelectBehavior.Replace }

        cmp.setup({
            snippet = {
                expand = function(args)
                    require('luasnip').lsp_expand(args.body)
                end,
            },
            mapping = cmp.mapping.preset.insert({
                ['<C-p>'] = cmp.mapping(cmp.mapping.select_prev_item(cmp_select), {'i'}),
                ['<C-n>'] = cmp.mapping(cmp.mapping.select_next_item(cmp_select), {'i'}),
                ['<C-y>'] = cmp.mapping.confirm({ select = true }),
                ['<C-Space>'] = cmp.mapping.complete(),
            }),
            sources = cmp.config.sources({
                { name = 'nvim_lsp' },
                { name = 'luasnip' },
            }, {
                { name = 'buffer' },
            })
        })

        vim.diagnostic.config({
            float = {
                focusable = false,
                style = 'minimal',
                border = 'rounded',
                source = 'always',
                header = '',
                prefix = '',
            },
        })
    end
}
Enter fullscreen mode Exit fullscreen mode

Main thing to edit here is the ‘bundle_path’ which contains the path to the extracted PowerShell Editor Services. Give nvim a restart, note that it may take a little while to kick in, but after the first load I find it to be pretty much instant every time I go straight into a PS file.

Snippets

If you would like code snippets (like in VS Code), simply uncomment two lines:

  • "rafamadriz/friendly-snippets" in the dependencies
  • require("luasnip.loaders.from_vscode").lazy_load() under the mason-lspconfig setup.

This will give you the snippets for PowerShell which you can find in the repository for the friendly-snippets repo.

Additional Plugins


TLDR: Read the docs. Always read the docs.

wsl Article's
30 articles in total
Favicon
Update WSL Ubuntu password
Favicon
Building OpenCV 4.10.0 with GUI Support in WSL
Favicon
Video: Install Ubuntu using WSL 2
Favicon
Install Zellij on WSL
Favicon
Work from anywhere with VSCode Remote Tunnels
Favicon
SSL verification error at depth 2 - Zscaler | WSL
Favicon
Accelerate 1-bit LLM Inference with BitNet on WSL2 (Ubuntu)
Favicon
Just start using WSL
Favicon
Change WSL/Docker files to another disk
Favicon
Setup your laravel 11 in windows
Favicon
Install Ubuntu on WSL 2
Favicon
How to Install WSL from PowerShell on Windows 10 and 11
Favicon
WSL in AWS Windows Server 2022 Core instance
Favicon
Docker Installation Log for WSL 2 on Windows
Favicon
Enable WSL shell in GitHub Desktop
Favicon
Installing Ruby using rbenv on your WSL Ubuntu system
Favicon
How to Install Redis on Windows Using WSL2
Favicon
PowerShell Development in Neovim
Favicon
WSL: Gerenciando o disco da distro
Favicon
Docker
Favicon
Share Postgresql from Windows to WSL Linux
Favicon
Add Manjaro into WSL 2
Favicon
Using WSL2 as primary driver for 3 months with Fedora
Favicon
Wsl installation error
Favicon
Install Debian in Different Location -WSL Windows
Favicon
Monitor GPU Usage in WSL debian
Favicon
Dicas e configurações para seu sistema linux
Favicon
Instalando de maneira rápida e eficiente suas ferramentas no WSL. Pt-3
Favicon
Arch install azure cli
Favicon
Melhorando e configurando seu novo Shell linux. Pt-2

Featured ones: