feat: add Haxe support (#4395)
* Add Haxe support * avoid unwrap * fix doc formatting * removed extra newline * fixed formatter and linter issues * fixed config file * better version of detecting contents of .haxerc Co-authored-by: David Knaack <davidkna@users.noreply.github.com> * removed openfl related defaults from detect_files Co-authored-by: David Knaack <davidkna@users.noreply.github.com> * fixed formatting * reworked reading .haxerc with fallback to haxe --version * fixed formatting * added fallback to executable for dev paths in .haxerc * fixed linter issue * added support for Windows paths * use or_else Co-authored-by: David Knaack <davidkna@users.noreply.github.com> * use shorter version with `?` Co-authored-by: David Knaack <davidkna@users.noreply.github.com> * simplified regex check removed check for "null" string * fixed format Co-authored-by: David Knaack <davidkna@users.noreply.github.com>
This commit is contained in:
parent
ef83e7a092
commit
2766c78749
|
@ -658,6 +658,33 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"haxe": {
|
||||
"default": {
|
||||
"detect_extensions": [
|
||||
"hx",
|
||||
"hxml"
|
||||
],
|
||||
"detect_files": [
|
||||
"haxelib.json",
|
||||
"hxformat.json",
|
||||
".haxerc"
|
||||
],
|
||||
"detect_folders": [
|
||||
".haxelib",
|
||||
"haxe_libraries"
|
||||
],
|
||||
"disabled": false,
|
||||
"format": "via [$symbol($version )]($style)",
|
||||
"style": "bold fg:202",
|
||||
"symbol": "⌘ ",
|
||||
"version_format": "v${raw}"
|
||||
},
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/HaxeConfig"
|
||||
}
|
||||
]
|
||||
},
|
||||
"helm": {
|
||||
"default": {
|
||||
"detect_extensions": [],
|
||||
|
@ -3238,6 +3265,63 @@
|
|||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"HaxeConfig": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"format": {
|
||||
"default": "via [$symbol($version )]($style)",
|
||||
"type": "string"
|
||||
},
|
||||
"version_format": {
|
||||
"default": "v${raw}",
|
||||
"type": "string"
|
||||
},
|
||||
"symbol": {
|
||||
"default": "⌘ ",
|
||||
"type": "string"
|
||||
},
|
||||
"style": {
|
||||
"default": "bold fg:202",
|
||||
"type": "string"
|
||||
},
|
||||
"disabled": {
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"detect_extensions": {
|
||||
"default": [
|
||||
"hx",
|
||||
"hxml"
|
||||
],
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"detect_files": {
|
||||
"default": [
|
||||
"haxelib.json",
|
||||
"hxformat.json",
|
||||
".haxerc"
|
||||
],
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"detect_folders": {
|
||||
"default": [
|
||||
".haxelib",
|
||||
"haxe_libraries"
|
||||
],
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"HelmConfig": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
|
|
@ -64,6 +64,9 @@ format = '\[[$symbol]($style)\]'
|
|||
[haskell]
|
||||
format = '\[[$symbol($version)]($style)\]'
|
||||
|
||||
[haxe]
|
||||
format = '\[[$symbol($version)]($style)\]'
|
||||
|
||||
[helm]
|
||||
format = '\[[$symbol($version)]($style)\]'
|
||||
|
||||
|
|
|
@ -37,6 +37,9 @@ symbol = " "
|
|||
[haskell]
|
||||
symbol = " "
|
||||
|
||||
[haxe]
|
||||
symbol = "⌘ "
|
||||
|
||||
[hg_branch]
|
||||
symbol = " "
|
||||
|
||||
|
|
|
@ -37,6 +37,9 @@ format = 'via [$symbol]($style)'
|
|||
[golang]
|
||||
format = 'via [$symbol]($style)'
|
||||
|
||||
[haxe]
|
||||
format = 'via [$symbol]($style)'
|
||||
|
||||
[helm]
|
||||
format = 'via [$symbol]($style)'
|
||||
|
||||
|
|
|
@ -286,6 +286,7 @@ $erlang\
|
|||
$golang\
|
||||
$guix_shell\
|
||||
$haskell\
|
||||
$haxe\
|
||||
$helm\
|
||||
$java\
|
||||
$julia\
|
||||
|
@ -1959,6 +1960,47 @@ By default the module will be shown if any of the following conditions are met:
|
|||
|
||||
*: This variable can only be used as a part of a style string
|
||||
|
||||
## Haxe
|
||||
|
||||
The `haxe` module shows the currently installed version of [Haxe](https://haxe.org/).
|
||||
By default the module will be shown if any of the following conditions are met:
|
||||
|
||||
- The current directory contains a `project.xml`, `Project.xml`, `application.xml`, `haxelib.json`, `hxformat.json` or `.haxerc` file
|
||||
- The current directory contains a `.haxelib` or a `haxe_libraries` directory
|
||||
- The current directory contains a file with the `.hx` or `.hxml` extension
|
||||
|
||||
### Options
|
||||
|
||||
| Option | Default | Description |
|
||||
| ------------------- | ----------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- |
|
||||
| `format` | `"via [$symbol($version )]($style)"` | The format for the module. |
|
||||
| `version_format` | `"v${raw}"` | The version format. Available vars are `raw`, `major`, `minor`, & `patch` |
|
||||
| `detect_extensions` | `["hx", "hxml"]` | Which extensions should trigger this module. |
|
||||
| `detect_files` | `["project.xml", "Project.xml", "application.xml", "haxelib.json", "hxformat.json", ".haxerc"]` | Which filenames should trigger this module. |
|
||||
| `detect_folders` | `[".haxelib", "haxe_libraries"]` | Which folders should trigger this modules. |
|
||||
| `symbol` | `"⌘ "` | A format string representing the symbol of Helm. |
|
||||
| `style` | `"bold fg:202"` | The style for the module. |
|
||||
| `disabled` | `false` | Disables the `haxe` module. |
|
||||
|
||||
### Variables
|
||||
|
||||
| Variable | Example | Description |
|
||||
| -------- | -------- | ------------------------------------ |
|
||||
| version | `v4.2.5` | The version of `haxe` |
|
||||
| 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
|
||||
|
||||
[haxe]
|
||||
format = "via [⌘ $version](bold fg:202) "
|
||||
```
|
||||
|
||||
## Helm
|
||||
|
||||
The `helm` module shows the currently installed version of [Helm](https://helm.sh/).
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Clone, Deserialize, Serialize)]
|
||||
#[cfg_attr(
|
||||
feature = "config-schema",
|
||||
derive(schemars::JsonSchema),
|
||||
schemars(deny_unknown_fields)
|
||||
)]
|
||||
#[serde(default)]
|
||||
pub struct HaxeConfig<'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 HaxeConfig<'a> {
|
||||
fn default() -> Self {
|
||||
HaxeConfig {
|
||||
format: "via [$symbol($version )]($style)",
|
||||
version_format: "v${raw}",
|
||||
symbol: "⌘ ",
|
||||
style: "bold fg:202",
|
||||
disabled: false,
|
||||
detect_extensions: vec!["hx", "hxml"],
|
||||
detect_files: vec!["haxelib.json", "hxformat.json", ".haxerc"],
|
||||
detect_folders: vec![".haxelib", "haxe_libraries"],
|
||||
}
|
||||
}
|
||||
}
|
|
@ -35,6 +35,7 @@ pub mod git_status;
|
|||
pub mod go;
|
||||
pub mod guix_shell;
|
||||
pub mod haskell;
|
||||
pub mod haxe;
|
||||
pub mod helm;
|
||||
pub mod hg_branch;
|
||||
pub mod hostname;
|
||||
|
@ -167,6 +168,8 @@ pub struct FullConfig<'a> {
|
|||
#[serde(borrow)]
|
||||
haskell: haskell::HaskellConfig<'a>,
|
||||
#[serde(borrow)]
|
||||
haxe: haxe::HaxeConfig<'a>,
|
||||
#[serde(borrow)]
|
||||
helm: helm::HelmConfig<'a>,
|
||||
#[serde(borrow)]
|
||||
hg_branch: hg_branch::HgBranchConfig<'a>,
|
||||
|
|
|
@ -59,6 +59,7 @@ pub const PROMPT_ORDER: &[&str] = &[
|
|||
"erlang",
|
||||
"golang",
|
||||
"haskell",
|
||||
"haxe",
|
||||
"helm",
|
||||
"java",
|
||||
"julia",
|
||||
|
|
|
@ -43,6 +43,7 @@ pub const ALL_MODULES: &[&str] = &[
|
|||
"golang",
|
||||
"guix_shell",
|
||||
"haskell",
|
||||
"haxe",
|
||||
"helm",
|
||||
"hg_branch",
|
||||
"hostname",
|
||||
|
|
|
@ -0,0 +1,315 @@
|
|||
use super::{Context, Module, ModuleConfig};
|
||||
|
||||
use crate::configs::haxe::HaxeConfig;
|
||||
use crate::formatter::StringFormatter;
|
||||
use crate::formatter::VersionFormatter;
|
||||
use serde_json as json;
|
||||
|
||||
use regex::Regex;
|
||||
const HAXERC_VERSION_PATTERN: &str = "(?:[0-9a-zA-Z][-+0-9.a-zA-Z]+)";
|
||||
|
||||
/// Creates a module with the current Haxe version
|
||||
pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||
let mut module = context.new_module("haxe");
|
||||
let config = HaxeConfig::try_load(module.config);
|
||||
|
||||
let is_haxe_project = context
|
||||
.try_begin_scan()?
|
||||
.set_files(&config.detect_files)
|
||||
.set_extensions(&config.detect_extensions)
|
||||
.set_folders(&config.detect_folders)
|
||||
.is_match();
|
||||
|
||||
if !is_haxe_project {
|
||||
return None;
|
||||
}
|
||||
|
||||
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" => {
|
||||
let haxe_version = get_haxe_version(context)?;
|
||||
VersionFormatter::format_module_version(
|
||||
module.get_name(),
|
||||
&haxe_version,
|
||||
config.version_format,
|
||||
)
|
||||
.map(Ok)
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
.parse(None, Some(context))
|
||||
});
|
||||
|
||||
module.set_segments(match parsed {
|
||||
Ok(segments) => segments,
|
||||
Err(error) => {
|
||||
log::warn!("Error in module `haxe`:\n{}", error);
|
||||
return None;
|
||||
}
|
||||
});
|
||||
|
||||
Some(module)
|
||||
}
|
||||
|
||||
fn get_haxe_version(context: &Context) -> Option<String> {
|
||||
get_haxerc_version(context).or_else(|| {
|
||||
let cmd_output = context.exec_cmd("haxe", &["--version"])?;
|
||||
parse_haxe_version(cmd_output.stdout.as_str())
|
||||
})
|
||||
}
|
||||
|
||||
fn get_haxerc_version(context: &Context) -> Option<String> {
|
||||
let raw_json = context.read_file_from_pwd(".haxerc")?;
|
||||
let package_json: json::Value = json::from_str(&raw_json).ok()?;
|
||||
|
||||
let raw_version = package_json.get("version")?.as_str()?;
|
||||
if raw_version.contains('/') || raw_version.contains('\\') {
|
||||
return None;
|
||||
}
|
||||
Some(raw_version.to_string())
|
||||
}
|
||||
|
||||
fn parse_haxe_version(raw_version: &str) -> Option<String> {
|
||||
let re = Regex::new(HAXERC_VERSION_PATTERN).ok()?;
|
||||
if !re.is_match(raw_version) {
|
||||
return None;
|
||||
}
|
||||
Some(raw_version.trim().to_string())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::parse_haxe_version;
|
||||
use crate::{test::ModuleRenderer, utils::CommandOutput};
|
||||
use nu_ansi_term::Color;
|
||||
use serde_json as json;
|
||||
use std::fs::File;
|
||||
use std::io;
|
||||
use std::io::Write;
|
||||
use tempfile::TempDir;
|
||||
|
||||
#[test]
|
||||
fn haxe_version() {
|
||||
let ok_versions = [
|
||||
"4.2.5",
|
||||
"4.3.0-rc.1+",
|
||||
"3.4.7abcdf",
|
||||
"779b005",
|
||||
"beta",
|
||||
"alpha",
|
||||
"latest",
|
||||
"/git/779b005/bin/haxe",
|
||||
"git/779b005/bin/haxe",
|
||||
];
|
||||
|
||||
let all_some = ok_versions.iter().all(|&v| parse_haxe_version(v).is_some());
|
||||
|
||||
assert!(all_some);
|
||||
|
||||
let sample_haxe_output = "4.3.0-rc.1+\n";
|
||||
|
||||
assert_eq!(
|
||||
Some("4.3.0-rc.1+".to_string()),
|
||||
parse_haxe_version(sample_haxe_output)
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn folder_without_haxe() -> io::Result<()> {
|
||||
let dir = tempfile::tempdir()?;
|
||||
File::create(dir.path().join("haxe.txt"))?.sync_all()?;
|
||||
let actual = ModuleRenderer::new("haxe")
|
||||
.cmd(
|
||||
"haxe --version",
|
||||
Some(CommandOutput {
|
||||
stdout: "4.3.0-rc.1+\n".to_owned(),
|
||||
stderr: "".to_owned(),
|
||||
}),
|
||||
)
|
||||
.path(dir.path())
|
||||
.collect();
|
||||
let expected = None;
|
||||
assert_eq!(expected, actual);
|
||||
dir.close()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn folder_with_hxml_file() -> io::Result<()> {
|
||||
let dir = tempfile::tempdir()?;
|
||||
File::create(dir.path().join("build.hxml"))?.sync_all()?;
|
||||
let actual = ModuleRenderer::new("haxe")
|
||||
.cmd(
|
||||
"haxe --version",
|
||||
Some(CommandOutput {
|
||||
stdout: "4.3.0-rc.1+\n".to_owned(),
|
||||
stderr: "".to_owned(),
|
||||
}),
|
||||
)
|
||||
.path(dir.path())
|
||||
.collect();
|
||||
let expected = Some(format!(
|
||||
"via {}",
|
||||
Color::Fixed(202).bold().paint("⌘ v4.3.0-rc.1+ ")
|
||||
));
|
||||
assert_eq!(expected, actual);
|
||||
dir.close()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn folder_with_haxe_file() -> io::Result<()> {
|
||||
let dir = tempfile::tempdir()?;
|
||||
File::create(dir.path().join("Main.hx"))?.sync_all()?;
|
||||
let actual = ModuleRenderer::new("haxe")
|
||||
.cmd(
|
||||
"haxe --version",
|
||||
Some(CommandOutput {
|
||||
stdout: "4.3.0-rc.1+\n".to_owned(),
|
||||
stderr: "".to_owned(),
|
||||
}),
|
||||
)
|
||||
.path(dir.path())
|
||||
.collect();
|
||||
let expected = Some(format!(
|
||||
"via {}",
|
||||
Color::Fixed(202).bold().paint("⌘ v4.3.0-rc.1+ ")
|
||||
));
|
||||
assert_eq!(expected, actual);
|
||||
dir.close()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn folder_with_invalid_haxerc_file() -> io::Result<()> {
|
||||
let dir = tempfile::tempdir()?;
|
||||
|
||||
let haxerc_name = ".haxerc";
|
||||
let haxerc_content = json::json!({
|
||||
"resolveLibs": "scoped"
|
||||
})
|
||||
.to_string();
|
||||
fill_config(&dir, haxerc_name, Some(&haxerc_content))?;
|
||||
let actual = ModuleRenderer::new("haxe")
|
||||
.cmd(
|
||||
"haxe --version",
|
||||
Some(CommandOutput {
|
||||
stdout: "4.3.0-rc.1+\n".to_owned(),
|
||||
stderr: "".to_owned(),
|
||||
}),
|
||||
)
|
||||
.path(dir.path())
|
||||
.collect();
|
||||
let expected = Some(format!(
|
||||
"via {}",
|
||||
Color::Fixed(202).bold().paint("⌘ v4.3.0-rc.1+ ")
|
||||
));
|
||||
assert_eq!(expected, actual);
|
||||
dir.close()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn folder_with_haxerc_file() -> io::Result<()> {
|
||||
let dir = tempfile::tempdir()?;
|
||||
|
||||
let haxerc_name = ".haxerc";
|
||||
let haxerc_content = json::json!({
|
||||
"version": "4.2.5",
|
||||
"resolveLibs": "scoped"
|
||||
})
|
||||
.to_string();
|
||||
fill_config(&dir, haxerc_name, Some(&haxerc_content))?;
|
||||
let actual = ModuleRenderer::new("haxe")
|
||||
.cmd(
|
||||
"haxe --version",
|
||||
Some(CommandOutput {
|
||||
stdout: "4.3.0-rc.1+\n".to_owned(),
|
||||
stderr: "".to_owned(),
|
||||
}),
|
||||
)
|
||||
.path(dir.path())
|
||||
.collect();
|
||||
let expected = Some(format!(
|
||||
"via {}",
|
||||
Color::Fixed(202).bold().paint("⌘ v4.2.5 ")
|
||||
));
|
||||
assert_eq!(expected, actual);
|
||||
dir.close()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn folder_with_haxerc_nightly_file() -> io::Result<()> {
|
||||
let dir = tempfile::tempdir()?;
|
||||
|
||||
let haxerc_name = ".haxerc";
|
||||
let haxerc_content = json::json!({
|
||||
"version": "779b005",
|
||||
"resolveLibs": "scoped"
|
||||
})
|
||||
.to_string();
|
||||
|
||||
fill_config(&dir, haxerc_name, Some(&haxerc_content))?;
|
||||
let actual = ModuleRenderer::new("haxe")
|
||||
.cmd(
|
||||
"haxe --version",
|
||||
Some(CommandOutput {
|
||||
stdout: "4.3.0-rc.1+\n".to_owned(),
|
||||
stderr: "".to_owned(),
|
||||
}),
|
||||
)
|
||||
.path(dir.path())
|
||||
.collect();
|
||||
let expected = Some(format!(
|
||||
"via {}",
|
||||
Color::Fixed(202).bold().paint("⌘ v779b005 ")
|
||||
));
|
||||
assert_eq!(expected, actual);
|
||||
dir.close()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn folder_with_haxerc_with_path() -> io::Result<()> {
|
||||
let dir = tempfile::tempdir()?;
|
||||
|
||||
let haxerc_name = ".haxerc";
|
||||
let haxerc_content = json::json!({
|
||||
"version": "/home/git/haxe/haxe.executable",
|
||||
"resolveLibs": "scoped"
|
||||
})
|
||||
.to_string();
|
||||
|
||||
fill_config(&dir, haxerc_name, Some(&haxerc_content))?;
|
||||
let actual = ModuleRenderer::new("haxe")
|
||||
.cmd(
|
||||
"haxe --version",
|
||||
Some(CommandOutput {
|
||||
stdout: "4.3.0-rc.1+\n".to_owned(),
|
||||
stderr: "".to_owned(),
|
||||
}),
|
||||
)
|
||||
.path(dir.path())
|
||||
.collect();
|
||||
let expected = Some(format!(
|
||||
"via {}",
|
||||
Color::Fixed(202).bold().paint("⌘ v4.3.0-rc.1+ ")
|
||||
));
|
||||
assert_eq!(expected, actual);
|
||||
dir.close()
|
||||
}
|
||||
|
||||
fn fill_config(
|
||||
project_dir: &TempDir,
|
||||
file_name: &str,
|
||||
contents: Option<&str>,
|
||||
) -> io::Result<()> {
|
||||
let mut file = File::create(project_dir.path().join(file_name))?;
|
||||
file.write_all(contents.unwrap_or("").as_bytes())?;
|
||||
file.sync_all()
|
||||
}
|
||||
}
|
|
@ -32,6 +32,7 @@ mod git_status;
|
|||
mod golang;
|
||||
mod guix_shell;
|
||||
mod haskell;
|
||||
mod haxe;
|
||||
mod helm;
|
||||
mod hg_branch;
|
||||
mod hostname;
|
||||
|
@ -130,6 +131,7 @@ pub fn handle<'a>(module: &str, context: &'a Context) -> Option<Module<'a>> {
|
|||
"golang" => golang::module(context),
|
||||
"guix_shell" => guix_shell::module(context),
|
||||
"haskell" => haskell::module(context),
|
||||
"haxe" => haxe::module(context),
|
||||
"helm" => helm::module(context),
|
||||
"hg_branch" => hg_branch::module(context),
|
||||
"hostname" => hostname::module(context),
|
||||
|
@ -239,6 +241,7 @@ pub fn description(module: &str) -> &'static str {
|
|||
"golang" => "The currently installed version of Golang",
|
||||
"guix_shell" => "The guix-shell environment",
|
||||
"haskell" => "The selected version of the Haskell toolchain",
|
||||
"haxe" => "The currently installed version of Haxe",
|
||||
"helm" => "The currently installed version of Helm",
|
||||
"hg_branch" => "The active branch of the repo in your current directory",
|
||||
"hostname" => "The system hostname",
|
||||
|
|
Loading…
Reference in New Issue