mirror of
https://github.com/Myriad-Dreamin/tinymist.git
synced 2025-08-04 02:08:17 +00:00
feat: show main file in the status bar (#1147)
This commit is contained in:
parent
c0e0e330c3
commit
30f242d393
6 changed files with 92 additions and 38 deletions
|
@ -15,9 +15,16 @@ pub struct DocVersion {
|
|||
pub revision: usize,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CompileStatus {
|
||||
pub group: String,
|
||||
pub path: String,
|
||||
pub status: TinymistCompileStatusEnum,
|
||||
}
|
||||
|
||||
pub enum EditorRequest {
|
||||
Diag(DocVersion, Option<DiagnosticsMap>),
|
||||
Status(String, TinymistCompileStatusEnum),
|
||||
Status(CompileStatus),
|
||||
WordCount(String, WordsCount),
|
||||
}
|
||||
|
||||
|
@ -46,7 +53,11 @@ impl EditorActor {
|
|||
}
|
||||
|
||||
pub async fn run(mut self) {
|
||||
let mut compile_status = TinymistCompileStatusEnum::Compiling;
|
||||
let mut compile_status = CompileStatus {
|
||||
group: "primary".to_owned(),
|
||||
status: TinymistCompileStatusEnum::Compiling,
|
||||
path: "".to_owned(),
|
||||
};
|
||||
let mut words_count = None;
|
||||
while let Some(req) = self.editor_rx.recv().await {
|
||||
match req {
|
||||
|
@ -59,13 +70,14 @@ impl EditorActor {
|
|||
|
||||
self.publish(group, diagnostics).await;
|
||||
}
|
||||
EditorRequest::Status(group, status) => {
|
||||
log::info!("received status request({group}) {status:?}");
|
||||
if self.notify_compile_status && group == "primary" {
|
||||
EditorRequest::Status(status) => {
|
||||
log::info!("received status request({status:?})");
|
||||
if self.notify_compile_status && status.group == "primary" {
|
||||
compile_status = status;
|
||||
self.client.send_notification::<TinymistCompileStatus>(
|
||||
TinymistCompileStatus {
|
||||
status: compile_status.clone(),
|
||||
status: compile_status.status.clone(),
|
||||
path: compile_status.path.clone(),
|
||||
words_count: words_count.clone(),
|
||||
},
|
||||
);
|
||||
|
@ -77,7 +89,8 @@ impl EditorActor {
|
|||
words_count = Some(wc);
|
||||
self.client.send_notification::<TinymistCompileStatus>(
|
||||
TinymistCompileStatus {
|
||||
status: compile_status.clone(),
|
||||
status: compile_status.status.clone(),
|
||||
path: compile_status.path.clone(),
|
||||
words_count: words_count.clone(),
|
||||
},
|
||||
);
|
||||
|
@ -156,8 +169,9 @@ pub enum TinymistCompileStatusEnum {
|
|||
|
||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct TinymistCompileStatus {
|
||||
struct TinymistCompileStatus {
|
||||
pub status: TinymistCompileStatusEnum,
|
||||
pub path: String,
|
||||
pub words_count: Option<WordsCount>,
|
||||
}
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ use std::{collections::HashMap, ops::Deref, sync::Arc};
|
|||
|
||||
use anyhow::bail;
|
||||
use log::{error, info, trace};
|
||||
use reflexo::path::unix_slash;
|
||||
use reflexo_typst::{
|
||||
error::prelude::*, typst::prelude::*, vfs::notify::MemoryEvent, world::EntryState,
|
||||
CompileReport, EntryReader, Error, ImmutPath, TaskInputs,
|
||||
|
@ -40,7 +41,7 @@ use tokio::sync::{mpsc, oneshot};
|
|||
use typst::{diag::SourceDiagnostic, World};
|
||||
|
||||
use super::{
|
||||
editor::{DocVersion, EditorRequest, TinymistCompileStatusEnum},
|
||||
editor::{CompileStatus, DocVersion, EditorRequest, TinymistCompileStatusEnum},
|
||||
typ_server::{
|
||||
CompilationHandle, CompileSnapshot, CompiledArtifact, Interrupt, SucceededArtifact,
|
||||
},
|
||||
|
@ -182,9 +183,9 @@ impl CompileHandler {
|
|||
}
|
||||
|
||||
impl CompilationHandle<LspCompilerFeat> for CompileHandler {
|
||||
fn status(&self, revision: usize, _rep: CompileReport) {
|
||||
fn status(&self, revision: usize, rep: CompileReport) {
|
||||
// todo: seems to duplicate with CompileStatus
|
||||
let status = match _rep {
|
||||
let status = match rep {
|
||||
CompileReport::Suspend => {
|
||||
self.push_diagnostics(revision, None);
|
||||
TinymistCompileStatusEnum::CompileSuccess
|
||||
|
@ -198,14 +199,21 @@ impl CompilationHandle<LspCompilerFeat> for CompileHandler {
|
|||
|
||||
let this = &self;
|
||||
this.editor_tx
|
||||
.send(EditorRequest::Status(this.diag_group.clone(), status))
|
||||
.send(EditorRequest::Status(CompileStatus {
|
||||
group: this.diag_group.clone(),
|
||||
path: rep
|
||||
.compiling_id()
|
||||
.map(|s| unix_slash(s.vpath().as_rooted_path()))
|
||||
.unwrap_or_default(),
|
||||
status,
|
||||
}))
|
||||
.unwrap();
|
||||
|
||||
#[cfg(feature = "preview")]
|
||||
if let Some(inner) = this.inner.read().as_ref() {
|
||||
use typst_preview::CompileStatus;
|
||||
|
||||
let status = match _rep {
|
||||
let status = match rep {
|
||||
CompileReport::Suspend => CompileStatus::CompileSuccess,
|
||||
CompileReport::Stage(_, _, _) => CompileStatus::Compiling,
|
||||
CompileReport::CompileSuccess(_, _, _) => CompileStatus::CompileSuccess,
|
||||
|
@ -218,7 +226,7 @@ impl CompilationHandle<LspCompilerFeat> for CompileHandler {
|
|||
}
|
||||
}
|
||||
|
||||
fn notify_compile(&self, snap: &CompiledArtifact<LspCompilerFeat>, _rep: CompileReport) {
|
||||
fn notify_compile(&self, snap: &CompiledArtifact<LspCompilerFeat>, rep: CompileReport) {
|
||||
// todo: we need to manage the revision for fn status() as well
|
||||
{
|
||||
let mut n_rev = self.notified_revision.lock();
|
||||
|
@ -241,14 +249,18 @@ impl CompilationHandle<LspCompilerFeat> for CompileHandler {
|
|||
self.export.signal(snap, snap.signal);
|
||||
|
||||
self.editor_tx
|
||||
.send(EditorRequest::Status(
|
||||
self.diag_group.clone(),
|
||||
if snap.doc.is_ok() {
|
||||
.send(EditorRequest::Status(CompileStatus {
|
||||
group: self.diag_group.clone(),
|
||||
path: rep
|
||||
.compiling_id()
|
||||
.map(|s| unix_slash(s.vpath().as_rooted_path()))
|
||||
.unwrap_or_default(),
|
||||
status: if snap.doc.is_ok() {
|
||||
TinymistCompileStatusEnum::CompileSuccess
|
||||
} else {
|
||||
TinymistCompileStatusEnum::CompileError
|
||||
},
|
||||
))
|
||||
}))
|
||||
.unwrap();
|
||||
|
||||
#[cfg(feature = "preview")]
|
||||
|
|
|
@ -81,6 +81,19 @@ In VSCode, enable compile status meaning that the extension will show the compil
|
|||
- `disable`
|
||||
- **Default**: `"enable"`
|
||||
|
||||
## `tinymist.statusBarFormat`
|
||||
|
||||
Set format string of the server status. For example, `{compileStatusIcon}{wordCount} [{fileName}]` will format the status as `$(check) 123 words [main]`. Valid placeholders are:
|
||||
|
||||
- `{compileStatusIcon}`: Icon indicating the compile status
|
||||
- `{wordCount}`: Number of words in the document
|
||||
- `{fileName}`: Name of the file being compiled
|
||||
|
||||
Note: The status bar will be hidden if the format string is empty.
|
||||
|
||||
- **Type**: `string`
|
||||
- **Default**: `"{compileStatusIcon} {wordCount} [{fileName}]"`
|
||||
|
||||
## `tinymist.typstExtraArgs`
|
||||
|
||||
You can pass any arguments as you like, and we will try to follow behaviors of the **same version** of typst-cli. Note: the arguments may be overridden by other settings. For example, `--font-path` will be overridden by `tinymist.fontPaths`.
|
||||
|
|
|
@ -365,7 +365,7 @@
|
|||
"default": null
|
||||
},
|
||||
"tinymist.compileStatus": {
|
||||
"title": "Show/Report compilation status",
|
||||
"title": "Show/Report Compile Status",
|
||||
"description": "In VSCode, enable compile status meaning that the extension will show the compilation status in the status bar. Since Neovim and Helix don't have a such feature, it is disabled by default at the language server label.",
|
||||
"type": "string",
|
||||
"default": "enable",
|
||||
|
@ -374,6 +374,12 @@
|
|||
"disable"
|
||||
]
|
||||
},
|
||||
"tinymist.statusBarFormat": {
|
||||
"title": "Format of the Server Status in the Status Bar",
|
||||
"markdownDescription": "Set format string of the server status. For example, `{compileStatusIcon}{wordCount} [{fileName}]` will format the status as `$(check) 123 words [main]`. Valid placeholders are:\n\n- `{compileStatusIcon}`: Icon indicating the compile status\n- `{wordCount}`: Number of words in the document\n- `{fileName}`: Name of the file being compiled\n\nNote: The status bar will be hidden if the format string is empty.",
|
||||
"type": "string",
|
||||
"default": "{compileStatusIcon} {wordCount} [{fileName}]"
|
||||
},
|
||||
"tinymist.typstExtraArgs": {
|
||||
"title": "Specifies the arguments for Typst as same as typst-cli",
|
||||
"description": "You can pass any arguments as you like, and we will try to follow behaviors of the **same version** of typst-cli. Note: the arguments may be overridden by other settings. For example, `--font-path` will be overridden by `tinymist.fontPaths`.",
|
||||
|
|
|
@ -516,8 +516,11 @@ async function commandActivateDocPath(
|
|||
if (extensionState.mut.focusingDoc?.isClosed) {
|
||||
extensionState.mut.focusingDoc = undefined;
|
||||
}
|
||||
const formatString = statusBarFormatString();
|
||||
// remove the status bar until the last focusing file is closed
|
||||
triggerStatusBar(!!(fsPath || extensionState.mut.focusingDoc?.isClosed === false));
|
||||
triggerStatusBar(
|
||||
!!formatString && !!(fsPath || extensionState.mut.focusingDoc?.isClosed === false),
|
||||
);
|
||||
await tinymist.executeCommand("tinymist.focusMain", [fsPath]);
|
||||
}
|
||||
|
||||
|
@ -600,3 +603,11 @@ function triggerSuggestAndParameterHints() {
|
|||
vscode.commands.executeCommand("editor.action.triggerSuggest");
|
||||
vscode.commands.executeCommand("editor.action.triggerParameterHints");
|
||||
}
|
||||
|
||||
export function statusBarFormatString() {
|
||||
const formatter = (
|
||||
(vscode.workspace.getConfiguration("tinymist").get("statusBarFormat") as string) || ""
|
||||
).trim();
|
||||
|
||||
return formatter;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import * as vscode from "vscode";
|
||||
import { statusBarFormatString } from "./extension";
|
||||
|
||||
let statusBarItem: vscode.StatusBarItem;
|
||||
|
||||
|
@ -23,6 +24,7 @@ interface WordsCount {
|
|||
|
||||
export interface TinymistStatus {
|
||||
status: "compiling" | "compileSuccess" | "compileError";
|
||||
path: string;
|
||||
wordsCount: WordsCount;
|
||||
}
|
||||
|
||||
|
@ -39,11 +41,13 @@ export function wordCountItemProcess(event: TinymistStatus) {
|
|||
statusBarItem = statusBarItem || initWordCountItem();
|
||||
|
||||
const updateTooltip = () => {
|
||||
statusBarItem.tooltip = `${words} ${plural("Word", words)}
|
||||
statusBarItem.tooltip = `
|
||||
Main file: ${event.path}
|
||||
${words} ${plural("Word", words)}
|
||||
${chars} ${plural("Character", chars)}
|
||||
${spaces} ${plural("Space", spaces)}
|
||||
${cjkChars} CJK ${plural("Character", cjkChars)}
|
||||
[Click to show logs]`;
|
||||
[Click to show logs]`.trim();
|
||||
};
|
||||
|
||||
words = event.wordsCount?.words || 0;
|
||||
|
@ -51,30 +55,24 @@ ${cjkChars} CJK ${plural("Character", cjkChars)}
|
|||
spaces = event.wordsCount?.spaces || 0;
|
||||
cjkChars = event.wordsCount?.cjkChars || 0;
|
||||
|
||||
const style: string = "errorStatus";
|
||||
const fileName = event.path ? event.path.split("/").slice(-1)[0] : "";
|
||||
const fileNameWithoutExt = fileName ? fileName.split(".").slice(0, -1).join(".") : "";
|
||||
|
||||
const formatString = statusBarFormatString()
|
||||
.replace(/\{wordCount\}/g, `${words} ${plural("Word", words)}`)
|
||||
.replace(/\{fileName\}/g, fileNameWithoutExt);
|
||||
|
||||
if (statusBarItem) {
|
||||
if (event.status === "compiling") {
|
||||
if (style === "compact") {
|
||||
statusBarItem.text = "$(sync~spin)";
|
||||
} else if (style === "errorStatus") {
|
||||
statusBarItem.text = `$(sync~spin) ${words} ${plural("Word", words)}`;
|
||||
}
|
||||
statusBarItem.text = formatString.replace(/\{compileStatusIcon\}/g, "$(sync~spin)");
|
||||
statusBarItem.backgroundColor = new vscode.ThemeColor("statusBarItem.prominentBackground");
|
||||
updateTooltip();
|
||||
} else if (event.status === "compileSuccess") {
|
||||
if (style === "compact") {
|
||||
statusBarItem.text = "$(typst-guy)";
|
||||
} else if (style === "errorStatus") {
|
||||
statusBarItem.text = `$(sync) ${words} ${plural("Word", words)}`;
|
||||
}
|
||||
statusBarItem.text = formatString.replace(/\{compileStatusIcon\}/g, "$(sync)");
|
||||
statusBarItem.backgroundColor = new vscode.ThemeColor("statusBarItem.prominentBackground");
|
||||
updateTooltip();
|
||||
} else if (event.status === "compileError") {
|
||||
if (style === "compact") {
|
||||
statusBarItem.text = "$(typst-guy)";
|
||||
} else if (style === "errorStatus") {
|
||||
statusBarItem.text = `$(sync) ${words} ${plural("Word", words)}`;
|
||||
}
|
||||
statusBarItem.text = formatString.replace(/\{compileStatusIcon\}/g, "$(sync)");
|
||||
statusBarItem.backgroundColor = new vscode.ThemeColor("statusBarItem.errorBackground");
|
||||
updateTooltip();
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue