diff --git a/.gitignore b/.gitignore
index 029a7af..384b407 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,4 +2,5 @@
bacon.toml
Cargo.lock
.DS_Store
-Dockerfile
\ No newline at end of file
+Dockerfile
+.idea/
\ No newline at end of file
diff --git a/Cargo.toml b/Cargo.toml
index 185977b..63b250f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -12,6 +12,7 @@ keywords = ["system", "cli", "fetch", "asynchronous", "asynch"]
categories = ["command-line-utilities"]
[dependencies]
+any_terminal_size = {version = "0.1.21", default-features = false}
console = { version = "0.15.0", default-features = false, features = ["ansi-parsing"] }
dirs = { version = "4.0.0", default-features = false }
libmacchina = { version = "3.8.6", default-features = false }
diff --git a/README.md b/README.md
index 2fdae46..fab05e5 100644
--- a/README.md
+++ b/README.md
@@ -178,7 +178,7 @@ OPTIONS:
| pre_text_style | A format string with each word separated by dots that describes the style of the text that before this module |
| pre_text | Text that comes before this module |
| output_style | A format string with each word separated by dots that describes the style of the output text |
-| Command | The command to run to get the output of the module |
+| command | The command to run to get the output of the module |
# Default Configuration
A default Configuration will look like so:
diff --git a/src/config.rs b/src/config.rs
index 1dd2000..fb2db5d 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -1,7 +1,10 @@
use crate::cli::Mode;
use crate::cli::Opt;
use crate::handle_error;
-use crate::modules::*;
+use crate::modules::{
+ Cpu, Delimiter, DesktopEnvironment, Format, Host, Kernel, Module, Os, Packages, Resolution,
+ Shell, Terminal, Uptime, User, WindowManager,
+};
use console::measure_text_width;
use console::style;
use console::Style;
@@ -29,6 +32,7 @@ pub struct Config {
desktop_environment: DesktopEnvironment,
window_manager: WindowManager,
terminal: Terminal,
+ cpu: Cpu,
#[serde(flatten)]
custom_modules: HashMap,
@@ -84,7 +88,7 @@ impl Config {
{line_len_sep} |",
error = r,
line_len_sep = " ".repeat(line.to_string().len()),
- col_len_sep = " ".repeat(column as usize),
+ col_len_sep = " ".repeat(column.try_into().unwrap()),
line = line,
line_contents =
string.lines().collect::>()[(line - 1) as usize],
@@ -123,7 +127,9 @@ impl Config {
let desktop_environment = self_clone.desktop_environment;
let window_manager = self_clone.window_manager;
let terminal = self_clone.terminal;
+ let cpu = self_clone.cpu;
let custom = self_clone.custom_modules;
+
if modules.contains(&"user") {
let handle = thread::spawn(move || (String::from("user"), user.get_info()));
handles.push(handle);
@@ -174,6 +180,10 @@ impl Config {
let handle = thread::spawn(move || (String::from("terminal"), terminal.get_info()));
handles.push(handle);
}
+ if modules.contains(&"cpu") {
+ let handle = thread::spawn(move || (String::from("cpu"), cpu.get_info()));
+ handles.push(handle);
+ }
for (name, module) in custom {
let handle = thread::spawn(move || (name, module.get_info()));
handles.push(handle);
@@ -202,8 +212,8 @@ impl Config {
vec
}
- fn logo(&self) -> Vec {
- let os = self.os.get_os();
+ fn logo() -> Vec {
+ let os = crate::modules::Os::get_os();
match os.trim() {
x if x.contains("macOS") => {
let yellow = Style::from_dotted_str("yellow.bold");
@@ -270,18 +280,49 @@ impl Config {
fn get_logo(&self) -> Vec {
if self.logo_cmd.is_empty() || self.logo_cmd == "auto" {
- self.logo()
+ Config::logo()
} else {
Config::run_cmd(&self.logo_cmd, "Failed to run logo command")
.lines()
- .map(|v| v.to_string())
+ .map(str::to_string)
.collect::>()
}
}
+ fn wrap_lines(module_order: &[String], logo: &[String]) -> Vec {
+ use any_terminal_size::{any_terminal_size, Width};
+
+ let size = any_terminal_size();
+ let mut terminal_width: usize = 0;
+ if let Some((Width(width), _)) = size {
+ terminal_width = width as usize;
+ }
+ let mut module_order_wrapped = Vec::new();
+
+ for (i, string) in module_order.iter().enumerate() {
+ if string.len() >= terminal_width - logo[i].len() {
+ use std::str;
+ let mut subs = string
+ .as_bytes()
+ .chunks(terminal_width - logo[i].len())
+ .map(str::from_utf8)
+ .collect::, _>>()
+ .unwrap();
+
+ module_order_wrapped.append(&mut subs);
+ } else {
+ module_order_wrapped.push(string);
+ }
+ }
+ module_order_wrapped
+ .iter()
+ .map(|&x| x.to_string())
+ .collect::>()
+ }
+
fn print_classic(&self) {
let mut sidelogo = self.get_logo();
- let mut order = self.module_order();
+ let mut order = Config::wrap_lines(&self.module_order(), &sidelogo);
let maxlength = self.logo_maxlength();
@@ -319,35 +360,30 @@ impl Config {
}
fn logo_maxlength(&self) -> usize {
- match self
+ if let Some(v) = self
.get_logo()
.iter()
.max_by_key(|&x| measure_text_width(x))
{
- Some(v) => measure_text_width(v),
- None => {
- UserFacingError::new("Failed to find logo line with greatest length")
- .print_and_exit();
- unreachable!()
- }
+ return measure_text_width(v);
}
+ UserFacingError::new("Failed to find logo line with greatest length").print_and_exit();
+ unreachable!()
}
fn info_maxlength(info: &[String]) -> usize {
- match info.iter().max_by_key(|&x| measure_text_width(x)) {
- Some(v) => measure_text_width(v),
- None => {
- UserFacingError::new("Failed to find info line with the greatest length")
- .help("Make sure that you have some modules defined.")
- .print_and_exit();
- unreachable!()
- }
+ if let Some(v) = info.iter().max_by_key(|&x| measure_text_width(x)) {
+ return measure_text_width(v);
}
+ UserFacingError::new("Failed to find info line with the greatest length")
+ .help("Make sure that you have some modules defined.")
+ .print_and_exit();
+ unreachable!()
}
fn print_side_table(&self) {
let mut sidelogo = self.get_logo();
- let mut info = self.module_order();
+ let mut info = Config::wrap_lines(&self.module_order(), &sidelogo);
let mut counter = 0;
info.resize(sidelogo.len() + self.format.padding_top, String::from(""));
sidelogo.resize(info.len() + self.format.padding_top, String::from(""));
@@ -412,7 +448,7 @@ impl Config {
fn print_bottom_table(&self) {
let sidelogo = self.get_logo();
- let info = self.module_order();
+ let info = Config::wrap_lines(&self.module_order(), &sidelogo);
let info_maxlength = Config::info_maxlength(&info);
for line in sidelogo {
@@ -432,7 +468,7 @@ impl Config {
"{vertical}{}{vertical}",
" ".repeat(info_maxlength + self.format.padding_right + self.format.padding_left),
vertical = self.format.vertical_char
- )
+ );
}
for line in info {
println!(
@@ -457,19 +493,18 @@ impl Config {
pub fn print(&self) {
let matches = Config::get_args();
- if let Some(v) = matches.mode {
- match v {
+ matches.mode.map_or_else(
+ || match self.format.mode {
Mode::Classic => self.print_classic(),
Mode::BottomBlock => self.print_bottom_table(),
Mode::SideBlock => self.print_side_table(),
- }
- } else {
- match self.format.mode {
+ },
+ |v| match v {
Mode::Classic => self.print_classic(),
Mode::BottomBlock => self.print_bottom_table(),
Mode::SideBlock => self.print_side_table(),
- }
- }
+ },
+ );
}
}
@@ -478,7 +513,7 @@ impl Default for Config {
Config {
offset: 4,
module_order: String::from(
- "user delimiter os host kernel uptime packages shell resolution desktop_environment window_manager terminal",
+ "user delimiter os host kernel uptime packages shell resolution desktop_environment window_manager terminal cpu",
),
logo_cmd: String::from("auto"),
format: Format::default(),
@@ -495,6 +530,7 @@ impl Default for Config {
desktop_environment: DesktopEnvironment::default(),
window_manager: WindowManager::default(),
terminal: Terminal::default(),
+ cpu: Cpu::default(),
}
}
}
diff --git a/src/main.rs b/src/main.rs
index 79b4d6c..103763d 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,3 +1,4 @@
+#![warn(clippy::pedantic)]
mod cli;
mod config;
mod modules;
diff --git a/src/modules.rs b/src/modules.rs
index d72d6d1..8124799 100644
--- a/src/modules.rs
+++ b/src/modules.rs
@@ -27,7 +27,7 @@ pub struct Format {
impl Default for Format {
fn default() -> Self {
- Format {
+ Self {
mode: Mode::Classic,
top_left_corner_char: '╭',
top_right_corner_char: '╮',
@@ -54,7 +54,7 @@ pub struct User {
impl Default for User {
fn default() -> Self {
- User {
+ Self {
pre_text_style: String::from("bold.yellow"),
pre_text: String::from(""),
output_style: String::from("bold.yellow"),
@@ -89,7 +89,7 @@ pub struct Delimiter {
impl Default for Delimiter {
fn default() -> Self {
- Delimiter {
+ Self {
style: String::from("white"),
repeat_num: 0,
char: '-',
@@ -120,7 +120,7 @@ pub struct Os {
impl Default for Os {
fn default() -> Self {
- Os {
+ Self {
pre_text_style: String::from("bold.yellow"),
pre_text: String::from("OS: "),
output_style: String::from("white"),
@@ -129,7 +129,7 @@ impl Default for Os {
}
impl Os {
- pub fn get_os(&self) -> String {
+ pub fn get_os() -> String {
let general_readout = GeneralReadout::new();
let os: String;
if cfg!(target_os = "linux") {
@@ -140,9 +140,9 @@ impl Os {
os
}
pub fn get_info(&self) -> String {
- let os = self.get_os();
+ let os = Os::get_os();
let build_version = Config::run_cmd("sw_vers -buildVersion", "Failed to get build version");
- let arch = Config::run_cmd("uname -m", "Failed to get arch");
+ let arch = Config::run_cmd("machine", "Failed to get arch");
let output_style = Style::from_dotted_str(&self.output_style);
format!(
@@ -165,7 +165,7 @@ pub struct Host {
impl Default for Host {
fn default() -> Self {
- Host {
+ Self {
pre_text_style: String::from("bold.yellow"),
pre_text: String::from("Host: "),
output_style: String::from("white"),
@@ -194,7 +194,7 @@ pub struct Kernel {
impl Default for Kernel {
fn default() -> Self {
- Kernel {
+ Self {
pre_text_style: String::from("bold.yellow"),
pre_text: String::from("Kernel: "),
output_style: String::from("white"),
@@ -228,7 +228,7 @@ pub struct Uptime {
impl Default for Uptime {
fn default() -> Self {
- Uptime {
+ Self {
pre_text_style: String::from("bold.yellow"),
pre_text: String::from("Uptime: "),
output_style: String::from("white"),
@@ -270,7 +270,7 @@ pub struct Packages {
impl Default for Packages {
fn default() -> Self {
- Packages {
+ Self {
pre_text_style: String::from("bold.yellow"),
pre_text: String::from("Packages: "),
output_style: String::from("white"),
@@ -304,7 +304,7 @@ pub struct Shell {
impl Default for Shell {
fn default() -> Self {
- Shell {
+ Self {
pre_text_style: String::from("bold.yellow"),
pre_text: String::from("Shell: "),
output_style: String::from("white"),
@@ -347,7 +347,7 @@ pub struct Resolution {
impl Default for Resolution {
fn default() -> Self {
- Resolution {
+ Self {
pre_text_style: String::from("bold.yellow"),
pre_text: String::from("Resolution: "),
output_style: String::from("white"),
@@ -378,7 +378,7 @@ pub struct DesktopEnvironment {
impl Default for DesktopEnvironment {
fn default() -> Self {
- DesktopEnvironment {
+ Self {
pre_text_style: String::from("bold.yellow"),
pre_text: String::from("Desktop Environment: "),
output_style: String::from("white"),
@@ -412,7 +412,7 @@ pub struct WindowManager {
impl Default for WindowManager {
fn default() -> Self {
- WindowManager {
+ Self {
pre_text_style: String::from("bold.yellow"),
pre_text: String::from("Window Manager: "),
output_style: String::from("white"),
@@ -446,7 +446,7 @@ pub struct Terminal {
impl Default for Terminal {
fn default() -> Self {
- Terminal {
+ Self {
pre_text_style: String::from("bold.yellow"),
pre_text: String::from("Terminal: "),
output_style: String::from("white"),
@@ -467,6 +467,37 @@ impl Terminal {
}
}
+#[derive(Deserialize, Debug, PartialEq, Clone)]
+#[serde(deny_unknown_fields, default)]
+pub struct Cpu {
+ pre_text_style: String,
+ pre_text: String,
+ output_style: String,
+}
+
+impl Default for Cpu {
+ fn default() -> Self {
+ Self {
+ pre_text_style: String::from("bold.yellow"),
+ pre_text: String::from("CPU: "),
+ output_style: String::from("white"),
+ }
+ }
+}
+
+impl Cpu {
+ pub fn get_info(&self) -> String {
+ let general_readout = GeneralReadout::new();
+ let cpu = handle_error!(general_readout.cpu_model_name(), "Failed to get CPU name");
+
+ format!(
+ "{}{}",
+ Style::from_dotted_str(&self.pre_text_style).apply_to(&self.pre_text),
+ Style::from_dotted_str(&self.output_style).apply_to(cpu),
+ )
+ }
+}
+
#[derive(Deserialize, Debug, PartialEq, Clone)]
#[serde(deny_unknown_fields, default)]
pub struct Module {
@@ -490,7 +521,7 @@ impl Module {
impl Default for Module {
fn default() -> Self {
- Module {
+ Self {
command: String::from(""),
output_style: String::from("white"),
pre_text: String::from(""),
diff --git a/src/utils.rs b/src/utils.rs
index 233cd68..b759be0 100644
--- a/src/utils.rs
+++ b/src/utils.rs
@@ -5,14 +5,14 @@ macro_rules! handle_error {
v
} else {
let r = $err.unwrap_err().to_string();
- if r != "" {
+ if r == "" {
UserFacingError::new($err_msg)
.help($help_msg)
- .reason(r)
.print_and_exit();
} else {
UserFacingError::new($err_msg)
.help($help_msg)
+ .reason(r)
.print_and_exit();
}
unreachable!()
@@ -23,10 +23,10 @@ macro_rules! handle_error {
v
} else {
let r = $err.unwrap_err().to_string();
- if r != "" {
- UserFacingError::new($err_msg).reason(r).print_and_exit();
- } else {
+ if r == "" {
UserFacingError::new($err_msg).print_and_exit();
+ } else {
+ UserFacingError::new($err_msg).reason(r).print_and_exit();
}
unreachable!()
}