Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ toml = "0.5.8"
yaml-rust = "0.4"
serde = "1.0.118"
serde_json = "1.0.61"
serde_yaml = "0.8"

chrono = "0.4"
chrono-humanize = "0.1.1"
Expand Down
8 changes: 1 addition & 7 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,11 @@ fn run() -> Result<()> {
if !repo::is_valid(&config.repo_path)? {
return Err("please run onefetch inside of a non-bare git repository".into());
}
let print_in_json_format = config.print_in_json_format;

let info = info::Info::new(config)?;

let mut printer = Printer::new(io::BufWriter::new(io::stdout()), info);

if print_in_json_format {
printer.print_json()?
} else {
printer.print()?
}
printer.print()?;

Ok(())
}
Expand Down
29 changes: 22 additions & 7 deletions src/onefetch/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use {
image_backends,
info_field::{InfoField, InfoFieldOff},
language::Language,
printer::SerializationFormat,
},
clap::{crate_description, crate_name, crate_version, App, AppSettings, Arg},
image::DynamicImage,
Expand All @@ -31,10 +32,11 @@ pub struct Cli {
pub excluded: Vec<String>,
pub print_languages: bool,
pub print_package_managers: bool,
pub print_in_json_format: bool,
pub output: Option<SerializationFormat>,
pub true_color: bool,
pub art_off: bool,
pub text_colors: Vec<String>,
pub iso_time: bool,
}

