tickly 2.0.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/Gemfile CHANGED
@@ -1,6 +1,6 @@
1
1
  source "http://rubygems.org"
2
2
 
3
- gem "bychar", "~> 1.2"
3
+ gem 'bychar', '~> 2'
4
4
 
5
5
  # Add dependencies to develop your gem here.
6
6
  # Include everything needed to run rake, tests, features, etc.
@@ -3,14 +3,14 @@
3
3
  A highly simplistic TCL parser and evaluator (primarily designed for parsing Nuke scripts). It structures
4
4
  the passed Nuke scripts into a TCL AST and return it. You can use some cheap tricks to discard the nodes you are not interested in.
5
5
 
6
- == Parsing
6
+ == Plain parsing
7
7
 
8
8
  Create a Parser object and pass TCL expressions/scripts to it. You can pass IO obejcts or strings. Note that parse()
9
9
  will always return an Array of expressions, even if you only fed it one expression line. For example:
10
10
 
11
11
  p = Tickly::Parser.new
12
12
 
13
- # One expression, even if it's invalid (2 is not a valid TCL bareword)- doesn't matter
13
+ # One expression, even if it's invalid (2 is not a valid TCL bareword - doesn't matter)
14
14
  p.parse '2' #=> [["2"]]
15
15
 
16
16
  # TCL command
@@ -35,40 +35,61 @@ Multiple expressions separated by ; or a newline will be accumulated as multiple
35
35
  Lots and lots of TCL features are not supported - remember that most Nuke scripts are machine-generated and they do not
36
36
  use most of the esoteric language features.
37
37
 
38
- == Evaulating
38
+ == Evaulating nodes in Nuke scripts
39
39
 
40
- Nuke uses the following syntax for it's nodes:
40
+ What you are likely to use Tickly for is parsing Nuke scripts. They got multiple node definitions, which
41
+ are actially arguments for a node constructor written out in TCL. Consider this ubiquitous fragment for a
42
+ hypothetic SomeNode in your script:
41
43
 
42
44
  SomeNode {
43
45
  someknob 15
44
46
  anotherknob 3
45
- andanother {curve x1 12 45 67}
47
+ animation {curve x1 12 45 67}
48
+ x_pos 123
49
+ y_pos -10
46
50
  }
47
51
 
48
- and so on. You can use a simple Evaluator object to run through the nodes returned by the parser. To set up
49
- the evaulation you need to create classes matching the node classes by name. For example, a Blur class:
52
+ and so on. You can use a NodeProcessor to capture these node constructors right as they are being parsed.
50
53
 
51
- class Blur
54
+ All the nodes you are not interested in will be discarded, which matters in terms of memory use.
55
+
56
+ To do it you need to create Ruby classes matching the node classes by name. For example, for that SomeNode
57
+ of ours:
58
+
59
+ class SomeNode
60
+ attr_reader :knobs
52
61
  def initialize(string_keyed_knobs_hash)
62
+ @knobs = string_keyed_knobs_hash
53
63
  end
54
64
  end
55
65
 
56
- e = Tickly::Evaluator.new
66
+ # Instantiate a new processor
67
+ e = Tickly::NodeProcessor.new
68
+
69
+ # Add the class
57
70
  e.add_node_handler_class Blur
58
71
 
59
- some_script_expressions = Tickly::Parser.new.parse(File.open("/mnt/raid/nuke/scripts/HugeShot_123.nk"))
72
+ file = File.open("/mnt/raid/nuke/scripts/HugeShot_123.nk")
60
73
 
61
- some_script_expressions.each do | expression_in_ast |
62
- # Everytime a Blur node is found in the script it will be instantiated,
74
+ e.parse(file) do | every_some_node |
75
+ # Everytime a SomeNode is found in the script it will be instantiated,
63
76
  # and the knobs of the node will be passed to the constructor that you define
64
- e.evaluate(expression_in_ast) do | blur_node |
65
- # Now a Blur node instance is all yours
66
- end
77
+ x_position = every_some_node.knobs["x_pos"]
78
+ ...
67
79
  end
68
80
 
81
+ If you are curious, this is how Tracksperanto parses various nodes containing tracking data:
82
+
83
+ parser = Tickly::NodeProcessor.new
84
+ parser.add_node_handler_class(Tracker3)
85
+ parser.add_node_handler_class(Reconcile3D)
86
+ parser.add_node_handler_class(PlanarTracker1_0)
87
+ parser.add_node_handler_class(Tracker4)
88
+
69
89
  == Animation curves
70
90
 
71
91
  You can parse Nuke's animation curves using Tickly::Curve. This will give you a way to iterate over every defined keyframe.
92
+ This currently does not happen automatically for things passing through the parser.
72
93
 
73
94
  == Contributing to tickly
74
95
 
@@ -4,7 +4,7 @@ require File.dirname(__FILE__) + "/tickly/curve"
4
4
  require File.dirname(__FILE__) + "/tickly/node_processor"
5
5
 
6
6
  module Tickly
7
- VERSION = '2.0.0'
7
+ VERSION = '2.1.0'
8
8
 
9
9
  # Provides the methods for quickly emitting the expression arrays,
