From 8302a3ccb4f83ecea0cad834c05c9e6f003f128a Mon Sep 17 00:00:00 2001 From: David Knaack Date: Wed, 20 Jan 2021 19:01:49 +0100 Subject: [PATCH] perf(custom): evaluate command lazily (#2173) --- docs/config/README.md | 24 +++++++++--------- src/configs/custom.rs | 2 +- src/modules/custom.rs | 58 ++++++++++++++++++++++--------------------- 3 files changed, 43 insertions(+), 41 deletions(-) diff --git a/docs/config/README.md b/docs/config/README.md index 97c3095a..7cd9dcf8 100644 --- a/docs/config/README.md +++ b/docs/config/README.md @@ -2559,18 +2559,18 @@ If you have an interesting example not covered there, feel free to share it ther ### Options | Option | Default | Description | -| ------------- | ----------------------------- | -------------------------------------------------------------------------------------------------------------------------- | -| `command` | | The command whose output should be printed. The command will be passed on stdin to the shell. | -| `when` | | A shell command used as a condition to show the module. The module will be shown if the command returns a `0` status code. | -| `shell` | | [See below](#custom-command-shell) | -| `description` | `""` | The description of the module that is shown when running `starship explain`. | -| `files` | `[]` | The files that will be searched in the working directory for a match. | -| `directories` | `[]` | The directories that will be searched in the working directory for a match. | -| `extensions` | `[]` | The extensions that will be searched in the working directory for a match. | -| `symbol` | `""` | The symbol used before displaying the command output. | -| `style` | `"bold green"` | The style for the module. | -| `format` | `"[$symbol$output]($style) "` | The format for the module. | -| `disabled` | `false` | Disables this `custom` module. | +| ------------- | ------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | +| `command` | | The command whose output should be printed. The command will be passed on stdin to the shell. | +| `when` | | A shell command used as a condition to show the module. The module will be shown if the command returns a `0` status code. | +| `shell` | | [See below](#custom-command-shell) | +| `description` | `""` | The description of the module that is shown when running `starship explain`. | +| `files` | `[]` | The files that will be searched in the working directory for a match. | +| `directories` | `[]` | The directories that will be searched in the working directory for a match. | +| `extensions` | `[]` | The extensions that will be searched in the working directory for a match. | +| `symbol` | `""` | The symbol used before displaying the command output. | +| `style` | `"bold green"` | The style for the module. | +| `format` | `"[$symbol($output )]($style)"` | The format for the module. | +| `disabled` | `false` | Disables this `custom` module. | ### Variables diff --git a/src/configs/custom.rs b/src/configs/custom.rs index 315542b2..69e77819 100644 --- a/src/configs/custom.rs +++ b/src/configs/custom.rs @@ -29,7 +29,7 @@ pub struct CustomConfig<'a> { impl<'a> RootModuleConfig<'a> for CustomConfig<'a> { fn new() -> Self { CustomConfig { - format: "[$symbol$output]($style) ", + format: "[$symbol($output )]($style)", symbol: "", command: "", when: None, diff --git a/src/modules/custom.rs b/src/modules/custom.rs index d72a874b..19959ed7 100644 --- a/src/modules/custom.rs +++ b/src/modules/custom.rs @@ -46,36 +46,38 @@ pub fn module<'a>(name: &str, context: &'a Context) -> Option> { let mut module = Module::new(name, config.description, Some(toml_config)); - let output = exec_command(config.command, &config.shell.0)?; + let parsed = StringFormatter::new(config.format).and_then(|formatter| { + formatter + .map_meta(|var, _| match var { + "symbol" => Some(config.symbol), + _ => None, + }) + .map_style(|variable| match variable { + "style" => Some(Ok(config.style)), + _ => None, + }) + .map(|variable| match variable { + "output" => { + let output = exec_command(config.command, &config.shell.0)?; + let trimmed = output.trim(); - let trimmed = output.trim(); - if !trimmed.is_empty() { - let parsed = StringFormatter::new(config.format).and_then(|formatter| { - formatter - .map_meta(|var, _| match var { - "symbol" => Some(config.symbol), - _ => None, - }) - .map_style(|variable| match variable { - "style" => Some(Ok(config.style)), - _ => None, - }) - .map(|variable| match variable { - // This may result in multiple calls to `get_module_version` when a user have - // multiple `$version` variables defined in `format`. - "output" => Some(Ok(trimmed)), - _ => None, - }) - .parse(None) - }); + if trimmed.is_empty() { + None + } else { + Some(Ok(trimmed.to_string())) + } + } + _ => None, + }) + .parse(None) + }); - match parsed { - Ok(segments) => module.set_segments(segments), - Err(error) => { - log::warn!("Error in module `custom.{}`:\n{}", name, error); - } - }; - } + match parsed { + Ok(segments) => module.set_segments(segments), + Err(error) => { + log::warn!("Error in module `custom.{}`:\n{}", name, error); + } + }; let elapsed = start.elapsed(); log::trace!("Took {:?} to compute custom module {:?}", elapsed, name); module.duration = elapsed;