Class: Jejune::Manager
Constant Summary
Constants included
from JString
JString::DOUBLE_ESC, JString::ESC_RX
Constants included
from Utils
Utils::JJS_EXTS
Constants included
from Constants
Constants::BROWSERS, Constants::CATCH_TYPES, Constants::CODE, Constants::DEFAULT_EXT, Constants::DELIMS, Constants::EXPRESSION_TYPES, Constants::FUNCTION_TYPES, Constants::OPEN_DELIM, Constants::OPERATOR_PRECEDENCE, Constants::PROPERTY_DEFINITION_TYPES, Constants::PROPERTY_TYPES
Instance Attribute Summary collapse
Attributes included from JString
#tab_width
Instance Method Summary
collapse
-
#add_dependency(path) ⇒ Object
-
#add_to_path(*directories) ⇒ Object
-
#cache_file(path) ⇒ Object
-
#commit_dependencies(file, deps) ⇒ Object
-
#compress(source, type = 'js') ⇒ Object
-
#define_macro(node) ⇒ Object
-
#expand_macro(name, *parameters) ⇒ Object
-
#find_library(name, system = false) ⇒ Object
-
#find_path(name, exts = DEFAULT_EXT) ⇒ Object
-
#find_relative(name, exts = DEFAULT_EXT) ⇒ Object
-
#find_resource(name, ext, system = false) ⇒ Object
-
#include!(lib) ⇒ Object
-
#initialize(*args) ⇒ Manager
constructor
A new instance of Manager.
-
#interpolate(blob, outdent = false) ⇒ Object
-
#load!(lib, system = false) ⇒ Object
-
#load_file(path) ⇒ Object
-
#loaded?(path) ⇒ Boolean
-
#log(message, color = 33) ⇒ Object
-
#parse(tokens, *args) ⇒ Object
-
#require!(lib, system = lib !~ /^[\.\/\~]/) ⇒ Object
-
#set_root_file(file, options = {}) ⇒ Object
-
#set_root_source(source, options = {}) ⇒ Object
-
#translate(input = @root_input, options = nil) ⇒ Object
-
#with_input(input) ⇒ Object
Methods included from JString
#collapse, #expand_tabs, #jstring, #outdent, #quote, #split_words, #string_value, #utf8
Methods included from Utils
ArgumentError, find_in_directory, find_in_path_list, jejune_file?, parse_ext_list
Constructor Details
#initialize(*args) ⇒ Manager
Returns a new instance of Manager.
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
# File 'lib/jejune/manager.rb', line 38
def initialize( *args )
options = {}
args.last.is_a?( Hash ) and options.update( args.pop )
@root_input = args.shift
@data_directory = File.expand_path( '~/.jejune' )
test( ?d, @data_directory ) or Dir.mkdir( @data_directory )
@cache_directory = File.join( @data_directory, 'cache' )
test( ?d, @cache_directory ) or Dir.mkdir( @cache_directory )
@input = nil
@input_stack = []
@load_path = options.fetch( :load_path, [] )
@load_path = [ @load_path ].flatten
@load_path.compact!
@loaded_files = {}
@translator = Translator.new( self )
@browser = options[ :browser ]
@location_markers = options.fetch( :location_markers, true )
@macros = options.fetch( :macros, {} )
@verbose = options.fetch( :verbose, false )
@dependency_map = {}
end
|
Instance Attribute Details
#browser ⇒ Object
Returns the value of attribute browser.
33
34
35
|
# File 'lib/jejune/manager.rb', line 33
def browser
@browser
end
|
#data_directory ⇒ Object
Returns the value of attribute data_directory.
32
33
34
|
# File 'lib/jejune/manager.rb', line 32
def data_directory
@data_directory
end
|
#dependency_map ⇒ Object
Returns the value of attribute dependency_map.
32
33
34
|
# File 'lib/jejune/manager.rb', line 32
def dependency_map
@dependency_map
end
|
Returns the value of attribute input.
32
33
34
|
# File 'lib/jejune/manager.rb', line 32
def input
@input
end
|
#load_path ⇒ Object
Returns the value of attribute load_path.
32
33
34
|
# File 'lib/jejune/manager.rb', line 32
def load_path
@load_path
end
|
#location_markers=(value) ⇒ Object
Sets the attribute location_markers
33
34
35
|
# File 'lib/jejune/manager.rb', line 33
def location_markers=(value)
@location_markers = value
end
|
#macros ⇒ Object
Returns the value of attribute macros.
32
33
34
|
# File 'lib/jejune/manager.rb', line 32
def macros
@macros
end
|
Returns the value of attribute root_input.
33
34
35
|
# File 'lib/jejune/manager.rb', line 33
def root_input
@root_input
end
|
#translator ⇒ Object
Returns the value of attribute translator.
32
33
34
|
# File 'lib/jejune/manager.rb', line 32
def translator
@translator
end
|
#verbose ⇒ Object
Returns the value of attribute verbose.
33
34
35
|
# File 'lib/jejune/manager.rb', line 33
def verbose
@verbose
end
|
Instance Method Details
#add_dependency(path) ⇒ Object
229
230
231
232
233
|
# File 'lib/jejune/manager.rb', line 229
def add_dependency( path )
full_path = File.expand_path( path )
@input and @input.dependencies.add( full_path )
@input_stack.each { | f | f.dependencies.add( full_path ) }
end
|
#add_to_path(*directories) ⇒ Object
72
73
74
75
|
# File 'lib/jejune/manager.rb', line 72
def add_to_path( *directories )
directories = [ directories ].flatten!.map! { | i | i.to_s }
@load_path.unshift( *directories )
end
|
#cache_file(path) ⇒ Object
110
111
112
113
|
# File 'lib/jejune/manager.rb', line 110
def cache_file( path )
id = MD5.hexdigest( File.expand_path( path ) << "\0" << @browser.to_s )
File.join( @cache_directory, id )
end
|
#commit_dependencies(file, deps) ⇒ Object
217
218
219
|
# File 'lib/jejune/manager.rb', line 217
def commit_dependencies( file, deps )
@dependency_map[ file ] = deps.to_a
end
|
#compress(source, type = 'js') ⇒ Object
198
199
200
201
202
203
204
205
|
# File 'lib/jejune/manager.rb', line 198
def compress( source, type = 'js' )
command = %W( yui-compressor --type #{ type } ).join( ' ' )
Open3.popen3( command ) do | inp, out, err |
inp.write source
inp.close
return out.read
end
end
|
#define_macro(node) ⇒ Object
65
66
67
68
69
70
|
# File 'lib/jejune/manager.rb', line 65
def define_macro( node )
macro = Macro.new( self, node )
@macros[ macro.name ] = macro
@input and @input.macros[ macro.name ] = macro
return macro
end
|
#expand_macro(name, *parameters) ⇒ Object
171
172
173
174
|
# File 'lib/jejune/manager.rb', line 171
def expand_macro( name, *parameters )
macro = @macros[ name.to_s ] or raise MacroNotFound.new( name.to_s )
macro.expand( *parameters )
end
|
#find_library(name, system = false) ⇒ Object
102
103
104
105
106
107
|
# File 'lib/jejune/manager.rb', line 102
def find_library( name, system = false )
unless path = system ? find_path( name ) : find_relative( name )
raise( "cannot locate file `#{ name }'" )
end
return path
end
|
#find_path(name, exts = DEFAULT_EXT) ⇒ Object
87
88
89
|
# File 'lib/jejune/manager.rb', line 87
def find_path( name, exts = DEFAULT_EXT )
find_in_path_list( @load_path, name, exts )
end
|
#find_relative(name, exts = DEFAULT_EXT) ⇒ Object
98
99
100
|
# File 'lib/jejune/manager.rb', line 98
def find_relative( name, exts = DEFAULT_EXT )
find_in_directory( @input ? @input.directory : File.expand_path( '.' ), name, exts )
end
|
#find_resource(name, ext, system = false) ⇒ Object
91
92
93
94
95
96
|
# File 'lib/jejune/manager.rb', line 91
def find_resource( name, ext, system = false )
unless path = system ? find_path( name, ext ) : find_relative( name, ext )
raise( "cannot locate file `#{ name }' (exts = #{ ext })" )
end
return path
end
|
#include!(lib) ⇒ Object
160
161
162
|
# File 'lib/jejune/manager.rb', line 160
def include!( lib )
require!( lib, false )
end
|
#interpolate(blob, outdent = false) ⇒ Object
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
|
# File 'lib/jejune/manager.rb', line 235
def interpolate( blob, outdent = false )
segments = []
s = SourceScanner.new(
blob.data, :file => blob.file, :line => blob.line, :column => blob.data_column
)
indent = nil
margin = true
nlines = 0
until s.eos?
case
when s.scan( /#(?:(\{)|([@%\$][\$\w]*))/ )
if s[ 1 ]
tks = s.lexer { | lx | lx.tokenize_until_balanced( LBRACE, RBRACE ) }
tree = parse( tks, :source_name => blob.file )
segments << [ ?c, translate( tree ) ]
elsif variable = s[ 2 ]
case variable[ 0 ]
when ?$
segments << [ ?c, variable ]
when ?@
variable.length > 1 or raise( "syntax error -- expected variable name: `#{ s.matched }'" )
segments << [ ?c, 'this.' << variable[ 1, variable.length ] ]
when ?%
variable.length > 1 or raise( "syntax error -- expected variable name: `#{ s.matched }'" )
segments << [ ?c, variable[ 1, variable.length ] ]
else
raise( "BUG: this shouldn't happen" )
end
else
raise( "BUG: this shouldn't happen" )
end
when s.scan( /\r?\n(?:\s*\r?\n)* / )
nl = s.matched
nlines += nl.count( "\n" )
if last = segments.last and last[ 0 ] == ?s
last[ 1 ] << nl
else
segments << [ ?s, nl ]
end
if leading_space = s.check( /^\s*(?=(\S))/ )
margin &&= ( s[ 1 ] == '|' )
n = expand_tabs( leading_space ).length
indent = indent ? n < indent ? n : indent : n
end
when s.scan( %r<(?: [^\\\r\n\#]+ | (?: \\ \\ )+ | \\ \r? \n | \\ . | \# (?! [\{\$@%] ))+>mx )
if last = segments.last and last[ 0 ] == ?s
last[ 1 ] << s.matched
else
segments << [ ?s, s.matched ]
end
else
msg = "BUG: this shouldn't happen!\n"
msg << ( '= ' * 30 ) << "\n"
msg << blob.inspect << "\n"
msg << ( '= ' * 30 ) << "\n"
msg << s.inspect
raise( msg )
end
end
if outdent and nlines > 0
if first = segments.first and first[ 0 ] == ?s
first[ 1 ].sub!( /\A[ \t]*\r?\n/, '' )
first.empty? and segments.shift
end
if last = segments.last and last[ 0 ] == ?s
last[ 1 ].sub!( /\r?\n[ \t]*\z/, '' )
last.empty? and segments.pop
end
for type, text in segments
if type == ?s
margin ? text.gsub!( /(\r?\n)[ \t]*\|[ \t]?/, '\1' ) :
text.gsub!( /(\r?\n)([ \t]*)/ ) { $1 << $2[ indent, $2.length ].to_s }
end
end
end
case segments.length
when 0 then %q("")
when 1
type, text = segments.first
type == ?s ? jstring( text ) : "(#{ text }).toString()"
else
segments.map! { | type, text | type == ?s ? jstring( text ) : text.strip }
%([#{ segments.join( ',' ) }].join(''))
end
end
|
#load!(lib, system = false) ⇒ Object
164
165
166
167
168
169
|
# File 'lib/jejune/manager.rb', line 164
def load!( lib, system = false )
path = find_library( lib, system )
@input and @input.dependencies.add( File.expand_path( path ) )
log( "load! #{ path.inspect }" )
jejune_file?( path ) ? load_file( path ) : File.read( path )
end
|
#load_file(path) ⇒ Object
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
|
# File 'lib/jejune/manager.rb', line 119
def load_file( path )
log( "cache check - #{ path }", 34 )
full_path = File.expand_path( path )
add_dependency( full_path )
@loaded_files.fetch( full_path ) do
cache = cache_file( full_path )
output = nil
begin
if test( ?f, cache ) and test( ?>, cache, path )
data = Marshal.load( File.read( cache ) )
for depend in data[ :dependencies ]
unless test( ?f, depend ) and test( ?>, cache, depend )
raise "no cache"
end
end
data[ :macros ].each_value { | macro | macro.manager = self }
@macros.update( data[ :macros ] )
return( @loaded_files[ full_path ] = data[ :output ] )
end
rescue => e
end
@loaded_files[ full_path ] = JJSFile.new( path, :manager => self, :cache_file => cache )
end
end
|
#loaded?(path) ⇒ Boolean
115
116
117
|
# File 'lib/jejune/manager.rb', line 115
def loaded?( path )
@loaded_files.has_key?( File.expand_path( path ) )
end
|
#log(message, color = 33) ⇒ Object
328
329
330
|
# File 'lib/jejune/manager.rb', line 328
def log( message, color = 33 )
@verbose and $stderr.puts( "\e[#{ color }m#{ message }\e[0m" )
end
|
#parse(tokens, *args) ⇒ Object
207
208
209
210
211
212
213
214
215
|
# File 'lib/jejune/manager.rb', line 207
def parse( tokens, *args )
options = args.last.is_a?( Hash ) ? args.pop : {}
rule = args.pop || options[ :rule ] || :program
stream = RewriteStream.new( tokens, options )
adaptor = RewriteAdaptor.new( stream )
parser = Parser.new( stream, :adaptor => adaptor )
parser.send( rule ).tree
end
|
#require!(lib, system = lib !~ /^[\.\/\~]/) ⇒ Object
153
154
155
156
157
158
|
# File 'lib/jejune/manager.rb', line 153
def require!( lib, system = lib !~ /^[\.\/\~]/ )
path = find_library( lib, system )
@input and @input.dependencies.add( File.expand_path( path ) )
log( "require! #{ path.inspect }" )
jejune_file?( path ) ? loaded?( path ) ? nil : load_file( path ) : File.read( path )
end
|
#set_root_file(file, options = {}) ⇒ Object
77
78
79
80
|
# File 'lib/jejune/manager.rb', line 77
def set_root_file( file, options = {} )
options[ :manager ] = self
@root_input = JJSFile.new( file, options )
end
|
#set_root_source(source, options = {}) ⇒ Object
82
83
84
85
|
# File 'lib/jejune/manager.rb', line 82
def set_root_source( source, options = {} )
options[ :manager ] = self
@root_input = JJSSource.new( source, options )
end
|
#translate(input = @root_input, options = nil) ⇒ Object
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
|
# File 'lib/jejune/manager.rb', line 176
def translate( input = @root_input, options = nil )
case input
when RewriteTree
@translator.translate( input )
when JJSInput
log( "translating #{ input.path }" )
with_input( input ) do
@translator.translate( input.tree )
end
when IO, ARGF
options ||= {}
options[ :manager ] = self
input = JJSFile.new( input, options )
translate( input )
when String
options ||= {}
options[ :manager ] = self
input = JJSSource.new( input, options )
translate( input )
end
end
|
221
222
223
224
225
226
227
|
# File 'lib/jejune/manager.rb', line 221
def with_input( input )
@input_stack.push( @input ) if @input
@input = input
yield self
ensure
@input = @input_stack.pop
end
|