munger 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ pkg/*
2
+ *.gem
3
+ .bundle
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in munger.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,24 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ munger (1.0.0)
5
+
6
+ GEM
7
+ remote: http://rubygems.org/
8
+ specs:
9
+ columnize (0.3.4)
10
+ linecache (0.46)
11
+ rbx-require-relative (> 0.0.4)
12
+ rbx-require-relative (0.0.5)
13
+ ruby-debug (0.10.4)
14
+ columnize (>= 0.1)
15
+ ruby-debug-base (~> 0.10.4.0)
16
+ ruby-debug-base (0.10.4)
17
+ linecache (>= 0.3)
18
+
19
+ PLATFORMS
20
+ ruby
21
+
22
+ DEPENDENCIES
23
+ munger!
24
+ ruby-debug
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ # The MIT License
2
+ #
3
+ # Copyright (c) 2008-2011 Bryan Stearns
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,11 @@
1
+ = munger: a file-modification library (& command-line utility)
2
+
3
+ Programmatically modify files: insert something before, after, or replacing
4
+ a line that matches a pattern, or just append at the end.
5
+
6
+ (More docs to come.)
7
+
8
+ == Copyright
9
+
10
+ Copyright (c) 2008-2011 Bryan Stearns. See LICENSE.txt for
11
+ further details.
data/Rakefile ADDED
@@ -0,0 +1,13 @@
1
+ require 'bundler'
2
+ require 'rake'
3
+ require 'rake/testtask'
4
+
5
+ Bundler::GemHelper.install_tasks
6
+
7
+ Rake::TestTask.new(:test) do |test|
8
+ test.libs << 'lib' << 'test'
9
+ test.pattern = 'test/**/test_*.rb'
10
+ test.verbose = true
11
+ end
12
+
13
+ task :default => :test
data/bin/munge ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+ munger_path = File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ $LOAD_PATH.unshift(munger_path) unless $LOAD_PATH.include?(munger_path)
4
+
5
+ require 'munger'
6
+ require 'munger/cli'
7
+ Munger::CLI.run!(*ARGV)
data/lib/munger/cli.rb ADDED
@@ -0,0 +1,55 @@
1
+ require 'rubygems'
2
+ require 'ruby-debug'
3
+ require 'optparse'
4
+
5
+ module Munger
6
+ class CLI
7
+ def self.run!(*args)
8
+ return self.new(*args).run
9
+ end
10
+
11
+ def initialize(*args)
12
+ @args = args
13
+ parse_args
14
+ end
15
+
16
+ def parse_args
17
+ @content = OptionParser.new do |opts|
18
+ opts.banner = "Usage: munge <options> CONTENT"
19
+ opts.on("--before PATTERN", "Insert before the line matching PATTERN") {|@pattern| set_mode(:before) }
20
+ opts.on("--after PATTERN", "Insert after the line matching PATTERN") {|@pattern| set_mode(:after) }
21
+ opts.on("--replace PATTERN", "Replace the line matching PATTERN") {|@pattern| set_mode(:replace) }
22
+ opts.on("--append", "Append to the file") { set_mode(:append) }
23
+ opts.on("--replace-or-append PATTERN", "Replace the line matching PATTERN, or append if not found") {|@pattern| set_mode(:replace_or_append) }
24
+
25
+ opts.on("--tag TAG", "Mark our insertion with this TAG") {|@tag|}
26
+ opts.on("--input INPUT", "The filename to read; '-' for stdin") \
27
+ {|@input_path|}
28
+ opts.on("--output OUTPUT", "The filename to write; '-' for stdout") {|@output_path|}
29
+ opts.on("--content CONTENT", "A file from which to read the content to insert; '-' for stdin") \
30
+ {|@content_path|}
31
+ opts.on("-v", "--verbose", "Increase verbosity") {|@verbose|}
32
+ end.parse!(@args).first
33
+
34
+ set_mode(:append) unless @mode
35
+ abort "No --input path specified" unless @input_path
36
+ abort "No --output path specified" unless @output_path
37
+ abort "Can't specify --content with CONTENT" if (@content != nil && @content_path != nil)
38
+ abort "No content specified" unless (@content || @content_path)
39
+
40
+ @options = Munger::Munge::OPTIONS.inject({}) do |h, option|
41
+ h[option] = instance_variable_get("@#{option}") rescue nil
42
+ h
43
+ end
44
+ end
45
+
46
+ def run
47
+ Munger::munge(@options)
48
+ end
49
+
50
+ def set_mode(new_mode)
51
+ abort("Only one --before|--after|--replace|--append allowed") if @mode
52
+ @mode = new_mode
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,107 @@
1
+ module Munger
2
+ def self.munge(options={})
3
+ content = Munger.raw_or_path(options, :content, :content_path)
4
+ input = Munger.raw_or_path(options, :input, :input_path)
5
+ munge = Munger::Munge.new(options)
6
+ output = munge.run(input, content)
7
+ Munger.raw_or_path(options, :output, :output_path, output)
8
+ end
9
+
10
+ class Munge
11
+ OPTIONS = [:mode, :pattern, :tag, :content, :content_path, :input,
12
+ :input_path, :output, :output_path, :path, :verbose]
13
+ attr_accessor *(OPTIONS + [:start_tag, :end_tag])
14
+
15
+ def initialize(options)
16
+ self.mode = options[:mode] || :append
17
+ self.pattern = Regexp.compile(options[:pattern]) unless mode == :append
18
+ self.tag = options[:tag] || ''
19
+ self.verbose = options[:verbose]
20
+
21
+ if verbose
22
+ settings = OPTIONS.map {|attr| "#{attr} = #{eval "#{attr}.inspect"}" }
23
+ puts settings.join(', ')
24
+ end
25
+ end
26
+
27
+ def run(input, content)
28
+ startTag = tag + " (munge start)"
29
+ endTag = tag + " (munge end)"
30
+ content = [startTag, content.rstrip, endTag].join("\n")
31
+
32
+ result = []
33
+ skipping = nil
34
+ needMatch = [:before, :replace, :after, :replace_or_append].include? mode
35
+ input.split("\n").each do |l|
36
+ if skipping
37
+ if l == endTag
38
+ puts "Done skipping: #{l}" if verbose
39
+ skipping = nil
40
+ if [:replace, :replace_or_append].include?(mode)
41
+ puts "Inserting content" if verbose
42
+ result << content
43
+ end
44
+ else
45
+ puts "Skipping: #{l}" if verbose
46
+ end
47
+ elsif l == startTag
48
+ puts "Start skipping: #{l}" if verbose
49
+ skipping = true
50
+ needMatch = nil
51
+ else
52
+ matched = needMatch && pattern.match(l)
53
+ if mode == :before && matched
54
+ puts "Matched (before): inserting before #{l}" if verbose
55
+ result << content
56
+ needMatch = nil
57
+ end
58
+ if [:replace, :replace_or_append].include?(mode) && matched
59
+ puts "Matched (#{mode}): replacing #{l}" if verbose
60
+ result << content
61
+ needMatch = nil
62
+ else
63
+ puts "Using existing line #{l}" if verbose
64
+ result << l
65
+ end
66
+ if mode == :after && matched
67
+ puts "Matched (after): inserting after #{l}" if verbose
68
+ result << content
69
+ needMatch = nil
70
+ end
71
+ end
72
+ end
73
+
74
+ if mode == :append or (mode == :replace_or_append && needMatch)
75
+ puts "Appending..." if verbose
76
+ result << content
77
+ end
78
+
79
+ result << "" # make sure we end with a newline
80
+ result.join("\n")
81
+ end
82
+ end
83
+
84
+ private
85
+ def self.raw_or_path(options, raw_sym, path_sym, data_to_write=nil)
86
+ raw_value = options.delete(raw_sym)
87
+ path = options.delete(path_sym)
88
+ path ||= options[:path]
89
+ if data_to_write # we're writing
90
+ if path == '-'
91
+ STDOUT.write(data_to_write)
92
+ elsif path
93
+ File.open(path, 'w') {|f| f.write(data_to_write) }
94
+ else
95
+ data_to_write # just return it.
96
+ end
97
+ else # we're reading
98
+ if raw_value
99
+ raw_value
100
+ elsif path == '-'
101
+ STDIN.read
102
+ else
103
+ File.read(path)
104
+ end
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,3 @@
1
+ module Munger
2
+ VERSION = "0.0.1"
3
+ end
data/lib/munger.rb ADDED
@@ -0,0 +1 @@
1
+ require 'munger/munge'
data/munger.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "munger/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "munger"
7
+ s.version = Munger::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Bryan Stearns"]
10
+ s.email = ["bryanstearns@gmail.com"]
11
+ s.homepage = "http://github.com/bryanstearns/munger"
12
+ s.summary = %q{File-content munging library (& command-line utility)}
13
+ s.description = """
14
+ Programmatically modify files: insert something before, after, or replacing
15
+ a line that matches a pattern, or just at the end.
16
+ """
17
+
18
+ s.rubyforge_project = "munger"
19
+
20
+ s.files = `git ls-files`.split("\n")
21
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
22
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
23
+ s.require_paths = ["lib"]
24
+
25
+ s.add_development_dependency(%q<ruby-debug>, [">= 0"])
26
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,23 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+
4
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
5
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
6
+
7
+ #[File.join(File.dirname(__FILE__), '..', 'lib', 'munger'),
8
+ # File.dirname(__FILE__)].each do |path|
9
+ # path = File.expand_path(path)
10
+ # unless $LOAD_PATH.include?(path)
11
+ # # puts "test/helper: $LOAD_PATH << #{path}"
12
+ # $LOAD_PATH.unshift(path)
13
+ # end
14
+ #end
15
+
16
+ require 'munger'
17
+
18
+ class Test::Unit::TestCase
19
+ end
20
+
21
+ def my_assert_equal(expected, was)
22
+ assert expected == was, "--- Expected:\n#{expected}\n--- Was:\n#{was}"
23
+ end
data/test/mungee ADDED
@@ -0,0 +1,5 @@
1
+ Jackdaws
2
+ Love my big
3
+ Sphinx
4
+ Of Quartz.
5
+
@@ -0,0 +1,150 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class TestMunger < Test::Unit::TestCase
4
+ def setup
5
+ @verbose = nil
6
+ @text = """Existing line number one
7
+ Existing line number two
8
+ Existing line number three
9
+ """
10
+ end
11
+
12
+ def test_before
13
+ @text = Munger::munge(:mode => :before,
14
+ :pattern => "line number one",
15
+ :tag => "# BeforeOneTest", :input => @text,
16
+ :content => "This goes before line one",
17
+ :verbose => @verbose)
18
+ my_assert_equal \
19
+ """# BeforeOneTest (munge start)
20
+ This goes before line one
21
+ # BeforeOneTest (munge end)
22
+ Existing line number one
23
+ Existing line number two
24
+ Existing line number three
25
+ """, @text
26
+
27
+ @text = Munger::munge(:mode => :before,
28
+ :pattern => "line number two",
29
+ :tag => "# BeforeTwoTest", :input => @text,
30
+ :content => "This goes before line two",
31
+ :verbose => @verbose)
32
+ my_assert_equal \
33
+ """# BeforeOneTest (munge start)
34
+ This goes before line one
35
+ # BeforeOneTest (munge end)
36
+ Existing line number one
37
+ # BeforeTwoTest (munge start)
38
+ This goes before line two
39
+ # BeforeTwoTest (munge end)
40
+ Existing line number two
41
+ Existing line number three
42
+ """, @text
43
+ end
44
+
45
+ def test_after
46
+ @text = Munger::munge(:mode => :after,
47
+ :pattern => "line number three",
48
+ :tag => "# AfterThreeTest", :input => @text,
49
+ :content => "This goes after line three",
50
+ :verbose => @verbose)
51
+ my_assert_equal \
52
+ """Existing line number one
53
+ Existing line number two
54
+ Existing line number three
55
+ # AfterThreeTest (munge start)
56
+ This goes after line three
57
+ # AfterThreeTest (munge end)
58
+ """, @text
59
+
60
+ @text = Munger::munge(:mode => :after,
61
+ :pattern => "line number three",
62
+ :tag => "# AfterThreeTest", :input => @text,
63
+ :content => "New stuff for after line three",
64
+ :verbose => @verbose)
65
+ my_assert_equal \
66
+ """Existing line number one
67
+ Existing line number two
68
+ Existing line number three
69
+ # AfterThreeTest (munge start)
70
+ New stuff for after line three
71
+ # AfterThreeTest (munge end)
72
+ """, @text
73
+ end
74
+
75
+ def test_replace
76
+ @text = Munger::munge(:mode => :replace, :tag => "# ReplaceTest",
77
+ :pattern => "line number two",
78
+ :input => @text,
79
+ :content => "This is some stuff to replace with",
80
+ :verbose => @verbose)
81
+ my_assert_equal \
82
+ """Existing line number one
83
+ # ReplaceTest (munge start)
84
+ This is some stuff to replace with
85
+ # ReplaceTest (munge end)
86
+ Existing line number three
87
+ """, @text
88
+ end
89
+
90
+ def test_replace_or_append_replacing
91
+ @text = Munger::munge(:mode => :replace_or_append,
92
+ :tag => "# ReplaceOrAppendTest",
93
+ :pattern => "line number two",
94
+ :input => @text,
95
+ :content => "This is some stuff to replace with",
96
+ :verbose => @verbose)
97
+ my_assert_equal \
98
+ """Existing line number one
99
+ # ReplaceOrAppendTest (munge start)
100
+ This is some stuff to replace with
101
+ # ReplaceOrAppendTest (munge end)
102
+ Existing line number three
103
+ """, @text
104
+ end
105
+
106
+ def test_replace_or_append_appending
107
+ @text = Munger::munge(:mode => :replace_or_append,
108
+ :tag => "# ReplaceOrAppendTest",
109
+ :pattern => "does not exist",
110
+ :input => @text,
111
+ :content => "This is some stuff to replace with",
112
+ :verbose => @verbose)
113
+ my_assert_equal \
114
+ """Existing line number one
115
+ Existing line number two
116
+ Existing line number three
117
+ # ReplaceOrAppendTest (munge start)
118
+ This is some stuff to replace with
119
+ # ReplaceOrAppendTest (munge end)
120
+ """, @text
121
+ end
122
+
123
+ def test_append
124
+ @text = Munger::munge(:mode => :append, :tag => "# AppendTest",
125
+ :input => @text,
126
+ :content => "This is some stuff to append",
127
+ :verbose => @verbose)
128
+ my_assert_equal \
129
+ """Existing line number one
130
+ Existing line number two
131
+ Existing line number three
132
+ # AppendTest (munge start)
133
+ This is some stuff to append
134
+ # AppendTest (munge end)
135
+ """, @text
136
+
137
+ @text = Munger::munge(:mode => :append, :tag => "# AppendTest",
138
+ :input => @text,
139
+ :content => "New stuff to append",
140
+ :verbose => @verbose)
141
+ my_assert_equal \
142
+ """Existing line number one
143
+ Existing line number two
144
+ Existing line number three
145
+ # AppendTest (munge start)
146
+ New stuff to append
147
+ # AppendTest (munge end)
148
+ """, @text
149
+ end
150
+ end
metadata ADDED
@@ -0,0 +1,99 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: munger
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Bryan Stearns
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-08-13 00:00:00 -07:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: ruby-debug
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: :development
34
+ version_requirements: *id001
35
+ description: |
36
+
37
+ Programmatically modify files: insert something before, after, or replacing
38
+ a line that matches a pattern, or just at the end.
39
+
40
+ email:
41
+ - bryanstearns@gmail.com
42
+ executables:
43
+ - munge
44
+ extensions: []
45
+
46
+ extra_rdoc_files: []
47
+
48
+ files:
49
+ - .gitignore
50
+ - Gemfile
51
+ - Gemfile.lock
52
+ - LICENSE.txt
53
+ - README.rdoc
54
+ - Rakefile
55
+ - bin/munge
56
+ - lib/munger.rb
57
+ - lib/munger/cli.rb
58
+ - lib/munger/munge.rb
59
+ - lib/munger/version.rb
60
+ - munger.gemspec
61
+ - test/helper.rb
62
+ - test/mungee
63
+ - test/test_munger.rb
64
+ has_rdoc: true
65
+ homepage: http://github.com/bryanstearns/munger
66
+ licenses: []
67
+
68
+ post_install_message:
69
+ rdoc_options: []
70
+
71
+ require_paths:
72
+ - lib
73
+ required_ruby_version: !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ hash: 3
79
+ segments:
80
+ - 0
81
+ version: "0"
82
+ required_rubygems_version: !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ hash: 3
88
+ segments:
89
+ - 0
90
+ version: "0"
91
+ requirements: []
92
+
93
+ rubyforge_project: munger
94
+ rubygems_version: 1.4.2
95
+ signing_key:
96
+ specification_version: 3
97
+ summary: File-content munging library (& command-line utility)
98
+ test_files: []
99
+