Skip to content

Commit fc2e6e8

Browse files
committed
Finish up library management
1 parent e4e7afd commit fc2e6e8

3 files changed

Lines changed: 64 additions & 13 deletions

File tree

commands.ts

Lines changed: 61 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,17 @@
11
import { fetchServerRefInfo, gitClone, RefEntry } from '$gitops'
2-
import { type ExtensionContext, window, workspace, Uri, FileType, QuickPickItem, QuickPickItemKind, env, UIKind, ProgressLocation, FileSystem } from 'vscode'
2+
import {
3+
type ExtensionContext,
4+
FileType,
5+
ProgressLocation,
6+
QuickPickItem,
7+
QuickPickItemKind,
8+
UIKind,
9+
Uri,
10+
commands,
11+
env,
12+
window,
13+
workspace,
14+
} from 'vscode'
315

416
interface LibraryDescriptor {
517
name: string
@@ -30,6 +42,7 @@ interface InstalledLibrary {
3042
name: string
3143
version: string | null
3244
folderName: string
45+
folderUri: Uri
3346
libFileName: string
3447
}
3548

@@ -57,11 +70,46 @@ const parseLibName = (text: string): [string, string[]] => {
5770
return [text, []]
5871
}
5972

60-
function exists(uri: Uri) {
61-
return workspace.fs.stat(uri).then(() => true, err => {
62-
if (err.code === 'FileNotFound') return false
63-
throw err
73+
async function showActionPicker(item: InstalledLibraryQuickPickItem) {
74+
if (!('data' in item) || !item.resourceUri) return
75+
const uriToLibFolder = item.data.folderUri
76+
const uriToLibFile = item.resourceUri
77+
78+
const choice = await window.showQuickPick([
79+
{
80+
iconPath: { id: 'file-code' },
81+
label: 'Open library file',
82+
callback: () => window.showTextDocument(uriToLibFile),
83+
},
84+
...(env.uiKind === UIKind.Desktop ? [{
85+
iconPath: { id: 'repo' },
86+
label: 'Mount as a git repository',
87+
// this will open the source control panel so showing no message should be fine
88+
callback: async () => {
89+
await commands.executeCommand('git.openRepository', uriToLibFolder.fsPath)
90+
await commands.executeCommand('workbench.scm.repositories.focus')
91+
},
92+
}] : []),
93+
{
94+
iconPath: { id: 'trash' },
95+
label: 'Delete the library',
96+
callback: async () => {
97+
const sure = await window.showWarningMessage(
98+
`Are you sure you want to delete the library located at "${uriToLibFolder.toString()}"?`,
99+
{ modal: true },
100+
{ title: 'Yes' },
101+
{ title: 'No', isCloseAffordance: true })
102+
if (sure?.title === 'Yes') {
103+
await workspace.fs.delete(uriToLibFile, { useTrash: true })
104+
window.showInformationMessage(`Deleted "${uriToLibFolder.toString()}"`)
105+
}
106+
},
107+
},
108+
], {
109+
placeHolder: `Choose the action to do with "${item.data.folderName}"...`,
64110
})
111+
112+
await choice?.callback()
65113
}
66114

67115
async function pickAndInstallFromLibraryCatalog(context: ExtensionContext) {
@@ -81,7 +129,7 @@ async function pickAndInstallFromLibraryCatalog(context: ExtensionContext) {
81129
type RefEntryDesc = ReturnType<ReturnType<typeof refEntryToItem>>
82130

83131
const qp = window.createQuickPick<RefEntryDesc>()
84-
qp.placeholder = 'Select a tag to install...' // TODO: tag "or input a commit hash"
132+
qp.placeholder = 'Select a tag or branch to clone...' // TODO: tag "or input a commit hash"
85133
qp.busy = true
86134
qp.show()
87135

@@ -173,7 +221,7 @@ async function probeInstalledLibraries(root: Uri) {
173221
.filter(([, type]) => type & FileType.Directory)
174222
.map(([name]) => name)
175223

176-
const dirsSettled = await Promise.allSettled(dirNames.map(async dn => {
224+
const dirsSettled = await Promise.allSettled(dirNames.map<Promise<InstalledLibrary | null>>(async dn => {
177225
const uri = Uri.joinPath(root, dn)
178226
const libFiles = await workspace.fs.readDirectory(uri).then(
179227
names => names.filter(([name, type]) => type & FileType.File && name.endsWith('.agda-lib')))
@@ -193,9 +241,10 @@ async function probeInstalledLibraries(root: Uri) {
193241
return {
194242
name: libName,
195243
version: libVersion.join('.'),
244+
folderUri: uri,
196245
folderName: dn,
197246
libFileName: libFile,
198-
} as InstalledLibrary
247+
}
199248
} catch (err: any) {
200249
err.folderName = dn
201250
throw err
@@ -216,11 +265,11 @@ async function probeInstalledLibraries(root: Uri) {
216265
if (result.value) {
217266
const lib = result.value
218267
return {
219-
iconPath: { id: 'library' },
268+
iconPath: { id: 'folder-library' },
220269
label: lib.name + (lib.version ? ' \u2022 ' + lib.version : ''),
221270
// resourceUri as description is too lengthy
222271
description: lib.folderName + '/' + lib.libFileName,
223-
resourceUri: Uri.joinPath(root, lib.folderName, lib.libFileName),
272+
resourceUri: Uri.joinPath(lib.folderUri, lib.libFileName),
224273
data: lib,
225274
buttons: [
226275
...(env.uiKind === UIKind.Desktop ?
@@ -302,6 +351,8 @@ async function _manageLibraries(context: ExtensionContext, ..._args: any[]) {
302351
if (item.command === 'install-a-library') {
303352
pickAndInstallFromLibraryCatalog(context)
304353
}
354+
} else if ('data' in item) {
355+
await showActionPicker(item)
305356
}
306357
})
307358

gitops/lib-desktop.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import { commands, extensions, FileType, window, workspace, type Uri } from 'vscode'
1+
import { commands, extensions, window, type Uri } from 'vscode'
22
import type { LibAPI, ServerRefInfo, GitCloneOptions, RefEntry } from '$gitops'
3-
import type { GitExtension, API as GitAPI, Repository } from './vscode-git'
3+
import type { GitExtension, API as GitAPI } from './vscode-git'
44

55
const decoder = new TextDecoder()
66
function decode(s: Uint8Array) {

gitops/lib-web.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { commands, extensions, FileType, Uri, window, workspace } from 'vscode'
1+
import { commands, extensions, Uri, window } from 'vscode'
22
import type { LibAPI, ServerRefInfo, GitCloneOptions } from '$gitops'
33

44

0 commit comments

Comments
 (0)