Skip to content

Commit

Permalink
Send contect to PrintHelpMessage
Browse files Browse the repository at this point in the history
  • Loading branch information
ajalt committed Jun 6, 2023
1 parent 2d70df0 commit 7cd3753
Show file tree
Hide file tree
Showing 6 changed files with 32 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -253,17 +253,17 @@ abstract class CliktCommand(
* Return `null` if the error does not have a message (e.g. [ProgramResult])
*/
fun getFormattedHelp(error: CliktError? = null): String? {
if (error != null && error !is UsageError && error !is PrintHelpMessage) {
if (error != null && error !is ContextCliktError) {
return error.message
}

val err = error as? UsageError // null for PrintHelpMessage
val ctx = err?.context ?: _context ?: createContext(emptyList(), null, emptyList())
val ctx = (error as? ContextCliktError)?.context
?: _context ?: createContext(emptyList(), null, emptyList())
val cmd = ctx.command
val programName = cmd.getCommandNameWithParents()
return ctx.helpFormatter.formatHelp(
ctx,
err,
error as? UsageError,
cmd.commandHelp,
cmd.commandHelpEpilog,
cmd.allHelpParams(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,25 @@ open class CliktError(
val printError: Boolean = true,
) : RuntimeException(message, cause)

/** An interface for CliktErrors that have a context attached */
interface ContextCliktError {
/**
* The context of the command that raised this error.
*
* Will be set automatically if thrown during command line processing.
*/
var context: Context?
}

/**
* An exception that indicates that the command's help should be printed.
*
* Execution should be immediately halted.
*
* @property error If true, execution should halt with an error. Otherwise, execution halt with no error code.
*/
class PrintHelpMessage(val command: CliktCommand, val error: Boolean = false) :
CliktError(printError = false)
class PrintHelpMessage(override var context: Context?, val error: Boolean = false) :
CliktError(printError = false), ContextCliktError

/**
* An exception that indicates that a message should be printed.
Expand Down Expand Up @@ -72,7 +82,7 @@ open class UsageError(
message: String?,
var paramName: String? = null,
statusCode: Int = 1,
) : CliktError(message, statusCode = statusCode) {
) : CliktError(message, statusCode = statusCode), ContextCliktError {
constructor(message: String, argument: Argument, statusCode: Int = 1)
: this(message, argument.name, statusCode)

Expand All @@ -89,12 +99,7 @@ open class UsageError(
return message ?: ""
}

/**
* The context of the command that raised this error.
*
* Will be set automatically if thrown during command line processing.
*/
var context: Context? = null
override var context: Context? = null
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ private class EagerOption(
}

internal fun helpOption(names: Set<String>, message: String): Option {
return EagerOption(names, message, false, emptyMap(), null) { throw PrintHelpMessage(context.command) }
return EagerOption(names, message, false, emptyMap(), null) { throw PrintHelpMessage(context) }
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ internal object Parser {
prefixes.remove("")

if (tokens.isEmpty() && command.printHelpOnEmptyArgs) {
throw PrintHelpMessage(command, error = true)
throw PrintHelpMessage(context, error = true)
}

fun isLongOptionWithEquals(prefix: String, token: String): Boolean {
Expand All @@ -95,8 +95,7 @@ internal object Parser {
token.substringBefore("=")
) in longNames
) return true
if (context.tokenTransformer(context, token.take(2)) in optionsByName) return false
return true
return context.tokenTransformer(context, token.take(2)) !in optionsByName
}

fun consumeParse(tokenIndex: Int, result: OptParseResult) {
Expand Down Expand Up @@ -276,7 +275,7 @@ internal object Parser {
MultiUsageError.buildOrNull(usageErrors)?.let { throw it }

if (subcommand == null && subcommands.isNotEmpty() && !command.invokeWithoutSubcommand) {
throw PrintHelpMessage(command, error = true)
throw PrintHelpMessage(context, error = true)
}

command.currentContext.invokedSubcommand = subcommand
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,7 @@ fun CliktCommand.test(
stdin: String = "",
envvars: Map<String, String> = emptyMap(),
): CliktCommandTestResult {
val toks = shlex("test", argv, null)
return test(toks, stdin, envvars)
return test(shlex("test", argv, null), stdin, envvars)
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import com.github.ajalt.clikt.parameters.types.int
import com.github.ajalt.clikt.testing.TestCommand
import com.github.ajalt.clikt.testing.formattedMessage
import com.github.ajalt.clikt.testing.parse
import com.github.ajalt.clikt.testing.test
import io.kotest.assertions.throwables.shouldThrow
import io.kotest.data.blocking.forAll
import io.kotest.data.row
Expand All @@ -21,6 +22,7 @@ import io.kotest.matchers.collections.shouldContainExactlyInAnyOrder
import io.kotest.matchers.should
import io.kotest.matchers.shouldBe
import io.kotest.matchers.shouldNotBe
import io.kotest.matchers.string.shouldStartWith
import kotlin.js.JsName
import kotlin.test.Test

Expand Down Expand Up @@ -225,6 +227,13 @@ class CliktCommandTest {
TestCommand().context { helpOptionNames = emptySet() }.subcommands(D()).parse("d")
}

@Test
@JsName("help_flag_gets_correct_context")
fun `help flag gets correct context`() {
TestCommand(name = "a").subcommands(TestCommand(name = "b"))
.test("b --help").output.shouldStartWith("Usage: a b")
}

@Test
@JsName("command_registered_functions")
fun `command registered functions`() {
Expand Down

0 comments on commit 7cd3753

Please sign in to comment.