You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
To provide command line arguments, you can either call `spago run` with the `-a` option to pass additional arguments directly to your application, or you can call `spago bundle-app`, which will create an index.js file that can be run directly with `node`.
36
+
For example, to provide the player name using the `-p` option:
40
37
41
38
```text
42
-
spago run -a "-p Phil"
39
+
$ spago run -a "-p Phil"
40
+
>
41
+
```
42
+
```text
43
+
$ spago bundle-app
44
+
$ node index.js -p Phil
43
45
>
44
46
```
45
47
@@ -882,7 +884,7 @@ The remainder of the `Game` module defines a set of similar actions, each using
882
884
883
885
Since our game logic runs in the `RWS` monad, it is necessary to run the computation in order to respond to the user's commands.
884
886
885
-
The front-end of our game is built using two packages: `yargs`, which provides an applicative interface to the `yargs`command line parsing library, and `node-readline`, which wraps NodeJS' `readline` module, allowing us to write interactive console-based applications.
887
+
The front-end of our game is built using two packages: `optparse`, which provides applicative command line parsing, and `node-readline`, which wraps NodeJS' `readline` module, allowing us to write interactive console-based applications.
886
888
887
889
The interface to our game logic is provided by the function `game` in the `Game` module:
888
890
@@ -972,45 +974,44 @@ The `runGame` function finally attaches the initial line handler to the console
972
974
973
975
## Handling Command Line Options
974
976
975
-
The final piece of the application is responsible for parsing command line options and creating the `GameEnvironment` configuration record. For this, we use the `yargs` package.
977
+
The final piece of the application is responsible for parsing command line options and creating the `GameEnvironment` configuration record. For this, we use the `optparse` package.
976
978
977
-
`yargs` is an example of _applicative command line option parsing_. Recall that an applicative functor allows us to lift functions of arbitrary arity over a type constructor representing some type of side-effect. In the case of the `yargs` package, the functor we are interested in is the `Y` functor, which adds the side-effect of reading from command line options. It provides the following handler:
979
+
`optparse` is an example of _applicative command line option parsing_. Recall that an applicative functor allows us to lift functions of arbitrary arity over a type constructor representing some type of side-effect. In the case of the `optparse` package, the functor we are interested in is the `Parser` functor (imported from the optparse module `Options.Applicative`, not to be confused with our `Parser` that we defined in the `Split` module), which adds the side-effect of reading from command line options. It provides the following handler:
The first argument is used to configure the `yargs` library. In our case, we simply provide a usage message, but the `Node.Yargs.Setup` module provides several other options.
991
+
The first argument is used to configure the `optparse` library. In our case, we simply configure it to show the help message when the application is run without any arguments (instead of showing a "missing argument" error) by using `OP.prefs OP.showHelpOnEmpty`, but the `Options.Applicative.Builder` module provides several other options.
990
992
991
-
The second argument uses the `map` function to lift the `runGame` function over the `Y` type constructor. The argument `env` is constructed in a `where` declaration using the applicative operators `<$>` and `<*>`:
993
+
The second argument is the complete description of our parser program:
Here, the `gameEnvironment` function, which has the type `PlayerName -> Boolean -> GameEnvironment`, is lifted over `Y`. The two arguments specify how to read the player name and debug flag from the command line options. The first argument describes the player name option, which is specified by the `-p` or `--player` options, and the second describes the debug mode flag, which is turned on using the `-d` or `--debug` options.
1000
+
Here `OP.info` combines a `Parser` with a set of options for how the help message is formatted. `env <**> OP.helper` takes any command line argument `Parser` named `env` and adds a `--help` option to it automatically. Options for the help message are of type `InfoMod`, which is a monoid, so we can use the `fold` function to add several options together.
1001
+
1002
+
The interesting part of our parser is constructing the `GameEnvironment`:
This demonstrates two basic functions defined in the `Node.Yargs.Applicative` module: `yarg`, which defines a command line option which takes an optional argument (of type `String`, `Number` or `Boolean`), and `flag`which defines a command line flag of type `Boolean`.
1008
+
`player` and `debug` are both `Parser`s, so we can use our applicative operators `<$>` and `<*>` to lift our `gameEnvironment` function, which has the type `PlayerName -> Boolean -> GameEnvironment` over `Parser`. `OP.strOption` constructs a command line option that expects a string value, and is configured via a collection of `Mod`s folded together. `OP.flag`works similarly, but doesn't expect an associated value. `optparse` offers extensive [documentation](https://pursuit.purescript.org/packages/purescript-optparse) on different modifiers available to build various command line parsers.
1008
1009
1009
1010
Notice how we were able to use the notation afforded by the applicative operators to give a compact, declarative specification of our command line interface. In addition, it is simple to add new command line arguments, simply by adding a new function argument to `runGame`, and then using `<*>` to lift `runGame` over an additional argument in the definition of `env`.
1010
1011
1011
1012
## Exercises
1012
1013
1013
-
1. (Medium) Add a new Boolean-valued property `cheatMode` to the `GameEnvironment` record. Add a new command line flag `-c` to the `yargs` configuration which enables cheat mode. The `cheat` command from the previous exercise should be disallowed if cheat mode is not enabled.
1014
+
1. (Medium) Add a new Boolean-valued property `cheatMode` to the `GameEnvironment` record. Add a new command line flag `-c` to the `optparse` configuration which enables cheat mode. The `cheat` command from the previous exercise should be disallowed if cheat mode is not enabled.
0 commit comments