rbname 0.0.2 → 0.0.3

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,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- OGY3MWE4ZTMxYWE2ZmE0OTVhMWMyOTFlOTI1OTMzNzQ0ZWFmNGM2MQ==
4
+ NzdhNGQ0M2MwZTBlOTJkYTk3NzAwMjc4MmM1NDhiMGIzZDE1ZmE2OQ==
5
5
  data.tar.gz: !binary |-
6
- NDg5MDE3YzllNWJlNDY1MTk4YjkxYzU2ZjJkZDhlMTRmY2YyM2VkMw==
6
+ YjA0MGIzOTU0MDc0YTg0M2RjZTU0NWY5ZWEwYzIyM2ZhYzE5MmZiNw==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- ODFiYzZjNGRjNWEyZWYxNDdiZWI3OWJjYmQ5MzRmY2I0MGE0ODdhYTRlYmEw
10
- NjExOGJlYWZmMjNjN2E2NDI3NTYwZTM3YmQ2MjQ3ZTAyZTAyZDMyZGU1MDkw
11
- MjM3MjJmNzE4NzdiNmQxNTAzNzYwOTk5ZTU3NzVmMzU3MzJlOTE=
9
+ OWYxMzc2NWU1MGE4OTA0NWZmMmY1NDY4ZTJlNWMxNWJiMGRkNzYzYTc2MDNm
10
+ ZDFjZWU2NGY0OTIxMGEwNTQwYWJlM2UyYjcxMGVmYmJjZWRkYzM5ZGY5ZjUw
11
+ NmM4ZTU1NThkMGY4OTYyNDJkNjhlZTM4NGI3OWQxNzcyYjU2MzA=
12
12
  data.tar.gz: !binary |-
13
- NjlkNzEyYWJjNzg5MWRmMWVkYWM4MjlhNGRmOWM5ODM4M2FmMDJkOGExOTkw
14
- M2Q0NTFjZjk1MjM1NTg3N2VmMjdiMmMzNzA1MDAzMTgxY2Q4ZmJmMzdjMjc5
15
- M2M3M2UwMzY3MWRiYTdmMDIxZWU2NGY4NTgxZTMyMDNhODVmZmQ=
13
+ MGJiZjg3MDllYzUyYTY5NjhkNjkyY2U5NjdkYzhlMzRiOTExOTI5NzNhYTcy
14
+ ZWVmMTdhNzExMTAyOGFlZmUzMWVkM2ExYWE5ZjI4OTVhY2MyZDkyMGE5M2Qz
15
+ MDdkMzIwMWYyNDM3YmFiNGViOTQ5YzFmYjMyYTc4OWQ1ZDVlYjI=
data/bin/rbname CHANGED
@@ -6,4 +6,4 @@ end
6
6
 
7
7
  require 'main'
8
8
 
9
- Main.replace_all
9
+ Main.new.replace_all
@@ -14,32 +14,68 @@ class ChangePrompt
14
14
  puts HORIZONTAL_LINE
15
15
  puts("#{USE_EDITOR}: Edit in Vi")
16
16
  replacements.each_with_index do |replacement, index|
17
- puts "#{index}: #{replacement.suggest(file_line.raw_contents)}"
17
+ puts "#{one_indexed(index)}: #{replacement.highlighted_suggest(file_line.raw_contents)}"
18
18
  end
19
19
  puts HORIZONTAL_LINE
20
+ get_the_input(replacements)
21
+ end
22
+
23
+ def self.get_the_input(replacements)
20
24
  user_input = gets
21
25
  puts("")
22
- ChangePrompt.new(user_input)
26
+ prompt = ChangePrompt.new(user_input, replacements)
27
+
28
+ until(prompt.valid?)
29
+ puts "Yo, #{prompt.instance_variable_get(:@user_input)} is not a good answer. Try again"
30
+ user_input = gets
31
+ puts("")
32
+ prompt = ChangePrompt.new(user_input, replacements)
33
+ end
34
+ prompt
23
35
  end
24
36
 
25
37
 
26
- def initialize(user_input)
38
+ def initialize(user_input, replacements)
27
39
  @user_input = user_input
40
+ @replacements = replacements
28
41
  end
29
42
 
30
43
  def chose_editor?
31
44
  user_input.downcase.match(USE_EDITOR.downcase)
32
45
  end
33
46
 
47
+ def selected_replacement
48
+ replacements[zero_indexed(integer_input)] if integer_input
49
+ end
50
+
51
+ def valid?
52
+ chose_editor? || valid_integer_input || user_input.chomp.empty?
53
+ end
54
+
55
+ private
56
+
57
+ attr_reader :replacements
58
+
34
59
  def integer_input
35
60
  Integer(user_input)
36
61
  rescue => e
37
62
  nil
38
63
  end
39
64
 
40
- private
65
+ def zero_indexed(index)
66
+ index - 1
67
+ end
68
+
69
+ def valid_integer_input
70
+ (1..replacements.count).include?(integer_input)
71
+ end
72
+
73
+ def self.one_indexed(index)
74
+ index + 1
75
+ end
41
76
 
