@@ -25,6 +25,7 @@ redraw_event: std.Thread.ResetEvent,
25
25
/// Accessed atomically.
26
26
done : bool ,
27
27
need_clear : bool ,
28
+ status : Status ,
28
29
29
30
refresh_rate_ns : u64 ,
30
31
initial_delay_ns : u64 ,
@@ -47,6 +48,22 @@ node_freelist: Freelist,
47
48
/// value may at times temporarily exceed the node count.
48
49
node_end_index : u32 ,
49
50
51
+ pub const Status = enum {
52
+ /// Indicates the application is progressing towards completion of a task.
53
+ /// Unless the application is interactive, this is the only status the
54
+ /// program will ever have!
55
+ working ,
56
+ /// The application has completed an operation, and is now waiting for user
57
+ /// input rather than calling exit(0).
58
+ success ,
59
+ /// The application encountered an error, and is now waiting for user input
60
+ /// rather than calling exit(1).
61
+ failure ,
62
+ /// The application encountered at least one error, but is still working on
63
+ /// more tasks.
64
+ failure_working ,
65
+ };
66
+
50
67
const Freelist = packed struct (u32 ) {
51
68
head : Node.OptionalIndex ,
52
69
/// Whenever `node_freelist` is added to, this generation is incremented
@@ -383,6 +400,7 @@ var global_progress: Progress = .{
383
400
.draw_buffer = undefined ,
384
401
.done = false ,
385
402
.need_clear = false ,
403
+ .status = .working ,
386
404
387
405
.node_parents = & node_parents_buffer ,
388
406
.node_storage = & node_storage_buffer ,
@@ -498,6 +516,11 @@ pub fn start(options: Options) Node {
498
516
return root_node ;
499
517
}
500
518
519
+ pub fn setStatus (new_status : Status ) void {
520
+ if (noop_impl ) return ;
521
+ @atomicStore (Status , & global_progress .status , new_status , .monotonic );
522
+ }
523
+
501
524
/// Returns whether a resize is needed to learn the terminal size.
502
525
fn wait (timeout_ns : u64 ) bool {
503
526
const resize_flag = if (global_progress .redraw_event .timedWait (timeout_ns )) | _ |
@@ -678,6 +701,14 @@ const save = "\x1b7";
678
701
const restore = "\x1b 8" ;
679
702
const finish_sync = "\x1b [?2026l" ;
680
703
704
+ const progress_remove = "\x1b ]9;4;0\x07 " ;
705
+ const @"progress_normal {d}" = "\x1b ]9;4;1;{d}\x07 " ;
706
+ const @"progress_error {d}" = "\x1b ]9;4;2;{d}\x07 " ;
707
+ const progress_pulsing = "\x1b ]9;4;3\x07 " ;
708
+ const progress_pulsing_error = "\x1b ]9;4;2\x07 " ;
709
+ const progress_normal_100 = "\x1b ]9;4;1;100\x07 " ;
710
+ const progress_error_100 = "\x1b ]9;4;2;100\x07 " ;
711
+
681
712
const TreeSymbol = enum {
682
713
/// ├─
683
714
tee ,
@@ -760,7 +791,7 @@ fn clearWrittenWithEscapeCodes() anyerror!void {
760
791
if (noop_impl or ! global_progress .need_clear ) return ;
761
792
762
793
global_progress .need_clear = false ;
763
- try write (clear );
794
+ try write (clear ++ progress_remove );
764
795
}
765
796
766
797
/// U+25BA or ►
@@ -1203,6 +1234,43 @@ fn computeRedraw(serialized_buffer: *Serialized.Buffer) struct { []u8, usize } {
1203
1234
i , const nl_n = computeNode (buf , i , 0 , serialized , children , root_node_index );
1204
1235
1205
1236
if (global_progress .terminal_mode == .ansi_escape_codes ) {
1237
+ {
1238
+ // Set progress state https://conemu.github.io/en/AnsiEscapeCodes.html#ConEmu_specific_OSC
1239
+ const root_storage = & serialized .storage [0 ];
1240
+ const storage = if (root_storage .name [0 ] != 0 or children [0 ].child == .none ) root_storage else & serialized .storage [@intFromEnum (children [0 ].child )];
1241
+ const estimated_total = storage .estimated_total_count ;
1242
+ const completed_items = storage .completed_count ;
1243
+ const status = @atomicLoad (Status , & global_progress .status , .monotonic );
1244
+ switch (status ) {
1245
+ .working = > {
1246
+ if (estimated_total == 0 ) {
1247
+ buf [i .. ][0.. progress_pulsing .len ].* = progress_pulsing .* ;
1248
+ i += progress_pulsing .len ;
1249
+ } else {
1250
+ const percent = completed_items * 100 / estimated_total ;
1251
+ i += (std .fmt .bufPrint (buf [i .. ], @"progress_normal {d}" , .{percent }) catch &.{}).len ;
1252
+ }
1253
+ },
1254
+ .success = > {
1255
+ buf [i .. ][0.. progress_remove .len ].* = progress_remove .* ;
1256
+ i += progress_remove .len ;
1257
+ },
1258
+ .failure = > {
1259
+ buf [i .. ][0.. progress_error_100 .len ].* = progress_error_100 .* ;
1260
+ i += progress_error_100 .len ;
1261
+ },
1262
+ .failure_working = > {
1263
+ if (estimated_total == 0 ) {
1264
+ buf [i .. ][0.. progress_pulsing_error .len ].* = progress_pulsing_error .* ;
1265
+ i += progress_pulsing_error .len ;
1266
+ } else {
1267
+ const percent = completed_items * 100 / estimated_total ;
1268
+ i += (std .fmt .bufPrint (buf [i .. ], @"progress_error {d}" , .{percent }) catch &.{}).len ;
1269
+ }
1270
+ },
1271
+ }
1272
+ }
1273
+
1206
1274
if (nl_n > 0 ) {
1207
1275
buf [i ] = '\r ' ;
1208
1276
i += 1 ;
0 commit comments