From feb4124cacf49a6eb5ba38c91deec44a382ea3c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dario=20Vladovi=C4=87?= Date: Wed, 29 Jul 2020 17:36:49 +0200 Subject: [PATCH] feat(swift): add Swift module (#1261) --- docs/config/README.md | 37 ++++++++++++ docs/presets/README.md | 3 + src/configs/mod.rs | 1 + src/configs/starship_root.rs | 1 + src/configs/swift.rs | 22 +++++++ src/module.rs | 1 + src/modules/mod.rs | 3 + src/modules/swift.rs | 114 +++++++++++++++++++++++++++++++++++ src/utils.rs | 8 +++ 9 files changed, 190 insertions(+) create mode 100644 src/configs/swift.rs create mode 100644 src/modules/swift.rs diff --git a/docs/config/README.md b/docs/config/README.md index c551e7a5..00b5b25f 100644 --- a/docs/config/README.md +++ b/docs/config/README.md @@ -204,6 +204,7 @@ $purescript\ $python\ $ruby\ $rust\ +$swift\ $terraform\ $zig\ $nix_shell\ @@ -1876,6 +1877,42 @@ and `$SINGULARITY_NAME` is set. format = "[📦 \\[$env\\]]($style) " ``` +## Swift + +The `swift` module shows the currently installed version of Swift. +The module will be shown if any of the following conditions are met: + +- The current directory contains a `Package.swift` file +- The current directory contains a file with the `.swift` extension + +### Options + +| Option | Default | Description | +| ---------- | ---------------------------------- | ------------------------------------------------ | +| `format` | `"via [$symbol$version]($style) "` | The format for the module. | +| `symbol` | `"🐦 "` | A format string representing the symbol of Swift | +| `style` | `"bold 202"` | The style for the module. | +| `disabled` | `false` | Disables the `swift` module. | + +### Variables + +| Variable | Example | Description | +| -------- | -------- | ------------------------------------ | +| version | `v5.2.4` | The version of `swift` | +| symbol | | Mirrors the value of option `symbol` | +| style\* | | Mirrors the value of option `style` | + +\*: This variable can only be used as a part of a style string + +### Example + +```toml +# ~/.config/starship.toml + +[swift] +format = "via [🏎 $version](red bold)" +``` + ## Terraform The `terraform` module shows the currently selected terraform workspace and version. diff --git a/docs/presets/README.md b/docs/presets/README.md index a3241b09..c7989cf7 100644 --- a/docs/presets/README.md +++ b/docs/presets/README.md @@ -81,4 +81,7 @@ symbol = " " [rust] symbol = " " + +[swift] +symbol = "ﯣ " ``` diff --git a/src/configs/mod.rs b/src/configs/mod.rs index 4ccd76f7..7cf20877 100644 --- a/src/configs/mod.rs +++ b/src/configs/mod.rs @@ -38,6 +38,7 @@ pub mod ruby; pub mod rust; pub mod singularity; mod starship_root; +pub mod swift; pub mod terraform; pub mod time; pub mod username; diff --git a/src/configs/starship_root.rs b/src/configs/starship_root.rs index de6645be..b740c099 100644 --- a/src/configs/starship_root.rs +++ b/src/configs/starship_root.rs @@ -43,6 +43,7 @@ pub const PROMPT_ORDER: &[&str] = &[ "python", "ruby", "rust", + "swift", "terraform", "zig", // ↑ Toolchain version modules ↑ diff --git a/src/configs/swift.rs b/src/configs/swift.rs new file mode 100644 index 00000000..0ee7617a --- /dev/null +++ b/src/configs/swift.rs @@ -0,0 +1,22 @@ +use crate::config::{ModuleConfig, RootModuleConfig}; + +use starship_module_config_derive::ModuleConfig; + +#[derive(Clone, ModuleConfig)] +pub struct SwiftConfig<'a> { + pub format: &'a str, + pub symbol: &'a str, + pub style: &'a str, + pub disabled: bool, +} + +impl<'a> RootModuleConfig<'a> for SwiftConfig<'a> { + fn new() -> Self { + SwiftConfig { + format: "via [$symbol$version]($style) ", + symbol: "🐦 ", + style: "bold 202", + disabled: false, + } + } +} diff --git a/src/module.rs b/src/module.rs index 7293c17e..3f33c9d2 100644 --- a/src/module.rs +++ b/src/module.rs @@ -47,6 +47,7 @@ pub const ALL_MODULES: &[&str] = &[ "crystal", "rust", "php", + "swift", "terraform", "singularity", "time", diff --git a/src/modules/mod.rs b/src/modules/mod.rs index ed171339..06ae9673 100644 --- a/src/modules/mod.rs +++ b/src/modules/mod.rs @@ -38,6 +38,7 @@ mod python; mod ruby; mod rust; mod singularity; +mod swift; mod terraform; mod time; mod username; @@ -94,6 +95,7 @@ pub fn handle<'a>(module: &str, context: &'a Context) -> Option> { "ruby" => ruby::module(context), "rust" => rust::module(context), "singularity" => singularity::module(context), + "swift" => swift::module(context), "terraform" => terraform::module(context), "time" => time::module(context), "crystal" => crystal::module(context), @@ -146,6 +148,7 @@ pub fn description(module: &str) -> &'static str { "python" => "The currently installed version of Python", "ruby" => "The currently installed version of Ruby", "rust" => "The currently installed version of Rust", + "swift" => "The currently installed version of Swift", "terraform" => "The currently selected terraform workspace and version", "time" => "The current local time", "username" => "The active user's username", diff --git a/src/modules/swift.rs b/src/modules/swift.rs new file mode 100644 index 00000000..b83bce1d --- /dev/null +++ b/src/modules/swift.rs @@ -0,0 +1,114 @@ +use super::{Context, Module, RootModuleConfig}; + +use crate::configs::swift::SwiftConfig; +use crate::formatter::StringFormatter; +use crate::utils; + +/// Creates a module with the current Swift version +/// +/// Will display the Swift version if any of the following criteria are met: +/// - The current directory contains a `Package.swift` file +/// - The current directory contains a file with extension `.swift` +pub fn module<'a>(context: &'a Context) -> Option> { + let is_swift_project = context + .try_begin_scan()? + .set_extensions(&["swift"]) + .is_match(); + + if !is_swift_project { + return None; + } + + let swift_version = utils::exec_cmd("swift", &["--version"])?.stdout; + + let mut module = context.new_module("swift"); + let config: SwiftConfig = SwiftConfig::try_load(module.config); + + 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 { + "version" => parse_swift_version(&swift_version).map(Ok), + _ => None, + }) + .parse(None) + }); + + module.set_segments(match parsed { + Ok(segments) => segments, + Err(error) => { + log::warn!("Error in module `swift`:\n{}", error); + return None; + } + }); + + Some(module) +} + +fn parse_swift_version(swift_version: &str) -> Option { + let version = swift_version + // split into ["Apple", "Swift", "version", "5.2.2", ...] + .split_whitespace() + // return "5.2.2" + .nth(3)?; + + Some(format!("v{}", version)) +} + +#[cfg(test)] +mod tests { + use super::parse_swift_version; + use crate::modules::utils::test::render_module; + use ansi_term::Color; + use std::fs::File; + use std::io; + + #[test] + fn test_parse_swift_version() { + let input = "Apple Swift version 5.2.2"; + assert_eq!(parse_swift_version(input), Some(String::from("v5.2.2"))); + } + + #[test] + fn folder_without_swift_files() -> io::Result<()> { + let dir = tempfile::tempdir()?; + File::create(dir.path().join("swift.txt"))?.sync_all()?; + let actual = render_module("swift", dir.path(), None); + let expected = None; + assert_eq!(expected, actual); + dir.close() + } + + #[test] + fn folder_with_package_file() -> io::Result<()> { + let dir = tempfile::tempdir()?; + File::create(dir.path().join("Package.swift"))?.sync_all()?; + let actual = render_module("swift", dir.path(), None); + let expected = Some(format!( + "via {} ", + Color::Fixed(202).bold().paint("🐦 v5.2.2") + )); + assert_eq!(expected, actual); + dir.close() + } + + #[test] + fn folder_with_swift_file() -> io::Result<()> { + let dir = tempfile::tempdir()?; + File::create(dir.path().join("main.swift"))?.sync_all()?; + let actual = render_module("swift", dir.path(), None); + let expected = Some(format!( + "via {} ", + Color::Fixed(202).bold().paint("🐦 v5.2.2") + )); + assert_eq!(expected, actual); + dir.close() + } +} diff --git a/src/utils.rs b/src/utils.rs index edca4609..18cd34a1 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -123,6 +123,14 @@ active boot switches: -d:release\n", stdout: String::from("ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-linux-gnu]\n"), stderr: String::default(), }), + "swift --version" => Some(CommandOutput { + stdout: String::from( + "\ +Apple Swift version 5.2.2 (swiftlang-1103.0.32.6 clang-1103.0.32.51) +Target: x86_64-apple-darwin19.4.0\n", + ), + stderr: String::default(), + }), "zig version" => Some(CommandOutput { stdout: String::from("0.6.0\n"), stderr: String::default(),