module Cog::Embeds
@api developer Methods for querying and manipulating project files
Public Instance Methods
Copy keep bodies from the original file to the scratch file @param original [String] file in which to search for keep statements. If the original does not exist, then scratch will serve as the original (we do this so that the keeps will get expanded in any case) @param scratch [String] file to which keep bodies will be copied @return [nil]
# File lib/cog/embeds.rb, line 39 def copy_keeps(original, scratch) Cog.activate_language(:filename => original) do original = scratch unless File.exists? original keeps = gather_keeps original, scratch keeps.each_pair do |hook, c| result = update c, :type => 'keep' do |c| c.keep_body end raise Errors::UnrecognizedKeepHook.new :hook => hook, :filename => original if result.nil? end end end
@param hook [String] embed hook for which to find directive occurrences @yieldparam context [EmbedContext] describes the context in which the embed statement was found
# File lib/cog/embeds.rb, line 71 def find(hook) x = @embeds[hook] unless x.nil? x.keys.sort.each do |filename| c = EmbedContext.new hook, filename, x[filename] Cog.activate_language :ext => c.extension do c.count.times do |index| c.index = index yield c end end end end end
@param filename [String] file from which to gather statements @option opt [Hash] :hash ({}) object in which to gather the mapping @option opt [String] :type ('cog') one of 'cog'
or 'keep'
@return [Hash] mapping from hooks to { 'filename' => count }
hashes
# File lib/cog/embeds.rb, line 56 def gather_from_file(filename, opt={}) bucket = opt[:hash] || {} type = opt[:type] || 'cog' lang = Cog.language_for filename File.read(filename).scan(statement type, '[-A-Za-z0-9_.]+', :lang => lang) do |m| hook = m[0] bucket[hook] ||= {} bucket[hook][filename] ||= 0 bucket[hook][filename] += 1 end bucket end
Search through all project files for cog embeds, and remember them so that generators can refer to them later
# File lib/cog/embeds.rb, line 8 def gather_from_project @embeds ||= {} Cog.supported_project_files.each do |filename| gather_from_file filename, :hash => @embeds, :type => 'cog' end end
@param original [String] file in which to search for keep statements @param scratch [String] file to which keep bodies will be copied (used to create the {EmbedContext} objects) @return [Hash] mapping from hooks to {EmbedContext} objects
# File lib/cog/embeds.rb, line 18 def gather_keeps(original, scratch) keeps = {} gather_from_file(original, :type => 'keep').each_pair do |hook, count| c = keeps[hook] = EmbedContext.new(hook, scratch, count[original]) raise Errors::DuplicateKeep.new :hook => hook if c.count > 1 Helpers::FileScanner.scan(original, statement('keep', hook)) do |s| c.keep_body = if s.match[4] == '{' s.capture_until end_statement('keep') s.captured_text else '' end end end keeps end
@param c [EmbedContext] describes the context in which the embed statement was found @option opt [String] :type ('cog') one of 'cog'
or 'keep'
@yieldparam context [EmbedContext] describes the context in which the embed statement was found @yieldreturn [String] the value to substitute into the embed expansion @return [Boolean,nil] true
if the statement was expanded or updated, false
if the statement was found, but not changed, nil
if it could not be found.
# File lib/cog/embeds.rb, line 91 def update(c, opt={}, &block) type = opt[:type] || 'cog' Helpers::FileScanner.scan(c.path, statement(type, c.hook), :occurrence => c.actual_index) do |s| c.lineno = s.marked_line_number c.args = s.match[2].split if s.match[2] c.once = !s.match[3].nil? if s.match[4] == '{' update_body c, s, opt, &block else expand_body c, s, opt, &block end end end
Private Instance Methods
@return [Regexp] pattern to match an line that looks like a cog statement, but is not the end statement
# File lib/cog/embeds.rb, line 124 def anything_but_end(type = 'cog') Cog.active_language.comment_pattern("#{type}\\s*:\\s*(?!\\s*[}]).*$") end
@return [Regexp] pattern to match the end of a cog embed statement
# File lib/cog/embeds.rb, line 119 def end_statement(type = 'cog') Cog.active_language.comment_pattern("#{type}\\s*:\\s*[}]") end
@param c [EmbedContext] @param s [FileScanner] @option opt [String] :type ('cog') one of 'cog'
or 'keep'
@return [Boolean] whether or not the scanner updated its file
# File lib/cog/embeds.rb, line 150 def expand_body(c, s, opt={}, &block) type = opt[:type] || 'cog' lang = Cog.active_language value = block.call(c).rstrip snip_line = lang.comment "#{c.to_statement type} {" unless c.once? value = [snip_line, value, lang.comment("#{type}: }")].join("\n") end s.insert_at_mark(value + "\n") end
Pattern groups are
-
1 - hook
-
2 - args
-
3 - once
-
4 - expansion begin (curly
{
)
@return [Regexp] pattern to match the beginning of a cog embed statement
# File lib/cog/embeds.rb, line 113 def statement(type, hook, opt={}) lang = opt[:lang] || Cog.active_language lang.comment_pattern("#{type}\\s*:\\s*(#{hook})\\s*(?:\\(\\s*(.+?)\\s*\\))?(\\s*once\\s*)?(?:\\s*([{]))?") end
@param c [EmbedContext] @param s [FileScanner] @option opt [String] :type ('cog') one of 'cog'
or 'keep'
@return [Boolean] whether or not the scanner updated its file
# File lib/cog/embeds.rb, line 132 def update_body(c, s, opt={}, &block) type = opt[:type] || 'cog' unless s.capture_until end_statement(type), :but_not => anything_but_end(type) raise Errors::SnippetExpansionUnterminated.new :filename => c.path.relative_to_project_root, :line => s.marked_line_number end c.body = s.captured_text value = block.call(c).rstrip if c.once? || value.normalize_eol != s.captured_text.rstrip.normalize_eol s.replace_captured_text(value + "\n", :once => c.once?) else false end end