Show estimated build end time during build

Ninja delivers estimated total build time and critical path time from
previous ninja log.

Bug: 292304818
Test: check if ETA shows
Change-Id: I014caaa3e8222a53c8822616b2ae31b88a3b0310
diff --git a/ui/terminal/format.go b/ui/terminal/format.go
index 4205bdc..241a1dd 100644
--- a/ui/terminal/format.go
+++ b/ui/terminal/format.go
@@ -51,9 +51,22 @@
 	return ""
 }
 
+func remainingTimeString(t time.Time) string {
+	now := time.Now()
+	if t.After(now) {
+		return t.Sub(now).Round(time.Duration(time.Second)).String()
+	}
+	return time.Duration(0).Round(time.Duration(time.Second)).String()
+}
 func (s formatter) progress(counts status.Counts) string {
 	if s.format == "" {
-		return fmt.Sprintf("[%3d%% %d/%d] ", 100*counts.FinishedActions/counts.TotalActions, counts.FinishedActions, counts.TotalActions)
+		output := fmt.Sprintf("[%3d%% %d/%d", 100*counts.FinishedActions/counts.TotalActions, counts.FinishedActions, counts.TotalActions)
+
+		if !counts.EstimatedTime.IsZero() {
+			output += fmt.Sprintf(" %s remaining", remainingTimeString(counts.EstimatedTime))
+		}
+		output += "] "
+		return output
 	}
 
 	buf := &strings.Builder{}
@@ -93,6 +106,13 @@
 			fmt.Fprintf(buf, "%3d%%", 100*counts.FinishedActions/counts.TotalActions)
 		case 'e':
 			fmt.Fprintf(buf, "%.3f", time.Since(s.start).Seconds())
+		case 'l':
+			if counts.EstimatedTime.IsZero() {
+				// No esitimated data
+				buf.WriteRune('?')
+			} else {
+				fmt.Fprintf(buf, "%s", remainingTimeString(counts.EstimatedTime))
+			}
 		default:
 			buf.WriteString("unknown placeholder '")
 			buf.WriteByte(c)