mirror of
https://github.com/MalteT/mensa.git
synced 2024-10-22 21:59:17 +02:00
parent
fcf81a71db
commit
ab9bd9801c
46
src/main.rs
46
src/main.rs
|
@ -63,10 +63,9 @@
|
|||
use chrono::Duration;
|
||||
use directories_next::ProjectDirs;
|
||||
use lazy_static::lazy_static;
|
||||
use serde::Serialize;
|
||||
use structopt::StructOpt;
|
||||
use strum::IntoEnumIterator;
|
||||
use tracing::error;
|
||||
use unicode_width::UnicodeWidthStr;
|
||||
|
||||
/// Colorizes the output.
|
||||
///
|
||||
|
@ -170,7 +169,9 @@ fn real_main() -> Result<()> {
|
|||
let canteens = Canteen::fetch(&state)?;
|
||||
Canteen::print_all(&state, &canteens);
|
||||
}
|
||||
Some(Command::Tags) => print_tags(&state),
|
||||
Some(Command::Tags) => {
|
||||
Tag::print_all(&state)?;
|
||||
}
|
||||
None => {
|
||||
let cmd = MealsCommand::default();
|
||||
let state = State::from(state, &cmd);
|
||||
|
@ -181,38 +182,6 @@ fn real_main() -> Result<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn print_tags<Cmd>(state: &State<Cmd>) {
|
||||
for tag in Tag::iter() {
|
||||
println!();
|
||||
const ID_WIDTH: usize = 4;
|
||||
const TEXT_INDENT: &str = " ";
|
||||
let emoji = if state.args.plain && tag.is_primary() {
|
||||
format!("{:>width$}", "-", width = ID_WIDTH)
|
||||
} else {
|
||||
let emoji = tag.as_id(state);
|
||||
let emoji_len = emoji.width();
|
||||
format!(
|
||||
"{}{}",
|
||||
" ".repeat(ID_WIDTH.saturating_sub(emoji_len)),
|
||||
emoji
|
||||
)
|
||||
};
|
||||
let description_width = get_sane_terminal_dimensions().0;
|
||||
let description = textwrap::fill(
|
||||
tag.describe(),
|
||||
textwrap::Options::new(description_width)
|
||||
.initial_indent(TEXT_INDENT)
|
||||
.subsequent_indent(TEXT_INDENT),
|
||||
);
|
||||
println!(
|
||||
"{} {}\n{}",
|
||||
color!(state: emoji; bright_yellow, bold),
|
||||
color!(state: tag; bold),
|
||||
color!(state: description; bright_black),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn get_sane_terminal_dimensions() -> (usize, usize) {
|
||||
terminal_size::terminal_size()
|
||||
.map(|(w, h)| (w.0 as usize, h.0 as usize))
|
||||
|
@ -221,3 +190,10 @@ fn get_sane_terminal_dimensions() -> (usize, usize) {
|
|||
.log_warn()
|
||||
.unwrap_or((80, 80))
|
||||
}
|
||||
|
||||
fn print_json<T: Serialize>(value: &T) -> Result<()> {
|
||||
let stdout = std::io::stdout();
|
||||
let output = stdout.lock();
|
||||
serde_json::to_writer_pretty(output, value)
|
||||
.map_err(|why| Error::Serializing(why, "writing meals as json"))
|
||||
}
|
||||
|
|
|
@ -10,8 +10,8 @@ use std::collections::HashSet;
|
|||
use crate::{
|
||||
cache::fetch_json,
|
||||
config::{args::MealsCommand, MealsState, PriceTags},
|
||||
error::{pass_info, Error, Result},
|
||||
get_sane_terminal_dimensions,
|
||||
error::{pass_info, Result},
|
||||
get_sane_terminal_dimensions, print_json,
|
||||
tag::Tag,
|
||||
State, ENDPOINT,
|
||||
};
|
||||
|
@ -128,10 +128,7 @@ impl Meal {
|
|||
let favs = state.get_favs_rule();
|
||||
let meals = meals.iter().filter(|meal| filter.is_match(meal));
|
||||
if state.args.json {
|
||||
let stdout = std::io::stdout();
|
||||
let output = stdout.lock();
|
||||
serde_json::to_writer_pretty(output, &meals.collect::<Vec<_>>())
|
||||
.map_err(|why| Error::Serializing(why, "writing meals as json"))
|
||||
print_json(&meals.collect::<Vec<_>>())
|
||||
} else {
|
||||
for meal in meals {
|
||||
let is_fav = favs.is_match(meal);
|
||||
|
|
75
src/tag.rs
75
src/tag.rs
|
@ -1,10 +1,16 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use lazy_static::lazy_static;
|
||||
use num_enum::{IntoPrimitive, TryFromPrimitive};
|
||||
use regex::RegexSet;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use strum::{Display, EnumIter};
|
||||
use strum::{Display, EnumIter, IntoEnumIterator};
|
||||
use unicode_width::UnicodeWidthStr;
|
||||
|
||||
use crate::config::State;
|
||||
use crate::{config::State, error::Result, get_sane_terminal_dimensions, print_json};
|
||||
|
||||
const ID_WIDTH: usize = 4;
|
||||
const TEXT_INDENT: &str = " ";
|
||||
|
||||
lazy_static! {
|
||||
/// These must have the same order as the variants in the [`Tag`] enum.
|
||||
|
@ -170,4 +176,69 @@ impl Tag {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Print this tag.
|
||||
///
|
||||
/// Does **not** respect `--json`, use [`Self::print_all`].
|
||||
pub fn print<Cmd>(&self, state: &State<Cmd>) {
|
||||
let emoji = if state.args.plain && self.is_primary() {
|
||||
format!("{:>width$}", "-", width = ID_WIDTH)
|
||||
} else {
|
||||
let emoji = self.as_id(state);
|
||||
let emoji_len = emoji.width();
|
||||
format!(
|
||||
"{}{}",
|
||||
" ".repeat(ID_WIDTH.saturating_sub(emoji_len)),
|
||||
emoji
|
||||
)
|
||||
};
|
||||
let description_width = get_sane_terminal_dimensions().0;
|
||||
let description = textwrap::fill(
|
||||
self.describe(),
|
||||
textwrap::Options::new(description_width)
|
||||
.initial_indent(TEXT_INDENT)
|
||||
.subsequent_indent(TEXT_INDENT),
|
||||
);
|
||||
println!(
|
||||
"{} {}\n{}",
|
||||
color!(state: emoji; bright_yellow, bold),
|
||||
color!(state: self; bold),
|
||||
color!(state: description; bright_black),
|
||||
);
|
||||
}
|
||||
|
||||
/// Print all tags.
|
||||
pub fn print_all<Cmd>(state: &State<Cmd>) -> Result<()> {
|
||||
if state.args.json {
|
||||
Self::print_all_json(state)
|
||||
} else {
|
||||
for tag in Tag::iter() {
|
||||
println!();
|
||||
tag.print(state);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Print all tags as json.
|
||||
///
|
||||
/// This will result in a list of objects containing the following keys:
|
||||
/// - id: An identifier, like 'Vegan' or '22'
|
||||
/// - name: The name of the tag.
|
||||
/// - desc: A simple description.
|
||||
///
|
||||
fn print_all_json<Cmd>(state: &State<Cmd>) -> Result<()> {
|
||||
let tags: Vec<HashMap<&str, String>> = Tag::iter()
|
||||
.map(|tag| {
|
||||
vec![
|
||||
("id", tag.as_id(state)),
|
||||
("name", tag.to_string()),
|
||||
("desc", tag.describe().to_owned()),
|
||||
]
|
||||
.into_iter()
|
||||
.collect()
|
||||
})
|
||||
.collect();
|
||||
print_json(&tags)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue