proteus 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. data/COPYING +674 -0
  2. data/README +88 -0
  3. data/Rakefile +33 -0
  4. data/bin/pro +189 -0
  5. data/lib/ClassParser.rb +84 -0
  6. data/lib/ComponentClass.rb +51 -0
  7. data/lib/ComponentInstance.rb +76 -0
  8. data/lib/DefinitionHelper.rb +157 -0
  9. data/lib/DefinitionParser.rb +107 -0
  10. data/lib/Facade.rb +116 -0
  11. data/lib/FileHelper.rb +80 -0
  12. data/lib/InputParser.rb +241 -0
  13. data/lib/InstanceParser.rb +65 -0
  14. data/lib/InstanceProxy.rb +100 -0
  15. data/lib/PropertyHash.rb +64 -0
  16. data/lib/TemplateRenderer.rb +128 -0
  17. data/lib/exceptions.rb +50 -0
  18. data/test/spec/ClassParser_spec.rb +314 -0
  19. data/test/spec/ComponentClass_spec.rb +44 -0
  20. data/test/spec/ComponentInstance_spec.rb +50 -0
  21. data/test/spec/DefinitionHelper_spec.rb +134 -0
  22. data/test/spec/DefinitionParser_spec.rb +236 -0
  23. data/test/spec/Facade_spec.rb +44 -0
  24. data/test/spec/FileHelper_spec.rb +113 -0
  25. data/test/spec/InputParser_spec.rb +424 -0
  26. data/test/spec/InstanceParser_spec.rb +125 -0
  27. data/test/spec/TemplateRenderer_spec.rb +54 -0
  28. data/test/spec/lib/NS1/TestComponent10.def +4 -0
  29. data/test/spec/lib/NS1/TestComponent11.def +4 -0
  30. data/test/spec/lib/NS1/TestComponent4.def +4 -0
  31. data/test/spec/lib/NS1/TestComponent5.def +4 -0
  32. data/test/spec/lib/NS1/TestComponent8.def +4 -0
  33. data/test/spec/lib/NS1/TestComponent9.def +4 -0
  34. data/test/spec/lib/NS2/TestComponent6.def +4 -0
  35. data/test/spec/lib/TestComponent1.def +4 -0
  36. data/test/spec/lib/TestComponent3.def +4 -0
  37. data/test/spec/test_lib_dir1/File1.def +0 -0
  38. data/test/spec/test_lib_dir1/File3.def +0 -0
  39. data/test/spec/test_lib_dir1/NS1/File4.def +0 -0
  40. data/test/spec/test_lib_dir1/NS1/NS2/File5.def +0 -0
  41. data/test/spec/test_lib_dir2/File1.def +0 -0
  42. data/test/spec/test_lib_dir2/File2.def +0 -0
  43. metadata +113 -0
