Skip to content

Commit

Permalink
CLI: Use --style=STYLE option to select formatter
Browse files Browse the repository at this point in the history
  • Loading branch information
Joseph Cooper committed Jun 13, 2024
1 parent cf8eac3 commit 93568fa
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 25 deletions.
36 changes: 25 additions & 11 deletions core/src/main/java/com/facebook/ktfmt/cli/ParsedArgs.kt
Original file line number Diff line number Diff line change
Expand Up @@ -60,30 +60,30 @@ data class ParsedArgs(
|formatting succeeded or failed on standard error. If none of the style options are
|passed, Meta's style is used.
|
|Alternatively, ktfmt can read Kotlin source code from standard input and write the
|Alternatively, ktfmt can read Kotlin source code from standard input and write the
|formatted result on standard output.
|
|Example:
| $ ktfmt --kotlinlang-style Main.kt src/Parser.kt
| Done formatting Main.kt
| Error formatting src/Parser.kt: @@@ERROR@@@; skipping.
|
|
|Commands options:
| -h, --help Show this help message
| -n, --dry-run Don't write to files, only report files which
| -n, --dry-run Don't write to files, only report files which
| would have changed
| --meta-style Use 2-space block indenting (default)
| --google-style Google internal style (2 spaces)
| --kotlinlang-style Kotlin language guidelines style (4 spaces)
| --stdin-name=<name> Name to report when formatting code from stdin
| --set-exit-if-changed Sets exit code to 1 if any input file was not
| --set-exit-if-changed Sets exit code to 1 if any input file was not
| formatted/touched
| --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
Expand All @@ -109,9 +109,21 @@ data class ParsedArgs(

for (arg in args) {
when {
arg == "--meta-style" -> formattingOptions = Formatter.META_FORMAT
arg == "--google-style" -> formattingOptions = Formatter.GOOGLE_FORMAT
arg == "--kotlinlang-style" -> formattingOptions = Formatter.KOTLINLANG_FORMAT
arg.startsWith("--style=") -> {
val parsedStyle =
parseKeyValueArg("--style", arg)
?: return ParseResult.Error(
unexpectedArg(arg)
)
formattingOptions = when (parsedStyle) {
"meta" -> Formatter.META_FORMAT
"google" -> Formatter.GOOGLE_FORMAT
"kotlinlang" -> Formatter.KOTLINLANG_FORMAT
else -> return ParseResult.Error(
"Unknown style '${parsedStyle}'. Style must be one of [dropbox, google, kotlinlang]."
)
}
}
arg == "--dry-run" || arg == "-n" -> dryRun = true
arg == "--set-exit-if-changed" -> setExitIfChanged = true
arg == "--do-not-remove-unused-imports" -> removeUnusedImports = false
Expand All @@ -120,8 +132,8 @@ data class ParsedArgs(
parseKeyValueArg("--stdin-name", arg)
?: return ParseResult.Error(
"Found option '${arg}', expected '${"--stdin-name"}=<value>'")
arg.startsWith("--") -> return ParseResult.Error("Unexpected option: $arg")
arg.startsWith("@") -> return ParseResult.Error("Unexpected option: $arg")
arg.startsWith("--") -> return ParseResult.Error(unexpectedArg(arg))
arg.startsWith("@") -> return ParseResult.Error(unexpectedArg(arg))
else -> fileNames.add(arg)
}
}
Expand All @@ -148,6 +160,8 @@ data class ParsedArgs(
))
}

private fun unexpectedArg(arg: String) = "Unexpected option: $arg"

private fun parseKeyValueArg(key: String, arg: String): String? {
val parts = arg.split('=', limit = 2)
return parts[1].takeIf { parts[0] == key || parts.size == 2 }
Expand Down
8 changes: 4 additions & 4 deletions core/src/test/java/com/facebook/ktfmt/cli/MainTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ class MainTest {
}

@Test
fun `kotlinlang-style is passed to formatter (file)`() {
fun `--style=kotlinlang is passed to formatter (file)`() {
val code =
"""fun f() {
for (child in
Expand All @@ -241,14 +241,14 @@ class MainTest {
emptyInput,
PrintStream(out),
PrintStream(err),
arrayOf("--kotlinlang-style", fooBar.toString()))
arrayOf("--style=kotlinlang", fooBar.toString()))
.run()

assertThat(fooBar.readText()).isEqualTo(code)
}

@Test
fun `kotlinlang-style is passed to formatter (stdin)`() {
fun `--style=kotlinlang is passed to formatter (stdin)`() {
val code =
"""fun f() {
|for (child in
Expand All @@ -271,7 +271,7 @@ class MainTest {
code.byteInputStream(),
PrintStream(out),
PrintStream(err),
arrayOf("--kotlinlang-style", "-"))
arrayOf("--style=kotlinlang", "-"))
.run()

assertThat(out.toString(UTF_8)).isEqualTo(formatted)
Expand Down
26 changes: 16 additions & 10 deletions core/src/test/java/com/facebook/ktfmt/cli/ParsedArgsTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -61,23 +61,29 @@ class ParsedArgsTest {
}

@Test
fun `parseOptions recognizes --meta-style`() {
val parsed = assertSucceeds(ParsedArgs.parseOptions(arrayOf("--meta-style", "foo.kt")))
fun `parseOptions recognizes --style=meta`() {
val parsed = assertSucceeds(ParsedArgs.parseOptions(arrayOf("--style=meta", "foo.kt")))
assertThat(parsed.formattingOptions).isEqualTo(Formatter.META_FORMAT)
}

@Test
fun `parseOptions recognizes --dropbox-style`() {
val parsed = assertSucceeds(ParsedArgs.parseOptions(arrayOf("--kotlinlang-style", "foo.kt")))
fun `parseOptions recognizes --style=kotlinlang`() {
val parsed = assertSucceeds(ParsedArgs.parseOptions(arrayOf("--style=kotlinlang", "foo.kt")))
assertThat(parsed.formattingOptions).isEqualTo(Formatter.KOTLINLANG_FORMAT)
}

@Test
fun `parseOptions recognizes --google-style`() {
val parsed = assertSucceeds(ParsedArgs.parseOptions(arrayOf("--google-style", "foo.kt")))
fun `parseOptions recognizes --style=google`() {
val parsed = assertSucceeds(ParsedArgs.parseOptions(arrayOf("--style=google", "foo.kt")))
assertThat(parsed.formattingOptions).isEqualTo(Formatter.GOOGLE_FORMAT)
}

@Test
fun `parseOptions rejects unknown style`() {
val parseResult = ParsedArgs.parseOptions(arrayOf("--style=custom-style", "foo.kt"))
assertThat(parseResult).isInstanceOf(ParseResult.Error::class.java)
}

@Test
fun `parseOptions recognizes --dry-run`() {
val parsed = assertSucceeds(ParsedArgs.parseOptions(arrayOf("--dry-run", "foo.kt")))
Expand Down Expand Up @@ -170,7 +176,7 @@ class ParsedArgsTest {
@Test
fun `processArgs use the @file option with file containing arguments`() {
val file = root.resolve("existing-file")
file.writeText("--google-style\n--dry-run\n--set-exit-if-changed\nFile1.kt\nFile2.kt\n")
file.writeText("--style=google\n--dry-run\n--set-exit-if-changed\nFile1.kt\nFile2.kt\n")

val result = ParsedArgs.processArgs(arrayOf("@" + file.absolutePath))
assertThat(result).isInstanceOf(ParseResult.Ok::class.java)
Expand All @@ -187,7 +193,7 @@ class ParsedArgsTest {
fun `parses multiple args successfully`() {
val testResult =
ParsedArgs.parseOptions(
arrayOf("--google-style", "--dry-run", "--set-exit-if-changed", "File.kt"),
arrayOf("--style=google", "--dry-run", "--set-exit-if-changed", "File.kt"),
)
assertThat(testResult)
.isEqualTo(
Expand All @@ -202,7 +208,7 @@ class ParsedArgsTest {
@Test
fun `last style in args wins`() {
val testResult =
ParsedArgs.parseOptions(arrayOf("--google-style", "--kotlinlang-style", "File.kt"))
ParsedArgs.parseOptions(arrayOf("--style=google", "--style=kotlinlang", "File.kt"))
assertThat(testResult)
.isEqualTo(
parseResultOk(
Expand All @@ -213,7 +219,7 @@ class ParsedArgsTest {

@Test
fun `error when parsing multiple args and one is unknown`() {
val testResult = ParsedArgs.parseOptions(arrayOf("@unknown", "--google-style", "File.kt"))
val testResult = ParsedArgs.parseOptions(arrayOf("@unknown", "--style=google", "File.kt"))
assertThat(testResult).isEqualTo(ParseResult.Error("Unexpected option: @unknown"))
}

Expand Down

0 comments on commit 93568fa

Please sign in to comment.