code_tools 4.1.0 → 4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cbaf6f2122fa3302144ef27d0c5484c82a8bec52
4
- data.tar.gz: 2b3eb698101465ed00e6b367cf55e357a1aede36
3
+ metadata.gz: da904aa42c144ba90f9479facf968c63f6c9502f
4
+ data.tar.gz: 090ca4a1c671a2fc91c8259801af3b6c128c21e6
5
5
  SHA512:
6
- metadata.gz: a24bfc3ab574bfbc0fbc38b0568919cf1cf3fabf340c270810ff4cdd8b90b9d825b55cd2f719891c6b78e3bd8a83c59723a72d7225a49cfa9148d6b93ea71dd4
7
- data.tar.gz: ceadd6e3b9b004033420b90e6e4f0bf4d63764765b3e9a2f74efd39060ed42be21309ce6773ad49346a962baba94bd71fb94ba4eb05256296beb1564e6ec65bc
6
+ metadata.gz: 16ad5be70ccf2e1b792f5f8745cd6c88d39c5520366ba3d4ced52104e59262478c73675b281600b5adf29a09cfe08cfaecc24107828aaa5aaad7dfe09720886b
7
+ data.tar.gz: 40d615576784fd90c4c3580e52e96d91c55913ca650622c3610db08802443b72f0bd988820e64a14a7854b71127d89366528c9e483a2b26c84d5724928578ac8
data/bin/code_tools CHANGED
@@ -1 +1,4 @@
1
- #!/bin/bash
1
+ #!/usr/bin/env ruby
2
+ puts "vamper - Version stamper"
3
+ puts "ender - CR/LF line ending fixer"
4
+ puts "spacer - Space/tab line fixer"
data/bin/ender ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'ender'
4
+ Ender.new.execute
data/bin/spacer ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'spacer'
4
+ Spacer.new.execute
data/lib/ender.rb ADDED
@@ -0,0 +1,167 @@
1
+ require 'ostruct'
2
+ require 'optparse'
3
+ require 'colorize'
4
+
5
+ $VERSION='4.2.0-20151225.0'
6
+
7
+ class Ender
8
+
9
+ def parse(args)
10
+ options = OpenStruct.new
11
+ options.output_filename = ''
12
+ options.input_filename = ''
13
+ options.convert_mode = nil
14
+
15
+ opt_parser = OptionParser.new do |opts|
16
+ opts.banner = %Q(Ender Line Ending Fixer. Version #{$VERSION}
17
+ Copyright (c) John Lyon-Smith, 2015.
18
+ Usage: #{File.basename(__FILE__)} [options]
19
+ )
20
+ opts.separator %Q(Options:
21
+ )
22
+
23
+ opts.on("-o", "--output FILE", String, "The output file. Default is the same as the input file.") do |file|
24
+ options.output_filename = File.expand_path(file)
25
+ end
26
+
27
+ opts.on("-m", "--mode MODE", [:auto, :lf, :cr, :crlf], "The convert mode (auto, cr, lf, crlf)",
28
+ "(auto) will use the most commonly occurring ending.",
29
+ "Updates will only be done when this argument is given.") do |mode|
30
+ options.convert_mode = mode
31
+ end
32
+
33
+ opts.on_tail("-?", "--help", "Show this message") do
34
+ puts opts
35
+ exit
36
+ end
37
+ end
38
+
39
+ opt_parser.parse!(args)
40
+ options.input_filename = ARGV.pop
41
+ raise 'Need to specify a file to process' unless options.input_filename
42
+ options.input_filename = File.expand_path(options.input_filename)
43
+ options
44
+ end
45
+
46
+ def execute
47
+ options = self.parse(ARGV)
48
+
49
+ if !File.exist?(options.input_filename)
50
+ error "File #{options.input_filename} does not exist"
51
+ exit
52
+ end
53
+
54
+ if options.output_filename.length == 0
55
+ options.output_filename = options.input_filename
56
+ end
57
+
58
+ # Read the entire file and determine all the different line endings
59
+ file_contents = IO.read(options.input_filename)
60
+ num_cr = 0
61
+ num_lf = 0
62
+ num_crlf = 0
63
+ num_lines = 1
64
+
65
+ i = 0
66
+ while i < file_contents.length do
67
+ c = file_contents[i]
68
+
69
+ if c == "\r"
70
+ if i < file_contents.length - 1 and file_contents[i + 1] == "\n"
71
+ num_crlf += 1
72
+ i += 1
73
+ else
74
+ num_cr += 1
75
+ end
76
+
77
+ num_lines += 1
78
+ elsif c == "\n"
79
+ num_lf += 1
80
+ num_lines += 1
81
+ end
82
+ i += 1
83
+ end
84
+
85
+ num_endings = (num_cr > 0 ? 1 : 0) + (num_lf > 0 ? 1 : 0) + (num_crlf > 0 ? 1 : 0)
86
+ le = num_endings > 1 ? :mixed : num_cr > 0 ? :cr : num_lf > 0 ? :lf : :crlf
87
+ msg = "\"#{options.input_filename}\", #{le.to_s}, #{num_lines} lines"
88
+
89
+ if options.convert_mode == nil
90
+ puts msg
91
+ exit
92
+ end
93
+
94
+ if options.convert_mode == :auto
95
+ # Find the most common line ending and make that the automatic line ending
96
+ auto_line_ending = :lf
97
+ n = num_lf
98
+
99
+ if num_crlf > n
100
+ auto_line_ending = :crlf
101
+ n = num_crlf
102
+ end
103
+
104
+ if num_cr > n
105
+ auto_line_ending = :cr
106
+ end
107
+
108
+ options.convert_mode = auto_line_ending
109
+ end
110
+
111
+ new_num_lines = 1
112
+
113
+ if (options.convert_mode == :cr and num_cr + 1 == num_lines) or
114
+ (options.convert_mode == :lf and num_lf + 1 == num_lines) or
115
+ (options.convert_mode == :crlf and num_crlf + 1 == num_lines)
116
+ # We're not changing the line endings; nothing to do
117
+ new_num_lines = num_lines
118
+ else
119
+ newline_chars =
120
+ options.convert_mode == :cr ? "\r" :
121
+ options.convert_mode == :lf ? "\n" :
122
+ "\r\n"
123
+
124
+ file = nil
125
+
126
+ begin
127
+ file = File.new(options.output_filename, 'w')
128
+
129
+ i = 0
130
+ while i < file_contents.length
131
+ c = file_contents[i]
132
+
133
+ if c == "\r"
134
+ if i < file_contents.length - 1 && file_contents[i + 1] == "\n"
135
+ i += 1
136
+ end
137
+
138
+ new_num_lines += 1
139
+ file.write(newline_chars)
140
+ elsif c == "\n"
141
+ new_num_lines += 1
142
+ file.write(newline_chars)
143
+ else
144
+ file.write(c)
145
+ end
146
+
147
+ i += 1
148
+ end
149
+ rescue Exception => e
150
+ error "unable to write #{options.output_filename}. #{e.to_s}"
151
+ exit
152
+ ensure
153
+ file.close() unless !file
154
+ end
155
+
156
+ msg += " -> \"#{options.output_filename}\", #{options.convert_mode.to_s}, #{new_num_lines} lines"
157
+ end
158
+
159
+ puts msg
160
+ end
161
+
162
+
163
+ def error(msg)
164
+ STDERR.puts "error: #{msg}".colorize(:red)
165
+ end
166
+
167
+ end
data/lib/spacer.rb ADDED
@@ -0,0 +1,405 @@
1
+ require 'ostruct'
2
+ require 'optparse'
3
+ require 'colorize'
4
+
5
+ $VERSION='4.2.0-20151225.0'
6
+
7
+ class Spacer
8
+
9
+ def parse(args)
10
+ options = OpenStruct.new
11
+ options.output_filename = ''
12
+ options.input_filename = nil
13
+ options.convert_mode = nil
14
+ options.tabsize = 4
15
+ options.round_down_spaces = false
16
+
17
+ opt_parser = OptionParser.new do |opts|
18
+ opts.banner = %Q(Spacer Text File Space/Tab Fixer Tool. Version #{$VERSION}
19
+ Copyright (c) John Lyon-Smith, 2015.
20
+ Usage: #{File.basename(__FILE__)} [options]
21
+ )
22
+ opts.separator %Q(Description:
23
+ When reporting the tool indicates beginning-of-line \(BOL\) tabs and spaces.
24
+ When replacing, all tabs not at the beginning of a line are replaced with spaces.
25
+ Spaces and tabs inside multi-line C# strings (@"...") and inside Ruby \%Q\(...\) strings
26
+ are ignored.
27
+ Note that conversion to tabs may still leave the file as mixed as some lines may have
28
+ spaces that are not a whole number multiple of the tabstop size. In that case use the
29
+ -round option to remove smooth out the spurious spaces.
30
+
31
+ )
32
+ opts.separator %Q(Options:
33
+ )
34
+
35
+ opts.on("-o", "--output FILE", String, "The output file. Default is the same as the input file.") do |file|
36
+ options.output_filename = File.expand_path(file)
37
+ end
38
+
39
+ opts.on("-m", "--mode MODE", [:mixed, :tabs, :spaces], "The convert mode (mixed, tabs or spaces)",
40
+ "Default is to just display the files current state.",
41
+ "Updates will only be done when this argument is given.") do |mode|
42
+ options.convert_mode = mode
43
+ end
44
+
45
+ opts.on("-t", "--tabsize SIZE", Integer, "Tab size. Default is 4 spaces.",
46
+ "Default is to just display the files current state.",
47
+ "Updates will only be done when this argument is given.") do |size|
48
+ options.tabsize = size
49
+ end
50
+
51
+ opts.on("-r", "--round", "When tabifying, round BOL spaces down to an exact number of tabs.") do |round|
52
+ options.round_down_spaces = round
53
+ end
54
+
55
+ opts.on_tail("-?", "--help", "Show this message") do
56
+ puts opts
57
+ exit
58
+ end
59
+ end
60
+
61
+ opt_parser.parse!(args)
62
+ options.input_filename = ARGV.pop
63
+ if options.input_filename == nil
64
+ error 'Need to specify a file to process'
65
+ exit
66
+ end
67
+ options.input_filename = File.expand_path(options.input_filename)
68
+ options
69
+ end
70
+
71
+ def execute
72
+ options = self.parse(ARGV)
73
+
74
+ if !File.exist?(options.input_filename)
75
+ error "File #{options.input_filename} does not exist"
76
+ exit
77
+ end
78
+
79
+ if options.output_filename.length == 0
80
+ options.output_filename = options.input_filename
81
+ end
82
+
83
+ if File.extname(options.input_filename) == '.cs'
84
+ file_type = :csharp
85
+ else
86
+ file_type = :other
87
+ end
88
+
89
+ lines = read_file_lines(options.input_filename)
90
+
91
+ if file_type == :csharp
92
+ before = count_csharp_bol_spaces_and_tabs(lines)
93
+ else
94
+ before = count_bol_spaces_and_tabs(lines)
95
+ end
96
+
97
+ if options.convert_mode != nil
98
+ if file_type == :other
99
+ untabify(lines, options)
100
+ else
101
+ csharp_untabify(lines, options)
102
+ end
103
+
104
+ if options.convert_mode == :tabs
105
+ if file_type == :other
106
+ tabify(lines, options)
107
+ else
108
+ csharp_tabify(lines, options)
109
+ end
110
+ end
111
+ end
112
+
113
+ ws = get_whitespace_type(before)
114
+
115
+ msg = "\"#{options.input_filename}\", #{file_type.to_s}, #{ws.to_s}"
116
+
117
+ if options.convert_mode != nil
118
+ if file_type == :csharp
119
+ after = count_csharp_bol_spaces_and_tabs(lines)
120
+ else
121
+ after = count_bol_spaces_and_tabs(lines)
122
+ end
123
+
124
+ ws = get_whitespace_type(after)
125
+ file = nil
126
+
127
+ begin
128
+ file = File.new(options.output_filename, 'w')
129
+
130
+ for line in lines do
131
+ file.write(line)
132
+ end
133
+ ensure
134
+ file.close() unless file == nil
135
+ end
136
+
137
+ msg += " -> \"#{options.output_filename}\", #{ws.to_s}"
138
+ end
139
+
140
+ puts msg
141
+ end
142
+
143
+ def get_whitespace_type(bol)
144
+ (bol.tabs > 0) ? (bol.spaces > 0 ? :mixed : :tabs) : :spaces
145
+ end
146
+
147
+ def read_file_lines(filename)
148
+ # Read the entire file
149
+ file_contents = File.read(filename)
150
+
151
+ # Convert to a list of lines, preserving the end-of-lines
152
+ lines = []
153
+ s = 0
154
+ i = 0
155
+
156
+ while i < file_contents.length do
157
+ c = file_contents[i]
158
+ c1 = i < file_contents.length - 1 ? file_contents[i + 1] : "\0"
159
+
160
+ if c == "\r"
161
+ i += 1
162
+
163
+ if c1 == "\n"
164
+ i += 1
165
+ end
166
+ elsif c == "\n"
167
+ i += 1
168
+ else
169
+ i += 1
170
+ next
171
+ end
172
+
173
+ lines.push(file_contents[s, i - s])
174
+ s = i
175
+ end
176
+
177
+ if s != i
178
+ lines.push(file_contents[s, i - s])
179
+ end
180
+
181
+ lines
182
+ end
183
+
184
+ def count_csharp_bol_spaces_and_tabs(lines)
185
+ bol = OpenStruct.new
186
+ bol.tabs = 0
187
+ bol.spaces = 0
188
+ in_multi_line_string = false
189
+
190
+ for line in lines do
191
+ in_bol = true
192
+ i = 0
193
+ while i < line.length do
194
+ c = line[i]
195
+ c1 = i < line.length - 1 ? line[i + 1] : "\0"
196
+
197
+ if in_multi_line_string and c == "\"" and c1 != "\""
198
+ in_multi_line_string = false
199
+ elsif c == "@" and c1 == "\""
200
+ in_multi_line_string = true
201
+ i += 1
202
+ elsif in_bol and !in_multi_line_string and c == " "
203
+ bol.spaces += 1
204
+ elsif in_bol and !in_multi_line_string and c == "\t"
205
+ bol.tabs += 1
206
+ else
207
+ in_bol = false
208
+ end
209
+ i += 1
210
+ end
211
+ end
212
+
213
+ bol
214
+ end
215
+
216
+ def count_bol_spaces_and_tabs(lines)
217
+ bol = OpenStruct.new
218
+ bol.spaces = 0
219
+ bol.tabs = 0
220
+
221
+ for line in lines do
222
+ for i in 0...line.length do
223
+ c = line[i]
224
+
225
+ if c == " "
226
+ bol.spaces += 1
227
+ elsif c == "\t"
228
+ bol.tabs += 1
229
+ else
230
+ break
231
+ end
232
+ end
233
+ end
234
+
235
+ bol
236
+ end
237
+
238
+ def untabify(lines, options)
239
+ i = 0
240
+ while i < lines.length do
241
+ line = lines[i]
242
+ j = 0
243
+ new_line = ""
244
+
245
+ while j < line.length do
246
+ c = line[j]
247
+
248
+ if c == "\t"
249
+ num_spaces = options.tabsize - (new_line.length % options.tabsize)
250
+ new_line += " " * num_spaces
251
+ else
252
+ new_line += c
253
+ end
254
+ j += 1
255
+ end
256
+
257
+ lines[i] = new_line
258
+ i += 1
259
+ end
260
+ end
261
+
262
+ def tabify(lines, options)
263
+ i = 0
264
+ while i < lines.length do
265
+ line = lines[i]
266
+ j = 0
267
+ bol = true
268
+ num_bol_spaces = 0
269
+ new_line = ""
270
+
271
+ while j < line.length do
272
+ c = line[j]
273
+
274
+ if bol and c == " "
275
+ num_bol_spaces += 1
276
+ elsif bol and c != " "
277
+ bol = false
278
+ new_line += "\t" * (num_bol_spaces / options.tabsize)
279
+
280
+ if !options.round_down_spaces
281
+ new_line += " " * (num_bol_spaces % options.tabsize)
282
+ end
283
+
284
+ new_line += c
285
+ else
286
+ new_line += c
287
+ end
288
+
289
+ j += 1
290
+ end
291
+
292
+ lines[i] = new_line
293
+ i += 1
294
+ end
295
+ end
296
+
297
+ def csharp_untabify(lines, options)
298
+ # Expand tabs anywhere on a line, but not inside @"..." strings
299
+ in_multi_line_string = false
300
+
301
+ i = 0
302
+ while i < lines.length do
303
+ line = lines[i]
304
+ in_string = false
305
+ new_line = ""
306
+ j = 0
307
+
308
+ while j < line.length do
309
+ c_1 = j > 0 ? line[j - 1] : '\0'
310
+ c = line[j]
311
+ c1 = j < line.length - 1 ? line[j + 1] : '\0'
312
+
313
+ raise "line #{i + 1} has overlapping regular and multiline strings" if (in_string and in_multi_line_string)
314
+
315
+ if !in_multi_line_string and c == "\t"
316
+ # Add spaces to next tabstop
317
+ num_spaces = options.tabsize - (new_line.length % options.tabsize)
318
+
319
+ new_line += " " * num_spaces
320
+ elsif !in_multi_line_string and !in_string and c == "\""
321
+ in_string = true
322
+ new_line += c
323
+ elsif !in_multi_line_string and !in_string and c == "@" and c1 == "\""
324
+ in_multi_line_string = true
325
+ new_line += c
326
+ j += 1
327
+ new_line += c1
328
+ elsif in_string and c == "\"" and c_1 != "\\"
329
+ in_string = false
330
+ new_line += c
331
+ elsif in_multi_line_string and c == "\"" and c1 != "\""
332
+ in_multi_line_string = false
333
+ new_line += c
334
+ else
335
+ new_line += c
336
+ end
337
+
338
+ lines[i] = new_line
339
+ j += 1
340
+ end
341
+ i += 1
342
+ end
343
+ end
344
+
345
+ def csharp_tabify(lines, options)
346
+ # Insert tabs for spaces, but only at the beginning of lines and not inside @"..." or "..." strings
347
+ in_multi_line_string = false
348
+ i = 0
349
+
350
+ while i < lines.length do
351
+ line = lines[i]
352
+ in_string = false
353
+ bol = true
354
+ num_bol_spaces = 0
355
+ new_line = ""
356
+ j = 0
357
+
358
+ while j < line.length do
359
+ c_1 = j > 0 ? line[j - 1] : "\0"
360
+ c = line[j]
361
+ c1 = j < line.length - 1 ? line[j + 1] : "\0"
362
+
363
+ if !in_string and !in_multi_line_string and bol and c == " "
364
+ # Just count the spaces
365
+ num_bol_spaces += 1
366
+ elsif !in_string and !in_multi_line_string and bol and c != " "
367
+ bol = false
368
+
369
+ new_line += "\t" * (num_bol_spaces / options.tabsize)
370
+
371
+ if !options.round_down_spaces
372
+ new_line += " " * (num_bol_spaces % options.tabsize)
373
+ end
374
+ # Process this character again as not BOL
375
+ j -= 1
376
+ elsif !in_multi_line_string and !in_string and c == '"'
377
+ in_string = true
378
+ new_line += c
379
+ elsif !in_multi_line_string and !in_string and c == "@" and c1 == "\""
380
+ in_multi_line_string = true
381
+ new_line += c
382
+ j += 1
383
+ new_line += c1
384
+ elsif in_string and c == "\"" and c_1 != "\\"
385
+ in_string = false
386
+ new_line += c
387
+ elsif in_multi_line_string and c == "\"" and c1 != "\""
388
+ in_multi_line_string = false
389
+ new_line += c
390
+ else
391
+ new_line += c
392
+ end
393
+
394
+ lines[i] = new_line
395
+ j += 1
396
+ end
397
+ i += 1
398
+ end
399
+ end
400
+
401
+ def error(msg)
402
+ STDERR.puts "error: #{msg}".colorize(:red)
403
+ end
404
+
405
+ end
data/lib/vamper.rb CHANGED
@@ -2,11 +2,12 @@ require 'tzinfo'
2
2
  require 'nokogiri'
