1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.tools.metalava.cli.common 18 19 import com.github.ajalt.clikt.core.CliktCommand 20 import com.github.ajalt.clikt.core.context 21 import com.github.ajalt.clikt.parameters.arguments.argument 22 import com.github.ajalt.clikt.parameters.arguments.multiple 23 import com.github.ajalt.clikt.parameters.groups.OptionGroup 24 import com.github.ajalt.clikt.parameters.groups.provideDelegate 25 import com.github.ajalt.clikt.parameters.options.default 26 import com.github.ajalt.clikt.parameters.options.option 27 import com.github.ajalt.clikt.parameters.options.switch 28 29 const val ARG_QUIET = "--quiet" 30 const val ARG_VERBOSE = "--verbose" 31 32 enum class Verbosity(val quiet: Boolean = false, val verbose: Boolean = false) { 33 /** Whether to report warnings and other diagnostics along the way. */ 34 QUIET(quiet = true), 35 36 /** Standard output level. */ 37 NORMAL, 38 39 /** Whether to report extra diagnostics along the way. */ 40 VERBOSE(verbose = true) 41 } 42 43 /** 44 * Container for options that need to be processed as early as possible, i.e. before any commands. 45 * 46 * Note this could generate results different from what would happen downstream, e.g. if 47 * `"--verbose"` was used as a flag value, e.g. `--hide --verbose`. But that's not a realistic 48 * problem. 49 */ 50 open class EarlyOptions : OptionGroup() { 51 52 val verbosity: Verbosity by 53 option( 54 help = 55 """ 56 Set the verbosity of the output.$HARD_NEWLINE 57 $ARG_QUIET - Only include vital output.$HARD_NEWLINE 58 $ARG_VERBOSE - Include extra diagnostic output.$HARD_NEWLINE 59 """ 60 .trimIndent() 61 ) 62 .switch( 63 ARG_QUIET to Verbosity.QUIET, 64 ARG_VERBOSE to Verbosity.VERBOSE, 65 ) 66 .default(Verbosity.NORMAL, defaultForHelp = "Neither $ARG_QUIET or $ARG_VERBOSE") 67 68 companion object { 69 /** 70 * Parse the arguments to extract the early options; ignores any unknown arguments or 71 * options. 72 */ parsenull73 fun parse(args: Array<String>): EarlyOptions { 74 val command = EarlyOptionCommand() 75 command.parse(args) 76 return command.earlyOptions 77 } 78 } 79 80 /** A command used to parse [EarlyOptions]. */ 81 private class EarlyOptionCommand : CliktCommand(treatUnknownOptionsAsArgs = true) { 82 init { <lambda>null83 context { 84 // Ignore help options. 85 helpOptionNames = emptySet() 86 } 87 } 88 89 /** 90 * Register an argument that will consume all the unknown options and arguments so that they 91 * will not be treated as an error but any collected values will just be ignored. 92 */ 93 @Suppress("unused") private val ignored by argument().multiple() 94 95 val earlyOptions by EarlyOptions() 96 runnull97 override fun run() {} 98 } 99 } 100