ppcommand 0.1.5 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +24 -0
- data/Gemfile +4 -0
- data/{LICENSE → LICENSE.txt} +3 -1
- data/{README.rdoc → README.md} +55 -41
- data/Rakefile +1 -37
- data/bin/pp +3 -9
- data/lib/ppcommand.rb +4 -213
- data/lib/ppcommand/main.rb +211 -0
- data/lib/ppcommand/version.rb +3 -0
- data/ppcommand.gemspec +21 -59
- metadata +89 -92
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: b056394e4ded505fc8f3504c999b3b4f58151c03
|
4
|
+
data.tar.gz: 3d4c6f399311cd0875c843b8bc15bb284eff3921
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 69b02307466c3f2f695c9b0cbe4d5775604d31c5bd6f00ccd325a7f69b6bcdd76e1005671d08337cc5b61899f758c42768c210b33917c7bc69c3048734db1f10
|
7
|
+
data.tar.gz: 143396ef13ff69181955a997acbcd147fcdd06a470163e30e91d2be4d5f6117fac9701cce1632727a73a97c738b001fb897d283721119cae12d6b60a21886537
|
data/.gitignore
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
*.bundle
|
19
|
+
*.so
|
20
|
+
*.o
|
21
|
+
*.a
|
22
|
+
mkmf.log
|
23
|
+
|
24
|
+
*~
|
data/Gemfile
ADDED
data/{LICENSE → LICENSE.txt}
RENAMED
data/{README.rdoc → README.md}
RENAMED
@@ -1,9 +1,16 @@
|
|
1
|
-
|
1
|
+
# ppcommand
|
2
2
|
|
3
|
-
Parse and
|
3
|
+
Parse and pretty print YAML/JSON/XML/CSV/HTML.
|
4
4
|
|
5
|
-
|
5
|
+
## Installation
|
6
6
|
|
7
|
+
```
|
8
|
+
$ gem install ppcommand
|
9
|
+
```
|
10
|
+
|
11
|
+
## Usage
|
12
|
+
|
13
|
+
```
|
7
14
|
$ pp --help
|
8
15
|
pp [options] [file|URI]
|
9
16
|
-c, --csv parse CSV and pp.
|
@@ -16,12 +23,13 @@ Parse and pp YAML/JSON/XML/CSV/HTML.
|
|
16
23
|
-t, --text do not parse. print plain text.
|
17
24
|
-h, --help show this help.
|
18
25
|
-v, --version show version.
|
26
|
+
```
|
19
27
|
|
28
|
+
## Example
|
20
29
|
|
21
|
-
|
22
|
-
|
23
|
-
Parse YAML and pp.
|
30
|
+
YAML
|
24
31
|
|
32
|
+
```
|
25
33
|
$ pp ./config/database.yml
|
26
34
|
{"development"=>
|
27
35
|
{"encoding"=>"utf8",
|
@@ -30,29 +38,39 @@ Parse YAML and pp.
|
|
30
38
|
"host"=>"localhost",
|
31
39
|
"password"=>nil,
|
32
40
|
"database"=>"appname_test",
|
33
|
-
"pool"=>5},
|
34
|
-
:
|
35
|
-
|
36
|
-
Parse JSON and pp.
|
37
|
-
|
38
|
-
$ pp http://api.twitter.com/1/statuses/public_timeline.json
|
39
|
-
[{"user"=>
|
40
|
-
{"name"=>"septiasabatina",
|
41
|
-
"profile_sidebar_fill_color"=>"FFFFFF",
|
42
|
-
"profile_sidebar_border_color"=>"FFFFFF",
|
43
|
-
"profile_background_tile"=>true,
|
44
|
-
"profile_link_color"=>"000000",
|
45
|
-
"url"=>"http://example.com",
|
46
|
-
"contributors_enabled"=>false,
|
47
|
-
"favourites_count"=>0,
|
48
|
-
"id"=>123456789,
|
49
|
-
"description"=>"",
|
50
|
-
"utc_offset"=>0,
|
51
|
-
"lang"=>"en",
|
41
|
+
"pool"=>5},
|
52
42
|
:
|
53
|
-
|
54
|
-
|
55
|
-
|
43
|
+
```
|
44
|
+
|
45
|
+
JSON
|
46
|
+
|
47
|
+
```
|
48
|
+
$ pp 'http://gdata.youtube.com/feeds/api/standardfeeds/most_popular?v=2&alt=json'
|
49
|
+
{"version"=>"1.0",
|
50
|
+
"encoding"=>"UTF-8",
|
51
|
+
"feed"=>
|
52
|
+
{"xmlns"=>"http://www.w3.org/2005/Atom",
|
53
|
+
"xmlns$gd"=>"http://schemas.google.com/g/2005",
|
54
|
+
"xmlns$openSearch"=>"http://a9.com/-/spec/opensearch/1.1/",
|
55
|
+
"xmlns$yt"=>"http://gdata.youtube.com/schemas/2007",
|
56
|
+
"xmlns$media"=>"http://search.yahoo.com/mrss/",
|
57
|
+
"gd$etag"=>"",
|
58
|
+
"id"=>{"$t"=>"tag:youtube.com,2008:standardfeed:global:most_popular"},
|
59
|
+
"updated"=>{"$t"=>"2015-01-01T00:00:00.000Z"},
|
60
|
+
"category"=>
|
61
|
+
[{"scheme"=>"http://schemas.google.com/g/2005#kind",
|
62
|
+
"term"=>"http://gdata.youtube.com/schemas/2007#video"}],
|
63
|
+
"title"=>{"$t"=>"Most Popular"},
|
64
|
+
"logo"=>{"$t"=>"http://www.gstatic.com/youtube/img/logo.png"},
|
65
|
+
"link"=>
|
66
|
+
[{"rel"=>"alternate",
|
67
|
+
"type"=>"text/html",
|
68
|
+
:
|
69
|
+
```
|
70
|
+
|
71
|
+
HTML (required nokogiri)
|
72
|
+
|
73
|
+
```
|
56
74
|
$ pp http://www.google.com/
|
57
75
|
#(Document:0x96c0ee {
|
58
76
|
name = "document",
|
@@ -64,9 +82,11 @@ Parse HTML and pp (required nokogiri).
|
|
64
82
|
#(Element:0x96adb6 {
|
65
83
|
name = "head",
|
66
84
|
:
|
85
|
+
```
|
67
86
|
|
68
87
|
Get URL contents as text, skip 3 lines, convert encoding to UTF-8, parse CSV and pp with labels. When using --csvtable(-C), the first line treated as label.
|
69
88
|
|
89
|
+
```
|
70
90
|
$ pp -t http://example.com/items.csv | head -n +3 | nkf -w | pp -C
|
71
91
|
[[[0, "name", "apple"],
|
72
92
|
[1, "price", "100"],
|
@@ -80,18 +100,12 @@ Get URL contents as text, skip 3 lines, convert encoding to UTF-8, parse CSV and
|
|
80
100
|
[3, "label1", "xxx"],
|
81
101
|
[4, "label2", "yyy"],
|
82
102
|
[5, "label3", "zzz"]]]
|
103
|
+
```
|
83
104
|
|
84
|
-
|
85
|
-
|
86
|
-
* Fork the project.
|
87
|
-
* Make your feature addition or bug fix.
|
88
|
-
* Add tests for it. This is important so I don't break it in a
|
89
|
-
future version unintentionally.
|
90
|
-
* Commit, do not mess with rakefile, version, or history.
|
91
|
-
(if you want to have your own version, that is fine but
|
92
|
-
bump version in a commit by itself I can ignore when I pull)
|
93
|
-
* Send me a pull request. Bonus points for topic branches.
|
94
|
-
|
95
|
-
== Copyright
|
105
|
+
## Contributing
|
96
106
|
|
97
|
-
|
107
|
+
1. Fork it ( https://github.com/[my-github-username]/ppcommand/fork )
|
108
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
109
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
110
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
111
|
+
5. Create a new Pull Request
|
data/Rakefile
CHANGED
@@ -1,38 +1,2 @@
|
|
1
|
-
require
|
2
|
-
require 'rake'
|
3
|
-
|
4
|
-
begin
|
5
|
-
require 'jeweler'
|
6
|
-
Jeweler::Tasks.new do |gem|
|
7
|
-
gem.name = "ppcommand"
|
8
|
-
gem.summary = %Q{Parse and pp YAML/JSON/XML/CSV/HTML}
|
9
|
-
gem.description = %Q{Parse and pp YAML/JSON/XML/CSV/HTML}
|
10
|
-
gem.email = "koseki@gmail.com"
|
11
|
-
gem.homepage = "http://github.com/koseki/ppcommand"
|
12
|
-
gem.authors = ["KOSEKI Kengo"]
|
13
|
-
gem.add_dependency('json')
|
14
|
-
gem.add_dependency('xml-simple')
|
15
|
-
gem.add_development_dependency "rspec", ">= 1.2.9"
|
16
|
-
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
17
|
-
end
|
18
|
-
Jeweler::GemcutterTasks.new
|
19
|
-
rescue LoadError
|
20
|
-
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
21
|
-
end
|
22
|
-
|
23
|
-
require 'spec/rake/spectask'
|
24
|
-
Spec::Rake::SpecTask.new(:spec) do |spec|
|
25
|
-
spec.libs << 'lib' << 'spec'
|
26
|
-
spec.spec_files = FileList['spec/**/*_spec.rb']
|
27
|
-
end
|
28
|
-
|
29
|
-
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
30
|
-
spec.libs << 'lib' << 'spec'
|
31
|
-
spec.pattern = 'spec/**/*_spec.rb'
|
32
|
-
spec.rcov = true
|
33
|
-
end
|
34
|
-
|
35
|
-
task :spec => :check_dependencies
|
36
|
-
|
37
|
-
task :default => :spec
|
1
|
+
require "bundler/gem_tasks"
|
38
2
|
|
data/bin/pp
CHANGED
@@ -1,13 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
|
4
|
-
$:.unshift File.dirname(__FILE__) + "/../lib"
|
5
|
-
end
|
3
|
+
$:.unshift File.join(File.dirname(__FILE__), '../lib')
|
6
4
|
|
7
|
-
|
8
|
-
require 'rubygems'
|
9
|
-
require 'ppcommand'
|
10
|
-
PPCommand.execute
|
11
|
-
rescue LoadError
|
12
|
-
end
|
5
|
+
require 'ppcommand'
|
13
6
|
|
7
|
+
PPCommand.execute
|
data/lib/ppcommand.rb
CHANGED
@@ -1,217 +1,8 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require 'optparse'
|
4
|
-
|
5
|
-
$KCODE = 'utf8' if RUBY_VERSION.to_f < 1.9
|
6
|
-
|
7
|
-
class PPCommand
|
1
|
+
require "ppcommand/version"
|
2
|
+
require "ppcommand/main"
|
8
3
|
|
4
|
+
module PPCommand
|
9
5
|
def self.execute
|
10
|
-
|
11
|
-
end
|
12
|
-
|
13
|
-
def pp_xml(source)
|
14
|
-
require 'rubygems'
|
15
|
-
require 'rexml/document'
|
16
|
-
puts pretty_xml(REXML::Document.new(source))
|
17
|
-
end
|
18
|
-
|
19
|
-
def pp_xmlsimple(source)
|
20
|
-
require 'rubygems'
|
21
|
-
require 'xmlsimple'
|
22
|
-
pp XmlSimple.xml_in(source)
|
23
|
-
end
|
24
|
-
|
25
|
-
def pp_json(source)
|
26
|
-
require 'rubygems'
|
27
|
-
require 'json'
|
28
|
-
pp JSON.parse(source)
|
29
|
-
end
|
30
|
-
|
31
|
-
def pp_yaml(source)
|
32
|
-
YAML.each_document(StringIO.new(source)) do |obj|
|
33
|
-
pp obj
|
34
|
-
end
|
6
|
+
PPCommand::Main.new.execute(ARGV)
|
35
7
|
end
|
36
|
-
|
37
|
-
def pp_csv(source)
|
38
|
-
require 'csv'
|
39
|
-
pp CSV.parse(source)
|
40
|
-
end
|
41
|
-
|
42
|
-
def pp_csvtable(source)
|
43
|
-
require 'csv'
|
44
|
-
data = CSV.parse(source)
|
45
|
-
keys = data.shift
|
46
|
-
result = []
|
47
|
-
data.each do |values|
|
48
|
-
entry = []
|
49
|
-
i = nil
|
50
|
-
keys.each_with_index do |k, i|
|
51
|
-
entry << [i, k, values[i]]
|
52
|
-
end
|
53
|
-
if keys.length < values.length
|
54
|
-
values[i + 1 .. -1].each_with_index do |v, j|
|
55
|
-
entry << [i + j + 1, nil, v]
|
56
|
-
end
|
57
|
-
end
|
58
|
-
result << entry
|
59
|
-
end
|
60
|
-
pp result
|
61
|
-
# data.map {|values| Hash[* [keys,values].transpose.flatten] }
|
62
|
-
end
|
63
|
-
|
64
|
-
def pp_html(source)
|
65
|
-
begin
|
66
|
-
require 'nokogiri'
|
67
|
-
rescue Exception => e
|
68
|
-
STDERR.puts "'nokogiri' is required to parse HTML."
|
69
|
-
STDERR.puts "$ sudo gem install nokorigi"
|
70
|
-
return
|
71
|
-
end
|
72
|
-
doc = Nokogiri.HTML(source)
|
73
|
-
# doc.serialize(:encoding => 'UTF-8', :save_with => Nokogiri::XML::Node::SaveOptions::FORMAT | Nokogiri::XML::Node::SaveOptions::AS_XML)
|
74
|
-
pp doc
|
75
|
-
end
|
76
|
-
|
77
|
-
def execute(argv)
|
78
|
-
opts = {:type => "auto"}
|
79
|
-
opp = OptionParser.new
|
80
|
-
|
81
|
-
opp.banner = "pp [options] [file|URI]"
|
82
|
-
opp.on_tail("-h", "--help", "show this help.") do
|
83
|
-
puts opp
|
84
|
-
exit
|
85
|
-
end
|
86
|
-
opp.on_tail("-v", "--version", "show version.") do
|
87
|
-
puts "ppcommand " + File.read(File.dirname(__FILE__) + "/../VERSION")
|
88
|
-
exit
|
89
|
-
end
|
90
|
-
|
91
|
-
opp.on("-c", "--csv", "parse CSV and pp."){|x| opts[:type] = "csv"}
|
92
|
-
opp.on("-C", "--csvtable", "parse CSV, add labels and pp."){|x| opts[:type] = "csvtable"}
|
93
|
-
opp.on("-H", "--html", "parse HTML and pp."){|x| opts[:type] = "html"}
|
94
|
-
opp.on("-j", "--json", "parse JSON and pp."){|x| opts[:type] = "json"}
|
95
|
-
opp.on("-x", "--xml", "parse XML using REXML and pp."){|x| opts[:type] = "xml"}
|
96
|
-
opp.on("-X", "--xmlsimple", "parse XML using XMLSimple and pp."){|x| opts[:type] = "xmlsimple"}
|
97
|
-
opp.on("-y", "--yaml", "parse YAML and pp."){|x| opts[:type] = "yaml"}
|
98
|
-
|
99
|
-
opp.on("-t", "--text", "do not parse. print plain text."){|x| opts[:type] = "text"}
|
100
|
-
|
101
|
-
opp.parse!(argv)
|
102
|
-
|
103
|
-
file = argv.shift
|
104
|
-
|
105
|
-
source = ""
|
106
|
-
if file.nil?
|
107
|
-
source = STDIN.read
|
108
|
-
elsif file=~ %r{^https?://}
|
109
|
-
require 'open-uri'
|
110
|
-
open(file) do |io|
|
111
|
-
source = io.read
|
112
|
-
if opts[:type] == "auto"
|
113
|
-
t = io.content_type
|
114
|
-
if t =~ /json/
|
115
|
-
opts[:type] = "json"
|
116
|
-
elsif t =~ /yaml/
|
117
|
-
opts[:type] = "yaml"
|
118
|
-
elsif t =~ /csv/
|
119
|
-
opts[:type] = "csv"
|
120
|
-
elsif t =~ /html/
|
121
|
-
opts[:type] = "html"
|
122
|
-
elsif t =~ /xml/
|
123
|
-
opts[:type] = "xml"
|
124
|
-
end
|
125
|
-
end
|
126
|
-
end
|
127
|
-
else
|
128
|
-
source = File.read(file)
|
129
|
-
end
|
130
|
-
|
131
|
-
if opts[:type] == "auto"
|
132
|
-
if file =~ /\.xml$/i
|
133
|
-
opts[:type] = "xml"
|
134
|
-
elsif file =~ /\.json$/i
|
135
|
-
opts[:type] = "json"
|
136
|
-
elsif file =~ /\.(?:csv|txt)$/i
|
137
|
-
opts[:type] = "csv"
|
138
|
-
elsif file =~ /\.html$/i
|
139
|
-
opts[:type] = "html"
|
140
|
-
else
|
141
|
-
opts[:type] = "yaml"
|
142
|
-
end
|
143
|
-
end
|
144
|
-
|
145
|
-
case opts[:type]
|
146
|
-
when "xml"
|
147
|
-
pp_xml(source)
|
148
|
-
when "xmlsimple"
|
149
|
-
pp_xmlsimple(source)
|
150
|
-
when "json"
|
151
|
-
pp_json(source)
|
152
|
-
when "csv"
|
153
|
-
pp_csv(source)
|
154
|
-
when "csvtable"
|
155
|
-
pp_csvtable(source)
|
156
|
-
when "html"
|
157
|
-
pp_html(source)
|
158
|
-
when "text"
|
159
|
-
puts source
|
160
|
-
else "yaml"
|
161
|
-
pp_yaml(source)
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
|
-
|
166
|
-
# original from http://snippets.dzone.com/posts/show/4953
|
167
|
-
def x_pretty_print(parent_node, itab)
|
168
|
-
buffer = ''
|
169
|
-
parent_node.elements.each do |node|
|
170
|
-
buffer += ' ' * itab + "<#{node.name}#{get_att_list(node, itab)}"
|
171
|
-
if node.to_a.length > 0
|
172
|
-
buffer += ">"
|
173
|
-
if node.text.nil?
|
174
|
-
buffer += "\n"
|
175
|
-
buffer += x_pretty_print(node,itab+2)
|
176
|
-
buffer += ' ' * itab + "</#{node.name}>\n"
|
177
|
-
else
|
178
|
-
node_text = node.text.strip
|
179
|
-
if node_text != ''
|
180
|
-
buffer += node_text
|
181
|
-
buffer += "</#{node.name}>\n"
|
182
|
-
else
|
183
|
-
buffer += "\n" + x_pretty_print(node,itab+2)
|
184
|
-
buffer += ' ' * itab + "</#{node.name}>\n"
|
185
|
-
end
|
186
|
-
end
|
187
|
-
else
|
188
|
-
buffer += " />\n"
|
189
|
-
end
|
190
|
-
|
191
|
-
end
|
192
|
-
buffer
|
193
|
-
end
|
194
|
-
|
195
|
-
def get_att_list(node, itab = 0)
|
196
|
-
att_list = ''
|
197
|
-
node.attributes.each { |attribute, val| att_list += "\n" + (" " * itab) + " #{attribute} = \"#{val}\"" }
|
198
|
-
att_list
|
199
|
-
end
|
200
|
-
|
201
|
-
def pretty_xml(doc)
|
202
|
-
buffer = ''
|
203
|
-
xml_declaration = doc.to_s.match('<\?.*\?>').to_s
|
204
|
-
buffer += "#{xml_declaration}\n" if not xml_declaration.nil?
|
205
|
-
xml_doctype = doc.to_s.match('<\!.*\">').to_s
|
206
|
-
buffer += "#{xml_doctype}\n" if not xml_doctype.nil?
|
207
|
-
buffer += "<#{doc.root.name}#{get_att_list(doc.root)}"
|
208
|
-
if doc.root.to_a.length > 0
|
209
|
-
buffer +=">\n#{x_pretty_print(doc.root,2)}</#{doc.root.name}>"
|
210
|
-
else
|
211
|
-
buffer += " />\n"
|
212
|
-
end
|
213
|
-
end
|
214
|
-
|
215
8
|
end
|
216
|
-
|
217
|
-
|
@@ -0,0 +1,211 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require 'pp'
|
4
|
+
require 'yaml'
|
5
|
+
require 'optparse'
|
6
|
+
|
7
|
+
module PPCommand
|
8
|
+
class Main
|
9
|
+
|
10
|
+
def pp_xml(source)
|
11
|
+
require 'rubygems'
|
12
|
+
require 'rexml/document'
|
13
|
+
puts pretty_xml(REXML::Document.new(source))
|
14
|
+
end
|
15
|
+
|
16
|
+
def pp_xmlsimple(source)
|
17
|
+
require 'rubygems'
|
18
|
+
require 'xmlsimple'
|
19
|
+
pp XmlSimple.xml_in(source)
|
20
|
+
end
|
21
|
+
|
22
|
+
def pp_json(source)
|
23
|
+
require 'rubygems'
|
24
|
+
require 'json'
|
25
|
+
pp JSON.parse(source)
|
26
|
+
end
|
27
|
+
|
28
|
+
def pp_yaml(source)
|
29
|
+
YAML.each_document(StringIO.new(source)) do |obj|
|
30
|
+
pp obj
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def pp_csv(source)
|
35
|
+
require 'csv'
|
36
|
+
pp CSV.parse(source)
|
37
|
+
end
|
38
|
+
|
39
|
+
def pp_csvtable(source)
|
40
|
+
require 'csv'
|
41
|
+
data = CSV.parse(source)
|
42
|
+
keys = data.shift
|
43
|
+
result = []
|
44
|
+
data.each do |values|
|
45
|
+
entry = []
|
46
|
+
i = nil
|
47
|
+
keys.each_with_index do |k, i|
|
48
|
+
entry << [i, k, values[i]]
|
49
|
+
end
|
50
|
+
if keys.length < values.length
|
51
|
+
values[i + 1 .. -1].each_with_index do |v, j|
|
52
|
+
entry << [i + j + 1, nil, v]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
result << entry
|
56
|
+
end
|
57
|
+
pp result
|
58
|
+
# data.map {|values| Hash[* [keys,values].transpose.flatten] }
|
59
|
+
end
|
60
|
+
|
61
|
+
def pp_html(source)
|
62
|
+
begin
|
63
|
+
require 'nokogiri'
|
64
|
+
rescue Exception => e
|
65
|
+
STDERR.puts "'nokogiri' is required to parse HTML."
|
66
|
+
STDERR.puts "$ gem install nokorigi"
|
67
|
+
return
|
68
|
+
end
|
69
|
+
doc = Nokogiri.HTML(source)
|
70
|
+
# doc.serialize(:encoding => 'UTF-8', :save_with => Nokogiri::XML::Node::SaveOptions::FORMAT | Nokogiri::XML::Node::SaveOptions::AS_XML)
|
71
|
+
pp doc
|
72
|
+
end
|
73
|
+
|
74
|
+
def execute(argv)
|
75
|
+
opts = {:type => "auto"}
|
76
|
+
opp = OptionParser.new
|
77
|
+
|
78
|
+
opp.banner = "pp [options] [file|URI]"
|
79
|
+
opp.on_tail("-h", "--help", "show this help.") do
|
80
|
+
puts opp
|
81
|
+
exit
|
82
|
+
end
|
83
|
+
opp.on_tail("-v", "--version", "show version.") do
|
84
|
+
puts "ppcommand #{ PPCommand::VERSION }"
|
85
|
+
exit
|
86
|
+
end
|
87
|
+
|
88
|
+
opp.on("-c", "--csv", "parse CSV and pp."){|x| opts[:type] = "csv"}
|
89
|
+
opp.on("-C", "--csvtable", "parse CSV, add labels and pp."){|x| opts[:type] = "csvtable"}
|
90
|
+
opp.on("-H", "--html", "parse HTML and pp."){|x| opts[:type] = "html"}
|
91
|
+
opp.on("-j", "--json", "parse JSON and pp."){|x| opts[:type] = "json"}
|
92
|
+
opp.on("-x", "--xml", "parse XML using REXML and pp."){|x| opts[:type] = "xml"}
|
93
|
+
opp.on("-X", "--xmlsimple", "parse XML using XMLSimple and pp."){|x| opts[:type] = "xmlsimple"}
|
94
|
+
opp.on("-y", "--yaml", "parse YAML and pp."){|x| opts[:type] = "yaml"}
|
95
|
+
|
96
|
+
opp.on("-t", "--text", "do not parse. print plain text."){|x| opts[:type] = "text"}
|
97
|
+
|
98
|
+
opp.parse!(argv)
|
99
|
+
|
100
|
+
file = argv.shift
|
101
|
+
|
102
|
+
source = ""
|
103
|
+
if file.nil?
|
104
|
+
source = STDIN.read
|
105
|
+
elsif file=~ %r{^https?://}
|
106
|
+
require 'open-uri'
|
107
|
+
open(file) do |io|
|
108
|
+
source = io.read
|
109
|
+
if opts[:type] == "auto"
|
110
|
+
t = io.content_type
|
111
|
+
if t =~ /json/
|
112
|
+
opts[:type] = "json"
|
113
|
+
elsif t =~ /yaml/
|
114
|
+
opts[:type] = "yaml"
|
115
|
+
elsif t =~ /csv/
|
116
|
+
opts[:type] = "csv"
|
117
|
+
elsif t =~ /html/
|
118
|
+
opts[:type] = "html"
|
119
|
+
elsif t =~ /xml/
|
120
|
+
opts[:type] = "xml"
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
else
|
125
|
+
source = File.read(file)
|
126
|
+
end
|
127
|
+
|
128
|
+
if opts[:type] == "auto"
|
129
|
+
if file =~ /\.xml$/i
|
130
|
+
opts[:type] = "xml"
|
131
|
+
elsif file =~ /\.json$/i
|
132
|
+
opts[:type] = "json"
|
133
|
+
elsif file =~ /\.(?:csv|txt)$/i
|
134
|
+
opts[:type] = "csv"
|
135
|
+
elsif file =~ /\.html$/i
|
136
|
+
opts[:type] = "html"
|
137
|
+
else
|
138
|
+
opts[:type] = "yaml"
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
case opts[:type]
|
143
|
+
when "xml"
|
144
|
+
pp_xml(source)
|
145
|
+
when "xmlsimple"
|
146
|
+
pp_xmlsimple(source)
|
147
|
+
when "json"
|
148
|
+
pp_json(source)
|
149
|
+
when "csv"
|
150
|
+
pp_csv(source)
|
151
|
+
when "csvtable"
|
152
|
+
pp_csvtable(source)
|
153
|
+
when "html"
|
154
|
+
pp_html(source)
|
155
|
+
when "text"
|
156
|
+
puts source
|
157
|
+
else "yaml"
|
158
|
+
pp_yaml(source)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
# original from http://snippets.dzone.com/posts/show/4953
|
163
|
+
def x_pretty_print(parent_node, itab)
|
164
|
+
buffer = ''
|
165
|
+
parent_node.elements.each do |node|
|
166
|
+
buffer += ' ' * itab + "<#{node.name}#{get_att_list(node, itab)}"
|
167
|
+
if node.to_a.length > 0
|
168
|
+
buffer += ">"
|
169
|
+
if node.text.nil?
|
170
|
+
buffer += "\n"
|
171
|
+
buffer += x_pretty_print(node,itab+2)
|
172
|
+
buffer += ' ' * itab + "</#{node.name}>\n"
|
173
|
+
else
|
174
|
+
node_text = node.text.strip
|
175
|
+
if node_text != ''
|
176
|
+
buffer += node_text
|
177
|
+
buffer += "</#{node.name}>\n"
|
178
|
+
else
|
179
|
+
buffer += "\n" + x_pretty_print(node,itab+2)
|
180
|
+
buffer += ' ' * itab + "</#{node.name}>\n"
|
181
|
+
end
|
182
|
+
end
|
183
|
+
else
|
184
|
+
buffer += " />\n"
|
185
|
+
end
|
186
|
+
|
187
|
+
end
|
188
|
+
buffer
|
189
|
+
end
|
190
|
+
|
191
|
+
def get_att_list(node, itab = 0)
|
192
|
+
att_list = ''
|
193
|
+
node.attributes.each { |attribute, val| att_list += "\n" + (" " * itab) + " #{attribute} = \"#{val}\"" }
|
194
|
+
att_list
|
195
|
+
end
|
196
|
+
|
197
|
+
def pretty_xml(doc)
|
198
|
+
buffer = ''
|
199
|
+
xml_declaration = doc.to_s.match('<\?.*\?>').to_s
|
200
|
+
buffer += "#{xml_declaration}\n" if not xml_declaration.nil?
|
201
|
+
xml_doctype = doc.to_s.match('<\!.*\">').to_s
|
202
|
+
buffer += "#{xml_doctype}\n" if not xml_doctype.nil?
|
203
|
+
buffer += "<#{doc.root.name}#{get_att_list(doc.root)}"
|
204
|
+
if doc.root.to_a.length > 0
|
205
|
+
buffer +=">\n#{x_pretty_print(doc.root,2)}</#{doc.root.name}>"
|
206
|
+
else
|
207
|
+
buffer += " />\n"
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
data/ppcommand.gemspec
CHANGED
@@ -1,64 +1,26 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'ppcommand/version'
|
5
5
|
|
6
|
-
Gem::Specification.new do |
|
7
|
-
|
8
|
-
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'ppcommand'
|
8
|
+
spec.version = PPCommand::VERSION
|
9
|
+
spec.authors = ['KOSEKI Kengo']
|
10
|
+
spec.email = ['koseki@gmail.com']
|
11
|
+
spec.summary = %q{Parse and pretty print YAML/JSON/XML/CSV/HTML}
|
12
|
+
spec.description = %q{Parse and pretty print YAML/JSON/XML/CSV/HTML}
|
13
|
+
spec.homepage = 'http://github.com/koseki/ppcommand'
|
14
|
+
spec.license = 'MIT'
|
9
15
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
s.description = %q{Parse and pp YAML/JSON/XML/CSV/HTML}
|
15
|
-
s.email = %q{koseki@gmail.com}
|
16
|
-
s.executables = ["pp"]
|
17
|
-
s.extra_rdoc_files = [
|
18
|
-
"LICENSE",
|
19
|
-
"README.rdoc"
|
20
|
-
]
|
21
|
-
s.files = [
|
22
|
-
".document",
|
23
|
-
".gitignore",
|
24
|
-
"LICENSE",
|
25
|
-
"README.rdoc",
|
26
|
-
"Rakefile",
|
27
|
-
"VERSION",
|
28
|
-
"bin/pp",
|
29
|
-
"lib/ppcommand.rb",
|
30
|
-
"ppcommand.gemspec",
|
31
|
-
"spec/ppcommand_spec.rb",
|
32
|
-
"spec/spec.opts",
|
33
|
-
"spec/spec_helper.rb"
|
34
|
-
]
|
35
|
-
s.homepage = %q{http://github.com/koseki/ppcommand}
|
36
|
-
s.rdoc_options = ["--charset=UTF-8"]
|
37
|
-
s.require_paths = ["lib"]
|
38
|
-
s.rubygems_version = %q{1.3.5}
|
39
|
-
s.summary = %q{Parse and pp YAML/JSON/XML/CSV/HTML}
|
40
|
-
s.test_files = [
|
41
|
-
"spec/ppcommand_spec.rb",
|
42
|
-
"spec/spec_helper.rb"
|
43
|
-
]
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ['lib']
|
44
20
|
|
45
|
-
|
46
|
-
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
47
|
-
s.specification_version = 3
|
21
|
+
spec.add_dependency 'xml-simple'
|
48
22
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
|
53
|
-
else
|
54
|
-
s.add_dependency(%q<json>, [">= 0"])
|
55
|
-
s.add_dependency(%q<xml-simple>, [">= 0"])
|
56
|
-
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
57
|
-
end
|
58
|
-
else
|
59
|
-
s.add_dependency(%q<json>, [">= 0"])
|
60
|
-
s.add_dependency(%q<xml-simple>, [">= 0"])
|
61
|
-
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
62
|
-
end
|
23
|
+
spec.add_development_dependency 'bundler', '~> 1.6'
|
24
|
+
spec.add_development_dependency 'rake'
|
25
|
+
spec.add_development_dependency 'rspec'
|
63
26
|
end
|
64
|
-
|
metadata
CHANGED
@@ -1,122 +1,119 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: ppcommand
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
prerelease:
|
6
|
-
segments:
|
7
|
-
- 0
|
8
|
-
- 1
|
9
|
-
- 5
|
10
|
-
version: 0.1.5
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.0
|
11
5
|
platform: ruby
|
12
|
-
authors:
|
6
|
+
authors:
|
13
7
|
- KOSEKI Kengo
|
14
8
|
autorequire:
|
15
9
|
bindir: bin
|
16
10
|
cert_chain: []
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
dependencies:
|
21
|
-
- !ruby/object:Gem::Dependency
|
22
|
-
name: json
|
23
|
-
prerelease: false
|
24
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
|
-
requirements:
|
27
|
-
- - ">="
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
hash: 3
|
30
|
-
segments:
|
31
|
-
- 0
|
32
|
-
version: "0"
|
33
|
-
type: :runtime
|
34
|
-
version_requirements: *id001
|
35
|
-
- !ruby/object:Gem::Dependency
|
11
|
+
date: 2014-12-21 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
36
14
|
name: xml-simple
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
- !ruby/object:Gem::Version
|
43
|
-
hash: 3
|
44
|
-
segments:
|
45
|
-
- 0
|
46
|
-
version: "0"
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
47
20
|
type: :runtime
|
48
|
-
version_requirements: *id002
|
49
|
-
- !ruby/object:Gem::Dependency
|
50
|
-
name: rspec
|
51
21
|
prerelease: false
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.6'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.6'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
63
48
|
type: :development
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description: Parse and pretty print YAML/JSON/XML/CSV/HTML
|
70
|
+
email:
|
71
|
+
- koseki@gmail.com
|
72
|
+
executables:
|
68
73
|
- pp
|
69
74
|
extensions: []
|
70
|
-
|
71
|
-
|
72
|
-
- LICENSE
|
73
|
-
- README.rdoc
|
74
|
-
files:
|
75
|
+
extra_rdoc_files: []
|
76
|
+
files:
|
75
77
|
- .document
|
76
|
-
-
|
77
|
-
-
|
78
|
+
- .gitignore
|
79
|
+
- Gemfile
|
80
|
+
- LICENSE.txt
|
81
|
+
- README.md
|
78
82
|
- Rakefile
|
79
83
|
- VERSION
|
80
84
|
- bin/pp
|
81
85
|
- lib/ppcommand.rb
|
86
|
+
- lib/ppcommand/main.rb
|
87
|
+
- lib/ppcommand/version.rb
|
82
88
|
- ppcommand.gemspec
|
83
89
|
- spec/ppcommand_spec.rb
|
84
90
|
- spec/spec.opts
|
85
91
|
- spec/spec_helper.rb
|
86
|
-
has_rdoc: true
|
87
92
|
homepage: http://github.com/koseki/ppcommand
|
88
|
-
licenses:
|
89
|
-
|
93
|
+
licenses:
|
94
|
+
- MIT
|
95
|
+
metadata: {}
|
90
96
|
post_install_message:
|
91
97
|
rdoc_options: []
|
92
|
-
|
93
|
-
require_paths:
|
98
|
+
require_paths:
|
94
99
|
- lib
|
95
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
none: false
|
106
|
-
requirements:
|
107
|
-
- - ">="
|
108
|
-
- !ruby/object:Gem::Version
|
109
|
-
hash: 3
|
110
|
-
segments:
|
111
|
-
- 0
|
112
|
-
version: "0"
|
100
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - '>='
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '0'
|
105
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
113
110
|
requirements: []
|
114
|
-
|
115
111
|
rubyforge_project:
|
116
|
-
rubygems_version:
|
112
|
+
rubygems_version: 2.0.14
|
117
113
|
signing_key:
|
118
|
-
specification_version:
|
119
|
-
summary: Parse and
|
120
|
-
test_files:
|
114
|
+
specification_version: 4
|
115
|
+
summary: Parse and pretty print YAML/JSON/XML/CSV/HTML
|
116
|
+
test_files:
|
121
117
|
- spec/ppcommand_spec.rb
|
118
|
+
- spec/spec.opts
|
122
119
|
- spec/spec_helper.rb
|