mirror of
https://github.com/typst/typst
synced 2025-05-14 17:15:28 +08:00
Greet users who run typst
for the first time (#5210)
This commit is contained in:
parent
382787d799
commit
89cecb188d
49
Cargo.lock
generated
49
Cargo.lock
generated
@ -339,6 +339,7 @@ dependencies = [
|
|||||||
"anstyle",
|
"anstyle",
|
||||||
"clap_lex",
|
"clap_lex",
|
||||||
"strsim",
|
"strsim",
|
||||||
|
"terminal_size",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -394,6 +395,27 @@ dependencies = [
|
|||||||
"unicode-width",
|
"unicode-width",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "color-print"
|
||||||
|
version = "0.3.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1ee543c60ff3888934877a5671f45494dd27ed4ba25c6670b9a7576b7ed7a8c0"
|
||||||
|
dependencies = [
|
||||||
|
"color-print-proc-macro",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "color-print-proc-macro"
|
||||||
|
version = "0.3.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "77ff1a80c5f3cb1ca7c06ffdd71b6a6dd6d8f896c42141fbd43f50ed28dcdb93"
|
||||||
|
dependencies = [
|
||||||
|
"nom",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "color_quant"
|
name = "color_quant"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
@ -1374,6 +1396,12 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "minimal-lexical"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "miniz_oxide"
|
name = "miniz_oxide"
|
||||||
version = "0.8.0"
|
version = "0.8.0"
|
||||||
@ -1425,6 +1453,16 @@ dependencies = [
|
|||||||
"tempfile",
|
"tempfile",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nom"
|
||||||
|
version = "7.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
"minimal-lexical",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "notify"
|
name = "notify"
|
||||||
version = "6.1.1"
|
version = "6.1.1"
|
||||||
@ -2447,6 +2485,16 @@ dependencies = [
|
|||||||
"winapi-util",
|
"winapi-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "terminal_size"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4f599bd7ca042cfdf8f4512b277c02ba102247820f9d9d4a9f521f496751a6ef"
|
||||||
|
dependencies = [
|
||||||
|
"rustix",
|
||||||
|
"windows-sys 0.59.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thin-vec"
|
name = "thin-vec"
|
||||||
version = "0.2.13"
|
version = "0.2.13"
|
||||||
@ -2698,6 +2746,7 @@ dependencies = [
|
|||||||
"clap_complete",
|
"clap_complete",
|
||||||
"clap_mangen",
|
"clap_mangen",
|
||||||
"codespan-reporting",
|
"codespan-reporting",
|
||||||
|
"color-print",
|
||||||
"comemo",
|
"comemo",
|
||||||
"dirs",
|
"dirs",
|
||||||
"ecow",
|
"ecow",
|
||||||
|
@ -38,13 +38,14 @@ bytemuck = "1"
|
|||||||
chinese-number = { version = "0.7.2", default-features = false, features = ["number-to-chinese"] }
|
chinese-number = { version = "0.7.2", default-features = false, features = ["number-to-chinese"] }
|
||||||
chrono = { version = "0.4.24", default-features = false, features = ["clock", "std"] }
|
chrono = { version = "0.4.24", default-features = false, features = ["clock", "std"] }
|
||||||
ciborium = "0.2.1"
|
ciborium = "0.2.1"
|
||||||
clap = { version = "4.4", features = ["derive", "env"] }
|
clap = { version = "4.4", features = ["derive", "env", "wrap_help"] }
|
||||||
clap_complete = "4.2.1"
|
clap_complete = "4.2.1"
|
||||||
clap_mangen = "0.2.10"
|
clap_mangen = "0.2.10"
|
||||||
ctrlc = "3.4.1"
|
|
||||||
codespan-reporting = "0.11"
|
codespan-reporting = "0.11"
|
||||||
|
color-print = "0.3.6"
|
||||||
comemo = "0.4"
|
comemo = "0.4"
|
||||||
csv = "1"
|
csv = "1"
|
||||||
|
ctrlc = "3.4.1"
|
||||||
dirs = "5"
|
dirs = "5"
|
||||||
ecow = { version = "0.2", features = ["serde"] }
|
ecow = { version = "0.2", features = ["serde"] }
|
||||||
env_proxy = "0.4"
|
env_proxy = "0.4"
|
||||||
@ -84,8 +85,8 @@ png = "0.17"
|
|||||||
portable-atomic = "1.6"
|
portable-atomic = "1.6"
|
||||||
proc-macro2 = "1"
|
proc-macro2 = "1"
|
||||||
pulldown-cmark = "0.9"
|
pulldown-cmark = "0.9"
|
||||||
quote = "1"
|
|
||||||
qcms = "0.3.0"
|
qcms = "0.3.0"
|
||||||
|
quote = "1"
|
||||||
rayon = "1.7.0"
|
rayon = "1.7.0"
|
||||||
regex = "1"
|
regex = "1"
|
||||||
resvg = { version = "0.43", default-features = false, features = ["raster-images"] }
|
resvg = { version = "0.43", default-features = false, features = ["raster-images"] }
|
||||||
|
@ -28,6 +28,7 @@ typst-svg = { workspace = true }
|
|||||||
typst-timing = { workspace = true }
|
typst-timing = { workspace = true }
|
||||||
chrono = { workspace = true }
|
chrono = { workspace = true }
|
||||||
clap = { workspace = true }
|
clap = { workspace = true }
|
||||||
|
color-print = { workspace = true }
|
||||||
codespan-reporting = { workspace = true }
|
codespan-reporting = { workspace = true }
|
||||||
comemo = { workspace = true }
|
comemo = { workspace = true }
|
||||||
dirs = { workspace = true }
|
dirs = { workspace = true }
|
||||||
@ -59,6 +60,7 @@ chrono = { workspace = true }
|
|||||||
clap = { workspace = true, features = ["string"] }
|
clap = { workspace = true, features = ["string"] }
|
||||||
clap_complete = { workspace = true }
|
clap_complete = { workspace = true }
|
||||||
clap_mangen = { workspace = true }
|
clap_mangen = { workspace = true }
|
||||||
|
color-print = { workspace = true }
|
||||||
semver = { workspace = true }
|
semver = { workspace = true }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
@ -13,9 +13,36 @@ use semver::Version;
|
|||||||
/// in environment variables.
|
/// in environment variables.
|
||||||
const ENV_PATH_SEP: char = if cfg!(windows) { ';' } else { ':' };
|
const ENV_PATH_SEP: char = if cfg!(windows) { ';' } else { ':' };
|
||||||
|
|
||||||
/// The Typst compiler.
|
/// The overall structure of the help.
|
||||||
|
#[rustfmt::skip]
|
||||||
|
const HELP_TEMPLATE: &str = "\
|
||||||
|
Typst {version}
|
||||||
|
|
||||||
|
{usage-heading} {usage}
|
||||||
|
|
||||||
|
{all-args}{after-help}\
|
||||||
|
";
|
||||||
|
|
||||||
|
/// Adds a list of useful links after the normal help.
|
||||||
|
#[rustfmt::skip]
|
||||||
|
const AFTER_HELP: &str = color_print::cstr!("\
|
||||||
|
<s><u>Resources:</></>
|
||||||
|
<s>Tutorial:</> https://typst.app/docs/tutorial/
|
||||||
|
<s>Reference documentation:</> https://typst.app/docs/reference/
|
||||||
|
<s>Templates & Packages:</> https://typst.app/universe/
|
||||||
|
<s>Forum for questions:</> https://forum.typst.app/
|
||||||
|
");
|
||||||
|
|
||||||
|
/// The Typst compiler
|
||||||
#[derive(Debug, Clone, Parser)]
|
#[derive(Debug, Clone, Parser)]
|
||||||
#[clap(name = "typst", version = crate::typst_version(), author)]
|
#[clap(
|
||||||
|
name = "typst",
|
||||||
|
version = crate::typst_version(),
|
||||||
|
author,
|
||||||
|
help_template = HELP_TEMPLATE,
|
||||||
|
after_help = AFTER_HELP,
|
||||||
|
max_term_width = 80,
|
||||||
|
)]
|
||||||
pub struct CliArguments {
|
pub struct CliArguments {
|
||||||
/// The command to run
|
/// The command to run
|
||||||
#[command(subcommand)]
|
#[command(subcommand)]
|
||||||
|
66
crates/typst-cli/src/greet.rs
Normal file
66
crates/typst-cli/src/greet.rs
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
use std::io::{self, Read};
|
||||||
|
|
||||||
|
/// This is shown to users who just type `typst` the first time.
|
||||||
|
#[rustfmt::skip]
|
||||||
|
const GREETING: &str = color_print::cstr!("\
|
||||||
|
<s>Welcome to Typst, we are glad to have you here!</> ❤️
|
||||||
|
|
||||||
|
If you are new to Typst, <s>start with the tutorial</> at \
|
||||||
|
<u>https://typst.app/docs/tutorial/</>. To get a quick start with your first \
|
||||||
|
project, <s>choose a template</> on <u>https://typst.app/universe/</>.
|
||||||
|
|
||||||
|
Here are the <s>most important commands</> you will be using:
|
||||||
|
|
||||||
|
- Compile a file once: <c!>typst compile file.typ</>
|
||||||
|
- Compile a file on every change: <c!>typst watch file.typ</>
|
||||||
|
- Set up a project from a template: <c!>typst init @preview/<<TEMPLATE>></>
|
||||||
|
|
||||||
|
Learn more about these commands by running <c!>typst help</>.
|
||||||
|
|
||||||
|
If you have a question, we and our community would be glad to help you out on \
|
||||||
|
the <s>Typst Forum</> at <u>https://forum.typst.app/</>.
|
||||||
|
|
||||||
|
Happy Typsting!
|
||||||
|
");
|
||||||
|
|
||||||
|
/// Greets (and exists) if not yet greeted.
|
||||||
|
pub fn greet() {
|
||||||
|
let Some(data_dir) = dirs::data_dir() else { return };
|
||||||
|
let path = data_dir.join("typst").join("greeted");
|
||||||
|
|
||||||
|
let prev_greet = std::fs::read_to_string(&path).ok();
|
||||||
|
if prev_greet.as_deref() == Some(crate::typst_version()) {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::fs::write(&path, crate::typst_version()).ok();
|
||||||
|
print_and_exit(GREETING);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Prints a colorized and line-wrapped message.
|
||||||
|
fn print_and_exit(message: &'static str) -> ! {
|
||||||
|
// Abuse clap for line wrapping ...
|
||||||
|
let err = clap::Command::new("typst")
|
||||||
|
.max_term_width(80)
|
||||||
|
.help_template("{about}")
|
||||||
|
.about(message)
|
||||||
|
.try_get_matches_from(["typst", "--help"])
|
||||||
|
.unwrap_err();
|
||||||
|
let _ = err.print();
|
||||||
|
|
||||||
|
// Windows users might have double-clicked the .exe file and have no chance
|
||||||
|
// to read it before the terminal closes.
|
||||||
|
if cfg!(windows) {
|
||||||
|
pause();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::process::exit(err.exit_code());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Waits for the user.
|
||||||
|
#[allow(clippy::unused_io_amount)]
|
||||||
|
fn pause() {
|
||||||
|
eprintln!();
|
||||||
|
eprintln!("Press enter to continue...");
|
||||||
|
io::stdin().lock().read(&mut [0]).unwrap();
|
||||||
|
}
|
@ -2,6 +2,7 @@ mod args;
|
|||||||
mod compile;
|
mod compile;
|
||||||
mod download;
|
mod download;
|
||||||
mod fonts;
|
mod fonts;
|
||||||
|
mod greet;
|
||||||
mod init;
|
mod init;
|
||||||
mod package;
|
mod package;
|
||||||
mod query;
|
mod query;
|
||||||
@ -16,6 +17,7 @@ use std::cell::Cell;
|
|||||||
use std::io::{self, Write};
|
use std::io::{self, Write};
|
||||||
use std::process::ExitCode;
|
use std::process::ExitCode;
|
||||||
|
|
||||||
|
use clap::error::ErrorKind;
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use codespan_reporting::term;
|
use codespan_reporting::term;
|
||||||
use codespan_reporting::term::termcolor::WriteColor;
|
use codespan_reporting::term::termcolor::WriteColor;
|
||||||
@ -30,8 +32,15 @@ thread_local! {
|
|||||||
static EXIT: Cell<ExitCode> = const { Cell::new(ExitCode::SUCCESS) };
|
static EXIT: Cell<ExitCode> = const { Cell::new(ExitCode::SUCCESS) };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The parsed commandline arguments.
|
/// The parsed command line arguments.
|
||||||
static ARGS: Lazy<CliArguments> = Lazy::new(CliArguments::parse);
|
static ARGS: Lazy<CliArguments> = Lazy::new(|| {
|
||||||
|
CliArguments::try_parse().unwrap_or_else(|error| {
|
||||||
|
if error.kind() == ErrorKind::DisplayHelpOnMissingArgumentOrSubcommand {
|
||||||
|
crate::greet::greet();
|
||||||
|
}
|
||||||
|
error.exit();
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
/// Entry point.
|
/// Entry point.
|
||||||
fn main() -> ExitCode {
|
fn main() -> ExitCode {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user