Skip to content

Commit 283b781

Browse files
committed
feat(workspace): support workspace.removeEmptyWorkspaceFolder
Closes #5120
1 parent 6044d1a commit 283b781

File tree

8 files changed

+67
-2
lines changed

8 files changed

+67
-2
lines changed

data/schema.json

+6
Original file line numberDiff line numberDiff line change
@@ -2474,6 +2474,12 @@
24742474
"scope": "application",
24752475
"description": "Use current working directory as workspace folder when no root patterns resolved."
24762476
},
2477+
"workspace.removeEmptyWorkspaceFolder": {
2478+
"type": "boolean",
2479+
"default": false,
2480+
"scope": "application",
2481+
"description": "Automatically remove the workspace folder when no buffer associated with it."
2482+
},
24772483
"languageserver": {
24782484
"type": "object",
24792485
"default": {},

doc/coc-config.txt

+7
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,13 @@ WORKSPACE
104104

105105
Scope: `application`, default: `true`
106106

107+
"workspace.removeEmptyWorkspaceFolder" *coc-config-workspace-removeEmptyWorkspaceFolder*
108+
109+
Automatically remove the workspace folder when no buffer associated
110+
with it.
111+
112+
Scope: `application`, default: `false`
113+
107114
------------------------------------------------------------------------------
108115
FILESYSTEMWATCH *coc-config-fileSystemWatch*
109116

doc/coc.txt

+16
Original file line numberDiff line numberDiff line change
@@ -2530,6 +2530,11 @@ Acceptable {action} names for |CocAction()| and |CocActionAsync()|.
25302530
Add {folder} to workspace folders, {folder} should be exists directory
25312531
on file system.
25322532

2533+
"removeWorkspaceFolder" {folder} *CocAction('removeWorkspaceFolder')*
2534+
2535+
Remove workspace fold {folder}, {folder} should be exists directory on
2536+
file system.
2537+
25332538
"ensureDocument" [{bufnr}] *CocAction('ensureDocument')*
25342539

25352540
Ensure current or specified document is attached to coc.nvim
@@ -3014,6 +3019,17 @@ Acceptable {action} names for |CocAction()| and |CocActionAsync()|.
30143019
position.
30153020
{forward} select backward when it's falsy value.
30163021

3022+
"sendRequest" {id} {method} [{params}] *CocAction('sendRequest')*
3023+
3024+
Send LSP request with {method} and {params} to the language server of
3025+
{id} (check the id by `:CocList services`).
3026+
Checkout the LSP specification at
3027+
https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/
3028+
3029+
"sendNotification" {id} {method} [{params}] *CocAction('sendNotification')*
3030+
3031+
Send LSP notification to language server with {id}.
3032+
30173033
--------------------------------------------------------------------------------
30183034
COMMANDS *coc-commands*
30193035

src/__tests__/core/keymaps.test.ts

+1
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ describe('registerLocalKeymap', () => {
149149
let called = false
150150
let disposable = keymaps.registerLocalKeymap(bufnr, 'n', 'n', () => {
151151
called = true
152+
return ''
152153
}, true)
153154
let res = await nvim.exec('nmap n', true)
154155
await nvim.input('n')

src/__tests__/core/workspaceFolder.test.ts

+14
Original file line numberDiff line numberDiff line change
@@ -312,4 +312,18 @@ describe('WorkspaceFolderController', () => {
312312
expect(res).toBe(false)
313313
})
314314
})
315+
316+
describe('onDocumentDetach()', () => {
317+
it('should check uris', async () => {
318+
updateConfiguration('workspace.removeEmptyWorkspaceFolder', true, false)
319+
let folder = os.tmpdir()
320+
workspaceFolder.addWorkspaceFolder(folder, false)
321+
workspaceFolder.onDocumentDetach([URI.parse('untitled:/1'), URI.parse('file:///foo/bar')])
322+
expect(workspaceFolder.workspaceFolders.length).toBe(0)
323+
workspaceFolder.addWorkspaceFolder(folder, false)
324+
workspaceFolder.onDocumentDetach([URI.parse('untitled:/1'), URI.file(path.join(os.tmpdir(), 'foo'))])
325+
expect(workspaceFolder.workspaceFolders.length).toBe(1)
326+
})
327+
328+
})
315329
})

src/core/documents.ts

+2
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,8 @@ export default class Documents implements Disposable {
449449
this._onDidCloseDocument.fire(doc.textDocument)
450450
this.buffers.delete(bufnr)
451451
doc.detach()
452+
const uris = this.textDocuments.map(o => URI.parse(o.uri))
453+
this.workspaceFolder.onDocumentDetach(uris)
452454
}
453455

454456
private async onBufWritePost(bufnr: number, changedtick: number): Promise<void> {

src/core/keymaps.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ const logger = createLogger('core-keymaps')
99

1010
export type MapMode = 'n' | 'i' | 'v' | 'x' | 's' | 'o' | '!'
1111
export type LocalMode = 'n' | 'i' | 'v' | 's' | 'x'
12-
export type KeymapCallback = () => Promise<string> | string
12+
export type KeymapCallback = () => Promise<string> | string | void | Promise<void>
1313

1414
export function getKeymapModifier(mode: MapMode): string {
1515
if (mode == 'n' || mode == 'o' || mode == 'x' || mode == 'v') return '<C-U>'
@@ -39,7 +39,8 @@ export default class Keymaps {
3939
let [fn, repeat] = keymap
4040
let res = await Promise.resolve(fn())
4141
if (repeat) await this.nvim.command(`silent! call repeat#set("\\<Plug>(coc-${key})", -1)`)
42-
return res ?? defaultReturn
42+
if (res == null) return defaultReturn
43+
return res as string
4344
}
4445

4546
/**

src/core/workspaceFolder.ts

+18
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,24 @@ export default class WorkspaceFolderController {
218218
})
219219
}
220220

221+
public onDocumentDetach(uris: URI[]): void {
222+
let shouldCheck = this.configurations.initialConfiguration.get('workspace.removeEmptyWorkspaceFolder', false)
223+
if (!shouldCheck) return
224+
let filepaths: string[] = []
225+
for (const uri of uris) {
226+
if (uri.scheme === 'file') {
227+
filepaths.push(uri.fsPath)
228+
}
229+
}
230+
for (const item of this.workspaceFolders) {
231+
const folder = URI.parse(item.uri).fsPath
232+
if (!filepaths.some(f => isParentFolder(folder, f))) {
233+
this.removeWorkspaceFolder(folder)
234+
return
235+
}
236+
}
237+
}
238+
221239
public getRootPatterns(document: Document, patternType: PatternType): ReadonlyArray<string> {
222240
if (patternType == PatternType.Buffer) return document.getVar('root_patterns', []) || []
223241
if (patternType == PatternType.LanguageServer) return this.getServerRootPatterns(document.languageId)

0 commit comments

Comments
 (0)