mirror of
https://codeberg.org/Cyborus/forgejo-cli.git
synced 2024-11-10 12:09:33 +01:00
Merge pull request 'add optional fancy output' (#53) from optional-pretty into main
Reviewed-on: https://codeberg.org/Cyborus/forgejo-cli/pulls/53
This commit is contained in:
commit
0a30d14035
3 changed files with 140 additions and 10 deletions
112
src/main.rs
112
src/main.rs
|
@ -1,3 +1,5 @@
|
|||
use std::io::IsTerminal;
|
||||
|
||||
use clap::{Parser, Subcommand};
|
||||
use eyre::{eyre, Context, OptionExt};
|
||||
use tokio::io::AsyncWriteExt;
|
||||
|
@ -14,6 +16,8 @@ mod repo;
|
|||
pub struct App {
|
||||
#[clap(long, short = 'H')]
|
||||
host: Option<String>,
|
||||
#[clap(long)]
|
||||
style: Option<Style>,
|
||||
#[clap(subcommand)]
|
||||
command: Command,
|
||||
}
|
||||
|
@ -36,6 +40,9 @@ pub enum Command {
|
|||
#[tokio::main]
|
||||
async fn main() -> eyre::Result<()> {
|
||||
let args = App::parse();
|
||||
|
||||
let _ = SPECIAL_RENDER.set(SpecialRender::new(args.style.unwrap_or_default()));
|
||||
|
||||
let mut keys = KeyInfo::load().await?;
|
||||
|
||||
let host_name = args.host.as_deref();
|
||||
|
@ -137,3 +144,108 @@ async fn tempfile(ext: Option<&str>) -> tokio::io::Result<(tokio::fs::File, std:
|
|||
.await?;
|
||||
Ok((file, path))
|
||||
}
|
||||
|
||||
use std::sync::OnceLock;
|
||||
static SPECIAL_RENDER: OnceLock<SpecialRender> = OnceLock::new();
|
||||
|
||||
fn special_render() -> &'static SpecialRender {
|
||||
SPECIAL_RENDER
|
||||
.get()
|
||||
.expect("attempted to get special characters before that was initialized")
|
||||
}
|
||||
|
||||
#[derive(clap::ValueEnum, Clone, Copy, Debug, Default)]
|
||||
enum Style {
|
||||
/// Use special characters, and colors.
|
||||
#[default]
|
||||
Fancy,
|
||||
/// No special characters and no colors. Always used in non-terminal contexts (i.e. pipes)
|
||||
Minimal,
|
||||
}
|
||||
|
||||
struct SpecialRender {
|
||||
dash: char,
|
||||
bullet: char,
|
||||
body_prefix: char,
|
||||
|
||||
red: &'static str,
|
||||
bright_red: &'static str,
|
||||
green: &'static str,
|
||||
bright_green: &'static str,
|
||||
blue: &'static str,
|
||||
bright_blue: &'static str,
|
||||
cyan: &'static str,
|
||||
bright_cyan: &'static str,
|
||||
yellow: &'static str,
|
||||
bright_yellow: &'static str,
|
||||
magenta: &'static str,
|
||||
bright_magenta: &'static str,
|
||||
black: &'static str,
|
||||
dark_grey: &'static str,
|
||||
light_grey: &'static str,
|
||||
white: &'static str,
|
||||
reset: &'static str,
|
||||
}
|
||||
|
||||
impl SpecialRender {
|
||||
fn new(display: Style) -> Self {
|
||||
let is_tty = std::io::stdout().is_terminal();
|
||||
match display {
|
||||
_ if !is_tty => Self::minimal(),
|
||||
Style::Fancy => Self::fancy(),
|
||||
Style::Minimal => Self::minimal(),
|
||||
}
|
||||
}
|
||||
|
||||
fn fancy() -> Self {
|
||||
Self {
|
||||
dash: '—',
|
||||
bullet: '•',
|
||||
body_prefix: '▌',
|
||||
|
||||
red: "\x1b[31m",
|
||||
bright_red: "\x1b[91m",
|
||||
green: "\x1b[32m",
|
||||
bright_green: "\x1b[92m",
|
||||
blue: "\x1b[34m",
|
||||
bright_blue: "\x1b[94m",
|
||||
cyan: "\x1b[36m",
|
||||
bright_cyan: "\x1b[96m",
|
||||
yellow: "\x1b[33m",
|
||||
bright_yellow: "\x1b[93m",
|
||||
magenta: "\x1b[35m",
|
||||
bright_magenta: "\x1b[95m",
|
||||
black: "\x1b[30m",
|
||||
dark_grey: "\x1b[90m",
|
||||
light_grey: "\x1b[37m",
|
||||
white: "\x1b[97m",
|
||||
reset: "\x1b[0m",
|
||||
}
|
||||
}
|
||||
|
||||
fn minimal() -> Self {
|
||||
Self {
|
||||
dash: '-',
|
||||
bullet: '-',
|
||||
body_prefix: '>',
|
||||
|
||||
red: "",
|
||||
bright_red: "",
|
||||
green: "",
|
||||
bright_green: "",
|
||||
blue: "",
|
||||
bright_blue: "",
|
||||
cyan: "",
|
||||
bright_cyan: "",
|
||||
yellow: "",
|
||||
bright_yellow: "",
|
||||
magenta: "",
|
||||
bright_magenta: "",
|
||||
black: "",
|
||||
dark_grey: "",
|
||||
light_grey: "",
|
||||
white: "",
|
||||
reset: "",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ use tokio::io::AsyncWriteExt;
|
|||
use crate::{
|
||||
keys::KeyInfo,
|
||||
repo::{RepoInfo, RepoName},
|
||||
SpecialRender,
|
||||
};
|
||||
|
||||
#[derive(Args, Clone, Debug)]
|
||||
|
@ -374,6 +375,13 @@ async fn view_release(
|
|||
&time::format_description::well_known::Rfc2822,
|
||||
)?;
|
||||
println!();
|
||||
let SpecialRender {
|
||||
bullet,
|
||||
body_prefix,
|
||||
dark_grey,
|
||||
reset,
|
||||
..
|
||||
} = crate::special_render();
|
||||
let body = release
|
||||
.body
|
||||
.as_ref()
|
||||
|
@ -381,7 +389,7 @@ async fn view_release(
|
|||
if !body.is_empty() {
|
||||
println!();
|
||||
for line in body.lines() {
|
||||
println!("> {line}");
|
||||
println!("{dark_grey}{body_prefix}{reset} {line}");
|
||||
}
|
||||
println!();
|
||||
}
|
||||
|
@ -396,10 +404,10 @@ async fn view_release(
|
|||
.name
|
||||
.as_ref()
|
||||
.ok_or_else(|| eyre::eyre!("asset does not have name"))?;
|
||||
println!("- {}", name);
|
||||
println!("{bullet} {}", name);
|
||||
}
|
||||
println!("- source.zip");
|
||||
println!("- source.tar.gz");
|
||||
println!("{bullet} source.zip");
|
||||
println!("{bullet} source.tar.gz");
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
22
src/repo.rs
22
src/repo.rs
|
@ -3,6 +3,8 @@ use eyre::{eyre, OptionExt};
|
|||
use forgejo_api::structs::CreateRepoOption;
|
||||
use url::Url;
|
||||
|
||||
use crate::SpecialRender;
|
||||
|
||||
pub struct RepoInfo {
|
||||
url: Url,
|
||||
name: Option<RepoName>,
|
||||
|
@ -351,6 +353,14 @@ impl RepoCommand {
|
|||
.ok_or_eyre("couldn't get repo name, please specify")?;
|
||||
let repo = api.repo_get(repo.owner(), repo.name()).await?;
|
||||
|
||||
let SpecialRender {
|
||||
dash,
|
||||
body_prefix,
|
||||
dark_grey,
|
||||
reset,
|
||||
..
|
||||
} = crate::special_render();
|
||||
|
||||
println!("{}", repo.full_name.ok_or_eyre("no full name")?);
|
||||
|
||||
if let Some(parent) = &repo.parent {
|
||||
|
@ -370,7 +380,7 @@ impl RepoCommand {
|
|||
println!();
|
||||
}
|
||||
for line in desc.lines() {
|
||||
println!("> {line}");
|
||||
println!("{dark_grey}{body_prefix}{reset} {line}");
|
||||
}
|
||||
}
|
||||
println!();
|
||||
|
@ -382,13 +392,13 @@ impl RepoCommand {
|
|||
|
||||
let stars = repo.stars_count.unwrap_or_default();
|
||||
if stars == 1 {
|
||||
print!("{stars} star - ");
|
||||
print!("{stars} star {dash} ");
|
||||
} else {
|
||||
print!("{stars} stars - ");
|
||||
print!("{stars} stars {dash} ");
|
||||
}
|
||||
|
||||
let watchers = repo.watchers_count.unwrap_or_default();
|
||||
print!("{watchers} watching - ");
|
||||
print!("{watchers} watching {dash} ");
|
||||
|
||||
let forks = repo.forks_count.unwrap_or_default();
|
||||
if forks == 1 {
|
||||
|
@ -410,7 +420,7 @@ impl RepoCommand {
|
|||
}
|
||||
if repo.has_pull_requests.unwrap_or_default() {
|
||||
if !first {
|
||||
print!(" - ");
|
||||
print!(" {dash} ");
|
||||
}
|
||||
let pulls = repo.open_pr_counter.unwrap_or_default();
|
||||
if pulls == 1 {
|
||||
|
@ -422,7 +432,7 @@ impl RepoCommand {
|
|||
}
|
||||
if repo.has_releases.unwrap_or_default() {
|
||||
if !first {
|
||||
print!(" - ");
|
||||
print!(" {dash} ");
|
||||
}
|
||||
let releases = repo.release_counter.unwrap_or_default();
|
||||
if releases == 1 {
|
||||
|
|
Loading…
Reference in a new issue