Skip to content

Instantly share code, notes, and snippets.

@ttscoff
Created September 22, 2012 17:57
Show Gist options
  • Save ttscoff/3767188 to your computer and use it in GitHub Desktop.
Save ttscoff/3767188 to your computer and use it in GitHub Desktop.
Create directory trees from indented text input
#!/usr/bin/ruby
=begin
Planter v1.3
Brett Terpstra 2013
ruby script to create a directory structure from indented data.
Three ways to use it:
- Pipe indented (tabs or 2 spaces) text to the script
- e.g. `cat "mytemplate" | planter.rb
- Create template.tpl files in ~/.planter and call them by their base name
- e.g. Create a text file in ~/.planter/site.tpl
- `planter.rb site`
- Call planter.rb without input and it will open your $EDITOR to create the tree on the fly
You can put %%X%% variables into templates, where X is a number that corresponds to the index
of the argument passed when planter is called. e.g. `planter.rb client "Mr. Butterfinger"`
would replace %%1%% in client.tpl with "Mr. Butterfinger". Use %%X|default%% to make a variable
optional with default replacement.
If a line in the template matches a file or folder that exists in ~/.planter, that file/folder
will be copied to the destination folder.
=end
require 'yaml'
require 'tmpdir'
require 'fileutils'
def get_hierarchy(input,parent=".",dirs_to_create=[])
input.each do |dirs|
if dirs.kind_of? Hash
dirs.each do |k,v|
dirs_to_create.push(File.expand_path("#{parent}/#{k.strip}"))
dirs_to_create = get_hierarchy(v,"#{parent}/#{k.strip}",dirs_to_create)
end
elsif dirs.kind_of? Array
dirs_to_create = get_hierarchy(dirs,parent,dirs_to_create)
elsif dirs.kind_of? String
dirs_to_create.push(File.expand_path("#{parent}/#{dirs.strip}"))
end
end
return dirs_to_create
end
def text_to_yaml(input, replacements = [])
variables_count = input.scan(/%%\d+%%/).length
if variables_count > replacements.length
$stderr.puts('Mismatch variable/replacement counts!')
$stderr.puts("Template has #{variables_count} required replacements, #{replacements.length} provided.")
Process.exit 1
end
input.gsub!(/%%(\d+)(?:\|(.*?))?%%/) do |match|
if replacements[$1.to_i - 1]
replacements[$1.to_i - 1]
elsif !$2.nil?
$2
else
print "Invalid variable"
Process.exit 1
end
end
lines = input.split(/[\n\r]/)
output = []
prev_indent = 0
lines.each_with_index do |line, i|
indent = line.gsub(/ /,"\t").match(/(\t*).*$/)[1]
if indent.length > prev_indent
lines[i-1] = lines[i-1].chomp + ":"
end
prev_indent = indent.length
lines[i] = indent.gsub(/\t/,' ') + "- " + lines[i].strip # unless indent.length == 0
end
lines.delete_if {|line|
line == ''
}
return "---\n" + lines.join("\n")
end
if STDIN.stat.size > 0
data = STDIN.read
elsif ARGV.length > 0
template = File.expand_path("~/.planter/#{ARGV[0].gsub(/\.tpl$/,'')}.tpl")
ARGV.shift
if File.exists? template
File.open(template, 'r') do |infile|
data = infile.read
end
else
puts "Specified template not found in ~/.planter/*.tpl"
end
else
tmpfile = File.expand_path(Dir.tmpdir + "/planter.tmp")
File.new(tmpfile, 'a+')
# at_exit {FileUtils.rm(tmpfile) if File.exists?(tmpfile)}
%x{$EDITOR "#{tmpfile}"}
data = ""
File.open(tmpfile, 'r') do |infile|
data = infile.read
end
end
data.strip!
yaml = YAML.load(text_to_yaml(data,ARGV))
dirs_to_create = get_hierarchy(yaml)
dirs_to_create.each do |dir|
curr_dir = ENV['PWD']
unless File.exists? dir
$stderr.puts "Creating #{dir.sub(/^#{curr_dir}\//,'')}"
if File.exists?(File.join(File.expand_path("~/.planter"),File.basename(dir)))
FileUtils.cp_r(File.join(File.expand_path("~/.planter"),File.basename(dir)), dir)
else
Dir.mkdir(dir)
end
else
$stderr.puts "Skipping #{dir.sub(/^#{curr_dir}\//,'')} (file exists)"
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment