diff options
author | Nicola Corti <corti.nico@gmail.com> | 2020-12-26 15:26:50 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-12-26 15:26:50 +0100 |
commit | 208251adefcfdba3604821daca848b76e78ff0eb (patch) | |
tree | 07a5d5a9a664b23710d72ded1b44d7e7a62f6fe0 /src/modules/kotlin.rs | |
parent | 53a08712eb2de5d507655d423cc78e7130a32dd1 (diff) |
feat(kotlin): Add the kotlin module (#2026)
Add a module to show the currently installed Kotlin version if a
.kt/.kts file is found in the current folder
Diffstat (limited to 'src/modules/kotlin.rs')
-rw-r--r-- | src/modules/kotlin.rs | 174 |
1 files changed, 174 insertions, 0 deletions
diff --git a/src/modules/kotlin.rs b/src/modules/kotlin.rs new file mode 100644 index 000000000..31d979b44 --- /dev/null +++ b/src/modules/kotlin.rs @@ -0,0 +1,174 @@ +use super::{Context, Module, RootModuleConfig}; + +use crate::configs::kotlin::KotlinConfig; +use crate::formatter::StringFormatter; +use crate::utils; + +use regex::Regex; +const KOTLIN_VERSION_PATTERN: &str = "(?P<version>[\\d\\.]+[\\d\\.]+[\\d\\.]+)"; + +/// Creates a module with the current Kotlin version +/// +/// Will display the Kotlin version if any of the following criteria are met: +/// - Current directory contains a file with a `.kt` or `.kts` extension +pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> { + let is_kotlin_project = context + .try_begin_scan()? + .set_extensions(&["kt", "kts"]) + .is_match(); + + if !is_kotlin_project { + return None; + } + + let mut module = context.new_module("kotlin"); + let config = KotlinConfig::try_load(module.config); + let kotlin_version = format_kotlin_version(&get_kotlin_version(&config.kotlin_binary)?)?; + 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" => Some(Ok(&kotlin_version)), + _ => None, + }) + .parse(None) + }); + + module.set_segments(match parsed { + Ok(segments) => segments, + Err(error) => { + log::warn!("Error in module `kotlin`:\n{}", error); + return None; + } + }); + + Some(module) +} + +fn get_kotlin_version(kotlin_binary: &str) -> Option<String> { + match utils::exec_cmd(kotlin_binary, &["-version"]) { + Some(output) => { + if output.stdout.is_empty() { + Some(output.stderr) + } else { + Some(output.stdout) + } + } + None => None, + } +} + +fn format_kotlin_version(kotlin_stdout: &str) -> Option<String> { + // kotlin -version output looks like this: + // Kotlin version 1.4.21-release-411 (JRE 14.0.1+7) + + // kotlinc -version output looks like this: + // info: kotlinc-jvm 1.4.21 (JRE 14.0.1+7) + let re = Regex::new(KOTLIN_VERSION_PATTERN).ok()?; + let captures = re.captures(kotlin_stdout)?; + let version = &captures["version"]; + Some(format!("v{}", version)) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::test::ModuleRenderer; + use ansi_term::Color; + use std::fs::File; + use std::io; + + #[test] + fn folder_without_kotlin_files() -> io::Result<()> { + let dir = tempfile::tempdir()?; + let actual = ModuleRenderer::new("kotlin").path(dir.path()).collect(); + let expected = None; + assert_eq!(expected, actual); + dir.close() + } + + #[test] + fn folder_with_kotlin_file() -> io::Result<()> { + let dir = tempfile::tempdir()?; + File::create(dir.path().join("main.kt"))?.sync_all()?; + let actual = ModuleRenderer::new("kotlin").path(dir.path()).collect(); + let expected = Some(format!("via {} ", Color::Blue.bold().paint("🅺 v1.4.21"))); + assert_eq!(expected, actual); + dir.close() + } + + #[test] + fn folder_with_kotlin_script_file() -> io::Result<()> { + let dir = tempfile::tempdir()?; + File::create(dir.path().join("main.kts"))?.sync_all()?; + let actual = ModuleRenderer::new("kotlin").path(dir.path()).collect(); + let expected = Some(format!("via {} ", Color::Blue.bold().paint("🅺 v1.4.21"))); + assert_eq!(expected, actual); + dir.close() + } + + #[test] + fn kotlin_binary_is_kotlin_runtime() -> io::Result<()> { + let dir = tempfile::tempdir()?; + File::create(dir.path().join("main.kt"))?.sync_all()?; + + let config = toml::toml! { + [kotlin] + kotlin_binary = "kotlin" + }; + + let actual = ModuleRenderer::new("kotlin") + .path(dir.path()) + .config(config) + .collect(); + + let expected = Some(format!("via {} ", Color::Blue.bold().paint("🅺 v1.4.21"))); + assert_eq!(expected, actual); + dir.close() + } + + #[test] + fn kotlin_binary_is_kotlin_compiler() -> io::Result<()> { + let dir = tempfile::tempdir()?; + File::create(dir.path().join("main.kt"))?.sync_all()?; + + let config = toml::toml! { + [kotlin] + kotlin_binary = "kotlinc" + }; + + let actual = ModuleRenderer::new("kotlin") + .path(dir.path()) + .config(config) + .collect(); + + let expected = Some(format!("via {} ", Color::Blue.bold().paint("🅺 v1.4.21"))); + assert_eq!(expected, actual); + dir.close() + } + + #[test] + fn test_format_kotlin_version_from_runtime() { + let kotlin_input = "Kotlin version 1.4.21-release-411 (JRE 14.0.1+7)"; + assert_eq!( + format_kotlin_version(kotlin_input), + Some("v1.4.21".to_string()) + ); + } + + #[test] + fn test_format_kotlin_version_from_compiler() { + let kotlin_input = "info: kotlinc-jvm 1.4.21 (JRE 14.0.1+7)"; + assert_eq!( + format_kotlin_version(kotlin_input), + Some("v1.4.21".to_string()) + ); + } +} |