Skip to content

Commit

Permalink
Version 2.2.0
Browse files Browse the repository at this point in the history
* Sequentially format with all attached LSP server
* Add special `order` format option

resolve #19
  • Loading branch information
lukas-reineke committed Mar 4, 2022
1 parent 9ce61a5 commit 555695b
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 18 deletions.
27 changes: 22 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ LSP-format.nvim is a wrapper around Neovims native LSP formatting.

It does

1. Asynchronously formats on save
2. Adds commands to disable formatting (globally or per filetype)
3. Makes it easier to send format options to the LSP
1. Asynchronously formatting on save
2. Sequentially formatting with all attached LSP server
3. Add commands for disabling formatting (globally or per filetype)
4. Makes it easier to send format options to the LSP

It does not

Expand Down Expand Up @@ -75,14 +76,18 @@ You can check if something is listening on buffer write events with `:autocmd Bu

Because formatting is async now, you can't save and quit in the same command. The formatting results will not get back
in time and Neovim will close without applying the changes.
In this case you need to use `vim.lsp.buf.formatting_sync()`
In this case you need to use `vim.lsp.buf.formatting_seq_sync()`

Add this abbreviation into your dotfiles to do the right thing when doing `:wq`

```lua
vim.cmd [[cabbrev wq execute "lua vim.lsp.buf.formatting_sync()" <bar> wq]]
vim.cmd [[cabbrev wq execute "lua vim.lsp.buf.formatting_seq_sync()" <bar> wq]]
```

#### `order` format option

`order` is a special format option that determines the order formatting is requested from the LSP server.

## FAQ

### How is it different to `autocmd BufWritePre <buffer> lua vim.lsp.buf.formatting_sync()`?
Expand Down Expand Up @@ -123,3 +128,15 @@ require "lspconfig".efm.setup {
Now Typescript gets formatted with 4 and YAML with 2 spaces by default.
And you can run `:Format tab_width=8` to overwrite the setting and format with 8 spaces.

### How do I exclude an LSP server from formatting?

To exclude a server, you have to set the clients `resolved_capabilities.document_formatting` to false.
Do this in the attach function, before you call `require "lsp-format".on_attach(client)`

```lua
local on_attach = function(client)
client.resolved_capabilities.document_formatting = false
require "lsp-format".on_attach(client)
end
require "lspconfig".gopls.setup { on_attach = on_attach }
```
25 changes: 19 additions & 6 deletions doc/format.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@


Author: Lukas Reineke <[email protected]>
Version: 2.0.1
Version: 2.1.0

==============================================================================
CONTENTS *lsp-format*
Expand All @@ -21,8 +21,9 @@ LSP-format.nvim is a wrapper around Neovims native LSP formatting.
It does

1. Asynchronously formatting on save
2. Add commands for disabling formatting (globally or per filetype)
3. Makes it easier to send format options to the LSP
2. Sequentially formatting with all attached LSP server
3. Add commands for disabling formatting (globally or per filetype)
4. Makes it easier to send format options to the LSP

It does not

Expand All @@ -36,11 +37,19 @@ function to each LSP that should use it.

The setup functions takes one optional argument that maps |filetypes| to
format options.

`order` is a special format option, a list of client names. Formatting is
requested from clients in the following order: first all clients that are not
in the `order` list, then the remaining clients in the order as they occur in
the `order` list. (same logic as |vim.lsp.buf.formatting_seq_sync()|)
>
require "lsp-format".setup {
lua = {
indent_width = 4,
},
golang = {
order = { "gopls", "efm" }
}
}
==============================================================================
Expand All @@ -50,10 +59,10 @@ format options.

Formats and saves the current buffer.
Optional takes format options separated by space.
Format options can be a key value pair separated by `=` `hello=world`, or
just a value `foobar`
Format options can be a key value pair separated by `=` `hello=world`,
just a value `foobar`, or a comma separated list for the order `efm,gopls`
>
:Format indent_width=2 no_call_parentheses
:Format indent_width=2 no_call_parentheses order=efm,gopls
------------------------------------------------------------------------------
:FormatDisable [{filetype}] *FormatDisable*
Expand All @@ -77,6 +86,10 @@ format options.
==============================================================================
4. CHANGELOG *lsp-format-changelog*

2.1.0
* Sequentially format with all attached LSP server
* Add special `order` format option

2.0.1
* Add notes to README

Expand Down
56 changes: 49 additions & 7 deletions lua/lsp-format/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ local M = {
format_options = {},
disabled = false,
disabled_filetypes = {},
queue = {},
}

M.setup = function(format_options)
Expand Down Expand Up @@ -31,20 +32,61 @@ M.setup = function(format_options)
vim.b.format_saving = true
vim.cmd [[update]]
vim.b.format_saving = false
M._next()
end
end
end
end

M.format = function(format_options_string)
local format_options = {}
for _, option in ipairs(vim.split(format_options_string or "", " ")) do
local key, value = unpack(vim.split(option, "="))
format_options[key] = value or true
end
if not vim.b.format_saving and not M.disabled and not M.disabled_filetypes[vim.bo.filetype] then
vim.b.format_changedtick = vim.b.changedtick
vim.lsp.buf.formatting((format_options_string and format_options) or M.format_options[vim.bo.filetype] or {})
local bufnr = vim.api.nvim_get_current_buf()
local clients = vim.tbl_values(vim.lsp.buf_get_clients())
for i, client in pairs(clients) do
if not client.resolved_capabilities.document_formatting then
table.remove(clients, i)
end
end

local format_options = M.format_options[vim.bo.filetype] or {}
for _, option in ipairs(vim.split(format_options_string or "", " ")) do
local key, value = unpack(vim.split(option, "="))
if key == "order" then
value = vim.split(value, ",")
end
format_options[key] = value or true
end

for _, client_name in pairs(format_options.order or {}) do
for i, client in pairs(clients) do
if client.name == client_name then
table.insert(clients, table.remove(clients, i))
break
end
end
end

table.insert(M.queue, { bufnr = bufnr, clients = clients, format_options = format_options })

M._next()
end
end

M._format = function(bufnr, client, format_options)
vim.b.format_changedtick = vim.b.changedtick
local params = vim.lsp.util.make_formatting_params(format_options)
client.request("textDocument/formatting", params, nil, bufnr)
end

M._next = function()
local next = M.queue[1]
if not next or #next.clients == 0 then
return
end
local next_client = table.remove(next.clients, 1)
M._format(next.bufnr, next_client, next.format_options)
if #next.clients == 0 then
table.remove(M.queue, 1)
end
end

Expand Down

0 comments on commit 555695b

Please sign in to comment.