mirror of
https://github.com/starship/starship.git
synced 2026-06-21 02:02:14 +07:00
feat(c++): adding c++ module (#6570)
This commit is contained in:
committed by
GitHub
parent
daf8d93d27
commit
ed07646099
+123
-2
@@ -134,7 +134,7 @@
|
||||
},
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/CConfig"
|
||||
"$ref": "#/definitions/CcConfig_for_CConfigMarker"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -241,6 +241,47 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"cpp": {
|
||||
"default": {
|
||||
"commands": [
|
||||
[
|
||||
"c++",
|
||||
"--version"
|
||||
],
|
||||
[
|
||||
"g++",
|
||||
"--version"
|
||||
],
|
||||
[
|
||||
"clang++",
|
||||
"--version"
|
||||
]
|
||||
],
|
||||
"detect_extensions": [
|
||||
"cpp",
|
||||
"cc",
|
||||
"cxx",
|
||||
"c++",
|
||||
"hpp",
|
||||
"hh",
|
||||
"hxx",
|
||||
"h++",
|
||||
"tcc"
|
||||
],
|
||||
"detect_files": [],
|
||||
"detect_folders": [],
|
||||
"disabled": true,
|
||||
"format": "via [$symbol($version(-$name) )]($style)",
|
||||
"style": "149 bold",
|
||||
"symbol": "C++ ",
|
||||
"version_format": "v${raw}"
|
||||
},
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/definitions/CcConfig_for_CppConfigMarker"
|
||||
}
|
||||
]
|
||||
},
|
||||
"crystal": {
|
||||
"default": {
|
||||
"detect_extensions": [
|
||||
@@ -2272,7 +2313,7 @@
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"CConfig": {
|
||||
"CcConfig_for_CConfigMarker": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"format": {
|
||||
@@ -2583,6 +2624,86 @@
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"CcConfig_for_CppConfigMarker": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"format": {
|
||||
"default": "via [$symbol($version(-$name) )]($style)",
|
||||
"type": "string"
|
||||
},
|
||||
"version_format": {
|
||||
"default": "v${raw}",
|
||||
"type": "string"
|
||||
},
|
||||
"style": {
|
||||
"default": "149 bold",
|
||||
"type": "string"
|
||||
},
|
||||
"symbol": {
|
||||
"default": "C++ ",
|
||||
"type": "string"
|
||||
},
|
||||
"disabled": {
|
||||
"default": true,
|
||||
"type": "boolean"
|
||||
},
|
||||
"detect_extensions": {
|
||||
"default": [
|
||||
"cpp",
|
||||
"cc",
|
||||
"cxx",
|
||||
"c++",
|
||||
"hpp",
|
||||
"hh",
|
||||
"hxx",
|
||||
"h++",
|
||||
"tcc"
|
||||
],
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"detect_files": {
|
||||
"default": [],
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"detect_folders": {
|
||||
"default": [],
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"commands": {
|
||||
"default": [
|
||||
[
|
||||
"c++",
|
||||
"--version"
|
||||
],
|
||||
[
|
||||
"g++",
|
||||
"--version"
|
||||
],
|
||||
[
|
||||
"clang++",
|
||||
"--version"
|
||||
]
|
||||
],
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"CrystalConfig": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
||||
@@ -705,6 +705,54 @@ If a C compiler is not supported by this module, you can request it by [raising
|
||||
format = 'via [$name $version]($style)'
|
||||
```
|
||||
|
||||
## CPP
|
||||
|
||||
The `cpp` module shows some information about your `C++` compiler. By default,
|
||||
the module will be shown if the current directory contains a `.cpp`, `.hpp`, or other `C++`-related files.
|
||||
|
||||
### Options
|
||||
|
||||
| Option | Default | Description |
|
||||
| ------------------- | -------------------------------------------------------------------------------- | ------------------------------------------------------------------------- |
|
||||
| `format` | `'via [$symbol($version(-$name) )]($style)'` | The format string for the module. |
|
||||
| `version_format` | `'v${raw}'` | The version format. Available vars are `raw`, `major`, `minor`, & `patch` |
|
||||
| `symbol` | `'C++ '` | The symbol used before displaying the compiler details |
|
||||
| `detect_extensions` | `['cpp', 'cc', 'cxx', 'c++', 'hpp', 'hh', 'hxx', 'h++', 'tcc']` | Which extensions should trigger this module. |
|
||||
| `detect_files` | `[]` | Which filenames should trigger this module. |
|
||||
| `detect_folders` | `[]` | Which folders should trigger this module. |
|
||||
| `commands` | `[ [ 'c++', '--version' ], [ 'g++', '--version' ], [ 'clang++', '--version' ] ]` | How to detect what the compiler is |
|
||||
| `style` | `'bold 149'` | The style for the module. |
|
||||
| `disabled` | `true` | Disables the `cpp` module. |
|
||||
|
||||
### Variables
|
||||
|
||||
| Variable | Example | Description |
|
||||
| -------- | ------- | ------------------------------------ |
|
||||
| name | clang++ | The name of the compiler |
|
||||
| version | 13.0.0 | The version of the compiler |
|
||||
| symbol | | Mirrors the value of option `symbol` |
|
||||
| style | | Mirrors the value of option `style` |
|
||||
|
||||
NB that `version` is not in the default format.
|
||||
|
||||
### Commands
|
||||
|
||||
The `commands` option accepts a list of commands to determine the compiler version and name.
|
||||
|
||||
Each command is represented as a list of the executable name, followed by its arguments, usually something like `['mycpp', '--version']`. Starship will try executing each command until it gets a result on STDOUT.
|
||||
|
||||
If a C++ compiler is not supported by this module, you can request it by [raising an issue on GitHub](https://github.com/starship/starship/).
|
||||
|
||||
### Example
|
||||
|
||||
```toml
|
||||
# ~/.config/starship.toml
|
||||
|
||||
[cpp]
|
||||
disabled = false
|
||||
format = 'via [$name $version]($style)'
|
||||
```
|
||||
|
||||
## Character
|
||||
|
||||
The `character` module shows a character (usually an arrow) beside where the text
|
||||
|
||||
@@ -7,6 +7,9 @@ format = '\[[$symbol($version)]($style)\]'
|
||||
[c]
|
||||
format = '\[[$symbol($version(-$name))]($style)\]'
|
||||
|
||||
[cpp]
|
||||
format = '\[[$symbol($version(-$name))]($style)\]'
|
||||
|
||||
[cmake]
|
||||
format = '\[[$symbol($version)]($style)\]'
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ $git_branch\
|
||||
$git_status\
|
||||
[](fg:color_aqua bg:color_blue)\
|
||||
$c\
|
||||
$cpp\
|
||||
$rust\
|
||||
$golang\
|
||||
$nodejs\
|
||||
@@ -106,6 +107,11 @@ symbol = " "
|
||||
style = "bg:color_blue"
|
||||
format = '[[ $symbol( $version) ](fg:color_fg0 bg:color_blue)]($style)'
|
||||
|
||||
[cpp]
|
||||
symbol = " "
|
||||
style = "bg:color_blue"
|
||||
format = '[[ $symbol( $version) ](fg:color_fg0 bg:color_blue)]($style)'
|
||||
|
||||
[rust]
|
||||
symbol = ""
|
||||
style = "bg:color_blue"
|
||||
|
||||
@@ -29,6 +29,7 @@ $pijul_channel\
|
||||
$docker_context\
|
||||
$package\
|
||||
$c\
|
||||
$cpp\
|
||||
$cmake\
|
||||
$cobol\
|
||||
$daml\
|
||||
@@ -258,6 +259,10 @@ format = " [buf](italic) [$symbol $version $buf_version]($style)"
|
||||
symbol = "ℂ "
|
||||
format = " [$symbol($version(-$name))]($style)"
|
||||
|
||||
[cpp]
|
||||
symbol = "ℂ "
|
||||
format = " [$symbol($version(-$name))]($style)"
|
||||
|
||||
[conda]
|
||||
symbol = "◯ "
|
||||
format = " conda [$symbol$environment]($style)"
|
||||
|
||||
@@ -10,6 +10,9 @@ symbol = " "
|
||||
[c]
|
||||
symbol = " "
|
||||
|
||||
[cpp]
|
||||
symbol = " "
|
||||
|
||||
[cmake]
|
||||
symbol = " "
|
||||
|
||||
|
||||
@@ -7,6 +7,9 @@ format = '(via [$symbol($version )]($style))'
|
||||
[c]
|
||||
format = '(via [$symbol($version(-$name) )]($style))'
|
||||
|
||||
[cpp]
|
||||
format = '(via [$symbol($version(-$name) )]($style))'
|
||||
|
||||
[cmake]
|
||||
format = '(via [$symbol($version )]($style))'
|
||||
|
||||
|
||||
@@ -69,6 +69,11 @@ symbol = " "
|
||||
style = "bg:#86BBD8"
|
||||
format = '[ $symbol ($version) ]($style)'
|
||||
|
||||
[cpp]
|
||||
symbol = " "
|
||||
style = "bg:#86BBD8"
|
||||
format = '[ $symbol ($version) ]($style)'
|
||||
|
||||
[docker_context]
|
||||
symbol = " "
|
||||
style = "bg:#06969A"
|
||||
|
||||
@@ -28,6 +28,9 @@ symbol = "bun "
|
||||
[c]
|
||||
symbol = "C "
|
||||
|
||||
[cpp]
|
||||
symbol = "C++ "
|
||||
|
||||
[cobol]
|
||||
symbol = "cobol "
|
||||
|
||||
|
||||
+8
-14
@@ -1,27 +1,21 @@
|
||||
use crate::configs::cc::CcConfig;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Clone, Deserialize, Serialize)]
|
||||
#[derive(Default, Clone, Deserialize, Serialize)]
|
||||
#[cfg_attr(
|
||||
feature = "config-schema",
|
||||
derive(schemars::JsonSchema),
|
||||
schemars(deny_unknown_fields)
|
||||
)]
|
||||
#[serde(default)]
|
||||
pub struct CConfig<'a> {
|
||||
pub format: &'a str,
|
||||
pub version_format: &'a str,
|
||||
pub style: &'a str,
|
||||
pub symbol: &'a str,
|
||||
pub disabled: bool,
|
||||
pub detect_extensions: Vec<&'a str>,
|
||||
pub detect_files: Vec<&'a str>,
|
||||
pub detect_folders: Vec<&'a str>,
|
||||
pub commands: Vec<Vec<&'a str>>,
|
||||
}
|
||||
pub struct CConfigMarker;
|
||||
|
||||
pub type CConfig<'a> = CcConfig<'a, CConfigMarker>;
|
||||
|
||||
impl Default for CConfig<'_> {
|
||||
fn default() -> Self {
|
||||
CConfig {
|
||||
CcConfig {
|
||||
marker: std::marker::PhantomData::<CConfigMarker>,
|
||||
|
||||
format: "via [$symbol($version(-$name) )]($style)",
|
||||
version_format: "v${raw}",
|
||||
style: "149 bold",
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
#[cfg_attr(
|
||||
feature = "config-schema",
|
||||
derive(schemars::JsonSchema),
|
||||
schemars(deny_unknown_fields),
|
||||
schemars(bound = "CcConfig<'a, T>: std::default::Default, T: schemars::JsonSchema")
|
||||
)]
|
||||
#[serde(default)]
|
||||
pub struct CcConfig<'a, T> {
|
||||
#[serde(skip)]
|
||||
pub marker: std::marker::PhantomData<T>,
|
||||
|
||||
pub format: &'a str,
|
||||
pub version_format: &'a str,
|
||||
pub style: &'a str,
|
||||
pub symbol: &'a str,
|
||||
pub disabled: bool,
|
||||
pub detect_extensions: Vec<&'a str>,
|
||||
pub detect_files: Vec<&'a str>,
|
||||
pub detect_folders: Vec<&'a str>,
|
||||
pub commands: Vec<Vec<&'a str>>,
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
use crate::configs::cc::CcConfig;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Default, Clone, Deserialize, Serialize)]
|
||||
#[cfg_attr(
|
||||
feature = "config-schema",
|
||||
derive(schemars::JsonSchema),
|
||||
schemars(deny_unknown_fields)
|
||||
)]
|
||||
pub struct CppConfigMarker;
|
||||
|
||||
pub type CppConfig<'a> = CcConfig<'a, CppConfigMarker>;
|
||||
|
||||
impl Default for CppConfig<'_> {
|
||||
fn default() -> Self {
|
||||
CcConfig {
|
||||
marker: std::marker::PhantomData::<CppConfigMarker>,
|
||||
|
||||
format: "via [$symbol($version(-$name) )]($style)",
|
||||
version_format: "v${raw}",
|
||||
style: "149 bold",
|
||||
symbol: "C++ ",
|
||||
disabled: true,
|
||||
detect_extensions: vec!["cpp", "cc", "cxx", "c++", "hpp", "hh", "hxx", "h++", "tcc"],
|
||||
detect_files: vec![],
|
||||
detect_folders: vec![],
|
||||
commands: vec![
|
||||
vec!["c++", "--version"],
|
||||
vec!["g++", "--version"],
|
||||
vec!["clang++", "--version"],
|
||||
],
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,12 +7,14 @@ pub mod battery;
|
||||
pub mod buf;
|
||||
pub mod bun;
|
||||
pub mod c;
|
||||
pub mod cc;
|
||||
pub mod character;
|
||||
pub mod cmake;
|
||||
pub mod cmd_duration;
|
||||
pub mod cobol;
|
||||
pub mod conda;
|
||||
pub mod container;
|
||||
pub mod cpp;
|
||||
pub mod crystal;
|
||||
pub mod custom;
|
||||
pub mod daml;
|
||||
@@ -140,6 +142,8 @@ pub struct FullConfig<'a> {
|
||||
#[serde(borrow)]
|
||||
container: container::ContainerConfig<'a>,
|
||||
#[serde(borrow)]
|
||||
cpp: cpp::CppConfig<'a>,
|
||||
#[serde(borrow)]
|
||||
crystal: crystal::CrystalConfig<'a>,
|
||||
#[serde(borrow)]
|
||||
daml: daml::DamlConfig<'a>,
|
||||
|
||||
@@ -57,6 +57,7 @@ pub const PROMPT_ORDER: &[&str] = &[
|
||||
"c",
|
||||
"cmake",
|
||||
"cobol",
|
||||
"cpp",
|
||||
"daml",
|
||||
"dart",
|
||||
"deno",
|
||||
|
||||
@@ -20,6 +20,7 @@ pub const ALL_MODULES: &[&str] = &[
|
||||
"cobol",
|
||||
"conda",
|
||||
"container",
|
||||
"cpp",
|
||||
"crystal",
|
||||
"daml",
|
||||
"dart",
|
||||
|
||||
+3
-86
@@ -1,92 +1,9 @@
|
||||
use super::{Context, Module, ModuleConfig};
|
||||
|
||||
use crate::configs::c::CConfig;
|
||||
use crate::formatter::StringFormatter;
|
||||
use crate::formatter::VersionFormatter;
|
||||
|
||||
use semver::Version;
|
||||
use std::borrow::Cow;
|
||||
use std::ops::Deref;
|
||||
use std::sync::LazyLock;
|
||||
use super::{Context, Module};
|
||||
use crate::modules::cc::{Lang, module as cc_module};
|
||||
|
||||
/// Creates a module with the current C compiler and version
|
||||
pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||
let mut module = context.new_module("c");
|
||||
let config: CConfig = CConfig::try_load(module.config);
|
||||
let is_c_project = context
|
||||
.try_begin_scan()?
|
||||
.set_extensions(&config.detect_extensions)
|
||||
.set_files(&config.detect_files)
|
||||
.set_folders(&config.detect_folders)
|
||||
.is_match();
|
||||
|
||||
if !is_c_project {
|
||||
return None;
|
||||
}
|
||||
|
||||
let parsed = StringFormatter::new(config.format).and_then(|formatter| {
|
||||
let c_compiler_info = LazyLock::new(|| context.exec_cmds_return_first(config.commands));
|
||||
|
||||
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 {
|
||||
"name" => {
|
||||
let c_compiler_info = &c_compiler_info.deref().as_ref()?.stdout;
|
||||
|
||||
let c_compiler = if c_compiler_info.contains("clang") {
|
||||
"clang"
|
||||
} else if c_compiler_info.contains("Free Software Foundation") {
|
||||
"gcc"
|
||||
} else {
|
||||
return None;
|
||||
};
|
||||
Some(Ok(Cow::Borrowed(c_compiler)))
|
||||
}
|
||||
"version" => {
|
||||
let c_compiler_info = &c_compiler_info.deref().as_ref()?.stdout;
|
||||
|
||||
// Clang says ...
|
||||
// Apple clang version 13.0.0 ...\n
|
||||
// OpenBSD clang version 11.1.0\n...
|
||||
// FreeBSD clang version 11.0.1 ...\n
|
||||
// so we always want the first semver-ish whitespace-
|
||||
// separated "word".
|
||||
// gcc says ...
|
||||
// gcc (OmniOS 151036/9.3.0-il-1) 9.3.0\n...
|
||||
// gcc (Debian 10.2.1-6) 10.2.1 ...\n
|
||||
// cc (GCC) 3.3.5 (Debian 1:3.3.5-13)\n...
|
||||
// so again we always want the first semver-ish word.
|
||||
VersionFormatter::format_module_version(
|
||||
module.get_name(),
|
||||
c_compiler_info
|
||||
.split_whitespace()
|
||||
.find(|word| Version::parse(word).is_ok())?,
|
||||
config.version_format,
|
||||
)
|
||||
.map(Cow::Owned)
|
||||
.map(Ok)
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
.parse(None, Some(context))
|
||||
});
|
||||
|
||||
module.set_segments(match parsed {
|
||||
Ok(segments) => segments,
|
||||
Err(error) => {
|
||||
log::warn!("Error in module `c`:\n{}", error);
|
||||
return None;
|
||||
}
|
||||
});
|
||||
|
||||
Some(module)
|
||||
cc_module(context, Lang::C)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
use super::{Context, Module, ModuleConfig};
|
||||
|
||||
use crate::configs::c::{CConfig, CConfigMarker};
|
||||
use crate::configs::cc::CcConfig;
|
||||
use crate::configs::cpp::{CppConfig, CppConfigMarker};
|
||||
use crate::formatter::StringFormatter;
|
||||
use crate::formatter::VersionFormatter;
|
||||
|
||||
use crate::segment::Segment;
|
||||
|
||||
use semver::Version;
|
||||
use std::borrow::Cow;
|
||||
use std::ops::Deref;
|
||||
use std::sync::LazyLock;
|
||||
|
||||
pub enum Lang {
|
||||
C,
|
||||
Cpp,
|
||||
}
|
||||
|
||||
fn is_cc_project<T>(config: &CcConfig<T>, context: &Context) -> Option<bool> {
|
||||
Some(
|
||||
context
|
||||
.try_begin_scan()?
|
||||
.set_extensions(&config.detect_extensions)
|
||||
.set_files(&config.detect_files)
|
||||
.set_folders(&config.detect_folders)
|
||||
.is_match(),
|
||||
)
|
||||
}
|
||||
|
||||
fn parse_module<T>(
|
||||
context: &Context,
|
||||
module: &mut Module,
|
||||
config: CcConfig<T>,
|
||||
compilers: [(&str, &str); 2],
|
||||
) -> Result<Vec<Segment>, crate::formatter::string_formatter::StringFormatterError> {
|
||||
StringFormatter::new(config.format).and_then(|formatter| {
|
||||
let cc_compiler_info = LazyLock::new(|| context.exec_cmds_return_first(config.commands));
|
||||
|
||||
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 {
|
||||
"name" => {
|
||||
let cc_compiler_info = &cc_compiler_info.deref().as_ref()?.stdout;
|
||||
|
||||
let cc_compiler =
|
||||
compilers
|
||||
.iter()
|
||||
.find_map(|(compiler_name, compiler_hint)| {
|
||||
cc_compiler_info
|
||||
.contains(compiler_hint)
|
||||
.then_some(*compiler_name)
|
||||
})?;
|
||||
Some(Ok(Cow::Borrowed(cc_compiler)))
|
||||
}
|
||||
"version" => {
|
||||
let cc_compiler_info = &cc_compiler_info.deref().as_ref()?.stdout;
|
||||
|
||||
VersionFormatter::format_module_version(
|
||||
module.get_name(),
|
||||
cc_compiler_info
|
||||
.split_whitespace()
|
||||
.find(|word| Version::parse(word).is_ok())?,
|
||||
config.version_format,
|
||||
)
|
||||
.map(Cow::Owned)
|
||||
.map(Ok)
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
.parse(None, Some(context))
|
||||
})
|
||||
}
|
||||
|
||||
fn create_module<'a, T>(
|
||||
context: &'a Context,
|
||||
lang: &str,
|
||||
compilers: [(&str, &str); 2],
|
||||
mut module: Module<'a>,
|
||||
config: CcConfig<T>,
|
||||
) -> Option<Module<'a>> {
|
||||
if config.disabled {
|
||||
return None;
|
||||
}
|
||||
|
||||
if !is_cc_project(&config, context)? {
|
||||
return None;
|
||||
}
|
||||
|
||||
let parsed = parse_module(context, &mut module, config, compilers);
|
||||
|
||||
module.set_segments(match parsed {
|
||||
Ok(segments) => segments,
|
||||
Err(error) => {
|
||||
log::warn!("Error in module `cc` for `lang: {}` :\n{}", lang, error);
|
||||
return None;
|
||||
}
|
||||
});
|
||||
|
||||
Some(module)
|
||||
}
|
||||
|
||||
pub fn module<'a>(context: &'a Context, lang: Lang) -> Option<Module<'a>> {
|
||||
match lang {
|
||||
Lang::C => {
|
||||
let lang = "c";
|
||||
let compilers = [("clang", "clang"), ("gcc", "Free Software Foundation")];
|
||||
let module = context.new_module(lang);
|
||||
let config = CConfig::try_load(module.config);
|
||||
|
||||
create_module::<CConfigMarker>(context, lang, compilers, module, config)
|
||||
}
|
||||
Lang::Cpp => {
|
||||
let lang = "cpp";
|
||||
let compilers = [("clang++", "clang"), ("g++", "Free Software Foundation")];
|
||||
let module = context.new_module(lang);
|
||||
let config = CppConfig::try_load(module.config);
|
||||
|
||||
create_module::<CppConfigMarker>(context, lang, compilers, module, config)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
use super::{Context, Module};
|
||||
use crate::modules::cc::{Lang, module as cc_module};
|
||||
|
||||
/// Creates a module with the current C compiler and version
|
||||
pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||
cc_module(context, Lang::Cpp)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{test::ModuleRenderer, utils::CommandOutput};
|
||||
use nu_ansi_term::Color;
|
||||
use std::fs::File;
|
||||
use std::io;
|
||||
|
||||
#[test]
|
||||
fn folder_without_cpp_files() -> io::Result<()> {
|
||||
let dir = tempfile::tempdir()?;
|
||||
|
||||
let actual = ModuleRenderer::new("cpp")
|
||||
.config(toml::toml! {
|
||||
[cpp]
|
||||
disabled = false
|
||||
})
|
||||
.path(dir.path())
|
||||
.collect();
|
||||
|
||||
let expected = None;
|
||||
assert_eq!(expected, actual);
|
||||
dir.close()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn folder_with_cpp_file() -> io::Result<()> {
|
||||
let dir = tempfile::tempdir()?;
|
||||
File::create(dir.path().join("any.cpp"))?.sync_all()?;
|
||||
|
||||
// What happens when `c++ --version` says it's modern clang++?
|
||||
// The case when it claims to be g++ is covered in folder_with_hpp_file,
|
||||
let actual = ModuleRenderer::new("cpp")
|
||||
.config(toml::toml! {
|
||||
[cpp]
|
||||
disabled = false
|
||||
})
|
||||
.cmd(
|
||||
"c++ --version",
|
||||
Some(CommandOutput {
|
||||
stdout: String::from(
|
||||
"\
|
||||
clang version 19.1.7
|
||||
Target: x86_64-pc-linux-gnu
|
||||
Thread model: posix
|
||||
InstalledDir: /usr/bin",
|
||||
),
|
||||
stderr: String::default(),
|
||||
}),
|
||||
)
|
||||
.path(dir.path())
|
||||
.collect();
|
||||
let expected = Some(format!(
|
||||
"via {}",
|
||||
Color::Fixed(149).bold().paint("C++ v19.1.7-clang++ ")
|
||||
));
|
||||
assert_eq!(expected, actual);
|
||||
|
||||
// What happens when `c++ --version` says it's ancient gcc?
|
||||
let actual = ModuleRenderer::new("cpp")
|
||||
.config(toml::toml! {
|
||||
[cpp]
|
||||
disabled = false
|
||||
})
|
||||
.cmd(
|
||||
"c++ --version",
|
||||
Some(CommandOutput {
|
||||
stdout: String::from(
|
||||
"\
|
||||
c++ (GCC) 3.3.5
|
||||
Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
This is free software; see the source for copying conditions. There is NO
|
||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.",
|
||||
),
|
||||
stderr: String::default(),
|
||||
}),
|
||||
)
|
||||
.path(dir.path())
|
||||
.collect();
|
||||
let expected = Some(format!(
|
||||
"via {}",
|
||||
Color::Fixed(149).bold().paint("C++ v3.3.5-g++ ")
|
||||
));
|
||||
assert_eq!(expected, actual);
|
||||
|
||||
// What happens with an unknown C++ compiler?
|
||||
let actual = ModuleRenderer::new("cpp")
|
||||
.config(toml::toml! {
|
||||
[cpp]
|
||||
disabled = false
|
||||
})
|
||||
.cmd(
|
||||
"c++ --version",
|
||||
Some(CommandOutput {
|
||||
stdout: String::from("HISOFT-C++ Compiler V1.2\nCopyright © 1984 HISOFT"),
|
||||
stderr: String::default(),
|
||||
}),
|
||||
)
|
||||
.path(dir.path())
|
||||
.collect();
|
||||
let expected = Some(format!("via {}", Color::Fixed(149).bold().paint("C++ ")));
|
||||
assert_eq!(expected, actual);
|
||||
|
||||
// What happens when 'c++ --version' doesn't work, but 'g++ --version' does?
|
||||
// This stubs out `c++` but we'll fall back to `g++ --version`
|
||||
let actual = ModuleRenderer::new("cpp")
|
||||
.config(toml::toml! {
|
||||
[cpp]
|
||||
disabled = false
|
||||
})
|
||||
.cmd("c++ --version", None)
|
||||
.path(dir.path())
|
||||
.collect();
|
||||
let expected = Some(format!(
|
||||
"via {}",
|
||||
Color::Fixed(149).bold().paint("C++ v14.2.1-g++ ")
|
||||
));
|
||||
assert_eq!(expected, actual);
|
||||
|
||||
// Now with both 'c++' and 'g++' not working, this should fall back to 'clang++ --version'
|
||||
let actual = ModuleRenderer::new("cpp")
|
||||
.config(toml::toml! {
|
||||
[cpp]
|
||||
disabled = false
|
||||
})
|
||||
.cmd("c++ --version", None)
|
||||
.cmd("g++ --version", None)
|
||||
.path(dir.path())
|
||||
.collect();
|
||||
let expected = Some(format!(
|
||||
"via {}",
|
||||
Color::Fixed(149).bold().paint("C++ v19.1.7-clang++ ")
|
||||
));
|
||||
assert_eq!(expected, actual);
|
||||
|
||||
// What happens when we can't find any of c++, g++ or clang++?
|
||||
let actual = ModuleRenderer::new("cpp")
|
||||
.config(toml::toml! {
|
||||
[cpp]
|
||||
disabled = false
|
||||
})
|
||||
.cmd("c++ --version", None)
|
||||
.cmd("g++ --version", None)
|
||||
.cmd("clang++ --version", None)
|
||||
.path(dir.path())
|
||||
.collect();
|
||||
let expected = Some(format!("via {}", Color::Fixed(149).bold().paint("C++ ")));
|
||||
assert_eq!(expected, actual);
|
||||
|
||||
dir.close()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn folder_with_hpp_file() -> io::Result<()> {
|
||||
let dir = tempfile::tempdir()?;
|
||||
File::create(dir.path().join("any.hpp"))?.sync_all()?;
|
||||
|
||||
let actual = ModuleRenderer::new("cpp")
|
||||
.config(toml::toml! {
|
||||
[cpp]
|
||||
disabled = false
|
||||
})
|
||||
.path(dir.path())
|
||||
.collect();
|
||||
let expected = Some(format!(
|
||||
"via {}",
|
||||
Color::Fixed(149).bold().paint("C++ v14.2.1-g++ ")
|
||||
));
|
||||
|
||||
assert_eq!(expected, actual);
|
||||
dir.close()
|
||||
}
|
||||
}
|
||||
@@ -4,12 +4,14 @@ mod azure;
|
||||
mod buf;
|
||||
mod bun;
|
||||
mod c;
|
||||
mod cc;
|
||||
mod character;
|
||||
mod cmake;
|
||||
mod cmd_duration;
|
||||
mod cobol;
|
||||
mod conda;
|
||||
mod container;
|
||||
mod cpp;
|
||||
mod crystal;
|
||||
pub mod custom;
|
||||
mod daml;
|
||||
@@ -125,6 +127,7 @@ pub fn handle<'a>(module: &str, context: &'a Context) -> Option<Module<'a>> {
|
||||
"cobol" => cobol::module(context),
|
||||
"conda" => conda::module(context),
|
||||
"container" => container::module(context),
|
||||
"cpp" => cpp::module(context),
|
||||
"daml" => daml::module(context),
|
||||
"dart" => dart::module(context),
|
||||
"deno" => deno::module(context),
|
||||
@@ -251,6 +254,7 @@ pub fn description(module: &str) -> &'static str {
|
||||
"cobol" => "The currently installed version of COBOL/GNUCOBOL",
|
||||
"conda" => "The current conda environment, if $CONDA_DEFAULT_ENV is set",
|
||||
"container" => "The container indicator, if inside a container.",
|
||||
"cpp" => "your cpp compiler type",
|
||||
"crystal" => "The currently installed version of Crystal",
|
||||
"daml" => "The Daml SDK version of your project",
|
||||
"dart" => "The currently installed version of Dart",
|
||||
|
||||
@@ -197,6 +197,36 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.",
|
||||
OpenBSD clang version 11.1.0
|
||||
Target: amd64-unknown-openbsd7.0
|
||||
Thread model: posix
|
||||
InstalledDir: /usr/bin",
|
||||
),
|
||||
stderr: String::default(),
|
||||
}),
|
||||
"c++ --version" => Some(CommandOutput {
|
||||
stdout: String::from(
|
||||
"\
|
||||
c++ (GCC) 14.2.1 20240910
|
||||
Copyright (C) 2024 Free Software Foundation, Inc.
|
||||
This is free software; see the source for copying conditions. There is NO
|
||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.",
|
||||
),
|
||||
stderr: String::default(),
|
||||
}),
|
||||
"g++ --version" => Some(CommandOutput {
|
||||
stdout: String::from(
|
||||
"\
|
||||
g++ (GCC) 14.2.1 20240910
|
||||
Copyright (C) 2024 Free Software Foundation, Inc.
|
||||
This is free software; see the source for copying conditions. There is NO
|
||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.",
|
||||
),
|
||||
stderr: String::default(),
|
||||
}),
|
||||
"clang++ --version" => Some(CommandOutput {
|
||||
stdout: String::from(
|
||||
"\
|
||||
clang version 19.1.7
|
||||
Target: x86_64-pc-linux-gnu
|
||||
Thread model: posix
|
||||
InstalledDir: /usr/bin",
|
||||
),
|
||||
stderr: String::default(),
|
||||
|
||||
Reference in New Issue
Block a user