Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve filesystem management #409

Merged
merged 14 commits into from
Apr 18, 2024
47 changes: 25 additions & 22 deletions demo/src/features/output.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,31 @@
import { ExtensionHostKind, registerExtension } from 'vscode/extensions'
import { useHtmlFileSystemProvider } from '../setup.common'

const { getApi } = registerExtension({
name: 'outputDemo',
publisher: 'codingame',
version: '1.0.0',
engines: {
vscode: '*'
}
}, ExtensionHostKind.LocalProcess)
if (!useHtmlFileSystemProvider) {
const { getApi } = registerExtension({
name: 'outputDemo',
publisher: 'codingame',
version: '1.0.0',
engines: {
vscode: '*'
}
}, ExtensionHostKind.LocalProcess)

void getApi().then(async vscode => {
const fakeOutputChannel = vscode.window.createOutputChannel('Fake output')
const anotherFakeOutputChannel = vscode.window.createOutputChannel('Your code', 'javascript')
void getApi().then(async vscode => {
const fakeOutputChannel = vscode.window.createOutputChannel('Fake output')
const anotherFakeOutputChannel = vscode.window.createOutputChannel('Your code', 'javascript')

fakeOutputChannel.append('Here\'s some fake output\n')
setInterval(() => {
fakeOutputChannel.append('Hello world\n')
}, 1000)
fakeOutputChannel.append('Here\'s some fake output\n')
setInterval(() => {
fakeOutputChannel.append('Hello world\n')
}, 1000)

const mainDocument = await vscode.workspace.openTextDocument(vscode.Uri.file('/tmp/test.js'))
anotherFakeOutputChannel.replace(mainDocument.getText())
vscode.workspace.onDidChangeTextDocument((e) => {
if (e.document === mainDocument && e.contentChanges.length > 0) {
anotherFakeOutputChannel.replace(e.document.getText())
}
const mainDocument = await vscode.workspace.openTextDocument(vscode.Uri.file('/tmp/test.js'))
anotherFakeOutputChannel.replace(mainDocument.getText())
vscode.workspace.onDidChangeTextDocument((e) => {
if (e.document === mainDocument && e.contentChanges.length > 0) {
anotherFakeOutputChannel.replace(e.document.getText())
}
})
})
})
}
4 changes: 2 additions & 2 deletions demo/src/features/scm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ const { getApi } = registerExtension({
})

void getApi().then(async vscode => {
const workspaceFolder = vscode.workspace.workspaceFolders![0]
const workspaceFolder = vscode.workspace.workspaceFolders?.[0]
if (workspaceFolder == null) {
throw new Error('No workspace folder')
return
}

vscode.commands.registerCommand('scm-demo.click-file', async (uri: Uri) => {
Expand Down
71 changes: 37 additions & 34 deletions demo/src/features/search.ts
Original file line number Diff line number Diff line change
@@ -1,41 +1,44 @@
import { ExtensionHostKind, registerExtension } from 'vscode/extensions'
import * as monaco from 'monaco-editor'
import { useHtmlFileSystemProvider } from '../setup.common'

const { getApi } = registerExtension({
name: 'searchProvider',
publisher: 'codingame',
version: '1.0.0',
engines: {
vscode: '*'
},
enabledApiProposals: ['fileSearchProvider', 'textSearchProvider']
}, ExtensionHostKind.LocalProcess, {
system: true // to be able to use api proposals
})

void getApi().then(async api => {
api.workspace.registerFileSearchProvider('file', {
async provideFileSearchResults () {
return monaco.editor.getModels().map(model => model.uri).filter(uri => uri.scheme === 'file')
}
if (!useHtmlFileSystemProvider) {
const { getApi } = registerExtension({
name: 'searchProvider',
publisher: 'codingame',
version: '1.0.0',
engines: {
vscode: '*'
},
enabledApiProposals: ['fileSearchProvider', 'textSearchProvider']
}, ExtensionHostKind.LocalProcess, {
system: true // to be able to use api proposals
})
api.workspace.registerTextSearchProvider('file', {
async provideTextSearchResults (query, _, progress) {
for (const model of monaco.editor.getModels()) {
const matches = model.findMatches(query.pattern, false, query.isRegExp ?? false, query.isCaseSensitive ?? false, query.isWordMatch ?? false ? ' ' : null, true)
if (matches.length > 0) {
const ranges = matches.map(match => new api.Range(match.range.startLineNumber, match.range.startColumn, match.range.endLineNumber, match.range.endColumn))
progress.report({
uri: model.uri,
ranges,
preview: {
text: model.getValue(),
matches: ranges
}
})

void getApi().then(async api => {
api.workspace.registerFileSearchProvider('file', {
async provideFileSearchResults () {
return monaco.editor.getModels().map(model => model.uri).filter(uri => uri.scheme === 'file')
}
})
api.workspace.registerTextSearchProvider('file', {
async provideTextSearchResults (query, _, progress) {
for (const model of monaco.editor.getModels()) {
const matches = model.findMatches(query.pattern, false, query.isRegExp ?? false, query.isCaseSensitive ?? false, query.isWordMatch ?? false ? ' ' : null, true)
if (matches.length > 0) {
const ranges = matches.map(match => new api.Range(match.range.startLineNumber, match.range.startColumn, match.range.endLineNumber, match.range.endColumn))
progress.report({
uri: model.uri,
ranges,
preview: {
text: model.getValue(),
matches: ranges
}
})
}
}
return {}
}
return {}
}
})
})
})
}
52 changes: 25 additions & 27 deletions demo/src/main.common.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import './style.css'
import * as monaco from 'monaco-editor'
import { registerFileSystemOverlay, HTMLFileSystemProvider } from '@codingame/monaco-vscode-files-service-override'
import { ILogService, StandaloneServices } from 'vscode/services'
import './setup.common'
import { ExtensionHostKind, registerExtension } from 'vscode/extensions'
import { useHtmlFileSystemProvider } from './setup.common'
import './features/output'
import './features/debugger'
import './features/search'
Expand Down Expand Up @@ -53,7 +52,6 @@ import '@codingame/monaco-vscode-markdown-math-default-extension'
import '@codingame/monaco-vscode-npm-default-extension'
import '@codingame/monaco-vscode-media-preview-default-extension'
import '@codingame/monaco-vscode-ipynb-default-extension'
import { ExtensionHostKind, registerExtension } from 'vscode/extensions'

const { getApi } = registerExtension({
name: 'demo-main',
Expand All @@ -65,20 +63,22 @@ const { getApi } = registerExtension({
}, ExtensionHostKind.LocalProcess)

void getApi().then(async vscode => {
const mainModelUri = vscode.Uri.file('/tmp/test.js')
await Promise.all([
vscode.workspace.openTextDocument(mainModelUri),
vscode.workspace.openTextDocument(monaco.Uri.file('/tmp/test_readonly.js')) // open the file so vscode sees it's locked
])
if (!useHtmlFileSystemProvider) {
const mainModelUri = vscode.Uri.file('/tmp/test.js')
await Promise.all([
vscode.workspace.openTextDocument(mainModelUri),
vscode.workspace.openTextDocument(monaco.Uri.file('/tmp/test_readonly.js')) // open the file so vscode sees it's locked
])

const diagnostics = vscode.languages.createDiagnosticCollection('demo')
diagnostics.set(mainModelUri, [{
range: new vscode.Range(2, 9, 2, 12),
severity: vscode.DiagnosticSeverity.Error,
message: 'This is not a real error, just a demo, don\'t worry',
source: 'Demo',
code: 42
}])
const diagnostics = vscode.languages.createDiagnosticCollection('demo')
diagnostics.set(mainModelUri, [{
range: new vscode.Range(2, 9, 2, 12),
severity: vscode.DiagnosticSeverity.Error,
message: 'This is not a real error, just a demo, don\'t worry',
source: 'Demo',
code: 42
}])
}

document.querySelector('#toggleFullWorkbench')!.addEventListener('click', async () => {
const url = new URL(window.location.href)
Expand All @@ -96,15 +96,13 @@ void getApi().then(async vscode => {
window.location.href = url.toString()
})

document.querySelector('#filesystem')!.addEventListener('click', async () => {
const dirHandle = await window.showDirectoryPicker()

const htmlFileSystemProvider = new HTMLFileSystemProvider(undefined, 'unused', StandaloneServices.get(ILogService))
await htmlFileSystemProvider.registerDirectoryHandle(dirHandle)
registerFileSystemOverlay(1, htmlFileSystemProvider)

vscode.workspace.updateWorkspaceFolders(0, 0, {
uri: vscode.Uri.file(dirHandle.name)
})
document.querySelector('#toggleHTMLFileSystemProvider')!.addEventListener('click', async () => {
const url = new URL(window.location.href)
if (url.searchParams.has('htmlFileSystemProvider')) {
url.searchParams.delete('htmlFileSystemProvider')
} else {
url.searchParams.set('htmlFileSystemProvider', 'true')
}
window.location.href = url.toString()
})
})
Loading