summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormarcybell <marcy@marcelinesystems.dev>2023-06-01 22:18:38 +0300
committerGitHub <noreply@github.com>2023-06-01 21:18:38 +0200
commit351bf9d0b382adcc3e073c1a293fd815bb623f37 (patch)
treebb7447e431e16dcdd195601386f7bdc31751bca5
parent2e8b51c5e8e712b9577bc924ff6717880863d17d (diff)
feat(golang): adding `mod_version` variable (#5177)
-rw-r--r--.github/config-schema.json5
-rw-r--r--docs/config/README.md41
-rw-r--r--src/configs/go.rs2
-rw-r--r--src/modules/golang.rs109
4 files changed, 138 insertions, 19 deletions
diff --git a/.github/config-schema.json b/.github/config-schema.json
index 6bc08e471..20e4fa3b6 100644
--- a/.github/config-schema.json
+++ b/.github/config-schema.json
@@ -649,6 +649,7 @@
],
"disabled": false,
"format": "via [$symbol($version )]($style)",
+ "not_capable_style": "bold red",
"style": "bold cyan",
"symbol": "🐹 ",
"version_format": "v${raw}"
@@ -3372,6 +3373,10 @@
"default": false,
"type": "boolean"
},
+ "not_capable_style": {
+ "default": "bold red",
+ "type": "string"
+ },
"detect_extensions": {
"default": [
"go"
diff --git a/docs/config/README.md b/docs/config/README.md
index b80f0fede..d75c805d3 100644
--- a/docs/config/README.md
+++ b/docs/config/README.md
@@ -1972,24 +1972,26 @@ By default the module will be shown if any of the following conditions are met:
### 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` |
-| `symbol` | `'🐹 '` | A format string representing the symbol of Go. |
-| `detect_extensions` | `['go']` | Which extensions should trigger this module. |
-| `detect_files` | `['go.mod', 'go.sum', 'go.work', 'glide.yaml', 'Gopkg.yml', 'Gopkg.lock', '.go-version']` | Which filenames should trigger this module. |
-| `detect_folders` | `['Godeps']` | Which folders should trigger this module. |
-| `style` | `'bold cyan'` | The style for the module. |
-| `disabled` | `false` | Disables the `golang` module. |
+| 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` |
+| `symbol` | `'🐹 '` | A format string representing the symbol of Go. |
+| `detect_extensions` | `['go']` | Which extensions should trigger this module. |
+| `detect_files` | `['go.mod', 'go.sum', 'go.work', 'glide.yaml', 'Gopkg.yml', 'Gopkg.lock', '.go-version']` | Which filenames should trigger this module. |
+| `detect_folders` | `['Godeps']` | Which folders should trigger this module. |
+| `style` | `'bold cyan'` | The style for the module. |
+| `not_capable_style` | `'bold red'` | The style for the module when the go directive in the go.mod file does not match the installed Go version. |
+| `disabled` | `false` | Disables the `golang` module. |
### Variables
-| Variable | Example | Description |
-| -------- | --------- | ------------------------------------ |
-| version | `v1.12.1` | The version of `go` |
-| symbol | | Mirrors the value of option `symbol` |
-| style\* | | Mirrors the value of option `style` |
+| Variable | Example | Description |
+| ----------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
+| version | `v1.12.1` | The version of `go` |
+| mod_version | `1.16` | `go` version requirement as set in the go directive of `go.mod`. Will only show if the version requirement does not match the `go` version. |
+| 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
@@ -2002,6 +2004,15 @@ By default the module will be shown if any of the following conditions are met:
format = 'via [🏎💨 $version](bold cyan) '
```
+### Using `mod_version`
+
+```toml
+# ~/.config/starship.toml
+
+[golang]
+format = 'via [$symbol($version )($mod_version )]($style)'
+```
+
## Guix-shell
The `guix_shell` module shows the [guix-shell](https://guix.gnu.org/manual/devel/en/html_node/Invoking-guix-shell.html) environment.
diff --git a/src/configs/go.rs b/src/configs/go.rs
index 2b4adebb3..8aaa83dc9 100644
--- a/src/configs/go.rs
+++ b/src/configs/go.rs
@@ -13,6 +13,7 @@ pub struct GoConfig<'a> {
pub symbol: &'a str,
pub style: &'a str,
pub disabled: bool,
+ pub not_capable_style: &'a str,
pub detect_extensions: Vec<&'a str>,
pub detect_files: Vec<&'a str>,
pub detect_folders: Vec<&'a str>,
@@ -26,6 +27,7 @@ impl<'a> Default for GoConfig<'a> {
symbol: "🐹 ",
style: "bold cyan",
disabled: false,
+ not_capable_style: "bold red",
detect_extensions: vec!["go"],
detect_files: vec![
"go.mod",
diff --git a/src/modules/golang.rs b/src/modules/golang.rs
index 52c65a67a..ee0f5095c 100644
--- a/src/modules/golang.rs
+++ b/src/modules/golang.rs
@@ -4,6 +4,12 @@ use crate::configs::go::GoConfig;
use crate::formatter::StringFormatter;
use crate::formatter::VersionFormatter;
+use once_cell::sync::Lazy;
+use regex::Regex;
+use semver::Version;
+use semver::VersionReq;
+use std::ops::Deref;
+
/// Creates a module with the current Go version
pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
let mut module = context.new_module("golang");
@@ -19,6 +25,10 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
return None;
}
+ let golang_version =
+ Lazy::new(|| parse_go_version(&context.exec_cmd("go", &["version"])?.stdout));
+ let mod_version = Lazy::new(|| get_go_mod_version(context));
+
let parsed = StringFormatter::new(config.format).and_then(|formatter| {
formatter
.map_meta(|var, _| match var {
@@ -26,21 +36,36 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
_ => None,
})
.map_style(|variable| match variable {
- "style" => Some(Ok(config.style)),
+ "style" => {
+ let in_mod_range =
+ check_go_version(golang_version.as_deref(), mod_version.as_deref());
+
+ if in_mod_range {
+ Some(Ok(config.style))
+ } else {
+ Some(Ok(config.not_capable_style))
+ }
+ }
_ => None,
})
.map(|variable| match variable {
"version" => {
- let golang_version =
- parse_go_version(&context.exec_cmd("go", &["version"])?.stdout)?;
+ let go_ver = golang_version.deref().as_ref()?;
VersionFormatter::format_module_version(
module.get_name(),
- &golang_version,
+ go_ver,
config.version_format,
)
.map(Ok)
}
+ "mod_version" => {
+ let in_mod_range =
+ check_go_version(golang_version.as_deref(), mod_version.as_deref());
+ let mod_ver = mod_version.as_deref()?.to_string();
+
+ (!in_mod_range).then_some(Ok(mod_ver))
+ }
_ => None,
})
.parse(None, Some(context))
@@ -74,6 +99,32 @@ fn parse_go_version(go_stdout: &str) -> Option<String> {
Some(version.to_string())
}
+fn get_go_mod_version(context: &Context) -> Option<String> {
+ let mod_str = context.read_file_from_pwd("go.mod")?;
+ let re = Regex::new(r"(?:go\s)(\d+(\.\d+)+)").unwrap();
+
+ if let Some(cap) = re.captures(&mod_str) {
+ let mod_ver = cap.get(1)?.as_str();
+ Some(mod_ver.to_string())
+ } else {
+ None
+ }
+}
+
+fn check_go_version(go_version: Option<&str>, mod_version: Option<&str>) -> bool {
+ let (Some(go_version), Some(mod_version)) = (go_version, mod_version) else {
+ return true;
+ };
+ let Ok(r) = VersionReq::parse(mod_version) else {
+ return true;
+ };
+ let Ok(v) = Version::parse(go_version) else {
+ return true;
+ };
+
+ r.matches(&v)
+}
+
#[cfg(test)]
mod tests {
use super::*;
@@ -81,6 +132,7 @@ mod tests {
use nu_ansi_term::Color;
use std::fs::{self, File};
use std::io;
+ use std::io::Write;
#[test]
fn folder_without_go_files() -> io::Result<()> {
@@ -203,4 +255,53 @@ mod tests {
let input = "go version go1.12 darwin/amd64";
assert_eq!(parse_go_version(input), Some("1.12".to_string()));
}
+
+ #[test]
+ fn show_mod_version_if_not_matching_go_version() -> io::Result<()> {
+ let dir = tempfile::tempdir()?;
+ let mut file = File::create(dir.path().join("go.mod"))?;
+ file.write_all(
+ b"package test\n\n
+ go 1.16",
+ )?;
+ file.sync_all()?;
+
+ let actual = ModuleRenderer::new("golang")
+ .path(dir.path())
+ .config(toml::toml! {
+ [golang]
+ format = "via [$symbol($version )($mod_version )]($style)"
+ })
+ .collect();
+ let expected = Some(format!(
+ "via {}",
+ Color::Red.bold().paint("🐹 v1.12.1 1.16 ")
+ ));
+
+ assert_eq!(expected, actual);
+ dir.close()
+ }
+
+ #[test]
+ fn hide_mod_version_when_it_matches_go_version() -> io::Result<()> {
+ let dir = tempfile::tempdir()?;
+ let mut file = File::create(dir.path().join("go.mod"))?;
+ file.write_all(
+ b"package test\n\n
+ go 1.12",
+ )?;
+ file.sync_all()?;
+
+ let actual = ModuleRenderer::new("golang")
+ .path(dir.path())
+ .config(toml::toml! {
+ [golang]
+ format = "via [$symbol($version )($mod_version )]($style)"
+ })
+ .collect();
+ let expected = Some(format!("via {}", Color::Cyan.bold().paint("🐹 v1.12.1 ")));
+
+ assert_eq!(expected, actual);
+ dir.close()
+ }
}