Skip to content

Commit 4acf693

Browse files
committed
build: make ui deps optional
1 parent 4c03594 commit 4acf693

File tree

7 files changed

+168
-14
lines changed

7 files changed

+168
-14
lines changed

implementations/rust/ockam/ockam_api/Cargo.toml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ storage = ["ockam/storage"]
4444
aws-lc = ["ockam_vault/aws-lc", "ockam_transport_tcp/aws-lc"]
4545
rust-crypto = ["ockam_vault/rust-crypto", "ockam_transport_tcp/ring"]
4646
privileged_portals = ["ockam_transport_tcp/privileged_portals"]
47+
encode_format = ["clap"]
48+
ui = ["encode_format", "r3bl_rs_utils_core", "r3bl_tui", "r3bl_tuify"]
4749

4850
[[bin]]
4951
name = "node_control_api_schema"
@@ -57,7 +59,7 @@ base64-url = "3.0.0"
5759
bytes = { version = "=1.9.0", default-features = false, features = ["serde"] }
5860
cfg-if = "1.0.0"
5961
chrono = { version = "0.4" }
60-
clap = { version = "4.5", default-features = false, features = ["derive"] }
62+
clap = { version = "4.5", default-features = false, features = ["derive", "std"], optional = true }
6163
colorful = "0.3"
6264
colors-transform = "0.2"
6365
dialoguer = "0.11"
@@ -92,9 +94,9 @@ opentelemetry-proto = { version = "0.27", features = ["full"] }
9294
opentelemetry-semantic-conventions = { version = "0.28", features = ["semconv_experimental"] }
9395
opentelemetry_sdk = { version = "0.27", features = ["logs", "metrics", "trace", "rt-tokio", "rt-tokio-current-thread", "testing"], default-features = false }
9496
petname = { version = "2.0.2", default-features = false, features = ["default-rng", "default-words"] }
95-
r3bl_rs_utils_core = "0.9"
96-
r3bl_tui = "0.5"
97-
r3bl_tuify = "0.1"
97+
r3bl_rs_utils_core = { version = "0.9", optional = true }
98+
r3bl_tui = { version = "0.5", optional = true }
99+
r3bl_tuify = { version = "0.1", optional = true }
98100
rand = "0.8"
99101
regex = "1.10.6"
100102
reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls-native-roots"] }

implementations/rust/ockam/ockam_api/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
#[macro_use]
2020
extern crate tracing;
2121

22+
23+
2224
pub mod address;
2325
pub mod authenticator;
2426
pub mod cli_state;
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,91 @@
1+
#[cfg(feature = "ui")]
12
pub mod colors;
3+
4+
#[cfg(not(feature = "ui"))]
5+
pub mod colors {
6+
use colorful::{core::color_string::CString, Colorful, RGB};
7+
use std::fmt::Display;
8+
9+
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
10+
pub enum OckamColor {
11+
OckamBlue,
12+
HeaderGradient,
13+
PrimaryResource,
14+
Success,
15+
Failure,
16+
FmtOKBackground,
17+
FmtINFOBackground,
18+
FmtWARNBackground,
19+
FmtERRORBackground,
20+
FmtLISTBackground,
21+
}
22+
23+
impl OckamColor {
24+
/// Hex string value for this color (kept consistent w/ full UI feature version).
25+
pub fn value(&self) -> &'static str {
26+
match self {
27+
OckamColor::OckamBlue => "#52c7ea",
28+
OckamColor::HeaderGradient => "#4FDAB8",
29+
OckamColor::PrimaryResource => "#4FDAB8",
30+
OckamColor::Success => "#A8C97D",
31+
OckamColor::Failure => "#ff0000",
32+
OckamColor::FmtOKBackground => "#A8C97D",
33+
OckamColor::FmtINFOBackground => "#0DCAF0",
34+
OckamColor::FmtWARNBackground => "#ff9a00",
35+
OckamColor::FmtERRORBackground => "#FF0000",
36+
OckamColor::FmtLISTBackground => "#0DCAF0",
37+
}
38+
}
39+
pub fn color(&self) -> RGB {
40+
// Provide simple, hard-coded fallback colors that don't require r3bl_* crates.
41+
match self {
42+
OckamColor::OckamBlue => RGB::new(0x52, 0xC7, 0xEA),
43+
OckamColor::HeaderGradient => RGB::new(0x4F, 0xDA, 0xB8),
44+
OckamColor::PrimaryResource => RGB::new(0x4F, 0xDA, 0xB8),
45+
OckamColor::Success => RGB::new(0xA8, 0xC9, 0x7D),
46+
OckamColor::Failure => RGB::new(0xFF, 0x00, 0x00),
47+
OckamColor::FmtOKBackground => RGB::new(0xA8, 0xC9, 0x7D),
48+
OckamColor::FmtINFOBackground => RGB::new(0x0D, 0xCA, 0xF0),
49+
OckamColor::FmtWARNBackground => RGB::new(0xFF, 0x9A, 0x00),
50+
OckamColor::FmtERRORBackground => RGB::new(0xFF, 0x00, 0x00),
51+
OckamColor::FmtLISTBackground => RGB::new(0x0D, 0xCA, 0xF0),
52+
}
53+
}
54+
}
55+
56+
// Re-exported macro to keep parity w/ full UI feature.
57+
#[macro_export]
58+
macro_rules! color {
59+
($text:expr, $color:expr) => {
60+
$text.to_string().color($color.color())
61+
};
62+
}
63+
64+
pub fn color_primary(input: impl Display) -> CString {
65+
input.to_string().color(OckamColor::PrimaryResource.color())
66+
}
67+
pub fn color_primary_alt(input: impl Display) -> String {
68+
// Fallback: no gradient, just plain text
69+
input.to_string()
70+
}
71+
pub fn color_ok(input: impl Display) -> CString {
72+
input.to_string().color(OckamColor::FmtOKBackground.color())
73+
}
74+
pub fn color_warn(input: impl Display) -> CString {
75+
input.to_string().color(OckamColor::FmtWARNBackground.color())
76+
}
77+
pub fn color_error(input: impl Display) -> CString {
78+
input.to_string().color(OckamColor::FmtERRORBackground.color())
79+
}
80+
pub fn color_email(input: impl Display) -> CString {
81+
input.to_string().color(OckamColor::PrimaryResource.color())
82+
}
83+
pub fn color_uri(input: impl Display) -> String {
84+
// Fallback: no gradient
85+
input.to_string()
86+
}
87+
}
88+
289
pub mod command;
390
pub mod output;
491
pub mod terminal;

