code_caser 0.0.4 → 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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a0fdaa2d4caf807b396c917cc218140c5c875099
4
- data.tar.gz: e70ac1a05cca5972956a60a2021f5c7cbca4daaf
3
+ metadata.gz: dff1ea58bc087c06e16db95c43a0ea694919d88e
4
+ data.tar.gz: 1d538e2ec7a88d444f52fa6760927ce11cfec071
5
5
  SHA512:
6
- metadata.gz: a26d48db5e215512f28a8e9233ed95a3cf9e8cfd5cacd2595a9d092fe5006ed4ef9336e3432a5888b6ff8e5f575f066a2f4b55cec2212f05292e65c6d98f9545
7
- data.tar.gz: b3a6c6469d3f98af007ca5449ace3a0050d9b42c80dc2973363631bab47d9152e38a523fc4dcf6002c4d9cc5711ce95d10df955cf30e4f2b4a091c8a16aa93bd
6
+ metadata.gz: 8c3af265ff4d2e4bb8b03af507ed976b48da522b361a637965a2bc2530d61cba00d063b7cdcd77b86c9163d528841fb3646951f218981e529053c27dadc8755b
7
+ data.tar.gz: 2eeefc372f4022f8fbcd612a93cda2cf236273b5924542de0284138f3bc17fb96838ff446b8548b39a7da9904e2e14fc7e54e7d0e32828f3f8d0b32bcb6a5775
data/README.md CHANGED
@@ -1,9 +1,7 @@
1
1
  # CodeCaser
2
-
3
2
  A simple Ruby command line utility that converts files from camelCase to snake_case and vice-versa.
4
3
 
5
4
  ## Installation
6
-
7
5
  To install:
