rbname 0.0.1

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.
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ %w(. ./lib/).each do |path|
4
+ $: << path
5
+ end
6
+
7
+ require 'main'
8
+
9
+ Main.replace_all
@@ -0,0 +1,49 @@
1
+ require 'colorize'
2
+ require 'file_line_presenter'
3
+
4
+ class ChangePrompt
5
+ LINES_OF_CONTEXT = 2
6
+ USE_EDITOR = "E"
7
+
8
+ attr_reader :user_input
9
+
10
+ def self.prompt(pattern, file_line, replacements)
11
+ present_line(file_line, pattern)
12
+ puts("How would you like to update the above line? Options below. Hit return to do nothing\n\n")
13
+ puts "------------------------------"
14
+ puts("#{USE_EDITOR}: Edit in Vi")
15
+ replacements.each_with_index do |replacement, index|
16
+ puts "#{index}: #{replacement.suggest(file_line.raw_contents)}"
17
+ end
18
+ puts "------------------------------"
19
+ user_input = gets
20
+ puts("")
21
+ ChangePrompt.new(user_input)
22
+ end
23
+
24
+
25
+ def initialize(user_input)
26
+ @user_input = user_input
27
+ end
28
+
29
+ def chose_editor?
30
+ user_input.downcase.match(USE_EDITOR.downcase)
31
+ end
32
+
33
+ def integer_input
34
+ Integer(user_input)
35
+ rescue => e
36
+ nil
37
+ end
38
+
39
+ private
40
+
41
+ def self.present_line(file_line, pattern)
42
+ puts "-----------------------------------"
43
+ puts("FILENAME: #{file_line.path}")
44
+ puts "-----------------------------------"
45
+ puts(FileLinePresenter.present_contents(file_line, pattern, LINES_OF_CONTEXT))
46
+ puts "-----------------------------------"
47
+ puts "\n"
48
+ end
49
+ end
@@ -0,0 +1,27 @@
1
+ require 'colorize'
2
+
3
+ class FileLine
4
+ attr_accessor :number, :path
5
+ def initialize(number, path)
6
+ @number = number
7
+ @path = path
8
+ end
9
+
10
+ def self.find_all(pattern, directory_path)
11
+ grep_results = `grep -Irn "#{pattern}" #{directory_path} --exclude-dir="*.*.*"`
12
+ grep_results.split("\n").map do |grep_hit|
13
+ file_path, line_number, _ = grep_hit.split(":")
14
+ line_number = line_number.to_i
15
+ FileLine.new(line_number, file_path)
16
+ end
17
+ end
18
+
19
+ def update_filesystem!(new_contents)
20
+ `sed -e '#{number} s/.*/#{new_contents}/' -i '' #{path}`
21
+ end
22
+
23
+ def raw_contents
24
+ `sed -n '#{number}p' #{path}`.chomp
25
+ end
26
+
27
+ end
@@ -0,0 +1,43 @@
1
+ require 'file_line'
2
+
3
+ class FileLinePresenter
4
+
5
+ TAB = " "
6
+
7
+ def self.present_contents(file_line, pattern, context = 0)
8
+ current_highlighted_line = with_line_number(file_line, with_highlighting(file_line, pattern))
9
+ line_number = file_line.number
10
+ line_path = file_line.path
11
+ lower_limit = [line_number - context, 1].max
12
+ upper_limit = [line_number + context, file_length(file_line)].min
13
+ above_line_indices = (lower_limit...line_number)
14
+ below_line_indices = (line_number + 1..upper_limit)
15
+
16
+ above_lines = numbered_lines_at(above_line_indices, line_path)
17
+ below_lines = numbered_lines_at(below_line_indices, line_path)
18
+ (above_lines + [current_highlighted_line] + below_lines).join("\n")
19
+ end
20
+
21
+ private
22
+
23
+ def self.numbered_lines_at(indices, path)
24
+ indices.map do |line_number|
25
+ with_line_number(FileLine.new(line_number, path))
26
+ end
27
+ end
28
+
29
+ def self.with_line_number(file_line, contents = file_line.raw_contents)
30
+ "#{file_line.number}:#{TAB}#{contents}"
31
+ end
32
+
33
+ def self.with_highlighting(file_line, pattern)
34
+ file_line.raw_contents.gsub!(/#{pattern}/) do |match|
35
+ match.red
36
+ end
37
+ end
38
+
39
+ def self.file_length(file_line)
40
+ `wc -l #{file_line.path}`.strip.split(" ")[0].to_i
41
+ end
42
+
43
+ end
@@ -0,0 +1,50 @@
1
+ require 'replacement'
2
+ require 'change_prompt'
3
+ require 'replacement_collection'
4
+
5
+ class Main
6
+ def self.replace_all
7
+ puts "We will be replacing some text today."
8
+ puts "What is a pattern describing the text you want to replace?"
9
+ pattern = gets.chomp
10
+ puts ""
11
+ puts "What is root of your search? ('.' would probably work fine)"
12
+ root_path = gets.chomp
13
+ puts ""
14
+
15
+ file_lines = FileLine.find_all(pattern, root_path)
16
+ replacement_collection = ReplacementCollection.new
17
+
18
+ file_lines.each do |file_line|
19
+ if file_line.raw_contents.match(pattern)
20
+ old_contents = file_line.raw_contents
21
+ applicable_replacements = replacement_collection.applicable_replacements(old_contents)
22
+ user_input = ChangePrompt.prompt(pattern, file_line, applicable_replacements)
23
+ if user_input.chose_editor?
24
+ edit_with_vim!(file_line, pattern)
25
+ update_replacement_collection!(replacement_collection, old_contents, file_line)
26
+ elsif user_input.integer_input
27
+ update_according_to_sugestion(user_input.integer_input, applicable_replacements, file_line)
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ def self.update_replacement_collection!(replacement_collection, old_contents, file_line)
36
+ new_contents = file_line.raw_contents
37
+ replacement_collection << Replacement.generate(old_contents, new_contents) unless old_contents == new_contents
38
+ end
39
+
40
+ def self.update_according_to_sugestion(integer_input, applicable_replacements, file_line)
41
+ replacement = applicable_replacements[integer_input]
42
+ new_contents = replacement.suggest(file_line.raw_contents)
43
+ file_line.update_filesystem!(new_contents)
44
+ end
45
+
46
+ def self.edit_with_vim!(file_line, pattern)
47
+ system "vim +#{file_line.number} #{file_line.path} -c '#{"/"+pattern}' -c 'normal n' -c 'normal N' -c 'normal zz'"
48
+ end
49
+
50
+ end
@@ -0,0 +1,39 @@
1
+ class Replacement
2
+ attr_reader :to_replace, :new_text
3
+
4
+ def initialize(to_replace, new_text)
5
+ @to_replace = to_replace
6
+ @new_text = new_text
7
+ end
8
+
9
+ def self.suggestions(replacements, to_change)
10
+ replacements.map { |replacement| replacement.suggest(to_change) }.uniq.compact
11
+ end
12
+
13
+ def self.generate(before, after)
14
+ leading_same_characters_count = (0..before.length).to_a.find do |index|
15
+ before[index] != after[index]
16
+ end
17
+
18
+ trailing_same_characters_count = (0..before.length).to_a.find do |index|
19
+ before[before.length - index - 1] != after[after.length - index - 1]
20
+ end
21
+
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)
24
+
25
+ Replacement.new(to_replace, new_text)
26
+ end
27
+
28
+ def suggest(to_change)
29
+ if to_change.match(to_replace)
30
+ to_change.gsub(to_replace, new_text)
31
+ end
32
+ end
33
+
34
+ private
35
+
36
+ def self.drop_characters(subject, leading, trailing)
37
+ subject[leading...(subject.size - trailing)]
38
+ end
39
+ end
@@ -0,0 +1,9 @@
1
+ class ReplacementCollection < Array
2
+ def applicable_replacements(line_contents)
3
+ select do |replacement|
4
+ line_contents.match(replacement.to_replace)
5
+ end
6
+ end
7
+ end
8
+
9
+
metadata ADDED
@@ -0,0 +1,85 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rbname
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Wai Lee Chin Feman
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-11-21 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: colorize
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ description: It makes stupid suggestions
47
+ email: skatenerd@gmail.com
48
+ executables:
49
+ - rbname
50
+ extensions: []
51
+ extra_rdoc_files: []
52
+ files:
53
+ - lib/change_prompt.rb
54
+ - lib/file_line.rb
55
+ - lib/file_line_presenter.rb
56
+ - lib/main.rb
57
+ - lib/replacement.rb
58
+ - lib/replacement_collection.rb
59
+ - bin/rbname
60
+ homepage: http://github.com/skatenerd
61
+ licenses:
62
+ - MIT
63
+ post_install_message:
64
+ rdoc_options: []
65
+ require_paths:
66
+ - lib
67
+ required_ruby_version: !ruby/object:Gem::Requirement
68
+ none: false
69
+ requirements:
70
+ - - ! '>='
71
+ - !ruby/object:Gem::Version
72
+ version: '0'
73
+ required_rubygems_version: !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ! '>='
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ requirements: []
80
+ rubyforge_project:
81
+ rubygems_version: 1.8.25
82
+ signing_key:
83
+ specification_version: 3
84
+ summary: CLI Find/Replace
85
+ test_files: []