10
10
  # is used in tests
@@ -19,7 +19,7 @@ module Tickly
19
19
  def parse(io_or_str)
20
20
  bare_io = io_or_str.respond_to?(:read) ? io_or_str : StringIO.new(io_or_str)
21
21
  # Wrap the IO in a Bychar buffer to read faster
22
- reader = Bychar::Reader.new(bare_io)
22
+ reader = Bychar.wrap(bare_io)
23
23
  # Use multiple_expressions = true so that the top-level parsed script is always an array
24
24
  # of expressions
25
25
  sub_parse(reader, stop_char = nil, stack_depth = 0, multiple_expressions = true)
@@ -27,7 +27,10 @@ module Tickly
27
27
 
28
28
  # Override this to remove any unneeded subexpressions.
29
29
  # Return the modified expression. If you return nil, the result
30
- # will not be added to the expression list
30
+ # will not be added to the expression list. You can also use this
31
+ # method for bottom-up expression evaluation, returning the result
32
+ # of the expression being evaluated. This method will be first called
33
+ # for the innermost expressions and then proceed up the call stack.
31
34
  def compact_subexpr(expr, at_depth)
32
35
  expr
33
36
  end
@@ -62,7 +65,7 @@ module Tickly
62
65
  last_char_was_linebreak = false
63
66
 
64
67
  no_eof do
65
- char = io.read_one_byte!
68
+ char = io.read_one_char!
66
69
 
67
70
  if char == stop_char # Bail out of a subexpr
68
71
  # Handle any remaining subexpressions
@@ -114,14 +117,14 @@ module Tickly
114
117
  def no_eof(&blk)
115
118
  begin
116
119
  loop(&blk)
117
- rescue Bychar::EOFError
120
+ rescue Bychar::EOF
118
121
  end
119
122
  end
120
123
 
121
124
  def parse_str(io, stop_char)
122
125
  buf = ''
123
126
  no_eof do
124
- c = io.read_one_byte!
127
+ c = io.read_one_char!
125
128
  if c == stop_char && buf[LAST_CHAR] != ESC
126
129
  return buf
127
130
  elsif buf[LAST_CHAR] == ESC # Eat out the escape char
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "tickly"
8
- s.version = "2.0.0"
8
+ s.version = "2.1.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Julik Tarkhanov"]
12
- s.date = "2013-03-21"
12
+ s.date = "2013-03-23"
13
13
  s.description = "Parses the subset of the TCL grammar needed for Nuke scripts"
14
14
  s.email = "me@julik.nl"
15
15
  s.extra_rdoc_files = [
@@ -55,14 +55,14 @@ Gem::Specification.new do |s|
55
55
  s.specification_version = 3
56
56
 
57
57
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
58
- s.add_runtime_dependency(%q<bychar>, ["~> 1.2"])
58
+ s.add_runtime_dependency(%q<bychar>, ["~> 2"])
59
59
  s.add_development_dependency(%q<rake>, [">= 0"])
60
60
  s.add_development_dependency(%q<shoulda>, [">= 0"])
61
61
  s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
62
62
  s.add_development_dependency(%q<jeweler>, ["~> 1.8.3"])
63
63
  s.add_development_dependency(%q<ruby-prof>, [">= 0"])
64
64
  else
65
- s.add_dependency(%q<bychar>, ["~> 1.2"])
65
+ s.add_dependency(%q<bychar>, ["~> 2"])
66
66
  s.add_dependency(%q<rake>, [">= 0"])
67
67
  s.add_dependency(%q<shoulda>, [">= 0"])
68
68
  s.add_dependency(%q<rdoc>, ["~> 3.12"])
@@ -70,7 +70,7 @@ Gem::Specification.new do |s|
70
70
  s.add_dependency(%q<ruby-prof>, [">= 0"])
71
71
  end
72
72
  else
73
- s.add_dependency(%q<bychar>, ["~> 1.2"])
73
+ s.add_dependency(%q<bychar>, ["~> 2"])
74
74
  s.add_dependency(%q<rake>, [">= 0"])
75
75
  s.add_dependency(%q<shoulda>, [">= 0"])
76
76
  s.add_dependency(%q<rdoc>, ["~> 3.12"])
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tickly
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-03-21 00:00:00.000000000 Z
12
+ date: 2013-03-23 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bychar
@@ -18,7 +18,7 @@ dependencies:
18
18
  requirements:
19
19
  - - ~>
20
20
  - !ruby/object:Gem::Version
21
- version: '1.2'
21
+ version: '2'
22
22
  type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
@@ -26,7 +26,7 @@ dependencies:
26
26
  requirements:
27
27
  - - ~>
28
28
  - !ruby/object:Gem::Version
29
- version: '1.2'
29
+ version: '2'
30
30
  - !ruby/object:Gem::Dependency
31
31
  name: rake
32
32
  requirement: !ruby/object:Gem::Requirement
@@ -157,7 +157,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
157
157
  version: '0'
158
158
  segments:
159
159
  - 0
160
- hash: 4279008670880210764
160
+ hash: -720429447261605785
161
161
  required_rubygems_version: !ruby/object:Gem::Requirement
162
162
  none: false
163
163
  requirements: