diff --git a/Cargo.lock b/Cargo.lock index 448771b40..23af0b0c1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,11 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +[[package]] +name = "ahash" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0adac150c2dd5a9c864d054e07bda5e6bc010cd10036ea5f17e82a2f5867f735" + [[package]] name = "aho-corasick" version = "0.7.13" @@ -333,6 +339,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "dlv-list" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b391911b9a786312a10cb9d2b3d0735adfd5a8113eb3648de26a75e91b0826c" +dependencies = [ + "rand", +] + [[package]] name = "doc-comment" version = "0.3.3" @@ -430,6 +445,15 @@ dependencies = [ "autocfg", ] +[[package]] +name = "hashbrown" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" +dependencies = [ + "ahash", +] + [[package]] name = "hermit-abi" version = "0.1.15" @@ -468,7 +492,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86b45e59b16c76b11bf9738fd5d38879d3bd28ad292d7b313608becb17ae2df9" dependencies = [ "autocfg", - "hashbrown", + "hashbrown 0.8.2", ] [[package]] @@ -787,6 +811,16 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "ordered-multimap" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87a6df8506c2d359d5105344891f283e8e7ef81a7c6a542d516f8707e4a09b6b" +dependencies = [ + "dlv-list", + "hashbrown 0.9.1", +] + [[package]] name = "os_info" version = "3.0.0" @@ -1020,6 +1054,16 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "rust-ini" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcdbf249a931ceb503aa80e08ca016675dbc7884eda8e2d88e85533d4dbade62" +dependencies = [ + "cfg-if", + "ordered-multimap", +] + [[package]] name = "ryu" version = "1.0.5" @@ -1153,6 +1197,7 @@ dependencies = [ "rand", "rayon", "regex", + "rust-ini", "serde_json", "shell-words", "starship_module_config_derive", diff --git a/Cargo.toml b/Cargo.toml index b5c43354f..2ae672dc8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,6 +33,7 @@ ansi_term = "0.12.1" dirs-next = "1.0.1" git2 = { version = "0.13.11", default-features = false } toml = { version = "0.5.6", features = ["preserve_order"] } +rust-ini = "0.16" serde_json = "1.0.58" rayon = "1.4.1" log = { version = "0.4.11", features = ["std"] } diff --git a/src/modules/python.rs b/src/modules/python.rs index d09d208ee..b8affc7df 100644 --- a/src/modules/python.rs +++ b/src/modules/python.rs @@ -1,3 +1,4 @@ +use ini::Ini; use std::path::Path; use super::{Context, Module, RootModuleConfig}; @@ -109,19 +110,29 @@ fn format_python_version(python_stdout: &str) -> String { fn get_python_virtual_env(context: &Context) -> Option { context.get_env("VIRTUAL_ENV").and_then(|venv| { - Path::new(&venv) - .file_name() - .map(|filename| String::from(filename.to_str().unwrap_or(""))) + get_prompt_from_venv(Path::new(&venv)).or_else(|| { + Path::new(&venv) + .file_name() + .map(|filename| String::from(filename.to_str().unwrap_or(""))) + }) }) } +fn get_prompt_from_venv(venv_path: &Path) -> Option { + Ini::load_from_file(venv_path.join("pyvenv.cfg")) + .ok()? + .general_section() + .get("prompt") + .map(String::from) +} #[cfg(test)] mod tests { use super::*; use crate::test::ModuleRenderer; use ansi_term::Color; - use std::fs::File; + use std::fs::{create_dir_all, File}; use std::io; + use std::io::Write; #[test] fn test_format_python_version() { @@ -317,6 +328,33 @@ mod tests { dir.close() } + #[test] + fn with_active_venv_and_prompt() -> io::Result<()> { + let dir = tempfile::tempdir()?; + create_dir_all(dir.path().join("my_venv"))?; + let mut venv_cfg = File::create(dir.path().join("my_venv").join("pyvenv.cfg"))?; + venv_cfg.write_all( + br#" +home = something +prompt = 'foo' + "#, + )?; + venv_cfg.sync_all()?; + + let actual = ModuleRenderer::new("python") + .path(dir.path()) + .env("VIRTUAL_ENV", dir.path().join("my_venv").to_str().unwrap()) + .collect(); + + let expected = Some(format!( + "via {} ", + Color::Yellow.bold().paint("🐍 v2.7.17 (foo)") + )); + + assert_eq!(actual, expected); + dir.close() + } + fn check_python2_renders(dir: &tempfile::TempDir, starship_config: Option) { let config = starship_config.unwrap_or(toml::toml! { [python]