-
Notifications
You must be signed in to change notification settings - Fork 0
/
build.rb
executable file
·147 lines (114 loc) · 3.34 KB
/
build.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#!/usr/bin/env ruby
require 'optparse'
require 'json'
require 'plist'
require 'listen'
class Hash
def symbolize_keys
symbolized_hash = Hash.new
self.each { |k, v| symbolized_hash[k.to_sym] = v }
symbolized_hash
end
end
class ThemeBuilder
attr_reader :scopes
def initialize(params)
log "Initializing ThemeBuilder"
log params
@config_path = params[:config_path]
@current_dir = File.dirname(__FILE__)
@src_dir = "#{@current_dir}/#{params[:source_directory]}"
@debug = params[:debug]
end
def log(message)
p " > #{message}" if @debug
end
def build
@meta = {}
@scopes = []
read_config
source_files.each do |file|
process_file(file)
end
save_theme
end
def source_files
glob_string = "#{@src_dir}/**/*.json"
Dir.glob(glob_string)
end
def read_source_file(path)
JSON.parse( replace_colors( File.read(path) ) ).symbolize_keys
end
def read_config
@config = JSON.parse( File.read(@config_path) ).symbolize_keys
@colors = @config[:colors]
end
def process_file(path)
contents = read_source_file(path)
@scopes.concat(contents[:settings])
@meta[:author] = contents[:author] if contents[:author]
@meta[:colorSpaceName] = contents[:colorSpaceName] if contents[:colorSpaceName]
@meta[:gutterSettings] = contents[:gutterSettings] if contents[:gutterSettings]
@meta[:uuid] = contents[:uuid] if contents[:uuid]
@meta[:name] = contents[:name] if contents[:name]
@meta[:semanticClass] = contents[:semanticClass] if contents[:semanticClass]
end
def replace_colors(body)
ret = body
@colors.each_pair do |color_key, color_value|
ret = ret.gsub("{{ #{color_key} }}", color_value)
end
ret
end
def save_theme
log "Saving theme #{@config[:outfile]}"
theme_data = {
author: @meta[:author],
colorSpaceName: @meta[:colorSpaceName],
gutterSettings: @meta[:gutterSettings],
uuid: @meta[:uuid],
name: @meta[:name],
semanticClass: @meta[:semanticClass],
settings: @scopes
}
write_outfile(theme_data)
end
def write_outfile(theme_data)
File.open(@config[:outfile], 'w') {|file| file.write(theme_data.to_plist)}
end
end
options = {
watch: false,
config_path: 'builder-config.json',
source_directory: 'src',
debug: false
}
OptionParser.new do |opts|
opts.banner = "Usage: build.rb [options]"
opts.on("-w", "--watch", "Watch for changes and recompile when changes are detected") do |v|
options[:watch] = true
end
opts.on("--config [PATH]", "Specify path to builder configuration file") do |v|
options[:config_path] = v unless v.nil?
end
opts.on("--source [PATH]", "Specify path to theme source files") do |v|
options[:source_directory] = v unless v.nil?
end
opts.on("-v", "--verbose", "Verbose log output") do |v|
options[:debug] = true
end
end.parse!
puts " >> ThemeBuilder Options: #{options.inspect}"
builder = ThemeBuilder.new(options)
builder.build
if options[:watch]
puts "Listening for changes in #{options[:source_directory]}..."
listener = Listen.to(options[:source_directory]) do |modified, added, removed|
puts " > modified: #{modified}" unless modified.empty?
puts " > added: #{added}" unless added.empty?
puts " > removed: #{removed}" unless removed.empty?
builder.build
end
listener.start
sleep
end