Add ExitCode type

This commit is contained in:
Richard Feldman 2022-09-19 15:21:52 -04:00
parent 45df950cf6
commit 0e472200f0
No known key found for this signature in database
GPG key ID: F1F21AA5B1D9E43B
2 changed files with 36 additions and 12 deletions

View file

@ -1,10 +1,34 @@
interface Program
exposes [Program, noArgs, withArgs, quick, withEnv]
exposes [Program, ExitCode, noArgs, withArgs, quick, withEnv, exitCode, exit]
imports [Task.{ Task }, InternalProgram.{ InternalProgram }, InternalTask, Effect]
## A [command-line interface](https://en.wikipedia.org/wiki/Command-line_interface) program.
Program : InternalProgram
## An [exit status](https://en.wikipedia.org/wiki/Exit_status) code.
ExitCode := U8
## Converts a [U8] to an [ExitCode].
##
## If you already have a [Task] and want to convert its success type
## from `{}` to [ExitCode], you may find [Program.exit] convenient.
exitCode : U8 -> ExitCode
exitCode = @ExitCode
## Attach an [ExitCode] to a task.
##
## Stderr.line "I hit an error and couldn't continue."
## |> Program.exit 1
##
## Note that this does not terminate the current process! By design, this platform does not have
## a [Task] which terminates the current process. Instead, error handling should be consistently
## done through task failures.
##
## To convert a [U8] directly into an [ExitCode], use [Program.exitCode].
exit : Task {} [] fx, U8 -> Task ExitCode [] fx
exit = \task, code ->
Task.map task \{} -> @ExitCode code
## A program which runs the given task and discards the values it produces on success or failure.
## One use for this is as an introductory [Program] when teaching someone how to use this platform.
##
@ -31,13 +55,13 @@ quick = \task ->
## the task's potential failures using something like [Task.attempt].
##
## For a similar program which does use command-line arguments, see [Program.withArgs].
noArgs : Task U8 [] * -> Program
noArgs : Task ExitCode [] * -> Program
noArgs = \task ->
effect =
InternalTask.toEffect task
|> Effect.map \result ->
when result is
Ok exitStatus -> exitStatus
Ok (@ExitCode u8) -> u8
Err _ -> 0 # TODO this is unreachable! Remove it after https://github.com/roc-lang/roc/issues/4054 lands
InternalProgram.fromEffect effect
@ -51,14 +75,14 @@ noArgs = \task ->
## If any command-line arguments contain invalid Unicode, the invalid parts will be replaced with
## the [Unicode replacement character](https://unicode.org/glossary/#replacement_character)
## (`<60>`).
withArgs : (List Str -> Task U8 [] *) -> Program
withArgs : (List Str -> Task ExitCode [] *) -> Program
withArgs = \toTask ->
effect = Effect.after Effect.args \args ->
toTask args
|> InternalTask.toEffect
|> Effect.map \result ->
when result is
Ok exitStatus -> exitStatus
Ok (@ExitCode u8) -> u8
Err _ -> 0 # TODO this is unreachable! Remove it after https://github.com/roc-lang/roc/issues/4054 lands
InternalProgram.fromEffect effect
@ -66,14 +90,14 @@ withArgs = \toTask ->
## A program which uses [command-line arguments](https://en.wikipedia.org/wiki/Command-line_interface#Arguments)
## and a dictionary of [environment variables](https://en.wikipedia.org/wiki/Environment_variable).
##
## This is a combination of [Program.withArgs] and [Env.dict]. Note that the task's failure type
## This is a combination of [Program.withArgs] and `Env.dict`. Note that the task's failure type
## must be `[]`. You can satisfy that by handling all the task's potential failures using
## something like [Task.attempt].
##
## If any command-line arguments contain invalid Unicode, the invalid parts will be replaced with
## the [Unicode replacement character](https://unicode.org/glossary/#replacement_character)
## (`<60>`).
withEnv : (List Str, Dict Str Str -> Task U8 [] *) -> Program
withEnv : (List Str, Dict Str Str -> Task ExitCode [] *) -> Program
withEnv = \toTask ->
effect =
args <- Effect.args |> Effect.after
@ -83,7 +107,7 @@ withEnv = \toTask ->
|> InternalTask.toEffect
|> Effect.map \result ->
when result is
Ok exitStatus -> exitStatus
Ok (@ExitCode code) -> code
Err _ -> 0 # TODO this is unreachable! Remove it after https://github.com/roc-lang/roc/issues/4054 lands
InternalProgram.fromEffect effect

View file

@ -1,7 +1,7 @@
app "file-io"
packages { pf: "cli-platform/main.roc" }
imports [
pf.Program.{ Program },
pf.Program.{ Program, ExitCode },
pf.Stdout,
pf.Stderr,
pf.Task.{ Task },
@ -15,7 +15,7 @@ app "file-io"
main : Program
main = Program.noArgs mainTask
mainTask : Task U8 [] [Write [File, Stdout, Stderr], Read [File], Env]
mainTask : Task ExitCode [] [Write [File, Stdout, Stderr], Read [File], Env]
mainTask =
path = Path.fromStr "out.txt"
task =
@ -36,7 +36,7 @@ mainTask =
when result is
Ok {} ->
Stdout.line "Successfully wrote a string to out.txt"
|> Task.map \{} -> 0 # exit status
|> Program.exit 0
Err err ->
msg =
@ -48,4 +48,4 @@ mainTask =
_ -> "Uh oh, there was an error!"
Stderr.line msg
|> Task.map \{} -> 1 # exit status
|> Program.exit 1