I recently needed to write code to check Ruby syntax. The Open3 library made it trivial. From the RDoc:
Open3 grants you access to stdin, stdout, and stderr when running another program.
Here's the code for the syntax checker. I also added an example of using Open3 with wc to print out how many lines of code the file contained.
require "open3" class SyntaxChecker def self.check(ruby) Open3.popen3 "ruby -wc" do |stdin, stdout, stderr| stdin.write ruby stdin.close output = stdout.read errors = stderr.read SyntaxCheckResult.new(output.any? ? output : errors) end end end class SyntaxCheckResult def initialize(output) @valid = (output == "Syntax OK\n") @output = output end def line_of_error $1.to_i if @output =~ /^-:(\d+):/ end def valid? @valid end end l, w, c = Open3.popen3 "wc" do |stdin, stdout, stderr| stdin.write File.read($0) stdin.close stdout.read.split end puts "This file contains #{l} lines, #{w} words, and #{c} characters." if __FILE__ == $0 require "test/unit" class SyntaxCheckerTest < Test::Unit::TestCase def test_valid_syntax result = SyntaxChecker.check "this.is.valid.syntax" assert_equal true, result.valid? end def test_invalid_syntax result = SyntaxChecker.check "this.is -> not -> valid $ruby:syntax" assert_equal false, result.valid? end def test_invalid_syntax_line_number result = SyntaxChecker.check "line(1).is.okay\nline(2) is not :(" assert_equal 2, result.line_of_error end end end
Also see POpen4:
POpen4 provides the Rubyist a single API across platforms for executing a command in a child process with handles on stdout, stderr, stdin streams as well as access to the process ID and exit status.