Skip to content

Commit 91edf28

Browse files
authored
uptime: Add -p, --pretty argument (#10143)
* uptime: Add -p, --pretty argument Rebase of PR #7910 All credits go to GitHub User: https://github.com/irbeam256 * Add localization for "up"
1 parent 4e0062d commit 91edf28

File tree

6 files changed

+123
-11
lines changed

6 files changed

+123
-11
lines changed

docs/src/extensions.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,9 @@ also provides a `-v`/`--verbose` flag.
184184

185185
## `uptime`
186186

187-
Similar to the proc-ps implementation and unlike GNU/Coreutils, `uptime` provides `-s`/`--since` to show since when the system is up.
187+
Similar to the proc-ps implementation and unlike GNU/Coreutils, `uptime` provides:
188+
* `-s`/`--since` to show since when the system is up
189+
* `-p`/`--pretty` to display uptime in a pretty-printed format
188190

189191
## `base32/base64/basenc`
190192

src/uu/uptime/locales/en-US.ftl

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ uptime-about-musl-warning = Warning: When built with musl libc, the `uptime` uti
99
# Help messages
1010
uptime-help-since = system up since
1111
uptime-help-path = file to search boot time from
12+
uptime-help-pretty = show uptime in pretty format
1213
1314
# Error messages
1415
uptime-error-io = couldn't get boot time: { $error }
@@ -18,6 +19,7 @@ uptime-error-couldnt-get-boot-time = couldn't get boot time
1819
1920
# Output messages
2021
uptime-output-unknown-uptime = up ???? days ??:??,
22+
uptime-output-up-text = up
2123
2224
uptime-user-count = { $count ->
2325
[one] 1 user
@@ -36,6 +38,18 @@ uptime-format = { $days ->
3638
[one] { $days } day, { $time }
3739
*[other] { $days } days { $time }
3840
}
41+
uptime-format-pretty-min = { $min ->
42+
[one] { $min } minute
43+
*[other] { $min } minutes
44+
}
45+
uptime-format-pretty-hour = { $hour ->
46+
[one] { $hour } hour
47+
*[other] { $hour } hours
48+
}
49+
uptime-format-pretty-day = { $day ->
50+
[one] { $day } day
51+
*[other] { $day } days
52+
}
3953
4054
# Load average formatting
4155
uptime-lib-format-loadavg = load average: { $avg1 }, { $avg5 }, { $avg15 }

src/uu/uptime/locales/fr-FR.ftl

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ uptime-about-musl-warning = Avertissement : Lorsque compilé avec musl libc, l'u
99
# Messages d'aide
1010
uptime-help-since = système actif depuis
1111
uptime-help-path = fichier pour rechercher l'heure de démarrage
12+
uptime-help-pretty = afficher le temps de disponibilité dans un format agréable
1213
1314
# Messages d'erreur
1415
uptime-error-io = impossible d'obtenir l'heure de démarrage : { $error }
@@ -18,6 +19,7 @@ uptime-error-couldnt-get-boot-time = impossible d'obtenir l'heure de démarrage
1819
1920
# Messages de sortie
2021
uptime-output-unknown-uptime = actif ???? jours ??:??,
22+
uptime-output-up-text = actif
2123
2224
uptime-user-count = { $count ->
2325
[one] 1 utilisateur
@@ -36,6 +38,18 @@ uptime-format = { $days ->
3638
[one] { $days } jour, { $time }
3739
*[other] { $days } jours { $time }
3840
}
41+
uptime-format-pretty-min = { $min ->
42+
[one] { $min } minute
43+
*[other] { $min } minutes
44+
}
45+
uptime-format-pretty-hour = { $hour ->
46+
[one] { $hour } heure
47+
*[other] { $hour } heures
48+
}
49+
uptime-format-pretty-day = { $day ->
50+
[one] { $day } jour
51+
*[other] { $day } jours
52+
}
3953
4054
# Formatage de la charge moyenne
4155
uptime-lib-format-loadavg = charge moyenne : { $avg1 }, { $avg5 }, { $avg15 }

src/uu/uptime/src/uptime.rs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ use uucore::utmpx::*;
2727
pub mod options {
2828
pub static SINCE: &str = "since";
2929
pub static PATH: &str = "path";
30+
pub static PRETTY: &str = "pretty";
3031
}
3132

3233
#[derive(Debug, Error)]
@@ -57,6 +58,8 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
5758

5859
if matches.get_flag(options::SINCE) {
5960
uptime_since()
61+
} else if matches.get_flag(options::PRETTY) {
62+
pretty_print_uptime()
6063
} else if let Some(path) = file_path {
6164
uptime_with_file(path)
6265
} else {
@@ -92,6 +95,13 @@ pub fn uu_app() -> Command {
9295
.value_parser(ValueParser::os_string())
9396
.value_hint(ValueHint::AnyPath),
9497
)
98+
.arg(
99+
Arg::new(options::PRETTY)
100+
.short('p')
101+
.long(options::PRETTY)
102+
.help(translate!("uptime-help-pretty"))
103+
.action(ArgAction::SetTrue),
104+
)
95105
}
96106

97107
#[cfg(unix)]
@@ -266,6 +276,17 @@ fn print_time() {
266276
}
267277

268278
fn print_uptime(boot_time: Option<time_t>) -> UResult<()> {
269-
print!("up {}, ", get_formatted_uptime(boot_time)?);
279+
let localized_text = translate!("uptime-output-up-text");
280+
let uptime_message = get_formatted_uptime(boot_time, OutputFormat::HumanReadable)?;
281+
282+
print!("{localized_text} {uptime_message}, ");
283+
Ok(())
284+
}
285+
286+
fn pretty_print_uptime() -> UResult<()> {
287+
let localized_text = translate!("uptime-output-up-text");
288+
let uptime_message = get_formatted_uptime(None, OutputFormat::PrettyPrint)?;
289+
290+
println!("{localized_text} {uptime_message}");
270291
Ok(())
271292
}

src/uucore/src/lib/features/uptime.rs

Lines changed: 61 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,56 @@ pub fn get_uptime(boot_time: Option<time_t>) -> UResult<i64> {
205205
Err(UptimeError::SystemUptime)?
206206
}
207207

208+
/// The format used to display a FormattedUptime.
209+
pub enum OutputFormat {
210+
/// Typical `uptime` output (e.g. 2 days, 3:04).
211+
HumanReadable,
212+
213+
/// Pretty printed output (e.g. 2 days, 3 hours, 04 minutes).
214+
PrettyPrint,
215+
}
216+
217+
struct FormattedUptime {
218+
up_days: i64,
219+
up_hours: i64,
220+
up_mins: i64,
221+
}
222+
223+
impl FormattedUptime {
224+
fn new(up_secs: i64) -> Self {
225+
let up_days = up_secs / 86400;
226+
let up_hours = (up_secs - (up_days * 86400)) / 3600;
227+
let up_mins = (up_secs - (up_days * 86400) - (up_hours * 3600)) / 60;
228+
229+
Self {
230+
up_days,
231+
up_hours,
232+
up_mins,
233+
}
234+
}
235+
236+
fn get_human_readable_uptime(&self) -> String {
237+
translate!(
238+
"uptime-format",
239+
"days" => self.up_days,
240+
"time" => format!("{:02}:{:02}", self.up_hours, self.up_mins))
241+
}
242+
243+
fn get_pretty_print_uptime(&self) -> String {
244+
let mut parts = Vec::new();
245+
if self.up_days > 0 {
246+
parts.push(translate!("uptime-format-pretty-day", "day" => self.up_days));
247+
}
248+
if self.up_hours > 0 {
249+
parts.push(translate!("uptime-format-pretty-hour", "hour" => self.up_hours));
250+
}
251+
if self.up_mins > 0 || parts.is_empty() {
252+
parts.push(translate!("uptime-format-pretty-min", "min" => self.up_mins));
253+
}
254+
parts.join(", ")
255+
}
256+
}
257+
208258
/// Get the system uptime
209259
///
210260
/// # Arguments
@@ -227,26 +277,28 @@ pub fn get_uptime(_boot_time: Option<time_t>) -> UResult<i64> {
227277
/// # Arguments
228278
///
229279
/// boot_time: Option<time_t> - Manually specify the boot time, or None to try to get it from the system.
280+
/// output_format: OutputFormat - Selects the format of the output string.
230281
///
231282
/// # Returns
232283
///
233284
/// Returns a UResult with the uptime in a human-readable format(e.g. "1 day, 3:45") if successful, otherwise an UptimeError.
234285
#[inline]
235-
pub fn get_formatted_uptime(boot_time: Option<time_t>) -> UResult<String> {
286+
pub fn get_formatted_uptime(
287+
boot_time: Option<time_t>,
288+
output_format: OutputFormat,
289+
) -> UResult<String> {
236290
let up_secs = get_uptime(boot_time)?;
237291

238292
if up_secs < 0 {
239293
Err(UptimeError::SystemUptime)?;
240294
}
241-
let up_days = up_secs / 86400;
242-
let up_hours = (up_secs - (up_days * 86400)) / 3600;
243-
let up_mins = (up_secs - (up_days * 86400) - (up_hours * 3600)) / 60;
244295

245-
Ok(translate!(
246-
"uptime-format",
247-
"days" => up_days,
248-
"time" => format!("{up_hours:02}:{up_mins:02}")
249-
))
296+
let formatted_uptime = FormattedUptime::new(up_secs);
297+
298+
match output_format {
299+
OutputFormat::HumanReadable => Ok(formatted_uptime.get_human_readable_uptime()),
300+
OutputFormat::PrettyPrint => Ok(formatted_uptime.get_pretty_print_uptime()),
301+
}
250302
}
251303

252304
/// Get the number of users currently logged in

tests/by-util/test_uptime.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,15 @@ fn test_uptime_since() {
267267
new_ucmd!().arg("--since").succeeds().stdout_matches(&re);
268268
}
269269

270+
#[test]
271+
fn test_uptime_pretty_print() {
272+
new_ucmd!()
273+
.arg("-p")
274+
.succeeds()
275+
.stdout_contains("up")
276+
.stdout_contains("minute");
277+
}
278+
270279
/// Test uptime reliability on macOS with sysctl kern.boottime fallback.
271280
/// This addresses intermittent failures from issue #3621 by ensuring
272281
/// the command consistently succeeds when utmpx data is unavailable.

0 commit comments

Comments
 (0)