calyx 0.20.0 → 0.21.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +33 -0
  3. data/.travis.yml +1 -1
  4. data/lib/calyx.rb +1 -0
  5. data/lib/calyx/grammar.rb +12 -0
  6. data/lib/calyx/mapping.rb +15 -0
  7. data/lib/calyx/modifiers.rb +10 -0
  8. data/lib/calyx/production/weighted_choices.rb +7 -0
  9. data/lib/calyx/registry.rb +2 -12
  10. data/lib/calyx/rule.rb +14 -4
  11. data/lib/calyx/version.rb +1 -1
  12. metadata +5 -69
  13. data/docs/404.html +0 -7
  14. data/docs/CNAME +0 -1
  15. data/docs/_config.yml +0 -27
  16. data/docs/_data/breadcrumbs.yml +0 -9
  17. data/docs/_data/docs.yml +0 -35
  18. data/docs/_data/examples.yml +0 -9
  19. data/docs/_includes/breadcrumbs.html +0 -36
  20. data/docs/_includes/contents.html +0 -12
  21. data/docs/_includes/icon-github.html +0 -4
  22. data/docs/_includes/icon-rubygems.html +0 -9
  23. data/docs/_includes/navbar.html +0 -24
  24. data/docs/_includes/pagebar.html +0 -12
  25. data/docs/_layouts/default.html +0 -13
  26. data/docs/_layouts/docs.html +0 -14
  27. data/docs/_layouts/home.html +0 -13
  28. data/docs/_layouts/page.html +0 -20
  29. data/docs/_posts/2017-09-14-welcome-to-jekyll.markdown +0 -25
  30. data/docs/_posts/2017-09-21-0.17.0-released.md +0 -10
  31. data/docs/_styles/card.scss +0 -7
  32. data/docs/_styles/colors.scss +0 -18
  33. data/docs/_styles/content.scss +0 -57
  34. data/docs/_styles/cta.scss +0 -25
  35. data/docs/_styles/grid.scss +0 -22
  36. data/docs/_styles/media.scss +0 -50
  37. data/docs/_styles/menu.scss +0 -54
  38. data/docs/_styles/modifiers.scss +0 -3
  39. data/docs/_styles/navbar.scss +0 -161
  40. data/docs/_styles/pagebar.scss +0 -32
  41. data/docs/_styles/reset.scss +0 -92
  42. data/docs/_styles/scale.scss +0 -23
  43. data/docs/_styles/spread.scss +0 -55
  44. data/docs/_styles/styleguide.scss +0 -52
  45. data/docs/_styles/syntax.scss +0 -84
  46. data/docs/_styles/typography.scss +0 -49
  47. data/docs/_styles/yard.scss +0 -36
  48. data/docs/api.html +0 -9662
  49. data/docs/assets/calyx-docs.css +0 -792
  50. data/docs/assets/calyx-flower-outline.svg +0 -202
  51. data/docs/assets/calyx-flower-reverse.svg +0 -202
  52. data/docs/assets/calyx-flower.svg +0 -202
  53. data/docs/assets/logo-small.png +0 -0
  54. data/docs/assets/logos/calyx-flower-1.svg +0 -22
  55. data/docs/assets/logos/calyx-flower-2.svg +0 -21
  56. data/docs/content/documentation.html +0 -20
  57. data/docs/content/examples.html +0 -12
  58. data/docs/content/examples/any-gradient.md +0 -32
  59. data/docs/content/examples/faker.md +0 -16
  60. data/docs/content/examples/tiny-woodland-bot.md +0 -24
  61. data/docs/content/guides/context.md +0 -45
  62. data/docs/content/guides/expressions.md +0 -175
  63. data/docs/content/guides/features.md +0 -50
  64. data/docs/content/guides/formats.md +0 -37
  65. data/docs/content/guides/installation.md +0 -51
  66. data/docs/content/guides/random.md +0 -100
  67. data/docs/content/guides/results.md +0 -62
  68. data/docs/content/index.html +0 -44
  69. data/docs/content/introduction.md +0 -23
  70. data/docs/content/introduction/concepts.md +0 -82
  71. data/docs/content/introduction/contributing.md +0 -43
  72. data/docs/content/introduction/tutorial.md +0 -129
  73. data/docs/content/styleguide.html +0 -71
  74. data/docs/docs.scss +0 -94
  75. data/docs/index.html +0 -12
  76. data/docs/package-lock.json +0 -1536
  77. data/docs/package.json +0 -16