data/README ADDED
@@ -0,0 +1,88 @@
1
+
2
+
3
+
4
+ Welcome to Proteus
5
+
6
+
7
+
8
+ Proteus is an abstraction of general document definition and display markup that
9
+ allows you to create and reuse complex patterns of structured content.
10
+
11
+ The purpose of Proteus is to allow you to describe documents in terms of their
12
+ content, abstracting away from the often cumbersome markup or syntax of its
13
+ native form (for example in HTML).
14
+
15
+
16
+ Project Goals:
17
+
18
+ 1. Content-orientation: we should be describing content, not the structure
19
+ used to display it.
20
+ 2. Human-readability: it should be easy for a human to write and maintain
21
+ documents.
22
+ 3. Flexibility: it should be easy to adapt the solution to solve a wide
23
+ variety of problems.
24
+ 4. Extensibility: it should be easy to change the behaviour of the system as
25
+ it is required.
26
+
27
+
28
+ For Users:
29
+
30
+ Proteus works by interpreting document definitions in YAML, for example:
31
+
32
+ Form:
33
+ - Control:
34
+ name: name
35
+ - Control:
36
+ name: age
37
+ - Control:
38
+ name: gender
39
+ type: select
40
+ options:
41
+ - male
42
+ - female
43
+
44
+ Each camelcase node indicates a "component" - a piece of content which displays
45
+ in a unique way. In the above example, the "Form" and "Control" nodes are
46
+ components and the rest of the information describes those components.
47
+
48
+
49
+ For Developers:
50
+
51
+ Proteus provides a simple system for describing new component types that
52
+ permits inheritance and composition of existing types, again in human readable
53
+ syntax. This allows users to create custom languages from existing components
54
+ quickly and easily.
55
+
56
+
57
+ The Name:
58
+
59
+ In Greek mythology, Proteus is an early sea-god who can foretell the future
60
+ and change his shape. From this feature of Proteus comes the adjective protean,
61
+ with the general meaning of "versatile", "mutable", "capable of assuming many
62
+ forms". -- Wikipedia
63
+
64
+
65
+ Homepage:
66
+
67
+ More information is available on the Proteus website,
68
+
69
+ proteus.rubyforge.org
70
+
71
+ or on Github,
72
+
73
+ github.com/wmadden/proteus
74
+
75
+
76
+ Licensing:
77
+ Proteus is free software: you can redistribute it and/or modify it under the
78
+ terms of the GNU General Public License as published by the Free Software
79
+ Foundation, either version 3 of the License, or (at your option) any later
80
+ version.
81
+
82
+ Proteus is distributed in the hope that it will be useful, but WITHOUT ANY
83
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
84
+ PARTICULAR PURPOSE. See the GNU General Public License for more details.
85
+
86
+ You should have received a copy of the GNU General Public License along with
87
+ Proteus. If not, see <http://www.gnu.org/licenses/>.
88
+
@@ -0,0 +1,33 @@
1
+
2
+ require 'rubygems'
3
+ require 'cucumber/rake/task'
4
+
5
+ require 'rake'
6
+ require 'spec/rake/spectask'
7
+
8
+ desc "Run all examples with RCov"
9
+ Spec::Rake::SpecTask.new(:spec) do |t|
10
+ t.spec_files = FileList['test/spec/**/*.rb']
11
+ t.rcov = true
12
+ t.rcov_opts = ['--exclude', 'spec']
13
+ t.rcov_dir = 'coverage/spec/'
14
+ end
15
+
16
+ require 'spec/rake/verify_rcov'
17
+
18
+ RCov::VerifyTask.new(:verify_rcov => :spec) do |t|
19
+ t.threshold = 100.0
20
+ t.index_html = 'coverage/spec/verify/index.html'
21
+ end
22
+
23
+ Cucumber::Rake::Task.new(:features) do |t|
24
+ t.cucumber_opts = "--format pretty"
25
+ t.rcov = true
26
+ t.rcov_opts << %[-o "test/features/cucumber"]
27
+ end
28
+
29
+ task :doc do |t|
30
+ `rdoc -aUd src/ -o doc/api`
31
+ end
32
+
33
+ task :default => [:spec, :features, :verify_rcov]
data/bin/pro ADDED
@@ -0,0 +1,189 @@
1
+ #!/usr/bin/ruby
2
+ ################################################################################
3
+ # proteus
4
+ #
5
+ # Executable interface to the system.
6
+ # -----------------------------------------------------------------------------
7
+ # (C) Copyright 2009 William Madden
8
+ #
9
+ # This file is part of Proteus.
10
+ #
11
+ # Proteus is free software: you can redistribute it and/or modify it under the
12
+ # terms of the GNU General Public License as published by the Free Software
13
+ # Foundation, either version 3 of the License, or (at your option) any later
14
+ # version.
15
+ #
16
+ # Proteus is distributed in the hope that it will be useful, but WITHOUT ANY
17
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
18
+ # A PARTICULAR PURPOSE. See the GNU General Public License for more details.
19
+ #
20
+ # You should have received a copy of the GNU General Public License along with
21
+ # Proteus. If not, see <http://www.gnu.org/licenses/>.
22
+ ################################################################################
23
+
24
+ require 'getoptlong'
25
+ require 'rdoc/usage'
26
+
27
+ require 'Facade.rb'
28
+ require 'TemplateRenderer.rb'
29
+ require 'exceptions.rb'
30
+
31
+ include Proteus
32
+
33
+ PROTEUS_VERSION = "v0.9.0"
34
+
35
+ USAGE =
36
+ """
37
+ Usage:
38
+ proteus [--path PATH] FILE
39
+ proteus --inline COMPONENT [--props PROPERTIES] [CHILDREN]
40
+ proteus --help
41
+
42
+ Options:
43
+ --help, -h Display this message.
44
+
45
+ --inline, -i Parse inline. Takes component information on the
46
+ command line and outputs the rendered component
47
+ instance.
48
+
49
+ --path, -p Sets the path to search for component definitions.
50
+ Defaults to /usr/lib/proteus.
51
+
52
+ --props, -P Sets the properties for an inline component.
53
+
54
+ --no-current, -C Don't add current directory to path.
55
+
56
+ --version, -V Output version.
57
+
58
+ """
59
+
60
+ PROTEUS_PATH = 'PROTEUS_PATH'
61
+
62
+ def exit_error( error )
63
+ puts error
64
+ puts USAGE
65
+ exit( 1 )
66
+ end
67
+
68
+ def parse_props( props )
69
+ result = {}
70
+
71
+ props.split( ',' ).each do |prop|
72
+ pair = prop.split(':')
73
+ result[ pair[0] ] = pair[1]
74
+ end
75
+
76
+ return result
77
+ end
78
+
79
+
80
+ def parse_command_line
81
+
82
+ @opts.each do |opt, arg|
83
+ case opt
84
+ when '--help', '-h'
85
+ puts( USAGE )
86
+ exit( 0 )
87
+ when '--inline', '-i'
88
+ @inline = true
89
+ when '--props', '-P'
90
+ @props = parse_props( arg )
91
+ when '--path', '-p'
92
+ @path = arg
93
+ when '--namespace', '-n'
94
+ @current_ns = arg
95
+ when '--no-current', '-C'
96
+ @exclude_current = true
97
+ when '--version', '-V'
98
+ puts( PROTEUS_VERSION )
99
+ exit( 0 )
100
+ end
101
+ end
102
+
103
+ end
104
+
105
+ #------------------------------
106
+ # ENTRY POINT
107
+ #------------------------------
108
+
109
+ # Option variables
110
+ @inline = false
111
+ @path = ENV[ PROTEUS_PATH ] || FileHelper::DEFAULT_PATH
112
+ @props = {}
113
+ @current_ns = []
114
+ @exclude_current = false
115
+
116
+ # Valid options
117
+ @opts = GetoptLong.new(
118
+ [ '--help', '-h', GetoptLong::NO_ARGUMENT ],
119
+ [ '--path', '-p', GetoptLong::REQUIRED_ARGUMENT ],
120
+ [ '--inline', '-i', GetoptLong::NO_ARGUMENT ],
121
+ [ '--props', '-P', GetoptLong::REQUIRED_ARGUMENT ],
122
+ [ '--namespace', '-n', GetoptLong::REQUIRED_ARGUMENT ],
123
+ [ '--no-current', '-C', GetoptLong::NO_ARGUMENT ],
124
+ [ '--version', '-V', GetoptLong::NO_ARGUMENT ]
125
+ )
126
+
127
+ # Parse command line
128
+ parse_command_line
129
+
130
+ # Set up system
131
+ facade = Facade.new
132
+
133
+ facade.path = @path + ':.'
134
+
135
+ # Initialize renderer
136
+ renderer = TemplateRenderer.new
137
+
138
+ # Parse input
139
+ if not @inline
140
+
141
+ # from file
142
+
143
+ if ARGV.length < 1
144
+ exit_error( "Error: no target given." )
145
+ elsif ARGV.length > 1
146
+ exit_error( "Error: multiple targets given." )
147
+ end
148
+
149
+ file = ARGV[0]
150
+
151
+ tree = facade.parse_file( file, @current_ns )
152
+
153
+ puts renderer.render( tree )
154
+
155
+ else
156
+
157
+ # from command line
158
+
159
+ if ARGV.length < 1
160
+ exit_error( "Error: no component identifier given." )
161
+ end
162
+
163
+ component_id = ARGV[0]
164
+
165
+ ARGV.shift
166
+ component_children = ARGV
167
+
168
+ component_properties = @props
169
+
170
+ class_path = facade.input_parser.parse_component_id( component_id )
171
+
172
+ begin
173
+ component_class = facade.definition_helper.get_class( class_path,
174
+ @current_ns )
175
+ rescue Exceptions::DefinitionUnavailable
176
+ exit_error( "Error: no definition found for '" + component_id + "'." )
177
+ end
178
+
179
+ component_children = facade.input_parser.parse_yaml( component_children,
180
+ @current_ns )
181
+
182
+ instance = ComponentInstance.new( component_class, component_properties,
183
+ component_children )
184
+
185
+ facade.input_parser.parse_instance( instance, @current_ns )
186
+
187
+ puts renderer.render( instance )
188
+
189
+ end
@@ -0,0 +1,84 @@
1
+ ################################################################################
2
+ # ClassParser.rb
3
+ #
4
+ # Responsible for interpreting YAML for component classes.
5
+ # -----------------------------------------------------------------------------
6
+ # (C) Copyright 2009 William Madden
7
+ #
8
+ # This file is part of Proteus.
9
+ #
10
+ # Proteus is free software: you can redistribute it and/or modify it under the
11
+ # terms of the GNU General Public License as published by the Free Software
12
+ # Foundation, either version 3 of the License, or (at your option) any later
13
+ # version.
14
+ #
15
+ # Proteus is distributed in the hope that it will be useful, but WITHOUT ANY
16
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
17
+ # A PARTICULAR PURPOSE. See the GNU General Public License for more details.
18
+ #
19
+ # You should have received a copy of the GNU General Public License along with
20
+ # Proteus. If not, see <http://www.gnu.org/licenses/>.
21
+ ################################################################################
22
+
23
+ require File.expand_path( File.join(File.dirname(__FILE__), 'exceptions.rb') )
24
+ require File.expand_path( File.join(File.dirname(__FILE__), 'ComponentClass.rb') )
25
+
26
+
27
+ module Proteus
28
+
29
+ #
30
+ # Provides functions for parsing component definitions (for component
31
+ # classes).
32
+ #
33
+ class ClassParser
34
+
35
+ # The regex for valid class names
36
+ @@CLASS_RE = /^([A-Z][a-zA-Z_0-9]*)(?:[\s]*<[\s]*([A-Z][a-zA-Z_0-9]*))?$/
37
+ @@CHILDREN = "children"
38
+
39
+ #---------------------------------------------------------------------------
40
+ #
41
+ # Methods
42
+ #
43
+ #---------------------------------------------------------------------------
44
+
45
+ public
46
+
47
+ #
48
+ # Parses YAML and returns the resultant component class.
49
+ #
50
+ # yaml: the YAML to parse
51
+ # new_class: the class instance to parse
52
+ #
53
+ def parse_yaml( yaml, new_class = nil )
54
+ result = new_class || ComponentClass.new
55
+
56
+ # Must be a hash of length one containing a hash
57
+ if not ( yaml.is_a?(Hash) and yaml.length == 1 and
58
+ (yaml.values[0].nil? or yaml.values[0].is_a?(Hash)) ) then
59
+
60
+ raise Exceptions::DefinitionMalformed, "Class definition malformed"
61
+ end
62
+
63
+ # Parse the class name
64
+ name = yaml.keys[0]
65
+ match = @@CLASS_RE.match( name )
66
+
67
+ # If there's no match, the definition is malformed
68
+ if match.nil?
69
+ raise Exceptions::DefinitionMalformed,
70
+ "Class identifier '" + name + "' malformed."
71
+ end
72
+
73
+ # Set properties of class
74
+ result.name = match[1]
75
+ result.parent = match[2]
76
+ result.properties = yaml.values[0] || {}
77
+ result.children = result.properties.delete(@@CHILDREN) || []
78
+
79
+ return result
80
+ end
81
+
82
+ end
83
+
84
+ end
@@ -0,0 +1,51 @@
1
+ ################################################################################
2
+ # ComponentClass.rb
3
+ #
4
+ # Represents an class of component.
5
+ # -----------------------------------------------------------------------------
6
+ # (C) Copyright 2009 William Madden
7
+ #
8
+ # This file is part of Proteus.
9
+ #
10
+ # Proteus is free software: you can redistribute it and/or modify it under the
11
+ # terms of the GNU General Public License as published by the Free Software
12
+ # Foundation, either version 3 of the License, or (at your option) any later
13
+ # version.
14
+ #
15
+ # Proteus is distributed in the hope that it will be useful, but WITHOUT ANY
16
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
17
+ # A PARTICULAR PURPOSE. See the GNU General Public License for more details.
18
+ #
19
+ # You should have received a copy of the GNU General Public License along with
20
+ # Proteus. If not, see <http://www.gnu.org/licenses/>.
21
+ ################################################################################
22
+
23
+ module Proteus
24
+
25
+ class ComponentClass
26
+
27
+ DEFAULT_CLASS = ComponentClass.new()
28
+
29
+ #---------------------------------------------------------------------------
30
+ #
31
+ # Constructor
32
+ #
33
+ #---------------------------------------------------------------------------
34
+
35
+ def initialize( )
36
+ @properties = {}
37
+ @children = []
38
+ end
39
+
40
+ #---------------------------------------------------------------------------
41
+ #
42
+ # Properties
43
+ #
44
+ #---------------------------------------------------------------------------
45
+
46
+ attr_accessor :name, :namespace, :parent, :properties, :children
47
+
48
+ end
49
+
50
+ end
51
+