templatron 0.1.2 → 0.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ca21f5aac9c3bd51b3316ef87238c19832833ab8
4
- data.tar.gz: 1b2cfa06b0f856fc2d7c504e8f40bee95ef26720
3
+ metadata.gz: 00b8850a510c189094e5761a68649d231319d9ec
4
+ data.tar.gz: 8736415297d84d92655d62e5e881d256e5eddb59
5
5
  SHA512:
6
- metadata.gz: 485ecfdd834358e64fad9ee80fe73a4f1d0c31dfa63454a5a1382e661c833a2c46d6dfc6f8352892e73f76a3cc6e47de083711a2ef4c6214d410ad665490ef65
7
- data.tar.gz: 30a4f9bd4718346ce401e68ab8391bee40b6b68c111f2e119f0f6a63f609a40e1ea741222105511c97c524ee8a0a5c4648b0e58ce7ebca58801e943d1c318b40
6
+ metadata.gz: f6b63bf41e826cf3862b3f4031bc5b74484bb16d8e7f168136b86a16ed32277b5437e73e1eee19bd356f9d3d98d8034948b80a4672061580719fdd5256a8af69
7
+ data.tar.gz: d70378ea9c97efff778e180e9e3272686b43acb022060a3745cdd0044e18f29254ccf2d2cba29fc6feea39b7877fc5fb0481f2b8dff2c912c28b0bdb4f40dc0a
@@ -1,80 +1,71 @@
1
1
  # -*- encoding: utf-8 -*-
2
+ require 'clamp'
2
3
  require 'templatron/version'
3
4
  require 'templatron/config'
4
5
  require 'templatron/generator'
5
- require 'optparse'
6
- require 'ostruct'
6
+ require 'templatron/collector'
7
7
 
8
8
  module Templatron
9
9
 
10
- # Public: CLI Stuff, parse command line inputs to determine what to do
11
- def self.execute
12
-
13
- usage = 'Usage: templatron TEMPLATE_NAME [args] [-o output_dir]'
14
-
15
- # If no argument has been given, print usage
16
- if ARGV.length == 0
17
- puts usage
18
- exit
10
+ # Represents a base class with command flags
11
+ class AbstractCommand < Clamp::Command
12
+ option ['-v', '--verbose'], :flag, 'Enable verbose mode', :default => false
13
+ option '--version', :flag, 'Show the current version' do
14
+ puts Templatron::VERSION
15
+ exit(0)
19
16
  end
17
+ end
20
18
 
21
- # Defines the structure and default values
22
- options = OpenStruct.new
23
- options.output_dir = Dir.pwd
24
- options.verbose = false
25
- options.delete_dir = false
26
-
27
- # Defines options parser
28
- opt_parser = OptionParser.new do |opts|
29
- opts.banner = usage
30
- opts.default_argv = '-h'
31
-
32
- opts.separator ''
33
- opts.separator 'Features:'
34
-
35
- # Defines where to put generated files
36
- opts.on('-o', '--output PATH', 'Where to put the generated files') do |dir|
37
- options.output_dir = dir
38
- end
39
-
40
- # Should we remove the output directory first
41
- opts.on('-d', '--delete', 'If set, clear the output directory first') do
42
- options.delete_dir = true
43
- end
44
-
45
- opts.separator ''
46
- opts.separator 'Common options:'
19
+ # Use to list the template dir
20
+ class ListCommand < AbstractCommand
21
+ parameter '[SUB_PATH]', 'Relative path to list from',
22
+ :attribute_name => :subpath,
23
+ :default => ''
24
+ option ['-a', '--all'], :flag, 'Also show files', :default => false
47
25
 
48
- # Verbose mode
49
- opts.on('-v', '--verbose', 'Verbose mode') do
50
- options.verbose = true
51
- end
26
+ def execute
27
+ col = Collector.new(subpath, all?, false, verbose?)
28
+ entries = col.list
52
29
 
53
- # Print the help
54
- opts.on_tail('-h', '--help', 'Show this message') do
55
- puts opts
56
- puts ''
57
- puts "Templates path: #{Templatron::templates_path}"
58
- exit
59
- end
30
+ entries.each { |e| puts e.sub(col.full_path, '') }
31
+ end
32
+ end
60
33
 