8
6
  ```
9
7
  $ gem install code_caser
@@ -34,3 +32,6 @@ $ code_caser to_camel --path=/folder/subfolder/*.js
34
32
  Use the ```--verbose``` flag to print any changes made to each file to the terminal.
35
33
 
36
34
  By default, backup copies of each file converted will be saved to a timestamped backup folder in the ```--path``` directory. You can prevent backups from being created by passing in the ```--no-save``` flag.
35
+
36
+ ## License
37
+ code_caser is available under the MIT License.
data/bin/code_caser CHANGED
@@ -3,24 +3,65 @@ require "rubygems"
3
3
  require "thor"
4
4
  require_relative "../lib/code_caser"
5
5
 
6
- class CaserCLI < Thor
7
-
8
- desc "to_camel", "converts files in PATH from snake_case to camelCase."
9
- option :path, type: :string, required: true
10
- option :save, type: :boolean, default: true
11
- option :verbose, type: :boolean, default: false
12
- def to_camel
13
- CodeCaser::to_camel(options)
6
+ module CodeCaser
7
+
8
+ module FileArgs
9
+ def self.included(base)
10
+ base.extend(ClassMethods)
11
+ end
12
+ module ClassMethods
13
+ def annotate(method_name, desc, save_option=true)
14
+ class_eval do # help keep things DRY:
15
+ desc method_name, desc
16
+ option :path, type: :string, required: true
17
+ option :ignore_after, type: :string, required: false,
18
+ desc: "ignore all text in each line after the string IGNORE_AFTER"
19
+ option :verbose, type: :boolean, default: false
20
+ option :save, type: :boolean, default: true if save_option
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ class AnalyzerCLI < Thor
27
+ include FileArgs
28
+ annotate "to_camel", "checks if any existing identifiers would be overridden by converting to camelCase", false
29
+ def to_camel
30
+ CodeCaser::Analyze::to_camel(options)
31
+ end
32
+ annotate "to_snake", "checks if any existing identifiers would be overridden by converting to snake_case", false
33
+ def to_snake
34
+ CodeCaser::Analyze::to_snake(options)
35
+ end
14
36
  end
15
37
 
16
- desc "to_snake", "converts files in PATH from camelCase to snake_case."
17
- option :path, type: :string, required: true
18
- option :save, type: :boolean, default: true
19
- option :verbose, type: :boolean, default: false
20
- def to_snake
21
- CodeCaser::to_snake(options)
38
+ class CaserCLI < Thor
39
+ include FileArgs
40
+ annotate "to_camel", "converts files in PATH from snake_case to camelCase"
41
+ def to_camel
42
+ CodeCaser::to_camel(options)
43
+ end
44
+
45
+ annotate "to_snake", "converts files in PATH from camelCase to snake_case"
46
+ def to_snake
47
+ CodeCaser::to_snake(options)
48
+ end
49
+
50
+ # TODO: add methods to convert a single string
51
+
52
+ register CodeCaser::AnalyzerCLI, "analyze", "analyze to_camel",
53
+ "checks if any existing identifiers would be overridden by converting to camelCase" #, options
54
+
55
+ register CodeCaser::AnalyzerCLI, "analyze", "analyze to_snake",
56
+ "checks if any existing identifiers would be overridden by converting to snake_case" #, options
57
+
58
+ desc "--version, -v", "print the version number"
59
+ def __print_version
60
+ puts CodeCaser::VERSION
61
+ end
62
+ map %w(--version -v) => :__print_version
22
63
  end
23
64
 
24
65
  end
25
66
 
26
- CaserCLI.start
67
+ CodeCaser::CaserCLI.start
@@ -0,0 +1,74 @@
1
+ module CodeCaser
2
+
3
+ # This class scans the provided files to determine if any converted identifiers
4
+ # overlap with existing identifiers.
5
+ class Analyzer
6
+ def initialize(opts)
7
+ @converter = opts.fetch(:converter)
8
+ @files = PathConverter.new(opts.fetch(:path)).get_files
9
+ @verbose = opts.fetch(:verbose, false)
10
+ @existing_identifiers = {}
11
+ @new_identifiers = {}
12
+ @overlapping_identifiers = []
13
+ end
14
+
15
+ def analyze
16
+ load_existing_identifiers
17
+ @files.each { |f| analyze_file(f) if File.file?(f) }
18
+ puts @existing_identifiers.keys.sort.inspect
19
+ print_new_identifiers if @verbose
20
+ @overlapping_identifiers = @new_identifiers.select {|k,v| @existing_identifiers.key?(k) }.keys
21
+ print_overlap
22
+ end
23
+
24
+ def load_existing_identifiers
25
+ @files.each { |f| load_existing_identifiers_from_file(f) if File.file?(f) }
26
+ end
27
+
28
+ def load_existing_identifiers_from_file(file_path)
29
+ puts "loading file: #{file_path}" if @verbose
30
+ IO.foreach(file_path) { |line| load_existing_identifiers_from_line(line) }
31
+ end
32
+
33
+ def load_existing_identifiers_from_line(line)
34
+ split_line(line).each { |l| @existing_identifiers[l] = true }
35
+ end
36
+
37
+ def analyze_file(file_path)
38
+ puts "loading file: #{file_path}" if @verbose
39
+ IO.foreach(file_path) { |line| analyze_line(line) }
40
+ end
41
+
42
+ def print_overlap
43
+ if @overlapping_identifiers.empty?
44
+ puts "\nNo overlapping identifiers found.".colorize(:green)
45
+ else
46
+ puts "\nThe following identifiers would overlap with existing names:".colorize(:yellow)
47
+ puts @overlapping_identifiers.join(",").colorize(:yellow)
48
+ end
49
+ end
50
+
51
+ def print_new_identifiers
52
+ puts "\nThe following identifiers would be replaced:".colorize(:yellow)
53
+ @new_identifiers.sort.to_h.each {|k,v| puts "#{v} -> #{k.colorize(:green)}" }
54
+ end
55
+
56
+ private
57
+
58
+ def analyze_line(original_line)
59
+ # discard anything after the ignore_after identifier
60
+ original_identifiers = @converter.chop(original_line).split(/\W+/)
61
+ original_identifiers.each do |identifier|
62
+ if identifier != (new_identifier = @converter.convert_line(identifier))
63
+ @new_identifiers[new_identifier] = identifier
64
+ end
65
+ end
66
+ end
67
+
68
+ def split_line(line)
69
+ @converter.chop(line).split(/\W+/)
70
+ end
71
+
72
+ end
73
+
74
+ end
@@ -2,17 +2,16 @@ require 'fileutils'
2
2
  require 'colorize'
3
3
 
4
4
  module CodeCaser
5
-
6
5
  class Caser
7
6
  def initialize(opts = {})
8
- @converter = opts[:converter]
9
- @path = File.directory?(opts[:path]) ? File.join(opts[:path], "*") : opts[:path]
10
- @save = opts[:save] || true
11
- @verbose = opts[:verbose] || false
7
+ @converter = opts.fetch(:converter)
8
+ @path_converter = PathConverter.new(opts.fetch(:path))
9
+ @save = opts.fetch(:save, true)
10
+ @verbose = opts.fetch(:verbose, false)
12
11
  end
13
12
 
14
13
  def start
15
- files = get_files
14
+ files = @path_converter.get_files
16
15
  if files.empty?
17
16
  puts "File or folder not found.\n"
18
17
  return
@@ -30,12 +29,8 @@ module CodeCaser
30
29
 
31
30
  private
32
31
 
33
- def get_files
34
- Dir.glob(File.expand_path(@path))
35
- end
36
-
37
32
  def backup_folder
38
- @backup_folder ||= File.dirname(@path) + "_backup_#{Time.new.to_i}"
33
+ @backup_folder ||= @path_converter.join("_backup_#{Time.new.to_i}")
39
34
  end
40
35
 
41
36
  def convert_files(files)
@@ -53,16 +48,12 @@ module CodeCaser
53
48
  FileUtils.rm(file_path)
54
49
  f = File.new(file_path, "w+")
55
50
  IO.foreach(backup_file_path) do |line|
56
- f.puts(convert_line(line))
51
+ f.puts(convert_line(line.chomp))
57
52
  end
58
53
  end
59
54
 
60
55
  def convert_line(line)
61
- if (converted_line = @converter.convert_line(line)) != line && @verbose
62
- puts " " + line.strip
63
- puts " " + converted_line.strip.colorize(:green)
64
- end
65
- converted_line
56
+ @converter.convert_line(line, @verbose)
66
57
  end
67
58
 
68
59
  def user_aborted?(files)
@@ -1,6 +1,44 @@
1
+ require 'colorize'
2
+
1
3
  module CodeCaser
2
- class CamelConverter
3
- def convert_line(str)
4
+ class Converter
5
+ def initialize(opts={})
6
+ if opts[:ignore_after]
7
+ @ignore_after = Regexp.new('(^.*?)(' + Regexp.escape(opts[:ignore_after]) + '.*)')
8
+ end
9
+ end
10
+
11
+ def convert_line(line, verbose=false)
12
+ converted_line = if @ignore_after && (data = match_data(line))
13
+ convert_string(data[1]) + data[2]
14
+ else
15
+ convert_string(line)
16
+ end
17
+ if verbose && converted_line != line
18
+ puts "\n " + line.strip
19
+ puts " " + converted_line.strip.colorize(:green)
20
+ end
21
+
22
+ converted_line
23
+ end
24
+
25
+ def chop(line)
26
+ @ignore_after && (data = match_data(line)) ? data[1] : line
27
+ end
28
+
29
+ def convert_string # concrete Converter implementations must supply this method
30
+ raise NotImplementedError
31
+ end
32
+
33
+ private
34
+
35
+ def match_data(line)
36
+ line.match(@ignore_after)
37
+ end
38
+ end
39
+
40
+ class CamelConverter < Converter
41
+ def convert_string(str)
4
42
  match = false
5
43
  output = str.reverse.gsub(/([a-z]+[A-Z]\B)(.)(?!\w*[A-Z]\b)/) { |s|
6
44
  match = true
@@ -17,8 +55,8 @@ module CodeCaser
17
55
  end
18
56
  end
19
57
 
20
- class SnakeConverter
21
- def convert_line(str)
58
+ class SnakeConverter < Converter
59
+ def convert_string(str)
22
60
  str.gsub(/([a-z0-9])_([a-z0-9])/) { |s| $1 + $2.upcase }
23
61
  end
24
62
 
@@ -0,0 +1,20 @@
1
+ module CodeCaser
2
+ class PathConverter
3
+
4
+ def initialize(path)
5
+ @path = File.directory?(path) ? File.join(path, "*") : path
6
+ end
7
+
8
+ def dirname
9
+ File.expand_path(File.dirname(@path))
10
+ end
11
+
12
+ def join(name)
13
+ File.join(dirname + name)
14
+ end
15
+
16
+ def get_files
17
+ Dir.glob(File.expand_path(@path))
18
+ end
19
+ end
20
+ end
@@ -1,3 +1,3 @@
1
1
  module CodeCaser
2
- VERSION = '0.0.4'
2
+ VERSION = '0.1.0'
3
3
  end
data/lib/code_caser.rb CHANGED
@@ -1,11 +1,22 @@
1
+
1
2
  Dir[File.dirname(__FILE__) + '/code_caser/*.rb'].each {|file| require file }
2
3
 
3
4
  module CodeCaser
4
- def self.to_camel(opts)
5
- Caser.new(opts.merge({ converter: SnakeConverter.new })).start
6
- end
5
+ def self.to_camel(opts)
6
+ Caser.new(opts.merge({ converter: SnakeConverter.new(opts) })).start
7
+ end
8
+
9
+ def self.to_snake(opts)
10
+ Caser.new(opts.merge({ converter: CamelConverter.new(opts) })).start
11
+ end
12
+
13
+ module Analyze
14
+ def self.to_camel(opts)
15
+ Analyzer.new(opts.merge(converter: SnakeConverter.new(opts))).analyze
16
+ end
7
17
 
8
- def self.to_snake(opts)
9
- Caser.new(opts.merge({ converter: CamelConverter.new })).start
10
- end
18
+ def self.to_snake(opts)
19
+ Analyzer.new(opts.merge(converter: CamelConverter.new(opts))).analyze
20
+ end
21
+ end
11
22
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: code_caser
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Steve Lovell
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-01-18 00:00:00.000000000 Z
11
+ date: 2017-01-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -71,8 +71,10 @@ files:
71
71
  - Rakefile
72
72
  - bin/code_caser
73
73
  - lib/code_caser.rb
74
+ - lib/code_caser/analyzer.rb
74
75
  - lib/code_caser/caser.rb
75
76
  - lib/code_caser/converters.rb
77
+ - lib/code_caser/path_converter.rb
76
78
  - lib/code_caser/version.rb
77
79
  homepage: https://github.com/stephenjlovell/code_caser
78
80
  licenses: