use crate::github::flags::ActionFlag;
use crate::github::types::{CheckState, Role};
pub const ROLE_AUTHOR: char = 'A';
pub const ROLE_REVIEWER: char = 'R';
pub const ROLE_ASSIGNEE: char = '@';
pub const NEEDS_ACTION: char = '\u{25CF}'; pub const NEEDS_ACTION_ASCII: char = '*';
pub const STATUS_REVIEW: char = '\u{2691}'; pub const STATUS_REVIEW_ASCII: char = '!';
pub const STATUS_CONFLICT: char = '\u{21C4}'; pub const STATUS_CONFLICT_ASCII: char = '~';
pub const STATUS_BEHIND: char = '\u{25B2}'; pub const STATUS_BEHIND_ASCII: char = '^';
pub const STATUS_THREADS: char = '\u{25CB}'; pub const STATUS_THREADS_ASCII: char = '?';
pub const STATUS_DRAFT: char = '\u{25C6}'; pub const STATUS_DRAFT_ASCII: char = 'D';
pub const CI_SUCCESS: char = '\u{2714}'; pub const CI_SUCCESS_ASCII: char = '+';
pub const CI_FAILURE: char = '\u{2716}'; pub const CI_FAILURE_ASCII: char = 'x';
pub const CI_PENDING: char = '\u{25CF}'; pub const CI_PENDING_ASCII: char = '.';
pub const CI_NONE: char = '\u{2014}'; pub const CI_NONE_ASCII: char = '-';
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ColorRole {
NeedsAction,
Success,
Warning,
Danger,
Muted,
#[allow(dead_code)]
Accent,
}
pub fn role_glyph(role: Role) -> char {
match role {
Role::Author => ROLE_AUTHOR,
Role::Reviewer => ROLE_REVIEWER,
Role::Assignee => ROLE_ASSIGNEE,
}
}
pub fn flag_glyph(flag: ActionFlag, ascii: bool) -> (char, ColorRole) {
match flag {
ActionFlag::Draft => {
let ch = if ascii { STATUS_DRAFT_ASCII } else { STATUS_DRAFT };
(ch, ColorRole::Muted)
}
ActionFlag::Conflict => {
let ch = if ascii { STATUS_CONFLICT_ASCII } else { STATUS_CONFLICT };
(ch, ColorRole::Danger)
}
ActionFlag::CiFailing => {
let ch = if ascii { CI_FAILURE_ASCII } else { CI_FAILURE };
(ch, ColorRole::Danger)
}
ActionFlag::ChangesRequested | ActionFlag::ReviewRequested => {
let ch = if ascii { STATUS_REVIEW_ASCII } else { STATUS_REVIEW };
(ch, ColorRole::NeedsAction)
}
ActionFlag::UnresolvedThreads => {
let ch = if ascii { STATUS_THREADS_ASCII } else { STATUS_THREADS };
(ch, ColorRole::NeedsAction)
}
ActionFlag::Behind => {
let ch = if ascii { STATUS_BEHIND_ASCII } else { STATUS_BEHIND };
(ch, ColorRole::Warning)
}
ActionFlag::Clean => (' ', ColorRole::Muted),
}
}
pub fn ci_glyph(state: Option<CheckState>, ascii: bool) -> (char, ColorRole) {
match state {
Some(CheckState::Success | CheckState::Expected) => {
let ch = if ascii { CI_SUCCESS_ASCII } else { CI_SUCCESS };
(ch, ColorRole::Success)
}
Some(CheckState::Failure | CheckState::Error) => {
let ch = if ascii { CI_FAILURE_ASCII } else { CI_FAILURE };
(ch, ColorRole::Danger)
}
Some(CheckState::Pending) => {
let ch = if ascii { CI_PENDING_ASCII } else { CI_PENDING };
(ch, ColorRole::Warning)
}
None => {
let ch = if ascii { CI_NONE_ASCII } else { CI_NONE };
(ch, ColorRole::Muted)
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn flag_glyph_complete() {
use ActionFlag::{
Behind, ChangesRequested, CiFailing, Clean, Conflict, Draft, ReviewRequested,
UnresolvedThreads,
};
for flag in [
Draft,
Conflict,
CiFailing,
ChangesRequested,
ReviewRequested,
UnresolvedThreads,
Behind,
Clean,
] {
let (ch, _) = flag_glyph(flag, false);
let _ = ch; }
}
#[test]
fn flag_glyph_ascii_only() {
use ActionFlag::{
Behind, ChangesRequested, CiFailing, Clean, Conflict, Draft, ReviewRequested,
UnresolvedThreads,
};
for flag in [
Draft,
Conflict,
CiFailing,
ChangesRequested,
ReviewRequested,
UnresolvedThreads,
Behind,
Clean,
] {
let (ch, _) = flag_glyph(flag, true);
assert!(ch.is_ascii(), "flag {flag:?} returned non-ASCII char '{ch}' in ASCII mode");
}
}
#[test]
fn ci_glyph_ascii_only() {
for state in [
Some(CheckState::Success),
Some(CheckState::Failure),
Some(CheckState::Error),
Some(CheckState::Pending),
Some(CheckState::Expected),
None,
] {
let (ch, _) = ci_glyph(state, true);
assert!(ch.is_ascii(), "ci_glyph({state:?}, true) returned non-ASCII '{ch}'");
}
}
#[test]
fn color_roles_are_mapped() {
let roles: Vec<ColorRole> = [
ActionFlag::Draft,
ActionFlag::Conflict,
ActionFlag::ChangesRequested,
ActionFlag::Behind,
ActionFlag::Clean,
]
.iter()
.map(|&f| flag_glyph(f, false).1)
.collect();
assert!(roles.contains(&ColorRole::Muted));
assert!(roles.contains(&ColorRole::Danger));
assert!(roles.contains(&ColorRole::NeedsAction));
assert!(roles.contains(&ColorRole::Warning));
}
}