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

feat: autogenerate CLI command docs #2535

Merged
merged 4 commits into from
Aug 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@
"build:references": "pnpm --filter js-api-generator run build",
"build:releases": "pnpm --filter releases-generator run build",
"build:config": "pnpm --filter config-generator run build",
"build:cli": "pnpm --filter cli-generator run build",
"build:astro": "astro build",
"build:i18n": "pnpm --filter docs-i18n-tracker run build",
"build": "pnpm dev:setup && pnpm build:references && pnpm build:config && pnpm build:releases && pnpm build:astro && pnpm build:i18n",
"build": "pnpm dev:setup && pnpm build:references && pnpm build:config && pnpm build:cli && pnpm build:releases && pnpm build:astro && pnpm build:i18n",
"preview": "astro preview"
},
"dependencies": {
Expand Down
100 changes: 100 additions & 0 deletions packages/cli-generator/build.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import { readFileSync, writeFileSync } from 'node:fs';
import { execSync } from 'node:child_process';
import { slug } from 'github-slugger';

interface Command {
name: string;
description: string;
}

function getSubcommands(commandOutput: string): Command[] {
const subcommands = [];

let readingSubcommands = false;
for (const line of commandOutput.split('\n').map((l) => l.trim())) {
if (readingSubcommands) {
if (line.length === 0) {
readingSubcommands = false;
} else {
const subcommand = line.substring(0, line.indexOf(' '));
const description = line.substring(subcommand.length).trim();
if (subcommand !== 'help') {
subcommands.push({ name: subcommand, description });
}
}
}
if (line === 'Commands:') {
readingSubcommands = true;
}
}

return subcommands;
}

function generateCommandDoc(command: string, level: number, subcommandList: Command[]): string {
const output = execSync(`pnpm tauri ${command} --help`)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This approach is kinda fragile whenever we change the layout of the help output but I don't think that will happen more than once.
Also running the binary just for the help output sounds weird when we have access to the docs/source code itself since we have tauri as a git submodule.

Is tauri auto generating the rustdocs/scheme and we can consume them the same way we do for the permissions and configs? If not is it not feasible to do so?

.toString()
.replace('pnpm run build', 'tauri');
const subcommands = getSubcommands(output);

subcommandList.push(
...subcommands.map((subcommand) => ({
...subcommand,
name: `${command} ${subcommand.name}`,
}))
);

const subcommandsDoc =
subcommands.length === 0
? ''
: `\n${subcommands.map(({ name }) => generateCommandDoc(`${command} ${name}`, level + 1, commandList)).join('\n\n')}`;

const heading = '#'.repeat(level);
return `${heading} \`${command}\`

<CommandTabs
npm="npm run tauri ${command}"
yarn="yarn tauri ${command}"
pnpm="pnpm tauri ${command}"
cargo="cargo tauri ${command}"
/>

\`\`\`
${output}
\`\`\`
${subcommandsDoc}
`;
}

const output = execSync('pnpm tauri --help').toString();
const subcommands = getSubcommands(output);

const commandList: Command[] = [];

let doc = '';

for (const command of subcommands) {
commandList.push(command);
const commandDoc = generateCommandDoc(command.name, 3, commandList);
doc += commandDoc;
}

let summary = `| Command | Description |
| ---------- | ------------------- |
`;

for (const { name, description } of commandList) {
summary += `| [\`${name}\`](#${slug(name)}) | ${description} |\n`;
}

const template = readFileSync('../../src/content/docs/reference/_cli.mdx').toString();

writeFileSync(
'../../src/content/docs/reference/cli.mdx',
template.replace(
'$LIST_OF_COMMANDS',
`${summary}

${doc}`
)
);
21 changes: 21 additions & 0 deletions packages/cli-generator/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"name": "cli-generator",
"version": "1.0.0",
"private": "true",
"description": "",
"main": "index.js",
"type": "module",
"scripts": {
"build": "tsm ./build.ts"
},
"keywords": [],
"author": "",
"license": "MIT",
"dependencies": {
"@tauri-apps/cli": "2.0.0-rc.3",
"@types/node": "^20.11.20",
"github-slugger": "^2.0.0",
"tsm": "^2.3.0",
"typescript": "^5.3.3"
}
}
8 changes: 8 additions & 0 deletions packages/cli-generator/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"compilerOptions": {
"target": "ES2021",
"esModuleInterop": true,
"strict": true,
"skipLibCheck": true
}
}
136 changes: 132 additions & 4 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pnpm-workspace.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ packages:
- 'packages/i18n-tracker'
- 'packages/js-api-generator'
- 'packages/config-generator'
- 'packages/cli-generator'
- 'packages/tauri-typedoc-theme'
- 'packages/releases-generator'
1 change: 1 addition & 0 deletions src/content/docs/reference/.gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
config.md
acl/*.md
cli.mdx
javascript/*
!javascript/index.mdx
32 changes: 32 additions & 0 deletions src/content/docs/reference/_cli.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
title: Command Line Interface
sidebar:
order: 1
tableOfContents:
minHeadingLevel: 2
maxHeadingLevel: 5
---

import { Tabs, TabItem } from '@astrojs/starlight/components';
import CommandTabs from '@components/CommandTabs.astro';

The Tauri command line interface (CLI) is the way to interact with Tauri throughout the development lifecycle.

You can add the Tauri CLI to your current project using your package manager of choice:

<CommandTabs
npm="npm install --save-dev @tauri-apps/cli@next"
yarn="yarn add -D @tauri-apps/cli@next"
pnpm="pnpm add -D @tauri-apps/cli@next"
cargo='cargo install tauri-cli --version "^2.0.0-rc"'
/>

:::tip[Developing a Plugin]

For CLI commands related to developing plugins visit the [Develop a Tauri Plugin guide](/develop/plugins/).

:::

## List of Commands

$LIST_OF_COMMANDS
Loading
Loading