Skip to content

Commit 12db671

Browse files
committed
Respect editor config for tab size when formatting
If the editor config is set to insert spaces instead of tabs, shfmt will respect that choice (including the number of spaces to insert).
1 parent e1c0a2a commit 12db671

File tree

3 files changed

+111
-8
lines changed

3 files changed

+111
-8
lines changed

server/src/server.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -833,7 +833,7 @@ export default class BashServer {
833833
return null
834834
}
835835

836-
return await this.formatter.format(document)
836+
return await this.formatter.format(document, params.options)
837837
} catch (err) {
838838
logger.error(`Error while formatting: ${err}`)
839839
}

server/src/shfmt/__tests__/index.test.ts

Lines changed: 94 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { FormattingOptions } from 'vscode-languageserver/node'
12
import { TextDocument } from 'vscode-languageserver-textdocument'
23

34
import { FIXTURE_DOCUMENT, FIXTURE_FOLDER } from '../../../../testing/fixtures'
@@ -17,14 +18,16 @@ function textToDoc(txt: string) {
1718
async function getFormattingResult({
1819
document,
1920
executablePath = 'shfmt',
21+
formatOptions,
2022
}: {
2123
document: TextDocument
2224
executablePath?: string
25+
formatOptions?: FormattingOptions
2326
}): Promise<[Awaited<ReturnType<Formatter['format']>>, Formatter]> {
2427
const formatter = new Formatter({
2528
executablePath,
2629
})
27-
const result = await formatter.format(document)
30+
const result = await formatter.format(document, formatOptions)
2831
return [result, formatter]
2932
}
3033

@@ -90,4 +93,94 @@ describe('formatter', () => {
9093
]
9194
`)
9295
})
96+
97+
it('should format using tabs when insertSpaces is false', async () => {
98+
const [result] = await getFormattingResult({
99+
document: FIXTURE_DOCUMENT.SHFMT,
100+
formatOptions: { tabSize: 4, insertSpaces: false },
101+
})
102+
expect(result).toMatchInlineSnapshot(`
103+
[
104+
{
105+
"newText": "#!/bin/bash
106+
set -ueo pipefail
107+
108+
if [ -z "$arg" ]; then
109+
echo indent
110+
fi
111+
112+
echo binary &&
113+
echo next line
114+
115+
case "$arg" in
116+
a)
117+
echo case indent
118+
;;
119+
esac
120+
121+
echo space redirects >/dev/null
122+
123+
function next() {
124+
echo line
125+
}
126+
",
127+
"range": {
128+
"end": {
129+
"character": 2147483647,
130+
"line": 2147483647,
131+
},
132+
"start": {
133+
"character": 0,
134+
"line": 0,
135+
},
136+
},
137+
},
138+
]
139+
`)
140+
})
141+
142+
it('should format using spaces when insertSpaces is true', async () => {
143+
const [result] = await getFormattingResult({
144+
document: FIXTURE_DOCUMENT.SHFMT,
145+
formatOptions: { tabSize: 3, insertSpaces: true },
146+
})
147+
expect(result).toMatchInlineSnapshot(`
148+
[
149+
{
150+
"newText": "#!/bin/bash
151+
set -ueo pipefail
152+
153+
if [ -z "$arg" ]; then
154+
echo indent
155+
fi
156+
157+
echo binary &&
158+
echo next line
159+
160+
case "$arg" in
161+
a)
162+
echo case indent
163+
;;
164+
esac
165+
166+
echo space redirects >/dev/null
167+
168+
function next() {
169+
echo line
170+
}
171+
",
172+
"range": {
173+
"end": {
174+
"character": 2147483647,
175+
"line": 2147483647,
176+
},
177+
"start": {
178+
"character": 0,
179+
"line": 0,
180+
},
181+
},
182+
},
183+
]
184+
`)
185+
})
93186
})

server/src/shfmt/index.ts

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,24 @@ export class Formatter {
2424
return this._canFormat
2525
}
2626

27-
public async format(document: TextDocument): Promise<TextEdit[]> {
27+
public async format(
28+
document: TextDocument,
29+
formatOptions?: LSP.FormattingOptions | null,
30+
): Promise<TextEdit[]> {
2831
if (!this._canFormat) {
2932
return []
3033
}
3134

32-
return this.executeFormat(document)
35+
return this.executeFormat(document, formatOptions)
3336
}
3437

35-
private async executeFormat(document: TextDocument): Promise<TextEdit[]> {
38+
private async executeFormat(
39+
document: TextDocument,
40+
formatOptions?: LSP.FormattingOptions | null,
41+
): Promise<TextEdit[]> {
3642
const documentText = document.getText()
3743

38-
const result = await this.runShfmt(documentText)
44+
const result = await this.runShfmt(documentText, formatOptions)
3945

4046
if (!this._canFormat) {
4147
return []
@@ -52,8 +58,12 @@ export class Formatter {
5258
]
5359
}
5460

55-
private async runShfmt(documentText: string): Promise<string> {
56-
const args: string[] = []
61+
private async runShfmt(
62+
documentText: string,
63+
formatOptions?: LSP.FormattingOptions | null,
64+
): Promise<string> {
65+
const indentation: number = formatOptions?.insertSpaces ? formatOptions.tabSize : 0
66+
const args: string[] = [`--indent=${indentation}`]
5767

5868
logger.debug(`Shfmt: running "${this.executablePath} ${args.join(' ')}"`)
5969

0 commit comments

Comments
 (0)