Skip to content

Commit 33fe055

Browse files
committed
Add initialization option to respect editor's formatting options
1 parent 1df14cc commit 33fe055

File tree

3 files changed

+50
-7
lines changed

3 files changed

+50
-7
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Added
11+
12+
- The language server has an initialization option called `respect_editor_formatting_options`.
13+
If it's true, the formatting handler will override the configurations `indent-width` and `indent-type` with values from [FormattingOptions](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#formattingOptions)
14+
1015
### Changed
1116

1217
- In language server mode, compute the difference between the unformatted and formatted document and only respond with the changes.

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,8 @@ StyLua can run as a language server, connecting with language clients that follo
253253
It will then respond to `textDocument/formatting` and `textDocument/rangeFormatting` requests.
254254
Formatting is only performed on files with a `lua` or `luau` language ID.
255255

256+
If the initialization option `respect_editor_formatting_options` is set to `true`, the formatting handler will override the configurations `indent-width` and `indent-type` with values from [FormattingOptions](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#formattingOptions).
257+
256258
You can start the language server by running:
257259

258260
```sh

src/cli/lsp.rs

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,13 @@ use lsp_server::{Connection, ErrorCode, Message, Response};
44
use lsp_textdocument::{FullTextDocument, TextDocuments};
55
use lsp_types::{
66
request::{Formatting, RangeFormatting, Request},
7-
DocumentFormattingParams, DocumentRangeFormattingParams, InitializeResult, OneOf, Range,
8-
ServerCapabilities, ServerInfo, TextDocumentSyncCapability, TextDocumentSyncKind, TextEdit,
9-
Uri,
7+
DocumentFormattingParams, DocumentRangeFormattingParams, FormattingOptions, InitializeParams,
8+
InitializeResult, OneOf, Range, ServerCapabilities, ServerInfo, TextDocumentSyncCapability,
9+
TextDocumentSyncKind, TextEdit, Uri,
1010
};
11+
use serde::Deserialize;
1112
use similar::{DiffOp, TextDiff};
12-
use stylua_lib::{format_code, OutputVerification};
13+
use stylua_lib::{format_code, IndentType, OutputVerification};
1314

1415
use crate::{config::ConfigResolver, opt};
1516

@@ -64,17 +65,30 @@ fn handle_formatting(
6465
document: &FullTextDocument,
6566
range: Option<stylua_lib::Range>,
6667
config_resolver: &mut ConfigResolver,
68+
formatting_options: Option<&FormattingOptions>,
6769
) -> Option<Vec<TextEdit>> {
6870
if document.language_id() != "lua" && document.language_id() != "luau" {
6971
return None;
7072
}
7173

7274
let contents = document.get_content(None);
7375

74-
let config = config_resolver
76+
let mut config = config_resolver
7577
.load_configuration(uri.path().as_str().as_ref())
7678
.unwrap_or_default();
7779

80+
if let Some(formatting_options) = formatting_options {
81+
config.indent_width = formatting_options
82+
.tab_size
83+
.try_into()
84+
.expect("u32 fits into usize");
85+
config.indent_type = if formatting_options.insert_spaces {
86+
IndentType::Spaces
87+
} else {
88+
IndentType::Tabs
89+
};
90+
}
91+
7892
let formatted_contents = format_code(contents, config, range, OutputVerification::None).ok()?;
7993

8094
let operations =
@@ -94,6 +108,7 @@ fn handle_request(
94108
request: lsp_server::Request,
95109
documents: &TextDocuments,
96110
config_resolver: &mut ConfigResolver,
111+
respect_editor_formatting_options: bool,
97112
) -> Response {
98113
match request.method.as_str() {
99114
Formatting::METHOD => {
@@ -115,6 +130,7 @@ fn handle_request(
115130
document,
116131
None,
117132
config_resolver,
133+
respect_editor_formatting_options.then_some(&params.options),
118134
) {
119135
Some(edits) => Response::new_ok(request.id, edits),
120136
None => Response::new_ok(request.id, serde_json::Value::Null),
@@ -151,6 +167,7 @@ fn handle_request(
151167
document,
152168
Some(range),
153169
config_resolver,
170+
respect_editor_formatting_options.then_some(&params.options),
154171
) {
155172
Some(edits) => Response::new_ok(request.id, edits),
156173
None => Response::new_ok(request.id, serde_json::Value::Null),
@@ -171,6 +188,12 @@ fn handle_request(
171188
}
172189
}
173190

191+
#[derive(Deserialize, Default)]
192+
#[serde(default)]
193+
struct InitializationOptions {
194+
respect_editor_formatting_options: Option<bool>,
195+
}
196+
174197
fn main_loop(connection: Connection, config_resolver: &mut ConfigResolver) -> anyhow::Result<()> {
175198
let initialize_result = InitializeResult {
176199
capabilities: ServerCapabilities {
@@ -187,7 +210,15 @@ fn main_loop(connection: Connection, config_resolver: &mut ConfigResolver) -> an
187210
}),
188211
};
189212

190-
let (id, _) = connection.initialize_start()?;
213+
let (id, initialize_params) = connection.initialize_start()?;
214+
215+
let initialize_params = serde_json::from_value::<InitializeParams>(initialize_params)?;
216+
let respect_editor_formatting_options = initialize_params
217+
.initialization_options
218+
.and_then(|opt| serde_json::from_value::<InitializationOptions>(opt).ok())
219+
.and_then(|opt| opt.respect_editor_formatting_options)
220+
.unwrap_or_default();
221+
191222
connection.initialize_finish(id, serde_json::to_value(initialize_result)?)?;
192223

193224
let mut documents = TextDocuments::new();
@@ -198,7 +229,12 @@ fn main_loop(connection: Connection, config_resolver: &mut ConfigResolver) -> an
198229
break;
199230
}
200231

201-
let response = handle_request(req, &documents, config_resolver);
232+
let response = handle_request(
233+
req,
234+
&documents,
235+
config_resolver,
236+
respect_editor_formatting_options,
237+
);
202238
connection.sender.send(Message::Response(response))?
203239
}
204240
Message::Response(_) => {}

0 commit comments

Comments
 (0)