cowtech-lib 1.9.0

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "http://rubygems.org"
2
+
3
+ group :development do
4
+ gem "jeweler", "~> 1.5.1"
5
+ gem "rcov", ">= 0"
6
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,17 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ git (1.2.5)
5
+ jeweler (1.5.1)
6
+ bundler (~> 1.0.0)
7
+ git (>= 1.2.5)
8
+ rake
9
+ rake (0.8.7)
10
+ rcov (0.9.9)
11
+
12
+ PLATFORMS
13
+ ruby
14
+
15
+ DEPENDENCIES
16
+ jeweler (~> 1.5.1)
17
+ rcov
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Shogun
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,19 @@
1
+ = cowtech-lib
2
+
3
+ A general purpose utility library.
4
+ http://github.com/ShogunPanda/cowtech-lib
5
+
6
+ == Contributing to cowtech-lib
7
+
8
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
9
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
10
+ * Fork the project
11
+ * Start a feature/bugfix branch
12
+ * Commit and push until you are happy with your contribution
13
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
14
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
15
+
16
+ == Copyright
17
+
18
+ Copyright (c) 2011 Shogun. See LICENSE.txt for further details.
19
+
data/Rakefile ADDED
@@ -0,0 +1,16 @@
1
+ require 'rubygems'
2
+ require 'jeweler'
3
+ require "./lib/cowtech-lib/version.rb"
4
+
5
+ Jeweler::Tasks.new do |gem|
6
+ gem.name = "cowtech-lib"
7
+ gem.homepage = "http://github.com/ShogunPanda/cowtech-lib"
8
+ gem.license = "MIT"
9
+ gem.summary = %Q{A general purpose utility library.}
10
+ gem.description = %Q{A general purpose utility library.}
11
+ gem.email = "shogun_panda@me.com"
12
+ gem.authors = ["Shogun"]
13
+ gem.version = Cowtech::Lib::Version::STRING
14
+ end
15
+
16
+ Jeweler::RubygemsDotOrgTasks.new
@@ -0,0 +1,56 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{cowtech-lib}
8
+ s.version = "1.9.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Shogun"]
12
+ s.date = %q{2011-02-21}
13
+ s.description = %q{A general purpose utility library.}
14
+ s.email = %q{shogun_panda@me.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE.txt",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ "Gemfile",
22
+ "Gemfile.lock",
23
+ "LICENSE.txt",
24
+ "README.rdoc",
25
+ "Rakefile",
26
+ "cowtech-lib.gemspec",
27
+ "lib/cowtech-lib.rb",
28
+ "lib/cowtech-lib/console.rb",
29
+ "lib/cowtech-lib/option_parser.rb",
30
+ "lib/cowtech-lib/script.rb",
31
+ "lib/cowtech-lib/shell.rb",
32
+ "lib/cowtech-lib/version.rb"
33
+ ]
34
+ s.homepage = %q{http://github.com/ShogunPanda/cowtech-lib}
35
+ s.licenses = ["MIT"]
36
+ s.require_paths = ["lib"]
37
+ s.rubygems_version = %q{1.3.7}
38
+ s.summary = %q{A general purpose utility library.}
39
+
40
+ if s.respond_to? :specification_version then
41
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
42
+ s.specification_version = 3
43
+
44
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
45
+ s.add_development_dependency(%q<jeweler>, ["~> 1.5.1"])
46
+ s.add_development_dependency(%q<rcov>, [">= 0"])
47
+ else
48
+ s.add_dependency(%q<jeweler>, ["~> 1.5.1"])
49
+ s.add_dependency(%q<rcov>, [">= 0"])
50
+ end
51
+ else
52
+ s.add_dependency(%q<jeweler>, ["~> 1.5.1"])
53
+ s.add_dependency(%q<rcov>, [">= 0"])
54
+ end
55
+ end
56
+
@@ -0,0 +1,314 @@
1
+ # encoding: utf-8
2
+ #
3
+ # cowtech-lib
4
+ # Author: Shogun <shogun_panda@me.com>
5
+ # Copyright © 2011 and above Shogun
6
+ # Released under the MIT License, which follows.
7
+ #
8
+ # The MIT License
9
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
10
+ # of this software and associated documentation files (the "Software"), to deal
11
+ # in the Software without restriction, including without limitation the rights
12
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
+ # copies of the Software, and to permit persons to whom the Software is
14
+ # furnished to do so, subject to the following conditions:
15
+ #
16
+ # The above copyright notice and this permission notice shall be included in
17
+ # all copies or substantial portions of the Software.
18
+ #
19
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25
+ # THE SOFTWARE.
26
+ #
27
+
28
+ require "rexml/document"
29
+ require "open4"
30
+ require "find"
31
+ require "fileutils"
32
+
33
+ class String
34
+ def to_a
35
+ [self]
36
+ end
37
+ end
38
+
39
+ module CowtechLib
40
+ =begin rdoc
41
+ A class which provides some method to operate with files and to format pretty messages.
42
+ =end
43
+ class Console
44
+ public
45
+
46
+ # Indentation level
47
+ attr :indent_level
48
+
49
+ # Whether show executed commands
50
+ attr :show_commands
51
+
52
+ # Whether show output of executed commands
53
+ attr :show_outputs
54
+
55
+ # Whether simply print commands rather than executing them
56
+ attr :skip_commands
57
+
58
+ # Exit status for commands
59
+ attr_reader :statuses
60
+
61
+ # Indentation string(s)
62
+ attr :indentator, true
63
+
64
+ # Sets indentation level.
65
+ # Arguments:
66
+ # * <em>indent</em>: The new indentation level
67
+ # * <em></em>: If the level is absolute or relative to the current level
68
+ def indent_set(level, absolute = false)
69
+ @indent_level = Math.max((!absolute ? @indent_level : 0) + level, 0)
70
+ end
71
+
72
+ # Resets indentation level to 0.
73
+ def indent_reset
74
+ @indent_level = 0
75
+ end
76
+
77
+ # Execute codes in an indented block
78
+ def indent_region(level, absolute = false, &block)
79
+ old_level = @indent_level
80
+ self.indent_set(level, absolute)
81
+ yield
82
+ @indent_level = old_level
83
+ end
84
+
85
+ # Indents a message.
86
+ #
87
+ # Arguments:
88
+ # * <em>msg</em>: The message to indent
89
+ # * <em>add_additional</em>: Whether add extra space to align to initial message "*"
90
+ # Returns: The indentated message
91
+ def indent(msg, level = nil)
92
+ (@@indentator * (level || @indent_level)) + msg
93
+ end
94
+
95
+ =begin rdoc
96
+ Substitute tag with color.
97
+
98
+ Arguments:
99
+ * <em>node</em>: The node which operate on
100
+ * <em>stack</em>: The stack of old styles. <b>Do not set this by yourself!</b>
101
+
102
+ Returns: The new text
103
+ =end
104
+ def subst_color(node, stack = [])
105
+ rv = ""
106
+ styles = (node.name == "text" and node.attributes["style"]) ? node.attributes["style"].split(" ") : nil
107
+
108
+ # Add style of current tag
109
+ if styles then
110
+ styles.each do |style|
111
+ rv += @@styles[style] || ""
112
+ end
113
+
114
+ stack.push(styles)
115
+ end
116
+
117
+ # Now parse subnodes
118
+ node.children.each do |child|
119
+ if child.node_type == :text then
120
+ rv += child.to_s
121
+ elsif child.name == "text" then
122
+ rv += self.subst_color(child, stack)
123
+ end
124
+ end
125
+
126
+ # Remove style of current tag
127
+ if styles then
128
+ stack.pop()
129
+
130
+ # Restore previous style
131
+ (stack.pop || ["default"]).each do |style|
132
+ rv += @@styles[style]
133
+ end
134
+ end
135
+
136
+ rv
137
+ end
138
+
139
+ # Prints a message.
140
+ # Arguments:
141
+ # * <em>msg</em>: The message to print
142
+ # * <em>dots</em>: Whether add "..." to the message
143
+ # * <em>newline</em>: Whether add a newline to the message
144
+ # * <em>plain</em>: Whether ignore tags
145
+ # * <em>must_indent</em>: Whether indent the message
146
+ # * <em>internal</em>: If the method is called by another method. <b>Do not set this by yourself!</b>
147
+ def write(*args)
148
+ msg = args[:msg]
149
+
150
+ # Check some alternative syntax
151
+ [:begin, :warn, :error, :debug, :info, :right, :end].each do |t|
152
+ if args[t] then
153
+ msg = args[t]
154
+ args[:type] = :t
155
+ args[t] = nil
156
+ end
157
+ args[:fatal] = true if args[:status] == :fail
158
+
159
+ # Check for specific msg type
160
+ if [:begin, :warn, :error, :debug, :info].include?(args[:type]) then
161
+ mc = {:begin => "bold green", :warn => "bold yellow", :error => "bold red", :debug => "magenta", :info => "bold cyan"}
162
+ color = args[:color] || mc[args[:type]]
163
+
164
+ if args[:full_color] then
165
+ msg = "<text style=\"#{color}\">*</text> #{self.indent(msg)}"
166
+ else
167
+ msg = "<text style=\"#{color}\">* #{self.indent(msg)}</text>"
168
+ end
169
+ end
170
+
171
+ # Add dots and indentation if needed
172
+ msg = self.indent(msg + (args[:trailing_dots] ? "..." : ""), args[:indent] ? @indent_level : -1)
173
+
174
+ # Parse the message
175
+ unless args[:plain] then
176
+ begin
177
+ msg = self.parse_message(REXML::Document.new("<text>#{msg}</text>").root)
178
+ rescue Exception => e
179
+ print "[ERROR] Invalid message tagging, check XML syntax (or color requested) of the following message:\n\n\t#{msg}\n\n"
180
+ exit(1)
181
+ end
182
+ end
183
+
184
+ # Add newline if needed
185
+ msg += "\n" if args[:newline]
186
+
187
+ if args[:internal] then
188
+ msg
189
+ else
190
+ if [:end, :right].include?(args[:type]) then
191
+ # Get screen width
192
+ @tty_width = `tput cols`.to_i if @tty_width < 0
193
+
194
+ # Get padding
195
+ pad = @tty_width - msg.inspect.gsub(/(\\e\[[0-9]+m)|(\")|(\\n)/, "").length
196
+
197
+ print "\033[A" if args[:up]
198
+ print "\033[0G\033[#{pad}C"
199
+ end
200
+
201
+ print(msg)
202
+ end
203
+
204
+ exit(args[:code] || 0) if args[:exit_after] || args[:fatal]
205
+ end
206
+
207
+ # Syntatic sugar
208
+ # Prints a warning message.
209
+ def warn(msg, *args)
210
+ args[:warn] = msg
211
+ self.write(*args)
212
+ end
213
+
214
+ # Prints an error message.
215
+ def error(msg, *args)
216
+ args[:error] = msg
217
+ self.write(*args)
218
+ end
219
+
220
+ # Prints and error message then abort.
221
+ def fatal(msg, *args)
222
+ args[:error] = msg
223
+ args[:exit_after] = true
224
+ args[:code] ||= 1
225
+ self.write(*args)
226
+ end
227
+
228
+ # Prints an error status
229
+ def status(*args)
230
+ args[:end] = @@statuses[status] || @@statuses[:ok]
231
+ self.write(*args)
232
+ end
233
+
234
+ # Read input from the user.
235
+ #
236
+ # Arguments:
237
+ # * <em>msg</em>: The prompt to show
238
+ # * <em>valids</em>: A list of regexp to validate the input
239
+ # * <em>case_sensitive</em>: Wheter the validation is case_sensitive
240
+ #
241
+ # Returns: The read input
242
+ def read(*args)
243
+ # Adjust prompt
244
+ msg = args[:msg] + (msg !~ /([:?](\s*))$/) ? ":" : "")
245
+ msg += " " unless msg =~ / ^/
246
+
247
+ # Turn choices into regular expressions
248
+ regexps = (args[:valids] || []).to_a.collect do |valid|
249
+ unless valid.is_a?(Regexp) then
250
+ valid = Regexp.new((valid !~ /^\^/ ? "^" : "") + valid + (valid !~ /\$$/ ? "$" : ""), Regexp::EXTENDED + (args[:case_sensitive] ? Regexp::IGNORECASE : 0), "U")
251
+ else
252
+ valid
253
+ end
254
+ end
255
+
256
+ rv = nil
257
+
258
+ # Read input
259
+ while true do
260
+ # Show message
261
+ print(msg)
262
+
263
+ # Get reply
264
+ bufs = gets.chop()
265
+
266
+ # If we don't have any regexp
267
+ if regexps.length == 0 then
268
+ rv = bufs
269
+ break
270
+ end
271
+
272
+ # Validate inputs
273
+ regexps.each do |re|
274
+ if bufs =~ re then
275
+ rv = bufs
276
+ break
277
+ end
278
+ end
279
+
280
+ break if rv
281
+ self.write(:warn => "Sorry, your reply was not understood. Please try again")
282
+ end
283
+ end
284
+
285
+ # Create a new Console.
286
+ def initialize
287
+ @indent_level = 0
288
+ @show_commands = false
289
+ @show_outputs = false
290
+ @skip_commands = false
291
+ @tty_width = -1
292
+ @@indentator= " "
293
+
294
+ @@styles = {
295
+ # Default color
296
+ "default" => "\33[0m",
297
+ # Text style
298
+ "bold" => "\33[1m", "underline" => "\33[4m", "blink" => "\33[5m", "reverse" => "\33[7m", "concealed" => "\33[8m",
299
+ # Foreground colors
300
+ "black" => "\33[30m", "red" => "\33[31m", "green" => "\33[32m", "yellow" => "\33[33m", "blue" => "\33[34m", "magenta" => "\33[35m", "cyan" => "\33[36m", "white" => "\33[37m",
301
+ # Background colors
302
+ "bg_black" => "\33[40m", "bg_red" => "\33[41m", "bg_green" => "\33[42m", "bg_yellow" => "\33[43m", "bg_blue" => "\33[44m", "bg_magenta" => "\33[45m", "bg_cyan" => "\33[46m", "bg_white" => "\33[47m"
303
+ }
304
+
305
+ @@statuses = {
306
+ :ok => '<text style="bold blue">[ <text style="bold green">OK</text> ]</text> ',
307
+ :pass => '<text style="bold blue">[<text style="bold cyan">PASS</text>]</text> ',
308
+ :fail => '<text style="bold blue">[<text style="bold red">FAIL</text>]</text> ',
309
+ :warn => '<text style="bold blue">[<text style="bold yellow">WARN</text>]</text> ',
310
+ }
311
+ end
312
+ end
313
+ end
314
+