yaml_command 0.1.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.
@@ -0,0 +1,42 @@
1
+ module YAMLCommand
2
+
3
+ # Read a YAML file, open in default editor, validate and save.
4
+ # If directory instead of a file, slurp together as temporary
5
+ # YAML file and then re-splat to save.
6
+ #
7
+ class Command::EditCommand < Command
8
+
9
+ TMP_FILE = ".tmp.yml" # TODO: real tmpfile
10
+
11
+ EDITOR = ENV['EDITOR'] || 'vi'
12
+
13
+ # Edit a YAML file, or edit a directory via slurp and splt.
14
+ def call(file_or_dir)
15
+ if File.directory?(file_or_dir)
16
+ data0 = Console.slurp(file_or_dir)
17
+ File.open(TMP_FILE, 'w'){ |f| f << data0.to_yaml }
18
+ edit_file(tmpfile)
19
+ data1 = YAML.load_file(TMP_FILE)
20
+ Console.splat(file_or_dir, :data=>data1)
21
+ elsif File.file?(file_or_dir)
22
+ edit_file(file_or_dir)
23
+ else
24
+ abort "does not exist"
25
+ end
26
+ end
27
+
28
+ #
29
+ def edit_file(file)
30
+ success = system "#{EDITOR} #{file}"
31
+ if success
32
+ begin
33
+ YAML.load_file(file)
34
+ rescue
35
+ edit_file(file)
36
+ end
37
+ end
38
+ end
39
+
40
+ end
41
+
42
+ end
@@ -0,0 +1,30 @@
1
+ module YAMLCommand
2
+
3
+ class Command::GetCommand < Command
4
+
5
+ # Output an indexed value of a YAML document.
6
+ def call(name)
7
+ case data
8
+ when Array
9
+ value = data[name.to_i]
10
+ else
11
+ value = data[name] || data[name.to_sym]
12
+ end
13
+
14
+ output(
15
+ case value
16
+ when String, Numeric
17
+ value
18
+ when Date
19
+ value.strftime('%Y-%m-%d')
20
+ when Time
21
+ value.strftime('%Y-%m-%d %H:%M:%S')
22
+ else
23
+ value
24
+ end
25
+ )
26
+ end
27
+
28
+ end
29
+
30
+ end
@@ -0,0 +1,36 @@
1
+ module YAMLCommand
2
+
3
+ class Command::SetCommand < Command
4
+
5
+ # Set an indexed value of a YAML document.
6
+ def call(name, new_value)
7
+ case data
8
+ when Array
9
+ raise ArgumentError unless name.to_s =~ /d+/
10
+ index = name.to_i
11
+ old_value = data[index]
12
+ data[index] = new_value
13
+ when Hash
14
+ if data.key?(name)
15
+ key = name
16
+ old_value = data[name]
17
+ data[name] = new_value
18
+ elsif data.key?(name.to_sym)
19
+ key = name.to_sym
20
+ old_value = data[key]
21
+ data[key] = new_value
22
+ end
23
+ else
24
+ raise NotImplementedError
25
+ end
26
+
27
+ if !old_value.eql?(new_value)
28
+ #TODO: save
29
+ output data
30
+ end
31
+
32
+ end
33
+
34
+ end
35
+
36
+ end
@@ -0,0 +1,52 @@
1
+ module YAMLCommand
2
+
3
+ # Given a directory, read each file into a mapping
4
+ # with directories into a nested mapping.
5
+ #
6
+ class Command::SlurpCommand < Command
7
+
8
+ # Import each file of a directory into a YAML file.
9
+ def slurp(dir)
10
+ output slurp_directory(dir)
11
+ end
12
+
13
+ #
14
+ alias_method :call, :slurp
15
+
16
+ #
17
+ def recurse?
18
+ @recurse
19
+ end
20
+
21
+ #
22
+ def recurse=(boolean)
23
+ @recurse = boolean
24
+ end
25
+
26
+ alias_switch :r, :recurse
27
+
28
+ private
29
+
30
+ # Import each file of a directory into a YAML file.
31
+ def slurp_directory(dir, hash={})
32
+ Dir.entries(dir).each do |path|
33
+ next if path == '.' or path == '..'
34
+ local = File.join(dir, path)
35
+ if File.directory?(local)
36
+ if recurse?
37
+ subhash = {}
38
+ hash[path] = slurp_directory(local, subhash)
39
+ end
40
+ else
41
+ text = File.read(local)
42
+ hash[path] = YAML.load(text) # any cases where this is not good idea?
43
+ end
44
+ end
45
+
46
+ hash
47
+ end
48
+
49
+ end
50
+
51
+ end
52
+
@@ -0,0 +1,52 @@
1
+ module YAMLCommand
2
+
3
+ # Sort command.
4
+ #
5
+ # Very limited at this point as it will only sort toplevel
6
+ # sequence or mappings.
7
+ #
8
+ class Command::SortCommand < Command
9
+
10
+ # Create files recursively?
11
+ #attr_switch :save
12
+ #alias_switch :s, :save
13
+
14
+ # Select ordering, descending or ascending (default).
15
+ # Use `descending` or `reverse` or abbreviations `d` or `r` for opposite order.
16
+ attr_accessor :order
17
+ alias_accessor :o, :order
18
+
19
+ # Sort in ascending or descending order.
20
+ def call(ypath=nil)
21
+ if ypath
22
+ raise NotImplementedError, "YPath not supported yet."
23
+ end
24
+
25
+ case data
26
+ when Array
27
+ new_data = data.sort
28
+ when Hash
29
+ new_data = {}
30
+ data.keys.sort.each do |k|
31
+ new_data[k] = data[k]
32
+ end
33
+ end
34
+
35
+ #save
36
+ output new_data
37
+ end
38
+
39
+ private
40
+
41
+ def sort(list)
42
+ case order
43
+ when /^r/, /^d/ # reverse or descending
44
+ list.sort.reverse
45
+ else
46
+ list.sort
47
+ end
48
+ end
49
+
50
+ end
51
+
52
+ end
@@ -0,0 +1,130 @@
1
+ module YAMLCommand
2
+
3
+ # Writes each entry of a YAML hash to a file.
4
+ # This is the opposite of #slurp.
5
+ #
6
+ class Command::SplatCommand < Command
7
+
8
+ # Create files recursively?
9
+ attr_switch :recurse
10
+ alias_switch :r, :recurse
11
+
12
+ # Dryrun mode.
13
+ attr_switch :dryrun
14
+ alias_switch :D, :dryrun
15
+
16
+ # Splat a YAML mapping document into a directory of files.
17
+ # One file is created for each mapping key.
18
+ def call(dir=nil)
19
+ raise 'not a mapping' unless Hash === data
20
+
21
+ dir ||= file.chomp('.yaml').chomp('.yml')
22
+
23
+ old_map = build_old_map(dir)
24
+ new_map = build_new_map(dir)
25
+
26
+ # TODO: get a list of keys that will actually change
27
+
28
+ remove = (old_map.keys - new_map.keys).sort
29
+
30
+ if dryrun?
31
+ save_dryrun(remove, new_map.keys)
32
+ return
33
+ end
34
+
35
+ unless remove.empty? or force?
36
+ $stderr.puts "This operation will remove:"
37
+ remove.each do |f|
38
+ $stderr.puts " #{f}"
39
+ end
40
+ $stderr.puts "Use -f/--force option to proceed."
41
+ return
42
+ end
43
+
44
+ remove.each do |f|
45
+ FileUtils.rm_r(f) if File.exist?(f)
46
+ end
47
+
48
+ new_map.each do |f,v|
49
+ if v != old_map[f]
50
+ d = File.dirname(f)
51
+ FileUtils.mkdir_p(d) unless File.directory?(d)
52
+ File.open(f, 'w'){ |f| f << v }
53
+ end
54
+ end
55
+
56
+ nil
57
+ end
58
+
59
+ private
60
+
61
+ #
62
+ def save_dryun(remove, write)
63
+ $stderr.puts "[DRYRUN]"
64
+ remove.each do |f|
65
+ $stderr.puts " (remove) #{f}"
66
+ end
67
+
68
+ write.each do |f|
69
+ $stderr.puts " (write) #{f}"
70
+ end
71
+ end
72
+
73
+ #
74
+ def build_new_map(dir, data=nil)
75
+ map = {}
76
+ data ||= data()
77
+ data.each do |k,v|
78
+ if Hash === v && recurse?
79
+ sub_map = build_new_map(File.join(dir, k), v)
80
+ map.update(sub_map)
81
+ else
82
+ value = render_value(v)
83
+ end
84
+ map[File.join(dir,k)] = value
85
+ end
86
+ map
87
+ end
88
+
89
+ #
90
+ def build_old_map(dir)
91
+ return {} unless File.directory?(dir)
92
+
93
+ map = {}
94
+ entries = Dir.entries(dir) - ['.', '..']
95
+ entries.each do |e|
96
+ k = File.join(dir, e)
97
+ if File.directory?(k)
98
+ if recurse?
99
+ value = build_old_map(File.join(dir, k))
100
+ map[k] = value
101
+ end
102
+ else
103
+ v = File.read(k)
104
+ value = render_value(v)
105
+ map[k] = value
106
+ end
107
+ end
108
+ map
109
+ end
110
+
111
+ #
112
+ def render_value(value)
113
+ case value
114
+ when Hash
115
+ txt = value.to_yaml
116
+ when String, Numeric
117
+ txt = value.to_s
118
+ when Date
119
+ txt = value.strftime('%Y-%m-%d')
120
+ when Time
121
+ txt = value.strftime('%Y-%m-%d %H:%M:%S')
122
+ else
123
+ txt = value.to_yaml
124
+ end
125
+ txt
126
+ end
127
+
128
+ end
129
+
130
+ end
@@ -0,0 +1,49 @@
1
+ module YAMLCommand
2
+
3
+ # TODO: View could use a better implmentation, it is very simplistic
4
+ # at this point.
5
+
6
+ # TODO: Should view make a YAML stream if given multiple files ?
7
+
8
+
9
+ # Display YAML file with color highlighting.
10
+ #
11
+ # This command requires the ANSI gem be installed.
12
+ #
13
+ class Command::ViewCommand < Command
14
+
15
+ #
16
+ # Invoke view command.
17
+ #
18
+ def call(path=nil)
19
+ require 'ansi'
20
+
21
+ colon = ":".ansi(:magenta)
22
+
23
+ if path
24
+ text = File.read(path)
25
+ else
26
+ if file
27
+ text = File.read(file)
28
+ else
29
+ text = $stdin.read
30
+ end
31
+ end
32
+
33
+ text.each_line do |line|
34
+ case line
35
+ when /^---/
36
+ print line
37
+ when /^(\s*\-)(.*?)$/
38
+ puts "%s%s" % [$1.ansi(:magenta), $2]
39
+ when /^(\s*\w+)\:(.*?)$/
40
+ puts "%s%s%s" % [$1.ansi(:cyan), colon, $2]
41
+ else
42
+ print line
43
+ end
44
+ end
45
+ end
46
+
47
+ end
48
+
49
+ end
data/man/yaml-edit.1 ADDED
@@ -0,0 +1,24 @@
1
+ .\" generated with Ronn/v0.7.3
2
+ .\" http://github.com/rtomayko/ronn/tree/0.7.3
3
+ .
4
+ .TH "YAML\-EDIT" "1" "December 2012" "YAML.ORG" "YAML COMMAND"
5
+ .
6
+ .SH "NAME"
7
+ \fByaml\-edit\fR \- yaml edit command
8
+ .
9
+ .SH "SYNOPSIS"
10
+ \fByaml edit [options] [path]\fR
11
+ .
12
+ .SH "DESCRIPTION"
13
+ Edit a YAML file using the standard editor (via $EDITOR)\. If a directory path is given then splurp the directory, edit the result and when saved splat the result back to the directory\.
14
+ .
15
+ .SH "OPTIONS"
16
+ The following options are available to the edit command\.
17
+ .
18
+ .IP "\(bu" 4
19
+ \fB\-F\fR/\fB\-\-file\fR \fIPATH\fR The YAML file to query, if not by stdin\.
20
+ .
21
+ .IP "" 0
22
+ .
23
+ .SH "SEE ALSO"
24
+ yaml(1), yaml\-set(1), yaml\-sort(1), yaml\-slurp(1), yaml\-splurp(1), yaml\-splat(1), yaml\-view(1)
@@ -0,0 +1,107 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta http-equiv='content-type' value='text/html;charset=utf8'>
5
+ <meta name='generator' value='Ronn/v0.7.3 (http://github.com/rtomayko/ronn/tree/0.7.3)'>
6
+ <title>yaml-edit(1) - yaml edit command</title>
7
+ <style type='text/css' media='all'>
8
+ /* style: man */
9
+ body#manpage {margin:0}
10
+ .mp {max-width:100ex;padding:0 9ex 1ex 4ex}
11
+ .mp p,.mp pre,.mp ul,.mp ol,.mp dl {margin:0 0 20px 0}
12
+ .mp h2 {margin:10px 0 0 0}
13
+ .mp > p,.mp > pre,.mp > ul,.mp > ol,.mp > dl {margin-left:8ex}
14
+ .mp h3 {margin:0 0 0 4ex}
15
+ .mp dt {margin:0;clear:left}
16
+ .mp dt.flush {float:left;width:8ex}
17
+ .mp dd {margin:0 0 0 9ex}
18
+ .mp h1,.mp h2,.mp h3,.mp h4 {clear:left}
19
+ .mp pre {margin-bottom:20px}
20
+ .mp pre+h2,.mp pre+h3 {margin-top:22px}
21
+ .mp h2+pre,.mp h3+pre {margin-top:5px}
22
+ .mp img {display:block;margin:auto}
23
+ .mp h1.man-title {display:none}
24
+ .mp,.mp code,.mp pre,.mp tt,.mp kbd,.mp samp,.mp h3,.mp h4 {font-family:monospace;font-size:14px;line-height:1.42857142857143}
25
+ .mp h2 {font-size:16px;line-height:1.25}
26
+ .mp h1 {font-size:20px;line-height:2}
27
+ .mp {text-align:justify;background:#fff}
28
+ .mp,.mp code,.mp pre,.mp pre code,.mp tt,.mp kbd,.mp samp {color:#131211}
29
+ .mp h1,.mp h2,.mp h3,.mp h4 {color:#030201}
30
+ .mp u {text-decoration:underline}
31
+ .mp code,.mp strong,.mp b {font-weight:bold;color:#131211}
32
+ .mp em,.mp var {font-style:italic;color:#232221;text-decoration:none}
33
+ .mp a,.mp a:link,.mp a:hover,.mp a code,.mp a pre,.mp a tt,.mp a kbd,.mp a samp {color:#0000ff}
34
+ .mp b.man-ref {font-weight:normal;color:#434241}
35
+ .mp pre {padding:0 4ex}
36
+ .mp pre code {font-weight:normal;color:#434241}
37
+ .mp h2+pre,h3+pre {padding-left:0}
38
+ ol.man-decor,ol.man-decor li {margin:3px 0 10px 0;padding:0;float:left;width:33%;list-style-type:none;text-transform:uppercase;color:#999;letter-spacing:1px}
39
+ ol.man-decor {width:100%}
40
+ ol.man-decor li.tl {text-align:left}
41
+ ol.man-decor li.tc {text-align:center;letter-spacing:4px}
42
+ ol.man-decor li.tr {text-align:right;float:right}
43
+ </style>
44
+ </head>
45
+ <!--
46
+ The following styles are deprecated and will be removed at some point:
47
+ div#man, div#man ol.man, div#man ol.head, div#man ol.man.
48
+
49
+ The .man-page, .man-decor, .man-head, .man-foot, .man-title, and
50
+ .man-navigation should be used instead.
51
+ -->
52
+ <body id='manpage'>
53
+ <div class='mp' id='man'>
54
+
55
+ <div class='man-navigation' style='display:none'>
56
+ <a href="#NAME">NAME</a>
57
+ <a href="#SYNOPSIS">SYNOPSIS</a>
58
+ <a href="#DESCRIPTION">DESCRIPTION</a>
59
+ <a href="#OPTIONS">OPTIONS</a>
60
+ <a href="#SEE-ALSO">SEE ALSO</a>
61
+ </div>
62
+
63
+ <ol class='man-decor man-head man head'>
64
+ <li class='tl'>yaml-edit(1)</li>
65
+ <li class='tc'>YAML COMMAND</li>
66
+ <li class='tr'>yaml-edit(1)</li>
67
+ </ol>
68
+
69
+ <h2 id="NAME">NAME</h2>
70
+ <p class="man-name">
71
+ <code>yaml-edit</code> - <span class="man-whatis">yaml edit command</span>
72
+ </p>
73
+
74
+ <h2 id="SYNOPSIS">SYNOPSIS</h2>
75
+
76
+ <p><code>yaml edit [options] [path]</code></p>
77
+
78
+ <h2 id="DESCRIPTION">DESCRIPTION</h2>
79
+
80
+ <p>Edit a YAML file using the standard editor (via $EDITOR). If a directory
81
+ path is given then splurp the directory, edit the result and when saved
82
+ splat the result back to the directory.</p>
83
+
84
+ <h2 id="OPTIONS">OPTIONS</h2>
85
+
86
+ <p>The following options are available to the edit command.</p>
87
+
88
+ <ul>
89
+ <li><code>-F</code>/<code>--file</code> <var>PATH</var>
90
+ The YAML file to query, if not by stdin.</li>
91
+ </ul>
92
+
93
+
94
+ <h2 id="SEE-ALSO">SEE ALSO</h2>
95
+
96
+ <p><a class="man-ref" href="yaml.1.html">yaml<span class="s">(1)</span></a>, <a class="man-ref" href="yaml-set.1.html">yaml-set<span class="s">(1)</span></a>, <span class="man-ref">yaml-sort<span class="s">(1)</span></span>, <a class="man-ref" href="yaml-slurp.1.html">yaml-slurp<span class="s">(1)</span></a>, <span class="man-ref">yaml-splurp<span class="s">(1)</span></span>, <a class="man-ref" href="yaml-splat.1.html">yaml-splat<span class="s">(1)</span></a>, <a class="man-ref" href="yaml-view.1.html">yaml-view<span class="s">(1)</span></a></p>
97
+
98
+
99
+ <ol class='man-decor man-foot man foot'>
100
+ <li class='tl'>YAML.ORG</li>
101
+ <li class='tc'>December 2012</li>
102
+ <li class='tr'>yaml-edit(1)</li>
103
+ </ol>
104
+
105
+ </div>
106
+ </body>
107
+ </html>