tickly 2.0.0 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
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: