Compare commits

...

36 commits
v0.3.0 ... main

Author SHA1 Message Date
715fa605a6 updated Cargo.toml and sbom 2024-12-13 11:02:27 -05:00
a161aab0ca Merge branch 'random-default' 2024-12-13 11:01:07 -05:00
a62316c9f5 updated README 2024-12-13 10:31:15 -05:00
d41df133b1 version bump 2024-12-07 23:02:06 -05:00
9bf53f1d27 default string now splits on semicolons, and spaces are used for variants in default 2024-12-07 23:00:39 -05:00
b91056d68a basic randomized default implementation 2024-12-06 00:03:13 -05:00
ad7fc4e0cd updated dependency version 2024-11-21 08:22:14 -05:00
0773529ba5 default flag behavior now correctly handles empty variable 2024-11-21 08:18:09 -05:00
90e5eb8f79 added the PRIDE_DEFAULT env var to set the default flag 2024-11-20 16:10:29 -05:00
9bac43bf5d added more matches for lesbian 7-stripe variant 2024-11-01 11:09:00 -04:00
0670e3796c version bump 2024-10-30 21:38:00 -04:00
0236f702b4 changed small scaling to be 5:3 with rounding 2024-10-30 21:37:38 -04:00
05e1bd48e0 errors now write to stderr instead of stdout 2024-07-12 10:49:46 -04:00
6a9bbe664a updated README 2024-07-06 21:18:15 -04:00
b1c32ff6f0 removed unused imports 2024-07-06 21:14:41 -04:00
d7fb635a74 updated sbom 2024-07-05 16:17:46 -04:00
d4cee3ed10 added 'wlw' alias to lesbian flag 2024-07-05 16:15:14 -04:00
1e8c7b2a1c added horizontal bound to progress flag 2024-07-05 14:08:52 -04:00
6f320b65fb fixed progress flag misbehaving at certain sizes 2024-07-05 14:07:36 -04:00
0c1c1148c2 made size flag change non-breaking and adjusted version 2024-07-05 10:40:24 -04:00
7cecac36ee fixed flags not matching and removed hard terminal requirement 2024-07-05 10:31:42 -04:00
fc326344f2 updated help text 2024-07-05 10:19:02 -04:00
c871781cc9 added new arbirtrary '--size' flag; removed '--small' flag 2024-07-05 10:17:31 -04:00
a4027ee475 created manual 2024-07-04 12:23:11 -04:00
0347462359 updated termion 2024-03-14 17:15:30 -04:00
3b1a6e6a36 updated Cargo.toml 2024-03-14 17:11:24 -04:00
9f225c540c added files for auditing tools 2024-03-14 17:10:38 -04:00
9f82e65a8a consistency changes to README 2024-02-22 14:12:17 -05:00
33fc042fb6 organized README 2024-02-22 14:11:26 -05:00
7942f7b035 updated gitignore 2024-02-15 20:52:22 -05:00
b7b6bd23b9 set binary name for crates.io package 2024-02-13 17:02:52 -05:00
5ee70eec05 added cargo install instructions 2024-02-11 20:08:04 -05:00
11ca93834d added neutrois pride flag 2024-02-11 19:41:01 -05:00
fd2009d1fd changed release profile 2024-02-04 18:30:27 -05:00
19c1eb1c39 updated README with installation section 2024-02-04 18:14:31 -05:00
577e39d3b2 fixed multisexual flag colors and multi/polysexual not appearing in list 2024-02-04 17:25:05 -05:00
14 changed files with 649 additions and 96 deletions

1
.gitignore vendored
View file

@ -1,2 +1,3 @@
Cargo.lock
/target
/packages

View file

@ -1,18 +1,27 @@
[package]
name = "pride"
version = "0.3.0"
version = "0.4.3"
edition = "2021"
authors = [ "Valerie Wolfe <sleeplessval@gmail.com>" ]
description = "Pride flags in the terminal."
homepage = "https://git.vwolfe.io/valerie/pride"
repository = "https://git.vwolfe.io/valerie/pride"
homepage = "https://git.sleeplessval.io/valerie/pride"
repository = "https://git.sleeplessval.io/valerie/pride"
license = "MIT"
categories = [ "command-line-utilities" ]
keywords = [ "lgbt", "pride", "cli" ]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[package.metadata.aur]
name = "pride"
source = "archive/v$pkgver.tar.gz"
[[bin]]
name = "pride"
path = "src/main.rs"
[dependencies]
oorandom = '11.1.4'
pico-args = "0.5.0"
termion = "2.0.1"
termion = "4.0.3"
[profile.release]
opt-level = 's'
@ -20,5 +29,5 @@ codegen-units = 1
debug = false
lto = true
panic = "abort"
strip = "debuginfo"
strip = "symbols"