61
- # Print version number
62
- opts.on_tail('--version', 'Show version') do
63
- puts Templatron::VERSION
64
- exit
65
- end
34
+ # Use to build stuff!
35
+ class BuildCommand < AbstractCommand
36
+ parameter 'TEMPLATE_NAME', 'Template to generate from',
37
+ :attribute_name => :template
38
+ parameter '[ARGS] ...', 'Template arguments',
39
+ :attribute_name => :arguments
40
+ option ['-o', '--output'], 'OUTPUT_DIR', 'Where to put the generated files',
41
+ :default => Dir.pwd
42
+ option ['-d', '--delete'], :flag, 'Clear the output folder first',
43
+ :default => false
44
+
45
+ def execute
46
+ # Instantiate the generator and build the stuff
47
+ gen = Generator.new(
48
+ template,
49
+ arguments,
50
+ output,
51
+ delete?,
52
+ verbose?)
53
+ t_start = Time.now
54
+ gen.build
55
+ t_end = Time.now
56
+ puts "BUILT in #{t_end - t_start} seconds"
66
57
  end
58
+ end
67
59
 
68
- opt_parser.parse!(ARGV)
60
+ # Entry point of the cli
61
+ class MainCommand < AbstractCommand
62
+ subcommand 'build', 'Build from templates', BuildCommand
63
+ subcommand 'list', 'List available templates', ListCommand
64
+ end
69
65
 
70
- # Instantiate the generator and build the stuff
71
- gen = Generator.new(
72
- ARGV[0],
73
- ARGV[1..ARGV.length],
74
- options.output_dir,
75
- options.delete_dir,
76
- options.verbose)
77
- gen.build
66
+ # Public: CLI Stuff, parse command line inputs to determine what to do
67
+ def self.execute
68
+ MainCommand.run
78
69
  end
79
70
 
80
71
  end
@@ -0,0 +1,96 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'templatron/config'
3
+
4
+ module Templatron
5
+
6
+ # Collector stuff
7
+ # Show templates and related informations
8
+ class Collector
9
+
10
+ attr_accessor :full_path
11
+
12
+ # Public: Initialize the collector instance
13
+ #
14
+ # path - Relative path of a template
15
+ # include_files - Also include files or not
16
+ # include_sub - Incluse subfolders?
17
+ # verbose - Verbose mode?
18
+ def initialize(path, include_files, include_sub, verbose = false)
19
+ @full_path = File.join(Templatron::templates_path, expand_path(path))
20
+ @verbose = verbose
21
+ @include_files = include_files
22
+ @include_subfolders = include_sub
23
+ end
24
+
25
+ # Public: List the content of this template
26
+ #
27
+ # Returns the list of entries for this instance
28
+ def list
29
+ puts "Listing content: of directory #{@full_path}" if @verbose
30
+
31
+ v = ['**']
32
+ v << '*' if @include_subfolders
33
+
34
+ entries = Dir.glob(escape_glob(File.join(@full_path, v)))
35
+ entries.map! { |e| e if File.directory?(e) }.compact! if !@include_files
36
+
37
+ entries
38
+ end
39
+
40
+ protected
41
+
42
+ # Internal: Escape special characters, needed for glob to work
43
+ #
44
+ # str - String to escape
45
+ #
46
+ # Returns an escaped string
47
+ def escape_glob(str)
48
+ str.gsub(/[\\\{\}\[\]\?]/) { |x| "\\"+x }
49
+ end
50
+
51
+ # Internal: Expand the path by looking in each subfolders and replacing default
52
+ # placeholder values with their real names
53
+ #
54
+ # Notes
55
+ # It may need a little refactoring
56
+ #
57
+ # path - Path to expand
58
+ #
59
+ # Examples
60
+ #
61
+ # Given base/profile/authors, it will returns base/profile/{$1 authors}
62
+ #
63
+ # Returns the real path
64
+ def expand_path(path)
65
+ tmp = path
66
+ final_path_components = []
67
+
68
+ until (p = File.split(tmp)).first == '.'
69
+ tmp = p.first
70
+ component = p.last
71
+
72
+ # Gets all entries in this folder
73
+ base_path = File.join(Templatron::templates_path, tmp)
74
+
75
+ Dir.glob(escape_glob(File.join(base_path, '*'))).each do |e|
76
+ next if !File.directory?(e) # Only process folders
77
+
78
+ e.scan(Templatron::PLACEHOLDER_REG).each do |match|
79
+ # Replace this component if it matches the user input
80
+ if component.include?(match[1])
81
+ component.sub!(match[1], e.match(Templatron::placeholder_block_reg(match[1])).to_s)
82
+ end
83
+ end
84
+ end
85
+
86
+ final_path_components << component
87
+ end
88
+
89
+ final_path_components << p.last
90
+
91
+ File.join(final_path_components.reverse)
92
+ end
93
+
94
+ end
95
+
96
+ end
@@ -4,8 +4,29 @@ module Templatron
4
4
  # This part will be joined to the user Dir.home
