I have neovim 0.8.0 installed. I have neovim/nvim-lspconfig plugin installed. I have installed pyright language server on my system (pip install pyright) I have configured neovim to use the pyright language server.

So now when I open a python file I get some warnings produced by pyright. :LspInfo command confirms that "1 client(s) attached to this buffer" and this client is pyright.

So far so good. Now I start editing some code. For example I write the following function call:

x = get_value_of_x("aaaaaaaaaa", "bbbbbbb", "ccccccc",

As you can see this code is not properly formatted. According to pep8 rules it should be formatted like this:

x = get_value_of_x("aaaaaaaaaa", "bbbbbbb", "ccccccc",

I expected that neovim integrated with language server will automatically indent the code, but somehow it does not happen.

I tried to trigger format explicitly by executing the following command:

:lua vim.lsp.buf.format()

but get following error message: [LSP] Format request failed, no matching language servers.

I tried to install different language server ("jedi-language-server") instead of "pyright" - and the result is approximately the same: both servers function properly (for example "go to definition" functionality works fine) but not auto-formatting is available.

No log messages generated during these formatting attempts in ~/.cache/nvim/lsp.log

How can I configure nvim / lsp servers to properly indent python code?

  • 1
    pyright does not offer formatting. Instead, install another tool to use formatting (I use null-ls + black + an autocmd to format on save) . Here's my config, which I use on MacOS and has links in comments to different wikis
    – Ben
    Commented Aug 2, 2022 at 17:34

6 Answers 6


Here is an example of how to make this work with lspconfig




local fn = vim.fn
local install_path = fn.stdpath("data") .. "/site/pack/packer/start/packer.nvim"
if fn.empty(fn.glob(install_path)) > 0 then
  Packer_Bootstrap = fn.system({

local packer_ok, packer = pcall(require, "packer")
if not packer_ok then

return packer.startup(function()
    requires = {
    config = function()
    use { "jose-elias-alvarez/null-ls.nvim",
    requires = { "nvim-lua/plenary.nvim" },
    config = function()
  if Packer_Bootstrap then


local lspconfig_ok, lspconfig = pcall(require, "lspconfig")
if not lspconfig_ok then

local mason_ok, mason = pcall(require, "mason")
if not mason_ok then

local mason_lspconfig_ok, mason_lspconfig = pcall(require, "mason-lspconfig")
if not mason_lspconfig_ok then

local _lsp = {}
function _lsp.setup()

  mason_lspconfig.setup_handlers {

return _lsp


local null_ls_ok, null_ls = pcall(require, "null-ls")
if not null_ls_ok then

local sources = {
  -- python
    extra_args = { "--line-length=120" }

null_ls.setup({ sources = sources })

Install plugins


Install LSPs

  • Install from the list, use i to install
:MasonInstall black
:MasonInstall pyright
:MasonInstall isort


Open a python file and run


This should report that the servers are setup and running.

Then however you choose to wire up the formatting command.


It took some time to figure out what is happening.

Short answer: looks like LSP servers do not affect nvim's indentation when you press "Enter" button while editing text. I had to install and properly configure 'nvim-treesitter' plugin to make things work.

More detailed answer. To find out what happens when you proceed to next line (push "Enter" button in insert mode or "o" button in normal mode) check value of the indentexpr setting:

:set indentexpr?

In my case it was a vimscript method, I found it in /usr/local/share/nvim/runtime/autoload/python.vim. (To find the location of the function run the following command: verbose function python#GetIndent, if it compains that the function is not found do edit you file and try again). You can check what this function does to calculate the indent level. It was interesting for me to look into this function and play with it a little. Bottomline: it does not try to use lsp.

Installation of different language servers did not affect indentexpr.

It turned out that for a long time I used not standard indentation implemented in my .vimrc/indent/python.vim - I really do not remember where have I got this file from. It was created in 2004 by some guy David Bustos - thanks a lot to him. Autoindentation implemented in this file is much better than standard, but still with some glitches. Lots changed since 2004, so there should be a better way.

Looks like a better way is 'nvim-treesitter' plugin. Very good instructions on plugin configuration can be found in this short tutorial: https://www.youtube.com/watch?v=hkxPa5w3bZ0&list=PLhoH5vyxr6Qq41NFL4GvhFp-WLd5xzIzZ

Example of configuration (via lua script):

local treesitter_ok, treesitter = pcall(require, 'nvim-treesitter.configs')
if treesitter_ok then
    ensure_installed = { 'c', 'lua', 'vim', 'help', 'python', 'go' },
    sync_install = false,                                                                                                 
    auto_install = false,                                                                                                       
    highlight = {                                                                                                 
      enable = false,
    indent = {
      enable = true,

Make sure to run :TSUpdate after or during installation (depends on plugin manager you use).

Make sure that treesitter is enabled for python: :TSInstallInfo

If everything is ok than treesitter is used for indentation:

:set indentexpr?

On-the-fly indentation is indeed better now.

UPDATE: Indentation is still not good. In some cases it's better, but still not good.

  • Thanks, perfect solution, works like a charm! Commented Jun 11, 2023 at 12:54

For range formatting you may have a look at black-macchiato.

Install black-macchiato by running the shell command:

pip install black-macchiato

To format a range of select lines run the vim command:

:'<,'>!python -m macchiato

Or install the pluging smbl64/vim-black-macchiato: vim-black-macchiato

  • 3
    If you're going for this, maybe it is more comfortable to run it as part of formatprg: :set formatprg=python3\ -m\ macchiato and then type gqip to format that paragraph.
    – r_31415
    Commented Jun 3, 2022 at 20:26

You need the efm language server, and the python black formatter. You also need to set up efm like this:

nvim_lsp.efm.setup {               
    on_attach = on_attach,    
    flags = {                                                                                                                                                                                 
      debounce_text_changes = 150,
    init_options = {documentFormatting = true},
    filetypes = {"python"},
    settings = {
        rootMarkers = {".git/"},
        languages = {
            python = {
                {formatCommand = "black --quiet -", formatStdin = true}

Efm is difficult to install. You need Go. I figured it out on my system using these commands:

GO111MODULE=on go get github.com/mattn/efm-langserver@latest    
echo 'export PATH=$PATH:~/go/bin' >> ~/.zshrc 

I would suggest trying null-ls, the configuration is relatively simple and you don't need to change your lspconfig settings at most of the time.

My conf is just a copy/paste from null-ls's wiki(formatting fires automatically when you save the buffer):


local augroup = vim.api.nvim_create_augroup("LspFormatting", {})
local null_ls = require("null-ls")

    on_attach = function(client, bufnr)
        if client.supports_method("textDocument/formatting") then
            vim.api.nvim_clear_autocmds({ group = augroup, buffer = bufnr })
            vim.api.nvim_create_autocmd("BufWritePre", {
                group = augroup,
                buffer = bufnr,
                callback = function()
                    -- on 0.8, you should use vim.lsp.buf.format({ bufnr = bufnr }) instead
                    vim.lsp.buf.format({ bufnr = bufnr })
    sources = {

You could find the original wiki here on null-ls's wiki

The following link is only for demonstrating that I do nothing special about the pyright configuration:


  • 1
    We would like to have as much as possible the full answer within the answer and limit at maximum the exterior link. Could you simplify your configuration, include it into the answer and explain it? Commented Mar 26, 2023 at 5:39
  • Thank you for reply. Actually I also use null-ls. null-ls is configured to use black source for formatting. But that doesn't affect nvim's behavior when I push "Enter" button. Could you check what happens when you open a new python file and manually print the text from my original question?
    – lesnik
    Commented Mar 27, 2023 at 13:16
  • I've included some code directly from one link; I'm not sure how the other link is relevant to null-ls, so I left it in but didn't include the code.
    – D. Ben Knoble
    Commented Mar 29, 2023 at 13:43
  • 1
    @lesnik Oh sorry I don't see you mention pressing "Enter" in the question. In my configuration the formatting fires when you save the buffer. When I open a new python file and manually print the text from your original question, the code is formatted as one line. Commented Mar 29, 2023 at 14:17
  • 1
    @VivianDeSmedt Thank you for your suggestion. I have added some more explanations. But since the code is from wiki and not mine, I think it's better to give a reference. Commented Mar 29, 2023 at 14:20

There are many ways.

Here is one using Coc.Nvim (neoclide/coc.nvim)

Follow the instructions to install Coc.Nvim

Basically (if you are using Plug)

  1. Add the following line to your .vimrc
Plug 'neoclide/coc.nvim' , {'branch': 'release'}
  1. Resource your .vimrc using the vim command:

:so %

  1. Run the vim command:


  1. Restart Neovim

When installed install Pyright support by entering the vim command:

:CocInstall coc-pyright

Add the following line to your .vimrc file to add Format support:

  " Add `:Format` command to format current buffer.
  command! -nargs=0 Format :call CocAction('format')

  " Use CTRL-S for selections ranges.
  " Requires 'textDocument/selectionRange' support of language server.
  nmap <silent> <C-s> <Plug>(coc-range-select)
  xmap <silent> <C-s> <Plug>(coc-range-select)

The :Format command format the entire file.

For that to work you'll need to have Black installed. This can be achieved using the following shell command:

pip install black

If Coc.Nvim fails to find Black you can configure it explicitly by typing the vim command:


The coc-settings.json file will open.

Make sure the following lines (On a Windows machine) are part of the config.

Remark: Coc.Nvim support also range formatting if the corresponding language server support it. It seems that PyRight is not supporting range formatting yet.

    "python.formatting.provider": "black",
    "python.formatting.blackPath": "C:\\Python36_x64\\Scripts\\black.exe",
  • 1
    Thanks for the answer! I have installed Coc.Nvim and coc-pyright extension. How can I use :Format command now? I have even installed black - but still the code is not properly indented.
    – lesnik
    Commented May 3, 2022 at 19:51
  • The vim command :Format should reformat your code but maybe you have a provlem with the installation of black. Can you tell us what is your OS? To verify black is in the path can you run the shell command black? Could you also try to save your file and run the vim command :!black % that should reformat it. Commented May 4, 2022 at 3:25
  • 1
    Operating system is ubuntu linux. Vim command :!black % works - it does re-format the whole file. But :Format does not: "E492: Not an editor command: Format". And frankly speaking the re-formatting of the whole file with black is not what I need. There could be several valid ways to format a function call and black re-formats even portions of code which are already correctly formatted :(
    – lesnik
    Commented May 4, 2022 at 7:38
  • 1
    Is the answer essentially "pyright and other python LSPs do not include formatting; use black for that"?
    – D. Ben Knoble
    Commented May 4, 2022 at 14:01
  • Coc.Nvim bring support for file formatting (using black) it also bring range formatting if the corresponding LSP is supporting it. It seems that PyRight doesn't support it yet. Commented May 4, 2022 at 17:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.