Class: Jrf::CLI

Inherits:
Object
  • Object
show all
Defined in:
lib/jrf/cli.rb,
lib/jrf/cli/runner.rb

Defined Under Namespace

Classes: Runner

Constant Summary collapse

USAGE =
"usage: jrf [options] 'STAGE >> STAGE >> ...'"
HELP_TEXT =
<<~'TEXT'
  usage: jrf [options] 'STAGE >> STAGE >> ...'

  JSON filter with the power and speed of Ruby.

  Options:
    -v, --verbose  print parsed stage expressions
    --lax          allow multiline JSON texts; split inputs by whitespace (also detects JSON-SEQ RS 0x1e)
    -p, --pretty   pretty-print JSON output instead of compact NDJSON
    --atomic-write-bytes N
                   group short outputs into atomic writes of up to N bytes
    -h, --help     show this help and exit

  Pipeline:
    Connect stages with top-level >>.
    The current value in each stage is available as _.

  Examples:
    jrf '_["foo"]'
    jrf 'select(_["x"] > 10) >> _["foo"]'
    jrf '_["items"] >> flat'
    jrf 'sort(_["at"]) >> _["id"]'
    jrf '_["msg"] >> reduce(nil) { |acc, v| acc ? "#{acc} #{v}" : v }'

  See Also:
    https://github.com/kazuho/jrf#readme
TEXT

Class Method Summary collapse

Class Method Details

.parse_atomic_write_bytes(value, err) ⇒ Object



109
110
111
112
113
114
115
# File 'lib/jrf/cli.rb', line 109

def self.parse_atomic_write_bytes(value, err)
  bytes = Integer(value, exception: false)
  return bytes if bytes && bytes.positive?

  err.puts "--atomic-write-bytes requires a positive integer"
  nil
end

.run(argv = ARGV, input: ARGF, out: $stdout, err: $stderr) ⇒ Object



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/jrf/cli.rb', line 37

def self.run(argv = ARGV, input: ARGF, out: $stdout, err: $stderr)
  verbose = false
  lax = false
  pretty = false
  atomic_write_bytes = Runner::DEFAULT_OUTPUT_BUFFER_LIMIT

  while argv.first&.start_with?("-")
    case argv.first
    when "-v", "--verbose"
      verbose = true
      argv.shift
    when "--lax"
      lax = true
      argv.shift
    when "-p", "--pretty"
      pretty = true
      argv.shift
    when /\A--atomic-write-bytes=(.+)\z/
      atomic_write_bytes = parse_atomic_write_bytes(Regexp.last_match(1), err)
      return 1 unless atomic_write_bytes
      argv.shift
    when "--atomic-write-bytes"
      argv.shift
      atomic_write_bytes = parse_atomic_write_bytes(argv.shift, err)
      return 1 unless atomic_write_bytes
    when "-h", "--help"
      out.puts HELP_TEXT
      return 0
    else
      err.puts "unknown option: #{argv.first}"
      err.puts USAGE
      return 1
    end
  end

  if argv.empty?
    err.puts USAGE
    return 1
  end

  expression = argv.shift
  inputs = Enumerator.new do |y|
    if argv.empty?
      y << input
    else
      argv.each do |path|
        if path == "-"
          y << input
        elsif path.end_with?(".gz")
          require "zlib"
          Zlib::GzipReader.open(path) do |source|
            y << source
          end
        else
          File.open(path, "rb") do |source|
            y << source
          end
        end
      end
    end
  end
  Runner.new(
    inputs: inputs,
    out: out,
    err: err,
    lax: lax,
    pretty: pretty,
    atomic_write_bytes: atomic_write_bytes
  ).run(expression, verbose: verbose)
  0
end