5
5
  PREFIX = '.templatron'
6
6
 
7
+ PLACEHOLDER_REG = /{\$(\d*)\W?([\w\s]*)}/
8
+
7
9
  # Public: Retrieve the full path which stores templates
8
10
  def self.templates_path
9
11
  File.join(Dir.home, PREFIX)
10
12
  end
13
+
14
+ # Public: Retrieve the placeholder reg for replacement
15
+ #
16
+ # match_i - Match key
17
+ #
18
+ # Returns the regex for replacement
19
+ def self.placeholder_reg(match_i)
20
+ /{\$#{match_i}\W?([\w\s]*)}/
21
+ end
22
+
23
+ # Public: Retrieve the placeholder reg block which contains
24
+ # the whole placeholder markup
25
+ #
26
+ # key - Key to look for
27
+ #
28
+ # Returns the regex needed to retrieve the whole placeholder markup
29
+ def self.placeholder_block_reg(key)
30
+ /({\$\d*\W?[#{key}]*})/
31
+ end
11
32
  end
@@ -1,6 +1,7 @@
1
1
  # -*- encoding: utf-8 -*-
2
- require 'FileUtils'
2
+ require 'fileutils'
3
3
  require 'templatron/config'
4
+ require 'templatron/collector'
4
5
 
5
6
  module Templatron
6
7
 
@@ -20,7 +21,8 @@ module Templatron
20
21
  @output = File.expand_path(output_dir)
21
22
  @verbose = verbose
22
23
  @clear = delete_dir
23
- @full_template_path = File.join(Templatron::templates_path, @template)
24
+
25
+ @collector = Collector.new(@template, true, true)
24
26
 
25
27
  process_raw_arguments(args)
26
28
  end
@@ -28,7 +30,7 @@ module Templatron
28
30
  # Public: Effectively process a template to generate it
29
31
  def build
30
32
  # Check template existence
31
- if !check_template_dir(@full_template_path)
33
+ if !check_template_dir(@collector.full_path)
32
34
  puts "The template #{@template} does not appear to exist in #{@full_template_path}"
33
35
  exit
34
36
  end
@@ -36,28 +38,45 @@ module Templatron
36
38
  # If sets, remove the output folder first
37
39
  if @clear
38
40
  puts "Clearing #{@output}" if @verbose
39
- FileUtils.remove_dir(@output, true)
41
+ begin
42
+ FileUtils.remove_dir(@output)
43
+ rescue => ex
44
+ puts """Could not clear the folder, maybe someone is accessing it?
45
+
46
+ #{ex.message}
47
+ """
48
+ exit(1)
49
+ end
40
50
  end
41
51
 
42
52
  # Print details if verbose is on
43
53
  if @verbose
44
- puts "Starting building #{@full_template_path} to #{@output}"
45
- puts "With:"
54
+ puts "Starting building #{@collector.full_path} to #{@output}"
55
+ puts "With:" if !@arguments.empty?
46
56
  @arguments.each_with_index do |arg, i|
47
57
  puts "\t{$#{i}} => #{arg}" if !arg.nil?
48
58
  end
49
59
  end
50
60
 
51
- # And then process each files/folder
52
- collect_str = File.join(@full_template_path, '**', '*')
53
- # At this point, all file entries have been collected
54
- entries = Dir[collect_str].map { |p| p if File.file?(p) }.compact
55
61
  # So process them right now
56
- process_files(entries)
62
+ process_files(@collector.list)
57
63
  end
58
64
 
59
65
  protected
60
66
 
67
+ # Internal: Try to create a directory and fails gracefuly
68
+ def create_directory(path)
69
+ begin
70
+ FileUtils.mkdir_p(path)
71
+ rescue => ex
72
+ puts """Error while creating the directory #{path}
73
+
74
+ #{ex.message}
75
+ """
76
+ exit(1)
77
+ end
78
+ end
79
+
61
80
  # Internal: Process each entries, copy the files and replaces variables
62
81
  #
63
82
  # entries - An array of files to process
@@ -65,23 +84,30 @@ module Templatron
65
84
  entries.each do |path|
66
85
 
67
86
  # Get base path
68
- new_path = path.gsub(@full_template_path, '')
87
+ new_path = path.sub(@collector.full_path, '')
69
88
 
89
+ is_dir = File.directory?(path)
90
+
70
91
  # Apply arguments to the path
71
92
  apply_arguments!(new_path)
72
93
 
73
- # Now we can copy the entry
74
94
  full_new_path = File.join(@output, new_path)
75
95
 
76
- puts "Copying #{path} to #{full_new_path}" if @verbose
96
+ if is_dir
97
+ puts "Creating directory #{path} to #{full_new_path}" if @verbose
98
+ create_directory(full_new_path)
99
+ else
100
+ # Now we can copy the entry
101
+ puts "Copying #{path} to #{full_new_path}" if @verbose
77
102
 
78
- FileUtils.mkdir_p(File.dirname(full_new_path))
79
- FileUtils.copy(path, full_new_path)
103
+ create_directory(File.dirname(full_new_path))
104
+ FileUtils.copy(path, full_new_path)
80
105
 
81
- file_content = File.read(full_new_path)
82
- apply_arguments!(file_content)
83
- File.open(full_new_path, 'w') do |f|
84
- f.puts file_content
106
+ file_content = File.read(full_new_path)
107
+ apply_arguments!(file_content)
108
+ File.open(full_new_path, 'w') do |f|
109
+ f.puts file_content
110
+ end
85
111
  end
86
112
  end
87
113
  end
@@ -109,17 +135,20 @@ module Templatron
109
135
  #
110
136
  # str - Where to look & replace
111
137
  def apply_arguments!(str)
112
- str.scan(/{\$(\d*)\W?([\w\s]*)}/).each do |match|
138
+ str.scan(Templatron::PLACEHOLDER_REG).each do |match|
113
139
  match_i = match[0].to_i
114
140
  arg_value = @arguments[match_i]
115
141
  arg_value = match[1] if arg_value.nil?
116
- str.gsub!(/{\$#{match_i}\W?([\w\s]*)}/, arg_value)
142
+
143
+ str.gsub!(Templatron::placeholder_reg(match_i), arg_value)
117
144
  end
118
145
  end
119
146
 
120
147
  # Internal: Check if the template directory exists
121
148
  #
122
149
  # dir - Where to look
150
+ #
151
+ # Returns true if the directory exists, false otherwise
123
152
  def check_template_dir(dir)
124
153
  Dir.exist?(dir)
125
154
  end
@@ -1,4 +1,4 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  module Templatron
3
- VERSION = '0.1.2'
3
+ VERSION = '0.2.0'
4
4
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: templatron
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Julien Leicher
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-03-19 00:00:00.000000000 Z
11
+ date: 2015-03-24 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Defines templates with variables and generates whatever you want
14
14
  email:
@@ -20,6 +20,7 @@ extra_rdoc_files: []
20
20
  files:
21
21
  - bin/templatron
22
22
  - lib/templatron/cli.rb
23
+ - lib/templatron/collector.rb
23
24
  - lib/templatron/config.rb
24
25
  - lib/templatron/generator.rb
25
26
  - lib/templatron/version.rb