From dba3467deeee255a85b64bb664e6d1ea245773dd Mon Sep 17 00:00:00 2001 From: Shu Kutsuzawa Date: Sat, 4 Apr 2020 03:16:34 +0900 Subject: [PATCH] feat: Add a julia module (#1030) * add a julia module * Update docs/config/README.md Co-Authored-By: Thomas O'Donnell * fix based on https://github.com/starship/starship/pull/1030#pullrequestreview-381767326 Co-authored-by: Thomas O'Donnell --- docs/config/README.md | 26 ++++++++ src/configs/julia.rs | 23 +++++++ src/configs/mod.rs | 1 + src/configs/starship_root.rs | 1 + src/module.rs | 1 + src/modules/julia.rs | 112 +++++++++++++++++++++++++++++++++++ src/modules/mod.rs | 3 + src/utils.rs | 4 ++ 8 files changed, 171 insertions(+) create mode 100644 src/configs/julia.rs create mode 100644 src/modules/julia.rs diff --git a/docs/config/README.md b/docs/config/README.md index a76ef28e..8dec600a 100644 --- a/docs/config/README.md +++ b/docs/config/README.md @@ -107,6 +107,7 @@ prompt_order = [ "golang", "haskell", "java", + "julia", "nodejs", "php", "python", @@ -794,6 +795,31 @@ symbol = "+ " threshold = 4 ``` +## Julia + +The `julia` module shows the currently installed version of Julia. +The module will be shown if any of the following conditions are met: + +- The current directory contains a `Project.toml` file +- The current directory contains a `Manifest.toml` file +- The current directory contains a file with the `.jl` extension + +### Options + +| Variable | Default | Description | +| ---------- | ------------- | -------------------------------------------------------- | +| `symbol` | `"∴ "` | The symbol used before displaying the version of Julia. | +| `style` | `"bold purple"` | The style for the module. | +| `disabled` | `false` | Disables the `julia` module. | + +### Example + +```toml +# ~/.config/starship.toml + +[julia] +symbol = "👸 " +``` ## Kubernetes Displays the current Kubernetes context name and, if set, the namespace from diff --git a/src/configs/julia.rs b/src/configs/julia.rs new file mode 100644 index 00000000..47b32258 --- /dev/null +++ b/src/configs/julia.rs @@ -0,0 +1,23 @@ +use crate::config::{ModuleConfig, RootModuleConfig, SegmentConfig}; + +use ansi_term::{Color, Style}; +use starship_module_config_derive::ModuleConfig; + +#[derive(Clone, ModuleConfig)] +pub struct JuliaConfig<'a> { + pub symbol: SegmentConfig<'a>, + pub version: SegmentConfig<'a>, + pub style: Style, + pub disabled: bool, +} + +impl<'a> RootModuleConfig<'a> for JuliaConfig<'a> { + fn new() -> Self { + JuliaConfig { + symbol: SegmentConfig::new("∴ "), + version: SegmentConfig::default(), + style: Color::Purple.bold(), + disabled: false, + } + } +} diff --git a/src/configs/mod.rs b/src/configs/mod.rs index d1ab700b..d6110bca 100644 --- a/src/configs/mod.rs +++ b/src/configs/mod.rs @@ -19,6 +19,7 @@ pub mod hg_branch; pub mod hostname; pub mod java; pub mod jobs; +pub mod julia; pub mod kubernetes; pub mod memory_usage; pub mod nix_shell; diff --git a/src/configs/starship_root.rs b/src/configs/starship_root.rs index 642891ab..c1564254 100644 --- a/src/configs/starship_root.rs +++ b/src/configs/starship_root.rs @@ -36,6 +36,7 @@ impl<'a> RootModuleConfig<'a> for StarshipRootConfig<'a> { "golang", "haskell", "java", + "julia", "nodejs", "php", "python", diff --git a/src/module.rs b/src/module.rs index b52c7756..90bca641 100644 --- a/src/module.rs +++ b/src/module.rs @@ -31,6 +31,7 @@ pub const ALL_MODULES: &[&str] = &[ "hostname", "java", "jobs", + "julia", "kubernetes", "line_break", "memory_usage", diff --git a/src/modules/julia.rs b/src/modules/julia.rs new file mode 100644 index 00000000..aaf58bf7 --- /dev/null +++ b/src/modules/julia.rs @@ -0,0 +1,112 @@ +use super::{Context, Module, RootModuleConfig}; + +use crate::configs::julia::JuliaConfig; +use crate::utils; + +/// Creates a module with the current Julia version +/// +/// Will display the Julia version if any of the following criteria are met: +/// - Current directory contains a `Project.toml` file +/// - Current directory contains a `Manifest.toml` file +/// - Current directory contains a file with the `.jl` extension +pub fn module<'a>(context: &'a Context) -> Option> { + let is_julia_project = context + .try_begin_scan()? + .set_files(&["Project.toml", "Manifest.toml"]) + .set_extensions(&["jl"]) + .is_match(); + + if !is_julia_project { + return None; + } + + let mut module = context.new_module("julia"); + let config: JuliaConfig = JuliaConfig::try_load(module.config); + + module.set_style(config.style); + module.create_segment("symbol", &config.symbol); + + let formatted_version = + format_julia_version(&utils::exec_cmd("julia", &["--version"])?.stdout.as_str())?; + module.create_segment("version", &config.version.with_value(&formatted_version)); + + Some(module) +} + +fn format_julia_version(julia_stdout: &str) -> Option { + // julia version output looks like this: + // julia version 1.4.0 + + let version = julia_stdout + // split into ["", "1.4.0"] + .splitn(2, "julia version") + // return "1.4.0" + .nth(1)? + .split_whitespace() + .next()?; + + Some(format!("v{}", version)) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::modules::utils::test::render_module; + use ansi_term::Color; + use std::fs::File; + use std::io; + use tempfile; + + #[test] + fn folder_without_julia_file() -> io::Result<()> { + let dir = tempfile::tempdir()?; + + let actual = render_module("julia", dir.path()); + + let expected = None; + assert_eq!(expected, actual); + dir.close() + } + + #[test] + fn folder_with_julia_file() -> io::Result<()> { + let dir = tempfile::tempdir()?; + File::create(dir.path().join("hello.jl"))?.sync_all()?; + + let actual = render_module("julia", dir.path()); + + let expected = Some(format!("via {} ", Color::Purple.bold().paint("∴ v1.4.0"))); + assert_eq!(expected, actual); + dir.close() + } + + #[test] + fn folder_with_project_toml() -> io::Result<()> { + let dir = tempfile::tempdir()?; + File::create(dir.path().join("Project.toml"))?.sync_all()?; + + let actual = render_module("julia", dir.path()); + + let expected = Some(format!("via {} ", Color::Purple.bold().paint("∴ v1.4.0"))); + assert_eq!(expected, actual); + dir.close() + } + + #[test] + fn folder_with_manifest_toml() -> io::Result<()> { + let dir = tempfile::tempdir()?; + File::create(dir.path().join("Manifest.toml"))?.sync_all()?; + + let actual = render_module("julia", dir.path()); + + let expected = Some(format!("via {} ", Color::Purple.bold().paint("∴ v1.4.0"))); + assert_eq!(expected, actual); + dir.close() + } + + #[test] + fn test_format_julia_version() { + let input = "julia version 1.4.0"; + assert_eq!(format_julia_version(input), Some("v1.4.0".to_string())); + } +} diff --git a/src/modules/mod.rs b/src/modules/mod.rs index 5fd21797..167f7b63 100644 --- a/src/modules/mod.rs +++ b/src/modules/mod.rs @@ -19,6 +19,7 @@ mod hg_branch; mod hostname; mod java; mod jobs; +mod julia; mod kubernetes; mod line_break; mod memory_usage; @@ -67,6 +68,7 @@ pub fn handle<'a>(module: &str, context: &'a Context) -> Option> { "hostname" => hostname::module(context), "java" => java::module(context), "jobs" => jobs::module(context), + "julia" => julia::module(context), "kubernetes" => kubernetes::module(context), "line_break" => line_break::module(context), "memory_usage" => memory_usage::module(context), @@ -110,6 +112,7 @@ pub fn description(module: &str) -> &'static str { "hostname" => "The system hostname", "java" => "The currently installed version of Java", "jobs" => "The current number of jobs running", + "julia" => "The currently installed version of Julia", "kubernetes" => "The current Kubernetes context name and, if set, the namespace", "line_break" => "Separates the prompt into two lines", "memory_usage" => "Current system memory and swap usage", diff --git a/src/utils.rs b/src/utils.rs index 82328388..5fbc4732 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -55,6 +55,10 @@ pub fn exec_cmd(cmd: &str, args: &[&str]) -> Option { stdout: String::from("go version go1.12.1 linux/amd64"), stderr: String::default(), }), + "julia --version" => Some(CommandOutput { + stdout: String::from("julia version 1.4.0"), + stderr: String::default(), + }), "node --version" => Some(CommandOutput { stdout: String::from("v12.0.0"), stderr: String::default(),