Skip to content

Commit abc8f8d

Browse files
committed
Merge branch 'main' of github.com:quarto-dev/quarto-cli into main
2 parents 34b3267 + 4337308 commit abc8f8d

File tree

7 files changed

+332
-115
lines changed

7 files changed

+332
-115
lines changed

src/command/command.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import { buildJsCommand } from "./build-js/cmd.ts";
2222
import { installCommand } from "./install/cmd.ts";
2323
import { publishCommand } from "./publish/cmd.ts";
2424
import { removeCommand } from "./remove/cmd.ts";
25+
import { listCommand } from "./list/cmd.ts";
2526

2627
// deno-lint-ignore no-explicit-any
2728
export function commands(): Command<any>[] {
@@ -35,6 +36,7 @@ export function commands(): Command<any>[] {
3536
runCommand,
3637
installCommand,
3738
removeCommand,
39+
listCommand,
3840
publishCommand,
3941
capabilitiesCommand,
4042
inspectCommand,

src/command/install/cmd.ts

Lines changed: 19 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -5,44 +5,35 @@
55
*
66
*/
77
import { Command } from "cliffy/command/mod.ts";
8-
import { Select } from "cliffy/prompt/select.ts";
98
import { initYamlIntelligenceResourcesFromFilesystem } from "../../core/schema/utils.ts";
109
import { createTempContext } from "../../core/temp.ts";
1110
import { installExtension } from "../../extension/install.ts";
12-
import {
13-
allTools,
14-
installableTool,
15-
installableTools,
16-
installTool,
17-
toolSummary,
18-
} from "../tools/tools.ts";
11+
import { installTool } from "../tools/tools.ts";
1912

2013
import { info } from "log/mod.ts";
21-
import { withSpinner } from "../../core/console.ts";
22-
import { InstallableTool } from "../tools/types.ts";
14+
import { loadTools, selectTool } from "../remove/tools-console.ts";
2315

2416
export const installCommand = new Command()
2517
.hidden()
2618
.name("install")
27-
.arguments("[target:string]")
2819
.arguments("<type:string> [target:string]")
2920
.option(
3021
"--no-prompt",
31-
"Do not prompt to confirm actions during installation",
22+
"Do not prompt to confirm actions",
3223
)
3324
.description(
3425
"Installs an extension or global dependency.",
3526
)
3627
.example(
37-
"Install extension from Github",
38-
"quarto install extension <gh-organization>/<gh-repo>",
28+
"Install extension (Github)",
29+
"quarto install extension <gh-org>/<gh-repo>",
3930
)
4031
.example(
41-
"Install extension from file",
42-
"quarto install extension tools/my-extension.tar.gz",
32+
"Install extension (file)",
33+
"quarto install extension <path-to-zip>",
4334
)
4435
.example(
45-
"Install extension from url",
36+
"Install extension (url)",
4637
"quarto install extension <url>",
4738
)
4839
.example(
@@ -53,6 +44,10 @@ export const installCommand = new Command()
5344
"Install Chromium",
5445
"quarto install tool chromium",
5546
)
47+
.example(
48+
"Choose tool to install",
49+
"quarto install tool",
50+
)
5651
.action(
5752
async (options: { prompt?: boolean }, type: string, target?: string) => {
5853
await initYamlIntelligenceResourcesFromFilesystem();
@@ -71,37 +66,15 @@ export const installCommand = new Command()
7166
// Use the tool name
7267
await installTool(target);
7368
} else {
74-
// Present a list of tools
75-
const toolsToInstall = await notInstalledTools();
76-
if (toolsToInstall.length === 0) {
77-
info("All tools already installed.");
78-
const summaries = [];
79-
for (const tool of installableTools()) {
80-
const summary = await toolSummary(tool);
81-
summaries.push(summary);
82-
}
69+
// Not provided, give the user a list to choose from
70+
const allTools = await loadTools();
71+
if (allTools.filter((tool) => !tool.installed).length === 0) {
72+
info("All tools are already installed.");
8373
} else {
84-
const toolsWithSummary = [];
85-
for (const tool of toolsToInstall) {
86-
const summary = await toolSummary(tool.name);
87-
toolsWithSummary.push({ tool, summary });
88-
}
89-
90-
const toolTarget: string = await Select.prompt({
91-
message: "Select a tool to install",
92-
options: toolsWithSummary.map((toolWithSummary) => {
93-
return {
94-
name: `${toolWithSummary.tool.name}${
95-
toolWithSummary.summary?.latestRelease.version
96-
? " (" +
97-
toolWithSummary.summary?.latestRelease.version + ")"
98-
: ""
99-
}`,
100-
value: toolWithSummary.tool.name,
101-
};
102-
}),
103-
});
74+
// Select which tool should be installed
75+
const toolTarget = await selectTool(allTools, "install");
10476
if (toolTarget) {
77+
info("");
10578
await installTool(toolTarget);
10679
}
10780
}
@@ -117,12 +90,3 @@ export const installCommand = new Command()
11790
}
11891
},
11992
);
120-
121-
async function notInstalledTools() {
122-
const toolsToInstall: InstallableTool[] = [];
123-
await withSpinner({ message: "Inspecting tools" }, async () => {
124-
const all = await allTools();
125-
toolsToInstall.push(...all.notInstalled);
126-
});
127-
return toolsToInstall;
128-
}

src/command/list/cmd.ts

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
/*
2+
* cmd.ts
3+
*
4+
* Copyright (C) 2021 by RStudio, PBC
5+
*
6+
*/
7+
import { Command } from "cliffy/command/mod.ts";
8+
import { Table } from "cliffy/table/mod.ts";
9+
import { initYamlIntelligenceResourcesFromFilesystem } from "../../core/schema/utils.ts";
10+
import { createTempContext } from "../../core/temp.ts";
11+
12+
import { info } from "log/mod.ts";
13+
import { outputTools } from "../remove/tools-console.ts";
14+
import { createExtensionContext } from "../../extension/extension.ts";
15+
import {
16+
Extension,
17+
ExtensionContext,
18+
extensionIdString,
19+
} from "../../extension/extension-shared.ts";
20+
import { projectContext } from "../../project/project-context.ts";
21+
22+
export const listCommand = new Command()
23+
.hidden()
24+
.name("list")
25+
.arguments("<type:string>")
26+
.description(
27+
"Lists an extension or global dependency.",
28+
)
29+
.example(
30+
"List installed extensions",
31+
"quarto list extensions",
32+
)
33+
.example(
34+
"List global tools",
35+
"quarto list tools",
36+
)
37+
.action(
38+
async (_options: unknown, type: string) => {
39+
await initYamlIntelligenceResourcesFromFilesystem();
40+
const temp = createTempContext();
41+
const extensionContext = createExtensionContext();
42+
try {
43+
if (type.toLowerCase() === "extensions") {
44+
await outputExtensions(Deno.cwd(), extensionContext);
45+
} else if (type.toLowerCase() === "tools") {
46+
await outputTools();
47+
} else {
48+
// This is an unrecognized type option
49+
info(
50+
`Unrecognized option '${type}' - please choose 'tools' or 'extensions'.`,
51+
);
52+
}
53+
} finally {
54+
temp.cleanup();
55+
}
56+
},
57+
);
58+
59+
async function outputExtensions(
60+
path: string,
61+
extensionContext: ExtensionContext,
62+
) {
63+
// Provide the with with a list
64+
const project = await projectContext(path);
65+
const extensions = extensionContext.extensions(path, project);
66+
67+
const extensionEntries: string[][] = [];
68+
69+
const provides = (extension: Extension) => {
70+
const contribs: string[] = [];
71+
if (
72+
extension.contributes.filters && extension.contributes.filters?.length > 0
73+
) {
74+
contribs.push("filter");
75+
}
76+
77+
if (
78+
extension.contributes.shortcodes &&
79+
extension.contributes.shortcodes?.length > 0
80+
) {
81+
contribs.push("shortcodes");
82+
}
83+
84+
if (
85+
extension.contributes.format
86+
) {
87+
contribs.push("formats");
88+
}
89+
return contribs.join(", ");
90+
};
91+
92+
extensions.forEach((ext) => {
93+
const row = [
94+
extensionIdString(ext.id),
95+
ext.version?.toString() || "(none)",
96+
`[${provides(ext)}]`,
97+
];
98+
extensionEntries.push(row);
99+
});
100+
101+
const table = new Table().header(["Id", "Version", "Type"]).body(
102+
extensionEntries,
103+
).padding(4);
104+
info(table.toString());
105+
}

0 commit comments

Comments
 (0)