sugamasao-saag 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.
Files changed (6) hide show
  1. data/ChangeLog +3 -0
  2. data/README +40 -0
  3. data/TODO +5 -0
  4. data/bin/saag +17 -0
  5. data/lib/saag.rb +239 -0
  6. metadata +80 -0
data/ChangeLog ADDED
@@ -0,0 +1,3 @@
1
+ 2009-06-21 sugamasao@gmail.com
2
+
3
+ * Version 0.1.0 : 1st Release
data/README ADDED
@@ -0,0 +1,40 @@
1
+ = saag
2
+
3
+ == Description
4
+
5
+ SASS automatic monitor and generate CSS file.
6
+ SASS ファイルを監視し、変更があれば即座に CSS ファイルへ変換します。
7
+ 手動で以下のコマンドを行うのと同等です。
8
+ % sass hoge.sass hoge.css
9
+
10
+ == Gem Installation
11
+
12
+ gem install sugamasao-saag --source http://gems.github.com
13
+
14
+ == Features/Problems
15
+
16
+ * Ruby 1.8.7 でのみ、動作確認を行っています
17
+ * 事前にSASS(HAML)のインストールが必要になります
18
+
19
+ == Synopsis
20
+
21
+ 使用例:
22
+ % saag
23
+  引数を使用しない場合、コマンド実行者のカレントディレクトリを基点とし、*.sass ファイルを探し、対象ファイルとします。
24
+ また、出力される CSS ファイルは sass ファイルと同じ階層になります。
25
+
26
+ % saag -i /path/to/sass
27
+ -i オプションを使用することで、sass ファイルのあるディレクトリ(ファイル名でも可)を指定する事が可能です。
28
+ 出力先は、上記と同様に、sass ファイルのあるディレクトリになります。
29
+
30
+ % saag -i /path/to/sass -o /path/to/css
31
+ -o オプションを使用することで、css の出力先ファイルを指定することができます。
32
+ 出力先ファイルのディレクトリ構成は、-i オプションに依存します。
33
+ 上記のオプションを指定、/path/to/sass/sub_dir/hoge.sass があった場合、出力先ディレクトリは
34
+ /path/to/css/sub_dir/hoge.css となります。
35
+
36
+ == Copyright
37
+
38
+ Author:: sugamasao <sugamasao@gmail.com>
39
+ License:: Ruby's
40
+
data/TODO ADDED
@@ -0,0 +1,5 @@
1
+ = TODO List
2
+
3
+ * GUI Interface
4
+ * Plugin Function
5
+
data/bin/saag ADDED
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+ # $Id$
3
+
4
+ # lib のパスを追加しておく
5
+ $LOAD_PATH.unshift(File.expand_path("#{File.dirname(__FILE__)}/../lib/"))
6
+
7
+ begin
8
+ require 'saag'
9
+ require 'sass'
10
+ rescue LoadError
11
+ require 'rubygems'
12
+ require 'saag'
13
+ require 'sass'
14
+ end
15
+
16
+ Saag.new(ARGV).run
17
+
data/lib/saag.rb ADDED
@@ -0,0 +1,239 @@
1
+ # $Id$
2
+
3
+ require 'optparse'
4
+ require 'logger'
5
+ require 'pp'
6
+
7
+ class Saag
8
+ Version = '0.1.0'
9
+ SASS_EXT = '.sass'
10
+ CSS_EXT = '.css'
11
+
12
+ def initialize(argv = [])
13
+ # parse option
14
+ @conf = {}
15
+ @exit = false
16
+ @logger = Logger.new(STDOUT)
17
+ @logger.level = Logger::INFO # default Log Level
18
+
19
+ begin
20
+ OptionParser.new do |opt|
21
+ opt.on('-i', '--input_path=VAL', 'input file path(directory or filename)') {|v| @conf[:in_path] = set_dir_path(v)}
22
+ opt.on('-o', '--output_path=VAL', 'generated css file output path') {|v| @conf[:out_path] = set_dir_path(v)}
23
+ opt.on('-r', '--render_opt=VAL', 'sass render option [nested or expanded or compact or compressed]' ){|v| @conf[:render_opt] = set_render_opt(v)}
24
+ opt.on('-v', '--version', 'show version' ){puts "#{self.class} #{Version}"; exit 1}
25
+ opt.on('-d', '--debug', 'log level to debug') {|v| @conf[:debug] = v}
26
+ end.parse!(argv)
27
+ rescue OptionParser::InvalidOption, OptionParser::MissingArgument => e
28
+ @logger.error('invalid args...! looks for "-h" option')
29
+ exit 1
30
+ end
31
+
32
+ @logger.info("sass file watching start... [app ver=#{Version}]")
33
+ @logger.level = Logger::DEBUG if @conf[:debug]
34
+
35
+ @logger.debug("args input_path => #{@conf[:in_path]}")
36
+ @logger.debug("args output_path => #{@conf[:out_path]}")
37
+ @logger.debug("args render_opt => #{@conf[:render_opt]}")
38
+
39
+ set_default_conf()
40
+ set_signal()
41
+
42
+ @logger.info("watching directory => #{@conf[:in_path]}")
43
+ @logger.info("output directory => #{@conf[:out_path]}")
44
+ end
45
+
46
+ def run
47
+ old_list = []
48
+ # メインループ
49
+ begin
50
+ loop do
51
+ old_list = main_loop(old_list)
52
+ break if @exit # SIGNAL を受けたりすると true
53
+ sleep 1
54
+ end
55
+ rescue SystemCallError => e
56
+ @logger.error("File I/O Error! [#{e.message}]")
57
+ rescue => e
58
+ @logger.error("FATLE Error! [#{e.message}]")
59
+ end
60
+
61
+ @logger.info("sass file watching exit...")
62
+ end
63
+
64
+ private
65
+
66
+ def main_loop(old_list)
67
+ return nil if @exit # SIGNAL を受けていたら処理を抜ける
68
+ new_list = get_file_list(@conf[:in_path])
69
+
70
+ return nil if @exit # SIGNAL を受けていたら処理を抜ける
71
+ file_list = check_file_list(old_list, new_list)
72
+
73
+ return nil if @exit # SIGNAL を受けていたら処理を抜ける
74
+ file_list.each do |sass_file|
75
+ if sass_file[:change]
76
+ @logger.info("change file found. => #{sass_file[:path]}")
77
+ css_text = Sass::Engine.new(File.read(sass_file[:path]), {:style => @conf[:render_opt] }).render
78
+ write_css_file(sass_file, css_text)
79
+ end
80
+ end
81
+
82
+ return new_list
83
+ end
84
+
85
+ # 絶対パスにし、ディレクトリの場合は最後尾にスラッシュを付ける
86
+ def set_dir_path(path)
87
+ path = File.expand_path(path)
88
+ path = path + '/' if File.directory?(path)
89
+ return path
90
+ end
91
+
92
+ def set_signal
93
+ begin
94
+ Signal.trap(:INT){
95
+ @logger.debug("Signal Trapping [:INT]")
96
+ @exit = true
97
+ }
98
+ rescue ArgumentError => e
99
+ @logger.debug("Signal Setting Error[#{e.message}]")
100
+ end
101
+
102
+ begin
103
+ Signal.trap(:TERM){
104
+ @logger.debug("Signal Trapping [:TERM]")
105
+ @exit = true
106
+ }
107
+ rescue ArgumentError => e
108
+ @logger.debug("Signal Setting Error[#{e.message}]")
109
+ end
110
+
111
+ begin
112
+ Signal.trap(:HUP){
113
+ @logger.debug("Signal Trapping [:HUP]")
114
+ @exit = true
115
+ }
116
+ rescue ArgumentError => e
117
+ @logger.debug("Signal Setting Error[#{e.message}]")
118
+ end
119
+
120
+ begin
121
+ Signal.trap(:BREAK){
122
+ @logger.debug("Signal Trapping [:BREAK]")
123
+ @exit = true
124
+ }
125
+ rescue ArgumentError => e
126
+ @logger.debug("Signal Setting Error[#{e.message}]")
127
+ end
128
+ end
129
+
130
+ def set_render_opt(input_opt)
131
+ opt = ""
132
+ case input_opt.downcase
133
+ when 'nested'
134
+ opt = :nested
135
+ when 'expanded'
136
+ opt = :expanded
137
+ when 'compact'
138
+ opt = :compact
139
+ when 'compressed'
140
+ opt = :compressed
141
+ else
142
+ opt = :nested
143
+ end
144
+
145
+ return opt
146
+ end
147
+
148
+ def set_default_conf()
149
+ if @conf[:in_path].nil? or @conf[:in_path].empty?
150
+ @conf[:in_path] = Dir.pwd + '/'
151
+ end
152
+ if @conf[:out_path].nil? or @conf[:out_path].empty?
153
+ if File.directory?(@conf[:in_path])
154
+ @conf[:out_path] = @conf[:in_path]
155
+ else
156
+ @conf[:out_path] =File.dirname( @conf[:in_path]) + '/'
157
+ end
158
+ end
159
+ if @conf[:render_opt].nil? or @conf[:render_opt].empty?
160
+ @conf[:render_opt] = :nested
161
+ end
162
+ end
163
+
164
+ # ファイルのパスと時刻のリストを作成する
165
+ def get_file_list(in_path)
166
+ list = []
167
+ if File.file?(in_path)
168
+ list << create_file_data(in_path)
169
+ else
170
+ list = Dir.glob("#{in_path}**/*#{SASS_EXT}").map do |m|
171
+ if File.file?(m)
172
+ create_file_data(m)
173
+ end
174
+ end
175
+ end
176
+
177
+ return list.compact
178
+ end
179
+
180
+ def create_file_data(path)
181
+ # 入力パスと実ファイルのパスの差分を出す(この差分が出力ディレクトリの連結パスとなる)
182
+ sub_path = ""
183
+ @logger.debug("create_file_data@path => [#{path}]")
184
+ @logger.debug("create_file_data@in_path => [#{@conf[:in_path]}]")
185
+ if path =~ /#{@conf[:in_path]}(.+)/
186
+ sub_path = $1
187
+ end
188
+ data = {
189
+ :path => path,
190
+ :sub_path => sub_path,
191
+ :time => File.mtime(path),
192
+ :change => true
193
+ }
194
+ @logger.debug("create_file_data@sub_path => #{sub_path}")
195
+ return data
196
+ end
197
+
198
+ def check_file_list(old_list, new_list)
199
+ return new_list if old_list.empty?
200
+
201
+ new_list.each do |new|
202
+ old_list.each do |old|
203
+ if(new[:path] == old[:path])
204
+ if(new[:time] > old[:time])
205
+ new[:change] = true
206
+ else
207
+ new[:change] = false
208
+ end
209
+ end
210
+ end
211
+ end
212
+
213
+ return new_list
214
+ end
215
+
216
+ def write_css_file(sass_file, css_text)
217
+ @logger.debug("@conf[:out_path] = #{@conf[:out_path]}, sass_file[:sub_path] = #{sass_file[:sub_path]}")
218
+ out_dir = ""
219
+ if sass_file[:sub_path].empty?
220
+ out_dir = @conf[:out_path]
221
+ else
222
+ out_dir = File.dirname(@conf[:out_path] + sass_file[:sub_path]) + '/'
223
+ end
224
+ filename = out_dir + File.basename(sass_file[:path], SASS_EXT) + CSS_EXT
225
+ @logger.debug("out_dir => #{out_dir}")
226
+
227
+ # ディレクトリが無ければ作成する
228
+ unless File.directory?(out_dir)
229
+ FileUtils.mkdir_p(out_dir)
230
+ @logger.info("create output directory => #{out_dir}")
231
+ end
232
+
233
+ File.open(filename, 'w') do |f|
234
+ f.puts(css_text)
235
+ end
236
+ @logger.info("generate css file => #{filename}")
237
+ end
238
+ end
239
+
metadata ADDED
@@ -0,0 +1,80 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sugamasao-saag
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - sugamasao
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-06-24 00:00:00 -07:00
13
+ default_executable:
14
+ - saag
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: haml
18
+ type: :runtime
19
+ version_requirement:
20
+ version_requirements: !ruby/object:Gem::Requirement
21
+ requirements:
22
+ - - ">="
23
+ - !ruby/object:Gem::Version
24
+ version: "0"
25
+ version:
26
+ description: SAss Automatic monitor and Generate css file.
27
+ email: sugamasao@gmail.com
28
+ executables:
29
+ - saag
30
+ extensions: []
31
+
32
+ extra_rdoc_files:
33
+ - ChangeLog
34
+ - README
35
+ - TODO
36
+ files:
37
+ - ChangeLog
38
+ - README
39
+ - bin/saag
40
+ - lib/saag.rb
41
+ - TODO
42
+ has_rdoc: false
43
+ homepage: http://github.com/sugamasao/saag
44
+ post_install_message:
45
+ rdoc_options:
46
+ - --title
47
+ - saag documentation
48
+ - --charset
49
+ - utf-8
50
+ - --opname
51
+ - index.html
52
+ - --line-numbers
53
+ - --main
54
+ - README
55
+ - --inline-source
56
+ - --exclude
57
+ - ^(examples|extras)/
58
+ require_paths:
59
+ - lib
60
+ required_ruby_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: 1.8.6
65
+ version:
66
+ required_rubygems_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: "0"
71
+ version:
72
+ requirements: []
73
+
74
+ rubyforge_project:
75
+ rubygems_version: 1.2.0
76
+ signing_key:
77
+ specification_version: 3
78
+ summary: SAss Automatic monitor and Generate css file.
79
+ test_files: []
80
+