calyx 0.11.3 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b5a355ab937e5afbf5ab76be107bee0f4e0b53a9
4
- data.tar.gz: be8ab43657f9a57fac3644fcb11a7f4c184433aa
3
+ metadata.gz: 19046d53109e4dfe958d0e9e4fd3a3ff2d446109
4
+ data.tar.gz: 4a41b45d945bcb44ea7359db7398d0bdb6c366e8
5
5
  SHA512:
6
- metadata.gz: 30858f8a309bf24795679caaae1f43558e5c4ecc8e356747c35745ecf6a680b18127183814f4cd0b0b8c4c96a6e8ba151b14fec506f56e806f184e037d98c5cc
7
- data.tar.gz: 166bcc17f2e120a8e0cc6b2b95f42696e032c51bcbdfc73d86d0645feefc403a442ddd50f34972f6c1ac3d7a622bb33073e42bf11b2aa0bd52024f169910c707
6
+ metadata.gz: 38527d602bf96335cef8c504612c0d4bfb1fbf17dd459420123ceeb2c088207921e0d68580ec1777cf822476ab4e3a935f8f2b02d2d7834642806a3593f4170c
7
+ data.tar.gz: e49e3d348caaec3290e6412317f31e29054f4dbecce4dbf35c264c2a952fc36c442e1adeb7af2d6444ca7429f82d59f1b2bf504f15dc6967641a383fa09ca18c
@@ -0,0 +1,49 @@
1
+ # Contributing to Calyx
2
+
3
+ Calyx is an open source project and contributions are welcome with the caveat that this is very much a personal creative project by Mark Rickerby, so keep that context in mind if you’re considering drastic code changes.
4
+
5
+ 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.
6
+
7
+ Should Calyx become more popular, these guidelines are likely to become more community-oriented, and I’ll look at handing project stewardship over to the community with a more formal project charter and structure.
8
+
9
+ ## General Contributions
10
+
11
+ 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?
12
+
13
+ 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.
14
+
15
+ ## Code Contributions
16
+
17
+ ### Submitting Changes
18
+
19
+ Changes to the source code and documentation should be submitted as a pull request on GitHub, corresponding to the following process:
20
+
21
+ - Fork the repo and make a new branch for your changes
22
+ - Submit your branch as a pull request against the master branch
23
+
24
+ If any aspects of your changes are ambiguous or unclear, use the pull request description to explain and provide further context (including code samples as necessary).
25
+
26
+ Please don’t bump the version as part of your changes (this happens separately).
27
+
28
+ ### Pull Request Checklist
29
+
30
+ - Extraneous and trivial small commits should be squashed into larger descriptive commits
31
+ - Commits should include concise and clear messages using standard formatting conventions
32
+ - The test suite must be passing
33
+ - Newly introduced code branches should be covered by tests
34
+ -- Introduce new tests if existing tests don’t support your changes
35
+ - Changes to method signatures and class organisation should be annotated by doc comments
36
+
37
+ ## Code of Conduct
38
+
39
+ As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
40
+
41
+ We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion.
42
+
43
+ Examples of unacceptable behaviour by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
44
+
45
+ The maintainer has the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct.
46
+
47
+ Instances of abusive, harassing, or otherwise unacceptable behaviour may be reported by opening an issue or contacting the maintainer.
48
+
49
+ *From the [Contributor Covenant](http://contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/).*
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # Calyx
2
2
 
3
3
  [![Gem Version](http://img.shields.io/gem/v/calyx.svg)](https://rubygems.org/gems/calyx)
4
- [![Build Status](https://travis-ci.org/maetl/calyx.svg?branch=master)](https://travis-ci.org/maetl/calyx)
4
+ [![Build Status](https://img.shields.io/travis/maetl/calyx.svg)](https://travis-ci.org/maetl/calyx)
5
5
 
6
6
  Calyx provides a simple API for generating text with declarative recursive grammars.
7
7
 
@@ -19,6 +19,60 @@ gem install calyx
19
19
  gem 'calyx'
20
20
  ```
21
21
 
22
+ ## Examples
23
+
24
+ The best way to get started quickly is to install the gem and run the examples locally.
25
+
26
+ ## Any Gradient
27
+
28
+ Requires Roda and Rack to be available.
29
+
30
+ ```
31
+ gem install roda
32
+ ```
33
+
34
+ Demonstrates how to use Calyx to construct SVG graphics. **Any Gradient** generates a rectangle with a linear gradient of random colours.
35
+
36
+ Run as a web server and preview the output in a browser (`http://localhost:9292`):
37
+
38
+ ```
39
+ ruby examples/any_gradient.rb
40
+ ```
41
+
42
+ Or generate SVG files via a command line pipe:
43
+
44
+ ```
45
+ ruby examples/any_gradient > gradient1.xml
46
+ ```
47
+
48
+ ## Tiny Woodland Bot
49
+
50
+ Requires the Twitter client gem and API access configured for a specific Twitter handle.
51
+
52
+ ```
53
+ gem install twitter
54
+ ```
55
+
56
+ Demonstrates how to use Calyx to make a minimal Twitter bot that periodically posts unique tweets. See [@tiny_woodland on Twitter](https://twitter.com/tiny_woodland) and the [writeup here](http://maetl.net/notes/storyboard/tiny-woodlands).
57
+
58
+ ```
59
+ TWITTER_CONSUMER_KEY=XXX-XXX
60
+ TWITTER_CONSUMER_SECRET=XXX-XXX
61
+ TWITTER_ACCESS_TOKEN=XXX-XXX
62
+ TWITTER_CONSUMER_SECRET=XXX-XXX
63
+ ruby examples/tiny_woodland_bot.rb
64
+ ```
65
+
66
+ ## Faker
67
+
68
+ [Faker](https://github.com/stympy/faker) is a popular library for generating fake names and associated sample data like internet addresses, company names and locations.
69
+
70
+ This example demonstrates how to use Calyx to reproduce the same functionality using custom lists defined in a YAML configuration file.
71
+
72
+ ```
73
+ ruby examples/faker.rb
74
+ ```
75
+
22
76
  ## Usage
23
77
 
24
78
  Require the library and inherit from `Calyx::Grammar` to construct a set of rules to generate a text.
@@ -231,11 +285,13 @@ Dot-notation is supported in template expressions, allowing you to call any avai
231
285
  ```ruby
232
286
  class Greeting < Calyx::Grammar
233
287
  start '{hello.capitalize} there.', 'Why, {hello} there.'
234
- hello 'hello'
288
+ hello 'hello', 'hi'
235
289
  end
236
290
 
237
291
  # => "Hello there."
292
+ # => "Hi there."
238
293
  # => "Why, hello there."
294
+ # => "Why, hi there."
239
295
  ```
240
296
 
241
297
  You can also extend the grammar with custom modifiers that provide useful formatting functions.
@@ -251,11 +307,13 @@ class Greeting < Calyx::Grammar
251
307
  end
252
308
 
253
309
  start '{hello.shoutycaps} there.', 'Why, {hello} there.'
254
- hello 'hello'
310
+ hello 'hello', 'hi'
255
311
  end
256
312
 
257
313
  # => "HELLO there."
314
+ # => "HI there."
258
315
  # => "Why, HELLO there."
316
+ # => "Why, HI there."
259
317
  ```
260
318
 
261
319
  ### Mappings
@@ -0,0 +1,60 @@
1
+ require 'roda'
2
+ require 'calyx'
3
+
4
+ class AnyGradient < Calyx::Grammar
5
+ html '<body style="margin:0; padding:0">{svg}</body>'
6
+ xml '<?xml version="1.0" encoding="utf-8"?>{svg}'
7
+ svg '
8
+ <svg width="100%"
9
+ height="100%"
10
+ version="1.1"
11
+ xmlns="http://www.w3.org/2000/svg"
12
+ xmlns:xlink="http://www.w3.org/1999/xlink">
13
+ {defs}
14
+ {rect}
15
+ </svg>
16
+ '
17
+ defs '
18
+ <defs>
19
+ {linear_gradient}
20
+ </defs>
21
+ '
22
+ linear_gradient '
23
+ <linearGradient id="linearGradient-1">
24
+ {stop_fixed}
25
+ {stop_offset}
26
+ </linearGradient>
27
+ '
28
+ stop_fixed '<stop stop-color="{stop_color}" offset="0%"></stop>'
29
+ stop_offset '<stop stop-color="{stop_color}" offset="{offset}"></stop>'
30
+ stop_color '#{hex_num}{hex_num}{hex_num}'
31
+ hex_num '{hex_val}{hex_val}'
32
+ hex_val '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
33
+ offset '{tens}{ones}%'
34
+ tens 3,4,5,6
35
+ ones 1,2,3,4,5,6,7,8,9,0
36
+ rect '
37
+ <rect id="gradient"
38
+ stroke="none"
39
+ fill="url(#linearGradient-1)"
40
+ fill-rule="evenodd"
41
+ x="0"
42
+ y="0"
43
+ width="100%"
44
+ height="100%"></rect>
45
+ '
46
+ end
47
+
48
+ class Server < Roda
49
+ route do |r|
50
+ r.root do
51
+ AnyGradient.new.generate(:html)
52
+ end
53
+ end
54
+ end
55
+
56
+ if STDOUT.tty?
57
+ Rack::Server.start :app => Server
58
+ else
59
+ STDOUT.puts AnyGradient.new.generate(:xml)
60
+ end
@@ -0,0 +1,31 @@
1
+ require "calyx"
2
+ require "twitter"
3
+ require "logger"
4
+
5
+ tiny_woodland = Calyx::Grammar.new do
6
+ start :field
7
+ field (0..7).map { "{row}{br}" }.join
8
+ row (0..12).map { "{point}" }.join
9
+ point trees: 0.6, foliage: 0.35, flowers: 0.05
10
+ trees "🌲", "🌳"
11
+ foliage "🌿", "🌱"
12
+ flowers "🌷", "🌻", "🌼"
13
+ creatures "🐗", "🐻", "🐝", "🐦"
14
+ br "\n"
15
+ end
16
+
17
+ twitter_client = Twitter::REST::Client.new do |config|
18
+ config.consumer_key = ENV["TWITTER_CONSUMER_KEY"]
19
+ config.consumer_secret = ENV["TWITTER_CONSUMER_SECRET"]
20
+ config.access_token = ENV["TWITTER_ACCESS_TOKEN"]
21
+ config.access_token_secret = ENV["TWITTER_CONSUMER_SECRET"]
22
+ end
23
+
24
+ logger = Logger.new(STDOUT)
25
+
26
+ begin
27
+ tweet = twitter_client.update(tiny_woodland.generate)
28
+ logger.info("Posted tweet: https://twitter.com/#{tweet.user.name}/status/#{tweet.id}")
29
+ rescue Exception => e
30
+ logger.error(e)
31
+ end
@@ -98,10 +98,13 @@ module Calyx
98
98
  # Grammar rules can be constructed on the fly when the passed-in block is
99
99
  # evaluated.
100
100
  #
101
- # @param [Number] seed
102
- def initialize(seed=nil, &block)
103
- @seed = seed || Random.new_seed
104
- srand(@seed)
101
+ # @param [Number, Random] seed
102
+ def initialize(seed=Random.new, &block)
103
+ if seed.is_a?(Numeric)
104
+ @rng = Random.new(seed)
105
+ else
106
+ @rng = seed
107
+ end
105
108
 
106
109
  if block_given?
107
110
  @registry = Registry.new
@@ -120,7 +123,7 @@ module Calyx
120
123
  def generate(*args)
121
124
  start_symbol, rules_map = map_default_args(*args)
122
125
 
123
- @registry.evaluate(start_symbol, rules_map).flatten.reject do |obj|
126
+ @registry.evaluate(start_symbol, @rng, rules_map).flatten.reject do |obj|
124
127
  obj.is_a?(Symbol)
125
128
  end.join(''.freeze)
126
129
  end
@@ -134,7 +137,7 @@ module Calyx
134
137
  def evaluate(*args)
135
138
  start_symbol, rules_map = map_default_args(*args)
136
139
 
137
- @registry.evaluate(start_symbol, rules_map)
140
+ @registry.evaluate(start_symbol, @rng, rules_map)
138
141
  end
139
142
 
140
143
  private
@@ -35,8 +35,8 @@ module Calyx
35
35
  # Evaluate the choice by randomly picking one of its possible options.
36
36
  #
37
37
  # @return [Array]
38
- def evaluate
39
- [:choice, @collection.sample.evaluate]
38
+ def evaluate(rng)
39
+ [:choice, @collection.sample(random: rng).evaluate(rng)]
40
40
  end
41
41
  end
42
42
  end
@@ -51,9 +51,9 @@ module Calyx
51
51
  # into a single result.
52
52
  #
53
53
  # @return [Array]
54
- def evaluate
54
+ def evaluate(rng)
55
55
  concat = @expansion.reduce([]) do |exp, atom|
56
- exp << atom.evaluate
56
+ exp << atom.evaluate(rng)
57
57
  end
58
58
 
59
59
  [:concat, concat]
@@ -18,8 +18,8 @@ module Calyx
18
18
  # returning the transformed result.
19
19
  #
20
20
  # @return [Array]
21
- def evaluate
22
- terminal = @production.evaluate.flatten.reject { |o| o.is_a?(Symbol) }.join(''.freeze)
21
+ def evaluate(rng)
22
+ terminal = @production.evaluate(rng).flatten.reject { |o| o.is_a?(Symbol) }.join(''.freeze)
23
23
  expression = @methods.reduce(terminal) do |value, method|
24
24
  @registry.transform(method, value)
25
25
  end
@@ -18,7 +18,7 @@ module Calyx
18
18
  # Evaluate the memo, using the registry to handle the expansion.
19
19
  #
20
20
  # @return [Array]
21
- def evaluate
21
+ def evaluate(rng)
22
22
  [@symbol, @registry.memoize_expansion(@symbol)]
23
23
  end
24
24
  end
@@ -16,8 +16,8 @@ module Calyx
16
16
  # Evaluate the non-terminal, using the registry to handle the expansion.
17
17
  #
18
18
  # @return [Array]
19
- def evaluate
20
- [@symbol, @registry.expand(@symbol).evaluate]
19
+ def evaluate(rng)
20
+ [@symbol, @registry.expand(@symbol).evaluate(rng)]
21
21
  end
22
22
  end
23
23
  end
@@ -12,7 +12,7 @@ module Calyx
12
12
  # Evaluate the terminal by returning its identity directly.
13
13
  #
14
14
  # @return [Array]
15
- def evaluate
15
+ def evaluate(rng)
16
16
  [:atom, @atom]
17
17
  end
18
18
  end
@@ -30,6 +30,7 @@ module Calyx
30
30
  # Initialize a new choice with a list of child nodes.
31
31
  #
32
32
  # @param [Array] collection
33
+ # @param [Random] rng
33
34
  def initialize(collection)
34
35
  @collection = collection
35
36
  end
@@ -41,12 +42,12 @@ module Calyx
41
42
  # of code recommended in the Ruby standard library documentation.
42
43
  #
43
44
  # @return [Array]
44
- def evaluate
45
+ def evaluate(rng)
45
46
  choice = @collection.max_by do |_, weight|
46
- rand ** (1.0 / weight)
47
+ rng.rand ** (1.0 / weight)
47
48
  end.first
48
49
 
49
- [:weighted_choice, choice.evaluate]
50
+ [:weighted_choice, choice.evaluate(rng)]
50
51
  end
51
52
  end
52
53
  end
@@ -1,7 +1,7 @@
1
1
  module Calyx
2
2
  # Lookup table of all the available rules in the grammar.
3
3
  class Registry
4
- attr_reader :rules, :transforms, :modifiers
4
+ attr_reader :rng, :rules, :transforms, :modifiers
5
5
 
6
6
  # Construct an empty registry.
7
7
  def initialize
@@ -78,7 +78,7 @@ module Calyx
78
78
  #
79
79
  # @param [Symbol] symbol
80
80
  def memoize_expansion(symbol)
81
- memos[symbol] ||= expand(symbol).evaluate
81
+ memos[symbol] ||= expand(symbol).evaluate(@rng)
82
82
  end
83
83
 
84
84
  # Merges the given registry instance with the target registry.
@@ -99,8 +99,8 @@ module Calyx
99
99
  # @param [Symbol] start_symbol
100
100
  # @param [Hash] rules_map
101
101
  # @return [Array]
102
- def evaluate(start_symbol=:start, rules_map={})
103
- reset_evaluation_context
102
+ def evaluate(start_symbol=:start, rng=Random.new, rules_map={})
103
+ reset_evaluation_context(rng)
104
104
 
105
105
  rules_map.each do |key, value|
106
106
  if rules.key?(key.to_sym)
@@ -117,7 +117,7 @@ module Calyx
117
117
  expansion = expand(start_symbol)
118
118
 
119
119
  if expansion.respond_to?(:evaluate)
120
- [start_symbol, expansion.evaluate]
120
+ [start_symbol, expansion.evaluate(rng)]
121
121
  else
122
122
  raise Errors::MissingRule.new(start_symbol)
123
123
  end
@@ -125,9 +125,10 @@ module Calyx
125
125
 
126
126
  private
127
127
 
128
- attr_reader :memos, :context
128
+ attr_reader :rng, :memos, :context
129
129
 
130
- def reset_evaluation_context
130
+ def reset_evaluation_context(rng)
131
+ @rng = rng
131
132
  @context = {}
132
133
  @memos = {}
133
134
  end
@@ -1,3 +1,3 @@
1
1
  module Calyx
2
- VERSION = '0.11.3'.freeze
2
+ VERSION = '0.12.0'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: calyx
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.3
4
+ version: 0.12.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mark Rickerby
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-08-07 00:00:00.000000000 Z
11
+ date: 2016-09-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -62,13 +62,15 @@ extra_rdoc_files: []
62
62
  files:
63
63
  - ".gitignore"
64
64
  - ".travis.yml"
65
+ - CONTRIBUTING.md
65
66
  - Gemfile
66
67
  - LICENSE
67
68
  - README.md
68
69
  - calyx.gemspec
70
+ - examples/any_gradient.rb
69
71
  - examples/faker.rb
70
72
  - examples/faker.yml
71
- - examples/tiny_woodland.rb
73
+ - examples/tiny_woodland_bot.rb
72
74
  - lib/calyx.rb
73
75
  - lib/calyx/errors.rb
74
76
  - lib/calyx/format.rb
@@ -103,7 +105,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
103
105
  version: '0'
104
106
  requirements: []
105
107
  rubyforge_project:
106
- rubygems_version: 2.4.5
108
+ rubygems_version: 2.5.1
107
109
  signing_key:
108
110
  specification_version: 4
109
111
  summary: Generate text with declarative recursive grammars
@@ -1,15 +0,0 @@
1
- require "calyx"
2
-
3
- tiny_woodland = Calyx::Grammar.new do
4
- start :field
5
- field (0..7).map { "{row}{br}" }.join
6
- row (0..18).map { "{point}" }.join
7
- point [:trees, 0.2], [:foliage, 0.25], [:flowers, 0.05], [:space, 0.5]
8
- trees "🌲", "🌳"
9
- foliage "🌿", "🌱"
10
- flowers "🌷", "🌻", "🌼"
11
- space " "
12
- br "\n"
13
- end
14
-
15
- puts tiny_woodland.generate