tangled
alpha
login
or
join now
stavola.xyz
/
small-rust
0
fork
atom
Small Rust scripts
0
fork
atom
overview
issues
pulls
pipelines
Add colors, epoch, into_qr, and port_check
stavola.xyz
2 months ago
7e848f8f
1ceb54f3
+336
4 changed files
expand all
collapse all
unified
split
colors.rs
epoch.rs
into_qr.rs
port_check.rs
+141
colors.rs
···
1
1
+
#!/usr/bin/env -S cargo +nightly -Zscript
2
2
+
3
3
+
---
4
4
+
[package]
5
5
+
edition = "2024"
6
6
+
[dependencies]
7
7
+
argh = "0.1"
8
8
+
owo-colors = "4"
9
9
+
---
10
10
+
11
11
+
use argh::FromArgs;
12
12
+
use owo_colors::{AnsiColors, OwoColorize, Rgb, XtermColors};
13
13
+
14
14
+
#[derive(FromArgs)]
15
15
+
#[argh(description = "Display terminal color capabilities")]
16
16
+
struct App {
17
17
+
#[argh(switch, description = "show only basic 16 ANSI colors.")]
18
18
+
basic: bool,
19
19
+
20
20
+
#[argh(switch, description = "show 256 color palette.")]
21
21
+
palette: bool,
22
22
+
23
23
+
#[argh(switch, description = "show true color (24-bit) gradient.")]
24
24
+
truecolor: bool,
25
25
+
}
26
26
+
27
27
+
const BLOCK: &str = " ";
28
28
+
29
29
+
fn main() {
30
30
+
let app: App = argh::from_env();
31
31
+
let show_all = !app.basic && !app.palette && !app.truecolor;
32
32
+
33
33
+
if show_all || app.basic {
34
34
+
print_basic_colors();
35
35
+
}
36
36
+
if show_all || app.palette {
37
37
+
print_256_palette();
38
38
+
}
39
39
+
if show_all || app.truecolor {
40
40
+
print_truecolor();
41
41
+
}
42
42
+
}
43
43
+
44
44
+
fn print_basic_colors() {
45
45
+
use AnsiColors::*;
46
46
+
const COLORS: [AnsiColors; 8] = [Black, Red, Green, Yellow, Blue, Magenta, Cyan, White];
47
47
+
48
48
+
println!("ANSI 16 Colors:\n");
49
49
+
50
50
+
print!(" Normal: ");
51
51
+
for color in COLORS {
52
52
+
print!("{}", BLOCK.on_color(color));
53
53
+
}
54
54
+
println!();
55
55
+
56
56
+
print!(" Bright: ");
57
57
+
for color in COLORS {
58
58
+
print!("{}", BLOCK.on_color(color).bold());
59
59
+
}
60
60
+
println!("\n");
61
61
+
}
62
62
+
63
63
+
fn print_256_palette() {
64
64
+
println!("256 Color Palette:\n");
65
65
+
66
66
+
// Standard 0-15
67
67
+
print!(" ");
68
68
+
for i in 0..16u8 {
69
69
+
print!("{}", BLOCK.on_color(XtermColors::from(i)));
70
70
+
}
71
71
+
println!("\n");
72
72
+
73
73
+
// Color cube 16-231
74
74
+
for row in 0..6u8 {
75
75
+
print!(" ");
76
76
+
for green in 0..6u8 {
77
77
+
for red in 0..6u8 {
78
78
+
let color = 16 + row * 36 + green * 6 + red;
79
79
+
print!("{}", BLOCK.on_color(XtermColors::from(color)));
80
80
+
}
81
81
+
print!(" ");
82
82
+
}
83
83
+
println!();
84
84
+
}
85
85
+
println!();
86
86
+
87
87
+
// Grayscale 232-255
88
88
+
print!(" ");
89
89
+
for i in 232..=255u8 {
90
90
+
print!("{}", BLOCK.on_color(XtermColors::from(i)));
91
91
+
}
92
92
+
println!("\n");
93
93
+
}
94
94
+
95
95
+
fn print_truecolor() {
96
96
+
println!("True Color (24-bit) Test:\n");
97
97
+
98
98
+
// Red gradient
99
99
+
print!(" ");
100
100
+
for i in 0..64u8 {
101
101
+
print!("{}", " ".on_color(Rgb(i * 4, 0, 0)));
102
102
+
}
103
103
+
println!();
104
104
+
105
105
+
// Green gradient
106
106
+
print!(" ");
107
107
+
for i in 0..64u8 {
108
108
+
print!("{}", " ".on_color(Rgb(0, i * 4, 0)));
109
109
+
}
110
110
+
println!();
111
111
+
112
112
+
// Blue gradient
113
113
+
print!(" ");
114
114
+
for i in 0..64u8 {
115
115
+
print!("{}", " ".on_color(Rgb(0, 0, i * 4)));
116
116
+
}
117
117
+
println!();
118
118
+
119
119
+
// Rainbow
120
120
+
print!(" ");
121
121
+
for i in 0..64 {
122
122
+
let (r, g, b) = hsv_to_rgb(i as f32 / 64.0 * 360.0);
123
123
+
print!("{}", " ".on_color(Rgb(r, g, b)));
124
124
+
}
125
125
+
println!("\n");
126
126
+
127
127
+
println!(" If gradients appear smooth, your terminal supports true color.\n");
128
128
+
}
129
129
+
130
130
+
fn hsv_to_rgb(h: f32) -> (u8, u8, u8) {
131
131
+
let x = 1.0 - ((h / 60.0) % 2.0 - 1.0).abs();
132
132
+
let (r, g, b) = match h as u32 {
133
133
+
0..=59 => (1.0, x, 0.0),
134
134
+
60..=119 => (x, 1.0, 0.0),
135
135
+
120..=179 => (0.0, 1.0, x),
136
136
+
180..=239 => (0.0, x, 1.0),
137
137
+
240..=299 => (x, 0.0, 1.0),
138
138
+
_ => (1.0, 0.0, x),
139
139
+
};
140
140
+
((r * 255.0) as u8, (g * 255.0) as u8, (b * 255.0) as u8)
141
141
+
}
+77
epoch.rs
···
1
1
+
#!/usr/bin/env -S cargo +nightly -Zscript
2
2
+
3
3
+
---
4
4
+
[package]
5
5
+
edition = "2024"
6
6
+
[dependencies]
7
7
+
argh = "0.1"
8
8
+
chrono = "0.4"
9
9
+
---
10
10
+
11
11
+
use argh::FromArgs;
12
12
+
use chrono::{DateTime, Local, NaiveDateTime, TimeZone, Utc};
13
13
+
14
14
+
#[derive(FromArgs)]
15
15
+
#[argh(description = "Convert between Unix timestamps and human-readable dates.")]
16
16
+
struct App {
17
17
+
#[argh(switch, description = "use UTC instead of local time.")]
18
18
+
utc: bool,
19
19
+
20
20
+
#[argh(switch, description = "treat timestamp as milliseconds.")]
21
21
+
millis: bool,
22
22
+
23
23
+
#[argh(positional, description = "timestamp, date (YYYY-MM-DD HH:MM:SS), or 'now'.")]
24
24
+
input: Option<String>,
25
25
+
}
26
26
+
27
27
+
fn main() {
28
28
+
let app: App = argh::from_env();
29
29
+
let input = app.input.as_deref().unwrap_or("now");
30
30
+
31
31
+
match input {
32
32
+
"now" => {
33
33
+
let now = Utc::now();
34
34
+
if app.millis {
35
35
+
println!("{}", now.timestamp_millis());
36
36
+
} else {
37
37
+
println!("{}", now.timestamp());
38
38
+
}
39
39
+
}
40
40
+
s if s.chars().all(|c| c.is_ascii_digit()) => {
41
41
+
let ts: i64 = s.parse().expect("invalid timestamp");
42
42
+
let dt = if app.millis {
43
43
+
Utc.timestamp_millis_opt(ts).single()
44
44
+
} else {
45
45
+
Utc.timestamp_opt(ts, 0).single()
46
46
+
}
47
47
+
.expect("invalid timestamp");
48
48
+
49
49
+
if app.utc {
50
50
+
println!("{}", dt.format("%Y-%m-%d %H:%M:%S UTC"));
51
51
+
} else {
52
52
+
let local: DateTime<Local> = dt.into();
53
53
+
println!("{}", local.format("%Y-%m-%d %H:%M:%S"));
54
54
+
}
55
55
+
}
56
56
+
s => {
57
57
+
let naive = NaiveDateTime::parse_from_str(s, "%Y-%m-%d %H:%M:%S")
58
58
+
.expect("expected format: YYYY-MM-DD HH:MM:SS");
59
59
+
60
60
+
let dt: DateTime<Utc> = if app.utc {
61
61
+
Utc.from_utc_datetime(&naive)
62
62
+
} else {
63
63
+
Local
64
64
+
.from_local_datetime(&naive)
65
65
+
.single()
66
66
+
.expect("invalid local time")
67
67
+
.into()
68
68
+
};
69
69
+
70
70
+
if app.millis {
71
71
+
println!("{}", dt.timestamp_millis());
72
72
+
} else {
73
73
+
println!("{}", dt.timestamp());
74
74
+
}
75
75
+
}
76
76
+
}
77
77
+
}
+70
into_qr.rs
···
1
1
+
#!/usr/bin/env -S cargo +nightly -Zscript
2
2
+
3
3
+
---
4
4
+
[package]
5
5
+
edition = "2024"
6
6
+
[dependencies]
7
7
+
argh = "0.1"
8
8
+
qrcode = "0.14.1"
9
9
+
---
10
10
+
11
11
+
use std::fs;
12
12
+
use std::path::PathBuf;
13
13
+
14
14
+
use argh::FromArgs;
15
15
+
16
16
+
use qrcode::QrCode;
17
17
+
use qrcode::render::unicode::Dense1x2;
18
18
+
19
19
+
#[derive(FromArgs)]
20
20
+
#[argh(description = "Create a QR code from anything.")]
21
21
+
struct App {
22
22
+
#[argh(option, description = "module width in characters.", default = "1")]
23
23
+
scale: u32,
24
24
+
25
25
+
#[argh(switch, description = "disable quiet zone border.")]
26
26
+
no_quiet_zone: bool,
27
27
+
28
28
+
#[argh(subcommand)]
29
29
+
command: Command,
30
30
+
}
31
31
+
32
32
+
#[derive(FromArgs)]
33
33
+
#[argh(subcommand)]
34
34
+
enum Command {
35
35
+
File(FileCmd),
36
36
+
Raw(RawCmd),
37
37
+
}
38
38
+
39
39
+
#[derive(FromArgs)]
40
40
+
#[argh(subcommand, name = "file")]
41
41
+
#[argh(description = "Read from a file")]
42
42
+
struct FileCmd {
43
43
+
#[argh(positional)]
44
44
+
path: PathBuf,
45
45
+
}
46
46
+
47
47
+
#[derive(FromArgs)]
48
48
+
#[argh(subcommand, name = "raw")]
49
49
+
#[argh(description = "Use raw input")]
50
50
+
struct RawCmd {
51
51
+
#[argh(positional)]
52
52
+
input: String,
53
53
+
}
54
54
+
55
55
+
fn main() {
56
56
+
let app: App = argh::from_env();
57
57
+
58
58
+
let data = match app.command {
59
59
+
Command::File(FileCmd { path }) => fs::read_to_string(path).expect("could not read file"),
60
60
+
Command::Raw(RawCmd { input }) => input,
61
61
+
};
62
62
+
63
63
+
let code = QrCode::new(data.into_bytes()).expect("could not create qr code");
64
64
+
let rendered = code
65
65
+
.render::<Dense1x2>()
66
66
+
.module_dimensions(app.scale, app.scale)
67
67
+
.quiet_zone(!app.no_quiet_zone)
68
68
+
.build();
69
69
+
println!("{}", rendered);
70
70
+
}
+48
port_check.rs
···
1
1
+
#!/usr/bin/env -S cargo +nightly -Zscript
2
2
+
3
3
+
---
4
4
+
[package]
5
5
+
edition = "2024"
6
6
+
[dependencies]
7
7
+
argh = "0.1"
8
8
+
---
9
9
+
10
10
+
use std::net::{TcpStream, ToSocketAddrs};
11
11
+
use std::process;
12
12
+
use std::time::Duration;
13
13
+
14
14
+
use argh::FromArgs;
15
15
+
16
16
+
#[derive(FromArgs)]
17
17
+
#[argh(description = "Check if a TCP port is reachable.")]
18
18
+
struct App {
19
19
+
#[argh(option, description = "timeout in seconds.", default = "5")]
20
20
+
timeout: u64,
21
21
+
22
22
+
#[argh(positional, description = "host to connect to.")]
23
23
+
host: String,
24
24
+
25
25
+
#[argh(positional, description = "port to connect to.")]
26
26
+
port: u16,
27
27
+
}
28
28
+
29
29
+
fn main() {
30
30
+
let app: App = argh::from_env();
31
31
+
let address = format!("{}:{}", app.host, app.port);
32
32
+
let timeout = Duration::from_secs(app.timeout);
33
33
+
34
34
+
let addrs: Vec<_> = address
35
35
+
.to_socket_addrs()
36
36
+
.expect("failed to resolve address")
37
37
+
.collect();
38
38
+
39
39
+
for addr in &addrs {
40
40
+
if TcpStream::connect_timeout(addr, timeout).is_ok() {
41
41
+
println!("reachable");
42
42
+
process::exit(0);
43
43
+
}
44
44
+
}
45
45
+
46
46
+
println!("unreachable");
47
47
+
process::exit(1);
48
48
+
}