@@ -1,51 +0,0 @@
1
- ---
2
- title: Installation
3
- layout: docs
4
- permalink: /guides/installation
5
- ---
6
-
7
- ## System requirements
8
-
9
- The following prerequisites are needed to install Calyx:
10
-
11
- - macOS, Windows, GNU/Linux or Unix
12
- - Ruby 2.3 or above (MRI 2.3+, JRuby 9+, Rubinius 3+)
13
- - RubyGems
14
-
15
- Calyx has no external Gem dependencies.
16
-
17
- ## For command line use
18
-
19
- Install the Calyx gem using the [RubyGems](https://rubygems.org) package manager:
20
-
21
- ```
22
- gem install calyx
23
- ```
24
-
25
- ## For applications
26
-
27
- Add the `calyx` dependency to your app’s `Gemfile`:
28
-
29
- ```ruby
30
- gem 'calyx'
31
- ```
32
-
33
- Run [Bundler](https://bundler.io/) to install it:
34
-
35
- ```
36
- bundle install
37
- ```
38
-
39
- ## For local development
40
-
41
- To contribute code back to Calyx or fork it in a new direction, clone the repo from GitHub:
42
-
43
- ```
44
- git clone git@github.com:maetl/calyx
45
- ```
46
-
47
- You can also download the latest build of the project as a ZIP archive:
48
-
49
- ```
50
- wget https://github.com/maetl/calyx/archive/master.zip
51
- ```
@@ -1,100 +0,0 @@
1
- ---
2
- layout: default
3
- title: Random Sampling
4
- permalink: /guides/random/
5
- ---
6
-
7
- # Random Sampling
8
-
9
- By default, the outcomes of generated rules are selected with Ruby’s built-in pseudorandom number generator (as seen in methods like `Kernel.rand` and `Array.sample`). To seed the random number generator, pass in an integer seed value as the first argument to the constructor:
10
-
11
- ```ruby
12
- grammar = Calyx::Grammar.new(seed: 12345) do
13
- # rules...
14
- end
15
- ```
16
-
17
- Alternatively, you can pass a preconfigured instance of Ruby’s stdlib `Random` class:
18
-
19
- ```ruby
20
- random = Random.new(12345)
21
-
22
- grammar = Calyx::Grammar.new(rng: random) do
23
- # rules...
24
- end
25
- ```
26
-
27
- When a random seed isn’t supplied, `Time.new.to_i` is used as the default seed, which makes each run of the generator relatively unique.
28
-
29
- ## Weighted Choices
30
-
31
- Choices can be weighted so that some rules have a greater probability of expanding than others.
32
-
33
- Weights are defined by passing a hash instead of a list of rules where the keys are strings or symbols representing the grammar rules and the values are weights.
34
-
35
- Weights can be represented as floats, integers or ranges.
36
-
37
- - Floats must be in the interval 0..1 and the given weights for a production must sum to 1.
38
- - Ranges must be contiguous and cover the entire interval from 1 to the maximum value of the largest range.
39
- - Integers (Fixnums) will produce a distribution based on the sum of all given numbers, with each number being a fraction of that sum.
40
-
41
- The following definitions produce an equivalent weighting of choices:
42
-
43
- ```ruby
44
- Calyx::Grammar.new do
45
- start 'heads' => 1, 'tails' => 1
46
- end
47
-
48
- Calyx::Grammar.new do
49
- start 'heads' => 0.5, 'tails' => 0.5
50
- end
51
-
52
- Calyx::Grammar.new do
53
- start 'heads' => 1..5, 'tails' => 6..10
54
- end
55
-
56
- Calyx::Grammar.new do
57
- start 'heads' => 50, 'tails' => 50
58
- end
59
- ```
60
-
61
- There’s a lot of interesting things you can do with this. For example, you can model the triangular distribution produced by rolling 2d6:
62
-
63
- ```ruby
64
- Calyx::Grammar.new do
65
- start(
66
- '2' => 1,
67
- '3' => 2,
68
- '4' => 3,
69
- '5' => 4,
70
- '6' => 5,
71
- '7' => 6,
72
- '8' => 5,
73
- '9' => 4,
74
- '10' => 3,
75
- '11' => 2,
76
- '12' => 1
77
- )
78
- end
79
- ```
80
-
81
- Or reproduce Gary Gygax’s famous generation table from the original [Dungeon Master’s Guide](https://en.wikipedia.org/wiki/Dungeon_Master%27s_Guide#Advanced_Dungeons_.26_Dragons) (page 171):
82
-
83
- ```ruby
84
- Calyx::Grammar.new do
85
- start(
86
- :empty => 0.6,
87
- :monster => 0.1,
88
- :monster_treasure => 0.15,
89
- :special => 0.05,
90
- :trick_trap => 0.05,
91
- :treasure => 0.05
92
- )
93
- empty 'Empty'
94
- monster 'Monster Only'
95
- monster_treasure 'Monster and Treasure'
96
- special 'Special'
97
- trick_trap 'Trick/Trap.'
98
- treasure 'Treasure'
99
- end
100
- ```
@@ -1,62 +0,0 @@
1
- ---
2
- layout: default
3
- title: Results
4
- permalink: /guides/results/
5
- ---
6
-
7
- # Generating Results
8
-
9
- ## Result objects
10
-
11
- Results are generated by calling `#generate` on the grammar instance. Results are immutable objects representing the unique randomized output from evaluating the grammar.
12
-
13
- ```ruby
14
- grammar = Calyx::Grammar.new do
15
- start "Where is the green sheep?"
16
- end
17
-
18
- result = grammar.generate
19
- # => Calyx::Result
20
- ```
21
-
22
- The core accessor methods on the result are:
23
-
24
- - `#text`
25
- - `#tree`
26
-
27
- Results can only be deterministically generated by seeding the random number generator.
28
-
29
- ## Accessing the flattened text string
30
-
31
- The `#text` method of the result provides access to the flattened text string generated by the grammar.
32
-
33
- ```ruby
34
- result = grammar.generate
35
-
36
- result.text
37
- # => "Where is the green sheep?"
38
- ```
39
-
40
- `#text` is aliased to the `#to_s` method so result objects can be concatenated and interpolated within other strings directly.
41
-
42
- ```ruby
43
- result = grammar.generate
44
-
45
- templated = "Q: #{result}"
46
- # => "Q: Where is the green sheep?"
47
- ```
48
-
49
- ## Accessing the generated tree
50
-
51
- The `#tree` method of the result provides access to the raw generated tree structure without being flattened into a string.
52
-
53
- The tree is encoded as an array of nested arrays, with the leading symbols labeling the choices and rules selected, and the trailing terminal leaves encoding string values.
54
-
55
- This is related to the concept of [s-expressions](https://en.wikipedia.org/wiki/S-expression). It’s a fairly speculative feature at this stage, but it leads to some interesting possibilities.
56
-
57
- ```ruby
58
- result = grammar.generate
59
-
60
- result.tree
61
- # => [:start, [:choice, [:concat, [[:atom, "Where is the green sheep?"]]]]]
62
- ```
@@ -1,44 +0,0 @@
1
- ---
2
- title: Calyx
3
- layout: home
4
- permanlink: /
5
- ---
6
-
7
- {% include navbar.html %}
8
-
9
- <div class="spread spread-hero">
10
- <figure class="identity">
11
- <img src="/assets/logos/calyx-flower-2.svg" width="80%" height="80%">
12
- </figure>
13
- <div class="lede">
14
- <h2>Create writing machines with generative grammars</h2>
15
-
16
- <ul class="cta-list">
17
- <li><a class="cta-button" href="#">Download</a></li>
18
- <li><a class="cta-button" href="#">Learn more</a></li>
19
- </ul>
20
- </div>
21
- </div>
22
-
23
- <div class="spread spread-intro">
24
- <p>Calyx is a simple and powerful tool for creating writing machines using the Ruby programming language.</p>
25
- </div>
26
-
27
- <div class="content">
28
- <h1>Calyx</h1>
29
- <p>Calyx provides a simple and powerful generative grammar format for creating writing machines using the Ruby programming language.</p>
30
- <p>Although the primary use case is procedurally generating text, Calyx grammars can be used to make anything where the output format is a string.</p>
31
- <p>Calyx provides a simple Ruby API for creating writing machines of all shapes and sizes using generative grammars.</p>
32
- <ul>
33
- <li><a href="https://github.com/maetl/calyx">Source code on GitHub</a></li>
34
- <li><a href="https://rubygems.org/gems/calyx">Package on Rubygems</a></li>
35
- </ul>
36
- </div>
37
-
38
- <div class="features">
39
- <p>An intuitive syntax for constructing text generators in native Ruby or JSON.</p>
40
-
41
- <p>Randomly select desired output from multiple choices.</p>
42
-
43
- <p>Use weighted probabilities to shape the odds of choices occurring.</p>
44
- </div>
@@ -1,23 +0,0 @@
1
- ---
2
- layout: docs
3
- title: Introduction
4
- permalink: /introduction/
5
- ---
6
-
7
- ## What is Calyx?
8
-
9
- Calyx is a simple and powerful software library for creating writing machines using the Ruby programming language. It provides tools for producing randomized sequences of text using a syntax inspired by generative grammars.
10
-
11
- Its primary affordances are for creating bots and weird combinatorial prose and poetry but you can use it to generate anything that has a textual or tree-based representation, including SVG graphics, narrative graphs and fake data schemas.
12
-
13
- ## Why grammars?
14
-
15
- There are many useful and interesting methods for generative writing. The grammar-based approach is popular, widely studied and practiced, and easy to get started with.
16
-
17
- Grammars offer direct authorial control over the fragments that combine to produce an output text. This involves more effort and structure than other more random approaches, but leads to carefully crafted and expressive results which still have a capacity to surprise, delight, and confound—as any good text generation method should.
18
-
19
- ## Getting Started
20
-
21
- Get started with a [simple tutorial](/introduction/tutorial/) or learn more about the [underlying concepts](/introduction/concepts/). If you’re new to Ruby and generative art in general, the [documentation for beginners](/introduction/beginners/) is a good place to start.
22
-
23
- Use the [guides](/docs/guides/) to learn how to use the various features and capabilities of the library. For more direct and structured information, the [reference](/docs/reference/) contains a full breakdown of everything that Calyx supports.
@@ -1,82 +0,0 @@
1
- ---
2
- title: Key Concepts
3
- layout: docs
4
- permalink: /introduction/concepts/
5
- ---
6
-
7
- ## What are grammars?
8
-
9
- A grammar is a set of interconnected rules that describe the syntax of a language. The grammar rules describe how to form strings in that language based on an alphabet.
10
-
11
- ## A dash of theory
12
-
13
- Traditionally, generative grammars are often described as recognizers. Given a particular string as input, the grammar defines whether or not that string is recognized.
14
-
15
- For example, let’s imagine what a pseudocode grammar representing whole numbers greater than zero might look like.
16
-
17
- ```
18
- start := leading_digit *digit
19
- leading_digit := 1..9
20
- digit := 0..9
21
- ```
22
-
23
- If we could turn this pseudocode grammar into a recognizer function and run it on a range of possible strings, we’d see the following results.
24
-
25
- ```ruby
26
- grammar.parse("1") # => true
27
- grammar.parse("2") # => true
28
- grammar.parse("99") # => true
29
- grammar.parse("111") # => true
30
- grammar.parse("134534") # => true
31
- grammar.parse("0") # => false
32
- grammar.parse("055") # => false
33
- grammar.parse("abc") # => false
34
- grammar.parse("1.5") # => false
35
- ```
36
-
37
- How does it work?
38
-
39
- The grammar here is made up of ‘production rules’, which in turn are made up of named symbols called ‘nonterminals’ and literal patterns called ‘terminals’ which match a range of possible strings.
40
-
41
- In this case, `start`, `leading_digit` and `digit` are nonterminals whereas `1..9` and `0..9` are terminals. By convention, `*` means ‘zero or more’, which specifies that the production can match repeating characters over and over until an unmatched character is found (formally, this is known as the [Kleene star](https://en.wikipedia.org/wiki/Kleene_star)).
42
-
43
- To recognize a string with the grammar, we start with a left hand side nonterminal (by convention, this is known as the start symbol, often named `start`) and substitute it with its right hand side production. We then do the same for the next set of nonterminals we find in the production, until we bottom out at a set of terminals matching the literal string.
44
-
45
- If we walk through
46
-
47
- ```
48
- grammar.parse("1")
49
- ```
50
-
51
- 1. Replace `start` with `leading_digit` then `*digit`
52
- 2. `leading_digit` is a terminal `1..9`, so check that the first character matches
53
- 3. `*digit`
54
-
55
-
56
-
57
- If you’re familiar with regular expressions, you’ll notice that this grammar seems to do exactly the same thing as the following regular expression.
58
-
59
- ```ruby
60
- /^[1-9][0-9]*$/
61
- ```
62
-
63
- Remarkably, this isn’t a coincidence or example of TMTOWTDI. It turns out that there’s a deep symmetry between grammars and regular expressions. Every regular grammar can be transformed into an equivalent regular expression and vice versa.
64
-
65
- ```
66
- Number := Zero | Integer | Decimal | Real
67
- Integer := LeadingDigit *Digit
68
- LeadingDigit := [1-9]
69
- Digit := [0-9]
70
- Decimal := Integer "." *Digit
71
- Real := Integer "/" Integer
72
- Zero := "0"
73
- ```
74
-
75
- The following sequences are recognised as valid by the number grammar:
76
-
77
- - `1`
78
- - `23.424`
79
- - `30000`
80
- - `1/7`
81
-
82
- Template expansion grammars
@@ -1,43 +0,0 @@
1
- ---
2
- title: Contributing to Calyx
3
- layout: docs
4
- permalink: /introduction/contributing/
5
- ---
6
-
7
- # Contributing to Calyx
8
-
9
- Calyx is an open source project and contributions are welcome.
10
-
11
- ## General Contributions
12
-
13
- The best way to contribute is to use the Gem. Install it on a local project and try things out. Does it work? Does it do what you expect? Is there anything missing?
14
-
15
- It’s really helpful to contribute to discussion on open issues, reporting bugs or suggest new features. Any feedback and criticism is received with gratitude.
16
-
17
- ## Code Contributions
18
-
19
- Changes that fix bugs and improve test coverage will generally be merged on-the-spot. Larger changes that introduce new features should harmonise with the vision, goals and style of the project. If in doubt, just ask in advance.
20
-
21
- ### Submitting Changes
22
-
23
- Changes to the source code and documentation should be submitted as a pull request on GitHub, corresponding to the following process:
24
-
25
- - Fork the repo and make a new branch for your changes
26
- - Submit your branch as a pull request against the master branch
27
-
28
- If any aspects of your changes need further explanation, use the pull request description to provide further detail and context (including code samples as necessary).
29
-
30
- Please don’t bump the version as part of your pull request (this happens separately).
31
-
32
- ### Pull Request Checklist
33
-
34
- - Extraneous and trivial small commits should be squashed into larger descriptive commits
35
- - Commits should include concise and clear messages using standard formatting conventions
36
- - The test suite must be passing
37
- - Newly introduced code branches should be covered by tests
38
- -- Introduce new tests if existing tests don’t support your changes
39
- - Changes to method signatures and class organisation should be annotated by doc comments
40
-
41
- ## Code of Conduct
42
-
43
- Please note that this project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms.
@@ -1,129 +0,0 @@
1
- ---
2
- title: Tutorial
3
- layout: docs
4
- permalink: /introduction/tutorial
5
- ---
6
-
7
- ## Objective
8
-
9
- This tutorial introduces Calyx with a basic ‘hello world’ example. Following these steps will help you get Calyx up and running and provide you with a code skeleton to start adding more interesting and creative things.
10
-
11
- ## Initial setup
12
-
13
- Before getting started, you’ll need to install Calyx from RubyGems and have it available in your local dev environment:
14
-
15
- ```
16
- gem install calyx
17
- ```
18
-
19
- If you’re not sure how to do this yet, there’s more information about setting up your Ruby environment in the [resources for beginners](/introduction/beginners/). The [installation guide](/docs/guide/installation/) contains further details about prerequisites and how to download and install the Gem.
20
-
21
- ## Getting started
22
-
23
- Create a file named `hello.rb` and add the following contents:
24
-
25
- ```ruby
26
- require "calyx"
27
-
28
- hello = Calyx::Grammar.new do
29
- start "Hello world!"
30
- end
31
- ```
32
-
33
- The first line imports the Calyx library and the lines following use the `Calyx::Grammar` class to define the rules for the generated text, in this case just ‘Hello world!’.
34
-
35
- To generate the text result, call the `#generate` method on the grammar object. Add this to the bottom of the `hello.rb` file:
36
-
37
- ```ruby
38
- puts hello.generate
39
- ```
40
-
41
- Run it on the command line by typing `ruby hello.rb`. You should see the following result:
42
-
43
- ```
44
- Hello world!
45
- ```
46
-
47
- ## Adding random choices
48
-
49
- Obviously, this hardcoded sentence isn’t very interesting by itself. To add variety to the text, rules can be defined with multiple choices to pick from:
50
-
51
- ```ruby
52
- hello = Calyx::Grammar.new do
53
- start 'Hello world!', 'Hi world!', 'Hey world!'
54
- end
55
- ```
56
-
57
- Each time `#generate` runs, Calyx evaluates the grammar and randomly selects a single choice from the list of possible choices. So if we run the grammar three times, we might see three different results:
58
-
59
- ```ruby
60
- hello.generate
61
- # => Hi world!
62
-
63
- hello.generate
64
- # => Hello world!
65
-
66
- hello.generate
67
- # => Yo world!
68
- ```
69
-
70
- ## Nesting rules inside rules
71
-
72
- When you embed the name of a rule in curly brackets inside a text fragment, Calyx will expand the embedded rule and replace it with generated output each time the grammar runs.
73
-
74
- The following example nests the `greeting` rule within the `start` rule:
75
-
76
- ```ruby
77
- hello = Calyx::Grammar.new do
78
- start '{greeting} world!'
79
- greeting 'Hello', 'Hi', 'Hey', 'Yo'
80
- end
81
- ```
82
-
83
- This generates the exact same text as before, but listing the greeting words on their own is more flexible and eliminates the need to write each variation of the phrase out in full.
84
-
85
- This process of starting with a larger fragment of text and breaking it up into smaller phrases and single words is something you’ll do a lot when writing larger and more detailed grammars.
86
-
87
- ## Using nesting to shape the text
88
-
89
- Rules can be arbitrarily nested and connected to generate larger and more complex texts. The way the rules branch out is going to define the shape and ‘flavor’ of the text.
90
-
91
- For example, to create more exaggerated variations of the phrase, we can branch out to pick from a list of happy adjectives or a list of sad adjectives:
92
-
93
- ```ruby
94
- hello = Calyx::Grammar.new do
95
- start '{greeting} {world_phrase}.'
96
- greeting 'Hello', 'Hi', 'Hey', 'Yo'
97
- world_phrase '{happy_adj} world', '{sad_adj} world', 'world'
98
- happy_adj 'wonderful', 'amazing', 'bright', 'beautiful'
99
- sad_adj 'cruel', 'miserable'
100
- end
101
- ```
102
-
103
- Nesting and branching can be manipulated to balance consistency with novelty. The exact same text fragments can be combined in a variety of ways to produce strikingly different resulting texts.
104
-
105
- The following grammar branches out at the top level, with `happy_phrase` and `sad_phrase` being generated from completely separate trees that don’t overlap:
106
-
107
- ```ruby
108
- hello = Calyx::Grammar.new do
109
- start '{happy_phrase} world.', '{sad_phrase} world.'
110
- happy_phrase '{happy_greeting} {happy_adj}'
111
- happy_greeting 'Hello', 'Hi', 'Hey', 'Yo'
112
- happy_adj 'wonderful', 'amazing', 'bright', 'beautiful'
113
- sad_phrase '{sad_greeting} {sad_adj}'
114
- sad_greeting 'Goodbye', 'So long', 'Farewell'
115
- sad_adj 'cruel', 'miserable'
116
- end
117
- ```
118
-
119
- Whereas this variation of the grammar uses the same content but generates everything from a single branch, resulting in a word salad with happy and sad fragments mashed together:
120
-
121
- ```ruby
122
- hello = Calyx::Grammar.new do
123
- start '{greeting} {adj} world.'
124
- greeting 'Hello', 'Hi', 'Hey', 'Yo', 'Goodbye', 'So long', 'Farewell'
125
- adj 'wonderful', 'amazing', 'bright', 'beautiful', 'cruel', 'miserable'
126
- end
127
- ```
128
-
129
- That’s really all you need to know to get started.