Class: Codger::Skeleton

Inherits:
Generator show all
Defined in:
lib/codger/skeleton.rb

Overview

A generator that produces code by using a git repository as a template.

By default:

  • README, README.md, README.markdown will be ignored, except to be printed as documentation if user input is required for the value of a param

  • generate.rb (if it exists) will be executed in the context of the Skeleton instance

  • Files ending in .erb will be interpolated in the context of the Skeleton instance

  • All other files will be copied directly

Methods for use in generate.rb and templates:

  • #src_path

  • #cancel

  • #copy

  • #interpolate

  • #ignore

  • #rename

Instance Attribute Summary collapse

Attributes inherited from Generator

#params, #target

Instance Method Summary collapse

Methods inherited from Generator

#dest_path, #ensure_folder, format_params, #param, #run, #tags

Constructor Details

#initialize(clone, identifier) ⇒ Skeleton

Create an instance reading from the git repository at the specified (local) path.



35
36
37
38
39
# File 'lib/codger/skeleton.rb', line 35

def initialize clone, identifier
  @identifier = identifier
  @git = Git.open(clone)
  @name = identifier.split('/').last.sub(/\.git\z/,'')
end

Instance Attribute Details

#identifierObject (readonly)

Returns the identifier that can (hopefully) be used to locate this skeleton in the future.



31
32
33
# File 'lib/codger/skeleton.rb', line 31

def identifier
  @identifier
end

#nameObject (readonly)

Returns a (non-unique) name for the generator. For skeletons this is based on the last segment of the origin URI or of the clone’s path.



29
30
31
# File 'lib/codger/skeleton.rb', line 29

def name
  @name
end

Instance Method Details

#cancelObject

Stop interpolation of the current template.



125
126
127
# File 'lib/codger/skeleton.rb', line 125

def cancel
  raise CancelInterpolation.new
end

#copy(*paths) ⇒ Object

For each path or array of paths, copy the corresponding files directly from the repository to the target directory. Alternatively, a hash of paths may be given, in which keys specify the name in the source repository and values specify the desired name in the target directory.



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/codger/skeleton.rb', line 65

def copy(*paths)
  paths = paths.flatten
  mappings = {}
  paths.each do |path|
    if path.is_a? Hash
      mappings.merge! path
    else
      mappings[path] = path
    end
  end

  mappings.each do |src, dest|
    ensure_folder dest
    FileUtils.cp src_path(src), dest_path(dest)
    @to_copy.delete src
  end
end

#generateObject

Perform code generation using the process outlined in the class documentation.



42
43
44
45
46
47
48
49
50
51
52
# File 'lib/codger/skeleton.rb', line 42

def generate
  @to_copy = @git.ls_files.keys - ['README', 'README.md', 'README.markdown', 'generate.rb', '.gitignore']

  code_path = src_path('generate.rb')
  if File.exists?(code_path)
    eval(File.read(code_path), binding, code_path)
  end

  interpolate(@to_copy.select {|path| path =~ /\.erb\z/})
  copy @to_copy
end

#helpObject

Returns the text of the README, README.md or README.markdown file, if any.



135
136
137
138
139
140
# File 'lib/codger/skeleton.rb', line 135

def help
  path = Dir[src_path('README')].first || Dir[src_path('README.md')].first || Dir[src_path('README.markdown')].first
  if path
    File.read path
  end
end

#ignore(*paths) ⇒ Object

For each path or array of paths, disable implicit copying.



130
131
132
# File 'lib/codger/skeleton.rb', line 130

def ignore(*paths)
  @to_copy -= paths.flatten
end

#interpolate(*paths) ⇒ Object

For each path or array of paths, interpolate (in the context of this object) the corresponding files and write the output to the target directory, stripping .erb from the filename. Alternatively, a hash of paths may be given, in which keys specify the name in the source repository and values specify the desired name in the target directory.

Note that calls to #rename may override the destination path.



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/codger/skeleton.rb', line 92

def interpolate(*paths)
  paths = paths.flatten
  mappings = {}
  paths.each do |path|
    if path.is_a? Hash
      mappings.merge! path
    else
      mappings[path] = path.sub(/\.erb\z/, '')
    end
  end

  mappings.each do |src, dest|
    begin
      @current_template_src = src
      @current_template_dest = dest
      template = ERB.new(File.read(src_path(src)), nil, '-')
      result = template.result(binding)
      ensure_folder @current_template_dest
      File.write File.expand_path(dest_path(@current_template_dest)), result
    rescue CancelInterpolation
    end
    @to_copy.delete src
  end
end

#rename(dest) ⇒ Object

Should only be called from within a file being interpolated. The output path will be changed to dest, which should be relative to the template’s folder.



120
121
122
# File 'lib/codger/skeleton.rb', line 120

def rename(dest)
  @current_template_dest = File.join(File.dirname(@current_template_src), dest)
end

#src_path(path) ⇒ Object

Return the full path to the given file in the repo.



55
56
57
# File 'lib/codger/skeleton.rb', line 55

def src_path(path)
  File.join(@git.dir.to_s, path)
end