42
77
  def self.present_line(file_line, pattern)
78
+ puts "\n" * 50
43
79
  puts HORIZONTAL_LINE
44
80
  puts("FILENAME: #{file_line.path}")
45
81
  puts HORIZONTAL_LINE
@@ -0,0 +1,9 @@
1
+ class Array
2
+ def max_key
3
+ values = map do |element|
4
+ yield(element)
5
+ end
6
+
7
+ values.index(values.max)
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ class Object
2
+ def identity
3
+ self
4
+ end
5
+ end
@@ -0,0 +1,11 @@
1
+ class String
2
+ def indices_of_pattern(pattern)
3
+ indices = []
4
+ split("").each_with_index do |_, idx|
5
+ if self[idx..-1].start_with?(pattern)
6
+ indices << idx
7
+ end
8
+ end
9
+ indices
10
+ end
11
+ end
@@ -1,10 +1,17 @@
1
1
  require 'replacement'
2
2
  require 'change_prompt'
3
3
  require 'replacement_collection'
4
+ require 'vim_edit'
4
5
 
5
6
  class Main
6
- def self.replace_all
7
7
 
8
+ attr_accessor :manual_edit
9
+
10
+ def initialize
11
+ @manual_edit = VimEdit.new
12
+ end
13
+
14
+ def replace_all
8
15
  pattern, root_path = prompt_search_details
9
16
 
10
17
  file_lines = FileLine.find_all(pattern, root_path)
@@ -16,10 +23,10 @@ class Main
16
23
  applicable_replacements = replacement_collection.applicable_replacements(old_contents)
17
24
  user_input = ChangePrompt.prompt(pattern, file_line, applicable_replacements)
18
25
  if user_input.chose_editor?
19
- edit_with_vim!(file_line, pattern)
26
+ manual_edit.execute!(file_line, pattern)
20
27
  record_manual_replacement!(replacement_collection, old_contents, file_line)
21
- elsif user_input.integer_input
22
- take_user_suggestion!(user_input.integer_input, applicable_replacements, file_line)
28
+ elsif user_input.selected_replacement
29
+ take_user_suggestion!(user_input.selected_replacement, file_line)
23
30
  end
24
31
  end
25
32
  end
@@ -27,30 +34,36 @@ class Main
27
34
 
28
35
  private
29
36
 
30
- def self.prompt_search_details
37
+ def prompt_search_details
31
38
  puts "We will be replacing some text today."
32
39
  puts "What is a pattern describing the text you want to replace?"
33
40
  pattern = gets.chomp
34
41
  puts ""
35
42
  puts "What is root of your search? ('.' would probably work fine)"
36
- root_path = gets.chomp
43
+ root_path = get_root_path
37
44
  puts ""
38
45
  [pattern, root_path]
39
46
  end
40
47
 
41
- def self.record_manual_replacement!(replacement_collection, old_contents, file_line)
48
+ def get_root_path
49
+ chomped = gets.chomp
50
+ if chomped.empty?
51
+ puts "Defaulting to current directory. Hit return to begin"
52
+ gets
53
+ return "."
54
+ end
55
+ return chomped
56
+ end
57
+
58
+ def record_manual_replacement!(replacement_collection, old_contents, file_line)
42
59
  new_contents = file_line.raw_contents
43
60
  replacement_collection << Replacement.generate(old_contents, new_contents) unless old_contents == new_contents
61
+ replacement_collection
44
62
  end
45
63
 
46
- def self.take_user_suggestion!(integer_input, applicable_replacements, file_line)
47
- replacement = applicable_replacements[integer_input]
64
+ def take_user_suggestion!(replacement, file_line)
48
65
  new_contents = replacement.suggest(file_line.raw_contents)
49
66
  file_line.update_filesystem!(new_contents)
50
67
  end
51
68
 
52
- def self.edit_with_vim!(file_line, pattern)
53
- system "vim +#{file_line.number} #{file_line.path} -c '#{"/"+pattern}' -c 'normal n' -c 'normal N' -c 'normal zz'"
54
- end
55
-
56
69
  end
@@ -1,13 +1,16 @@
1
- class Replacement
2
- attr_reader :to_replace, :new_text
1
+ require 'extensions/array'
2
+ require 'extensions/string'
3
+ require 'extensions/object'
4
+ require 'replacement/score'
3
5
 
4
- def initialize(to_replace, new_text)
5
- @to_replace = to_replace
6
- @new_text = new_text
7
- end
6
+ class Replacement
7
+ attr_reader :removed_by_user, :added_by_user
8
8
 
9
- def self.suggestions(replacements, to_change)
10
- replacements.map { |replacement| replacement.suggest(to_change) }.uniq.compact
9
+ def initialize(removed_by_user, added_by_user, left_context, right_context)
10
+ @removed_by_user = removed_by_user
11
+ @added_by_user = added_by_user
12
+ @left_context = left_context
13
+ @right_context = right_context
11
14
  end
