diff --git a/core/src/main/java/com/facebook/ktfmt/cli/Main.kt b/core/src/main/java/com/facebook/ktfmt/cli/Main.kt index 2b8dde1a..944ee8d7 100644 --- a/core/src/main/java/com/facebook/ktfmt/cli/Main.kt +++ b/core/src/main/java/com/facebook/ktfmt/cli/Main.kt @@ -80,6 +80,10 @@ class Main( val parsedArgs = when (processArgs) { is ParseResult.Ok -> processArgs.parsedValue + is ParseResult.ShowMessage -> { + err.println(processArgs.message) + return EXIT_CODE_SUCCESS + } is ParseResult.Error -> { err.println(processArgs.errorMessage) return EXIT_CODE_FAILURE diff --git a/core/src/main/java/com/facebook/ktfmt/cli/ParsedArgs.kt b/core/src/main/java/com/facebook/ktfmt/cli/ParsedArgs.kt index b443afea..6690add0 100644 --- a/core/src/main/java/com/facebook/ktfmt/cli/ParsedArgs.kt +++ b/core/src/main/java/com/facebook/ktfmt/cli/ParsedArgs.kt @@ -48,6 +48,50 @@ data class ParsedArgs( return parseOptions(arguments) } + val HELP_TEXT = """ktfmt - command line Kotlin source code pretty-printer + | + |Usage: + | ktfmt [--style=dropbox | --style=google | --style=kotlinlang ] [-n | --dry-run] [--set-exit-if-changed] + | [--do-not-remove-unused-imports] ... + | ktfmt @ARGFILE + | + | ktfmt formats Kotlin source code files in-place, reporting for each file whether the + | formatting succeeded or failed on standard error. If none of the style options are + |passed, Facebook's style is used. + | + |Alternatively, ktfmt can read Kotlin source code from standard in and write the + |formatted result on standard output. + | + |Example: + | $ ktfmt --dropbox-style Main.kt src/Parser.kt + | Done formatting Main.kt + | Error formatting src/Parser.kt: @@@ERROR@@@; skipping. + | + |Commands options: + | -n, --dry-run Don't write to files, only report files which + | would have changed + | --style=dropbox Use 4-space block indenting + | --style=google Google style + | --style=kotlinlang Kotlin language guidelines style + | --set-exit-if-changed Sets exit code to 1 if any input code was not + | correctly formatted + | --do-not-remove-unused-imports Leaves all imports in place, even if not used + | + |ARGFILE: + | If the only argument begins with '@', the remainder of the argument is treated + | as the name of a file to read options and arguments from, one per line. + | + | e.g. + | $ cat arg-file.txt + | --google-style + | -n + | File1.kt + | File2.kt + | $ ktfmt @arg-file1.txt + | Done formatting File1.kt + | Done formatting File2.kt + """.trimMargin() + /** parseOptions parses command-line arguments passed to ktfmt. */ fun parseOptions(args: Array): ParseResult { val fileNames = mutableListOf() @@ -57,6 +101,9 @@ data class ParsedArgs( var removeUnusedImports = true var stdinName: String? = null + if (args.contains("--help")) + return ParseResult.ShowMessage(HELP_TEXT) + for (arg in args) { when { arg == "--dropbox-style" -> formattingOptions = Formatter.DROPBOX_FORMAT @@ -107,6 +154,6 @@ data class ParsedArgs( sealed interface ParseResult { data class Ok(val parsedValue: ParsedArgs) : ParseResult - + data class ShowMessage(val message: String): ParseResult data class Error(val errorMessage: String) : ParseResult } diff --git a/core/src/test/java/com/facebook/ktfmt/cli/MainTest.kt b/core/src/test/java/com/facebook/ktfmt/cli/MainTest.kt index 33d78cdb..fe66b597 100644 --- a/core/src/test/java/com/facebook/ktfmt/cli/MainTest.kt +++ b/core/src/test/java/com/facebook/ktfmt/cli/MainTest.kt @@ -493,4 +493,17 @@ class MainTest { assertThat(exitCode).isEqualTo(0) assertThat(file.readText(UTF_8)).isEqualTo("""fun f() = println("hello, world")""" + "\n") } + + @Test + fun `--help gives return code of 0`() { + val exitCode = Main( + emptyInput, + PrintStream(out), + PrintStream(err), + arrayOf("--help"), + ) + .run() + + assertThat(exitCode).isEqualTo(0) + } } diff --git a/core/src/test/java/com/facebook/ktfmt/cli/ParsedArgsTest.kt b/core/src/test/java/com/facebook/ktfmt/cli/ParsedArgsTest.kt index ae5461bb..f16e7b75 100644 --- a/core/src/test/java/com/facebook/ktfmt/cli/ParsedArgsTest.kt +++ b/core/src/test/java/com/facebook/ktfmt/cli/ParsedArgsTest.kt @@ -133,6 +133,18 @@ class ParsedArgsTest { assertThat(parseResult).isInstanceOf(ParseResult.Error::class.java) } + @Test + fun `parseOptions recognises --help`() { + val parseResult = ParsedArgs.parseOptions(arrayOf("--help")) + assertThat(parseResult).isInstanceOf(ParseResult.ShowMessage::class.java) + } + + @Test + fun `arg --help overrides all others`() { + val parseResult = ParsedArgs.parseOptions(arrayOf("--style=google", "@unknown", "--help", "file.kt")) + assertThat(parseResult).isInstanceOf(ParseResult.ShowMessage::class.java) + } + @Test fun `processArgs use the @file option with non existing file`() { val e =