lib/hysh.rb in hysh-0.0.1 vs lib/hysh.rb in hysh-0.0.2
- old
+ new
@@ -21,20 +21,22 @@
WARN = :warn
RAISE = :raise
@@on_command_error = IGNORE
# :startdoc:
+ module_function
+
# :section: Common Utilities
# :call-seq:
# with_set_globals(var_name, val, ...) { ... }
#
# Set the global variable named +var_name+ (a string or symbol) to
# +val+, then run the block, return the return value of the block.
# Restore the original value of the variable upon returning.
# Multiple pairs of +var_name+ and +val+ can be specified.
- def self.with_set_globals(*var_vals)
+ def with_set_globals(*var_vals)
orig_var_vals = var_vals.each_slice(2).map { |var, val|
svar = var.to_s
unless svar.start_with? '$'
raise ArgumentError, "Invalid global variable name: #{svar}"
end
@@ -62,11 +64,11 @@
# +$stderr, etc.) to +io+ (redirection in Ruby), and arrange to
# redirect the +fd+ (usally 0, 1, 2, etc. to +io+ for the external
# programs, then run the block, return the return value of the
# block. Restore the original value of the variable and cancel the
# arrangement to external program redirections upon returning.
- def self.with_redirect_to(fd, var, io, &b)
+ def with_redirect_to(fd, var, io, &b)
@@redirections.push([fd, io]) if fd
if var
with_set_globals(var, io, &b)
else
yield
@@ -81,11 +83,11 @@
# Set the +$stdin+ to +io+ (redirection in Ruby), and arrange to
# redirect the file descriptor 0 to +io+ for the external programs,
# then run the block, return the return value of the block. Restore
# the original value of the $stdin and cancel the arrangement to
# external program redirections upon returning.
- def self.with_redirect_stdin_to(io, &b)
+ def with_redirect_stdin_to(io, &b)
with_redirect_to(0, :$stdin, io, &b)
end
# :call-seq:
# with_redirect_stdout_to(io) { ... }
@@ -93,11 +95,11 @@
# Set the +$stdout+ to +io+ (redirection in Ruby), and arrange to
# redirect the file descriptor 1 to +io+ for the external programs,
# then run the block, return the return value of the block. Restore
# the original value of the $stdout and cancel the arrangement to
# external program redirections upon returning.
- def self.with_redirect_stdout_to(io, &b)
+ def with_redirect_stdout_to(io, &b)
with_redirect_to(1, :$stdout, io, &b)
end
# :call-seq:
# with_redirect_stderr_to(io) { ... }
@@ -105,11 +107,11 @@
# Set the +$stderr+ to +io+ (redirection in Ruby), and arrange to
# redirect the file descriptor 2 to +io+ for the external programs,
# then run the block, return the return value of the block. Restore
# the original value of the $stderr and cancel the arrangement to
# external program redirections upon returning.
- def self.with_redirect_stderr_to(io, &b)
+ def with_redirect_stderr_to(io, &b)
with_redirect_to(2, :$stderr, io, &b)
end
# :call-seq:
# with_redirect_stdin_file(args...) { ... }
@@ -119,11 +121,11 @@
# (redirection in Ruby), and arrange to redirect the file descriptor
# 0 to the returned +io+ for the external programs, then run the
# block, return the return value of the block. Restore the original
# value of the $stdin and cancel the arrangement to external program
# redirections upon returning.
- def self.with_redirect_stdin_to_file(*args, &b)
+ def with_redirect_stdin_to_file(*args, &b)
File.open(*args) { |f|
with_redirect_stdin_to f, &b
}
end
@@ -135,11 +137,11 @@
# (redirection in Ruby), and arrange to redirect the file descriptor
# 1 to the returned +io+ for the external programs, then run the
# block, return the return value of the block. Restore the original
# value of the $stdout and cancel the arrangement to external
# program redirections upon returning.
- def self.with_redirect_stdout_to_file(*args, &b)
+ def with_redirect_stdout_to_file(*args, &b)
if args.size == 1
args.push "w"
end
File.open(*args) { |f|
with_redirect_stdout_to f, &b
@@ -154,20 +156,20 @@
# (redirection in Ruby), and arrange to redirect the file descriptor
# 2 to the returned +io+ for the external programs, then run the
# block, return the return value of the block. Restore the original
# value of the $stderr and cancel the arrangement to external
# program redirections upon returning.
- def self.with_redirect_stderr_to_file(*args, &b)
+ def with_redirect_stderr_to_file(*args, &b)
if args.size == 1
args.push "w"
end
File.open(*args) { |f|
with_redirect_stderr_to f, &b
}
end
- def self.__out_io(args, options, proc_arg) # :nodoc:
+ def __out_io(args, options, proc_arg) # :nodoc:
Tempfile.open(TEMP_BASE) { |tempf|
tempf.unlink
ret = nil
with_redirect_stdout_to(tempf) {
ret = __run args, options, proc_arg
@@ -188,11 +190,11 @@
# +options+ via stdout redirection. +command+ and +options+
# parameters are same as that of +Process.spawn+. Return the
# collected output string and the return value of the block or the
# function or exit success status of the external program as a two
# element array. Restore stdout redirection upon returning.
- def self.out_s(*args, &blk)
+ def out_s(*args, &blk)
__out_io(*__parse_args(args, blk)) { |tempf|
tempf.read
}
end
@@ -201,11 +203,11 @@
# out_ss(function) -> [string, any]
# out_ss(command...[, options]) -> [string, true or false]
#
# Same as out_s, except the collected output string are right
# stripped before return.
- def self.out_ss(*args_in, &blk)
+ def out_ss(*args_in, &blk)
s, ret = out_s(*args_in, &blk)
[s.rstrip, ret]
end
# :call-seq:
@@ -227,11 +229,11 @@
# program specified via +command+ and +options+ via stdout
# redirection. +command+ and +options+ are same as that of
# +Process.spawn+. Feed each line of output to the block as +line+.
# Return the exit success status of the forked sub-process or the
# external program. Restore stdout redirection upon returning.
- def self.out_lines(*args_in, &blk)
+ def out_lines(*args_in, &blk)
args, options, proc_arg = __parse_args args_in
if block_given?
__popen(nil, true, nil, args, options, proc_arg) { |pid, stdin, stdout, stderr|
stdout.each_line(&blk)
Process.waitpid pid
@@ -248,11 +250,11 @@
# out_err_s() { ... } -> [string, any]
# out_err_s(function) -> [string, any]
# out_err_s(command...[, options]) -> [string, true or false]
#
# Same as out_s, except collect output of stderr too.
- def self.out_err_s(*args_in, &blk)
+ def out_err_s(*args_in, &blk)
args, options, proc_arg = __parse_args args_in, blk
Tempfile.open(TEMP_BASE) { |tempf|
tempf.unlink
ret = nil
with_redirect_stdout_to(tempf) {
@@ -271,16 +273,16 @@
# out_err_ss(function) -> [string, any]
# out_err_ss(command...[, options]) -> [string, true or false]
#
# Same as out_err_s, except the collected output string are right
# stripped before return.
- def self.out_err_ss(*args_in, &blk)
+ def out_err_ss(*args_in, &blk)
s, ret = out_err_s(*args_in, &blk)
[s.rstrip. ret]
end
- def self.__in_io(args, options, proc_arg) # :nodoc:
+ def __in_io(args, options, proc_arg) # :nodoc:
Tempfile.open(TEMP_BASE) { |tempf|
tempf.unlink
yield tempf
tempf.rewind
with_redirect_stdin_to(tempf) {
@@ -299,11 +301,11 @@
# program specified via +command+ and +options+ via stdin
# redirection. +command+ and +options+ are same as that of
# +Process.spawn+. Return the return value of the block or the
# function or the exit success status of the external program.
# Restore stdin redirection upon returning.
- def self.in_s(s, *args_in, &blk)
+ def in_s(s, *args_in, &blk)
args, options, proc_arg = __parse_args args_in, blk
__in_io(args, options, proc_arg) { |tempf|
tempf.write s
}
end
@@ -313,11 +315,11 @@
# in_lines(lines, function) -> any
# in_lines(lines, command...[, options]) -> true or false
#
# Same as +in_s+, except input string are specified via +lines+
# (Array of String).
- def self.in_lines(lines, *args_in, &blk)
+ def in_lines(lines, *args_in, &blk)
args, options, proc_arg = __parse_args args_in, blk
__in_io(args, options, proc_arg) { |tempf|
lines.each { |line| tempf.write line }
}
end
@@ -327,11 +329,11 @@
# io_s(string, function) -> [string, any]
# io_s(stirng, command...[, options]) -> [string, true or false]
#
# Redirect the stdin and stdout like that of +in_s+ and +out_s+,
# return value is same of +out_s+.
- def self.io_s(s, *args_in, &blk)
+ def io_s(s, *args_in, &blk)
in_s(s) {
out_s {
run *args_in, &blk
}
}
@@ -342,11 +344,11 @@
# io_ss(string, function) -> [string, any]
# io_ss(stirng, command...[, options]) -> [string, true or false]
#
# Same as +io_s+, except the output string is right stripped before
# returning.
- def self.io_ss(s, *args_in, &blk)
+ def io_ss(s, *args_in, &blk)
s = io_s(s, *args_in, &blk)
s.rstrip
end
# :section: Run Process
@@ -355,35 +357,35 @@
# ignore_on_command_error() { ... }
#
# When running the block, the non-zero exit status of running
# external program are ignored. The original behavior is restored
# upon returning.
- def self.ignore_on_command_error(&b)
+ def ignore_on_command_error(&b)
with_set_globals(:@@on_command_error, IGNORE, &b)
end
# :call-seq:
# warn_on_command_error() { ... }
#
# When running the block, the warning message will be print to
# $stderr when the external program exited with non-zero status.
# The original behavior is restored upon returning.
- def self.warn_on_command_error(&b)
+ def warn_on_command_error(&b)
with_set_globals(:@@on_command_error, WARN, &b)
end
# :call-seq:
# raise_on_command_error() { ... }
#
# When running the block, an +Hysh::CommandError+ exception will be
# raised when the external program exited with non-zero status. The
# original behavior is restored upon returning.
- def self.raise_on_command_error(&b)
+ def raise_on_command_error(&b)
with_set_globals(:@@on_command_error, RAISE, &b)
end
- def self.__parse_args(args, blk = nil) # :nodoc:
+ def __parse_args(args, blk = nil) # :nodoc:
args = [args] unless args.is_a? Array
if args.last.is_a?(Hash)
options = args.pop
else
options = {}
@@ -408,11 +410,11 @@
# specified via parameters. The +env_var+ specifies the environment
# variable name, and the +val+ specifies the value, when +val+ is
# nil, the envioronment variable will be removed. Multiple pairs of
# the environment variable names and values can be specified. The
# changes to the environment are restored upon returning.
- def self.with_change_env(*var_vals)
+ def with_change_env(*var_vals)
orig_var_vals = var_vals.each_slice(2).map { |var, val|
orig_val = ENV[var]
[var, orig_val]
}
var_vals.each_slice(2) { |var, val|
@@ -429,15 +431,15 @@
# :call-seq:
# chdir(dir) { ... }
#
# Same as +Dir.chdir+.
- def self.chdir(dir, &b)
+ def chdir(dir, &b)
Dir.chdir(dir, &b)
end
- def self.__spawn(args, options_in, proc_arg) # :nodoc:
+ def __spawn(args, options_in, proc_arg) # :nodoc:
if proc_arg
Process.fork {
fclose = options_in[:close] || []
fclose.each { |f| f.close }
fin = options_in[0]
@@ -471,11 +473,11 @@
#
# Run the block or the function specified via +function+ in a forked
# sub-process, or run external program specified via +command+ and
# +options+, +command+ and +options+ are same as that of
# Process.spawn. Return the +pid+.
- def self.spawn(*args_in, &blk)
+ def spawn(*args_in, &blk)
__spawn *__parse_args(args_in, blk)
end
# Exception class raised when an external program exits with
# non-zero status and raise_on_command_error take effect.
@@ -502,11 +504,11 @@
attr_reader :cmdline
# External program exit status, as Process:Status
attr_reader :status
end
- def self.__check_command_status(cmd) # :nodoc:
+ def __check_command_status(cmd) # :nodoc:
unless $?.success?
if @@on_command_error != IGNORE
err = CommandError.new(cmd, $?)
case @@on_command_error
when WARN
@@ -519,11 +521,11 @@
else
true
end
end
- def self.__run(args, options, proc_arg) #:nodoc:
+ def __run(args, options, proc_arg) #:nodoc:
if proc_arg
args.first.()
else
pid = __spawn args, options, proc_arg
Process.waitpid pid
@@ -541,23 +543,23 @@
# +command+ and +options+, +command+ and +options+ are same as that
# of Process.spawn and return whether external program the exit with
# 0. All IO redirections, environment change, current directory
# change, etc. will take effect when running the block, the function
# and the external program.
- def self.run(*args_in, &blk)
+ def run(*args_in, &blk)
__run *__parse_args(args_in, blk)
end
- def self.__check_close(*ios) # :nodoc:
+ def __check_close(*ios) # :nodoc:
ios.each { |io|
if io && !io.closed?
io.close
end
}
end
- def self.__popen(stdin, stdout, stderr, args, options, proc_arg) # :nodoc:
+ def __popen(stdin, stdout, stderr, args, options, proc_arg) # :nodoc:
options[:close] = [] if proc_arg
stdin_in = stdin_out = nil
stdout_in = stdout_out = nil
stderr_in = stderr_out = nil
@@ -622,11 +624,11 @@
# closed and the process will be detached if necessary upon
# returning.
#
# If no block is given, the pid and stdin, stdout and stderr pipe
# will be returned.
- def self.popen(stdin, stdout, stderr, *args_in, &blk)
+ def popen(stdin, stdout, stderr, *args_in, &blk)
args, options, proc_arg = __parse_args args_in
options[:close] = [] if proc_arg
__popen(stdin, stdout, stderr, args, options, proc_arg, &blk)
end
@@ -653,11 +655,11 @@
# [command, ..., options] # command with argument and options in an array
# [command, ...] # command with/without arguments in an array
# command # command without argument
# [function] # function in an array
# function # function
- def self.pipe(*cmds, &blk)
+ def pipe(*cmds, &blk)
if block_given?
cmds.push [blk]
end
if cmds.empty?
raise ArgumentError.new('No argument or block!')
@@ -732,11 +734,11 @@
#
# Run the functions and the external programs specified via
# +command_line+, and the block if given, from left to right.
# +command_line+ is same as that of +pipe+. Return the return value
# or exit success status of the last function or external command.
- def self.run_seq(*cmds, &blk)
+ def run_seq(*cmds, &blk)
if block_given?
cmds.push blk
end
ret = true
cmds.each { |cmd|
@@ -755,11 +757,11 @@
# block returns non-nil/false, or any external program exits
# successfully, stop running the remaining function, or external
# program and return the value. If all failed, false or nil will be
# returned. If no function, external program, or block is given,
# return false.
- def self.run_or(*cmds, &blk)
+ def run_or(*cmds, &blk)
if block_given?
cmds.push blk
end
return false if cmds.empty?
@@ -785,11 +787,11 @@
# stop running the remaining function, or external program and
# return the value. If all succeed, return the return value of the
# last function, the block or the exit success status of the
# external program. If no function, external program, or block is
# provided, return true.
- def self.run_and(*cmds, &blk)
+ def run_and(*cmds, &blk)
if block_given?
cmds.push blk
end
return true if cmds.empty?
@@ -809,11 +811,11 @@
# :call-seq:
# filter_line() { |line| ... } -> true
#
# Feed each line from $stdin to the block, if non-nil/false
# returned, write the return value to the $stdout.
- def self.filter_line
+ def filter_line
$stdin.each_line { |line|
if ret_line = yield(line)
$stdout.write ret_line
end
}
@@ -823,14 +825,61 @@
# :call-seq:
# filter_char() { |char| ... } -> true
#
# Feed each character from $stdin to the block, if non-nil/false
# returned, write the return value to the $stdout.
- def self.filter_char
+ def filter_char
$stdin.each_char { |ch|
if ret_ch = yield(ch)
$stdout.write ret_ch
end
}
true
end
+
+ def __with_add_hysh_to_self(s, &blk) # :nodoc:
+ sclass = s.singleton_class
+ mm_defined = sclass.instance_methods(false).include? :method_missing
+ mm_defined ||= sclass.private_instance_methods(false).include? :method_missing
+ class << s
+ alias __hysh_origin_method_missing__ method_missing
+ def method_missing(m, *args, &blk)
+ __hysh_origin_method_missing__ m, args, &blk
+ rescue NoMethodError
+ if Hysh.singleton_class.public_method_defined? m
+ Hysh.send m, *args, &blk
+ else
+ Hysh.run m.to_s, *args.map { |a| a.to_s }, &blk
+ end
+ end
+ end
+ s.instance_eval &blk
+ ensure
+ class << s
+ remove_method :method_missing
+ end
+ if mm_defined
+ class << s
+ alias method_missing __hysh_origin_method_missing__
+ end
+ end
+ class << s
+ remove_method :__hysh_origin_method_missing__
+ end
+ end
+end
+
+# :call-seq:
+# hysh_script { ... }
+#
+# Call the block, in addition to the methods, variables reference of
+# current self object, the public methods in Hysh module can be called
+# directly too, and all other method callings are regarded as external
+# program running. That is, if there is no ls method defined for
+# self, you can run it via
+#
+# hysh_script {
+# ls
+# }
+def hysh_script(&blk)
+ Hysh.__with_add_hysh_to_self(self, &blk)
end