feat: make all export available by commands (#1547)

This commit is contained in:
Myriad-Dreamin 2025-03-20 16:18:13 +08:00 committed by GitHub
parent 1039e6f4fe
commit fadf85e68a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 229 additions and 26 deletions

View file

@ -458,11 +458,11 @@ impl ServerState {
}
if let Some(Some(path)) = open.then_some(res.as_ref()) {
log::info!("open with system default apps: {path:?}");
log::trace!("open with system default apps: {path:?}");
do_open(path).log_error("failed to open with system default apps");
}
log::info!("CompileActor: on export end: {path:?} as {res:?}");
log::trace!("CompileActor: on export end: {path:?} as {res:?}");
Ok(tinymist_query::CompilerQueryResponse::OnExport(res))
})
}

View file

@ -1,6 +1,7 @@
//! The actor that handles various document export, like PDF and SVG export.
use std::str::FromStr;
use std::sync::atomic::AtomicUsize;
use std::{path::PathBuf, sync::Arc};
use reflexo::ImmutPath;
@ -150,7 +151,11 @@ impl ExportTask {
bail!("ExportTask({task:?}): output path is a directory: {to:?}");
}
let to = to.with_extension(task.extension());
log::info!("ExportTask({task:?}): exporting {entry:?} to {to:?}");
static EXPORT_ID: AtomicUsize = AtomicUsize::new(0);
let export_id = EXPORT_ID.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
log::info!("ExportTask({export_id}): exporting {entry:?} to {to:?}");
if let Some(e) = to.parent() {
if !e.exists() {
std::fs::create_dir_all(e).context("failed to create directory")?;
@ -312,7 +317,7 @@ impl ExportTask {
.await
.context("failed to export")?;
log::info!("ExportTask({task:?}): export complete");
log::info!("ExportTask({export_id}): export complete");
Ok(Some(to))
}
}

View file

@ -1056,6 +1056,11 @@
}
],
"commands": [
{
"command": "tinymist.exportCurrentFile",
"title": "%extension.tinymist.command.tinymist.exportCurrentFile%",
"category": "Typst"
},
{
"command": "tinymist.exportCurrentPdf",
"title": "%extension.tinymist.command.tinymist.exportCurrentPdf%",
@ -1077,6 +1082,11 @@
"category": "Typst",
"icon": "$(file-pdf)"
},
{
"command": "tinymist.exportCurrentFileAndShow",
"title": "%extension.tinymist.command.tinymist.exportCurrentFileAndShow%",
"category": "Typst"
},
{
"command": "tinymist.copyAnsiHighlight",
"title": "%extension.tinymist.command.tinymist.copyAnsiHighlight%",

View file

@ -32,6 +32,7 @@ import { copyAndPasteActivate, dragAndDropActivate } from "./features/drop-paste
import { testingActivate } from "./features/testing";
import { testingDebugActivate } from "./features/testing/debug";
import { FeatureEntry, tinymistActivate, tinymistDeactivate } from "./extension.shared";
import { commandAskAndExport, commandAskAndShow, ExportKind } from "./features/export";
LanguageState.Client = LanguageClient;
@ -203,7 +204,9 @@ async function languageActivate(context: IContext) {
commands.registerCommand("tinymist.openExternal", openExternal),
commands.registerCommand("tinymist.exportCurrentPdf", () => commandExport("Pdf")),
commands.registerCommand("tinymist.exportCurrentFile", commandAskAndExport),
commands.registerCommand("tinymist.showPdf", () => commandShow("Pdf")),
commands.registerCommand("tinymist.exportCurrentFileAndShow", commandAskAndShow),
commands.registerCommand("tinymist.getCurrentDocumentMetrics", commandGetCurrentDocumentMetrics),
commands.registerCommand("tinymist.clearCache", commandClearCache),
commands.registerCommand("tinymist.runCodeLens", commandRunCodeLens),
@ -241,29 +244,13 @@ async function openExternal(target: string): Promise<void> {
await vscode.env.openExternal(uri);
}
async function commandExport(
mode: "Pdf" | "Html" | "Svg" | "Png",
extraOpts?: any,
): Promise<string | undefined> {
const activeEditor = window.activeTextEditor;
if (activeEditor === undefined) {
export async function commandExport(kind: ExportKind, opts?: any): Promise<string | undefined> {
const uri = window.activeTextEditor?.document.uri.fsPath;
if (!uri) {
return;
}
const uri = activeEditor.document.uri.fsPath;
const handler = tinymist[`export${mode}`];
handler(uri, extraOpts);
const res = await tinymist.executeCommand<string | null>(`tinymist.export${mode}`, [
uri,
...(extraOpts ? [extraOpts] : []),
]);
if (res === null) {
return undefined;
}
return res;
return (await tinymist[`export${kind}`](uri, opts)) || undefined;
}
async function commandGetCurrentDocumentMetrics(): Promise<any> {
@ -303,7 +290,7 @@ async function commandCopyAnsiHighlight(): Promise<void> {
* Implements the functionality for the 'Show PDF' button shown in the editor title
* if a `.typ` file is opened.
*/
async function commandShow(kind: "Pdf" | "Html" | "Svg" | "Png", extraOpts?: any): Promise<void> {
export async function commandShow(kind: ExportKind, extraOpts?: any): Promise<void> {
const activeEditor = window.activeTextEditor;
if (activeEditor === undefined) {
return;

View file

@ -0,0 +1,110 @@
import * as vscode from "vscode";
import { l10nMsg } from "../l10n";
import { commandExport, commandShow } from "../extension";
export type ExportKind = "Pdf" | "Html" | "Svg" | "Png" | "Markdown" | "Text" | "Query";
export interface QuickExportFormatMeta {
label: string;
description: string;
exportKind: ExportKind;
extraOpts?: any;
}
const quickExports: QuickExportFormatMeta[] = [
{
label: "PDF",
description: l10nMsg("Export as PDF"),
exportKind: "Pdf",
},
{
label: l10nMsg("PNG (Merged)"),
description: l10nMsg("Export as a single PNG by merging pages"),
exportKind: "Png",
extraOpts: { page: { merged: { gap: "0pt" } } },
},
{
label: l10nMsg("SVG (Merged)"),
description: l10nMsg("Export as a single SVG by merging pages"),
exportKind: "Svg",
extraOpts: { page: { merged: { gap: "0pt" } } },
},
{
label: "HTML",
description: l10nMsg("Export as HTML"),
exportKind: "Html",
},
{
label: "Markdown",
description: l10nMsg("Export as Markdown"),
exportKind: "Markdown",
},
{
label: "Text",
description: l10nMsg("Export as Text"),
exportKind: "Text",
},
// {
// label: "Query (JSON)",
// description: l10nMsg("Query current document and export the result as a JSON file"),
// exportKind: "Query",
// },
// {
// label: "Query (YAML)",
// description: l10nMsg("Query current document and export the result as a YAML file"),
// exportKind: "Query",
// },
// {
// label: "Query (Task)",
// description: l10nMsg("Query current document and export the result as a file. We will ask a few questions and update the tasks.json file for you."),
// exportKind: "Query",
// },
{
label: l10nMsg("PNG (First Page)"),
description: l10nMsg("Export the first page as a single PNG"),
exportKind: "Png",
},
// {
// label: l10nMsg("PNG (Task)"),
// description: l10nMsg("Export as PNG (and update tasks.json)"),
// exportKind: "Png",
// },
{
label: l10nMsg("SVG (First Page)"),
description: l10nMsg("Export the first page as a single SVG"),
exportKind: "Svg",
},
// {
// label: l10nMsg("SVG (Task)"),
// description: l10nMsg("Export as SVG (and update tasks.json)"),
// exportKind: "Svg",
// },
];
export async function commandAskAndExport(): Promise<void> {
const picked = await vscode.window.showQuickPick(quickExports, {
title: l10nMsg("Pick a method to export"),
});
if (picked === undefined) {
return;
}
console.log("picked", picked);
await commandExport(picked.exportKind, picked.extraOpts);
}
export async function commandAskAndShow(): Promise<void> {
const picked = await vscode.window.showQuickPick(quickExports, {
title: l10nMsg("Pick a method to export and show"),
});
if (picked === undefined) {
return;
}
console.log("picked", picked);
await commandShow(picked.exportKind, picked.extraOpts);
}

View file

@ -3,4 +3,87 @@
[" (Preview)"]
en = " (Preview)"
zh = "(预览)"
zh = " (预览)"
["Export as HTML"]
en = "Export as HTML"
zh = "导出为 HTML"
["Export as Markdown"]
en = "Export as Markdown"
zh = "导出为 Markdown"
["Export as PDF"]
en = "Export as PDF"
zh = "导出为 PDF"
["Export as PNG (and update tasks.json)"]
en = "Export as PNG (and update tasks.json)"
zh = "导出为 PNG (并更新 tasks.json)"
["Export as SVG (and update tasks.json)"]
en = "Export as SVG (and update tasks.json)"
zh = "导出为 SVG (并更新 tasks.json)"
["Export as Text"]
en = "Export as Text"
zh = "导出为纯文本文件"
["Export as a single PNG by merging pages"]
en = "Export as a single PNG by merging pages"
zh = "合并页面并导出为单个 PNG"
["Export as a single SVG by merging pages"]
en = "Export as a single SVG by merging pages"
zh = "合并页面并导出为单个 SVG"
["Export the first page as a single PNG"]
en = "Export the first page as a single PNG"
zh = "导出首页为单个 PNG"
["Export the first page as a single SVG"]
en = "Export the first page as a single SVG"
zh = "导出首页为单个 SVG"
["PNG (First Page)"]
en = "PNG (First Page)"
zh = "PNG (首页)"
["PNG (Merged)"]
en = "PNG (Merged)"
zh = "PNG (合并)"
["PNG (Task)"]
en = "PNG (Task)"
zh = "PNG (任务)"
["Pick a method to export and show"]
en = "Pick a method to export and show"
["Pick a method to export"]
en = "Pick a method to export"
zh = "选择导出方式"
["Query current document and export the result as a JSON file"]
en = "Query current document and export the result as a JSON file"
zh = "查询当前文档并导出结果为 JSON 文件"
["Query current document and export the result as a YAML file"]
en = "Query current document and export the result as a YAML file"
zh = "查询当前文档并导出结果为 YAML 文件"
["Query current document and export the result as a file. We will ask a few questions and update the tasks.json file for you."]
en = "Query current document and export the result as a file. We will ask a few questions and update the tasks.json file for you."
zh = "查询当前文档并导出结果为文件。我们将会询问一些问题并为您更新 tasks.json 文件。"
["SVG (First Page)"]
en = "SVG (First Page)"
zh = "SVG (首页)"
["SVG (Merged)"]
en = "SVG (Merged)"
zh = "SVG (合并)"
["SVG (Task)"]
en = "SVG (Task)"
zh = "SVG (任务)"

View file

@ -39,6 +39,14 @@ vi = "Dịch vụ ngôn ngữ tích hợp cho Typst"
zh = "Typst 的集成语言服务"
zh-TW = "Typst 的集成語言服務"
[extension.tinymist.command.tinymist.exportCurrentFile]
en = "Export the Opened File as Specified Format"
zh = "将当前打开的文件导出为指定格式"
[extension.tinymist.command.tinymist.exportCurrentFileAndShow]
en = "Export the Opened File as Specified Format and Show the Result"
zh = "将当前打开的文件导出为指定格式并显示结果"
[extension.tinymist.command.tinymist.exportCurrentPdf]
en = "Export the Opened File as PDF"
ar = "تصدير الملف المفتوح كملف PDF"