feat: Add starship preset command (#4112)

* Add starship preset command

* Use ValueEnum for preset command

* Generate ValueEnum struct in build.rs

* Use absolute paths and refactor codegen

* Use dunce to canonicalize path

* Use raw string literal in include_bytes!

* Use .cloned()

* Apply fixes

* Fix path escaping

* Removed error message if stdout is unavailable

Co-authored-by: David Knaack <davidkna@users.noreply.github.com>

Co-authored-by: David Knaack <davidkna@users.noreply.github.com>
This commit is contained in:
Artyom Belousov 2022-08-02 12:51:15 +03:00 committed by GitHub
parent b456b9c519
commit c8a5adb412
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 137 additions and 2 deletions

View File

@ -110,6 +110,7 @@ nix = { version = "0.24.2", default-features = false, features = ["feature", "fs
[build-dependencies]
shadow-rs = "0.16.1"
dunce = "1.0.2"
[target.'cfg(windows)'.build-dependencies]
winres = "0.1.12"

View File

@ -1,7 +1,11 @@
use std::error::Error;
use std::fs::{self, File};
use std::io::Write;
fn main() -> Result<(), Box<dyn Error>> {
use shadow_rs::SdResult;
fn main() -> SdResult<()> {
shadow_rs::new().map_err(|err| err.to_string())?;
shadow_rs::new_hook(gen_presets_hook)?;
#[cfg(windows)]
{
@ -13,3 +17,55 @@ fn main() -> Result<(), Box<dyn Error>> {
Ok(())
}
fn gen_presets_hook(mut file: &File) -> SdResult<()> {
println!("cargo:rerun-if-changed=docs/.vuepress/public/presets/toml");
let paths = fs::read_dir("docs/.vuepress/public/presets/toml")?;
let mut presets = String::new();
let mut match_arms = String::new();
for path in paths {
let unwrapped = path?;
let file_name = unwrapped.file_name();
let full_path = dunce::canonicalize(unwrapped.path())?;
let full_path = full_path.to_str().expect("failed to convert to string");
let name = file_name
.to_str()
.and_then(|v| v.strip_suffix(".toml"))
.expect("Failed to process filename");
presets.push_str(format!("print::Preset(\"{}\"),\n", name).as_str());
match_arms.push_str(
format!(
r#"
"{name}" => {{
let mut stdout = io::stdout().lock();
let _ = stdout.write_all(include_bytes!(r"{full_path}"));
}}
"#
)
.as_str(),
);
}
writeln!(
file,
r#"
use std::io::{{self, Write}};
use crate::print;
pub fn get_preset_list<'a>() -> &'a [print::Preset] {{
&[
{presets}
]
}}
pub fn print_preset_content(name: &str) {{
match name {{
{match_arms}
_ => {{}}
}}
}}
"#
)?;
Ok(())
}

View File

@ -9,6 +9,10 @@ in brackets instead of using the default Starship wording ("via", "on", etc.).
### Configuration
```sh
starship preset bracketed-segments > ~/.config/starship.toml
```
[Click to download TOML](/presets/toml/bracketed-segments.toml)
<<< @/.vuepress/public/presets/toml/bracketed-segments.toml

View File

@ -12,6 +12,10 @@ This preset changes the symbols for each module to use Nerd Font symbols.
### Configuration
```sh
starship preset nerd-font-symbols > ~/.config/starship.toml
```
[Click to download TOML](/presets/toml/nerd-font-symbols.toml)
<<< @/.vuepress/public/presets/toml/nerd-font-symbols.toml

View File

@ -8,6 +8,10 @@ This preset hides the version of language runtimes. If you work in containers or
### Configuration
```sh
starship preset no-runtime-versions > ~/.config/starship.toml
```
[Click to download TOML](/presets/toml/no-runtime-versions.toml)
<<< @/.vuepress/public/presets/toml/no-runtime-versions.toml

View File

@ -13,6 +13,10 @@ It also shows how path substitution works in starship.
### Configuration
```sh
starship preset pastel-powerline > ~/.config/starship.toml
```
[Click to download TOML](/presets/toml/pastel-powerline.toml)
<<< @/.vuepress/public/presets/toml/pastel-powerline.toml

View File

@ -9,6 +9,10 @@ don't have access to Unicode.
### Configuration
```sh
starship preset plain-text-symbols > ~/.config/starship.toml
```
[Click to download TOML](/presets/toml/plain-text-symbols.toml)
<<< @/.vuepress/public/presets/toml/plain-text-symbols.toml

View File

@ -8,6 +8,10 @@ This preset emulates the look and behavior of [Pure](https://github.com/sindreso
### Configuration
```sh
starship preset pure-preset > ~/.config/starship.toml
```
[Click to download TOML](/presets/toml/pure-preset.toml)
<<< @/.vuepress/public/presets/toml/pure-preset.toml

View File

@ -63,6 +63,15 @@ enum Commands {
#[clap(flatten)]
properties: Properties,
},
/// Prints a preset config
Preset {
/// The name of preset to be printed
#[clap(required_unless_present("list"), value_enum)]
name: Option<print::Preset>,
/// List out all preset names
#[clap(short, long)]
list: bool,
},
/// Prints the computed starship configuration
PrintConfig {
/// Print the default instead of the computed config
@ -182,6 +191,7 @@ fn main() {
print::module(&module_name, properties);
}
}
Commands::Preset { name, list } => print::preset_command(name, list),
Commands::Config { name, value } => {
if let Some(name) = name {
if let Some(value) = value {

View File

@ -1,4 +1,5 @@
use ansi_term::ANSIStrings;
use clap::{PossibleValue, ValueEnum};
use rayon::prelude::*;
use std::collections::BTreeSet;
use std::fmt::{self, Debug, Write as FmtWrite};
@ -15,6 +16,7 @@ use crate::module::Module;
use crate::module::ALL_MODULES;
use crate::modules;
use crate::segment::Segment;
use crate::shadow;
pub struct Grapheme<'a>(pub &'a str);
@ -450,6 +452,35 @@ pub fn print_schema() {
println!("{}", serde_json::to_string_pretty(&schema).unwrap());
}
#[derive(Clone, Debug)]
pub struct Preset(pub &'static str);
impl ValueEnum for Preset {
fn value_variants<'a>() -> &'a [Self] {
shadow::get_preset_list()
}
fn to_possible_value<'a>(&self) -> Option<clap::PossibleValue<'a>> {
Some(PossibleValue::new(self.0))
}
}
pub fn preset_command(name: Option<Preset>, list: bool) {
if list {
println!("{}", preset_list());
return;
}
let variant = name.expect("name argument must be specified");
shadow::print_preset_content(variant.0);
}
fn preset_list() -> String {
Preset::value_variants()
.iter()
.map(|v| format!("{}\n", v.0))
.collect()
}
#[cfg(test)]
mod test {
use super::*;
@ -490,6 +521,19 @@ mod test {
assert_eq!(expected, actual);
}
#[test]
fn preset_list_returns_one_or_more_items() {
assert!(preset_list().trim().split('\n').count() > 0);
}
#[test]
fn preset_command_does_not_panic_on_correct_inputs() {
preset_command(None, true);
Preset::value_variants()
.iter()
.for_each(|v| preset_command(Some(v.clone()), false));
}
#[test]
#[cfg(feature = "config-schema")]
fn print_schema_does_not_panic() {