12
15
 
13
16
  def self.generate(before, after)
@@ -19,21 +22,41 @@ class Replacement
19
22
  before[before.length - index - 1] != after[after.length - index - 1]
20
23
  end
21
24
 
22
- to_replace = drop_characters(before, leading_same_characters_count, trailing_same_characters_count)
23
- new_text = drop_characters(after, leading_same_characters_count, trailing_same_characters_count)
25
+ removed_by_user = drop_characters(before, leading_same_characters_count, trailing_same_characters_count)
26
+ added_by_user = drop_characters(after, leading_same_characters_count, trailing_same_characters_count)
27
+
28
+ left_context = before[0...leading_same_characters_count]
24
29
 
25
- Replacement.new(to_replace, new_text)
30
+ right_context = before[-trailing_same_characters_count..-1]
31
+
32
+ Replacement.new(removed_by_user, added_by_user, left_context, right_context)
26
33
  end
27
34
 
28
- def suggest(to_change)
29
- if to_change.match(to_replace)
30
- to_change.sub(to_replace, new_text)
31
- end
35
+ def suggest(requiring_suggestions)
36
+ formattable_suggest(requiring_suggestions, &:identity)
37
+ end
38
+
39
+ def highlighted_suggest(requiring_suggestions)
40
+ formattable_suggest(requiring_suggestions, &:red)
32
41
  end
33
42
 
34
43
  private
35
44
 
45
+ def formattable_suggest(requiring_suggestions)
46
+ indices = requiring_suggestions.indices_of_pattern(removed_by_user)
47
+
48
+ best_replacement_index = indices.max_key do |index|
49
+ Score.best_score(removed_by_user, requiring_suggestions, @left_context, @right_context, index)
50
+ end
51
+
52
+ return unless best_replacement_index
53
+
54
+ subbed = requiring_suggestions[best_replacement_index..-1].sub(removed_by_user, yield(added_by_user))
55
+ requiring_suggestions[0...best_replacement_index] + subbed
56
+ end
57
+
36
58
  def self.drop_characters(subject, leading, trailing)
37
59
  subject[leading...(subject.size - trailing)]
38
60
  end
39
61
  end
62
+
@@ -0,0 +1,25 @@
1
+ class Replacement
2
+ class Score
3
+ def self.best_score(pattern, to_update, left_context, right_context, pattern_index)
4
+ [right_score(pattern, to_update, right_context, pattern_index),
5
+ left_score(to_update, left_context, pattern_index)].max
6
+ end
7
+
8
+ def self.right_score(pattern, to_update, right_context, pattern_index)
9
+ pattern_length = pattern.length
10
+ start_index = pattern_index + pattern_length
11
+ string_dot_product(to_update[start_index..-1], right_context).count
12
+ end
13
+
14
+ def self.left_score(to_update, left_context, pattern_index)
15
+ string_dot_product(to_update[0...pattern_index].reverse, left_context.reverse).count
16
+ end
17
+
18
+
19
+ def self.string_dot_product(first, second)
20
+ first.split("").zip(second.split("")).take_while do |(a,b)|
21
+ a == b
22
+ end
23
+ end
24
+ end
25
+ end
@@ -1,7 +1,7 @@
1
1
  class ReplacementCollection < Array
2
2
  def applicable_replacements(line_contents)
3
3
  select do |replacement|
4
- line_contents.match(Regexp.escape(replacement.to_replace))
4
+ line_contents.match(Regexp.escape(replacement.removed_by_user))
5
5
  end
6
6
  end
7
7
  end
@@ -0,0 +1,5 @@
1
+ class VimEdit
2
+ def execute!(file_line, pattern)
3
+ system "vim +#{file_line.number} #{file_line.path} -c '#{"/"+pattern}' -c 'normal n' -c 'normal N' -c 'normal zz'"
4
+ end
5
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rbname
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Wai Lee Chin Feman
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-11-21 00:00:00.000000000 Z
11
+ date: 2013-12-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -46,11 +46,16 @@ extensions: []
46
46
  extra_rdoc_files: []
47
47
  files:
48
48
  - lib/change_prompt.rb
49
+ - lib/extensions/array.rb
50
+ - lib/extensions/object.rb
51
+ - lib/extensions/string.rb
49
52
  - lib/file_line.rb
50
53
  - lib/file_line_presenter.rb
51
54
  - lib/main.rb
52
55
  - lib/replacement.rb
56
+ - lib/replacement/score.rb
53
57
  - lib/replacement_collection.rb
58
+ - lib/vim_edit.rb
54
59
  - bin/rbname
55
60
  homepage: http://github.com/skatenerd
56
61
  licenses:
@@ -72,7 +77,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
72
77
  version: '0'
73
78
  requirements: []
74
79
  rubyforge_project:
75
- rubygems_version: 2.1.2
80
+ rubygems_version: 2.1.11
76
81
  signing_key:
77
82
  specification_version: 4
78
83
  summary: CLI Find/Replace