implementations/rust/ockam/ockam_api/src/ui/output/mod.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,28 @@
11
mod branding;
2+
#[cfg(feature = "encode_format")]
23
mod encode_format;
34
mod ockam_abac;
45
mod output_format;
56
mod utils;
67

78
pub use branding::OutputBranding;
9+
#[cfg(feature = "encode_format")]
810
pub use encode_format::EncodeFormat;
11+
12+
#[cfg(not(feature = "encode_format"))]
13+
#[derive(Debug, Clone, PartialEq, Eq)]
14+
pub enum EncodeFormat {
15+
Plain,
16+
Hex,
17+
}
18+
19+
#[cfg(not(feature = "encode_format"))]
20+
impl EncodeFormat {
21+
pub fn encode_value<T: Output>(&self, value: &T) -> crate::Result<String> {
22+
// Fallback: without the encode_format feature, both variants just return the plain item.
23+
value.item()
24+
}
25+
}
926
pub use output_format::OutputFormat;
1027
pub use utils::*;
1128

implementations/rust/ockam/ockam_api/src/ui/terminal/fmt.rs

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,24 @@ pub const MIETTE_PADDING: &str = " ";
88
pub const INDENTATION: &str = " ";
99

1010
pub fn get_separator_width() -> usize {
11-
// If we can't get the terminal width, use the default width
12-
let mut terminal_width = r3bl_tuify::get_terminal_width();
13-
if terminal_width == 0 {
14-
terminal_width = r3bl_tuify::DEFAULT_WIDTH;
11+
// When the full UI feature is enabled, use dynamic terminal sizing from r3bl_tuify.
12+
#[cfg(feature = "ui")]
13+
{
14+
let mut terminal_width = r3bl_tuify::get_terminal_width();
15+
if terminal_width == 0 {
16+
terminal_width = r3bl_tuify::DEFAULT_WIDTH;
17+
}
18+
let terminal_width = std::cmp::max(terminal_width, 2 * PADDING.len());
19+
return std::cmp::min(terminal_width - PADDING.len(), r3bl_tuify::DEFAULT_WIDTH);
20+
}
21+
22+
// Fallback when `ui` feature (and thus r3bl_tuify) is disabled: use a fixed width.
23+
#[cfg(not(feature = "ui"))]
24+
{
25+
// Pick a sane default (80 cols) minus left padding, but never under 10.
26+
let width = 80usize.saturating_sub(PADDING.len());
27+
std::cmp::max(width, 10)
1528
}
16-
// Make sure the separator width is at least twice the length of the padding.
17-
// We want to show a small separator even if the terminal is too narrow.
18-
let terminal_width = std::cmp::max(terminal_width, 2 * PADDING.len());
19-
// Limit the separator width to the default width
20-
std::cmp::min(terminal_width - PADDING.len(), r3bl_tuify::DEFAULT_WIDTH)
2129
}
2230

2331
#[test]

implementations/rust/ockam/ockam_api/src/ui/terminal/mod.rs

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,24 @@ use indicatif::{ProgressBar, ProgressDrawTarget, ProgressStyle};
1515
use jaq_interpret::{Ctx, FilterT, ParseCtx, RcIter, Val};
1616
use miette::{miette, IntoDiagnostic};
1717
use ockam_core::env::get_env_with_default;
18+
#[cfg(feature = "ui")]
19+
#[allow(unused_imports)]
1820
use r3bl_rs_utils_core::{ch, ChUnit};
21+
22+
23+
#[cfg(feature = "ui")]
1924
use r3bl_tuify::{get_size, select_from_list, SelectionMode, StyleSheet};
25+
#[cfg(not(feature = "ui"))]
26+
#[allow(dead_code)]
27+
pub(crate) fn get_size() -> (usize, usize) {
28+
(80, 24)
29+
}
30+
#[cfg(not(feature = "ui"))]
31+
#[allow(dead_code)]
32+
pub(crate) fn select_from_list<T: Clone>(_: &str, items: &[T]) -> Option<T> {
33+
items.first().cloned()
34+
}
35+
2036
use serde::Serialize;
2137
use std::fmt::Write as _;
2238
use std::fmt::{Debug, Display};
@@ -139,7 +155,13 @@ impl<W: TerminalWriter + Debug> Terminal<W> {
139155
let no_input = Self::should_disable_user_input(no_input);
140156
let stdout = W::stdout(no_color, OutputBranding::default());
141157
let stderr = W::stderr(no_color, OutputBranding::default());
142-
let max_width_col_count = get_size().map(|it| it.col_count).unwrap_or(ch!(80)).into();
158+
#[cfg(feature = "ui")]
159+
let max_width_col_count: usize = get_size().map(|it| it.col_count.into()).unwrap_or(80);
160+
#[cfg(not(feature = "ui"))]
161+
let max_width_col_count = {
162+
let (cols, _rows) = get_size();
163+
cols
164+
};
143165
Self {
144166
stdout,
145167
stderr,
@@ -186,6 +208,7 @@ impl<W: TerminalWriter + Debug> Terminal<W> {
186208
}
187209
}
188210

211+
#[cfg(feature = "ui")]
189212
pub fn confirm_interactively(&self, header: String) -> bool {
190213
let user_input = select_from_list(
191214
header,
@@ -202,8 +225,15 @@ impl<W: TerminalWriter + Debug> Terminal<W> {
202225
}
203226
}
204227

228+
#[cfg(not(feature = "ui"))]
229+
pub fn confirm_interactively(&self, header: String) -> bool {
230+
let user_input = select_from_list(&header, &["YES".to_string(), "NO".to_string()]);
231+
matches!(user_input, Some(ref it) if it == "YES")
232+
}
233+
205234
/// Returns the selected items by the user, or an empty `Vec` if the user did not select any item
206235
/// or if the user is not able to select an item (e.g. not a TTY, `--no-input` flag, etc.).
236+
#[cfg(feature = "ui")]
207237
pub fn select_multiple(&self, header: String, items: Vec<String>) -> Vec<String> {
208238
if !self.can_ask_for_user_input() {
209239
return Vec::new();
@@ -221,6 +251,12 @@ impl<W: TerminalWriter + Debug> Terminal<W> {
221251
user_selected_list.unwrap_or_default()
222252
}
223253

254+
#[cfg(not(feature = "ui"))]
255+
pub fn select_multiple(&self, _header: String, _items: Vec<String>) -> Vec<String> {
256+
// Fallback: interactive multi-selection unavailable without `ui` feature.
257+
Vec::new()
258+
}
259+
224260
pub fn can_ask_for_user_input(&self) -> bool {
225261
!self.no_input && self.stderr.is_tty() && !self.quiet
226262
}

implementations/rust/ockam/ockam_command/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ ockam = { path = "../ockam", version = "^0.157.0", features = [
7777
ockam_abac = { path = "../ockam_abac", version = "0.84.0", features = ["std"] }
7878
ockam_api = { path = "../ockam_api", version = "0.100.0", default-features = false, features = [
7979
"std",
80+
"ui",
8081
] }
8182
ockam_core = { path = "../ockam_core", version = "^0.126.0" }
8283
ockam_multiaddr = { path = "../ockam_multiaddr", version = "0.71.0", features = [
@@ -130,6 +131,7 @@ zip-extract = "0.2.3"
130131
assert_cmd = "2"
131132
mockito = "1.5.0"
132133
ockam_api = { path = "../ockam_api", version = "0.100.0", default-features = false, features = [
134+
"ui",
133135
"test-utils",
134136
] }
135137
ockam_macros = { path = "../ockam_macros", version = "^0.39.0" }

0 commit comments

Comments
 (0)