View file

@ -3,13 +3,56 @@
A Rust utility to display pride flags in the terminal.
A list of currently implemented flags is available on the [project wiki](https://git.vwolfe.io/valerie/pride/wiki/Flags).
A list of currently implemented flags is available on the [project wiki](https://git.sleeplessval.io/valerie/pride/wiki/Flags).
## Dependencies
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).
## Installation
### Manual Install
<details>
<summary>Release Binary</summary>
Copy the compiled binary from the <a href="https://git.sleeplessval.io/valerie/pride/releases/">releases page</a>
to a directory in <code>$PATH</code>, such as <code>/usr/bin/</code>.
</details>
<details>
<summary>Compile from Source</summary>
Compile using cargo with the command <code>cargo build --release</code> and
copy the file from <code>target/release/</code> to a directory in
<code>$PATH</code>, such as <code>/usr/bin/</code>.
</details>
<details>
<summary>makepkg (AUR)</summary>
Clone the <a href="https://aur.archlinux.org/pride.git">AUR Repository</a> and
run the command <code>makepkg --install</code>.
</details>
### Package Managers
<details>
<summary>Arch Linux (AUR): <code>pride</code></summary>
Install the package from the <a href="https://aur.archlinux.org/packages/pride"><code>pride</code> AUR Package</a>
using an AUR package manager such as <a href="https://github.com/Morganamilo/paru"><code>paru</code></a>.
</details>
<details>
<summary>Cargo: <code>pride-term</code></summary>
Install the package using Cargo with the command <code>cargo install pride-term</code>.
</details>
### Man Page
<details>
<summary>Section 6</summary>
Copy <code>man/pride.6</code> into <code>/usr/share/man/man6/</code>.
</details>
## Libraries
- [pico-args](https://crates.io/crates/pico-args) — argument parsing

4
deny.toml Normal file
View file

@ -0,0 +1,4 @@
[licenses]
allow = [ "MIT" ]

117
man/pride.6 Normal file
View file

@ -0,0 +1,117 @@
.Dd $Mdocdate$
.Dt PRIDE 6
.Os
.Sh NAME
.Nm pride
.Nd shows pride flags in the terminal
.Sh SYNOPSIS
.Nm
.Op Fl hlv
.Op Fl s Op Ar size
.Op Ar flag
.Sh DESCRIPTION
.Nm
displays pride flags in the terminal using ANSI truecolor sequences.
.Ss OPTIONS
.Bl -tag -width Ds
.It Fl h , Fl -help
Shows a brief help text.
.It Fl l , Fl -list
Shows a list of available pride flags.
.It Fl s , Fl -size Op Ar size
Scales the flag to the given size: no value or 'small' will produce the minimum size; one number sets the width; and two numbers separated by 'x' sets width and height respectively.
.It Fl v , Fl -version
Shows version information.
.It Ar flag
The name of the flag to display. Defaults to 'rainbow'.
.El
.Sh FLAGS
.Bl -tag -width Ds
.It Ic agender
.It Ic aromantic, aro
.It Ic aroace, aromantic-asexual
The aromantic-asexual pride flag by @aroaesflags@tumblr.com.
.Pp
VARIANTS
.Bl -tag -width Ds -compact
.It Ic halves, side-by-side, sbs
.El
.It Ic bigender
.It Ic bisexual, bi
The bisexual pride flag designed by Michael Page in 1998.
.It Ic demiboy
.It Ic demigender
.It Ic demigirl
.It Ic demiromantic
.It Ic demisexual
.It Ic gay, mlm
The gay men pride flag designed by @gayflagblog@tumblr.com in 2019.
.It Ic genderfluid
.It Ic gender-nonconforming, gendernonconforming, gnc
.It Ic genderqueer
.It Ic gendervoid
.It Ic lesbian, wlw
The 5-stripe lesbian pride flag designed by Emily Gwen in 2018.
.Pp
VARIANTS
.Bl -tag -width Ds -compact
.It Ic 7, 7-color, 7-stripe
The 7-stripe lesbian pride flag designed by Emily Gwen in 2018.
.El
.It Ic multisexual, m-spec, mspec
.It Ic multigender
.It Ic neutrois
.It Ic nonbinary, nb
The nonbinary pride flag designed by Kyle Rowan in 2014.
.It Ic pansexual, pan
The pansexual pride flag designed by Jasper V circa 2010.
.It Ic polysexual
.It Ic progress
The progress rainbow pride flag designed by Daniel Quasar in 2018.
.It Ic rainbow, pride
The 1979 6-stripe revision of Gilbert Baker's rainbow pride flag.
.Pp
VARIANTS
.Bl -tag -width Ds -compact
.It Ic 8-color, gilbert-baker, sex-and-magic
Gilbert Baker's original 8-stripe rainbow pride flag from 1978.
.It Ic philadelphia
The rainbow flag designed for 2017 Philadelphia Pride.
.It Ic progress
.El
.It Ic transgender, trans
The transgender pride flag designed by Monica Helms in 1999.
.El
.Sh ENVIRONMENT
.Bl -tag -width Ds
.It PRIDE_DEFAULT
A string containing the name of one or more flags to use as the default when no
.Ar flag
argument is provided. If the string contains a semicolon-separated list of flags, a random one will be selected from the list. If a space is found in the chosen substring, it will be used to provide the
.Ar flag
and
.Ar variant
arguments.
.El
.Sh EXIT STATUS
.Bl -tag -width Ds
.It 1
Unmatched
.Ar flag
name.
.It 2
Failed to parse
.Ar size .
.It 3
The provided
.Ar size
is too small to render.
.El
.Sh EXAMPLES
Create a full-width banner flag using tput:
.Pp
.Dl $ pride -s `tput cols`
.Pp
.Sh AUTHORS
.An -nosplit
.An Valerie Wolfe Aq Mt sleeplessval@gmail.com

243
sbom.xml Normal file
View file

@ -0,0 +1,243 @@
{
"SPDXID": "SPDXRef-DOCUMENT",
"creationInfo": {
"created": "2024-12-13T16:02:17.260Z",
"creators": [
"Tool: cargo-sbom-v0.8.4"
]
},
"dataLicense": "CC0-1.0",
"documentNamespace": "https://spdx.org/spdxdocs/pride-93ad73c9-b337-4ad0-bd63-92e9b7d1a2d8",
"files": [
{
"SPDXID": "SPDXRef-File-pride",
"checksums": [],
"fileName": "pride",
"fileTypes": [
"BINARY"
]
}
],
"name": "pride",
"packages": [
{
"SPDXID": "SPDXRef-Package-oorandom-11.1.4",
"description": "A tiny, robust PRNG implementation.",
"downloadLocation": "registry+https://github.com/rust-lang/crates.io-index",
"externalRefs": [
{
"referenceCategory": "PACKAGE-MANAGER",
"referenceLocator": "pkg:cargo/oorandom@11.1.4",
"referenceType": "purl"
}
],
"licenseConcluded": "MIT",
"licenseDeclared": "MIT",
"name": "oorandom",
"versionInfo": "11.1.4"
},
{
"SPDXID": "SPDXRef-Package-redox_syscall-0.5.7",
"description": "A Rust library to access raw Redox system calls",
"downloadLocation": "registry+https://github.com/rust-lang/crates.io-index",
"externalRefs": [
{
"referenceCategory": "PACKAGE-MANAGER",
"referenceLocator": "pkg:cargo/redox_syscall@0.5.7",
"referenceType": "purl"
}
],
"licenseConcluded": "MIT",
"licenseDeclared": "MIT",
"name": "redox_syscall",
"versionInfo": "0.5.7"
},
{
"SPDXID": "SPDXRef-Package-pride-0.4.3",
"description": "Pride flags in the terminal.",
"downloadLocation": "NONE",
"homepage": "https://git.sleeplessval.io/valerie/pride",
"licenseConcluded": "MIT",
"licenseDeclared": "MIT",
"name": "pride",
"versionInfo": "0.4.3"
},
{
"SPDXID": "SPDXRef-Package-termion-4.0.3",
"description": "A bindless library for manipulating terminals.",
"downloadLocation": "registry+https://github.com/rust-lang/crates.io-index",
"externalRefs": [
{
"referenceCategory": "PACKAGE-MANAGER",
"referenceLocator": "pkg:cargo/termion@4.0.3",
"referenceType": "purl"
}
],
"licenseConcluded": "MIT",
"licenseDeclared": "MIT",
"name": "termion",
"versionInfo": "4.0.3"
},
{
"SPDXID": "SPDXRef-Package-redox_termios-0.1.3",
"description": "A Rust library to access Redox termios functions",
"downloadLocation": "registry+https://github.com/rust-lang/crates.io-index",
"externalRefs": [
{
"referenceCategory": "PACKAGE-MANAGER",
"referenceLocator": "pkg:cargo/redox_termios@0.1.3",
"referenceType": "purl"
}
],
"licenseConcluded": "MIT",
"licenseDeclared": "MIT",
"name": "redox_termios",
"versionInfo": "0.1.3"
},
{
"SPDXID": "SPDXRef-Package-libc-0.2.167",
"description": "Raw FFI bindings to platform libraries like libc.\n",
"downloadLocation": "registry+https://github.com/rust-lang/crates.io-index",
"externalRefs": [
{
"referenceCategory": "PACKAGE-MANAGER",
"referenceLocator": "pkg:cargo/libc@0.2.167",
"referenceType": "purl"
}
],
"homepage": "https://github.com/rust-lang/libc",
"licenseConcluded": "MIT OR Apache-2.0",
"licenseDeclared": "MIT OR Apache-2.0",
"name": "libc",
"versionInfo": "0.2.167"
},
{
"SPDXID": "SPDXRef-Package-bitflags-2.6.0",
"description": "A macro to generate structures which behave like bitflags.\n",
"downloadLocation": "registry+https://github.com/rust-lang/crates.io-index",
"externalRefs": [
{
"referenceCategory": "PACKAGE-MANAGER",
"referenceLocator": "pkg:cargo/bitflags@2.6.0",
"referenceType": "purl"
}
],
"homepage": "https://github.com/bitflags/bitflags",
"licenseConcluded": "MIT OR Apache-2.0",
"licenseDeclared": "MIT OR Apache-2.0",
"name": "bitflags",
"versionInfo": "2.6.0"
},
{
"SPDXID": "SPDXRef-Package-libredox-0.1.3",
"description": "Redox stable ABI",
"downloadLocation": "registry+https://github.com/rust-lang/crates.io-index",
"externalRefs": [
{
"referenceCategory": "PACKAGE-MANAGER",
"referenceLocator": "pkg:cargo/libredox@0.1.3",
"referenceType": "purl"
}
],
"licenseConcluded": "MIT",
"licenseDeclared": "MIT",
"name": "libredox",
"versionInfo": "0.1.3"
},
{
"SPDXID": "SPDXRef-Package-numtoa-0.2.4",
"description": "Convert numbers into stack-allocated byte arrays",
"downloadLocation": "registry+https://github.com/rust-lang/crates.io-index",
"externalRefs": [
{
"referenceCategory": "PACKAGE-MANAGER",
"referenceLocator": "pkg:cargo/numtoa@0.2.4",
"referenceType": "purl"
}
],
"licenseConcluded": "MIT OR Apache-2.0",
"licenseDeclared": "MIT OR Apache-2.0",
"name": "numtoa",
"versionInfo": "0.2.4"
},
{
"SPDXID": "SPDXRef-Package-pico-args-0.5.0",
"description": "An ultra simple CLI arguments parser.",
"downloadLocation": "registry+https://github.com/rust-lang/crates.io-index",
"externalRefs": [
{
"referenceCategory": "PACKAGE-MANAGER",
"referenceLocator": "pkg:cargo/pico-args@0.5.0",
"referenceType": "purl"
}
],
"licenseConcluded": "MIT",
"licenseDeclared": "MIT",
"name": "pico-args",
"versionInfo": "0.5.0"
}
],
"relationships": [
{
"relatedSpdxElement": "SPDXRef-Package-redox_termios-0.1.3",
"relationshipType": "DEPENDS_ON",
"spdxElementId": "SPDXRef-Package-termion-4.0.3"
},
{
"relatedSpdxElement": "SPDXRef-Package-libc-0.2.167",
"relationshipType": "DEPENDS_ON",
"spdxElementId": "SPDXRef-Package-termion-4.0.3"
},
{
"relatedSpdxElement": "SPDXRef-Package-pride-0.4.3",
"relationshipType": "GENERATED_FROM",
"spdxElementId": "SPDXRef-File-pride"
},
{
"relatedSpdxElement": "SPDXRef-Package-bitflags-2.6.0",
"relationshipType": "DEPENDS_ON",
"spdxElementId": "SPDXRef-Package-libredox-0.1.3"
},
{
"relatedSpdxElement": "SPDXRef-Package-libc-0.2.167",
"relationshipType": "DEPENDS_ON",
"spdxElementId": "SPDXRef-Package-libredox-0.1.3"
},
{
"relatedSpdxElement": "SPDXRef-Package-libredox-0.1.3",
"relationshipType": "DEPENDS_ON",
"spdxElementId": "SPDXRef-Package-termion-4.0.3"
},
{
"relatedSpdxElement": "SPDXRef-Package-pico-args-0.5.0",
"relationshipType": "DEPENDS_ON",
"spdxElementId": "SPDXRef-Package-pride-0.4.3"
},
{
"relatedSpdxElement": "SPDXRef-Package-termion-4.0.3",
"relationshipType": "DEPENDS_ON",
"spdxElementId": "SPDXRef-Package-pride-0.4.3"
},
{
"relatedSpdxElement": "SPDXRef-Package-redox_syscall-0.5.7",
"relationshipType": "DEPENDS_ON",
"spdxElementId": "SPDXRef-Package-libredox-0.1.3"
},
{
"relatedSpdxElement": "SPDXRef-Package-numtoa-0.2.4",
"relationshipType": "DEPENDS_ON",
"spdxElementId": "SPDXRef-Package-termion-4.0.3"
},
{
"relatedSpdxElement": "SPDXRef-Package-oorandom-11.1.4",
"relationshipType": "DEPENDS_ON",
"spdxElementId": "SPDXRef-Package-pride-0.4.3"
},
{
"relatedSpdxElement": "SPDXRef-Package-bitflags-2.6.0",
"relationshipType": "DEPENDS_ON",
"spdxElementId": "SPDXRef-Package-redox_syscall-0.5.7"
}
],
"spdxVersion": "SPDX-2.3"
}

View file

@ -1,15 +1,13 @@
//! flags that require more complex rendering than just scaling colored stripes
use termion::{
terminal_size,
color::{ Bg, Rgb }
};
use termion::color::{ Bg, Rgb };
use crate::{
color::*,
draw,
error,
flag::{ self, Flag },
state::State,
util::{ ansi_len, ansi_substr }
};
@ -27,7 +25,7 @@ pub static TRIANGLE_21: [char; 3] = ['', '🭬', ''];
/// 2/3 slope slant
pub static SLANT_23: [char; 2] = ['🭒', '🭏'];
pub fn progress(small: bool) -> Flag {
pub fn progress(state: &State) -> Flag {
let red = bg(0xE50000);
let orange = bg(0xFF8D00);
let yellow = bg(0xFFEE00);
@ -42,7 +40,8 @@ pub fn progress(small: bool) -> Flag {
let pink: u32 = 0x7ACBF5;
let white: u32 = 0xFFFFFF;
let (width, height) = if small { (18, 6) } else { terminal_size().unwrap() };
let (width, height) = state.size.get(18, 6);
if height < 6 || width < 6 { error::too_small(width, height); }
// create color slices and line buffer
let stripes = [red, orange, yellow, green, blue, purple];
@ -55,7 +54,7 @@ pub fn progress(small: bool) -> Flag {
// 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 chevron_width = if full_depth > 6 { (full_depth / 6) - 1 } else { 0 };
let direction_thresh = linecount / 2;
let corner = linecount % 2 == 1;
@ -96,17 +95,14 @@ pub fn progress(small: bool) -> Flag {
// grab our substring constraints
let start = (direction_thresh - n) as usize - 1;
let diff = display_length - start;
let diff = if display_length >= start { display_length - start } else { 0 };
// take substring of chevron line...
let mut line = ansi_substr(&base, start as usize, base_length);
line += &stripes[index].to_string();
if diff > 0 { line.push(TRIANGLE_21[0]); }
// ... and add the colored stripe
line += &format!(
"{stripe}{separator}{line}",
stripe = stripes[index],
separator = TRIANGLE_21[0],
line = " ".repeat(width as usize - diff)
);
line += &" ".repeat(width as usize - diff);
lines.push(line);
line_no += 1;
@ -132,15 +128,12 @@ pub fn progress(small: bool) -> Flag {
if index > 5 { break; }
let start = n as usize;
let diff = display_length - start;
let diff = if display_length >= start { display_length - start } else { 0 };
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)
);
line += &stripes[index].to_string();
if diff > 0 { line.push(TRIANGLE_21[2]); }
line += &" ".repeat(width as usize - diff);
lines.push(line);
line_no += 1;
@ -151,12 +144,13 @@ pub fn progress(small: bool) -> Flag {
// everything below this point is in alphabetical order
pub fn aroace(small: bool) -> Flag {
pub fn aroace_halves(state: &State) -> 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 (width, height) = state.size.get(60, 20);
if height < 20 { error::too_small(width, height); }
let mut lines: Vec<String> = Vec::new();
@ -185,6 +179,8 @@ pub fn aroace(small: bool) -> Flag {
fn demi_orientation_render(middle: Bg<Rgb>, bottom: Bg<Rgb>, width: u16, height: u16) -> Vec<String> {
let white = bg(0xFFFFFF);
if height < 5 { error::too_small(width, height); }
let stripes = vec![white, white, middle, bottom, bottom];
// initial stripe output buffer
@ -219,21 +215,21 @@ fn demi_orientation_render(middle: Bg<Rgb>, bottom: Bg<Rgb>, width: u16, height:
lines
}
pub fn demiromantic(small: bool) -> Flag {
pub fn demiromantic(state: &State) -> Flag {
let green = bg(0x3DA542);
let gray = bg(0xD2D2D2);
let (width, height) = if small { (15, 5) } else { terminal_size().unwrap() };
let (width, height) = state.size.get(15, 5);
let lines = demi_orientation_render(green, gray, width, height);
Flag::Lines(lines)
}
pub fn demisexual(small: bool) -> Flag {
pub fn demisexual(state: &State) -> Flag {
let purple = bg(0x832FA8);
let grey = bg(0x7B868C);
let (width, height) = if small { (15, 5) } else { terminal_size().unwrap() };
let (width, height) = state.size.get(15, 5);
let lines = demi_orientation_render(purple, grey, width, height);
Flag::Lines(lines)
@ -274,7 +270,7 @@ pub fn intersex() -> Flag {
}
pub fn polyamory(small: bool) -> Flag {
pub fn polyamory(state: &State) -> Flag {
let blue = rgb(0x019FE3);
let magenta = rgb(0xE50051);
let purple = rgb(0x340C46);
@ -285,7 +281,8 @@ pub fn polyamory(small: bool) -> Flag {
let semicircle = '\u{E0B6}';
let separators = ['\u{E0BE}', '\u{E0BA}'];
let (width, height) = if small { (18, 6) } else { terminal_size().unwrap() };
let (width, height) = state.size.get(18, 6);
if height < 6 { error::too_small(width, height); }
// create stripe array and line buffer
let stripes = [magenta, purple]; // only stripes 2 and 3 need tracked

View file

@ -1,10 +1,11 @@
//! render handling code
use std::io::{ self, Write };
use std::io::{
self,
Write
};
use termion::{
terminal_size,
clear,
color::{ Bg, Fg, Rgb },
cursor,
@ -14,39 +15,53 @@ use termion::{
use crate::{
color::{ RESET, RESET_BG },
flag::Flag
error,
flag::Flag,
state::{ Size, State }
};
pub static BLOCK: &str = "";
pub static UHALF: &str = "";
/// prints a provided vec of lines to stdout
pub fn draw_lines(lines: Vec<String>, hold: bool) {
pub fn draw_full(lines: Vec<String>) {
let mut stdout = io::stdout().into_raw_mode().unwrap();
// get in position for draw
let count = lines.len() as u16;
for _ in 0..count { write!(stdout, "\n").ok(); }
write!(stdout, "{}", cursor::Up(count)).ok();
if hold { write!(stdout, "{}{}", cursor::Hide, clear::All).ok(); }
// clear screen and hide cursor
write!(stdout, "{}{}", cursor::Hide, clear::All).ok();
// write lines
let down = cursor::Down(1);
for line in lines {
let left = cursor::Left(line.len() as u16);
write!(stdout, "{line}{left}{down}").ok();
}
// clear formatting and flush buffer
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();
// hold for input
let stdin = io::stdin();
for _ in stdin.keys() { break; }
// clear and show cursor
write!(stdout, "{}{}", clear::All, cursor::Show).ok();
stdout.flush().ok();
}
pub fn draw_lines(lines: Vec<String>, state: &State) {
match state.size {
Size::Full => draw_full(lines),
_ => for line in lines { println!("{line}{RESET}{RESET_BG}") }
}
}
/// generates lines for foreground colors provided as a vec of strings for the draw_lines method
pub fn fg_stripes(colors: Vec<Fg<Rgb>>, width: u16, height: u16) -> Vec<String> {
let width = width as usize;
@ -98,22 +113,19 @@ pub fn bg_stripes(colors: Vec<Bg<Rgb>>, width: u16, height: u16) -> Vec<String>
impl Flag {
/// renders a flag to stdout
pub fn draw(self, hold: bool) {
pub fn draw(self, state: &State) {
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;
}
let count = colors.len() as u16;
let (width, height) = state.size.get((count * 20 + 3) / 6, count);
if height < count { error::too_small(width, height); }
fg_stripes(colors, width, height)
},
Flag::Lines(lines)
=> lines
};
draw_lines(lines, hold);
draw_lines(lines, &state);
}
}

24
src/error.rs Normal file
View file

@ -0,0 +1,24 @@
use std::process::exit;
pub fn unmatched_flag(target: String) {
eprintln!("pride: no flag {target}");
exit(1);
}
pub fn size_missing() {
eprintln!("pride: size flag requires a value");
exit(2);
}
pub fn size_error(value: &str) {
eprintln!("pride: size '{value}' is invalid");
exit(2);
}
pub fn too_small(width: u16, height: u16) {
eprintln!("pride: this flag must be bigger than {width}x{height}");
exit(3);
}

View file

@ -158,13 +158,19 @@ pub fn multigender() -> Flag {
pub fn multisexual() -> Flag {
let purple = rgb(0x724DC9);
let blue = rgb(0xFF3D9B);
let blue = rgb(0xA0EFFE);
let pink = rgb(0xFF3D9B);
Flag::Stripes(vec![purple, WHITE, blue, pink])
}
pub fn neutrois() -> Flag {
let green = rgb(0x2D9A1B);
Flag::Stripes(vec![WHITE, green, BLACK])
}
pub fn nonbinary() -> Flag {
let yellow = rgb(0xFFF433);
let purple = rgb(0x9B59D0);

View file

@ -13,13 +13,13 @@ Display pride flags in the terminal.
usage: pride [flags] [name]
args:
<name> The pride flag to display
<name> The pride flag to display
flags:
-h, --help Shows this help text
--version Show version information
-l, --list Prints a list of printable flags
-s, --small Prints a small version without holding
-h, --help Shows this help text
--version Show version information
-l, --list Prints a list of printable flags
-s, --size [size] Sets the size of the output flag.
Use 'pride --list' to see a list of printable flags
@ -49,8 +49,11 @@ flag list:
gendervoid gendervoid pride flag
lesbian lesbian pride flag
multigender multigender pride flag
multisexual multisexual pride flag
neutrois neutrois pride flag
nonbinary nonbinary pride flag
pansexual pansexual pride flag
polysexual polysexual pride flag
rainbow six-color rainbow flag
progress progress arrow rainbow flag
transgender transgender pride flag");
@ -127,15 +130,17 @@ names:
=> { println!("The gender-nonconforming pride flag.\n\nnames:\n 'gender-nonconforming', 'gendernonconforming', 'gnc'"); },
"lesbian"
"lesbian" | "wlw"
=> {
println!("The 5-stripe lesbian flag designed by Emily Gwen in 2018.
names:
'lesbian'
'lesbian', 'wlw'
variants:
7-color 7-stripe flag, also designed in 2018 by Emily Gwen");
7 7-stripe flag, also designed in 2018 by Emily Gwen
7-color
7-stripe");
},

View file

@ -1,8 +1,7 @@
//! main method module
use std::{
io::{ stdout, IsTerminal },
process::exit
env::var,
time::UNIX_EPOCH
};
use pico_args::Arguments;
@ -10,21 +9,31 @@ use pico_args::Arguments;
mod color;
mod complex;
mod draw;
mod error;
mod flag;
mod help;
mod state;
mod util;
mod variant;
use crate::flag::Flag;
use crate::{
flag::Flag,
state::State
};
static VERSION: &str = env!("CARGO_PKG_VERSION");
pub const FLAG_HELP: [&str;2] = [ "-h", "--help" ];
pub const FLAG_LIST: [&str;2] = [ "-l", "--list" ];
pub const FLAG_SIZE: [&str;2] = [ "-s", "--size" ];
pub const FLAG_VERSION: [&str;2] = [ "-v", "--version" ];
fn main() {
// collect args
let mut args = Arguments::from_env();
// handle help flag
if args.contains(["-h", "--help"]) {
if args.contains(FLAG_HELP) {
let target = args.subcommand().unwrap();
if target.is_some() { help::flag_help(&target.unwrap()); }
else { help::help_text(); }
@ -32,27 +41,38 @@ fn main() {
}
// handle list flag
if args.contains(["-l", "--list"]) {
if args.contains(FLAG_LIST) {
help::list_text();
return;
}
// handle version flag
if args.contains(["-v", "--version"]) {
if args.contains(FLAG_VERSION) {
println!("pride v{VERSION}");
return;
}
if !stdout().is_terminal() {
println!("pride: output must be a terminal");
exit(2);
}
let state = State::new(&mut args);
// get small flag
let small = args.contains(["-s", "--small"]);
let subcommand = args.subcommand().unwrap();
let variant = args.subcommand().unwrap_or(None);
let ( subcommand, variant ) =
if let Ok(Some(subcommand)) = args.subcommand() { ( Some(subcommand), args.subcommand().unwrap()) }
else if let Ok(default) = var("PRIDE_DEFAULT") {
if default.is_empty() { ( None, None ) }
else if default.contains(';') {
let split: Vec<&str> = default.split(';').collect();
if let Ok(time) = UNIX_EPOCH.elapsed() {
let index = oorandom::Rand32::new(time.as_secs()).rand_u32();
let chosen = split[index as usize % split.len()].to_owned();
if chosen.contains(' ') {
let split: Vec<&str> = chosen.split(' ').collect();
( Some(split[0].to_owned()), Some(split[1].to_owned()) )
} else { ( Some(chosen), None ) }
} else { ( None, None ) }
} else if default.contains(' ') {
let split: Vec<&str> = default.split(' ').collect();
( Some(split[0].to_owned()), Some(split[1].to_owned()) )
} else { ( Some(default), None ) }
} else { ( None, None ) };
// get color vec from matched flag
let flag: Flag = match subcommand.as_deref() {
@ -65,14 +85,14 @@ fn main() {
Some("philadelphia")
=> variant::philadelphia(),
Some("progress")
=> complex::progress(small),
=> complex::progress(&state),
_
=> flag::pride()
}
},
Some("progress")
=> complex::progress(small),
=> complex::progress(&state),
Some("agender")
@ -88,7 +108,7 @@ fn main() {
=> {
match variant.as_deref() {
Some("halves" | "side-by-side" | "sbs")
=> complex::aroace(small),
=> complex::aroace_halves(&state),
_
=> flag::aroace()
}
@ -109,14 +129,15 @@ fn main() {
=> flag::demigirl(),
Some("demiromantic")
=> complex::demiromantic(small),
=> complex::demiromantic(&state),
Some("demisexual")
=> complex::demisexual(small),
=> complex::demisexual(&state),
// Some("disability")
// => complex::disability();
Some("gay" | "mlm")
=> flag::gay(),
@ -132,28 +153,36 @@ fn main() {
Some("gendervoid")
=> flag::gendervoid(),
// Some("intersex")
// => complex::intersex(),
Some("lesbian")
Some("lesbian" | "wlw")
=> {
match variant.as_deref() {
Some("7-color")
Some("7" | "7-color" | "7-stripe")
=> variant::lesbian_7(),
_
=> flag::lesbian()
}
}
Some("multisexual" | "m-spec" | "mspec")
=> flag::multisexual(),
Some("multigender")
=> flag::multigender(),
Some("neutrois")
=> flag::neutrois(),
Some("nonbinary" | "nb")
=> flag::nonbinary(),
Some("pansexual" | "pan")
=> flag::pansexual(),
@ -163,20 +192,17 @@ fn main() {
Some("polysexual")
=> flag::polysexual(),
Some("transgender" | "trans")
=> flag::transgender(),
_
=> {
println!("pride: no flag '{}'", subcommand.unwrap());
help::help_text();
exit(1)
}
=> { error::unmatched_flag(subcommand.unwrap()); panic!() }
};
// draw flag
flag.draw(!small);
flag.draw(&state);
}

66
src/state.rs Normal file
View file

@ -0,0 +1,66 @@
use std::io::{ stdout, IsTerminal };
use pico_args::{ Arguments, Error };
use termion::terminal_size;
use crate::{ FLAG_SIZE, error };
#[derive(PartialEq)]
pub enum Size {
Full,
Small,
Set(u16, u16),
Wide(u16)
}
impl Size {
pub fn from(value: &str) -> Size {
if value == "small" { return Size::Small; }
let split: Vec<&str> = value.split('x').collect();
let len = split.len();
if len == 2 {
if let (Ok(width), Ok(height)) = (str::parse::<u16>(split.get(0).unwrap()), str::parse::<u16>(split.get(1).unwrap())) {
return Size::Set(width, height);
}
} else if len == 1 {
if let Ok(width) = str::parse::<u16>(split.get(0).unwrap()) {
return Size::Wide(width);
}
}
error::size_error(value);
panic!();
}
pub fn get(&self, width: u16, height: u16) -> (u16, u16) {
match self {
Size::Full => terminal_size().unwrap(),
Size::Set(width, height) => (width.clone(), height.clone()),
Size::Small => (width, height),
Size::Wide(width) => (width.clone(), height)
}
}
}
pub struct State {
pub size: Size,
pub is_terminal: bool,
}
impl State {
pub fn new(args: &mut Arguments) -> State {
let is_terminal = stdout().is_terminal();
let size = match args.value_from_str::<[&str;2], String>(FLAG_SIZE).as_deref() {
Ok(value) => Size::from(value),
Err(Error::MissingOption(_)) |
Err(Error::MissingArgument) => if is_terminal { Size::Full } else { Size::Small },
Err(Error::OptionWithoutAValue(_)) => Size::Small,
_ => { error::size_missing(); panic!() }
};
State { size, is_terminal }
}
}

View file

@ -27,7 +27,7 @@ pub fn philadelphia() -> Flag {
Flag::Stripes(inner)
=> inner,
_
=> { panic!("impossible enum variant"); }
=> panic!("impossible enum variant")
};
colors.insert(0, BLACK);
colors.insert(1, brown);