impl Cli {
Expand All @@ -60,10 +62,20 @@ impl Cli {
.help("Run as if onefetch was started in <input> instead of the current working directory.",
))
.arg(
Arg::with_name("json")
.short("j")
.long("json")
.help("Outputs Onefetch in JSON format.")
Arg::with_name("output")
.short("o")
.long("output")
.help("Outputs Onefetch in a specific format (json, yaml).")
.takes_value(true)
.possible_values(&SerializationFormat::iter()
.map(|format| format.into())
.collect::<Vec<&str>>())
)
.arg(
Arg::with_name("isotime")
.short("z")
.long("isotime")
.help("Outputs Onefetch with ISO 8601 formated timestamps")
)
.arg(
Arg::with_name("languages")
Expand Down Expand Up @@ -243,7 +255,9 @@ impl Cli {
let no_color_palette = matches.is_present("no-color-palette");
let print_languages = matches.is_present("languages");
let print_package_managers = matches.is_present("package-managers");
let print_in_json_format = matches.is_present("json");
let iso_time = matches.is_present("isotime");

let output = matches.value_of("output").map(SerializationFormat::from_str).transpose().unwrap();

let fields_to_hide: Vec<String> = if let Some(values) = matches.values_of("disable-fields")
{
Expand Down Expand Up @@ -339,10 +353,11 @@ impl Cli {
excluded,
print_languages,
print_package_managers,
print_in_json_format,
output,
true_color,
text_colors,
art_off,
iso_time,
})
}
}
4 changes: 2 additions & 2 deletions src/onefetch/info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,10 +219,10 @@ impl Info {
let git_username = internal_repo.get_git_username()?;
let number_of_tags = internal_repo.get_number_of_tags()?;
let number_of_branches = internal_repo.get_number_of_branches()?;
let creation_date = internal_repo.get_creation_date()?;
let creation_date = internal_repo.get_creation_date(config.iso_time)?;
let number_of_commits = internal_repo.get_number_of_commits();
let authors = internal_repo.get_authors(config.number_of_authors);
let last_change = internal_repo.get_date_of_last_commit();
let last_change = internal_repo.get_date_of_last_commit(config.iso_time);
let (repo_size, file_count) = internal_repo.get_repo_size();
let workdir = internal_repo.get_work_dir()?;
let license = Detector::new()?.get_license(&workdir)?;
Expand Down
121 changes: 69 additions & 52 deletions src/onefetch/printer.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
use crate::onefetch::{ascii_art::AsciiArt, error::*, info::Info};
use colored::Color;
use std::io::Write;
use strum::{EnumIter, EnumString, IntoStaticStr};

const CENTER_PAD_LENGTH: usize = 3;

#[derive(EnumString, EnumIter, IntoStaticStr)]
#[strum(serialize_all = "lowercase")]
pub enum SerializationFormat {
Json,
Yaml,
}

pub struct Printer<W> {
writer: W,
info: Info,
Expand All @@ -15,64 +23,73 @@ impl<W: Write> Printer<W> {
}

pub fn print(&mut self) -> Result<()> {
let center_pad = " ".repeat(CENTER_PAD_LENGTH);
let info_str = format!("{}", &self.info);
let mut info_lines = info_str.lines();
let colors: Vec<Color> = Vec::new();
let mut buf = String::new();
match &self.info.config.output {
Some(format) => match format {
SerializationFormat::Json => {
write!(self.writer, "{}", serde_json::to_string_pretty(&self.info).unwrap())?
}
SerializationFormat::Yaml => {
write!(self.writer, "{}", serde_yaml::to_string(&self.info).unwrap())?
}
},
None => {
let center_pad = " ".repeat(CENTER_PAD_LENGTH);
let info_str = format!("{}", &self.info);
let mut info_lines = info_str.lines();
let colors: Vec<Color> = Vec::new();
let mut buf = String::new();

if self.info.config.art_off {
buf.push_str(&info_str);
} else if let Some(custom_image) = &self.info.config.image {
buf.push_str(
&self
.info
.config
.image_backend
.as_ref()
.unwrap()
.add_image(
info_lines.map(|s| format!("{}{}", center_pad, s)).collect(),
custom_image,
self.info.config.image_color_resolution,
)
.chain_err(|| "Error while drawing image")?,
);
} else {
let mut logo_lines = if let Some(custom_ascii) = &self.info.config.ascii_input {
AsciiArt::new(custom_ascii, &colors, !self.info.config.no_bold)
} else {
AsciiArt::new(self.get_ascii(), &self.info.ascii_colors, !self.info.config.no_bold)
};
if self.info.config.art_off {
buf.push_str(&info_str);
} else if let Some(custom_image) = &self.info.config.image {
buf.push_str(
&self
.info
.config
.image_backend
.as_ref()
.unwrap()
.add_image(
info_lines.map(|s| format!("{}{}", center_pad, s)).collect(),
custom_image,
self.info.config.image_color_resolution,
)
.chain_err(|| "Error while drawing image")?,
);
} else {
let mut logo_lines = if let Some(custom_ascii) = &self.info.config.ascii_input {
AsciiArt::new(custom_ascii, &colors, !self.info.config.no_bold)
} else {
AsciiArt::new(
self.get_ascii(),
&self.info.ascii_colors,
!self.info.config.no_bold,
)
};

loop {
match (logo_lines.next(), info_lines.next()) {
(Some(logo_line), Some(info_line)) => {
buf.push_str(&format!("{}{}{:^}\n", logo_line, center_pad, info_line))
}
(Some(logo_line), None) => buf.push_str(&format!("{}\n", logo_line)),
(None, Some(info_line)) => buf.push_str(&format!(
"{:<width$}{}{:^}\n",
"",
center_pad,
info_line,
width = logo_lines.width()
)),
(None, None) => {
buf.push('\n');
break;
loop {
match (logo_lines.next(), info_lines.next()) {
(Some(logo_line), Some(info_line)) => buf
.push_str(&format!("{}{}{:^}\n", logo_line, center_pad, info_line)),
(Some(logo_line), None) => buf.push_str(&format!("{}\n", logo_line)),
(None, Some(info_line)) => buf.push_str(&format!(
"{:<width$}{}{:^}\n",
"",
center_pad,
info_line,
width = logo_lines.width()
)),
(None, None) => {
buf.push('\n');
break;
}
}
}
}

write!(self.writer, "{}", buf)?;
}
}

write!(self.writer, "{}", buf)?;

Ok(())
}

pub fn print_json(&mut self) -> Result<()> {
write!(self.writer, "{}", serde_json::to_string_pretty(&self.info).unwrap())?;
Ok(())
}

Expand Down
8 changes: 4 additions & 4 deletions src/onefetch/repo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,12 @@ impl<'a> Repo<'a> {
Ok(logs)
}

pub fn get_creation_date(&self) -> Result<String> {
pub fn get_creation_date(&self, iso_time: bool) -> Result<String> {
let first_commit = self.logs.last();
let output = match first_commit {
Some(commit) => {
let time = commit.time();
utils::git_time_to_human_time(&time)
utils::git_time_to_formatted_time(&time, iso_time)
}
None => "".into(),
};
Expand Down Expand Up @@ -84,11 +84,11 @@ impl<'a> Repo<'a> {
authors
}

pub fn get_date_of_last_commit(&self) -> String {
pub fn get_date_of_last_commit(&self, iso_time: bool) -> String {
let last_commit = self.logs.first();

match last_commit {
Some(commit) => utils::git_time_to_human_time(&commit.time()),
Some(commit) => utils::git_time_to_formatted_time(&commit.time(), iso_time),
None => "".into(),
}
}
Expand Down
10 changes: 7 additions & 3 deletions src/onefetch/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,18 @@ pub fn bytes_to_human_readable(bytes: u128) -> String {
byte.get_appropriate_unit(true).to_string()
}

pub fn git_time_to_human_time(time: &Time) -> String {
pub fn git_time_to_formatted_time(time: &Time, iso_time: bool) -> String {
let (offset, _) = match time.offset_minutes() {
n if n < 0 => (-n, '-'),
n => (n, '+'),
};

let offset = FixedOffset::west(offset);
let dt_with_tz = offset.timestamp(time.seconds(), 0);
let ht = HumanTime::from(dt_with_tz);
ht.to_text_en(Accuracy::Rough, Tense::Past)
if iso_time {
dt_with_tz.with_timezone(&chrono::Utc).to_rfc3339_opts(chrono::SecondsFormat::Secs, true)
} else {
let ht = HumanTime::from(dt_with_tz);
ht.to_text_en(Accuracy::Rough, Tense::Past)
}
}