From 46904e504566d833601c52ae36848348f61e94a8 Mon Sep 17 00:00:00 2001 From: Stephen Ball Date: Thu, 5 Dec 2019 18:04:27 +0000 Subject: [PATCH] feat: Add PHP version module (#244) --- .github/workflows/workflow.yml | 5 +++ README.md | 1 + docs/config/README.md | 25 +++++++++++++ src/configs/mod.rs | 1 + src/configs/php.rs | 21 +++++++++++ src/module.rs | 1 + src/modules/mod.rs | 2 + src/modules/php.rs | 67 ++++++++++++++++++++++++++++++++++ tests/Dockerfile | 12 ++++++ tests/testsuite/php.rs | 56 ++++++++++++++++++++++++++++ 10 files changed, 191 insertions(+) create mode 100644 src/configs/php.rs create mode 100644 src/modules/php.rs create mode 100644 tests/testsuite/php.rs diff --git a/.github/workflows/workflow.yml b/.github/workflows/workflow.yml index 7308948c..7d3f2153 100644 --- a/.github/workflows/workflow.yml +++ b/.github/workflows/workflow.yml @@ -124,6 +124,11 @@ jobs: with: dotnet-version: "2.2.402" + # Install PHP at a fixed version + - uses: shivammathur/setup-php@master + with: + php-version: '7.3.8' + # Install Mercurial (pre-installed on linux, installed from pip on macos # and from choco on windows), - name: Install Mercurial (macos) diff --git a/README.md b/README.md index 758807aa..2c1d45d0 100644 --- a/README.md +++ b/README.md @@ -88,6 +88,7 @@ The prompt shows information you need while you're working, while staying sleek - Current Rust version (`🦀`) - Current Ruby version (`💎`) - Current Python version (`🐍`) +- Current PHP version (`🐘`) - Current Go version (`🐹`) - Nix-shell environment detection - Print an environment variable diff --git a/docs/config/README.md b/docs/config/README.md index cfc94e48..9b297323 100644 --- a/docs/config/README.md +++ b/docs/config/README.md @@ -841,6 +841,31 @@ and `poetry` packages. symbol = "🎁 " ``` +## PHP + +The `php` module shows the currently installed version of PHP. +The module will be shown if any of the following conditions are met: + +- The current directory contains a `composer.json` file +- The current directory contains a `.php` file + +### Options + +| Variable | Default | Description | +| ---------- | ------------ | ------------------------------------------------------ | +| `symbol` | `"🐘 "` | The symbol used before displaying the version of PHP. | +| `style` | `"bold red"` | The style for the module. | +| `disabled` | `false` | Disables the `php` module. | + +### Example + +```toml +# ~/.config/starship.toml + +[php] +symbol = "🔹 " +``` + ## Python The `python` module shows the currently installed version of Python. diff --git a/src/configs/mod.rs b/src/configs/mod.rs index c30ac9a9..55330789 100644 --- a/src/configs/mod.rs +++ b/src/configs/mod.rs @@ -19,6 +19,7 @@ pub mod memory_usage; pub mod nix_shell; pub mod nodejs; pub mod package; +pub mod php; pub mod python; pub mod ruby; pub mod rust; diff --git a/src/configs/php.rs b/src/configs/php.rs new file mode 100644 index 00000000..efe1f648 --- /dev/null +++ b/src/configs/php.rs @@ -0,0 +1,21 @@ +use crate::config::{ModuleConfig, RootModuleConfig, SegmentConfig}; + +use ansi_term::{Color, Style}; +use starship_module_config_derive::ModuleConfig; + +#[derive(Clone, ModuleConfig)] +pub struct PhpConfig<'a> { + pub symbol: SegmentConfig<'a>, + pub style: Style, + pub disabled: bool, +} + +impl<'a> RootModuleConfig<'a> for PhpConfig<'a> { + fn new() -> Self { + PhpConfig { + symbol: SegmentConfig::new("🐘 "), + style: Color::Red.bold(), + disabled: false, + } + } +} diff --git a/src/module.rs b/src/module.rs index 7e3cb813..591934f2 100644 --- a/src/module.rs +++ b/src/module.rs @@ -34,6 +34,7 @@ pub const ALL_MODULES: &[&str] = &[ "python", "ruby", "rust", + "php", "time", "username", ]; diff --git a/src/modules/mod.rs b/src/modules/mod.rs index 2f891e8d..f69c9465 100644 --- a/src/modules/mod.rs +++ b/src/modules/mod.rs @@ -20,6 +20,7 @@ mod memory_usage; mod nix_shell; mod nodejs; mod package; +mod php; mod python; mod ruby; mod rust; @@ -61,6 +62,7 @@ pub fn handle<'a>(module: &str, context: &'a Context) -> Option> { "nix_shell" => nix_shell::module(context), "nodejs" => nodejs::module(context), "package" => package::module(context), + "php" => php::module(context), "python" => python::module(context), "ruby" => ruby::module(context), "rust" => rust::module(context), diff --git a/src/modules/php.rs b/src/modules/php.rs new file mode 100644 index 00000000..3e29ca1f --- /dev/null +++ b/src/modules/php.rs @@ -0,0 +1,67 @@ +use std::process::Command; + +use super::{Context, Module, RootModuleConfig, SegmentConfig}; + +use crate::configs::php::PhpConfig; + +/// Creates a module with the current PHP version +/// +/// Will display the PHP version if any of the following criteria are met: +/// - Current directory contains a `.php` file +/// - Current directory contains a `composer.json` file +pub fn module<'a>(context: &'a Context) -> Option> { + let is_php_project = context + .try_begin_scan()? + .set_files(&["composer.json"]) + .set_extensions(&["php"]) + .is_match(); + + if !is_php_project { + return None; + } + + match get_php_version() { + Some(php_version) => { + let mut module = context.new_module("php"); + let config: PhpConfig = PhpConfig::try_load(module.config); + + module.set_style(config.style); + + let formatted_version = format_php_version(&php_version)?; + module.create_segment("symbol", &config.symbol); + module.create_segment("version", &SegmentConfig::new(&formatted_version)); + + Some(module) + } + None => None, + } +} + +fn get_php_version() -> Option { + match Command::new("php") + .arg("-r") + .arg("echo PHP_MAJOR_VERSION.'.'.PHP_MINOR_VERSION.'.'.PHP_RELEASE_VERSION;") + .output() + { + Ok(output) => Some(String::from_utf8(output.stdout).unwrap()), + Err(_) => None, + } +} + +fn format_php_version(php_version: &str) -> Option { + let mut formatted_version = String::with_capacity(php_version.len() + 1); + formatted_version.push('v'); + formatted_version.push_str(php_version); + Some(formatted_version) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_format_php_version() { + let input = "7.3.8"; + assert_eq!(format_php_version(input), Some("v7.3.8".to_string())); + } +} diff --git a/tests/Dockerfile b/tests/Dockerfile index 6b0af7d2..12372e24 100644 --- a/tests/Dockerfile +++ b/tests/Dockerfile @@ -61,6 +61,18 @@ RUN mkdir -p "$DOTNET_HOME" \ ENV PATH $DOTNET_HOME:$PATH RUN dotnet help +# Install PHP +ENV PHP_VERSION 7.3.8 +ENV PHPENV_ROOT /home/nonroot/.phpenv +ENV PATH $PHPENV_ROOT/bin:$PHPENV_ROOT/shims:$PATH +ENV CONFIGURE_OPTS "--without-tidy --disable-zip" +RUN curl -L https://raw.githubusercontent.com/phpenv/phpenv-installer/master/bin/phpenv-installer | bash \ + && phpenv install $PHP_VERSION \ + && phpenv global $PHP_VERSION \ + && chmod -R a+x $PHPENV_ROOT +# Check that PHP was correctly installed +RUN php --version + # Install Mercurial RUN HGPYTHON3=1 pip install mercurial # Check that Mercurial was correctly installed diff --git a/tests/testsuite/php.rs b/tests/testsuite/php.rs new file mode 100644 index 00000000..49759abd --- /dev/null +++ b/tests/testsuite/php.rs @@ -0,0 +1,56 @@ +use std::fs::File; +use std::io; + +use ansi_term::Color; + +use crate::common; +use crate::common::TestCommand; + +#[test] +fn folder_without_php_files() -> io::Result<()> { + let dir = common::new_tempdir()?; + + let output = common::render_module("php") + .arg("--path") + .arg(dir.path()) + .output()?; + let actual = String::from_utf8(output.stdout).unwrap(); + + let expected = ""; + assert_eq!(expected, actual); + Ok(()) +} + +#[test] +#[ignore] +fn folder_with_composer_file() -> io::Result<()> { + let dir = common::new_tempdir()?; + File::create(dir.path().join("composer.json"))?; + + let output = common::render_module("php") + .arg("--path") + .arg(dir.path()) + .output()?; + let actual = String::from_utf8(output.stdout).unwrap(); + + let expected = format!("via {} ", Color::Red.bold().paint("🐘 v7.3.8")); + assert_eq!(expected, actual); + Ok(()) +} + +#[test] +#[ignore] +fn folder_with_php_file() -> io::Result<()> { + let dir = common::new_tempdir()?; + File::create(dir.path().join("any.php"))?; + + let output = common::render_module("php") + .arg("--path") + .arg(dir.path()) + .output()?; + let actual = String::from_utf8(output.stdout).unwrap(); + + let expected = format!("via {} ", Color::Red.bold().paint("🐘 v7.3.8")); + assert_eq!(expected, actual); + Ok(()) +}