feat(config): Adds support for --profile <custom profile name> (#3467)

Co-authored-by: Kevin Song <chips@ksong.dev>
Co-authored-by: David Knaack <davidkna@users.noreply.github.com>
This commit is contained in:
Florent Vilmart 2023-01-11 22:25:36 -05:00 committed by GitHub
parent bb549e665e
commit 10433e31ef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 115 additions and 20 deletions

View File

@ -1744,6 +1744,13 @@
"type": "string" "type": "string"
} }
} }
},
"profiles": {
"default": {},
"type": "object",
"additionalProperties": {
"type": "string"
}
} }
}, },
"additionalProperties": false, "additionalProperties": false,

View File

@ -1,3 +1,4 @@
use indexmap::IndexMap;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::collections::HashMap; use std::collections::HashMap;
@ -20,6 +21,7 @@ pub struct StarshipRootConfig {
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub palette: Option<String>, pub palette: Option<String>,
pub palettes: HashMap<String, Palette>, pub palettes: HashMap<String, Palette>,
pub profiles: IndexMap<String, String>,
} }
pub type Palette = HashMap<String, String>; pub type Palette = HashMap<String, String>;
@ -125,6 +127,7 @@ impl Default for StarshipRootConfig {
format: "$all".to_string(), format: "$all".to_string(),
right_format: String::new(), right_format: String::new(),
continuation_prompt: "[∙](bright-black) ".to_string(), continuation_prompt: "[∙](bright-black) ".to_string(),
profiles: Default::default(),
scan_timeout: 30, scan_timeout: 30,
command_timeout: 500, command_timeout: 500,
add_newline: true, add_newline: true,

View File

@ -647,11 +647,12 @@ pub enum Shell {
} }
/// Which kind of prompt target to print (main prompt, rprompt, ...) /// Which kind of prompt target to print (main prompt, rprompt, ...)
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub enum Target { pub enum Target {
Main, Main,
Right, Right,
Continuation, Continuation,
Profile(String),
} }
/// Properties as passed on from the shell as arguments /// Properties as passed on from the shell as arguments

View File

