Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add a julia module #1030

Merged
merged 3 commits into from
Apr 3, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions docs/config/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ prompt_order = [
"golang",
"haskell",
"java",
"julia",
"nodejs",
"php",
"python",
Expand Down Expand Up @@ -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 = "👸 "

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this example may not be compliant with Julia's community standards:

do not sexualize the term "Julia" or any other aspects of the project. While "Julia" is a female name in many parts of the world, the programming language is not a person and does not have a gender.

I'd suggest using something different, e.g. "Mathematical Bold Capital J" (U+1D409):

symbol = "𝐉 "

or "Mathematical Sans-serif Bold Small J" (U+1D5F7), which looks similar to the j in Julia's logo:

symbol = "𝗷 "

WDYT?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, it would probably be best if we changed it.
I like both your suggestions, @waldyrious. Another option if the "Therefore" symbol, present in the Julia logotype and favicon: or

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The therefore symbol is actually already the default :) if I understood the code correctly, this was an example of customizing the symbol. However, the second symbol you listed is an even better match to the Julia logo! I'd suggest replacing the current default with it and using one of the J symbols I proposed as an example of customization.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The therefore symbol is actually already the default :)

Ah right. My bad. 🤦‍♂
This is what happens when I swoop into issues without reading the context. 😅

However, the second symbol you listed is an even better match to the Julia logo! I'd suggest replacing the current default with it and using one of the J symbols I proposed as an example of customization.

Sounds good to me. 👍
Would you be open to creating a PR for the change, Waldir?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh.. I didn't know https://julialang.org/community/standards/ 🙇

I will fix this as soon as possible.

```
## Kubernetes

Displays the current Kubernetes context name and, if set, the namespace from
Expand Down
23 changes: 23 additions & 0 deletions src/configs/julia.rs
Original file line number Diff line number Diff line change
@@ -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,
}
}
}
1 change: 1 addition & 0 deletions src/configs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions src/configs/starship_root.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ impl<'a> RootModuleConfig<'a> for StarshipRootConfig<'a> {
"golang",
"haskell",
"java",
"julia",
"nodejs",
"php",
"python",
Expand Down
1 change: 1 addition & 0 deletions src/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ pub const ALL_MODULES: &[&str] = &[
"hostname",
"java",
"jobs",
"julia",
"kubernetes",
"line_break",
"memory_usage",
Expand Down
112 changes: 112 additions & 0 deletions src/modules/julia.rs
Original file line number Diff line number Diff line change
@@ -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<Module<'a>> {
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<String> {
// 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()));
}
}
3 changes: 3 additions & 0 deletions src/modules/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ mod hg_branch;
mod hostname;
mod java;
mod jobs;
mod julia;
mod kubernetes;
mod line_break;
mod memory_usage;
Expand Down Expand Up @@ -67,6 +68,7 @@ pub fn handle<'a>(module: &str, context: &'a Context) -> Option<Module<'a>> {
"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),
Expand Down Expand Up @@ -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",
Expand Down
4 changes: 4 additions & 0 deletions src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ pub fn exec_cmd(cmd: &str, args: &[&str]) -> Option<CommandOutput> {
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(),
Expand Down