| // Copyright 2014 The Bazel Authors. All rights reserved. | 
 | // | 
 | // Licensed under the Apache License, Version 2.0 (the "License"); | 
 | // you may not use this file except in compliance with the License. | 
 | // You may obtain a copy of the License at | 
 | // | 
 | //    http://www.apache.org/licenses/LICENSE-2.0 | 
 | // | 
 | // Unless required by applicable law or agreed to in writing, software | 
 | // distributed under the License is distributed on an "AS IS" BASIS, | 
 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 | // See the License for the specific language governing permissions and | 
 | // limitations under the License. | 
 | package com.google.devtools.build.lib.runtime; | 
 |  | 
 | import com.google.devtools.build.lib.runtime.ExperimentalStateTracker.ProgressMode; | 
 | import com.google.devtools.common.options.EnumConverter; | 
 | import com.google.devtools.common.options.Option; | 
 | import com.google.devtools.common.options.OptionDocumentationCategory; | 
 | import com.google.devtools.common.options.OptionEffectTag; | 
 | import com.google.devtools.common.options.OptionMetadataTag; | 
 | import com.google.devtools.common.options.OptionsBase; | 
 |  | 
 | /** | 
 |  * BlazeCommandEventHandler: an event handler established for the duration of a single Blaze | 
 |  * command. | 
 |  */ | 
 | public class BlazeCommandEventHandler { | 
 |  | 
 |   public enum UseColor { YES, NO, AUTO } | 
 |   public enum UseCurses { YES, NO, AUTO } | 
 |  | 
 |   public static class UseColorConverter extends EnumConverter<UseColor> { | 
 |     public UseColorConverter() { | 
 |       super(UseColor.class, "--color setting"); | 
 |     } | 
 |   } | 
 |  | 
 |   public static class UseCursesConverter extends EnumConverter<UseCurses> { | 
 |     public UseCursesConverter() { | 
 |       super(UseCurses.class, "--curses setting"); | 
 |     } | 
 |   } | 
 |  | 
 |   /** Progress mode converter. */ | 
 |   public static class ProgressModeConverter extends EnumConverter<ProgressMode> { | 
 |     public ProgressModeConverter() { | 
 |       super(ProgressMode.class, "--experimental_ui_mode setting"); | 
 |     } | 
 |   } | 
 |  | 
 |   public static class Options extends OptionsBase { | 
 |  | 
 |     @Option( | 
 |       name = "show_progress", | 
 |       defaultValue = "true", | 
 |       documentationCategory = OptionDocumentationCategory.UNCATEGORIZED, | 
 |       effectTags = {OptionEffectTag.UNKNOWN}, | 
 |       help = "Display progress messages during a build." | 
 |     ) | 
 |     public boolean showProgress; | 
 |  | 
 |     @Option( | 
 |       name = "show_task_finish", | 
 |       defaultValue = "false", | 
 |       documentationCategory = OptionDocumentationCategory.UNCATEGORIZED, | 
 |       effectTags = {OptionEffectTag.UNKNOWN}, | 
 |       help = "Display progress messages when tasks complete, not just when they start." | 
 |     ) | 
 |     public boolean showTaskFinish; | 
 |  | 
 |     @Option( | 
 |       name = "show_progress_rate_limit", | 
 |       defaultValue = "0.2", // A nice middle ground; snappy but not too spammy in logs. | 
 |       documentationCategory = OptionDocumentationCategory.UNCATEGORIZED, | 
 |       effectTags = {OptionEffectTag.UNKNOWN}, | 
 |       help = "Minimum number of seconds between progress messages in the output." | 
 |     ) | 
 |     public double showProgressRateLimit; | 
 |  | 
 |     @Option( | 
 |         name = "color", | 
 |         defaultValue = "auto", | 
 |         converter = UseColorConverter.class, | 
 |         documentationCategory = OptionDocumentationCategory.UNCATEGORIZED, | 
 |         effectTags = {OptionEffectTag.UNKNOWN}, | 
 |         help = "Use terminal controls to colorize output.") | 
 |     public UseColor useColorEnum; | 
 |  | 
 |     @Option( | 
 |         name = "curses", | 
 |         defaultValue = "auto", | 
 |         converter = UseCursesConverter.class, | 
 |         documentationCategory = OptionDocumentationCategory.UNCATEGORIZED, | 
 |         effectTags = {OptionEffectTag.UNKNOWN}, | 
 |         help = "Use terminal cursor controls to minimize scrolling output.") | 
 |     public UseCurses useCursesEnum; | 
 |  | 
 |     @Option( | 
 |       name = "terminal_columns", | 
 |       defaultValue = "80", | 
 |       metadataTags = {OptionMetadataTag.HIDDEN}, | 
 |       documentationCategory = OptionDocumentationCategory.UNDOCUMENTED, | 
 |       effectTags = {OptionEffectTag.UNKNOWN}, | 
 |       help = "A system-generated parameter which specifies the terminal width in columns." | 
 |     ) | 
 |     public int terminalColumns; | 
 |  | 
 |     @Option( | 
 |         name = "isatty", | 
 |         // TODO(b/137881511): Old name should be removed after 2020-01-01, or whenever is | 
 |         // reasonable. | 
 |         oldName = "is_stderr_atty", | 
 |         defaultValue = "false", | 
 |         metadataTags = {OptionMetadataTag.HIDDEN}, | 
 |         documentationCategory = OptionDocumentationCategory.UNDOCUMENTED, | 
 |         effectTags = {OptionEffectTag.UNKNOWN}, | 
 |         help = | 
 |             "A system-generated parameter which is used to notify the " | 
 |                 + "server whether this client is running in a terminal. " | 
 |                 + "If this is set to false, then '--color=auto' will be treated as '--color=no'. " | 
 |                 + "If this is set to true, then '--color=auto' will be treated as '--color=yes'.") | 
 |     public boolean isATty; | 
 |  | 
 |     // This lives here (as opposed to the more logical BuildRequest.Options) | 
 |     // because the client passes it to the server *always*.  We don't want the | 
 |     // client to have to figure out when it should or shouldn't to send it. | 
 |     @Option( | 
 |       name = "emacs", | 
 |       defaultValue = "false", | 
 |       documentationCategory = OptionDocumentationCategory.UNDOCUMENTED, | 
 |       effectTags = {OptionEffectTag.UNKNOWN}, | 
 |       help = | 
 |           "A system-generated parameter which is true iff EMACS=t or INSIDE_EMACS is set " | 
 |               + "in the environment of the client.  This option controls certain display " | 
 |               + "features." | 
 |     ) | 
 |     public boolean runningInEmacs; | 
 |  | 
 |     @Option( | 
 |       name = "show_timestamps", | 
 |       defaultValue = "false", | 
 |       documentationCategory = OptionDocumentationCategory.UNCATEGORIZED, | 
 |       effectTags = {OptionEffectTag.UNKNOWN}, | 
 |       help = "Include timestamps in messages" | 
 |     ) | 
 |     public boolean showTimestamp; | 
 |  | 
 |     @Option( | 
 |         name = "progress_in_terminal_title", | 
 |         defaultValue = "false", | 
 |         documentationCategory = OptionDocumentationCategory.UNCATEGORIZED, | 
 |         effectTags = {OptionEffectTag.UNKNOWN}, | 
 |         help = | 
 |             "Show the command progress in the terminal title. " | 
 |                 + "Useful to see what bazel is doing when having multiple terminal tabs.") | 
 |     public boolean progressInTermTitle; | 
 |  | 
 |     @Option( | 
 |       name = "experimental_external_repositories", | 
 |       defaultValue = "false", | 
 |       documentationCategory = OptionDocumentationCategory.UNCATEGORIZED, | 
 |       effectTags = {OptionEffectTag.UNKNOWN}, | 
 |       help = "Use external repositories for improved stability and speed when available." | 
 |     ) | 
 |     public boolean externalRepositories; | 
 |  | 
 |     @Option( | 
 |       name = "force_experimental_external_repositories", | 
 |       defaultValue = "false", | 
 |       documentationCategory = OptionDocumentationCategory.UNCATEGORIZED, | 
 |       effectTags = {OptionEffectTag.UNKNOWN}, | 
 |       help = "Forces --experimental_external_repositories." | 
 |     ) | 
 |     public boolean forceExternalRepositories; | 
 |  | 
 |     @Option( | 
 |         name = "attempt_to_print_relative_paths", | 
 |         oldName = "experimental_ui_attempt_to_print_relative_paths", | 
 |         defaultValue = "false", | 
 |         documentationCategory = OptionDocumentationCategory.LOGGING, | 
 |         effectTags = {OptionEffectTag.TERMINAL_OUTPUT}, | 
 |         help = | 
 |             "When printing the location part of messages, attempt to use a path relative to the " | 
 |                 + "workspace directory or one of the directories specified by --package_path.") | 
 |     public boolean attemptToPrintRelativePaths; | 
 |  | 
 |     @Option( | 
 |         name = "experimental_ui_debug_all_events", | 
 |         defaultValue = "false", | 
 |         metadataTags = {OptionMetadataTag.HIDDEN}, | 
 |         documentationCategory = OptionDocumentationCategory.UNDOCUMENTED, | 
 |         effectTags = {OptionEffectTag.UNKNOWN}, | 
 |         help = "Report all events known to the Bazel UI.") | 
 |     public boolean experimentalUiDebugAllEvents; | 
 |  | 
 |     @Option( | 
 |         name = "experimental_ui_mode", | 
 |         defaultValue = "oldest_actions", | 
 |         converter = ProgressModeConverter.class, | 
 |         documentationCategory = OptionDocumentationCategory.UNCATEGORIZED, | 
 |         effectTags = {OptionEffectTag.TERMINAL_OUTPUT}, | 
 |         help = | 
 |             "Determines what kind of data is shown in the detailed progress bar. By default, it is " | 
 |                 + "set to show the oldest actions and their running time. The underlying data " | 
 |                 + "source is usually sampled in a mode-dependend way to fit within the number of " | 
 |                 + "lines given by --ui_actions_shown.") | 
 |     public ProgressMode uiProgressMode; | 
 |  | 
 |     @Option( | 
 |         name = "ui_actions_shown", | 
 |         oldName = "experimental_ui_actions_shown", | 
 |         defaultValue = "8", | 
 |         documentationCategory = OptionDocumentationCategory.UNCATEGORIZED, | 
 |         effectTags = {OptionEffectTag.TERMINAL_OUTPUT}, | 
 |         help = | 
 |             "Number of concurrent actions shown in the detailed progress bar; each " | 
 |                 + "action is shown on a separate line. The progress bar always shows " | 
 |                 + "at least one one, all numbers less than 1 are mapped to 1. " | 
 |                 + "This option has no effect if --noui is set.") | 
 |     public int uiSamplesShown; | 
 |  | 
 |     @Option( | 
 |         name = "experimental_ui_limit_console_output", | 
 |         defaultValue = "0", | 
 |         documentationCategory = OptionDocumentationCategory.UNCATEGORIZED, | 
 |         effectTags = {OptionEffectTag.UNKNOWN}, | 
 |         help = | 
 |             "Number of bytes to which the UI will limit its output (non-positive " | 
 |                 + "values indicate unlimited). Once the limit is approaching, the UI " | 
 |                 + "will try hard to limit in a meaningful way, but will ultimately just drop all " | 
 |                 + "output.") | 
 |     public int experimentalUiLimitConsoleOutput; | 
 |  | 
 |     @Option( | 
 |         name = "experimental_ui_deduplicate", | 
 |         defaultValue = "false", | 
 |         documentationCategory = OptionDocumentationCategory.LOGGING, | 
 |         effectTags = {OptionEffectTag.TERMINAL_OUTPUT}, | 
 |         help = "Make the UI deduplicate messages to have a cleaner scroll-back log.") | 
 |     public boolean experimentalUiDeduplicate; | 
 |  | 
 |     public boolean useColor() { | 
 |       return useColorEnum == UseColor.YES || (useColorEnum == UseColor.AUTO && isATty); | 
 |     } | 
 |  | 
 |     public boolean useCursorControl() { | 
 |       return useCursesEnum == UseCurses.YES || (useCursesEnum == UseCurses.AUTO && isATty); | 
 |     } | 
 |   } | 
 | } |