Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add newRecipe script #186

Merged
merged 5 commits into from
Jul 17, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 11 additions & 15 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,18 @@ Follow these instructions for contributing new recipes. The Goal headers indicat

#### Goal 2: Setup a New Recipe's Boilerplate by Copying a Current Similar One

1. Pick an existing recipe to duplicate as a starting point. The `HelloLog` recipe is the simplest and is set up to work on both Node.js and Browser backends.
- In the examples that follow, we'll assume that you copied the `HelloLog` recipe and wish to use the "Unique Recipe Name" of `MyNewRecipe`
1. Pick an existing recipe to duplicate as a starting point. Here are some suggestions:
- `HelloLog` - If your recipe is compatible with both Node.js and web browser backends. _Note:_ Logging to the console **is** supported by **both** backends.
- `ReadPrintFileContentsNode` - If your recipe is **only** compatible with the `Node.js` backend.
- `DiceCLI` - If your recipe is **only** compatible with the `Node.js` backend **and** requires user interact for testing (e.g. a CLI app). This is to prevent our CI process from blocking while waiting for input during testing.
- `WindowPropertiesJs` - If your recipe is **only** compatible with the web browser backend.
- If your recipe targets a particular web framework:
- `HelloConcur`
- `HelloHalogenHooks`
- `HelloReactHooks`
1. Run the recipe creation script. Substitute `MyNewRecipe` with your recipe name:
```
cd recipes
cp -r HelloLog MyNewRecipe
```
1. Rename the copied folder to the "Unique Recipe Name" assigned in the original issue.
1. Depending on the backend-compatibility of your recipe, follow the instructions below:
1. If your recipe is incompatible with the browser environment, delete the `web` directory.
- If your recipe uses `node-*` libraries, it is incompatible with the browser.
- Logging to the console **is** supported in the browser.
1. If your recipe is incompatible with the Node.js backend, delete the `nodeSupported.md` file.
1. If your recipe is compatible with Node.js, but the resulting program should not be run during CI (e.g. a program that parses command-line arguments), then rename `nodeSupported.md` to `nodeSupportedSkipCI.md`.
1. Replace all usages of the original recipe's name with your new recipe's name. For example:
```
grep -rl 'HelloLog' MyNewRecipe | xargs sed -i 's/HelloLog/MyNewRecipe/g'
./scripts/newRecipe.sh MyNewRecipe HelloLog
```

#### Goal 3: Implement and Submit the Recipe
Expand Down
31 changes: 16 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,48 +36,49 @@ Use "make RecipeName-target" to run a recipe

=== Node Recipes ===
make ReadPrintFileContents-node
make HelloWorld-node
make HelloLog-node
...

=== Web Recipes ===
make WindowProperties-web
make HelloWorld-web
make HelloLog-web
...
```

Then simply copy and paste one of the listed commands. For example:

Running a node-compatible recipe:
```
> make HelloWorld-node
=== Running HelloWorld on the Node.js backend ===
> make HelloLog-node
=== Running HelloLog on the Node.js backend ===
[info] Installation complete.
[info] Build succeeded.
Hello world!
```

Running a web-compatible recipe:
```
> make HelloWorld-web
=== Building HelloWorld ===
> make HelloLog-web
=== Building HelloLog ===
[info] Installation complete.
[info] Build succeeded.
=== Launching HelloWorld in the web browser ===
=== Launching HelloLog in the web browser ===
...
```

## Current Recipe Suffixes

| Recipes ending with ... | ... mean the following approach/library is used |
| - | - |
| `HalogenClassic` | Component-style Halogen |
| `HalogenHooks` | Hooks-style Halogen |
| `ReactClassic` | Component-style React via [react-basic](https://github.com/lumihq/purescript-react-basic) |
| `ReactHooks` | Hooks-style React via [react-basic](https://github.com/lumihq/purescript-react-basic) |
| `Js` | Run plain PureScript on the web without a web framework |
| `Log` | Log content to both the browser's console and the terminal |
| `Node` | Run PureScript on Node.js where no user interaction occurs |
| `CLI` | Run PureScript on Node.js with user interaction |
| `HalogenClassic` | [Component-style Halogen](https://github.com/purescript-halogen/purescript-halogen/) |
| `HalogenHooks` | [Hooks-style Halogen](https://github.com/thomashoneyman/purescript-halogen-hooks/) |
| `ReactClassic` | [Component-style React](https://github.com/lumihq/purescript-react-basic-classic) via [react-basic](https://github.com/lumihq/purescript-react-basic) |
| `ReactHooks` | [Hooks-style React](https://github.com/spicydonuts/purescript-react-basic-hooks/) via [react-basic](https://github.com/lumihq/purescript-react-basic) |
| `Concur` | [Concur](https://github.com/purescript-concur/purescript-concur-react) |
| `Js` | Run plain PureScript **only** on the web (no node.js) without a web framework |
| `Log` | Log content to **both** the browser's dev console and the terminal |
| `Node` | Run PureScript **only** on Node.js where no user interaction occurs |
| `CLI` | Run PureScript **only** on Node.js with user interaction |

## Recipes

Expand Down
8 changes: 7 additions & 1 deletion makefile
Original file line number Diff line number Diff line change
Expand Up @@ -139,12 +139,18 @@ nodeCompatSkipCI = $(call recipeDir,$1)/nodeSupportedSkipCI.md
> exit 1
> fi

.PHONY: %-node
# Runs recipe as node.js console app
.PHONY: %-node
%-node: $(call recipeDir,%) %-nodeCompatible
> @echo === Running $* on the Node.js backend ===
> spago -x $(call recipeSpago,$*) run --main $(call main,$*)

# Watches for changes and rebuilds and reruns recipe as node.js console app
.PHONY: %-node-watch
%-node-watch: $(call recipeDir,%) %-nodeCompatible
> @echo === Watching to build and run $* on the Node.js backend ===
> spago -x $(call recipeSpago,$*) run --main $(call main,$*) -w

# Functions for browser-comptabile recipes that help generate paths

webDir = $(call recipeDir,$1)/web
Expand Down
31 changes: 16 additions & 15 deletions scripts/ReadmeContent.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,45 +36,46 @@ Use "make RecipeName-target" to run a recipe

=== Node Recipes ===
make ReadPrintFileContents-node
make HelloWorld-node
make HelloLog-node
...

=== Web Recipes ===
make WindowProperties-web
make HelloWorld-web
make HelloLog-web
...
```

