mirror of
https://github.com/starship/starship.git
synced 2026-06-22 02:02:12 +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": [
|
"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": {
|
"crystal": {
|
||||||
"default": {
|
"default": {
|
||||||
"detect_extensions": [
|
"detect_extensions": [
|
||||||
@@ -2272,7 +2313,7 @@
|
|||||||
},
|
},
|
||||||
"additionalProperties": false
|
"additionalProperties": false
|
||||||
},
|
},
|
||||||
"CConfig": {
|
"CcConfig_for_CConfigMarker": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"format": {
|
"format": {
|
||||||
@@ -2583,6 +2624,86 @@
|
|||||||
},
|
},
|
||||||
"additionalProperties": false
|
"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": {
|
"CrystalConfig": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"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)'
|
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
|
## Character
|
||||||
|
|
||||||
The `character` module shows a character (usually an arrow) beside where the text
|
The `character` module shows a character (usually an arrow) beside where the text
|
||||||
|
|||||||
@@ -7,6 +7,9 @@ format = '\[[$symbol($version)]($style)\]'
|
|||||||
[c]
|
[c]
|
||||||
format = '\[[$symbol($version(-$name))]($style)\]'
|
format = '\[[$symbol($version(-$name))]($style)\]'
|
||||||
|
|
||||||
|
[cpp]
|
||||||
|
format = '\[[$symbol($version(-$name))]($style)\]'
|
||||||
|
|
||||||
[cmake]
|
[cmake]
|
||||||
format = '\[[$symbol($version)]($style)\]'
|
format = '\[[$symbol($version)]($style)\]'
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ $git_branch\
|
|||||||
$git_status\
|
$git_status\
|
||||||
[](fg:color_aqua bg:color_blue)\
|
[](fg:color_aqua bg:color_blue)\
|
||||||
$c\
|
$c\
|
||||||
|
$cpp\
|
||||||
$rust\
|
$rust\
|
||||||
$golang\
|
$golang\
|
||||||
$nodejs\
|
$nodejs\
|
||||||
@@ -106,6 +107,11 @@ symbol = " "
|
|||||||
style = "bg:color_blue"
|
style = "bg:color_blue"
|
||||||
format = '[[ $symbol( $version) ](fg:color_fg0 bg:color_blue)]($style)'
|
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]
|
[rust]
|
||||||
symbol = ""
|
symbol = ""
|
||||||
style = "bg:color_blue"
|
style = "bg:color_blue"
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ $pijul_channel\
|
|||||||
$docker_context\
|
$docker_context\
|
||||||
$package\
|
$package\
|
||||||
$c\
|
$c\
|
||||||
|
$cpp\
|
||||||
$cmake\
|
$cmake\
|
||||||
$cobol\
|
$cobol\
|
||||||
$daml\
|
$daml\
|
||||||
@@ -258,6 +259,10 @@ format = " [buf](italic) [$symbol $version $buf_version]($style)"
|
|||||||
symbol = "ℂ "
|
symbol = "ℂ "
|
||||||
format = " [$symbol($version(-$name))]($style)"
|
format = " [$symbol($version(-$name))]($style)"
|
||||||
|
|
||||||
|
[cpp]
|
||||||
|
symbol = "ℂ "
|
||||||
|
format = " [$symbol($version(-$name))]($style)"
|
||||||
|
|
||||||
[conda]
|
[conda]
|
||||||
symbol = "◯ "
|
symbol = "◯ "
|
||||||
format = " conda [$symbol$environment]($style)"
|
format = " conda [$symbol$environment]($style)"
|
||||||
|
|||||||
@@ -10,6 +10,9 @@ symbol = " "
|
|||||||
[c]
|
[c]
|
||||||
symbol = " "
|
symbol = " "
|
||||||
|
|
||||||
|
[cpp]
|
||||||
|
symbol = " "
|
||||||
|
|
||||||
[cmake]
|
[cmake]
|
||||||
symbol = " "
|
symbol = " "
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,9 @@ format = '(via [$symbol($version )]($style))'
|
|||||||
[c]
|
[c]
|
||||||
format = '(via [$symbol($version(-$name) )]($style))'
|
format = '(via [$symbol($version(-$name) )]($style))'
|
||||||
|
|
||||||
|
[cpp]
|
||||||
|
format = '(via [$symbol($version(-$name) )]($style))'
|
||||||
|
|
||||||
[cmake]
|
[cmake]
|
||||||
format = '(via [$symbol($version )]($style))'
|
format = '(via [$symbol($version )]($style))'
|
||||||
|
|
||||||
|
|||||||
@@ -69,6 +69,11 @@ symbol = " "
|
|||||||
style = "bg:#86BBD8"
|
style = "bg:#86BBD8"
|
||||||
format = '[ $symbol ($version) ]($style)'
|
format = '[ $symbol ($version) ]($style)'
|
||||||
|
|
||||||
|
[cpp]
|
||||||
|
symbol = " "
|
||||||
|
style = "bg:#86BBD8"
|
||||||
|
format = '[ $symbol ($version) ]($style)'
|
||||||
|
|
||||||
[docker_context]
|
[docker_context]
|
||||||
symbol = " "
|
symbol = " "
|
||||||
style = "bg:#06969A"
|
style = "bg:#06969A"
|
||||||
|
|||||||
@@ -28,6 +28,9 @@ symbol = "bun "
|
|||||||
[c]
|
[c]
|
||||||
symbol = "C "
|
symbol = "C "
|
||||||
|
|
||||||
|
[cpp]
|
||||||
|
symbol = "C++ "
|
||||||
|
|
||||||
[cobol]
|
[cobol]
|
||||||
symbol = "cobol "
|
symbol = "cobol "
|
||||||
|
|
||||||
|
|||||||
+8
-14
@@ -1,27 +1,21 @@
|
|||||||
|
use crate::configs::cc::CcConfig;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Clone, Deserialize, Serialize)]
|
#[derive(Default, Clone, Deserialize, Serialize)]
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "config-schema",
|
feature = "config-schema",
|
||||||
derive(schemars::JsonSchema),
|
derive(schemars::JsonSchema),
|
||||||
schemars(deny_unknown_fields)
|
schemars(deny_unknown_fields)
|
||||||
)]
|
)]
|
||||||
#[serde(default)]
|
pub struct CConfigMarker;
|
||||||
pub struct CConfig<'a> {
|
|
||||||
pub format: &'a str,
|
pub type CConfig<'a> = CcConfig<'a, CConfigMarker>;
|
||||||
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>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for CConfig<'_> {
|
impl Default for CConfig<'_> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
CConfig {
|
CcConfig {
|
||||||
|
marker: std::marker::PhantomData::<CConfigMarker>,
|
||||||
|
|
||||||
format: "via [$symbol($version(-$name) )]($style)",
|
format: "via [$symbol($version(-$name) )]($style)",
|
||||||
version_format: "v${raw}",
|
version_format: "v${raw}",
|
||||||
style: "149 bold",
|
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 buf;
|
||||||
pub mod bun;
|
pub mod bun;
|
||||||
pub mod c;
|
pub mod c;
|
||||||
|
pub mod cc;
|
||||||
pub mod character;
|
pub mod character;
|
||||||
pub mod cmake;
|
pub mod cmake;
|
||||||
pub mod cmd_duration;
|
pub mod cmd_duration;
|
||||||
pub mod cobol;
|
pub mod cobol;
|
||||||
pub mod conda;
|
pub mod conda;
|
||||||
pub mod container;
|
pub mod container;
|
||||||
|
pub mod cpp;
|
||||||
pub mod crystal;
|
pub mod crystal;
|
||||||
pub mod custom;
|
pub mod custom;
|
||||||
pub mod daml;
|
pub mod daml;
|
||||||
@@ -140,6 +142,8 @@ pub struct FullConfig<'a> {
|
|||||||
#[serde(borrow)]
|
#[serde(borrow)]
|
||||||
container: container::ContainerConfig<'a>,
|
container: container::ContainerConfig<'a>,
|
||||||
#[serde(borrow)]
|
#[serde(borrow)]
|
||||||
|
cpp: cpp::CppConfig<'a>,
|
||||||
|
#[serde(borrow)]
|
||||||
crystal: crystal::CrystalConfig<'a>,
|
crystal: crystal::CrystalConfig<'a>,
|
||||||
#[serde(borrow)]
|
#[serde(borrow)]
|
||||||
daml: daml::DamlConfig<'a>,
|
daml: daml::DamlConfig<'a>,
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ pub const PROMPT_ORDER: &[&str] = &[
|
|||||||
"c",
|
"c",
|
||||||
"cmake",
|
"cmake",
|
||||||
"cobol",
|
"cobol",
|
||||||
|
"cpp",
|
||||||
"daml",
|
"daml",
|
||||||
"dart",
|
"dart",
|
||||||
"deno",
|
"deno",
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ pub const ALL_MODULES: &[&str] = &[
|
|||||||
"cobol",
|
"cobol",
|
||||||
"conda",
|
"conda",
|
||||||
"container",
|
"container",
|
||||||
|
"cpp",
|
||||||
"crystal",
|
"crystal",
|
||||||
"daml",
|
"daml",
|
||||||
"dart",
|
"dart",
|
||||||
|
|||||||
+3
-86
@@ -1,92 +1,9 @@
|
|||||||
use super::{Context, Module, ModuleConfig};
|
use super::{Context, Module};
|
||||||
|
use crate::modules::cc::{Lang, module as cc_module};
|
||||||
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;
|
|
||||||
|
|
||||||
/// Creates a module with the current C compiler and version
|
/// Creates a module with the current C compiler and version
|
||||||
pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
|
||||||
let mut module = context.new_module("c");
|
cc_module(context, Lang::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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[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 buf;
|
||||||
mod bun;
|
mod bun;
|
||||||
mod c;
|
mod c;
|
||||||
|
mod cc;
|
||||||
mod character;
|
mod character;
|
||||||
mod cmake;
|
mod cmake;
|
||||||
mod cmd_duration;
|
mod cmd_duration;
|
||||||
mod cobol;
|
mod cobol;
|
||||||
mod conda;
|
mod conda;
|
||||||
mod container;
|
mod container;
|
||||||
|
mod cpp;
|
||||||
mod crystal;
|
mod crystal;
|
||||||
pub mod custom;
|
pub mod custom;
|
||||||
mod daml;
|
mod daml;
|
||||||
@@ -125,6 +127,7 @@ pub fn handle<'a>(module: &str, context: &'a Context) -> Option<Module<'a>> {
|
|||||||
"cobol" => cobol::module(context),
|
"cobol" => cobol::module(context),
|
||||||
"conda" => conda::module(context),
|
"conda" => conda::module(context),
|
||||||
"container" => container::module(context),
|
"container" => container::module(context),
|
||||||
|
"cpp" => cpp::module(context),
|
||||||
"daml" => daml::module(context),
|
"daml" => daml::module(context),
|
||||||
"dart" => dart::module(context),
|
"dart" => dart::module(context),
|
||||||
"deno" => deno::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",
|
"cobol" => "The currently installed version of COBOL/GNUCOBOL",
|
||||||
"conda" => "The current conda environment, if $CONDA_DEFAULT_ENV is set",
|
"conda" => "The current conda environment, if $CONDA_DEFAULT_ENV is set",
|
||||||
"container" => "The container indicator, if inside a container.",
|
"container" => "The container indicator, if inside a container.",
|
||||||
|
"cpp" => "your cpp compiler type",
|
||||||
"crystal" => "The currently installed version of Crystal",
|
"crystal" => "The currently installed version of Crystal",
|
||||||
"daml" => "The Daml SDK version of your project",
|
"daml" => "The Daml SDK version of your project",
|
||||||
"dart" => "The currently installed version of Dart",
|
"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
|
OpenBSD clang version 11.1.0
|
||||||
Target: amd64-unknown-openbsd7.0
|
Target: amd64-unknown-openbsd7.0
|
||||||
Thread model: posix
|
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",
|
InstalledDir: /usr/bin",
|
||||||
),
|
),
|
||||||
stderr: String::default(),
|
stderr: String::default(),
|
||||||
|
|||||||
Reference in New Issue
Block a user