3
3
  require 'ostruct'
4
4
  require 'optparse'
5
+ require 'colorize'
5
6
  require_relative './vamper/version_file.rb'
6
7
  require_relative './vamper/version_config_file.rb'
7
8
  require_relative './core_ext.rb'
8
9
 
9
- $VERSION='4.1.0-20151225.0'
10
+ $VERSION='4.2.0-20151225.0'
10
11
 
11
12
  class Vamper
12
13
 
@@ -16,15 +17,15 @@ class Vamper
16
17
  options.version_file_name = ''
17
18
 
18
19
  opt_parser = OptionParser.new do |opts|
19
- opts.banner = %Q(Version Stamper. Version #{$VERSION}
20
+ opts.banner = %Q(Vamper Version Stamper. Version #{$VERSION}
20
21
  Copyright (c) John Lyon-Smith, 2016.
21
22
  Usage: #{File.basename(__FILE__)} [options]
22
23
  )
23
24
  opts.separator %Q(Options:
24
25
  )
25
26
 
26
- opts.on("-u", "--update", "Increment the build number and update all files") do |dir|
27
- options.do_update = true
27
+ opts.on("-u", "--update", "Increment the build number and update all files") do |update|
28
+ options.do_update = update
28
29
  end
29
30
 
30
31
  opts.on_tail("-?", "--help", "Show this message") do
@@ -189,7 +190,7 @@ Usage: #{File.basename(__FILE__)} [options]
189
190
  end
190
191
 
191
192
  def error(msg)
192
- puts "error: ".red + "#{msg}"
193
+ puts "error: #{msg}".colorize(:red)
193
194
  end
194
195
 
195
196
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: code_tools
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.1.0
4
+ version: 4.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Lyon-smith
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-12-25 00:00:00.000000000 Z
11
+ date: 2015-12-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: tzinfo
@@ -38,18 +38,38 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '1.6'
41
+ - !ruby/object:Gem::Dependency
42
+ name: colorize
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 0.7.7
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 0.7.7
41
55
  description: Tools for source code maintenance, including version stamping, line endings
42
56
  and tab/space conversion.
43
57
  email: john@jamoki.com
44
58
  executables:
45
- - vamper
46
59
  - code_tools
60
+ - ender
61
+ - spacer
62
+ - vamper
47
63
  extensions: []
48
64
  extra_rdoc_files: []
49
65
  files:
50
66
  - bin/code_tools
67
+ - bin/ender
68
+ - bin/spacer
51
69
  - bin/vamper
52
70
  - lib/core_ext.rb
71
+ - lib/ender.rb
72
+ - lib/spacer.rb
53
73
  - lib/vamper.rb
54
74
  - lib/vamper/default.version.config
55
75
  - lib/vamper/version_config_file.rb