inversion 1.3.1 → 1.4.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.
Files changed (98) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/Examples.md +134 -0
  4. data/GettingStarted.md +50 -0
  5. data/Guide.md +14 -0
  6. data/{History.rdoc → History.md} +52 -43
  7. data/{README.rdoc → README.md} +43 -34
  8. data/Tags.md +555 -0
  9. data/bin/inversion +4 -8
  10. data/lib/inversion/cli/api.rb +75 -0
  11. data/lib/inversion/cli/tagtokens.rb +34 -0
  12. data/lib/inversion/cli/tree.rb +70 -0
  13. data/lib/inversion/cli.rb +406 -0
  14. data/lib/inversion/exceptions.rb +0 -1
  15. data/lib/inversion/mixins.rb +10 -11
  16. data/lib/inversion/parser.rb +5 -6
  17. data/lib/inversion/refinements.rb +18 -0
  18. data/lib/inversion/renderstate.rb +24 -25
  19. data/lib/inversion/sinatra.rb +0 -1
  20. data/lib/inversion/template/attrtag.rb +7 -5
  21. data/lib/inversion/template/begintag.rb +0 -1
  22. data/lib/inversion/template/calltag.rb +0 -1
  23. data/lib/inversion/template/codetag.rb +37 -28
  24. data/lib/inversion/template/commenttag.rb +0 -1
  25. data/lib/inversion/template/configtag.rb +3 -4
  26. data/lib/inversion/template/containertag.rb +1 -2
  27. data/lib/inversion/template/defaulttag.rb +1 -2
  28. data/lib/inversion/template/elsetag.rb +0 -1
  29. data/lib/inversion/template/elsiftag.rb +0 -1
  30. data/lib/inversion/template/endtag.rb +2 -3
  31. data/lib/inversion/template/escapetag.rb +1 -2
  32. data/lib/inversion/template/fortag.rb +2 -3
  33. data/lib/inversion/template/fragmenttag.rb +1 -2
  34. data/lib/inversion/template/iftag.rb +3 -1
  35. data/lib/inversion/template/importtag.rb +2 -3
  36. data/lib/inversion/template/includetag.rb +1 -2
  37. data/lib/inversion/template/node.rb +4 -5
  38. data/lib/inversion/template/pptag.rb +1 -2
  39. data/lib/inversion/template/publishtag.rb +2 -3
  40. data/lib/inversion/template/rescuetag.rb +1 -2
  41. data/lib/inversion/template/subscribetag.rb +3 -4
  42. data/lib/inversion/template/tag.rb +3 -4
  43. data/lib/inversion/template/textnode.rb +1 -2
  44. data/lib/inversion/template/timedeltatag.rb +1 -2
  45. data/lib/inversion/template/unlesstag.rb +0 -1
  46. data/lib/inversion/template/uriencodetag.rb +1 -2
  47. data/lib/inversion/template/yieldtag.rb +0 -1
  48. data/lib/inversion/template.rb +18 -22
  49. data/lib/inversion/tilt.rb +1 -2
  50. data/lib/inversion.rb +2 -3
  51. data/spec/helpers.rb +19 -13
  52. data/spec/inversion/mixins_spec.rb +1 -1
  53. data/spec/inversion/monkeypatches_spec.rb +1 -1
  54. data/spec/inversion/parser_spec.rb +1 -1
  55. data/spec/inversion/renderstate_spec.rb +1 -1
  56. data/spec/inversion/sinatra_spec.rb +1 -1
  57. data/spec/inversion/template/attrtag_spec.rb +1 -1
  58. data/spec/inversion/template/begintag_spec.rb +1 -1
  59. data/spec/inversion/template/calltag_spec.rb +1 -1
  60. data/spec/inversion/template/codetag_spec.rb +24 -1
  61. data/spec/inversion/template/commenttag_spec.rb +1 -1
  62. data/spec/inversion/template/configtag_spec.rb +1 -1
  63. data/spec/inversion/template/containertag_spec.rb +1 -1
  64. data/spec/inversion/template/defaulttag_spec.rb +1 -1
  65. data/spec/inversion/template/elsetag_spec.rb +1 -1
  66. data/spec/inversion/template/elsiftag_spec.rb +1 -1
  67. data/spec/inversion/template/endtag_spec.rb +1 -1
  68. data/spec/inversion/template/escapetag_spec.rb +1 -1
  69. data/spec/inversion/template/fortag_spec.rb +1 -1
  70. data/spec/inversion/template/fragmenttag_spec.rb +1 -1
  71. data/spec/inversion/template/iftag_spec.rb +1 -1
  72. data/spec/inversion/template/importtag_spec.rb +1 -1
  73. data/spec/inversion/template/includetag_spec.rb +1 -1
  74. data/spec/inversion/template/node_spec.rb +1 -1
  75. data/spec/inversion/template/pptag_spec.rb +1 -1
  76. data/spec/inversion/template/publishtag_spec.rb +1 -1
  77. data/spec/inversion/template/rescuetag_spec.rb +1 -1
  78. data/spec/inversion/template/subscribetag_spec.rb +1 -1
  79. data/spec/inversion/template/tag_spec.rb +1 -1
  80. data/spec/inversion/template/textnode_spec.rb +1 -1
  81. data/spec/inversion/template/timedeltatag_spec.rb +1 -1
  82. data/spec/inversion/template/unlesstag_spec.rb +1 -1
  83. data/spec/inversion/template/uriencodetag_spec.rb +1 -1
  84. data/spec/inversion/template/yieldtag_spec.rb +1 -1
  85. data/spec/inversion/template_spec.rb +1 -1
  86. data/spec/inversion/tilt_spec.rb +1 -1
  87. data/spec/inversion_spec.rb +1 -1
  88. data.tar.gz.sig +0 -0
  89. metadata +59 -45
  90. metadata.gz.sig +0 -0
  91. data/Examples.rdoc +0 -134
  92. data/GettingStarted.rdoc +0 -44
  93. data/Guide.rdoc +0 -47
  94. data/Manifest.txt +0 -86
  95. data/Rakefile +0 -7
  96. data/Tags.rdoc +0 -560
  97. data/lib/inversion/command.rb +0 -278
  98. data/lib/inversion/monkeypatches.rb +0 -21
