feat: add Raku module (#4048)
* feat: add Raku module * Update docs/config/README.md Co-authored-by: Thomas O'Donnell <andytom@users.noreply.github.com> Co-authored-by: Thomas O'Donnell <andytom@users.noreply.github.com>
This commit is contained in:
parent
73425e7417
commit
1a4fac63f7
|
@ -1091,6 +1091,31 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"raku": {
|
||||
"default": {
|
||||
"detect_extensions": [
|
||||
"p6",
|
||||
"pm6",
|
||||
"pod6",
|
||||
"raku",
|
||||
"rakumod"
|
||||
],
|
||||
"detect_files": [
|
||||
"META6.json"
|
||||
],
|
||||
"detect_folders": [],
|
||||
"disabled": false,
|
||||
"format": "via [$symbol($version-$vm_version )]($style)",
|
||||
"style": "149 bold",
|
||||
"symbol": "🦋 ",
|
||||
"version_format": "${raw}"
|
||||
},
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/RakuConfig"
|
||||
}
|
||||
]
|
||||
},
|
||||
"red": {
|
||||
"default": {
|
||||
"detect_extensions": [
|
||||
|
@ -3948,6 +3973,60 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"RakuConfig": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"format": {
|
||||
"default": "via [$symbol($version-$vm_version )]($style)",
|
||||
"type": "string"
|
||||
},
|
||||
"version_format": {
|
||||
"default": "${raw}",
|
||||
"type": "string"
|
||||
},
|
||||
"symbol": {
|
||||
"default": "🦋 ",
|
||||
"type": "string"
|
||||
},
|
||||
"style": {
|
||||
"default": "149 bold",
|
||||
"type": "string"
|
||||
},
|
||||
"disabled": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"detect_extensions": {
|
||||
"default": [
|
||||
"p6",
|
||||
"pm6",
|
||||
"pod6",
|
||||
"raku",
|
||||
"rakumod"
|
||||
],
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"detect_files": {
|
||||
"default": [
|
||||
"META6.json"
|
||||
],
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"detect_folders": {
|
||||
"default": [],
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"RedConfig": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
|
|
@ -115,6 +115,9 @@ format = '\[[$symbol($version)]($style)\]'
|
|||
[python]
|
||||
format = '\[[${symbol}${pyenv_prefix}(${version})(\($virtualenv\))]($style)\]'
|
||||
|
||||
[raku]
|
||||
format = '\[[$symbol($version-$vm_version)]($style)\]'
|
||||
|
||||
[red]
|
||||
format = '\[[$symbol($version)]($style)\]'
|
||||
|
||||
|
|
|
@ -70,6 +70,9 @@ format = 'via [$symbol]($style)'
|
|||
[python]
|
||||
format = 'via [$symbol]($style)'
|
||||
|
||||
[raku]
|
||||
format = 'via [$symbol]($style)'
|
||||
|
||||
[red]
|
||||
format = 'via [$symbol]($style)'
|
||||
|
||||
|
|
|
@ -109,6 +109,9 @@ symbol = "purs "
|
|||
[python]
|
||||
symbol = "py "
|
||||
|
||||
[raku]
|
||||
symbol = "raku "
|
||||
|
||||
[ruby]
|
||||
symbol = "rb "
|
||||
|
||||
|
|
|
@ -2928,6 +2928,45 @@ any of the following conditions are met:
|
|||
format = "with [📐 $version](blue bold) "
|
||||
```
|
||||
|
||||
## Raku
|
||||
|
||||
The `raku` module shows the currently installed version of [Raku](https://www.raku.org/).
|
||||
By default the module will be shown if any of the following conditions are met:
|
||||
|
||||
- The current directory contains a `META6.json` file
|
||||
- The current directory contains a `.p6`, `.pm6`, `.raku`, `.rakumod` or `.pod6`
|
||||
|
||||
### Options
|
||||
|
||||
| Option | Default | Description |
|
||||
| ------------------- | ------------------------------------------------ | ------------------------------------------------------------------------- |
|
||||
| `format` | `"via [$symbol($version-$vm_version )]($style)"` | The format string for the module. |
|
||||
| `version_format` | `"v${raw}"` | The version format. Available vars are `raw`, `major`, `minor`, & `patch` |
|
||||
| `symbol` | `"🦋 "` | The symbol used before displaying the version of Raku |
|
||||
| `detect_extensions` | `["p6", "pm6", "pod6", "raku", "rakumod"]` | Which extensions should trigger this module. |
|
||||
| `detect_files` | `["META6.json"]` | Which filenames should trigger this module. |
|
||||
| `detect_folders` | `[]` | Which folders should trigger this module. |
|
||||
| `style` | `"bold 149"` | The style for the module. |
|
||||
| `disabled` | `false` | Disables the `raku` module. |
|
||||
|
||||
### Variables
|
||||
|
||||
| Variable | Example | Description |
|
||||
| ---------- | ------- | ------------------------------------ |
|
||||
| version | `v6.d` | The version of `raku` |
|
||||
| vm_version | `moar` | The version of VM `raku` is built on |
|
||||
| symbol | | Mirrors the value of option `symbol` |
|
||||
| style\* | | Mirrors the value of option `style` |
|
||||
|
||||
### Example
|
||||
|
||||
```toml
|
||||
# ~/.config/starship.toml
|
||||
|
||||
[raku]
|
||||
format = "via [🦪 $version]($style) "
|
||||
```
|
||||
|
||||
## Red
|
||||
|
||||
By default the `red` module shows the currently installed version of [Red](https://www.red-lang.org/).
|
||||
|
|
|
@ -56,6 +56,7 @@ pub mod php;
|
|||
pub mod pulumi;
|
||||
pub mod purescript;
|
||||
pub mod python;
|
||||
pub mod raku;
|
||||
pub mod red;
|
||||
pub mod rlang;
|
||||
pub mod ruby;
|
||||
|
@ -198,6 +199,8 @@ pub struct FullConfig<'a> {
|
|||
#[serde(borrow)]
|
||||
python: python::PythonConfig<'a>,
|
||||
#[serde(borrow)]
|
||||
raku: raku::RakuConfig<'a>,
|
||||
#[serde(borrow)]
|
||||
red: red::RedConfig<'a>,
|
||||
#[serde(borrow)]
|
||||
rlang: rlang::RLangConfig<'a>,
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Clone, Deserialize, Serialize)]
|
||||
#[cfg_attr(feature = "config-schema", derive(schemars::JsonSchema))]
|
||||
#[serde(default)]
|
||||
pub struct RakuConfig<'a> {
|
||||
pub format: &'a str,
|
||||
pub version_format: &'a str,
|
||||
pub symbol: &'a str,
|
||||
pub style: &'a str,
|
||||
pub disabled: bool,
|
||||
pub detect_extensions: Vec<&'a str>,
|
||||
pub detect_files: Vec<&'a str>,
|
||||
pub detect_folders: Vec<&'a str>,
|
||||
}
|
||||
|
||||
impl<'a> Default for RakuConfig<'a> {
|
||||
fn default() -> Self {
|
||||
RakuConfig {
|
||||
format: "via [$symbol($version-$vm_version )]($style)",
|
||||
version_format: "${raw}",
|
||||
symbol: "🦋 ",
|
||||
style: "149 bold",
|
||||
disabled: false,
|
||||
detect_extensions: vec!["p6", "pm6", "pod6", "raku", "rakumod"],
|
||||
detect_files: vec!["META6.json"],
|
||||
detect_folders: vec![],
|
||||
}
|
||||
}
|
||||
}
|
|
@ -61,6 +61,7 @@ pub const PROMPT_ORDER: &[&str] = &[
|
|||
"pulumi",
|
||||
"purescript",
|
||||
"python",
|
||||
"raku",
|
||||
"rlang",
|
||||
"red",
|
||||
"ruby",
|
||||
|
|
|
@ -64,6 +64,7 @@ pub const ALL_MODULES: &[&str] = &[
|
|||
"pulumi",
|
||||
"purescript",
|
||||
"python",
|
||||
"raku",
|
||||
"red",
|
||||
"rlang",
|
||||
"ruby",
|
||||
|
|
|
@ -53,6 +53,7 @@ mod php;
|
|||
mod pulumi;
|
||||
mod purescript;
|
||||
mod python;
|
||||
mod raku;
|
||||
mod red;
|
||||
mod rlang;
|
||||
mod ruby;
|
||||
|
@ -145,6 +146,7 @@ pub fn handle<'a>(module: &str, context: &'a Context) -> Option<Module<'a>> {
|
|||
"pulumi" => pulumi::module(context),
|
||||
"purescript" => purescript::module(context),
|
||||
"python" => python::module(context),
|
||||
"raku" => raku::module(context),
|
||||
"rlang" => rlang::module(context),
|
||||
"red" => red::module(context),
|
||||
"ruby" => ruby::module(context),
|
||||
|
@ -248,6 +250,7 @@ pub fn description(module: &str) -> &'static str {
|
|||
"pulumi" => "The current username, stack, and installed version of Pulumi",
|
||||
"purescript" => "The currently installed version of PureScript",
|
||||
"python" => "The currently installed version of Python",
|
||||
"raku" => "The currently installed version of Raku",
|
||||
"red" => "The currently installed version of Red",
|
||||
"rlang" => "The currently installed version of R",
|
||||
"ruby" => "The currently installed version of Ruby",
|
||||
|
|
|
@ -0,0 +1,199 @@
|
|||
use super::{Context, Module, ModuleConfig};
|
||||
|
||||
use crate::configs::raku::RakuConfig;
|
||||
use crate::formatter::StringFormatter;
|
||||
use crate::formatter::VersionFormatter;
|
||||
use once_cell::sync::Lazy;
|
||||
use std::ops::Deref;
|
||||
|
||||
/// Creates a module with the current raku version
|
||||
pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||
let mut module = context.new_module("raku");
|
||||
let config: RakuConfig = RakuConfig::try_load(module.config);
|
||||
let is_raku_project = context
|
||||
.try_begin_scan()?
|
||||
.set_extensions(&config.detect_extensions)
|
||||
.set_files(&config.detect_files)
|
||||
.set_folders(&config.detect_folders)
|
||||
.is_match();
|
||||
|
||||
if !is_raku_project {
|
||||
return None;
|
||||
}
|
||||
|
||||
let versions = Lazy::new(|| get_raku_version(context));
|
||||
|
||||
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" => versions
|
||||
.deref()
|
||||
.as_ref()
|
||||
.map(|(raku_version, _)| raku_version)
|
||||
.map(|raku_version| {
|
||||
VersionFormatter::format_module_version(
|
||||
module.get_name(),
|
||||
raku_version,
|
||||
config.version_format,
|
||||
)
|
||||
})?
|
||||
.map(Ok),
|
||||
"vm_version" => versions
|
||||
.deref()
|
||||
.as_ref()
|
||||
.map(|(_, vm_version)| vm_version.to_string())
|
||||
.map(Ok),
|
||||
_ => None,
|
||||
})
|
||||
.parse(None, Some(context))
|
||||
});
|
||||
|
||||
module.set_segments(match parsed {
|
||||
Ok(segments) => segments,
|
||||
Err(error) => {
|
||||
log::warn!("Error in module `raku`:\n{}", error);
|
||||
return None;
|
||||
}
|
||||
});
|
||||
|
||||
Some(module)
|
||||
}
|
||||
|
||||
fn get_raku_version(context: &Context) -> Option<(String, String)> {
|
||||
let output = context.exec_cmd("raku", &["--version"])?.stdout;
|
||||
|
||||
parse_raku_version(&output)
|
||||
}
|
||||
|
||||
fn parse_raku_version(version: &str) -> Option<(String, String)> {
|
||||
let mut lines = version.lines();
|
||||
// skip 1st line
|
||||
let _ = lines.next()?;
|
||||
// split 2nd line into ["Implement", "the", "Raku®", ..., "v6.d."], take "v6.d."
|
||||
// get rid of the trailing "."
|
||||
let raku_version = lines
|
||||
.next()?
|
||||
.split_whitespace()
|
||||
.nth(5)?
|
||||
.strip_suffix('.')?
|
||||
.to_string();
|
||||
|
||||
// split line into ["Built", "on", "MoarVM", ...], take "MoarVM"
|
||||
// and change MoarVM to Moar (community's preference), leave other VMs as they are
|
||||
let vm_version = lines
|
||||
.next()?
|
||||
.split_whitespace()
|
||||
.nth(2)?
|
||||
.replace("MoarVM", "Moar");
|
||||
|
||||
Some((raku_version.to_lowercase(), vm_version.to_lowercase()))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::test::ModuleRenderer;
|
||||
use ansi_term::Color;
|
||||
use std::fs::File;
|
||||
use std::io;
|
||||
|
||||
#[test]
|
||||
fn test_parse_raku_version() {
|
||||
let moar_input = "\
|
||||
Welcome to Rakudo™ v2021.12.
|
||||
Implementing the Raku® Programming Language v6.d.
|
||||
Built on MoarVM version 2021.12.
|
||||
";
|
||||
let jvm_input = "\
|
||||
Welcome to Rakudo™ v2021.12.
|
||||
Implementing the Raku® Programming Language v6.d.
|
||||
Built on JVM version 2021.12.
|
||||
";
|
||||
assert_eq!(
|
||||
parse_raku_version(moar_input),
|
||||
Some(("v6.d".to_string(), "moar".to_string()))
|
||||
);
|
||||
assert_eq!(
|
||||
parse_raku_version(jvm_input),
|
||||
Some(("v6.d".to_string(), "jvm".to_string()))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn folder_without_raku_files() -> io::Result<()> {
|
||||
let dir = tempfile::tempdir()?;
|
||||
let actual = ModuleRenderer::new("raku").path(dir.path()).collect();
|
||||
let expected = None;
|
||||
assert_eq!(expected, actual);
|
||||
|
||||
dir.close()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn folder_with_meta6_json_file() -> io::Result<()> {
|
||||
let dir = tempfile::tempdir()?;
|
||||
File::create(dir.path().join("META6.json"))?.sync_all()?;
|
||||
|
||||
let actual = ModuleRenderer::new("raku").path(dir.path()).collect();
|
||||
|
||||
let expected = Some(format!(
|
||||
"via {}",
|
||||
Color::Fixed(149).bold().paint("🦋 v6.d-moar ")
|
||||
));
|
||||
assert_eq!(expected, actual);
|
||||
dir.close()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn folder_with_raku_file() -> io::Result<()> {
|
||||
let dir = tempfile::tempdir()?;
|
||||
File::create(dir.path().join("any.raku"))?.sync_all()?;
|
||||
|
||||
let actual = ModuleRenderer::new("raku").path(dir.path()).collect();
|
||||
|
||||
let expected = Some(format!(
|
||||
"via {}",
|
||||
Color::Fixed(149).bold().paint("🦋 v6.d-moar ")
|
||||
));
|
||||
assert_eq!(expected, actual);
|
||||
dir.close()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn folder_with_raku_module_file() -> io::Result<()> {
|
||||
let dir = tempfile::tempdir()?;
|
||||
File::create(dir.path().join("any.rakumod"))?.sync_all()?;
|
||||
|
||||
let actual = ModuleRenderer::new("raku").path(dir.path()).collect();
|
||||
|
||||
let expected = Some(format!(
|
||||
"via {}",
|
||||
Color::Fixed(149).bold().paint("🦋 v6.d-moar ")
|
||||
));
|
||||
assert_eq!(expected, actual);
|
||||
dir.close()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn folder_with_rakudoc_file() -> io::Result<()> {
|
||||
let dir = tempfile::tempdir()?;
|
||||
File::create(dir.path().join("any.pod6"))?.sync_all()?;
|
||||
|
||||
let actual = ModuleRenderer::new("raku").path(dir.path()).collect();
|
||||
|
||||
let expected = Some(format!(
|
||||
"via {}",
|
||||
Color::Fixed(149).bold().paint("🦋 v6.d-moar ")
|
||||
));
|
||||
assert_eq!(expected, actual);
|
||||
dir.close()
|
||||
}
|
||||
}
|
|
@ -319,6 +319,15 @@ For more information about these matters see
|
|||
https://www.gnu.org/licenses/."#
|
||||
),
|
||||
}),
|
||||
"raku --version" => Some(CommandOutput {
|
||||
stdout: String::from(
|
||||
"\
|
||||
Welcome to Rakudo™ v2021.12.
|
||||
Implementing the Raku® Programming Language v6.d.
|
||||
Built on MoarVM version 2021.12.\n",
|
||||
),
|
||||
stderr: String::default(),
|
||||
}),
|
||||
"red --version" => Some(CommandOutput {
|
||||
stdout: String::from("0.6.4\n"),
|
||||
stderr: String::default()
|
||||
|
|
Loading…
Reference in New Issue