diff --git a/bin/csv-filter b/bin/csv-filter new file mode 100755 index 00000000..9dab8f4e --- /dev/null +++ b/bin/csv-filter @@ -0,0 +1,28 @@ +#!/usr/bin/env ruby + +require 'optparse' +require 'csv' + +options = {} + +parser = OptionParser.new + +parser.version = CSV::VERSION +parser.banner = <<-BANNER +Usage: #{parser.program_name} [options] + + Reads and parses the CSV text content of the standard input per the given input options. + From that content, generates CSV text per the given output options + and writes that text to the standard output. +BANNER + +begin + parser.parse! +rescue OptionParser::InvalidOption + $stderr.puts($!.message) + $stderr.puts(parser) + exit(false) +end + +CSV.filter(**options) do |row| +end diff --git a/csv.gemspec b/csv.gemspec index f5cf5827..f5ac1f07 100644 --- a/csv.gemspec +++ b/csv.gemspec @@ -38,6 +38,7 @@ Gem::Specification.new do |spec| end end spec.files = files + spec.executables = ["csv-filter"] spec.rdoc_options.concat(["--main", "README.md"]) rdoc_files = [ "LICENSE.txt", diff --git a/test/csv/test_csv_filter.rb b/test/csv/test_csv_filter.rb new file mode 100644 index 00000000..20fbe2af --- /dev/null +++ b/test/csv/test_csv_filter.rb @@ -0,0 +1,74 @@ +# frozen_string_literal: false + +require_relative "helper" + +class TestCSVFilter < Test::Unit::TestCase + def setup + @csv = <<-CSV +aaa,bbb,ccc +ddd,eee,fff + CSV + end + + # Return stdout and stderr from CLI execution. + def run_csv_filter(csv, *options) + top_dir = File.join(__dir__, "..", "..") + csv_filter = File.join(top_dir, "bin", "csv-filter") + if File.exist?(csv_filter) + # In-place test + command_line = [ + Gem.ruby, + "-I", + File.join(top_dir, "lib"), + csv_filter, + *options, + ] + else + # Gem test + command_line = [ + Gem.ruby, + "-S", + "csv-filter", + *options, + ] + end + Tempfile.create("stdout", mode: File::RDWR) do |stdout| + Tempfile.create("stderr", mode: File::RDWR) do |stderr| + Tempfile.create(["csv-filter", ".csv"]) do |input| + input.write(csv) + input.close + system(*command_line, in: input.path, out: stdout, err: stderr) + stdout.rewind + stderr.rewind + [stdout.read, stderr.read] + end + end + end + end + + # Test for invalid option. + def test_invalid_option + output, error = run_csv_filter("", "-Z") + assert_equal(["", "invalid option: -Z\n"], + [output, error.lines.first]) + end + + # Test for no options. + def test_no_options + assert_equal([@csv, ""], + run_csv_filter(@csv)) + end + + # Tests for general options. + + def test_option_h + output, error = run_csv_filter("", "-h") + assert_equal(["Usage: csv-filter [options]\n", ""], + [output.lines.first, error]) + end + + def test_option_v + assert_equal(["csv-filter #{CSV::VERSION}\n", ""], + run_csv_filter("", "-v")) + end +end