Compare commits
12 commits
d18db743ee
...
f769a65a6d
Author | SHA1 | Date | |
---|---|---|---|
f769a65a6d | |||
b303f3197a | |||
d6370da9e2 | |||
b238dbeecb | |||
b318c96734 | |||
b0678542ef | |||
2802f6dd42 | |||
bd00a2813f | |||
f7afc30f2e | |||
07ee54024d | |||
1332a306bc | |||
f8e02e06fb |
10 changed files with 530 additions and 104 deletions
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "pride"
|
||||
version = "0.1.5"
|
||||
version = "0.2.1"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
|
10
README.md
10
README.md
|
@ -3,14 +3,12 @@
|
|||
|
||||
A Rust utility to display pride flags in the terminal.
|
||||
|
||||
**This project is under heavy construction! It is subject to major structural and
|
||||
architectural changes. There are no issues with functionality, but I will continue
|
||||
to make major changes and refactors until the main roadmap is complete.**
|
||||
A list of currently implemented flags is available on the [project wiki](https://git.vwolfe.io/valerie/pride/wiki/Flags).
|
||||
|
||||
Currently supports a variety of stripe flags.
|
||||
## Dependencies
|
||||
|
||||
Under Construction features:
|
||||
- ["Complex" Flags](https://git.vwolfe.io/valerie/pride/src/branch/complex)
|
||||
Some Complex renderers utilize [Powerline's](https://github.com/ryanoasis/powerline-extra-symbols)
|
||||
slant symbols, and therefore require use of a Powerline font, such as [Fira Code](https://github.com/tonsky/FiraCode).
|
||||
|
||||
## Libraries
|
||||
|
||||
|
|
12
src/color.rs
12
src/color.rs
|
@ -1,5 +1,5 @@
|
|||
|
||||
use termion::color::{ Fg, Rgb, Reset };
|
||||
use termion::color::{ Bg, Fg, Rgb, Reset };
|
||||
|
||||
pub type Color = Fg<Rgb>;
|
||||
pub type Colors = Vec<Fg<Rgb>>;
|
||||
|
@ -8,8 +8,9 @@ pub static BLACK: Color = Fg(Rgb(0x00, 0x00, 0x00));
|
|||
pub static WHITE: Color = Fg(Rgb(0xFF, 0xFF, 0xFF));
|
||||
|
||||
pub static RESET: Fg<Reset> = Fg(Reset);
|
||||
pub static RESET_BG: Bg<Reset> = Bg(Reset);
|
||||
|
||||
/// converts a hex integer to Fg(Rgb)
|
||||
/// produces a termion foreground color from the provided integer
|
||||
pub fn rgb(hex: u32) -> Color {
|
||||
// colors should be 0xrrggbb = 0x__rrggbb; drop the most significant byte
|
||||
let [_, r, g, b] = hex.to_be_bytes();
|
||||
|
@ -17,3 +18,10 @@ pub fn rgb(hex: u32) -> Color {
|
|||
Fg(Rgb(r, g, b))
|
||||
}
|
||||
|
||||
/// produces a termion background color from the provided integer
|
||||
pub fn bg(hex: u32) -> Bg<Rgb> {
|
||||
let [_, r, g, b] = hex.to_be_bytes();
|
||||
|
||||
Bg(Rgb(r, g, b))
|
||||
}
|
||||
|
||||
|
|
292
src/complex.rs
Normal file
292
src/complex.rs
Normal file
|
@ -0,0 +1,292 @@
|
|||
//! flags that require more complex rendering than just scaling colored stripes
|
||||
|
||||
use termion::{
|
||||
terminal_size,
|
||||
|
||||
color::{ Bg, Rgb }
|
||||
};
|
||||
|
||||
use crate::{
|
||||
color::*,
|
||||
draw,
|
||||
flag::{ self, Flag },
|
||||
util::{ ansi_len, ansi_substr }
|
||||
};
|
||||
|
||||
/// vertically stacking eighths
|
||||
pub static V_EIGHTH: [char; 7] = ['▁', '▂', '▃', '▄', '▅', '▆', '▇'];
|
||||
/// horizontally stacking eighths
|
||||
pub static H_EIGHTH: [char; 7] = ['▏', '▎', '▍', '▌', '▋', '▊', '▉'];
|
||||
|
||||
/// shading by intensity
|
||||
pub static SHADING: [char; 3] = ['░', '▒', '▓'];
|
||||
|
||||
/// 2/1 slope triangle cut in
|
||||
pub static TRIANGLE_21: [char; 3] = ['', '🭬', ''];
|
||||
|
||||
/// 2/3 slope slant
|
||||
pub static SLANT_23: [char; 2] = ['🭒', '🭏'];
|
||||
|
||||
pub fn progress(small: bool) -> Flag {
|
||||
let red = bg(0xE50000);
|
||||
let orange = bg(0xFF8D00);
|
||||
let yellow = bg(0xFFEE00);
|
||||
let green = bg(0x028121);
|
||||
let blue = bg(0x004CFF);
|
||||
let purple = bg(0x770088);
|
||||
|
||||
// we need these colors in both fg & bg; just hold the integers for now
|
||||
let black: u32 = 0;
|
||||
let brown: u32 = 0x784F17;
|
||||
let ltblue: u32 = 0xEAACB8;
|
||||
let pink: u32 = 0x7ACBF5;
|
||||
let white: u32 = 0xFFFFFF;
|
||||
|
||||
let (width, height) = if small { (18, 6) } else { terminal_size().unwrap() };
|
||||
|
||||
// create color slices and line buffer
|
||||
let stripes = [red, orange, yellow, green, blue, purple];
|
||||
let chevrons = [white, ltblue, pink, brown, black];
|
||||
let mut lines: Vec<String> = Vec::new();
|
||||
|
||||
// set up stripe index
|
||||
let mut index = 0;
|
||||
|
||||
/* ok, coming up with procedure:
|
||||
* - can't rely on bg_stripes; line count, threshold, etc., will need to happen here
|
||||
* - line count will always be the largest multiple of 6 smaller than height; c = h - (h % 6)
|
||||
* - chevrons may have larger widths: TODO calc
|
||||
* - depth will be funky; line depth will need to use "full" depth; (Df - Dl) / Wc = Ic (TODO verify?)
|
||||
* - switch stripe index on *absolute* line number rather than n
|
||||
* - chevron building will be BLOCK.repeat(width) + TRIANGLE_21[0] (fg Ic, bg Ic + 1)
|
||||
* - chevrons[len - 1] will need unique handling to draw stripes
|
||||
*/
|
||||
|
||||
// set up constraints
|
||||
let linecount = height - (height % 6); // largest multiple of 6 smaller than height
|
||||
let full_depth = width / 3;
|
||||
let chevron_width = (full_depth / 6) - 1;
|
||||
let direction_thresh = linecount / 2;
|
||||
let corner = linecount % 2 == 1;
|
||||
|
||||
let thresh = linecount / 6; // stripe threshold; no bg_stripes call!
|
||||
let mut line_no = 0; // absolute line number; n is relative
|
||||
|
||||
// chevron helper
|
||||
let build_chevron = | separator: char | -> String {
|
||||
let mut output = format!(
|
||||
"{fg}{bg}{stripe}{separator}",
|
||||
fg = rgb(chevrons[0]),
|
||||
bg = bg(chevrons[1]),
|
||||
stripe = draw::BLOCK.repeat( usize::max(chevron_width as usize * 2, 1) )
|
||||
);
|
||||
let stripe = draw::BLOCK.repeat(chevron_width as usize);
|
||||
for i in 1..4 {
|
||||
output += &format!(
|
||||
"{fg}{bg}{stripe}{separator}",
|
||||
fg = rgb(chevrons[i]),
|
||||
bg = bg(chevrons[i + 1])
|
||||
);
|
||||
}
|
||||
output += &format!(
|
||||
"{fg}{stripe}",
|
||||
fg = rgb(chevrons[4])
|
||||
);
|
||||
|
||||
output
|
||||
};
|
||||
|
||||
// piecewise functions: ascent -> peak -> descent
|
||||
let mut base = build_chevron(TRIANGLE_21[0]);
|
||||
let base_length = base.len();
|
||||
let display_length = ansi_len(&base) + 1; // chevron width will always stay the same; add 1 for the last separator
|
||||
for n in 0..direction_thresh {
|
||||
// advance stripe color at stripe threshold by line number
|
||||
if line_no != 0 && line_no % thresh == 0 { index += 1; }
|
||||
|
||||
// grab our substring constraints
|
||||
let start = (direction_thresh - n) as usize - 1;
|
||||
let diff = display_length - start;
|
||||
|
||||
// take substring of chevron line...
|
||||
let mut line = ansi_substr(&base, start as usize, base_length);
|
||||
// ... and add the colored stripe
|
||||
line += &format!(
|
||||
"{stripe}{separator}{line}",
|
||||
stripe = stripes[index],
|
||||
separator = TRIANGLE_21[0],
|
||||
line = " ".repeat(width as usize - diff)
|
||||
);
|
||||
|
||||
lines.push(line);
|
||||
line_no += 1;
|
||||
}
|
||||
if corner {
|
||||
if line_no % thresh == 0 { index += 1; }
|
||||
|
||||
let base = build_chevron(TRIANGLE_21[1]);
|
||||
let mut line = ansi_substr(&base, 0, base_length);
|
||||
line += &format!(
|
||||
"{stripe}{separator}{line}",
|
||||
stripe = stripes[index],
|
||||
separator = TRIANGLE_21[1],
|
||||
line = " ".repeat(width as usize - display_length)
|
||||
);
|
||||
|
||||
lines.push(line);
|
||||
line_no += 1;
|
||||
}
|
||||
base = build_chevron(TRIANGLE_21[2]);
|
||||
for n in 0..direction_thresh {
|
||||
if line_no % thresh == 0 { index += 1; }
|
||||
if index > 5 { break; }
|
||||
|
||||
let start = n as usize;
|
||||
let diff = display_length - start;
|
||||
|
||||
let mut line = ansi_substr(&base, start, base_length);
|
||||
line += &format!(
|
||||
"{stripe}{separator}{line}",
|
||||
stripe = stripes[index],
|
||||
separator = TRIANGLE_21[2],
|
||||
line = " ".repeat(width as usize - diff)
|
||||
);
|
||||
|
||||
lines.push(line);
|
||||
line_no += 1;
|
||||
}
|
||||
|
||||
Flag::Lines(lines)
|
||||
}
|
||||
|
||||
// everything below this point is in alphabetical order
|
||||
|
||||
pub fn aroace(small: bool) -> Flag {
|
||||
// pull colors from aro & ace stripe flags
|
||||
let Flag::Stripes(aro) = flag::aromantic() else { panic!() };
|
||||
let Flag::Stripes(ace) = flag::asexual() else { panic!() };
|
||||
|
||||
let (width, height) = if small { (60, 20) } else { terminal_size().unwrap() };
|
||||
|
||||
let mut lines: Vec<String> = Vec::new();
|
||||
|
||||
// set up constraints
|
||||
let linecount = height - (height % 20);
|
||||
let aro_thresh = linecount / 5; // threshold for aromantic colors
|
||||
let ace_thresh = linecount / 4; // threshold for asexual colors
|
||||
let stripe = draw::BLOCK.repeat((width / 2) as usize);
|
||||
|
||||
let mut aro_index = 0;
|
||||
let mut ace_index = 0;
|
||||
for n in 0..linecount {
|
||||
// switch colors on thresholds
|
||||
if n != 0 {
|
||||
if n % aro_thresh == 0 { aro_index += 1; }
|
||||
if n % ace_thresh == 0 { ace_index += 1; }
|
||||
}
|
||||
let line = format!("{}{stripe}{}{stripe}", aro[aro_index], ace[ace_index]);
|
||||
lines.push(line);
|
||||
}
|
||||
|
||||
Flag::Lines(lines)
|
||||
}
|
||||
|
||||
fn demi_orientation_render(middle: Bg<Rgb>, bottom: Bg<Rgb>, width: u16, height: u16) -> Vec<String> {
|
||||
let white = bg(0xFFFFFF);
|
||||
|
||||
let stripes = vec![white, white, middle, bottom, bottom];
|
||||
|
||||
// initial stripe output buffer
|
||||
let mut lines: Vec<String> = draw::bg_stripes(stripes, width, height);
|
||||
|
||||
// assemble triangle cut-in
|
||||
let linecount = lines.len();
|
||||
let depth = linecount / 2;
|
||||
let corner = linecount % 2 == 1;
|
||||
// piecewise functions: ascending -> peak -> descending
|
||||
for n in 0..depth {
|
||||
let line = lines[n].clone();
|
||||
|
||||
let replacement = format!("{BLACK}{}{}", draw::BLOCK.repeat(n), TRIANGLE_21[0]);
|
||||
lines[n] = line.replacen(&" ".repeat(n + 1), &replacement, 1);
|
||||
}
|
||||
if corner {
|
||||
let line = lines[depth].clone();
|
||||
|
||||
let replacement = format!("{BLACK}{}{}", draw::BLOCK.repeat(depth), TRIANGLE_21[1]);
|
||||
lines[depth] = line.replacen(&" ".repeat(depth + 1), &replacement, 1);
|
||||
}
|
||||
let start = depth + (linecount % 2);
|
||||
for n in 0..depth {
|
||||
let line = lines[start + n].clone();
|
||||
|
||||
let size = depth - n - 1;
|
||||
let replacement = format!("{BLACK}{}{}", draw::BLOCK.repeat(size), TRIANGLE_21[2]);
|
||||
lines[start + n] = line.replacen(&" ".repeat(size + 1), &replacement, 1);
|
||||
}
|
||||
|
||||
lines
|
||||
}
|
||||
|
||||
pub fn demiromantic(small: bool) -> Flag {
|
||||
let green = bg(0x3DA542);
|
||||
let gray = bg(0xD2D2D2);
|
||||
|
||||
let (width, height) = if small { (15, 5) } else { terminal_size().unwrap() };
|
||||
let lines = demi_orientation_render(green, gray, width, height);
|
||||
|
||||
Flag::Lines(lines)
|
||||
}
|
||||
|
||||
pub fn demisexual(small: bool) -> Flag {
|
||||
let purple = bg(0x832FA8);
|
||||
let grey = bg(0x7B868C);
|
||||
|
||||
let (width, height) = if small { (15, 5) } else { terminal_size().unwrap() };
|
||||
let lines = demi_orientation_render(purple, grey, width, height);
|
||||
|
||||
Flag::Lines(lines)
|
||||
}
|
||||
|
||||
pub fn disability() {
|
||||
let gray = bg(0x575757);
|
||||
|
||||
let green: u32 = 0x3AAD7D;
|
||||
let blue: u32 = 0x79BFE0;
|
||||
let white: u32 = 0xE8E8E8;
|
||||
let yellow: u32 = 0xEDDB76;
|
||||
let red: u32 = 0xCD7281;
|
||||
|
||||
let stripes = [red, yellow, white, blue, green];
|
||||
|
||||
// 2/3 slant stripes with gray background
|
||||
|
||||
}
|
||||
|
||||
pub fn intersex() -> Flag {
|
||||
let yellow = bg(0xFFDA00);
|
||||
let purple = rgb(0x7A00AC);
|
||||
|
||||
let block = " ";
|
||||
let stripe = block.repeat(9);
|
||||
let part = block.repeat(4);
|
||||
|
||||
let lines = vec![
|
||||
format!("{yellow}{stripe}"),
|
||||
format!("{part}{purple}O{part}"),
|
||||
format!("{stripe}")
|
||||
];
|
||||
|
||||
Flag::Lines(lines)
|
||||
}
|
||||
|
||||
pub fn polyamorous() {
|
||||
let blue = rgb(0x019FE3);
|
||||
let magenta = rgb(0xE50051);
|
||||
let purple = rgb(0x340C46);
|
||||
let yellow = rgb(0x00FCBF);
|
||||
|
||||
// blue / magenta / purple vert
|
||||
// WHITE isosceles cutin with yellow heart pointed right
|
||||
}
|
||||
|
126
src/draw.rs
126
src/draw.rs
|
@ -4,76 +4,110 @@ use termion::{
|
|||
terminal_size,
|
||||
|
||||
clear,
|
||||
color::{ Bg, Fg, Rgb },
|
||||
cursor,
|
||||
input::TermRead,
|
||||
raw::IntoRawMode
|
||||
};
|
||||
|
||||
use crate::color::{ RESET, Colors };
|
||||
use crate::flag::BLOCK;
|
||||
use crate::{
|
||||
color::{ RESET, RESET_BG },
|
||||
flag::Flag
|
||||
};
|
||||
|
||||
/// draw a fullscreen stripe flag and hold for keypress
|
||||
pub fn full(colors: Colors) {
|
||||
// prepare stdin and stdout
|
||||
pub static BLOCK: &str = "█";
|
||||
pub static UHALF: &str = "▀";
|
||||
|
||||
pub fn draw_lines(lines: Vec<String>, hold: bool) {
|
||||
let mut stdout = io::stdout().into_raw_mode().unwrap();
|
||||
let stdin = io::stdin();
|
||||
|
||||
// get constraints
|
||||
let count = colors.len();
|
||||
let (width, height) = terminal_size().unwrap();
|
||||
let thresh = height as usize / count;
|
||||
let count = lines.len() as u16;
|
||||
for _ in 0..count { write!(stdout, "\n").ok(); }
|
||||
write!(stdout, "{}", cursor::Up(count)).ok();
|
||||
|
||||
// clear the terminal
|
||||
write!(stdout, "{}{}", cursor::Hide, clear::All).ok();
|
||||
if hold { write!(stdout, "{}{}", cursor::Hide, clear::All).ok(); }
|
||||
|
||||
let down = cursor::Down(1);
|
||||
for line in lines {
|
||||
let left = cursor::Left(line.len() as u16);
|
||||
write!(stdout, "{line}{left}{down}").ok();
|
||||
}
|
||||
|
||||
write!(stdout, "{RESET}{RESET_BG}").ok();
|
||||
stdout.flush().ok();
|
||||
if hold {
|
||||
let stdin = io::stdin();
|
||||
for _ in stdin.keys() { break; }
|
||||
write!(stdout, "{}", clear::All).ok();
|
||||
}
|
||||
write!(stdout, "{}", cursor::Show).ok();
|
||||
stdout.flush().ok();
|
||||
}
|
||||
|
||||
// build terminal width stripe string
|
||||
let stripe = BLOCK.repeat(width as usize);
|
||||
pub fn fg_stripes(colors: Vec<Fg<Rgb>>, width: u16, height: u16) -> Vec<String> {
|
||||
let width = width as usize;
|
||||
let height = height as usize;
|
||||
let count = colors.len();
|
||||
|
||||
let thresh = height / count;
|
||||
|
||||
let stripe = BLOCK.repeat(width);
|
||||
let mut output = Vec::new();
|
||||
|
||||
// create our color index
|
||||
let mut index = 0;
|
||||
// for every terminal row...
|
||||
for n in 0..(height as usize) {
|
||||
// ... increment our index at color change threshold
|
||||
for n in 0..height {
|
||||
if n != 0 && n % thresh == 0 {
|
||||
index += 1;
|
||||
// and break if out of bounds
|
||||
if index >= count { break; }
|
||||
}
|
||||
// ... draw the stripe with color at index
|
||||
write!(
|
||||
stdout,
|
||||
"{color}{stripe}{RESET}",
|
||||
color = colors[index]
|
||||
).ok();
|
||||
}
|
||||
// flush stdout
|
||||
stdout.flush().ok();
|
||||
|
||||
// wait for keypress
|
||||
for _ in stdin.keys() { break; }
|
||||
write!(stdout, "{}{}", cursor::Show, clear::All).ok();
|
||||
stdout.flush().ok();
|
||||
let color = colors[index];
|
||||
output.push(format!("{color}{stripe}"));
|
||||
}
|
||||
|
||||
/// draws a small stripe flag
|
||||
pub fn small(colors: Colors) {
|
||||
// prepare stdout
|
||||
let mut stdout = io::stdout();
|
||||
|
||||
// get constraints
|
||||
output
|
||||
}
|
||||
pub fn bg_stripes(colors: Vec<Bg<Rgb>>, width: u16, height: u16) -> Vec<String> {
|
||||
let width = width as usize;
|
||||
let height = height as usize;
|
||||
let count = colors.len();
|
||||
let width = count * 3;
|
||||
|
||||
// build small stripe string
|
||||
let stripe = BLOCK.repeat(width);
|
||||
let thresh = height / count;
|
||||
|
||||
// print a stripe for all colors
|
||||
for color in colors {
|
||||
println!("{color}{stripe}");
|
||||
let stripe = " ".repeat(width);
|
||||
let mut output = Vec::new();
|
||||
|
||||
let mut index = 0;
|
||||
for n in 0..height {
|
||||
if n != 0 && n % thresh == 0 {
|
||||
index += 1;
|
||||
if index >= count { break; }
|
||||
}
|
||||
let color = colors[index];
|
||||
output.push(format!("{color}{stripe}"));
|
||||
}
|
||||
|
||||
output
|
||||
}
|
||||
|
||||
impl Flag {
|
||||
pub fn draw(self, hold: bool) {
|
||||
let lines = match self {
|
||||
Flag::Stripes(colors)
|
||||
=> {
|
||||
let (width, height);
|
||||
if hold { (width, height) = terminal_size().unwrap(); }
|
||||
else {
|
||||
height = colors.len() as u16;
|
||||
width = height * 3;
|
||||
}
|
||||
fg_stripes(colors, width, height)
|
||||
},
|
||||
Flag::Lines(lines)
|
||||
=> lines
|
||||
};
|
||||
draw_lines(lines, hold);
|
||||
}
|
||||
// reset our foreground color to play nice and flush stdout
|
||||
print!("{RESET}");
|
||||
stdout.flush().ok();
|
||||
}
|
||||
|
||||
|
|
70
src/flag.rs
70
src/flag.rs
|
@ -3,9 +3,13 @@
|
|||
|
||||
use crate::color::*;
|
||||
|
||||
pub static BLOCK: &str = "█";
|
||||
pub enum Flag {
|
||||
Stripes(Colors),
|
||||
Lines(Vec<String>)
|
||||
}
|
||||
|
||||
pub fn pride() -> Colors {
|
||||
|
||||
pub fn pride() -> Flag {
|
||||
let red = rgb(0xE50000);
|
||||
let orange = rgb(0xFF8D00);
|
||||
let yellow = rgb(0xFFEE00);
|
||||
|
@ -13,58 +17,58 @@ pub fn pride() -> Colors {
|
|||
let blue = rgb(0x004CFF);
|
||||
let purple = rgb(0x770088);
|
||||
|
||||
vec![red, orange, yellow, green, blue, purple]
|
||||
Flag::Stripes(vec![red, orange, yellow, green, blue, purple])
|
||||
}
|
||||
|
||||
pub fn transgender() -> Colors {
|
||||
pub fn transgender() -> Flag {
|
||||
let pink = rgb(0x7ACBF5);
|
||||
let blue = rgb(0xEAACB8);
|
||||
|
||||
vec![pink, blue, WHITE, blue, pink]
|
||||
Flag::Stripes(vec![pink, blue, WHITE, blue, pink])
|
||||
}
|
||||
|
||||
// everything below here is alphabetical
|
||||
|
||||
pub fn agender() -> Colors {
|
||||
pub fn agender() -> Flag {
|
||||
let gray = rgb(0xB9B9B9);
|
||||
let green = rgb(0xB8F483);
|
||||
|
||||
vec![BLACK, gray, WHITE, green, WHITE, gray, BLACK]
|
||||
Flag::Stripes(vec![BLACK, gray, WHITE, green, WHITE, gray, BLACK])
|
||||
}
|
||||
|
||||
pub fn aromantic() -> Colors {
|
||||
pub fn aromantic() -> Flag {
|
||||
let green = rgb(0x3BA740);
|
||||
let lime = rgb(0xA8D47A);
|
||||
let grey = rgb(0xABABAB);
|
||||
|
||||
vec![green, lime, WHITE, grey, BLACK]
|
||||
Flag::Stripes(vec![green, lime, WHITE, grey, BLACK])
|
||||
}
|
||||
|
||||
pub fn asexual() -> Colors {
|
||||
pub fn asexual() -> Flag {
|
||||
let grey = rgb(0xA4A4A4);
|
||||
let purple = rgb(0x810081);
|
||||
|
||||
vec![BLACK, grey, WHITE, purple]
|
||||
Flag::Stripes(vec![BLACK, grey, WHITE, purple])
|
||||
}
|
||||
|
||||
pub fn bigender() -> Colors {
|
||||
pub fn bigender() -> Flag {
|
||||
let pink = rgb(0xE676A6);
|
||||
let yellow = rgb(0xF9F04C);
|
||||
let purple = rgb(0xAB6BBB);
|
||||
let blue = rgb(0x6D96DC);
|
||||
|
||||
vec![pink, yellow, WHITE, purple, blue]
|
||||
Flag::Stripes(vec![pink, yellow, WHITE, purple, blue])
|
||||
}
|
||||
|
||||
pub fn bisexual() -> Colors {
|
||||
pub fn bisexual() -> Flag {
|
||||
let magenta = rgb(0xC42A6F);
|
||||
let purple = rgb(0x915392);
|
||||
let blue = rgb(0x1437A2);
|
||||
|
||||
vec![magenta, magenta, purple, blue, blue]
|
||||
Flag::Stripes(vec![magenta, magenta, purple, blue, blue])
|
||||
}
|
||||
|
||||
pub fn gay() -> Colors {
|
||||
pub fn gay() -> Flag {
|
||||
let green1 = rgb(0x00906D);
|
||||
let green2 = rgb(0x00D1A7);
|
||||
let green3 = rgb(0x7EEBC1);
|
||||
|
@ -72,68 +76,68 @@ pub fn gay() -> Colors {
|
|||
let blue2 = rgb(0x5543D3);
|
||||
let blue3 = rgb(0x461280);
|
||||
|
||||
vec![green1, green2, green3, WHITE, blue1, blue2, blue3]
|
||||
Flag::Stripes(vec![green1, green2, green3, WHITE, blue1, blue2, blue3])
|
||||
}
|
||||
|
||||
pub fn genderfluid() -> Colors {
|
||||
pub fn genderfluid() -> Flag {
|
||||
let pink = rgb(0xFF75A2);
|
||||
let violet = rgb(0xBE18D6);
|
||||
let blue = rgb(0x333EBD);
|
||||
|
||||
vec![pink, WHITE, violet, BLACK, blue]
|
||||
Flag::Stripes(vec![pink, WHITE, violet, BLACK, blue])
|
||||
}
|
||||
|
||||
pub fn gender_nonconforming() -> Colors {
|
||||
pub fn gender_nonconforming() -> Flag {
|
||||
let purple = rgb(0x50284D);
|
||||
let magenta = rgb(0x96467B);
|
||||
let blue = rgb(0x5C96F7);
|
||||
|
||||
vec![purple, purple, magenta, blue, WHITE, blue, magenta, purple, purple]
|
||||
Flag::Stripes(vec![purple, purple, magenta, blue, WHITE, blue, magenta, purple, purple])
|
||||
}
|
||||
|
||||
pub fn genderqueer() -> Colors {
|
||||
pub fn genderqueer() -> Flag {
|
||||
let purple = rgb(0xB899DF);
|
||||
let green = rgb(0x6B8E3B);
|
||||
|
||||
vec![purple, WHITE, green]
|
||||
Flag::Stripes(vec![purple, WHITE, green])
|
||||
}
|
||||
|
||||
pub fn gendervoid() -> Colors {
|
||||
pub fn gendervoid() -> Flag {
|
||||
let navy = rgb(0x08114A);
|
||||
let gray = rgb(0x4A484B);
|
||||
|
||||
vec![navy, gray, BLACK, gray, navy]
|
||||
Flag::Stripes(vec![navy, gray, BLACK, gray, navy])
|
||||
}
|
||||
|
||||
pub fn lesbian() -> Colors {
|
||||
pub fn lesbian() -> Flag {
|
||||
let red = rgb(0xD62800);
|
||||
let orange = rgb(0xFF9B56);
|
||||
let pink = rgb(0xD462A6);
|
||||
let magenta = rgb(0xA40062);
|
||||
|
||||
vec![red, orange, WHITE, pink, magenta]
|
||||
Flag::Stripes(vec![red, orange, WHITE, pink, magenta])
|
||||
}
|
||||
|
||||
pub fn multigender() -> Colors {
|
||||
pub fn multigender() -> Flag {
|
||||
let blue = rgb(0x3F47CC);
|
||||
let ltblue = rgb(0x01A4E9);
|
||||
let orange = rgb(0xFB7F27);
|
||||
|
||||
vec![blue, ltblue, orange, ltblue, blue]
|
||||
Flag::Stripes(vec![blue, ltblue, orange, ltblue, blue])
|
||||
}
|
||||
|
||||
pub fn nonbinary() -> Colors {
|
||||
pub fn nonbinary() -> Flag {
|
||||
let yellow = rgb(0xFFF433);
|
||||
let purple = rgb(0x9B59D0);
|
||||
|
||||
vec![yellow, WHITE, purple, BLACK]
|
||||
Flag::Stripes(vec![yellow, WHITE, purple, BLACK])
|
||||
}
|
||||
|
||||
pub fn pansexual() -> Colors {
|
||||
pub fn pansexual() -> Flag {
|
||||
let magenta = rgb(0xFF1B8D);
|
||||
let yellow = rgb(0xFFDA00);
|
||||
let cyan = rgb(0x1BB3FF);
|
||||
|
||||
vec![magenta, yellow, cyan]
|
||||
Flag::Stripes(vec![magenta, yellow, cyan])
|
||||
}
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@ pub fn list_text() {
|
|||
flag list:
|
||||
agender agender pride flag
|
||||
aro, aromantic aromantic pride flag
|
||||
aroace aromantic-asexual pride flag
|
||||
ace, asexual asexual pride flag
|
||||
bigender bigender pride flag
|
||||
bi, bisexual bisexual pride flag
|
||||
|
@ -42,6 +43,7 @@ flag list:
|
|||
nb, nonbinary nonbinary pride flag
|
||||
pan, pansexual pansexual pride flag
|
||||
pride, rainbow six-color rainbow flag
|
||||
progress progress arrow rainbow flag
|
||||
trans, transgender transgender pride flag");
|
||||
}
|
||||
|
||||
|
@ -58,7 +60,8 @@ variants:
|
|||
8-color Gilbert Baker's original 1978 flag with 8 stripes
|
||||
gilbert-baker
|
||||
sex-and-magic
|
||||
philadelphia The 2017 Philadelphia Pride flag with black and brown stripes");
|
||||
philadelphia The 2017 Philadelphia Pride flag with black and brown stripes
|
||||
progress The 2018 Progess rainbow pride flag designed by Daniel Quasar");
|
||||
},
|
||||
|
||||
"transgender" | "trans"
|
||||
|
@ -78,7 +81,9 @@ names:
|
|||
|
||||
variants:
|
||||
7-color 7-stripe flag, also designed in 2018 by Emily Gwen");
|
||||
}
|
||||
},
|
||||
"progress"
|
||||
=> { println!("Daniel Quasar's 2018 Progress rainbow pride flag.\n\nnames:\n 'progress'"); }
|
||||
|
||||
_
|
||||
=> help_text()
|
||||
|
|
37
src/main.rs
37
src/main.rs
|
@ -3,12 +3,17 @@ use std::process::exit;
|
|||
use pico_args::Arguments;
|
||||
|
||||
mod color;
|
||||
mod complex;
|
||||
mod draw;
|
||||
mod flag;
|
||||
<<<<<<< HEAD
|
||||
mod help;
|
||||
=======
|
||||
mod util;
|
||||
>>>>>>> main
|
||||
mod variant;
|
||||
|
||||
use crate::color::Colors;
|
||||
use crate::flag::Flag;
|
||||
|
||||
static VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||
|
||||
|
@ -42,7 +47,7 @@ fn main() {
|
|||
let subcommand = args.subcommand().unwrap();
|
||||
|
||||
// get color vec from matched flag
|
||||
let colors: Colors = match subcommand.as_deref() {
|
||||
let flag: Flag = match subcommand.as_deref() {
|
||||
Some("pride" | "rainbow")
|
||||
| None
|
||||
=> {
|
||||
|
@ -52,6 +57,8 @@ fn main() {
|
|||
=> variant::gilbert_baker(),
|
||||
Some("philadelphia")
|
||||
=> variant::philadelphia(),
|
||||
Some("progress")
|
||||
=> complex::progress(small),
|
||||
_
|
||||
=> flag::pride()
|
||||
}
|
||||
|
@ -70,12 +77,24 @@ fn main() {
|
|||
Some("asexual" | "ace")
|
||||
=> flag::asexual(),
|
||||
|
||||
Some("aroace" | "aromantic-asexual")
|
||||
=> complex::aroace(small),
|
||||
|
||||
Some("bigender")
|
||||
=> flag::bigender(),
|
||||
|
||||
Some("bisexual" | "bi")
|
||||
=> flag::bisexual(),
|
||||
|
||||
Some("demiromantic")
|
||||
=> complex::demiromantic(small),
|
||||
|
||||
Some("demisexual")
|
||||
=> complex::demisexual(small),
|
||||
|
||||
// Some("disability")
|
||||
// => complex::disability();
|
||||
|
||||
Some("gay" | "mlm")
|
||||
=> flag::gay(),
|
||||
|
||||
|
@ -91,6 +110,9 @@ fn main() {
|
|||
Some("gendervoid")
|
||||
=> flag::gendervoid(),
|
||||
|
||||
Some("intersex")
|
||||
=> complex::intersex(),
|
||||
|
||||
Some("lesbian")
|
||||
=> {
|
||||
let variant = args.subcommand().unwrap_or(None);
|
||||
|
@ -111,11 +133,16 @@ fn main() {
|
|||
Some("pansexual" | "pan")
|
||||
=> flag::pansexual(),
|
||||
|
||||
_ => { help::help_text(); exit(1) } // (or die)
|
||||
// Some("poly" | "polyamorous" | "polyamory")
|
||||
// => complex::polyamorous(),
|
||||
|
||||
Some("progress")
|
||||
=> flag::progress(),
|
||||
|
||||
_ => { help_text(); exit(1) }
|
||||
};
|
||||
|
||||
if small { draw::small(colors); }
|
||||
else { draw::full(colors); }
|
||||
flag.draw(!small);
|
||||
|
||||
}
|
||||
|
||||
|
|
52
src/util.rs
Normal file
52
src/util.rs
Normal file
|
@ -0,0 +1,52 @@
|
|||
|
||||
/// gets the substring of displayed characters of an ANSI formatted string
|
||||
pub fn ansi_substr(source: &str, start: usize, end: usize) -> String {
|
||||
// init output string
|
||||
let mut output = String::new();
|
||||
|
||||
// trackers
|
||||
let mut escaped = false;
|
||||
let mut index = 0;
|
||||
for character in source.chars() {
|
||||
// escape character delimits start and end of ansi sequences
|
||||
if character == '\u{1B}' {
|
||||
escaped = true;
|
||||
output.push(character);
|
||||
}
|
||||
// push ALL escaped characters
|
||||
if escaped {
|
||||
output.push(character);
|
||||
// and unset esc on m
|
||||
if character == 'm' { escaped = false; }
|
||||
}
|
||||
// non-escaped characters must obey bounds
|
||||
else {
|
||||
if index < start {
|
||||
index += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
output.push(character);
|
||||
index += 1;
|
||||
|
||||
if index > end { break; }
|
||||
}
|
||||
}
|
||||
output
|
||||
}
|
||||
|
||||
/// gets the number of displayed characters in an ANSI formatted string
|
||||
pub fn ansi_len(source: &str) -> usize {
|
||||
let mut output = 0;
|
||||
let mut escaped = false;
|
||||
|
||||
for character in source.chars() {
|
||||
if character == '\u{1B}' { escaped = true; }
|
||||
|
||||
if !escaped { output += 1; }
|
||||
else if character == 'm' { escaped = false; }
|
||||
}
|
||||
|
||||
output
|
||||
}
|
||||
|
|
@ -3,10 +3,10 @@
|
|||
|
||||
use crate::{
|
||||
color::*,
|
||||
flag
|
||||
flag::{ self, Flag }
|
||||
};
|
||||
|
||||
pub fn gilbert_baker() -> Colors {
|
||||
pub fn gilbert_baker() -> Flag {
|
||||
let pink = rgb(0xFF69B4); // sex
|
||||
let red = rgb(0xFF0000); // life
|
||||
let orange = rgb(0xFF8F00); // healing
|
||||
|
@ -16,20 +16,26 @@ pub fn gilbert_baker() -> Colors {
|
|||
let indigo = rgb(0x3E0099); // serenity
|
||||
let purple = rgb(0x8F008F); // spirit
|
||||
|
||||
vec![pink, red, orange, yellow, green, cyan, indigo, purple]
|
||||
Flag::Stripes(vec![pink, red, orange, yellow, green, cyan, indigo, purple])
|
||||
}
|
||||
|
||||
pub fn philadelphia() -> Colors {
|
||||
pub fn philadelphia() -> Flag {
|
||||
let brown = rgb(0x784F17);
|
||||
|
||||
let mut output = flag::pride();
|
||||
output.insert(0, BLACK);
|
||||
output.insert(1, brown);
|
||||
let base = flag::pride();
|
||||
let mut colors = match base {
|
||||
Flag::Stripes(inner)
|
||||
=> inner,
|
||||
_
|
||||
=> { panic!("impossible enum variant"); }
|
||||
};
|
||||
colors.insert(0, BLACK);
|
||||
colors.insert(1, brown);
|
||||
|
||||
output
|
||||
Flag::Stripes(colors)
|
||||
}
|
||||
|
||||
pub fn lesbian_7() -> Colors {
|
||||
pub fn lesbian_7() -> Flag {
|
||||
let orange1 = rgb(0xD52D00); // gender non-conformity
|
||||
let orange2 = rgb(0xEF7627); // independence
|
||||
let orange3 = rgb(0xFF9A56); // community
|
||||
|
@ -38,6 +44,6 @@ pub fn lesbian_7() -> Colors {
|
|||
let pink2 = rgb(0xB55690); // love and sex
|
||||
let pink3 = rgb(0xA30262); // femininity
|
||||
|
||||
vec![orange1, orange2, orange3, WHITE, pink1, pink2, pink3]
|
||||
Flag::Stripes(vec![orange1, orange2, orange3, WHITE, pink1, pink2, pink3])
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue