code-tools 5.0.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/bin/code-tools +4 -0
- data/bin/ender +153 -0
- data/bin/spacer +154 -0
- data/bin/vamper +180 -0
- data/lib/core_ext.rb +54 -0
- data/lib/spacer/csharp.rb +142 -0
- data/lib/spacer/text.rb +85 -0
- data/lib/spacer.rb +2 -0
- data/lib/vamper/default.version.config +105 -0
- data/lib/vamper/version_config_file.rb +42 -0
- data/lib/vamper/version_file.rb +97 -0
- data/lib/vamper.rb +3 -0
- metadata +102 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 5bccd6fecbea6c93c32b92522d03fc000ebe403b
|
|
4
|
+
data.tar.gz: 927adb322732ca9f2f37cff0372d0f5c215810be
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 596b5fec512b56871f04ed48d2633fd567ba80efa53c7b2bb5732b92643d707e8b8dcf76651dcea097b3323a8b212f0f6957ace5fef32ea9a543c780b8b83bd1
|
|
7
|
+
data.tar.gz: e9335f94a397cc1333d31aa0bd3df41fb3aa282840f1e50c39f07bfd67091d600d25572c0db1e9e59a7a8f72b312b0d5c14c4b5fd44a904aba874aa1e053a80b
|
data/bin/code-tools
ADDED
data/bin/ender
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require 'rubygems'
|
|
4
|
+
require 'bundler/setup'
|
|
5
|
+
require 'methadone'
|
|
6
|
+
|
|
7
|
+
class Tool
|
|
8
|
+
include Methadone::Main
|
|
9
|
+
include Methadone::CLILogging
|
|
10
|
+
|
|
11
|
+
main do |input_file|
|
|
12
|
+
unless File.exist?(input_file)
|
|
13
|
+
error "File #{input_file} does not exist"
|
|
14
|
+
next 1
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
output_file = options[:output_file]
|
|
18
|
+
|
|
19
|
+
if output_file.nil?
|
|
20
|
+
output_file = input_file
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Read the entire file and determine all the different line endings
|
|
24
|
+
file_contents = IO.read(input_file)
|
|
25
|
+
num_cr = 0
|
|
26
|
+
num_lf = 0
|
|
27
|
+
num_crlf = 0
|
|
28
|
+
num_lines = 1
|
|
29
|
+
|
|
30
|
+
i = 0
|
|
31
|
+
while i < file_contents.length do
|
|
32
|
+
c = file_contents[i]
|
|
33
|
+
|
|
34
|
+
if c == "\r"
|
|
35
|
+
if i < file_contents.length - 1 and file_contents[i + 1] == "\n"
|
|
36
|
+
num_crlf += 1
|
|
37
|
+
i += 1
|
|
38
|
+
else
|
|
39
|
+
num_cr += 1
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
num_lines += 1
|
|
43
|
+
elsif c == "\n"
|
|
44
|
+
num_lf += 1
|
|
45
|
+
num_lines += 1
|
|
46
|
+
end
|
|
47
|
+
i += 1
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
num_endings = (num_cr > 0 ? 1 : 0) + (num_lf > 0 ? 1 : 0) + (num_crlf > 0 ? 1 : 0)
|
|
51
|
+
le = num_endings > 1 ? :mixed : num_cr > 0 ? :cr : num_lf > 0 ? :lf : :crlf
|
|
52
|
+
msg = "\"#{input_file}\", #{le.to_s}, #{num_lines} lines"
|
|
53
|
+
|
|
54
|
+
if options[:mode].nil?
|
|
55
|
+
info msg
|
|
56
|
+
next 1
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
if options[:mode] == :auto
|
|
60
|
+
# Find the most common line ending and make that the automatic line ending
|
|
61
|
+
auto_line_ending = :lf
|
|
62
|
+
n = num_lf
|
|
63
|
+
|
|
64
|
+
if num_crlf > n
|
|
65
|
+
auto_line_ending = :crlf
|
|
66
|
+
n = num_crlf
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
if num_cr > n
|
|
70
|
+
auto_line_ending = :cr
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
options[:mode] = auto_line_ending
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
new_num_lines = 1
|
|
77
|
+
|
|
78
|
+
if (options[:mode] == :cr and num_cr + 1 == num_lines) or
|
|
79
|
+
(options[:mode] == :lf and num_lf + 1 == num_lines) or
|
|
80
|
+
(options[:mode] == :crlf and num_crlf + 1 == num_lines)
|
|
81
|
+
# We're not changing the line endings; nothing to do
|
|
82
|
+
new_num_lines = num_lines
|
|
83
|
+
else
|
|
84
|
+
newline_chars =
|
|
85
|
+
options[:mode] == :cr ? "\r" :
|
|
86
|
+
options[:mode] == :lf ? "\n" :
|
|
87
|
+
"\r\n"
|
|
88
|
+
|
|
89
|
+
file = nil
|
|
90
|
+
|
|
91
|
+
begin
|
|
92
|
+
file = File.new(output_file, 'w')
|
|
93
|
+
|
|
94
|
+
i = 0
|
|
95
|
+
while i < file_contents.length
|
|
96
|
+
c = file_contents[i]
|
|
97
|
+
|
|
98
|
+
if c == "\r"
|
|
99
|
+
if i < file_contents.length - 1 && file_contents[i + 1] == "\n"
|
|
100
|
+
i += 1
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
new_num_lines += 1
|
|
104
|
+
file.write(newline_chars)
|
|
105
|
+
elsif c == "\n"
|
|
106
|
+
new_num_lines += 1
|
|
107
|
+
file.write(newline_chars)
|
|
108
|
+
else
|
|
109
|
+
file.write(c)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
i += 1
|
|
113
|
+
end
|
|
114
|
+
rescue Exception => e
|
|
115
|
+
error "unable to write #{output_file}. #{e.to_s}"
|
|
116
|
+
next 1
|
|
117
|
+
ensure
|
|
118
|
+
file.close() unless !file
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
msg += " -> \"#{output_file}\", #{options[:mode].to_s}, #{new_num_lines} lines"
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
info msg
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
change_logger Methadone::CLILogger.new
|
|
128
|
+
|
|
129
|
+
description 'Ender - the line ending fixer'
|
|
130
|
+
version '5.0.0'
|
|
131
|
+
|
|
132
|
+
on("-o", "--output-file FILE", "The output file. Default is the same as the input file.")
|
|
133
|
+
on("-m", "--mode MODE",
|
|
134
|
+
"The convert mode, either auto, cr, lf, crlf. auto will use the most commonly occurring ending. "\
|
|
135
|
+
"Updates will only be done when this argument is given.") do |mode|
|
|
136
|
+
options[:mode] = case mode
|
|
137
|
+
when 'auto', 'a'
|
|
138
|
+
:auto
|
|
139
|
+
when 'lf'
|
|
140
|
+
:lf
|
|
141
|
+
when 'cr'
|
|
142
|
+
:cr
|
|
143
|
+
when 'crlf'
|
|
144
|
+
:crlf
|
|
145
|
+
else
|
|
146
|
+
exit_now! "Unknown mode #{mode}"
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
arg :input_file, "Input file to check or convert"
|
|
151
|
+
|
|
152
|
+
go!
|
|
153
|
+
end
|
data/bin/spacer
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require 'rubygems'
|
|
4
|
+
require 'bundler/setup'
|
|
5
|
+
require 'methadone'
|
|
6
|
+
require 'spacer'
|
|
7
|
+
|
|
8
|
+
class Tool
|
|
9
|
+
include Methadone::Main
|
|
10
|
+
include Methadone::CLILogging
|
|
11
|
+
|
|
12
|
+
# When reporting the tool indicates beginning-of-line \(BOL\) tabs and spaces.
|
|
13
|
+
# When replacing, all tabs not at the beginning of a line are replaced with spaces.
|
|
14
|
+
# Spaces and tabs inside multi-line C# strings (@"...") and inside Ruby \%Q\(...\) strings
|
|
15
|
+
# are ignored.
|
|
16
|
+
# Note that conversion to tabs may still leave the file as mixed as some lines may have
|
|
17
|
+
# spaces that are not a whole number multiple of the tabstop size. In that case use the
|
|
18
|
+
# -round option to remove smooth out the spurious spaces.
|
|
19
|
+
|
|
20
|
+
def self.get_whitespace_type(bol)
|
|
21
|
+
(bol.tabs > 0) ? (bol.spaces > 0 ? :mixed : :tabs) : :spaces
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def self.read_file_lines(filename)
|
|
25
|
+
# Read the entire file
|
|
26
|
+
file_contents = File.read(filename)
|
|
27
|
+
|
|
28
|
+
# Convert to a list of lines, preserving the end-of-lines
|
|
29
|
+
lines = []
|
|
30
|
+
s = 0
|
|
31
|
+
i = 0
|
|
32
|
+
|
|
33
|
+
while i < file_contents.length do
|
|
34
|
+
c = file_contents[i]
|
|
35
|
+
c1 = i < file_contents.length - 1 ? file_contents[i + 1] : "\0"
|
|
36
|
+
|
|
37
|
+
if c == "\r"
|
|
38
|
+
i += 1
|
|
39
|
+
|
|
40
|
+
if c1 == "\n"
|
|
41
|
+
i += 1
|
|
42
|
+
end
|
|
43
|
+
elsif c == "\n"
|
|
44
|
+
i += 1
|
|
45
|
+
else
|
|
46
|
+
i += 1
|
|
47
|
+
next
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
lines.push(file_contents[s, i - s])
|
|
51
|
+
s = i
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
if s != i
|
|
55
|
+
lines.push(file_contents[s, i - s])
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
lines
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
main do |input_file|
|
|
62
|
+
unless File.exist?(input_file)
|
|
63
|
+
error "File #{input_file} does not exist"
|
|
64
|
+
next 1
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
output_file = options[:output_file]
|
|
68
|
+
|
|
69
|
+
if output_file.nil?
|
|
70
|
+
output_file = input_file
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
if File.extname(input_file) == '.cs'
|
|
74
|
+
file_type = :csharp
|
|
75
|
+
else
|
|
76
|
+
file_type = :text
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
lines = read_file_lines(input_file)
|
|
80
|
+
|
|
81
|
+
if file_type == :text
|
|
82
|
+
before = Spacer::Text.count_bol_spaces_and_tabs(lines)
|
|
83
|
+
else
|
|
84
|
+
before = Spacer::CSharp.count_bol_spaces_and_tabs(lines)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
if !options[:mode].nil?
|
|
88
|
+
if file_type == :text
|
|
89
|
+
Spacer::Text.untabify(lines, options[:tabsize])
|
|
90
|
+
else
|
|
91
|
+
Spacer::CSharp.untabify(lines, options[:tabsize])
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
if options[:mode] == :tabs
|
|
95
|
+
if file_type == :text
|
|
96
|
+
Spacer::Text.tabify(lines, options[:tabsize], options[:round])
|
|
97
|
+
else
|
|
98
|
+
Spacer::CSharp.tabify(lines, options[:tabsize], options[:round])
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
msg = "\"#{input_file}\", #{file_type.to_s}, #{get_whitespace_type(before).to_s}"
|
|
104
|
+
|
|
105
|
+
if !options[:mode].nil?
|
|
106
|
+
if file_type == :text
|
|
107
|
+
after = Spacer::Text.count_bol_spaces_and_tabs(lines)
|
|
108
|
+
else
|
|
109
|
+
after = Spacer::CSharp.count_bol_spaces_and_tabs(lines)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
file = nil
|
|
113
|
+
|
|
114
|
+
begin
|
|
115
|
+
file = File.new(output_file, 'w')
|
|
116
|
+
|
|
117
|
+
for line in lines do
|
|
118
|
+
file.write(line)
|
|
119
|
+
end
|
|
120
|
+
ensure
|
|
121
|
+
file.close() unless file == nil
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
msg += " -> \"#{output_file}\", #{get_whitespace_type(after).to_s}"
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
info msg
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
description 'Spacer - source file space/tab fixer tool'
|
|
131
|
+
version '5.0.0'
|
|
132
|
+
|
|
133
|
+
options[:tabsize] = 4
|
|
134
|
+
options[:round] = false
|
|
135
|
+
|
|
136
|
+
on("-o", "--output-file FILE", "The output file. Default is the same as the input file.")
|
|
137
|
+
on("-m", "--mode MODE","The convert mode (tabs or spaces) Default is to just display the files current state."\
|
|
138
|
+
"Updates will only be done when this argument is given.") do |mode|
|
|
139
|
+
options[:mode] = case mode
|
|
140
|
+
when 'tabs', 't'
|
|
141
|
+
:tabs
|
|
142
|
+
when 'spaces', 's'
|
|
143
|
+
:spaces
|
|
144
|
+
else
|
|
145
|
+
exit_now! "Unknown mode #{mode}"
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
on("-t", "--tabsize TABSIZE", "Tab size in spaces to assume. Default is #{options[:tabsize]} spaces.")
|
|
149
|
+
on("-r", "--round", "When tabifying, round BOL spaces down to an exact number of tabs.")
|
|
150
|
+
|
|
151
|
+
arg :input_file, "Input file to check or convert"
|
|
152
|
+
|
|
153
|
+
go!
|
|
154
|
+
end
|
data/bin/vamper
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require 'rubygems'
|
|
4
|
+
require 'bundler/setup'
|
|
5
|
+
require 'methadone'
|
|
6
|
+
require 'vamper'
|
|
7
|
+
require 'tzinfo'
|
|
8
|
+
|
|
9
|
+
class Tool
|
|
10
|
+
include Methadone::Main
|
|
11
|
+
include Methadone::CLILogging
|
|
12
|
+
|
|
13
|
+
def self.find_version_file()
|
|
14
|
+
dir = Dir.pwd
|
|
15
|
+
|
|
16
|
+
while dir.length != 0
|
|
17
|
+
files = Dir.glob('*.version')
|
|
18
|
+
if files.length > 0
|
|
19
|
+
file = files[0]
|
|
20
|
+
break
|
|
21
|
+
else
|
|
22
|
+
if dir == '/'
|
|
23
|
+
dir = ''
|
|
24
|
+
else
|
|
25
|
+
dir = File.expand_path('..', dir)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
if file.nil?
|
|
31
|
+
exit_now! 'Unable to find a .version file in this or parent directories.'
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
file
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def self.get_full_date(now)
|
|
38
|
+
now.year * 10000 + now.month * 100 + now.mday
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def get_jdate(now, start_year)
|
|
42
|
+
(((now.year - start_year + 1) * 10000) + (now.month * 100) + now.mday).to_s
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
main do |input_file|
|
|
46
|
+
if input_file.nil? or !File.exist?(input_file)
|
|
47
|
+
input_file = find_version_file
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
input_file = File.expand_path(input_file)
|
|
51
|
+
|
|
52
|
+
project_name = File.basename(input_file, '.version')
|
|
53
|
+
version_config_file_name = "#{File.dirname(input_file)}/#{project_name}.version.config"
|
|
54
|
+
|
|
55
|
+
info "Version file is '#{input_file}'"
|
|
56
|
+
info "Version config is '#{version_config_file_name}'"
|
|
57
|
+
info "Project name is '#{project_name}'"
|
|
58
|
+
|
|
59
|
+
if File.exists?(input_file)
|
|
60
|
+
version_data = Vamper::VersionFile.new(File.open(input_file))
|
|
61
|
+
else
|
|
62
|
+
version_data = Vamper::VersionFile.new
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
now = TZInfo::Timezone.get(version_data.time_zone).now
|
|
66
|
+
|
|
67
|
+
case version_data.build_value_type
|
|
68
|
+
when :JDate
|
|
69
|
+
build = get_jdate(now, version_data.start_year)
|
|
70
|
+
|
|
71
|
+
if version_data.build != build
|
|
72
|
+
version_data.revision = 0
|
|
73
|
+
version_data.build = build
|
|
74
|
+
else
|
|
75
|
+
version_data.revision += 1
|
|
76
|
+
end
|
|
77
|
+
when :Incremental
|
|
78
|
+
version_data.build += 1
|
|
79
|
+
version_data.revision = 0
|
|
80
|
+
else # :FullDate
|
|
81
|
+
build = get_full_date(now)
|
|
82
|
+
|
|
83
|
+
if version_data.build != build
|
|
84
|
+
version_data.revision = 0
|
|
85
|
+
version_data.build = build
|
|
86
|
+
else
|
|
87
|
+
version_data.revision += 1
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
tags = version_data.tags
|
|
92
|
+
|
|
93
|
+
case version_data.build_value_type
|
|
94
|
+
when :FullDate
|
|
95
|
+
build_str = build.to_s
|
|
96
|
+
tags[:DashBuild] = build_str[0..3] + '-' + build_str[4..5] + '-' + build_str[6..7]
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
info 'Version tags are:'
|
|
100
|
+
tags.each { |key, value|
|
|
101
|
+
info " #{key}=#{value}"
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if options[:update]
|
|
105
|
+
info 'Updating version information:'
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
unless File.exists?(version_config_file_name)
|
|
109
|
+
FileUtils.cp(Vamper::VersionConfigFile.get_default_file, version_config_file_name)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
version_config_file = Vamper::VersionConfigFile.new(File.open(version_config_file_name), tags)
|
|
113
|
+
file_list = version_data.files.map { |file_name| file_name.replace_tags!(tags) }
|
|
114
|
+
|
|
115
|
+
file_list.each do |file_name|
|
|
116
|
+
path = File.expand_path(File.join(File.dirname(input_file), file_name))
|
|
117
|
+
path_file_name = File.basename(path)
|
|
118
|
+
match = false
|
|
119
|
+
|
|
120
|
+
for file_type in version_config_file.file_types do
|
|
121
|
+
match = file_type.file_specs.any? { |file_spec| file_spec.match(path_file_name) }
|
|
122
|
+
unless match
|
|
123
|
+
next
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
if file_type.write
|
|
127
|
+
dir = File.dirname(path)
|
|
128
|
+
unless Dir.exists?(dir)
|
|
129
|
+
error "Directory '#{dir}' does not exist to write file ''#{path_file_name}''"
|
|
130
|
+
exit(1)
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
if options[:update]
|
|
134
|
+
IO.write(path, file_type.write)
|
|
135
|
+
end
|
|
136
|
+
else # !file_type.write
|
|
137
|
+
if File.exists?(path)
|
|
138
|
+
if options[:update]
|
|
139
|
+
file_type.updates.each do |update|
|
|
140
|
+
content = IO.read(path)
|
|
141
|
+
# At this point the only ${...} variables left in the replace strings are Before and After
|
|
142
|
+
# This line converts the ${...} into \k<...> to put captured groups from search back
|
|
143
|
+
# into the replace string.
|
|
144
|
+
content.gsub!(%r(#{update.search})m, update.replace.gsub(/\${(\w+)}/,'\\\\k<\\1>'))
|
|
145
|
+
IO.write(path, content)
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
else
|
|
149
|
+
error "file #{path} does not exist to update"
|
|
150
|
+
exit(1)
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
break
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
unless match
|
|
158
|
+
error "file '#{path}' has no matching file type in the .version.config"
|
|
159
|
+
exit(1)
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
info path
|
|
163
|
+
|
|
164
|
+
if options[:update]
|
|
165
|
+
version_data.write_to(File.open(input_file, 'w'))
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
description 'Vamper - file version stamper'
|
|
171
|
+
version '5.0.0'
|
|
172
|
+
|
|
173
|
+
options[:update] = false
|
|
174
|
+
|
|
175
|
+
on("-u", "--update", "Actually do the update.")
|
|
176
|
+
|
|
177
|
+
arg :input_file, "A version file. Default is to search parent directories for *.version", :optional
|
|
178
|
+
|
|
179
|
+
go!
|
|
180
|
+
end
|
data/lib/core_ext.rb
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
class String
|
|
2
|
+
def underscore
|
|
3
|
+
self.gsub(/::/, '/').
|
|
4
|
+
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
|
5
|
+
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
|
6
|
+
tr('-', '_').
|
|
7
|
+
downcase
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def replace_tags(tags)
|
|
11
|
+
str = self
|
|
12
|
+
tags.each { |name, value|
|
|
13
|
+
str = str.gsub(%r(\$\{#{name.to_s}\})m, value)
|
|
14
|
+
}
|
|
15
|
+
str
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def replace_tags!(tags)
|
|
19
|
+
tags.each { |name, value|
|
|
20
|
+
self.gsub!(%r(\$\{#{name.to_s}\})m, value)
|
|
21
|
+
}
|
|
22
|
+
self
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# colorization
|
|
26
|
+
def colorize(color_code)
|
|
27
|
+
"\e[#{color_code}m#{self}\e[0m"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def red
|
|
31
|
+
colorize(31)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def green
|
|
35
|
+
colorize(32)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def yellow
|
|
39
|
+
colorize(33)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def blue
|
|
43
|
+
colorize(34)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def pink
|
|
47
|
+
colorize(35)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def light_blue
|
|
51
|
+
colorize(36)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
end
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
require 'ostruct'
|
|
2
|
+
|
|
3
|
+
module Spacer
|
|
4
|
+
module CSharp
|
|
5
|
+
def self.count_bol_spaces_and_tabs(lines)
|
|
6
|
+
bol = OpenStruct.new
|
|
7
|
+
bol.tabs = 0
|
|
8
|
+
bol.spaces = 0
|
|
9
|
+
in_multi_line_string = false
|
|
10
|
+
|
|
11
|
+
for line in lines do
|
|
12
|
+
in_bol = true
|
|
13
|
+
i = 0
|
|
14
|
+
while i < line.length do
|
|
15
|
+
c = line[i]
|
|
16
|
+
c1 = i < line.length - 1 ? line[i + 1] : "\0"
|
|
17
|
+
|
|
18
|
+
if in_multi_line_string and c == "\"" and c1 != "\""
|
|
19
|
+
in_multi_line_string = false
|
|
20
|
+
elsif c == "@" and c1 == "\""
|
|
21
|
+
in_multi_line_string = true
|
|
22
|
+
i += 1
|
|
23
|
+
elsif in_bol and !in_multi_line_string and c == " "
|
|
24
|
+
bol.spaces += 1
|
|
25
|
+
elsif in_bol and !in_multi_line_string and c == "\t"
|
|
26
|
+
bol.tabs += 1
|
|
27
|
+
else
|
|
28
|
+
in_bol = false
|
|
29
|
+
end
|
|
30
|
+
i += 1
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
bol
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def self.untabify(lines, tabsize)
|
|
38
|
+
# Expand tabs anywhere on a line, but not inside @"..." strings
|
|
39
|
+
in_multi_line_string = false
|
|
40
|
+
|
|
41
|
+
i = 0
|
|
42
|
+
while i < lines.length do
|
|
43
|
+
line = lines[i]
|
|
44
|
+
in_string = false
|
|
45
|
+
new_line = ""
|
|
46
|
+
j = 0
|
|
47
|
+
|
|
48
|
+
while j < line.length do
|
|
49
|
+
c_1 = j > 0 ? line[j - 1] : '\0'
|
|
50
|
+
c = line[j]
|
|
51
|
+
c1 = j < line.length - 1 ? line[j + 1] : '\0'
|
|
52
|
+
|
|
53
|
+
raise "line #{i + 1} has overlapping regular and multiline strings" if (in_string and in_multi_line_string)
|
|
54
|
+
|
|
55
|
+
if !in_multi_line_string and c == "\t"
|
|
56
|
+
# Add spaces to next tabstop
|
|
57
|
+
num_spaces = tabsize - (new_line.length % tabsize)
|
|
58
|
+
|
|
59
|
+
new_line += " " * num_spaces
|
|
60
|
+
elsif !in_multi_line_string and !in_string and c == "\""
|
|
61
|
+
in_string = true
|
|
62
|
+
new_line += c
|
|
63
|
+
elsif !in_multi_line_string and !in_string and c == "@" and c1 == "\""
|
|
64
|
+
in_multi_line_string = true
|
|
65
|
+
new_line += c
|
|
66
|
+
j += 1
|
|
67
|
+
new_line += c1
|
|
68
|
+
elsif in_string and c == "\"" and c_1 != "\\"
|
|
69
|
+
in_string = false
|
|
70
|
+
new_line += c
|
|
71
|
+
elsif in_multi_line_string and c == "\"" and c1 != "\""
|
|
72
|
+
in_multi_line_string = false
|
|
73
|
+
new_line += c
|
|
74
|
+
else
|
|
75
|
+
new_line += c
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
lines[i] = new_line
|
|
79
|
+
j += 1
|
|
80
|
+
end
|
|
81
|
+
i += 1
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def self.tabify(lines, tabsize, round_down_spaces)
|
|
86
|
+
# Insert tabs for spaces, but only at the beginning of lines and not inside @"..." or "..." strings
|
|
87
|
+
in_multi_line_string = false
|
|
88
|
+
i = 0
|
|
89
|
+
|
|
90
|
+
while i < lines.length do
|
|
91
|
+
line = lines[i]
|
|
92
|
+
in_string = false
|
|
93
|
+
bol = true
|
|
94
|
+
num_bol_spaces = 0
|
|
95
|
+
new_line = ""
|
|
96
|
+
j = 0
|
|
97
|
+
|
|
98
|
+
while j < line.length do
|
|
99
|
+
c_1 = j > 0 ? line[j - 1] : "\0"
|
|
100
|
+
c = line[j]
|
|
101
|
+
c1 = j < line.length - 1 ? line[j + 1] : "\0"
|
|
102
|
+
|
|
103
|
+
if !in_string and !in_multi_line_string and bol and c == " "
|
|
104
|
+
# Just count the spaces
|
|
105
|
+
num_bol_spaces += 1
|
|
106
|
+
elsif !in_string and !in_multi_line_string and bol and c != " "
|
|
107
|
+
bol = false
|
|
108
|
+
|
|
109
|
+
new_line += "\t" * (num_bol_spaces / tabsize)
|
|
110
|
+
|
|
111
|
+
if !round_down_spaces
|
|
112
|
+
new_line += " " * (num_bol_spaces % tabsize)
|
|
113
|
+
end
|
|
114
|
+
# Process this character again as not BOL
|
|
115
|
+
j -= 1
|
|
116
|
+
elsif !in_multi_line_string and !in_string and c == '"'
|
|
117
|
+
in_string = true
|
|
118
|
+
new_line += c
|
|
119
|
+
elsif !in_multi_line_string and !in_string and c == "@" and c1 == "\""
|
|
120
|
+
in_multi_line_string = true
|
|
121
|
+
new_line += c
|
|
122
|
+
j += 1
|
|
123
|
+
new_line += c1
|
|
124
|
+
elsif in_string and c == "\"" and c_1 != "\\"
|
|
125
|
+
in_string = false
|
|
126
|
+
new_line += c
|
|
127
|
+
elsif in_multi_line_string and c == "\"" and c1 != "\""
|
|
128
|
+
in_multi_line_string = false
|
|
129
|
+
new_line += c
|
|
130
|
+
else
|
|
131
|
+
new_line += c
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
lines[i] = new_line
|
|
135
|
+
j += 1
|
|
136
|
+
end
|
|
137
|
+
i += 1
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
end
|
|
142
|
+
end
|
data/lib/spacer/text.rb
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
module Spacer
|
|
2
|
+
module Text
|
|
3
|
+
def self.count_bol_spaces_and_tabs(lines)
|
|
4
|
+
bol = OpenStruct.new
|
|
5
|
+
bol.spaces = 0
|
|
6
|
+
bol.tabs = 0
|
|
7
|
+
|
|
8
|
+
for line in lines do
|
|
9
|
+
for i in 0...line.length do
|
|
10
|
+
c = line[i]
|
|
11
|
+
|
|
12
|
+
if c == " "
|
|
13
|
+
bol.spaces += 1
|
|
14
|
+
elsif c == "\t"
|
|
15
|
+
bol.tabs += 1
|
|
16
|
+
else
|
|
17
|
+
break
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
bol
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def self.untabify(lines, tabsize)
|
|
26
|
+
i = 0
|
|
27
|
+
while i < lines.length do
|
|
28
|
+
line = lines[i]
|
|
29
|
+
j = 0
|
|
30
|
+
new_line = ""
|
|
31
|
+
|
|
32
|
+
while j < line.length do
|
|
33
|
+
c = line[j]
|
|
34
|
+
|
|
35
|
+
if c == "\t"
|
|
36
|
+
num_spaces = tabsize - (new_line.length % tabsize)
|
|
37
|
+
new_line += " " * num_spaces
|
|
38
|
+
else
|
|
39
|
+
new_line += c
|
|
40
|
+
end
|
|
41
|
+
j += 1
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
lines[i] = new_line
|
|
45
|
+
i += 1
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def self.tabify(lines, tabsize, round_down_spaces)
|
|
50
|
+
i = 0
|
|
51
|
+
while i < lines.length do
|
|
52
|
+
line = lines[i]
|
|
53
|
+
j = 0
|
|
54
|
+
bol = true
|
|
55
|
+
num_bol_spaces = 0
|
|
56
|
+
new_line = ""
|
|
57
|
+
|
|
58
|
+
while j < line.length do
|
|
59
|
+
c = line[j]
|
|
60
|
+
|
|
61
|
+
if bol and c == " "
|
|
62
|
+
num_bol_spaces += 1
|
|
63
|
+
elsif bol and c != " "
|
|
64
|
+
bol = false
|
|
65
|
+
new_line += "\t" * (num_bol_spaces / tabsize)
|
|
66
|
+
|
|
67
|
+
if !round_down_spaces
|
|
68
|
+
new_line += " " * (num_bol_spaces % tabsize)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
new_line += c
|
|
72
|
+
else
|
|
73
|
+
new_line += c
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
j += 1
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
lines[i] = new_line
|
|
80
|
+
i += 1
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
end
|
|
85
|
+
end
|
data/lib/spacer.rb
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8" ?>
|
|
2
|
+
<VersionConfig>
|
|
3
|
+
<FileType>
|
|
4
|
+
<Name>Ruby Files</Name>
|
|
5
|
+
<FileSpec>*.rb</FileSpec>
|
|
6
|
+
<Update>
|
|
7
|
+
<Search>(?'Before'\$VERSION=\')([0-9]+\.[0-9]+\.[0-9]+)-[0-9]+\.[0-9]+(?'After'\')</Search>
|
|
8
|
+
<Replace>${Before}${Major}.${Minor}.${Patch}-${Build}.${Revision}${After}</Replace>
|
|
9
|
+
</Update>
|
|
10
|
+
</FileType>
|
|
11
|
+
<FileType>
|
|
12
|
+
<Name>Version-in-a-text-file</Name>
|
|
13
|
+
<FileSpec>*.version.txt</FileSpec>
|
|
14
|
+
<Write>Release ${Major}.${Minor}.${Build}.${Revision}</Write>
|
|
15
|
+
</FileType>
|
|
16
|
+
<FileType>
|
|
17
|
+
<Name>Windows Manifest File</Name>
|
|
18
|
+
<FileSpec>WMManifest.xml</FileSpec>
|
|
19
|
+
<Update>
|
|
20
|
+
<Search>(?'Before'Version=")([0-9]+\.[0-9]+)(?'After'\.[0-9]+\.[0-9]+")</Search>
|
|
21
|
+
<Replace>${Before}${Major}.${Minor}${After}</Replace>
|
|
22
|
+
</Update>
|
|
23
|
+
</FileType>
|
|
24
|
+
<FileType>
|
|
25
|
+
<Name>C# Source</Name>
|
|
26
|
+
<FileSpec>*.cs</FileSpec>
|
|
27
|
+
<Update>
|
|
28
|
+
<Search>(?'Before'AssemblyVersion\(")([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)(?'After'"\))</Search>
|
|
29
|
+
<Replace>${Before}${Major}.${Minor}.0.0${After}</Replace>
|
|
30
|
+
</Update>
|
|
31
|
+
<Update>
|
|
32
|
+
<Search>(?'Before'AssemblyFileVersion\(")([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)(?'After'"\))</Search>
|
|
33
|
+
<Replace>${Before}${Major}.${Minor}.${Build}.${Revision}${After}</Replace>
|
|
34
|
+
</Update>
|
|
35
|
+
<Update>
|
|
36
|
+
<Search>(?'Before'AssemblyProduct\(")([^"]*)(?'After'"\))</Search>
|
|
37
|
+
<Replace>${Before}${Product}${After}</Replace>
|
|
38
|
+
</Update>
|
|
39
|
+
<Update>
|
|
40
|
+
<Search>(?'Before'AssemblyCopyright\(")([^"]*)(?'After'"\))</Search>
|
|
41
|
+
<Replace>${Before}${Copyright}${After}</Replace>
|
|
42
|
+
</Update>
|
|
43
|
+
<Update>
|
|
44
|
+
<Search>(?'Before'AssemblyCompany\(")([^"]*)(?'After'"\))</Search>
|
|
45
|
+
<Replace>${Before}${Company}${After}</Replace>
|
|
46
|
+
</Update>
|
|
47
|
+
</FileType>
|
|
48
|
+
<FileType>
|
|
49
|
+
<Name>Windows RC File</Name>
|
|
50
|
+
<FileSpec>*.rc</FileSpec>
|
|
51
|
+
<Update>
|
|
52
|
+
<Search>(?'Before'FILEVERSION )([0-9]+,[0-9]+,[0-9]+,[0-9]+)</Search>
|
|
53
|
+
<Replace>${Before}${Major},${Minor},${Build},${Revision}</Replace>
|
|
54
|
+
</Update>
|
|
55
|
+
<Update>
|
|
56
|
+
<Search>(?'Before'PRODUCTVERSION )([0-9]+,[0-9]+,[0-9]+,[0-9]+)</Search>
|
|
57
|
+
<Replace>${Before}${Major},${Minor},${Build},${Revision}</Replace>
|
|
58
|
+
</Update>
|
|
59
|
+
<Update>
|
|
60
|
+
<Search>(?'Before'"FileVersion",[ \t]*")([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)(?'After'")</Search>
|
|
61
|
+
<Replace>${Before}${Major}.${Minor}.${Build}.${Revision}${After}</Replace>
|
|
62
|
+
</Update>
|
|
63
|
+
<Update>
|
|
64
|
+
<Search>(?'Before'"ProductVersion",[ \t]*")([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)(?'After'")</Search>
|
|
65
|
+
<Replace>${Before}${Major}.${Minor}.${Build}.${Revision}${After}</Replace>
|
|
66
|
+
</Update>
|
|
67
|
+
</FileType>
|
|
68
|
+
<FileType>
|
|
69
|
+
<Name>WiX Files</Name>
|
|
70
|
+
<FileSpec>*.wxi</FileSpec>
|
|
71
|
+
<FileSpec>*.wxs</FileSpec>
|
|
72
|
+
<Update>
|
|
73
|
+
<Search>(?'Before'ProductVersion = ")([0-9]+\.[0-9]+)(?'After'")</Search>
|
|
74
|
+
<Replace>${Before}${Major}.${Minor}${After}</Replace>
|
|
75
|
+
</Update>
|
|
76
|
+
<Update>
|
|
77
|
+
<Search>(?'Before'ProductBuild = ")([0-9]+\.([0-9]|[1-9][0-9]))(?'After'")</Search>
|
|
78
|
+
<Replace>${Before}${Build}.${Revision}${After}</Replace>
|
|
79
|
+
</Update>
|
|
80
|
+
</FileType>
|
|
81
|
+
<FileType>
|
|
82
|
+
<Name>.NET Config Files</Name>
|
|
83
|
+
<FileSpec>*.config</FileSpec>
|
|
84
|
+
<Update>
|
|
85
|
+
<Search>(?'Before', +Version=)\d+\.\d+(?'After'\.0\.0 *,)</Search>
|
|
86
|
+
<Replace>${Before}${Major}.${Minor}${After}</Replace>
|
|
87
|
+
</Update>
|
|
88
|
+
</FileType>
|
|
89
|
+
<FileType>
|
|
90
|
+
<Name>Visual Studio Project Files</Name>
|
|
91
|
+
<FileSpec>*.csproj</FileSpec>
|
|
92
|
+
<Update>
|
|
93
|
+
<Search>(?'Before'<OutputName>" + projectName + @"_)([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)(?'After'</OutputName>)</Search>
|
|
94
|
+
<Replace>${Before}${Major}.${Minor}.${Build}.${Revision}${After}</Replace>
|
|
95
|
+
</Update>
|
|
96
|
+
</FileType>
|
|
97
|
+
<FileType>
|
|
98
|
+
<Name>VSIX Manifest</Name>
|
|
99
|
+
<FileSpec>*.vsixmanifest</FileSpec>
|
|
100
|
+
<Update>
|
|
101
|
+
<Search>(?'Before'<Version>)([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)(?'After'</Version>)</Search>
|
|
102
|
+
<Replace>${Before}${Major}.${Minor}.${Build}.${Revision}${After}</Replace>
|
|
103
|
+
</Update>
|
|
104
|
+
</FileType>
|
|
105
|
+
</VersionConfig>
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
require 'nokogiri'
|
|
2
|
+
require_relative '../core_ext.rb'
|
|
3
|
+
|
|
4
|
+
module Vamper
|
|
5
|
+
class VersionConfigFile
|
|
6
|
+
|
|
7
|
+
def self.get_default_file
|
|
8
|
+
File.join(File.dirname(__FILE__), 'default.version.config')
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def initialize(io, tags)
|
|
12
|
+
doc = Nokogiri::XML(io)
|
|
13
|
+
|
|
14
|
+
@file_types = []
|
|
15
|
+
doc.xpath('/VersionConfig/FileType').each do |node|
|
|
16
|
+
file_type_struct = Struct.new(:name, :file_specs, :updates, :write)
|
|
17
|
+
search_replace_struct = Struct.new(:search, :replace)
|
|
18
|
+
file_type = file_type_struct.new
|
|
19
|
+
file_type.name = node.name
|
|
20
|
+
file_type.file_specs = node.xpath('FileSpec').map { |sub_node|
|
|
21
|
+
Regexp.new('^' + Regexp::escape(sub_node.text).gsub('\\*', '.*').gsub('\\?', '.') + '$')
|
|
22
|
+
}
|
|
23
|
+
update_node_set = node.xpath('Update')
|
|
24
|
+
if update_node_set
|
|
25
|
+
# Replace ${...} entries in the replace string with equivalent tags if available
|
|
26
|
+
file_type.updates = update_node_set.map { |sub_node|
|
|
27
|
+
s_and_r = search_replace_struct.new(
|
|
28
|
+
%r(#{sub_node.at_xpath('Search').text.gsub(/\(\?'(\w+)'/, '(?<\\1>')}),
|
|
29
|
+
sub_node.at_xpath('Replace').text.replace_tags(tags))
|
|
30
|
+
}
|
|
31
|
+
end
|
|
32
|
+
write_node = node.at_xpath('Write')
|
|
33
|
+
if write_node
|
|
34
|
+
file_type.write = write_node.text.replace_tags(tags)
|
|
35
|
+
end
|
|
36
|
+
@file_types.push(file_type)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
attr_reader :file_types
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
require 'nokogiri'
|
|
2
|
+
require_relative '../core_ext.rb'
|
|
3
|
+
|
|
4
|
+
module Vamper
|
|
5
|
+
class BadVersionFile < StandardError; end
|
|
6
|
+
|
|
7
|
+
class VersionFile
|
|
8
|
+
attr_reader :tags
|
|
9
|
+
|
|
10
|
+
def initialize(io)
|
|
11
|
+
if io
|
|
12
|
+
@doc = Nokogiri::XML(io, &:noblanks)
|
|
13
|
+
|
|
14
|
+
unless @doc.root.name == 'Version'
|
|
15
|
+
raise BadVersionFile, 'Root element must be Version'
|
|
16
|
+
end
|
|
17
|
+
else
|
|
18
|
+
@doc = Nokogiri::XML::Document.new
|
|
19
|
+
@doc.root.add_child(Nokogiri::XML::Element.new('Version', @doc))
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
add_attribute @doc.root, :BuildValueType => :JDate
|
|
23
|
+
add_child_list_element @doc.root, :Files, :Tags
|
|
24
|
+
add_child_element tags_element,
|
|
25
|
+
:Major => 1, :Minor => 0, :Build => 0, :Patch => 0, :Revision => 0, :TimeZone => 'UTC'
|
|
26
|
+
add_child_element tags_element, {:StartYear => TZInfo::Timezone.get(self.time_zone).now.year}
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def add_attribute(parent_node, attr_definitions)
|
|
30
|
+
attr_definitions.each { |attr_symbol, attr_default|
|
|
31
|
+
method_name = attr_symbol.to_s.underscore
|
|
32
|
+
unless parent_node[attr_symbol]
|
|
33
|
+
parent_node[attr_symbol] = attr_default
|
|
34
|
+
end
|
|
35
|
+
define_singleton_method(method_name.to_sym) {
|
|
36
|
+
parent_node[attr_symbol].to_sym
|
|
37
|
+
}
|
|
38
|
+
define_singleton_method((method_name + '=').to_sym) { |value|
|
|
39
|
+
parent_node[attr_symbol] = value.to_s
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def add_child_list_element(parent_element, *element_symbols)
|
|
45
|
+
element_symbols.each { |element_symbol|
|
|
46
|
+
name = element_symbol.to_s
|
|
47
|
+
elem = parent_element.at(name)
|
|
48
|
+
unless elem
|
|
49
|
+
elem = parent_element.add_child(Nokogiri::XML::Element.new(name, @doc))
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
method_name = name.underscore + '_element'
|
|
53
|
+
define_singleton_method(method_name.to_sym) {
|
|
54
|
+
elem
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def add_child_element(parent_element, element_definitions)
|
|
60
|
+
element_definitions.each { |element_symbol, element_default|
|
|
61
|
+
name = element_symbol.to_s
|
|
62
|
+
elem = parent_element.at(name)
|
|
63
|
+
unless elem
|
|
64
|
+
elem = parent_element.add_child(Nokogiri::XML::Element.new(name, @doc))
|
|
65
|
+
elem.content = element_default.to_s
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
method_name = name.underscore
|
|
69
|
+
case element_default
|
|
70
|
+
when Fixnum
|
|
71
|
+
define_singleton_method(method_name.to_sym) {
|
|
72
|
+
Integer(elem.content)
|
|
73
|
+
}
|
|
74
|
+
when String
|
|
75
|
+
define_singleton_method(method_name.to_sym) {
|
|
76
|
+
elem.content.to_s
|
|
77
|
+
}
|
|
78
|
+
end
|
|
79
|
+
define_singleton_method((method_name + '=').to_sym) { |value|
|
|
80
|
+
elem.content = value.to_s
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def write_to(io)
|
|
86
|
+
@doc.write_xml_to(io, :indent_text => ' ', :indent => 2)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def tags
|
|
90
|
+
Hash[tags_element.children.select {|node| node.name != 'text'}.map {|node| [node.name.to_sym, node.content]}]
|
|
91
|
+
end
|
|
92
|
+
def files
|
|
93
|
+
files_element.children.select {|node| node.name != 'text'}.map {|node| node.content}
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
end
|
|
97
|
+
end
|
data/lib/vamper.rb
ADDED
metadata
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: code-tools
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 5.0.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- John Lyon-smith
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2016-01-13 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: tzinfo
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '1.2'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '1.2'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: nokogiri
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '1.6'
|
|
34
|
+
type: :runtime
|
|
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: methadone
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '1.9'
|
|
48
|
+
type: :runtime
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '1.9'
|
|
55
|
+
description: Tools for source code maintenance, including version stamping, line endings
|
|
56
|
+
and tab/space conversion.
|
|
57
|
+
email: john@jamoki.com
|
|
58
|
+
executables:
|
|
59
|
+
- code-tools
|
|
60
|
+
- ender
|
|
61
|
+
- spacer
|
|
62
|
+
- vamper
|
|
63
|
+
extensions: []
|
|
64
|
+
extra_rdoc_files: []
|
|
65
|
+
files:
|
|
66
|
+
- bin/code-tools
|
|
67
|
+
- bin/ender
|
|
68
|
+
- bin/spacer
|
|
69
|
+
- bin/vamper
|
|
70
|
+
- lib/core_ext.rb
|
|
71
|
+
- lib/spacer.rb
|
|
72
|
+
- lib/spacer/csharp.rb
|
|
73
|
+
- lib/spacer/text.rb
|
|
74
|
+
- lib/vamper.rb
|
|
75
|
+
- lib/vamper/default.version.config
|
|
76
|
+
- lib/vamper/version_config_file.rb
|
|
77
|
+
- lib/vamper/version_file.rb
|
|
78
|
+
homepage: http://rubygems.org/gems/code_tools
|
|
79
|
+
licenses:
|
|
80
|
+
- MIT
|
|
81
|
+
metadata: {}
|
|
82
|
+
post_install_message:
|
|
83
|
+
rdoc_options: []
|
|
84
|
+
require_paths:
|
|
85
|
+
- lib
|
|
86
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
87
|
+
requirements:
|
|
88
|
+
- - "~>"
|
|
89
|
+
- !ruby/object:Gem::Version
|
|
90
|
+
version: '2.0'
|
|
91
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
92
|
+
requirements:
|
|
93
|
+
- - ">="
|
|
94
|
+
- !ruby/object:Gem::Version
|
|
95
|
+
version: '0'
|
|
96
|
+
requirements: []
|
|
97
|
+
rubyforge_project:
|
|
98
|
+
rubygems_version: 2.4.5
|
|
99
|
+
signing_key:
|
|
100
|
+
specification_version: 4
|
|
101
|
+
summary: Source code tools
|
|
102
|
+
test_files: []
|