Skip to content

Commit

Permalink
Support for table styles
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelklishin committed Feb 2, 2025
1 parent 2764a47 commit a6c56fa
Show file tree
Hide file tree
Showing 4 changed files with 170 additions and 16 deletions.
30 changes: 28 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,34 @@
# rabbitmqadmin-ng Change Log

## v0.23.0 (in development
## v0.23.0 (in development)

No (documented) changes yet.
### Enhancements

* New general option `--table-style`, can be used to change output table styling.

For example, an equivalent of `--non-interactive` in terms of styling is

```shell
rabbitmqadmin --table-style=borderless show overview
```

More available styles:

```shell
rabbitmqadmin --table-style=ascii show overview
```

```shell
rabbitmqadmin --table-style=psql show overview
```

```shell
rabbitmqadmin --table-style=markdown show overview
```

```shell
rabbitmqadmin --table-style=dots show overview
```


## v0.22.0 (Feb 1, 2025)
Expand Down
11 changes: 11 additions & 0 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use std::path::PathBuf;
use super::constants::*;
use super::static_urls::*;
use super::tanzu_cli::tanzu_subcommands;
use crate::output::TableStyle;
use clap::{Arg, ArgAction, Command};
use rabbitmq_http_client::commons::{
BindingDestinationType, ExchangeType, QueueType, SupportedProtocol,
Expand Down Expand Up @@ -186,10 +187,20 @@ pub fn parser() -> Command {
Arg::new("non_interactive")
.long("non-interactive")
.help("pass when invoking from scripts")
.conflicts_with("table_style")
.required(false)
.value_parser(clap::value_parser!(bool))
.action(ArgAction::SetTrue),
)
// --table-style
.arg(
Arg::new("table_style")
.long("table-style")
.help("style preset to apply to output tables: modern, borderless, ascii, dots, psql, markdown, sharp")
.conflicts_with("non_interactive")
.required(false)
.value_parser(clap::value_parser!(TableStyle))
)
.subcommand_required(true)
.subcommand_value_name("command")
.subcommands([
Expand Down
28 changes: 28 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use crate::constants::{
DEFAULT_PASSWORD, DEFAULT_PATH_PREFIX, DEFAULT_SCHEME, DEFAULT_USERNAME, DEFAULT_VHOST,
HTTPS_SCHEME,
};
use crate::output::TableStyle;
use clap::ArgMatches;
use serde::Deserialize;
use std::collections::HashMap;
Expand Down Expand Up @@ -70,6 +71,9 @@ pub struct SharedSettings {

#[serde(skip_serializing_if = "Option::is_none")]
pub virtual_host: Option<String>,

#[serde(skip_serializing_if = "Option::is_none")]
pub table_style: Option<TableStyle>,
}

impl SharedSettings {
Expand Down Expand Up @@ -164,6 +168,11 @@ impl SharedSettings {
.cloned()
.or(config_file_defaults.virtual_host.clone())
.unwrap_or(DEFAULT_VHOST.to_owned());
let table_style = cli_args
.get_one::<TableStyle>("table_style")
.cloned()
.or(Some(TableStyle::default()))
.unwrap_or(TableStyle::default());

Self {
tls: should_use_tls,
Expand All @@ -177,6 +186,7 @@ impl SharedSettings {
username: Some(username.to_string()),
password: Some(password.to_string()),
virtual_host: Some(vhost),
table_style: Some(table_style),
}
}

Expand Down Expand Up @@ -221,6 +231,11 @@ impl SharedSettings {
.get_one::<String>("vhost")
.cloned()
.unwrap_or(DEFAULT_VHOST.to_owned());
let table_style = cli_args
.get_one::<TableStyle>("table_style")
.cloned()
.or(Some(TableStyle::default()))
.unwrap_or(TableStyle::default());

Self {
tls: should_use_tls,
Expand All @@ -234,6 +249,7 @@ impl SharedSettings {
username: Some(username.to_string()),
password: Some(password.to_string()),
virtual_host: Some(vhost),
table_style: Some(table_style),
}
}

Expand Down Expand Up @@ -285,6 +301,11 @@ impl SharedSettings {
.cloned()
.or(config_file_defaults.virtual_host.clone())
.unwrap_or(DEFAULT_VHOST.to_owned());
let table_style = cli_args
.get_one::<TableStyle>("table_style")
.cloned()
.or(Some(TableStyle::default()))
.unwrap_or(TableStyle::default());

Self {
tls: should_use_tls,
Expand All @@ -298,6 +319,7 @@ impl SharedSettings {
username: Some(username),
password: Some(password),
virtual_host: Some(vhost),
table_style: Some(table_style),
}
}

Expand Down Expand Up @@ -341,6 +363,11 @@ impl SharedSettings {
.get_one::<String>("vhost")
.cloned()
.unwrap_or(DEFAULT_VHOST.to_owned());
let table_style = cli_args
.get_one::<TableStyle>("table_style")
.cloned()
.or(Some(TableStyle::default()))
.unwrap_or(TableStyle::default());

Self {
tls: should_use_tls,
Expand All @@ -354,6 +381,7 @@ impl SharedSettings {
username: Some(username),
password: Some(password),
virtual_host: Some(vhost),
table_style: Some(table_style),
}
}

Expand Down
117 changes: 103 additions & 14 deletions src/output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,59 +21,148 @@ use rabbitmq_http_client::responses::{
NodeMemoryBreakdown, Overview, SchemaDefinitionSyncStatus, WarmStandbyReplicationStatus,
};
use reqwest::StatusCode;
use serde::{Deserialize, Serialize};
use std::fmt;
use sysexits::ExitCode;
use tabled::settings::object::Rows;
use tabled::settings::{Panel, Remove, Style};
use tabled::{Table, Tabled};

#[derive(Default, Serialize, Deserialize, Debug, PartialEq, Eq, Clone, Copy)]
pub enum TableStyle {
#[default]
Modern,
Borderless,
Markdown,
Sharp,
Ascii,
Psql,
Dots,
}

impl From<&str> for TableStyle {
fn from(s: &str) -> Self {
match s {
"modern" => TableStyle::Modern,
"borderless" => TableStyle::Borderless,
"ascii" => TableStyle::Ascii,
"markdown" => TableStyle::Markdown,
"sharp" => TableStyle::Sharp,
"psql" => TableStyle::Psql,
"dots" => TableStyle::Dots,
_ => TableStyle::default(),
}
}
}

impl From<String> for TableStyle {
fn from(value: String) -> Self {
TableStyle::from(value.as_str())
}
}

#[derive(Copy, Clone)]
pub struct TableStyler {
non_interactive: bool,
pub style: TableStyle,
}

impl TableStyler {
pub fn new(args: &SharedSettings) -> Self {
let non_interactive = args.non_interactive;
if args.non_interactive {
return Self {
style: TableStyle::Borderless,
};
};

Self { non_interactive }
Self {
style: args.table_style.unwrap_or_default(),
}
}

pub fn apply(self, table: &mut Table) {
if self.non_interactive {
table.with(Style::empty());
table.with(Remove::row(Rows::first()));
} else {
table.with(Style::modern());
match self.style {
TableStyle::Modern => {
self.apply_modern(table);
}
TableStyle::Borderless => {
self.apply_borderless(table);
}
TableStyle::Markdown => {
self.apply_markdown(table);
}
TableStyle::Sharp => {
self.apply_sharp(table);
}
TableStyle::Ascii => {
self.apply_ascii(table);
}
TableStyle::Psql => {
self.apply_psql(table);
}
TableStyle::Dots => {
self.apply_dots(table);
}
}
}

fn apply_modern(self, table: &mut Table) -> &Table {
table.with(Style::modern())
}

fn apply_borderless(self, table: &mut Table) -> &Table {
table.with(Style::empty());
table.with(Remove::row(Rows::first()))
}

fn apply_markdown(self, table: &mut Table) -> &Table {
table.with(Style::markdown())
}

fn apply_sharp(self, table: &mut Table) -> &Table {
table.with(Style::sharp())
}

fn apply_psql(self, table: &mut Table) -> &Table {
table.with(Style::psql())
}

fn apply_dots(self, table: &mut Table) -> &Table {
table.with(Style::dots())
}

fn apply_ascii(self, table: &mut Table) -> &Table {
table.with(Style::ascii())
}
}

#[allow(dead_code)]
pub struct ResultHandler {
pub struct ResultHandler<'a> {
cli_args: &'a SharedSettings,
table_styler: TableStyler,
pub non_interactive: bool,
pub quiet: bool,
pub idempotently: bool,
pub exit_code: Option<ExitCode>,
table_styler: TableStyler,
}

impl ResultHandler {
pub fn new(common_args: &SharedSettings, command_args: &ArgMatches) -> Self {
impl<'a> ResultHandler<'a> {
pub fn new(common_args: &'a SharedSettings, command_args: &ArgMatches) -> Self {
let non_interactive = common_args.non_interactive;
let quiet = common_args.quiet;
let idempotently = match command_args.try_get_one::<bool>("idempotently") {
Ok(val) => val.cloned().unwrap_or(false),
Err(_) => false,
};
let table_formatter = TableStyler::new(common_args);

let table_styler = TableStyler::new(common_args);

Self {
cli_args: common_args,
table_styler,
quiet,
non_interactive,
idempotently,
exit_code: None,
table_styler: table_formatter,
}
}

Expand Down

0 comments on commit a6c56fa

Please sign in to comment.