@@ -1,278 +0,0 @@
1
- # -*- ruby -*-
2
- # frozen_string_literal: true
3
- # vim: set noet nosta sw=4 ts=4 :
4
-
5
- require 'logger'
6
- require 'trollop'
7
- require 'highline'
8
- require 'sysexits'
9
- require 'shellwords'
10
-
11
- require 'inversion' unless defined?( Inversion )
12
-
13
-
14
- # Command class for the 'inversion' command-line tool.
15
- class Inversion::Command
16
- extend Sysexits
17
-
18
- # The list of valid subcommands
19
- SUBCOMMANDS = %w[api tagtokens tree]
20
-
21
- # Class-instance variable for the HighLine prompt object
22
- @prompt = nil
23
-
24
-
25
- ### Run the command
26
- def self::run( args )
27
- opts, args = self.parse_options( args )
28
- subcommand = args.shift
29
-
30
- command = self.new( opts )
31
- command.run( subcommand, args )
32
- rescue => err
33
- $stderr.puts "%p: %s" % [ err.class, err.message ]
34
- $stderr.puts( err.backtrace.join("\n ") ) if opts && opts.debug
35
- end
36
-
37
-
38
- ### Fetch the HighLine instance for the command, creating it if necessary.
39
- def self::prompt
40
- unless @prompt
41
- @prompt = HighLine.new
42
- @prompt.page_at = @prompt.output_rows - 5
43
- @prompt.wrap_at = @prompt.output_cols - 2
44
- end
45
-
46
- @prompt
47
- end
48
-
49
-
50
- ### Create an option parser for the command and return it
51
- def self::create_option_parser
52
- pr = self.prompt
53
- progname = pr.color( File.basename($0), :bold, :yellow )
54
-
55
- return Trollop::Parser.new do
56
- version Inversion.version_string( true )
57
-
58
- banner (<<-END_BANNER).gsub(/^\t+/, '')
59
- #{progname} OPTIONS SUBCOMMAND ARGS
60
-
61
- Run the specified SUBCOMMAND with the given ARGS.
62
- END_BANNER
63
- text ''
64
-
65
- stop_on( *SUBCOMMANDS )
66
- text pr.color('Subcommands', :bold, :white)
67
- text pr.list( SUBCOMMANDS, :columns_across )
68
- text ''
69
-
70
- text pr.color('Inversion Config', :bold, :white)
71
- opt :ignore_unknown_tags, "Ignore unknown tags instead of displaying an error"
72
- opt :path, "Add one or more directories to the template search path",
73
- :type => :string, :multi => true
74
- text ''
75
-
76
-
77
- text pr.color('Other Options', :bold, :white)
78
- opt :debug, "Enable debugging output"
79
- end
80
- end
81
-
82
-
83
- ### Parse the given command line +args+, returning a populated options struct
84
- ### and any remaining arguments.
85
- def self::parse_options( args )
86
- oparser = self.create_option_parser
87
- opts = oparser.parse( args )
88
-
89
- if oparser.leftovers.empty?
90
- $stderr.puts "No subcommand given.\nUsage: "
91
- oparser.educate( $stderr )
92
- exit :usage
93
- end
94
- args.replace( oparser.leftovers )
95
-
96
- return opts, args
97
- rescue Trollop::HelpNeeded
98
- oparser.educate( $stderr )
99
- exit :ok
100
- rescue Trollop::VersionNeeded
101
- $stderr.puts( oparser.version )
102
- exit :ok
103
- end
104
-
105
-
106
- ### Create a new instance of the command that will use the specified +opts+
107
- ### to parse and dump info about the given +templates+.
108
- def initialize( opts )
109
- @opts = opts
110
- @prompt = self.class.prompt
111
-
112
- # Configure logging
113
- Loggability.level = opts.debug ? :debug : :error
114
- Loggability.format_with( :color ) if $stdin.tty?
115
-
116
- # Configure Inversion's strictness
117
- Inversion::Template.configure(
118
- :ignore_unknown_tags => opts.ignore_unknown_tags,
119
- :template_paths => opts.path,
120
- )
121
- end
122
-
123
-
124
- ######
125
- public
126
- ######
127
-
128
- # The command-line options
129
- attr_reader :opts
130
-
131
- # The command's prompt object (HighLine)
132
- attr_reader :prompt
133
-
134
-
135
- ### Run the given +subcommand+ with the specified +args+.
136
- def run( subcommand, args )
137
- case subcommand.to_sym
138
- when :tree
139
- self.dump_node_trees( args )
140
- when :api
141
- self.describe_templates( args )
142
- when :tagtokens
143
- self.dump_tokens( args )
144
- else
145
- self.output_error( "No such command #{subcommand.dump}" )
146
- end
147
- end
148
-
149
-
150
- ### Load the Inversion::Template from the specified +tmplpath+ and return it. If there
151
- ### is an error loading the template, output the error and return +nil+.
152
- def load_template( tmplpath )
153
- template = Inversion::Template.load( tmplpath )
154
- return template
155
- rescue Errno => err
156
- self.prompt.say "Failed to load %s: %s" % [ tmplpath, err.message ]
157
- rescue Inversion::ParseError => err
158
- self.prompt.say "%s: Invalid template: %p: %s" %
159
- [ tmplpath, err.class, err.message ]
160
- self.prompt.say( err.backtrace.join("\n ") ) if self.opts.debug
161
- end
162
-
163
-
164
- ### Dump the node tree of the given +templates+.
165
- def dump_node_trees( templates )
166
- templates.each do |path|
167
- template = self.load_template( path )
168
- self.output_blank_line
169
- self.output_template_header( template )
170
- self.output_template_nodes( template.node_tree )
171
- end
172
- end
173
-
174
-
175
- ### Output the given +tree+ of nodes at the specified +indent+ level.
176
- def output_template_nodes( tree, indent=0 )
177
- indenttxt = ' ' * indent
178
- tree.each do |node|
179
- self.prompt.say( indenttxt + node.as_comment_body )
180
- self.output_template_nodes( node.subnodes, indent+4 ) if node.is_container?
181
- end
182
- end
183
-
184
-
185
- ### Output a description of the templates.
186
- def describe_templates( templates )
187
- templates.each do |path|
188
- template = self.load_template( path )
189
- self.output_blank_line
190
- self.output_template_header( template )
191
- self.describe_template_api( template )
192
- self.describe_publications( template )
193
- self.describe_subscriptions( template )
194
- end
195
- end
196
-
197
-
198
- ### Output a header between each template.
199
- def output_template_header( template )
200
- header_info = "%s (%0.2fK, %s)" %
201
- [ template.source_file, template.source.bytesize/1024.0, template.source.encoding ]
202
- header_line = "-- %s" % [ header_info ]
203
- self.prompt.say( self.prompt.color(header_line, :bold, :white) )
204
- end
205
-
206
-
207
- ### Output a description of the +template+'s attributes, subscriptions, etc.
208
- def describe_template_api( template )
209
- attrs = template.attributes.keys.map( &:to_s )
210
- return if attrs.empty?
211
-
212
- self.output_subheader "%d Attribute/s" % [ attrs.length ]
213
- self.output_list( attrs.sort )
214
- self.output_blank_line
215
- end
216
-
217
-
218
- ### Output a list of sections the template publishes.
219
- def describe_publications( template )
220
- ptags = template.node_tree.find_all {|node| node.is_a?(Inversion::Template::PublishTag) }
221
- return if ptags.empty?
222
-
223
- pubnames = ptags.map( &:key ).map( &:to_s ).uniq.sort
224
- self.output_subheader "%d Publication/s" % [ pubnames.length ]
225
- self.output_list( pubnames )
226
- self.output_blank_line
227
- end
228
-
229
-
230
- ### Output a list of sections the template subscribes to.
231
- def describe_subscriptions( template )
232
- stags = template.node_tree.find_all {|node| node.is_a?(Inversion::Template::SubscribeTag) }
233
- return if stags.empty?
234
-
235
- subnames = stags.map( &:key ).map( &:to_s ).uniq.sort
236
- self.output_subheader "%d Subscription/s" % [ subnames.length ]
237
- self.output_list( subnames )
238
- self.output_blank_line
239
- end
240
-
241
-
242
- ### Attempt to parse the given +code+ and dump its tokens as a tagpattern.
243
- def dump_tokens( args )
244
- code = args.join(' ')
245
-
246
- require 'ripper'
247
- tokens = Ripper.lex( code ).collect do |(pos, tok, text)|
248
- "%s<%p>" % [ tok.to_s.sub(/^on_/,''), text ]
249
- end.join(' ')
250
-
251
- self.prompt.say( tokens )
252
- end
253
-
254
-
255
- ### Display a columnar list.
256
- def output_list( columns )
257
- self.prompt.say( self.prompt.list(columns, :columns_down) )
258
- end
259
-
260
-
261
- ### Display an error message.
262
- def output_error( message )
263
- self.prompt.say( self.prompt.color(message, :red) )
264
- end
265
-
266
-
267
- ### Output a subheader with the given +caption+.
268
- def output_subheader( caption )
269
- self.prompt.say( self.prompt.color(caption, :cyan) )
270
- end
271
-
272
-
273
- ### Output a blank line
274
- def output_blank_line
275
- self.prompt.say( "\n" )
276
- end
277
-
278
- end # class Inversion::Command
@@ -1,21 +0,0 @@
1
- # -*- ruby -*-
2
- # frozen_string_literal: true
3
- # vim: set noet nosta sw=4 ts=4 :
4
-
5
- require 'inversion' unless defined?( Inversion )
6
- require 'ripper'
7
-
8
- # Monkeypatch mixin to expose the 'tokens' instance variable of
9
- # Ripper::TokenPattern::MatchData. Included in Ripper::TokenPattern::MatchData.
10
- module Inversion::RipperAdditions
11
-
12
- # the array of token tuples
13
- attr_reader :tokens
14
-
15
- end
16
-
17
- # :stopdoc:
18
- class Ripper::TokenPattern::MatchData
19
- include Inversion::RipperAdditions
20
- end
21
-