tb 0.7 → 0.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/tb.rb +2 -1
- data/lib/tb/cmd_grep.rb +2 -2
- data/lib/tb/cmd_tar.rb +3 -3
- data/lib/tb/cmd_to_ltsv.rb +48 -0
- data/lib/tb/cmdtop.rb +2 -1
- data/lib/tb/cmdutil.rb +19 -1
- data/lib/tb/enumerable.rb +8 -1
- data/lib/tb/ltsv.rb +187 -0
- data/lib/tb/ropen.rb +12 -1
- data/lib/tb/search.rb +4 -4
- data/test/test_cmd_to_ltsv.rb +65 -0
- data/test/test_ltsv.rb +40 -0
- data/test/test_pnm.rb +2 -0
- metadata +16 -19
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: d65f3c5949c1861ab81e5719b92b36e316bd3f84
|
4
|
+
data.tar.gz: 97b21fa7f980f3f8d8dcb11628c67d2e3b4ec574
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d222449efff43a8eee436cbd3b6bcc265ba15e05e783e310058baef59e338b0ada20e64e721e223c7c9eac005f206940ddea882248c1a152104f23b6c92ab9c7
|
7
|
+
data.tar.gz: 30ab19ba71070b0127dbfd96e8f48fefea0f5a03832d35b1dfee87b587e76af83208c06b5d8cad3a54265567adccabeb06d60c48bee814e5f8427ff4e5df92ad
|
data/lib/tb.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# lib/tb.rb - entry file for table library
|
2
2
|
#
|
3
|
-
# Copyright (C) 2010-
|
3
|
+
# Copyright (C) 2010-2013 Tanaka Akira <akr@fsij.org>
|
4
4
|
#
|
5
5
|
# Redistribution and use in source and binary forms, with or without
|
6
6
|
# modification, are permitted provided that the following conditions
|
@@ -42,6 +42,7 @@ require 'tb/basic'
|
|
42
42
|
require 'tb/record'
|
43
43
|
require 'tb/csv'
|
44
44
|
require 'tb/tsv'
|
45
|
+
require 'tb/ltsv'
|
45
46
|
require 'tb/pnm'
|
46
47
|
require 'tb/json'
|
47
48
|
require 'tb/reader'
|
data/lib/tb/cmd_grep.rb
CHANGED
@@ -39,8 +39,8 @@ def (Tb::Cmd).op_grep
|
|
39
39
|
"Search rows using regexp or ruby expression."
|
40
40
|
define_common_option(op, "hNo", "--no-pager")
|
41
41
|
op.def_option('-f FIELD', 'search field') {|field| Tb::Cmd.opt_grep_f = field }
|
42
|
-
op.def_option('-e REGEXP', '
|
43
|
-
op.def_option('--ruby RUBY-EXP', '
|
42
|
+
op.def_option('-e REGEXP', 'specify a regexp.') {|pattern| Tb::Cmd.opt_grep_e = pattern }
|
43
|
+
op.def_option('--ruby RUBY-EXP', 'predicate written in ruby. A hash is given as _. no usual regexp argument.') {|ruby_exp| Tb::Cmd.opt_grep_ruby = ruby_exp }
|
44
44
|
op.def_option('-v', 'ouput the records which doesn\'t match') { Tb::Cmd.opt_grep_v = true }
|
45
45
|
op
|
46
46
|
end
|
data/lib/tb/cmd_tar.rb
CHANGED
@@ -39,7 +39,7 @@ def (Tb::Cmd).op_tar
|
|
39
39
|
define_common_option(op, "hNo", "--no-pager")
|
40
40
|
op.def_option('-l', 'show more attributes.') {|fs| Tb::Cmd.opt_tar_l += 1 }
|
41
41
|
op.def_option('--ustar', 'ustar format (POSIX.1-1988). No GNU and POSIX.1-2001 extension.') {|fs| Tb::Cmd.opt_tar_ustar = true }
|
42
|
-
op.def_option('--hash=ALGORITHMS', 'hash algorithms
|
42
|
+
op.def_option('--hash=ALGORITHMS', 'show the hash of contents. algorithms can be some of md5,sha256,sha384,sha512 (default: none)') {|hs| Tb::Cmd.opt_tar_hash.concat split_field_list_argument(hs) }
|
43
43
|
op
|
44
44
|
end
|
45
45
|
|
@@ -365,11 +365,11 @@ def (Tb::Cmd).tar_open_with(arg)
|
|
365
365
|
tar_open_with0(arg) {|f|
|
366
366
|
magic = f.read(8)
|
367
367
|
case magic
|
368
|
-
when /\A\x1f\x8b
|
368
|
+
when /\A\x1f\x8b/n, /\A\037\235/n # \x1f\x8b is gzip format. \037\235 is "compress" format of old Unix.
|
369
369
|
decompression = ['gzip', '-dc']
|
370
370
|
when /\ABZh/
|
371
371
|
decompression = ['bzip2', '-dc']
|
372
|
-
when /\A\xFD7zXZ\x00/
|
372
|
+
when /\A\xFD7zXZ\x00/n
|
373
373
|
decompression = ['xz', '-dc']
|
374
374
|
end
|
375
375
|
begin
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# Copyright (C) 2013 Tanaka Akira <akr@fsij.org>
|
2
|
+
#
|
3
|
+
# Redistribution and use in source and binary forms, with or without
|
4
|
+
# modification, are permitted provided that the following conditions
|
5
|
+
# are met:
|
6
|
+
#
|
7
|
+
# 1. Redistributions of source code must retain the above copyright
|
8
|
+
# notice, this list of conditions and the following disclaimer.
|
9
|
+
# 2. Redistributions in binary form must reproduce the above
|
10
|
+
# copyright notice, this list of conditions and the following
|
11
|
+
# disclaimer in the documentation and/or other materials provided
|
12
|
+
# with the distribution.
|
13
|
+
# 3. The name of the author may not be used to endorse or promote
|
14
|
+
# products derived from this software without specific prior
|
15
|
+
# written permission.
|
16
|
+
#
|
17
|
+
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
18
|
+
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
19
|
+
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
20
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
21
|
+
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
22
|
+
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
23
|
+
# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
24
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
25
|
+
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
26
|
+
# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
27
|
+
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
28
|
+
|
29
|
+
Tb::Cmd.subcommands << 'to-ltsv'
|
30
|
+
|
31
|
+
def (Tb::Cmd).op_to_ltsv
|
32
|
+
op = OptionParser.new
|
33
|
+
op.banner = "Usage: tb to-ltsv [OPTS] [TABLE]\n" +
|
34
|
+
"Convert a table to LTSV (Tab Separated Value)."
|
35
|
+
define_common_option(op, "hNo", "--no-pager")
|
36
|
+
op
|
37
|
+
end
|
38
|
+
|
39
|
+
def (Tb::Cmd).main_to_ltsv(argv)
|
40
|
+
op_to_ltsv.parse!(argv)
|
41
|
+
exit_if_help('to-ltsv')
|
42
|
+
argv = ['-'] if argv.empty?
|
43
|
+
tbl = Tb::CatReader.open(argv, Tb::Cmd.opt_N).to_tb
|
44
|
+
with_output {|out|
|
45
|
+
tbl_generate_ltsv(tbl, out)
|
46
|
+
}
|
47
|
+
end
|
48
|
+
|
data/lib/tb/cmdtop.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (C) 2011-
|
1
|
+
# Copyright (C) 2011-2013 Tanaka Akira <akr@fsij.org>
|
2
2
|
#
|
3
3
|
# Redistribution and use in source and binary forms, with or without
|
4
4
|
# modification, are permitted provided that the following conditions
|
@@ -38,6 +38,7 @@ require 'tb/cmdutil'
|
|
38
38
|
require 'tb/cmd_help'
|
39
39
|
require 'tb/cmd_to_csv'
|
40
40
|
require 'tb/cmd_to_tsv'
|
41
|
+
require 'tb/cmd_to_ltsv'
|
41
42
|
require 'tb/cmd_to_pnm'
|
42
43
|
require 'tb/cmd_to_json'
|
43
44
|
require 'tb/cmd_to_yaml'
|
data/lib/tb/cmdutil.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (C) 2011-
|
1
|
+
# Copyright (C) 2011-2013 Tanaka Akira <akr@fsij.org>
|
2
2
|
#
|
3
3
|
# Redistribution and use in source and binary forms, with or without
|
4
4
|
# modification, are permitted provided that the following conditions
|
@@ -152,6 +152,20 @@ def tbl_generate_tsv(tbl, out)
|
|
152
152
|
end
|
153
153
|
end
|
154
154
|
|
155
|
+
def tbl_generate_ltsv(tbl, out)
|
156
|
+
if Tb::Cmd.opt_N
|
157
|
+
header = tbl.list_fields
|
158
|
+
Tb.ltsv_stream_output(out) {|gen|
|
159
|
+
tbl.each {|rec|
|
160
|
+
assoc = header.map {|f| [f, rec[f]] }
|
161
|
+
gen << assoc
|
162
|
+
}
|
163
|
+
}
|
164
|
+
else
|
165
|
+
tbl.generate_ltsv(out)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
155
169
|
def with_output(filename=Tb::Cmd.opt_output)
|
156
170
|
if filename && filename != '-'
|
157
171
|
tmp = filename + ".part"
|
@@ -188,6 +202,8 @@ def output_tbenum(te)
|
|
188
202
|
case filename
|
189
203
|
when /\.csv\z/
|
190
204
|
fmt = 'csv'
|
205
|
+
when /\.ltsv\z/
|
206
|
+
fmt = 'ltsv'
|
191
207
|
when /\.json\z/
|
192
208
|
fmt = 'json'
|
193
209
|
end
|
@@ -196,6 +212,8 @@ def output_tbenum(te)
|
|
196
212
|
case fmt
|
197
213
|
when 'csv'
|
198
214
|
write_proc = lambda {|out| te.write_to_csv(out, !Tb::Cmd.opt_N) }
|
215
|
+
when 'ltsv'
|
216
|
+
write_proc = lambda {|out| te.write_to_ltsv(out) }
|
199
217
|
when 'json'
|
200
218
|
write_proc = lambda {|out| te.write_to_json(out) }
|
201
219
|
else
|
data/lib/tb/enumerable.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Copyright (C) 2012 Tanaka Akira <akr@fsij.org>
|
1
|
+
# Copyright (C) 2012-2013 Tanaka Akira <akr@fsij.org>
|
2
2
|
#
|
3
3
|
# Redistribution and use in source and binary forms, with or without
|
4
4
|
# modification, are permitted provided that the following conditions
|
@@ -232,6 +232,13 @@ module Tb::Enumerable
|
|
232
232
|
end
|
233
233
|
end
|
234
234
|
|
235
|
+
def write_to_ltsv(out)
|
236
|
+
self.each {|pairs|
|
237
|
+
out.print Tb.ltsv_assoc_join(pairs)
|
238
|
+
out.print "\n"
|
239
|
+
}
|
240
|
+
end
|
241
|
+
|
235
242
|
def write_to_json(out)
|
236
243
|
require 'json'
|
237
244
|
out.print "["
|
data/lib/tb/ltsv.rb
ADDED
@@ -0,0 +1,187 @@
|
|
1
|
+
# lib/tb/ltsv.rb - LTSV related fetures for table library
|
2
|
+
#
|
3
|
+
# Copyright (C) 2013 Tanaka Akira <akr@fsij.org>
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without
|
6
|
+
# modification, are permitted provided that the following conditions
|
7
|
+
# are met:
|
8
|
+
#
|
9
|
+
# 1. Redistributions of source code must retain the above copyright
|
10
|
+
# notice, this list of conditions and the following disclaimer.
|
11
|
+
# 2. Redistributions in binary form must reproduce the above
|
12
|
+
# copyright notice, this list of conditions and the following
|
13
|
+
# disclaimer in the documentation and/or other materials provided
|
14
|
+
# with the distribution.
|
15
|
+
# 3. The name of the author may not be used to endorse or promote
|
16
|
+
# products derived from this software without specific prior
|
17
|
+
# written permission.
|
18
|
+
#
|
19
|
+
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
20
|
+
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
21
|
+
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
22
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
23
|
+
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
24
|
+
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
25
|
+
# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
26
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
27
|
+
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
28
|
+
# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
29
|
+
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
30
|
+
|
31
|
+
require 'stringio'
|
32
|
+
|
33
|
+
class Tb
|
34
|
+
def Tb.load_ltsv(filename, &block)
|
35
|
+
Tb.parse_ltsv(File.read(filename), &block)
|
36
|
+
end
|
37
|
+
|
38
|
+
def Tb.parse_ltsv(ltsv)
|
39
|
+
assoc_list = []
|
40
|
+
ltsv_stream_input(ltsv) {|assoc|
|
41
|
+
assoc_list << assoc
|
42
|
+
}
|
43
|
+
fields_hash = {}
|
44
|
+
assoc_list.each {|assoc|
|
45
|
+
assoc.each {|key, val|
|
46
|
+
fields_hash[key] ||= fields_hash.size
|
47
|
+
}
|
48
|
+
}
|
49
|
+
header = fields_hash.keys
|
50
|
+
t = Tb.new(header)
|
51
|
+
assoc_list.each {|assoc|
|
52
|
+
t.insert Hash[assoc]
|
53
|
+
}
|
54
|
+
t
|
55
|
+
end
|
56
|
+
|
57
|
+
def Tb.ltsv_stream_input(ltsv)
|
58
|
+
ltsvreader = LTSVReader.new(ltsv)
|
59
|
+
while assoc = ltsvreader.shift
|
60
|
+
yield assoc
|
61
|
+
end
|
62
|
+
nil
|
63
|
+
end
|
64
|
+
|
65
|
+
def Tb.ltsv_escape_string(str)
|
66
|
+
if /[\0-\x1f":\\\x7f]/ =~ str
|
67
|
+
'"' +
|
68
|
+
str.gsub(/[\0-\x1f":\\\x7f]/) {
|
69
|
+
ch = $&
|
70
|
+
case ch
|
71
|
+
when "\0"; '\0'
|
72
|
+
when "\a"; '\a'
|
73
|
+
when "\b"; '\b'
|
74
|
+
when "\f"; '\f'
|
75
|
+
when "\n"; '\n'
|
76
|
+
when "\r"; '\r'
|
77
|
+
when "\t"; '\t'
|
78
|
+
when "\v"; '\v'
|
79
|
+
when "\e"; '\e'
|
80
|
+
else
|
81
|
+
"\\x%02X" % ch.ord
|
82
|
+
end
|
83
|
+
} +
|
84
|
+
'"'
|
85
|
+
else
|
86
|
+
str
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def Tb.ltsv_unescape_string(str)
|
91
|
+
if /\A\s*"(.*)"\s*\z/ =~ str
|
92
|
+
$1.gsub(/\\([0abfnrtve]|x([0-9A-Fa-f][0-9A-Fa-f]))/) {
|
93
|
+
if $2
|
94
|
+
[$2.to_i].pack("H2")
|
95
|
+
else
|
96
|
+
case $1
|
97
|
+
when "0"; "\0"
|
98
|
+
when "a"; "\a"
|
99
|
+
when "b"; "\b"
|
100
|
+
when "f"; "\f"
|
101
|
+
when "n"; "\n"
|
102
|
+
when "r"; "\r"
|
103
|
+
when "t"; "\t"
|
104
|
+
when "v"; "\v"
|
105
|
+
when "e"; "\e"
|
106
|
+
else
|
107
|
+
raise "[bug] unexpected escape"
|
108
|
+
end
|
109
|
+
end
|
110
|
+
}
|
111
|
+
else
|
112
|
+
str
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
class LTSVReader
|
117
|
+
include Tb::Enumerable
|
118
|
+
|
119
|
+
def initialize(input)
|
120
|
+
if input.respond_to? :to_str
|
121
|
+
@input = StringIO.new(input)
|
122
|
+
else
|
123
|
+
@input = input
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def shift
|
128
|
+
line = @input.gets
|
129
|
+
return nil if !line
|
130
|
+
line = line.chomp("\n")
|
131
|
+
line = line.chomp("\r")
|
132
|
+
ary = line.split(/\t/, -1)
|
133
|
+
assoc = ary.map {|str|
|
134
|
+
/:/ =~ str
|
135
|
+
key = $`
|
136
|
+
val = $'
|
137
|
+
key = Tb.ltsv_unescape_string(key)
|
138
|
+
val = Tb.ltsv_unescape_string(val)
|
139
|
+
[key, val]
|
140
|
+
}
|
141
|
+
assoc
|
142
|
+
end
|
143
|
+
|
144
|
+
def header_and_each(header_proc)
|
145
|
+
header_proc.call(nil) if header_proc
|
146
|
+
while assoc = self.shift
|
147
|
+
yield Hash[assoc]
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def each(&block)
|
152
|
+
header_and_each(nil, &block)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def Tb.ltsv_stream_output(out)
|
157
|
+
gen = Object.new
|
158
|
+
gen.instance_variable_set(:@out, out)
|
159
|
+
def gen.<<(assoc)
|
160
|
+
@out << Tb.ltsv_assoc_join(assoc) << "\n"
|
161
|
+
end
|
162
|
+
yield gen
|
163
|
+
end
|
164
|
+
|
165
|
+
# :call-seq:
|
166
|
+
# generate_ltsv(out='') {|recordids| modified_recordids }
|
167
|
+
# generate_ltsv(out='')
|
168
|
+
#
|
169
|
+
def generate_ltsv(out='', fields=nil, &block)
|
170
|
+
recordids = list_recordids
|
171
|
+
if block_given?
|
172
|
+
recordids = yield(recordids)
|
173
|
+
end
|
174
|
+
Tb.ltsv_stream_output(out) {|gen|
|
175
|
+
recordids.each {|recordid|
|
176
|
+
gen << get_record(recordid)
|
177
|
+
}
|
178
|
+
}
|
179
|
+
out
|
180
|
+
end
|
181
|
+
|
182
|
+
def Tb.ltsv_assoc_join(assoc)
|
183
|
+
assoc.map {|key, val|
|
184
|
+
Tb.ltsv_escape_string(key) + ':' + Tb.ltsv_escape_string(val)
|
185
|
+
}.join("\t")
|
186
|
+
end
|
187
|
+
end
|
data/lib/tb/ropen.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# lib/tb/ropen.rb - Tb::Reader.open
|
2
2
|
#
|
3
|
-
# Copyright (C) 2011-
|
3
|
+
# Copyright (C) 2011-2013 Tanaka Akira <akr@fsij.org>
|
4
4
|
#
|
5
5
|
# Redistribution and use in source and binary forms, with or without
|
6
6
|
# modification, are permitted provided that the following conditions
|
@@ -37,6 +37,9 @@ def Tb.open_reader(filename, opts={})
|
|
37
37
|
when /\Atsv:/
|
38
38
|
filename = $'
|
39
39
|
rawreader_maker_for_tb_reader = lambda {|io| Tb::TSVReader.new(io) }
|
40
|
+
when /\Altsv:/
|
41
|
+
filename = $'
|
42
|
+
rawreader_maker_for_tb_reader = lambda {|io| Tb::LTSVReader.new(io) }
|
40
43
|
when /\Ap[pgbn]m:/
|
41
44
|
filename = $'
|
42
45
|
rawreader_maker_for_tb_reader = lambda {|io| Tb.pnm_stream_input(io) }
|
@@ -47,6 +50,8 @@ def Tb.open_reader(filename, opts={})
|
|
47
50
|
rawreader_maker_for_tb_reader = lambda {|io| Tb::CSVReader.new(io) }
|
48
51
|
when /\.tsv\z/
|
49
52
|
rawreader_maker_for_tb_reader = lambda {|io| Tb::TSVReader.new(io) }
|
53
|
+
when /\.ltsv\z/
|
54
|
+
reader_maker_for_tb_reader = lambda {|io| Tb::LTSVReader.new(io) }
|
50
55
|
when /\.p[pgbn]m\z/
|
51
56
|
rawreader_maker_for_tb_reader = lambda {|io| Tb.pnm_stream_input(io) }
|
52
57
|
when /\.json\z/
|
@@ -65,6 +70,12 @@ def Tb.open_reader(filename, opts={})
|
|
65
70
|
json_reader_maker.call(io)
|
66
71
|
}
|
67
72
|
end
|
73
|
+
elsif reader_maker_for_tb_reader
|
74
|
+
if filename == '-'
|
75
|
+
reader = reader_maker_for_tb_reader.call($stdin)
|
76
|
+
else
|
77
|
+
reader = reader_maker_for_tb_reader.call(File.open(filename))
|
78
|
+
end
|
68
79
|
else
|
69
80
|
# rawreader_maker_for_tb_reader should be available.
|
70
81
|
reader = Tb::Reader.new(opts) {|body|
|
data/lib/tb/search.rb
CHANGED
@@ -101,10 +101,10 @@ module Tb::Search
|
|
101
101
|
when :s, :south; try_rmove(0, 1, aa, st, &b)
|
102
102
|
when :e, :east; try_rmove(1, 0, aa, st, &b)
|
103
103
|
when :w, :west; try_rmove(-1, 0, aa, st, &b)
|
104
|
-
when :ne, :
|
105
|
-
when :nw, :
|
106
|
-
when :se, :
|
107
|
-
when :sw, :
|
104
|
+
when :ne, :northeast; try_rmove(1, -1, aa, st, &b)
|
105
|
+
when :nw, :northwest; try_rmove(-1, -1, aa, st, &b)
|
106
|
+
when :se, :southeast; try_rmove(1, 1, aa, st, &b)
|
107
|
+
when :sw, :southwest; try_rmove(-1, 1, aa, st, &b)
|
108
108
|
when :debug_print_state; p st; yield st
|
109
109
|
when Array
|
110
110
|
case pat[0]
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'tb/cmdtop'
|
3
|
+
require 'tmpdir'
|
4
|
+
|
5
|
+
class TestTbCmdToLTSV < Test::Unit::TestCase
|
6
|
+
def setup
|
7
|
+
Tb::Cmd.reset_option
|
8
|
+
@curdir = Dir.pwd
|
9
|
+
@tmpdir = Dir.mktmpdir
|
10
|
+
Dir.chdir @tmpdir
|
11
|
+
end
|
12
|
+
def teardown
|
13
|
+
Tb::Cmd.reset_option
|
14
|
+
Dir.chdir @curdir
|
15
|
+
FileUtils.rmtree @tmpdir
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_basic
|
19
|
+
File.open(i="i.csv", "w") {|f| f << <<-"End".gsub(/^[ \t]+/, '') }
|
20
|
+
a,b,c
|
21
|
+
0,1,2
|
22
|
+
4,5,6
|
23
|
+
End
|
24
|
+
Tb::Cmd.main_to_ltsv(['-o', o="o.ltsv", i])
|
25
|
+
assert_equal(<<-"End".gsub(/^[ \t]+/, ''), File.read(o))
|
26
|
+
a:0\tb:1\tc:2
|
27
|
+
a:4\tb:5\tc:6
|
28
|
+
End
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_numeric
|
32
|
+
File.open(i="i.csv", "w") {|f| f << <<-"End".gsub(/^[ \t]+/, '') }
|
33
|
+
a,b,c
|
34
|
+
0,1,2
|
35
|
+
4,5,6
|
36
|
+
End
|
37
|
+
Tb::Cmd.main_to_ltsv(['-o', o="o.ltsv", '-N', i])
|
38
|
+
assert_equal(<<-"End".gsub(/^[ \t]+/, ''), File.read(o))
|
39
|
+
1:a\t2:b\t3:c
|
40
|
+
1:0\t2:1\t3:2
|
41
|
+
1:4\t2:5\t3:6
|
42
|
+
End
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_twofile
|
46
|
+
File.open(i1="i1.csv", "w") {|f| f << <<-"End".gsub(/^[ \t]+/, '') }
|
47
|
+
a,b
|
48
|
+
1,2
|
49
|
+
3,4
|
50
|
+
End
|
51
|
+
File.open(i2="i2.csv", "w") {|f| f << <<-"End".gsub(/^[ \t]+/, '') }
|
52
|
+
b,a
|
53
|
+
5,6
|
54
|
+
7,8
|
55
|
+
End
|
56
|
+
Tb::Cmd.main_to_ltsv(['-o', o="o.ltsv", i1, i2])
|
57
|
+
assert_equal(<<-"End".gsub(/^[ \t]+/, ''), File.read(o))
|
58
|
+
a:1\tb:2
|
59
|
+
a:3\tb:4
|
60
|
+
a:6\tb:5
|
61
|
+
a:8\tb:7
|
62
|
+
End
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
data/test/test_ltsv.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'tb'
|
2
|
+
require 'test/unit'
|
3
|
+
|
4
|
+
class TestTbLTSV < Test::Unit::TestCase
|
5
|
+
def test_parse
|
6
|
+
r = Tb::LTSVReader.new("a:1\tb:2\na:3\tb:4\n")
|
7
|
+
result = []
|
8
|
+
r.with_header {|header|
|
9
|
+
result << header
|
10
|
+
}.each {|obj|
|
11
|
+
result << obj
|
12
|
+
}
|
13
|
+
assert_equal([nil, {"a"=>"1", "b"=>"2"}, {"a"=>"3", "b"=>"4"}], result)
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_parse2
|
17
|
+
ltsv = "a:1\tb:2\n"
|
18
|
+
t = Tb.parse_ltsv(ltsv)
|
19
|
+
records = []
|
20
|
+
t.each_record {|record|
|
21
|
+
records << record.to_h_with_reserved
|
22
|
+
}
|
23
|
+
assert_equal(
|
24
|
+
[{"_recordid"=>0, "a"=>"1", "b"=>"2"}],
|
25
|
+
records)
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_generate_ltsv
|
29
|
+
tbl = Tb.new %w[a b], %w[foo bar]
|
30
|
+
tbl.generate_ltsv(out="")
|
31
|
+
assert_equal("a:foo\tb:bar\n", out)
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_generate_ltsv_with_block
|
35
|
+
tbl = Tb.new %w[a b], %w[foo bar], %w[q w]
|
36
|
+
tbl.generate_ltsv(out="") {|recids| recids.reverse }
|
37
|
+
assert_equal("a:q\tb:w\na:foo\tb:bar\n", out)
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
data/test/test_pnm.rb
CHANGED
metadata
CHANGED
@@ -1,32 +1,24 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '0.
|
5
|
-
prerelease:
|
4
|
+
version: '0.8'
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Tanaka Akira
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2013-03-29 00:00:00.000000000 Z
|
13
12
|
dependencies: []
|
14
|
-
description:
|
15
|
-
|
13
|
+
description: |
|
14
|
+
tb is a manipulation tool for table: CSV, TSV, LTSV, JSON, etc.
|
16
15
|
|
17
16
|
tb provides a command and a library for manipulating tables:
|
18
|
-
|
19
17
|
Unix filter like operations (grep, sort, cat, cut, ls, etc.),
|
20
|
-
|
21
18
|
SQL like operations (join, group, etc.),
|
22
|
-
|
23
19
|
other table operations (gsub, rename, cross, melt, unmelt, etc.),
|
24
|
-
|
25
20
|
information extractions (git, svn, tar),
|
26
|
-
|
27
21
|
and more.
|
28
|
-
|
29
|
-
'
|
30
22
|
email: akr@fsij.org
|
31
23
|
executables:
|
32
24
|
- tb
|
@@ -61,6 +53,7 @@ files:
|
|
61
53
|
- lib/tb/cmd_tar.rb
|
62
54
|
- lib/tb/cmd_to_csv.rb
|
63
55
|
- lib/tb/cmd_to_json.rb
|
56
|
+
- lib/tb/cmd_to_ltsv.rb
|
64
57
|
- lib/tb/cmd_to_pnm.rb
|
65
58
|
- lib/tb/cmd_to_pp.rb
|
66
59
|
- lib/tb/cmd_to_tsv.rb
|
@@ -81,6 +74,7 @@ files:
|
|
81
74
|
- lib/tb/fileenumerator.rb
|
82
75
|
- lib/tb/func.rb
|
83
76
|
- lib/tb/json.rb
|
77
|
+
- lib/tb/ltsv.rb
|
84
78
|
- lib/tb/pager.rb
|
85
79
|
- lib/tb/pnm.rb
|
86
80
|
- lib/tb/reader.rb
|
@@ -124,6 +118,7 @@ files:
|
|
124
118
|
- test/test_cmd_tar_tvf.rb
|
125
119
|
- test/test_cmd_to_csv.rb
|
126
120
|
- test/test_cmd_to_json.rb
|
121
|
+
- test/test_cmd_to_ltsv.rb
|
127
122
|
- test/test_cmd_to_pnm.rb
|
128
123
|
- test/test_cmd_to_pp.rb
|
129
124
|
- test/test_cmd_to_tsv.rb
|
@@ -139,6 +134,7 @@ files:
|
|
139
134
|
- test/test_fieldset.rb
|
140
135
|
- test/test_fileenumerator.rb
|
141
136
|
- test/test_json.rb
|
137
|
+
- test/test_ltsv.rb
|
142
138
|
- test/test_pager.rb
|
143
139
|
- test/test_pnm.rb
|
144
140
|
- test/test_reader.rb
|
@@ -150,28 +146,27 @@ files:
|
|
150
146
|
- test/test_zipper.rb
|
151
147
|
homepage: https://github.com/akr/tb
|
152
148
|
licenses: []
|
149
|
+
metadata: {}
|
153
150
|
post_install_message:
|
154
151
|
rdoc_options: []
|
155
152
|
require_paths:
|
156
153
|
- lib
|
157
154
|
required_ruby_version: !ruby/object:Gem::Requirement
|
158
|
-
none: false
|
159
155
|
requirements:
|
160
|
-
- -
|
156
|
+
- - '>='
|
161
157
|
- !ruby/object:Gem::Version
|
162
158
|
version: 1.9.2
|
163
159
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
164
|
-
none: false
|
165
160
|
requirements:
|
166
|
-
- -
|
161
|
+
- - '>='
|
167
162
|
- !ruby/object:Gem::Version
|
168
163
|
version: '0'
|
169
164
|
requirements: []
|
170
165
|
rubyforge_project:
|
171
|
-
rubygems_version:
|
166
|
+
rubygems_version: 2.0.2
|
172
167
|
signing_key:
|
173
|
-
specification_version:
|
174
|
-
summary:
|
168
|
+
specification_version: 4
|
169
|
+
summary: 'manipulation tool for tables: CSV, TSV, LTSV, JSON, etc.'
|
175
170
|
test_files:
|
176
171
|
- test/test_basic.rb
|
177
172
|
- test/test_catreader.rb
|
@@ -198,6 +193,7 @@ test_files:
|
|
198
193
|
- test/test_cmd_tar_tvf.rb
|
199
194
|
- test/test_cmd_to_csv.rb
|
200
195
|
- test/test_cmd_to_json.rb
|
196
|
+
- test/test_cmd_to_ltsv.rb
|
201
197
|
- test/test_cmd_to_pnm.rb
|
202
198
|
- test/test_cmd_to_pp.rb
|
203
199
|
- test/test_cmd_to_tsv.rb
|
@@ -213,6 +209,7 @@ test_files:
|
|
213
209
|
- test/test_fieldset.rb
|
214
210
|
- test/test_fileenumerator.rb
|
215
211
|
- test/test_json.rb
|
212
|
+
- test/test_ltsv.rb
|
216
213
|
- test/test_pager.rb
|
217
214
|
- test/test_pnm.rb
|
218
215
|
- test/test_reader.rb
|