feat(localip): add module to print the current ipv4 address (#3289)

This commit is contained in:
QuiCkSTaR 2022-01-30 21:31:26 +01:00 committed by GitHub
parent 6e24358052
commit 5a26355b0e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 212 additions and 10 deletions

7
Cargo.lock generated
View File

@ -818,6 +818,12 @@ version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3"
[[package]]
name = "local_ipaddress"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6a104730949fbc4c78e4fa98ed769ca0faa02e9818936b61032d2d77526afa9"
[[package]] [[package]]
name = "log" name = "log"
version = "0.4.14" version = "0.4.14"
@ -1605,6 +1611,7 @@ dependencies = [
"gethostname", "gethostname",
"git2", "git2",
"indexmap", "indexmap",
"local_ipaddress",
"log", "log",
"mockall", "mockall",
"nix 0.23.1", "nix 0.23.1",

View File

@ -36,6 +36,7 @@ directories-next = "2.0.0"
gethostname = "0.2.2" gethostname = "0.2.2"
git2 = { version = "0.13.25", default-features = false } git2 = { version = "0.13.25", default-features = false }
indexmap = { version = "1.8.0", features = ["serde"] } indexmap = { version = "1.8.0", features = ["serde"] }
local_ipaddress = "0.1.3"
log = { version = "0.4.14", features = ["std"] } log = { version = "0.4.14", features = ["std"] }
notify-rust = { version = "4.5.5", optional = true } notify-rust = { version = "4.5.5", optional = true }
once_cell = "1.9.0" once_cell = "1.9.0"

View File

@ -192,6 +192,7 @@ format = "$all"
format = """ format = """
$username\ $username\
$hostname\ $hostname\
$localip\
$shlvl\ $shlvl\
$singularity\ $singularity\
$kubernetes\ $kubernetes\
@ -1728,16 +1729,17 @@ then the module will also show when there are 0 jobs running.
### Options ### Options
| Option | Default | Description | | Option | Default | Description |
| ------------------------------------------------------------------------------------------------------- | ----------------------------- | ------------------------------------------------------------------------ | | ------------------ | ----------------------------- | ------------------------------------------------------------------------ |
| `threshold`* | `1` | Show number of jobs if exceeded. | | `threshold`* | `1` | Show number of jobs if exceeded. |
| `symbol_threshold` | `1` | Show `symbol` if the job count is at least `symbol_threshold`. | | `symbol_threshold` | `1` | Show `symbol` if the job count is at least `symbol_threshold`. |
| `number_threshold` | `2` | Show the number of jobs if the job count is at least `number_threshold`. | | `number_threshold` | `2` | Show the number of jobs if the job count is at least `number_threshold`. |
| `format` | `"[$symbol$number]($style) "` | The format for the module. | | `format` | `"[$symbol$number]($style) "` | The format for the module. |
| `symbol` | `"✦"` | The string used to represent the `symbol` variable. | | `symbol` | `"✦"` | The string used to represent the `symbol` variable. |
| `style` | `"bold blue"` | The style for the module. | | `style` | `"bold blue"` | The style for the module. |
| `disabled` | `false` | Disables the `jobs` module. | | `disabled` | `false` | Disables the `jobs` module. |
| *: This option is deprecated, please use the `number_threshold` and `symbol_threshold` options instead. | | |
*: This option is deprecated, please use the `number_threshold` and `symbol_threshold` options instead.
### Variables ### Variables
@ -1801,6 +1803,39 @@ By default the module will be shown if any of the following conditions are met:
symbol = "∴ " symbol = "∴ "
``` ```
## localip
The `localip` module shows the IPv4 address of the primary network interface.
### Options
| Option | Default | Description |
| ---------- | ------------------------- | ------------------------------------------------------ |
| `ssh_only` | `true` | Only show IP address when connected to an SSH session. |
| `format` | `"[$localipv4]($style) "` | The format for the module. |
| `style` | `"bold yellow"` | The style for the module. |
| `disabled` | `true` | Disables the `localip` module. |
### Variables
| Variable | Example | Description |
| --------- | ------------ | ----------------------------------- |
| localipv4 | 192.168.1.13 | Contains the primary IPv4 address |
| style\* | | Mirrors the value of option `style` |
*: This variable can only be used as a part of a style string
### Example
```toml
# ~/.config/starship.toml
[localip]
ssh_only = false
format = "@[$localipv4](bold red) "
disabled = false
```
## Kotlin ## Kotlin
The `kotlin` module shows the currently installed version of [Kotlin](https://kotlinlang.org/). The `kotlin` module shows the currently installed version of [Kotlin](https://kotlinlang.org/).

23
src/configs/localip.rs Normal file
View File

@ -0,0 +1,23 @@
use crate::config::ModuleConfig;
use serde::Serialize;
use starship_module_config_derive::ModuleConfig;
#[derive(Clone, ModuleConfig, Serialize)]
pub struct LocalipConfig<'a> {
pub ssh_only: bool,
pub format: &'a str,
pub style: &'a str,
pub disabled: bool,
}
impl<'a> Default for LocalipConfig<'a> {
fn default() -> Self {
LocalipConfig {
ssh_only: true,
format: "[$localipv4]($style) ",
style: "yellow bold",
disabled: true,
}
}
}

View File

@ -40,6 +40,7 @@ pub mod julia;
pub mod kotlin; pub mod kotlin;
pub mod kubernetes; pub mod kubernetes;
pub mod line_break; pub mod line_break;
pub mod localip;
pub mod lua; pub mod lua;
pub mod memory_usage; pub mod memory_usage;
pub mod nim; pub mod nim;
@ -122,6 +123,7 @@ pub struct FullConfig<'a> {
kotlin: kotlin::KotlinConfig<'a>, kotlin: kotlin::KotlinConfig<'a>,
kubernetes: kubernetes::KubernetesConfig<'a>, kubernetes: kubernetes::KubernetesConfig<'a>,
line_break: line_break::LineBreakConfig, line_break: line_break::LineBreakConfig,
localip: localip::LocalipConfig<'a>,
lua: lua::LuaConfig<'a>, lua: lua::LuaConfig<'a>,
memory_usage: memory_usage::MemoryConfig<'a>, memory_usage: memory_usage::MemoryConfig<'a>,
nim: nim::NimConfig<'a>, nim: nim::NimConfig<'a>,
@ -202,6 +204,7 @@ impl<'a> Default for FullConfig<'a> {
kotlin: Default::default(), kotlin: Default::default(),
kubernetes: Default::default(), kubernetes: Default::default(),
line_break: Default::default(), line_break: Default::default(),
localip: Default::default(),
lua: Default::default(), lua: Default::default(),
memory_usage: Default::default(), memory_usage: Default::default(),
nim: Default::default(), nim: Default::default(),

View File

@ -20,6 +20,7 @@ pub struct StarshipRootConfig {
pub const PROMPT_ORDER: &[&str] = &[ pub const PROMPT_ORDER: &[&str] = &[
"username", "username",
"hostname", "hostname",
"localip",
"shlvl", "shlvl",
"singularity", "singularity",
"kubernetes", "kubernetes",

View File

@ -45,6 +45,7 @@ pub const ALL_MODULES: &[&str] = &[
"kotlin", "kotlin",
"kubernetes", "kubernetes",
"line_break", "line_break",
"localip",
"lua", "lua",
"memory_usage", "memory_usage",
"nim", "nim",

128
src/modules/localip.rs Normal file
View File

@ -0,0 +1,128 @@
use super::{Context, Module};
use crate::config::RootModuleConfig;
use crate::configs::localip::LocalipConfig;
use crate::formatter::StringFormatter;
/// Creates a module with the ipv4 address of the local machine.
///
/// The `local_ipaddress` crate is used to determine the local IP address of your machine.
/// An accurate and fast way, especially if there are multiple IP addresses available,
/// is to connect a UDP socket and then reading its local endpoint.
///
/// Will display the ip if all of the following criteria are met:
/// - localip.disabled is absent or false
/// - localip.ssh_only is false OR the user is currently connected as an SSH session (`$SSH_CONNECTION`)
pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
let mut module = context.new_module("localip");
let config: LocalipConfig = LocalipConfig::try_load(module.config);
let ssh_connection = context.get_env("SSH_CONNECTION");
if config.ssh_only && ssh_connection.is_none() {
return None;
}
let localip = local_ipaddress::get().unwrap_or_default();
if localip.is_empty() {
log::warn!("unable to determine local ipv4 address");
return None;
}
let parsed = StringFormatter::new(config.format).and_then(|formatter| {
formatter
.map_style(|variable| match variable {
"style" => Some(Ok(config.style)),
_ => None,
})
.map(|variable| match variable {
"localipv4" => Some(Ok(&localip)),
_ => None,
})
.parse(None, Some(context))
});
module.set_segments(match parsed {
Ok(segments) => segments,
Err(error) => {
log::warn!("Error in module `localip`:\n{}", error);
return None;
}
});
Some(module)
}
#[cfg(test)]
mod tests {
use crate::test::ModuleRenderer;
use ansi_term::{Color, Style};
macro_rules! get_localip {
() => {
if let Some(localip) = local_ipaddress::get() {
localip
} else {
println!(
"localip was not tested because socket connection failed! \
This could be caused by an unconventional network setup."
);
return;
}
};
}
#[test]
fn is_ipv4_format() {
let localip = get_localip!();
assert!(regex::Regex::new(r"^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$")
.unwrap()
.is_match(&localip));
}
#[test]
fn ssh_only_false() {
let localip = get_localip!();
let actual = ModuleRenderer::new("localip")
.config(toml::toml! {
[localip]
ssh_only = false
})
.collect();
let expected = Some(format!("{} ", style().paint(localip)));
assert_eq!(expected, actual);
}
#[test]
fn no_ssh() {
let actual = ModuleRenderer::new("localip")
.config(toml::toml! {
[localip]
ssh_only = true
})
.collect();
let expected = None;
assert_eq!(expected, actual);
}
#[test]
fn ssh() {
let localip = get_localip!();
let actual = ModuleRenderer::new("localip")
.config(toml::toml! {
[localip]
ssh_only = true
trim_at = ""
})
.env("SSH_CONNECTION", "something")
.collect();
let expected = Some(format!("{} ", style().paint(localip)));
assert_eq!(expected, actual);
}
fn style() -> Style {
Color::Yellow.bold()
}
}

View File

@ -35,6 +35,7 @@ mod julia;
mod kotlin; mod kotlin;
mod kubernetes; mod kubernetes;
mod line_break; mod line_break;
mod localip;
mod lua; mod lua;
mod memory_usage; mod memory_usage;
mod nim; mod nim;
@ -121,6 +122,7 @@ pub fn handle<'a>(module: &str, context: &'a Context) -> Option<Module<'a>> {
"kotlin" => kotlin::module(context), "kotlin" => kotlin::module(context),
"kubernetes" => kubernetes::module(context), "kubernetes" => kubernetes::module(context),
"line_break" => line_break::module(context), "line_break" => line_break::module(context),
"localip" => localip::module(context),
"lua" => lua::module(context), "lua" => lua::module(context),
"memory_usage" => memory_usage::module(context), "memory_usage" => memory_usage::module(context),
"nim" => nim::module(context), "nim" => nim::module(context),
@ -212,6 +214,7 @@ pub fn description(module: &str) -> &'static str {
"kotlin" => "The currently installed version of Kotlin", "kotlin" => "The currently installed version of Kotlin",
"kubernetes" => "The current Kubernetes context name and, if set, the namespace", "kubernetes" => "The current Kubernetes context name and, if set, the namespace",
"line_break" => "Separates the prompt into two lines", "line_break" => "Separates the prompt into two lines",
"localip" => "The currently assigned ipv4 address",
"lua" => "The currently installed version of Lua", "lua" => "The currently installed version of Lua",
"memory_usage" => "Current system memory and swap usage", "memory_usage" => "Current system memory and swap usage",
"nim" => "The currently installed version of Nim", "nim" => "The currently installed version of Nim",