Then simply copy and paste one of the listed commands. For example:

Running a node-compatible recipe:
```
> make HelloWorld-node
=== Running HelloWorld on the Node.js backend ===
> make HelloLog-node
=== Running HelloLog on the Node.js backend ===
[info] Installation complete.
[info] Build succeeded.
Hello world!
```

Running a web-compatible recipe:
```
> make HelloWorld-web
=== Building HelloWorld ===
> make HelloLog-web
=== Building HelloLog ===
[info] Installation complete.
[info] Build succeeded.
=== Launching HelloWorld in the web browser ===
=== Launching HelloLog in the web browser ===
...
```

## Current Recipe Suffixes

| Recipes ending with ... | ... mean the following approach/library is used |
| - | - |
| `HalogenClassic` | Component-style Halogen |
| `HalogenHooks` | Hooks-style Halogen |
| `ReactClassic` | Component-style React via [react-basic](https://github.com/lumihq/purescript-react-basic) |
| `ReactHooks` | Hooks-style React via [react-basic](https://github.com/lumihq/purescript-react-basic) |
| `Js` | Run plain PureScript on the web without a web framework |
| `Log` | Log content to both the browser's console and the terminal |
| `Node` | Run PureScript on Node.js where no user interaction occurs |
| `CLI` | Run PureScript on Node.js with user interaction |
| `HalogenClassic` | [Component-style Halogen](https://github.com/purescript-halogen/purescript-halogen/) |
| `HalogenHooks` | [Hooks-style Halogen](https://github.com/thomashoneyman/purescript-halogen-hooks/) |
| `ReactClassic` | [Component-style React](https://github.com/lumihq/purescript-react-basic-classic) via [react-basic](https://github.com/lumihq/purescript-react-basic) |
| `ReactHooks` | [Hooks-style React](https://github.com/spicydonuts/purescript-react-basic-hooks/) via [react-basic](https://github.com/lumihq/purescript-react-basic) |
| `Concur` | [Concur](https://github.com/purescript-concur/purescript-concur-react) |
| `Js` | Run plain PureScript **only** on the web (no node.js) without a web framework |
| `Log` | Log content to **both** the browser's dev console and the terminal |
| `Node` | Run PureScript **only** on Node.js where no user interaction occurs |
| `CLI` | Run PureScript **only** on Node.js with user interaction |
82 changes: 82 additions & 0 deletions scripts/newRecipe.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#!/usr/bin/env bash

# Exit on first failure
set -e

print_error() {
cat <<HELP
Error: $1

Usage:
./scripts/newRecipe.sh <new recipe name> <optional recipe to copy>

Examples:
./scripts/newRecipe.sh MyNewRecipe
./scripts/newRecipe.sh MyNewRecipe HelloHalogenHooks
./scripts/newRecipe.sh MyNewRecipe recipes/HelloHalogenHooks/
HELP
exit 1
}

# Valid number of arguments is either 1 or 2
[ $# -eq 0 ] && print_error 'No arguments'
[ $# -gt 2 ] && print_error 'Too many arguments'

# Use a default original recipe if one is not provided.
# Just take basename of recipe path.
orig=$(basename ${2:-HelloLog})

echo "Creating new recipe $1 from $orig"

# Echo all following script commands
set -x

# Copy original recipe to new recipe directory
cp -r recipes/$orig recipes/$1

# Replace all usages of the original recipe's name with the new recipe's name
grep -rl $orig recipes/$1 | xargs sed -i "s/$orig/$1/g"


# ====== Additional instructions =======

# Disable echo of all following script commands
set +x

echo --- Some helpful development commands for this recipe: ---

# Basic node
[ -f recipes/$1/nodeSupported.md ] && cat <<CMD

* Watch for changes and rebuild and re-run in node.js:
make $1-node-watch
CMD

# Node CLI - Watching causes issues with this
[ -f recipes/$1/nodeSupportedSkipCI.md ] && cat <<CMD

* Re-run in node.js:
make $1-node
CMD

# Web
[ -d recipes/$1/web ] && cat <<CMD

* Launch in web browser (will refresh upon rebuild):
make $1-web

* Watch for changes and rebuild (only necessary if editing without purs-ide):
make $1-build-watch
CMD

# Common
cat <<CMD

--------- Common to all recipe types: ---------

* Manual rebuild:
make $1-build

* Regenerate recipe table (run this after editing recipes/$1/README.md):
make readme
CMD