@ -85,8 +85,11 @@ enum Commands {
/// Print the right prompt (instead of the standard left prompt) /// Print the right prompt (instead of the standard left prompt)
#[clap(long)] #[clap(long)]
right: bool, right: bool,
/// Print the continuation prompt (instead of the standard left prompt) /// Print the prompt with the specified profile name (instead of the standard left prompt)
#[clap(long, conflicts_with = "right")] #[clap(long, conflicts_with = "right")]
profile: Option<String>,
/// Print the continuation prompt (instead of the standard left prompt)
#[clap(long, conflicts_with = "right", conflicts_with = "profile")]
continuation: bool, continuation: bool,
#[clap(flatten)] #[clap(flatten)]
properties: Properties, properties: Properties,
@ -172,12 +175,14 @@ fn main() {
Commands::Prompt { Commands::Prompt {
properties, properties,
right, right,
profile,
continuation, continuation,
} => { } => {
let target = match (right, continuation) { let target = match (right, profile, continuation) {
(true, _) => Target::Right, (true, _, _) => Target::Right,
(_, true) => Target::Continuation, (_, Some(profile_name), _) => Target::Profile(profile_name),
(_, _) => Target::Main, (_, _, true) => Target::Continuation,
(_, _, _) => Target::Main,
}; };
print::prompt(properties, target) print::prompt(properties, target)
} }

View File

@ -11,6 +11,7 @@ use unicode_width::UnicodeWidthChar;
use crate::configs::PROMPT_ORDER; use crate::configs::PROMPT_ORDER;
use crate::context::{Context, Properties, Shell, Target}; use crate::context::{Context, Properties, Shell, Target};
use crate::formatter::string_formatter::StringFormatterError;
use crate::formatter::{StringFormatter, VariableHolder}; use crate::formatter::{StringFormatter, VariableHolder};
use crate::module::Module; use crate::module::Module;
use crate::module::ALL_MODULES; use crate::module::ALL_MODULES;
@ -403,32 +404,42 @@ fn all_modules_uniq(module_list: &BTreeSet<String>) -> Vec<String> {
/// and the list of all modules used in a format string /// and the list of all modules used in a format string
fn load_formatter_and_modules<'a>(context: &'a Context) -> (StringFormatter<'a>, BTreeSet<String>) { fn load_formatter_and_modules<'a>(context: &'a Context) -> (StringFormatter<'a>, BTreeSet<String>) {
let config = &context.root_config; let config = &context.root_config;
let (formatter, config_param) = match &context.target {
Target::Main => (StringFormatter::new(&config.format), "format".to_string()),
Target::Right => (
StringFormatter::new(&config.right_format),
"right_format".to_string(),
),
Target::Continuation => (
StringFormatter::new(&config.continuation_prompt),
"continuation_prompt".to_string(),
),
Target::Profile(name) => (
match config.profiles.get(name) {
Some(format) => StringFormatter::new(format),
_ => Err(StringFormatterError::Custom("Invalid Profile".to_string())),
},
format!("profile: {}", &name),
),
};
let lformatter = StringFormatter::new(&config.format);
let rformatter = StringFormatter::new(&config.right_format); let rformatter = StringFormatter::new(&config.right_format);
let cformatter = StringFormatter::new(&config.continuation_prompt);
if lformatter.is_err() { if formatter.is_err() {
log::error!("Error parsing `format`") log::error!("Error parsing `{}`", config_param);
} }
if rformatter.is_err() { if rformatter.is_err() {
log::error!("Error parsing `right_format`") log::error!("Error parsing `right_format`")
} }
if cformatter.is_err() {
log::error!("Error parsing `continuation_prompt`")
}
match (lformatter, rformatter, cformatter) { match (formatter, rformatter) {
(Ok(lf), Ok(rf), Ok(cf)) => { (Ok(lf), Ok(rf)) => {
let mut modules: BTreeSet<String> = BTreeSet::new(); let mut modules: BTreeSet<String> = BTreeSet::new();
if context.target != Target::Continuation { if context.target != Target::Continuation {
modules.extend(lf.get_variables()); modules.extend(lf.get_variables());
modules.extend(rf.get_variables()); modules.extend(rf.get_variables());
} }
match context.target { (lf, modules)
Target::Main => (lf, modules),
Target::Right => (rf, modules),
Target::Continuation => (cf, modules),
}
} }
_ => (StringFormatter::raw(">"), BTreeSet::new()), _ => (StringFormatter::raw(">"), BTreeSet::new()),
} }
@ -475,6 +486,26 @@ mod test {
use crate::config::StarshipConfig; use crate::config::StarshipConfig;
use crate::test::default_context; use crate::test::default_context;
#[test]
fn main_prompt() {
let mut context = default_context();
context.config = StarshipConfig {
config: Some(toml::toml! {
add_newline=false
format="$character"
[character]
format=">\n>"
}),
};
context.root_config.format = "$character".to_string();
context.target = Target::Main;
context.root_config.add_newline = false;
let expected = String::from(">\n>");
let actual = get_prompt(context);
assert_eq!(expected, actual);
}
#[test] #[test]
fn right_prompt() { fn right_prompt() {
let mut context = default_context(); let mut context = default_context();
@ -493,6 +524,54 @@ mod test {
assert_eq!(expected, actual); assert_eq!(expected, actual);
} }
#[test]
fn custom_prompt() {
let mut context = default_context();
context.config = StarshipConfig {
config: Some(toml::toml! {
add_newline = false
[profiles]
test="0_0$character"
[character]
format=">>"
}),
};
context
.root_config
.profiles
.insert("test".to_string(), "0_0$character".to_string());
context.target = Target::Profile("test".to_string());
context.root_config.add_newline = false;
let expected = String::from("0_0>>");
let actual = get_prompt(context);
assert_eq!(expected, actual);
}
#[test]
fn custom_prompt_fallback() {
let mut context = default_context();
context.config = StarshipConfig {
config: Some(toml::toml! {
add_newline=false
[profiles]
test="0_0$character"
[character]
format=">>"
}),
};
context
.root_config
.profiles
.insert("test".to_string(), "0_0$character".to_string());
context.target = Target::Profile("wrong_prompt".to_string());
context.root_config.add_newline = false;
let expected = String::from(">");
let actual = get_prompt(context);
assert_eq!(expected, actual);
}
#[test] #[test]
fn continuation_prompt() { fn continuation_prompt() {
let mut context = default_context(); let mut context = default_context();