lib/masterview/initializer.rb in masterview-0.2.4 vs lib/masterview/initializer.rb in masterview-0.2.5

- old
+ new

@@ -42,10 +42,13 @@ #-- # todo - change configuration to accomodate non-file based storage, use MIOTree objects # [JJB 13-Jun-2006] #++ # + +require 'date' + module MasterView # A Configuration holds all the configuration settings used the # MasterView::Initializer to configure the template engine. # @@ -74,11 +77,10 @@ # config.template_dst_dir_path = "masterview/output" # #...set other config options... # MasterView::Initializer.run( :process, config ) # class Configuration - # directory in which the MasterView plugin or gem is installed attr_reader :mv_installation_dir #:nodoc: # root directory of MasterView itself and the built-in directives # This is lib/masterview w/in the plugin or gem installation directory. @@ -321,10 +323,11 @@ attr_accessor :handle_parse_exceptions # Default option settings for template parsing (a hash) # :tidy => false - run tidy before parsing (tidy_path must be set if enabled) # :escape_erb => true - escapes <% %> before parsing + # :default_generate => true - adds in mv:generate="{template_path}" if none found attr_accessor :default_parser_options # Path on this system to tidy library if <tt>:tidy</tt> parser option is enabled # so that masterview templates will be run through tidy before being parsed. # Allows invalid xhmtl to be corrected before masterview template parsing is performed. @@ -411,10 +414,16 @@ # setting is false, enable rails app to read rhtml(erb) directly from MasterView cache # bypassing the serialization to the file system. # Default: +false+ attr_accessor :generate_rhtml_files + # These are the original default parser options, whatever is set in the config + # will be merged with these to arrive at the result. This allows us to easily + # add new defaults in and even if users empty this hash, the defaults will get added + # to disable they specifically set something to false or nil + OriginalDefaultParserOptions = { :tidy => false, :escape_erb => true, :default_generate => true } # :nodoc: save the originals + # Create a new Configuration instance, initialized with the default # values. # # Optional arguments to the constructor allow for initializing defaults # for a rails app when not actually running rails or for initializing @@ -427,17 +436,23 @@ # # The +app_root_path+ and +rails_app_root_path+ arguments are mutually exclusive. # Use +rails_app_root_path+ when operating on a Rails application which # isn't actually running; use +app_root_path+ for a non-rails application. # + + # list of [ :log_level, msg ] pairs for config initialization/validation messages + # used by the initializer to validate load path and report any problems + attr_accessor :initialization_messages #:nodoc: + ####:invalid_directive_paths + def initialize( params={} ) + rails_env = (defined?(RAILS_ENV)) ? RAILS_ENV : nil # unpack the supported keyword args app_root_path = params[:app_root_path] rails_app_root_path = params[:rails_app_root_path] - env = params[:environment] - + env = params[:environment] || rails_env is_development = env == 'development' program_root_path = File.expand_path( '.' ) #assert program_root_path == Dir.pwd @@ -554,13 +569,13 @@ STDOUT.puts "...template_dst_dir_path=#{template_dst_dir_path || 'nil'}" if debug_TRACE_HACK # template parsing options self.handle_parse_exceptions = true - self.default_parser_options = { :tidy => false, :escape_erb => true } + self.default_parser_options = OriginalDefaultParserOptions.clone #we'll merge in whatever changes they make over the original set in const above # default locations where tidy likely to be found; assume on user's PATH if on Windows - self.tidy_path = RUBY_PLATFORM =~ /mswin32/ ? 'tidy.exe' : '/usr/lib/libtidy.so' + self.tidy_path = RUBY_PLATFORM =~ /mswin32/ ? 'c:/tidy/lib/tidy.dll' : '/usr/lib/libtidy.so' self.namespace_prefix = 'mv:' self.inline_erb_start = '{{{' self.inline_erb_end = '}}}' self.inline_erb_substitution_regex = /\{\{\{(([^}]|\}[^}]|\}\}[^}])*)\}\}\}/ @@ -571,10 +586,12 @@ self.enable_view_rhtml = is_development self.generate_rhtml_files = false STDOUT.puts "...mv config initialized with default settings\n" if debug_TRACE_HACK + self.initialization_messages = [] # for installer validation checking and problem reporting + end def decide_if_running_rails #:nodoc: #old way using program name except that this needs to be maintained @running_rails = has_rails_context && ($PROGRAM_NAME =~ rails_runner_scripts_pattern) != nil @@ -680,13 +697,12 @@ initializer end # Create a new Initializer instance that references the given Configuration # instance. - def initialize(configuration) #:nodoc: - @configuration = configuration - @log_msg_q = [] # collect log messages that arrive prior to the logger + def initialize(config) #:nodoc: + @configuration = config end # Load the MasterView configuration settings # and initialize the template engine. def process @@ -699,16 +715,19 @@ # Does *not* load and configure the template engine. # # Intended for use in testing. def initialize_configuration #?? return if MasterView.const_defined?(:ConfigSettings) ?? + #ISSUE: support format_datetime option on the logger settings?? [DJL 30-Jul-2006] + configuration.initialization_messages << [ :info, + "Initializing MasterView configuration (#{DateTime.now.strftime('%Y-%m-%d %H:%M')})" ] + configuration.initialization_messages << [ :info, + "Program name = #{$PROGRAM_NAME}" ] # log the program that is starting the session load_config_settings ensure_valid_settings install_config_settings # make a final check for running_rails? (in case config settings changed scripts spec) - # this logging didn't seem to work?? - # @log_msg_q << [ :info, 'Program name = '+$PROGRAM_NAME ] # log the program that is starting configuration.decide_if_running_rails # keep a permananent record of how we got started configuration.freeze configuration.directive_paths.freeze MasterView.const_set('ConfigSettings', configuration) @@ -750,15 +769,16 @@ # ensure that the directive load path entries are clean and available if not config.directive_paths.empty? clean_paths = [] config.directive_paths.each { | dir | - if dir.nil? || ! File.directory?(dir) + if dir.nil?: continue; end + if ! File.directory?(dir) err_msg = "Invalid directive load path directory: '#{dir}'" - #overzealous: raise InvalidPathError.new() - #but doesn't exist yet: Log.error err_mage - @log_msg_q << [ :error, err_msg ] + #overzealous: raise InvalidPathError.new(err_msg) + # just note the problem and let initializer report it later + config.initialization_messages << [ :error, err_msg ] else dir_path = File.expand_path( dir ) clean_paths << dir_path if ! clean_paths.include?(dir_path) # no dups end } @@ -792,10 +812,13 @@ end def set_module_constants #:nodoc: config = configuration + + # save configuration so we can get to it later + MasterView.const_set('LoadedConfiguration', config) # create loaded feature map - this map will track exactly what was loaded taking into account failures, so it can differ # from what is configured. key = feature symbol, value = true if enabled and loaded MasterView.const_set('LoadedFeatures', {} ) @@ -812,11 +835,11 @@ MasterView.const_set('OmitGeneratedComments', (not config.include_generated_file_comment)) MasterView.const_set('GeneratedCommentText', config.generated_file_comment) # template parsing options MasterView.const_set('RescueExceptions', config.handle_parse_exceptions) - MasterView.const_set('DefaultParserOptions', config.default_parser_options) + MasterView.const_set('DefaultParserOptions', Configuration::OriginalDefaultParserOptions.merge(config.default_parser_options)) # merge in changes with original, so we can add more defaults later, users have to explicitly set an option to false to cancel them MasterView.const_set('TidyPath', config.tidy_path) MasterView.const_set('NamespacePrefix', config.namespace_prefix) MasterView.const_set('InlineErbStart', config.inline_erb_start) MasterView.const_set('InlineErbEnd', config.inline_erb_end) MasterView.const_set('InlineErbSubstitutionRegex', config.inline_erb_substitution_regex) @@ -838,57 +861,58 @@ # Load the masterview code def load_plugin #:nodoc: require 'masterview' #:nodoc: end - # Complete installation of masterview after its code has been loaded + # Complete installation of masterview after its own code has been loaded def complete_plugin_installation #:nodoc: #?? return if MasterView.const_defined?(:Initialized) ?? - initialize_mio initialize_logger + initialize_mio #Back out experiment: causes load order problems ##load_directives # held off on this until logger is installed install_in_rails # mark the module as fully loaded and configured MasterView.const_set('Initialized', true) after_initialize # callback to client's afer_initialize block end + # Initialize MasterView::Log with a logger which emits to std output, default DEBUG level + def initialize_logger #:nodoc: + #?return if defined?(Log) + require 'masterview/extras/init_logger' + # release any queued-up initialization messages yearning to be free + configuration.initialization_messages.each { | msg_level, msg | + Log.send msg_level, msg + } + end + # Initialize the MasterView I/O subsystem def initialize_mio config = configuration MasterView.const_set('DefaultSerializer', MIOSerializer) # all root_path directory anchor points for I/O are expanded absolute paths io_mgr = MIOTrees.new template_extension = File.extname( config.template_filename_pattern ) io_mgr.template = FileMIOTree.new( config.template_src_dir_path, template_extension, - :escape_erb => config.default_parser_options[:escape_erb], - :tidy => config.default_parser_options[:tidy], + :escape_erb => DefaultParserOptions[:escape_erb], # use DefaultParserOptions since already has config merged + :tidy => DefaultParserOptions[:tidy], + :default_generate => DefaultParserOptions[:default_generate], #TODO: expose the following in Configuration.default_parser_options and document :caching => false, :logging => true ) + if config.generate_rhtml_files io_mgr.erb = FileMIOTree.new( config.template_dst_dir_path, config.generated_file_default_extension, :logging => true) else io_mgr.erb = RailsErbCacheMIOTree.new( config.generated_file_default_extension, :logging => true) end io_mgr.backup = FileMIOTree.new( config.rebuild_backups_tmp_dir_path ) if config.rebuild_backups_tmp_dir_path MasterView.const_set('IOMgr', io_mgr) MasterView::LoadedFeatures[:tidy_template_read] = config.default_parser_options[:tidy] end - # Initialize MasterView::Log with a logger which emits to std output, default DEBUG level - def initialize_logger #:nodoc: - #?return if defined?(Log) - require 'masterview/extras/init_logger' - # Kick out any queued-up log messages yearning to be free - @log_msg_q.each { | msg_level, msg | - Log.send err_level, msg - } - @log_msg_q.clear - end - def load_directives #:nodoc: # get the directives loaded prior to firing up any template parsing return if ! configuration.on_rails? #ISSUE: causes problem for test cases; is this ever a good idea?? MasterView::DirectivesRegistry.process_directives_load_path( configuration.directive_paths, @@ -905,41 +929,10 @@ end # install the MasterviewController to support masterview admin pages in the site def enable_mv_admin_pages #:nodoc: return if ! configuration.enable_admin_pages #MasterView::EnableMasterViewAdminPages - MasterView::Log.info{ 'MasterView Admin pages enabled' } - - # verify that stylesheets we use are available and if not copy them to public/stylesheets - mv_generator_templates_dir = "#{configuration.mv_installation_dir}/generators/masterview/templates" - unless File.exist?(mv_generator_templates_dir) - # we are in a gem so things are in different directories - MasterView::Log.debug{ 'MasterView appears to be installed as a gem...' } - mv_generator_dir = configuration.mv_installation_dir.gsub('\\','/').gsub( %r{/masterview-([^/]+)$}, '/masterview_generator-\1' ) - mv_generator_templates_dir = "#{mv_generator_dir}/templates" - end - MasterView::Log.debug{ 'MasterView gem admin stylesheet src dir='+mv_generator_templates_dir } - - if File.directory?(mv_generator_templates_dir) - rails_app_stylesheets_dir = Pathname.for_path(RAILS_ROOT) + 'public/stylesheets/masterview' - stylesheet_specs = [ - # from/to spec: [ <src filename in templates dir>, <target filename in app stylesheets dir> ] - [ 'style.css', 'style.css' ], - [ 'sidebox.css', 'sidebox.css' ], - [ 'color-scheme.css', 'color-scheme.css' ] - ] - src_dir_accessor = MasterView::FileMIOTree.new( mv_generator_templates_dir ) - dst_dir_accessor = MasterView::FileMIOTree.new( rails_app_stylesheets_dir, '.css', :logging => true) - stylesheet_specs.each { | from, to | - src_file = src_dir_accessor.path(from) - dst_file = dst_dir_accessor.path(to) - dst_file.write( src_file.read ) unless dst_file.exist? - } - end - # add our app directories with the masterview_controller to the load path - mv_controller_code_dirs = Dir[File.join(configuration.mv_code_base_dir, '/extras/app/**/*')].select { |dir| - File.directory?(dir) } - mv_controller_code_dirs.each { |dir| $LOAD_PATH.push dir } + require 'masterview/extras/init_mv_admin_pages' end def parse_templates_at_startup #:nodoc: if configuration.parse_masterview_templates_at_startup require 'masterview/extras/watcher'