sq_ruby_grep 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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 7ecbae1d7f5407a9164e0945f0b9a4c2597abb97
4
+ data.tar.gz: 43c21842405cf2548d04417a3481d2b2ddba8b57
5
+ SHA512:
6
+ metadata.gz: 9822f2472d575e7caa1ccb8daa64fe5f3abed5ef394598aef434016452006ecac6cd63bbada25acbd8cbbe25a6cb851d74a8dd672b7962c78a777dc372886e2f
7
+ data.tar.gz: f49524ba86648e4fb8797e5d8be4572b6cd154ae71cf60cf9284c597c385300667ff7fef89f68c3e7eb8b40374e16b0e9bc16cd15f8c4976018543d6753a6f5c
data/.gitignore ADDED
@@ -0,0 +1,15 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
15
+ .idea
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --require spec_helper
3
+ -fdoc
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in grep_challenge.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 coolelvis
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,34 @@
1
+ # SqRubyGrep
2
+
3
+ It just the training project for SQ interview. Forget it! :)
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```
10
+ gem 'sq_ruby_grep'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install sq_ruby_grep
20
+
21
+ ## Usage
22
+
23
+ $ sq_ruby_grep [FILE] [options]
24
+
25
+ -e, --regex=PATTERN Use PATTERN as the pattern.
26
+
27
+ -A, --after-context=NUM Print NUM lines of trailing context after matching lines.
28
+
29
+ -B, --before-context=NUM Print NUM line of leading context before matching lines.
30
+
31
+ -c, --colorize Colorize matches
32
+
33
+ -h, --help Prints this help
34
+
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
7
+
8
+ require "bundler/gem_tasks"
9
+
data/bin/sq_ruby_grep ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ lib = File.expand_path('../../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'sq_ruby_grep'
6
+
7
+ SqRubyGrep.run
data/example.rb ADDED
@@ -0,0 +1,12 @@
1
+ lib = File.expand_path('../lib', __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require 'sq_ruby_grep'
4
+
5
+ SqRubyGrep.grep(file_path:'test/fixtures/text.txt', pattern: /non/, after_lines: 2, before_lines: 2, colorize: true).each do |result|
6
+ p '------------'
7
+ puts result.before_context
8
+ puts '---' + result.match_line
9
+ puts result.after_context
10
+ p '------------'
11
+ end
12
+
@@ -0,0 +1,47 @@
1
+ require 'optparse'
2
+
3
+ module SqRubyGrep
4
+ class Parser
5
+ def self.parse(options)
6
+ args = Hash.new
7
+
8
+ opt_parser = OptionParser.new do |opts|
9
+ opts.banner = 'RubyGrep searches the named input FILE for lines containing a match to the given PATTERN.'
10
+ opts.banner = 'Usage: ruby_grep [FILE] [options]'
11
+
12
+ opts.on('-e PATTERN', '--regex=PATTERN', String, 'Use PATTERN as the pattern.') do |pattern|
13
+ args[:pattern] = pattern
14
+ end
15
+
16
+ opts.on('-A NUM', '--after-context=NUM', Integer, 'Print NUM lines of trailing context after matching lines.') do |n|
17
+ args[:after_lines] = n
18
+ end
19
+
20
+ opts.on('-B NUM', '--before-context=NUM', Integer, 'Print NUM line of leading context before matching lines.') do |n|
21
+ args[:before_lines] = n
22
+ end
23
+
24
+ opts.on('-c', '--colorize', 'Colorize matches') do
25
+ args[:colorize] = true
26
+ end
27
+
28
+ opts.on('-h', '--help', 'Prints this help') do
29
+ puts opts
30
+ exit
31
+ end
32
+
33
+ end
34
+
35
+ opt_parser.parse!(options)
36
+
37
+ args[:file_path] = ARGV.shift
38
+
39
+ if args[:file_path].to_s.empty? || args[:pattern].to_s.empty?
40
+ puts opt_parser
41
+ exit
42
+ end
43
+
44
+ return args
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,19 @@
1
+ class RingBuffer < Array
2
+ attr_reader :max_size
3
+
4
+ def initialize(max_size, enum = nil)
5
+ @max_size = max_size
6
+ enum.each { |e| self << e } if enum
7
+ end
8
+
9
+ def <<(el)
10
+ if self.size < @max_size || @max_size.nil?
11
+ super
12
+ else
13
+ self.shift
14
+ self.push(el)
15
+ end
16
+ end
17
+
18
+ alias :push :<<
19
+ end
@@ -0,0 +1,3 @@
1
+ module SqRubyGrep
2
+ VERSION = "0.0.3"
3
+ end
@@ -0,0 +1,70 @@
1
+ require 'sq_ruby_grep/version'
2
+ require 'sq_ruby_grep/ring_buffer'
3
+ require 'sq_ruby_grep/parser'
4
+
5
+ module SqRubyGrep
6
+
7
+ Result = Struct.new(:match_line, :before_context, :after_context)
8
+
9
+ def self.run
10
+ resuts = grep(Parser.parse(ARGV))
11
+
12
+ resuts.each do |result|
13
+ puts '--'
14
+ puts result.before_context
15
+ puts result.match_line
16
+ puts result.after_context
17
+ end
18
+
19
+ puts '----'
20
+ puts "Line count: #{resuts.count}"
21
+ end
22
+
23
+ def self.grep(file_path:, pattern:, after_lines: 0, before_lines: 0, colorize: false)
24
+ results = []
25
+
26
+ buffer = RingBuffer.new(after_lines + before_lines + 1)
27
+ current_position = 0
28
+
29
+ File.open(file_path, 'r') do |file|
30
+ file.each_line do |line|
31
+ buffer << line
32
+ current_position += 1
33
+
34
+ offset = buffer.size - after_lines - 1
35
+
36
+ if current_position > after_lines && buffer[offset].match(pattern)
37
+ match_line = buffer[offset]
38
+ match_line = self.colorize(match_line, pattern) if colorize
39
+
40
+ result = Result.new(match_line, buffer[0, offset], buffer[offset + 1, after_lines])
41
+
42
+ results << result
43
+ end
44
+ end
45
+
46
+ offset = (buffer.size - after_lines) > 0 ? (buffer.size - after_lines) : 0
47
+
48
+ buffer[offset, after_lines].each_with_index do |line, i|
49
+ if line.match(pattern)
50
+ before_offset = (offset + i) > before_lines ? (offset + i - before_lines) : 0
51
+ _before_lines = (offset + i) > before_lines ? before_lines : (offset + i)
52
+
53
+ line = colorize(line, pattern) if colorize
54
+
55
+ result = Result.new(line, buffer[before_offset, _before_lines], buffer[i + offset + 1, after_lines])
56
+
57
+ results << result
58
+ end
59
+ end
60
+
61
+ end
62
+
63
+ results
64
+ end
65
+
66
+ def self.colorize(string, pattern)
67
+ string.gsub(/(#{pattern})/, "\e[0;33m\\1\033[0m")
68
+ end
69
+
70
+ end
@@ -0,0 +1,2 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+ require 'sq_ruby_grep'
@@ -0,0 +1,137 @@
1
+ require 'spec_helper'
2
+
3
+ describe SqRubyGrep do
4
+ context 'when grep file' do
5
+ let(:lines) { lines = File.readlines path }
6
+ let(:path) { 'test/fixtures/lines.txt' }
7
+ let(:after_lines) { 3 }
8
+ let(:before_lines) { 3 }
9
+ let(:result) { SqRubyGrep.grep(file_path:path, pattern: pattern, before_lines: before_lines, after_lines: after_lines).first }
10
+ let(:pattern) { /#{target_line} line/ }
11
+
12
+ context 'when the target line at the middle' do
13
+
14
+ let(:target_line) { 6 }
15
+
16
+ it 'before_context is valid' do
17
+ expect(result.before_context).to eql lines[target_line - before_lines - 1 , before_lines]
18
+ end
19
+
20
+ it 'match_line is valid' do
21
+ expect(result.match_line).to eql lines[target_line - 1]
22
+ end
23
+
24
+ it 'after_context is valid' do
25
+ expect(result.after_context).to eql lines[target_line, after_lines]
26
+ end
27
+
28
+ context 'when after_lines is out scope of file' do
29
+ let(:after_lines) { 30 }
30
+
31
+ it 'after_context is valid' do
32
+ expect(result.after_context).to eql lines[target_line, after_lines]
33
+ end
34
+
35
+ it 'before_context is valid' do
36
+ expect(result.before_context).to eql lines[target_line - before_lines - 1 , before_lines]
37
+ end
38
+ end
39
+
40
+ context 'when before_lines is out scope of file' do
41
+ let(:before_lines) { 30 }
42
+
43
+ it 'after_context is valid' do
44
+ expect(result.after_context).to eql lines[target_line, after_lines]
45
+ end
46
+
47
+ it 'before_context is valid' do
48
+ expect(result.before_context).to eql lines[0 , target_line - 1]
49
+ end
50
+ end
51
+
52
+ end
53
+
54
+ context 'when the target line at the end' do
55
+ let(:target_line) { 12 }
56
+
57
+ it 'before_context is valid' do
58
+ expect(result.before_context).to eql lines[target_line - before_lines - 1 , before_lines]
59
+ end
60
+
61
+ it 'match_line is valid' do
62
+ expect(result.match_line).to eql lines[target_line - 1]
63
+ end
64
+
65
+ it 'after_context is valid' do
66
+ expect(result.after_context).to eql lines[target_line, after_lines]
67
+ end
68
+
69
+ context 'when after_lines is out scope of file' do
70
+ let(:after_lines) { 30 }
71
+
72
+ it 'after_context is valid' do
73
+ expect(result.after_context).to eql lines[target_line, after_lines]
74
+ end
75
+
76
+ it 'before_context is valid' do
77
+ expect(result.before_context).to eql lines[target_line - before_lines - 1 , before_lines]
78
+ end
79
+ end
80
+
81
+ context 'when before_lines is out scope of file' do
82
+ let(:before_lines) { 30 }
83
+
84
+ it 'after_context is valid' do
85
+ expect(result.after_context).to eql lines[target_line, after_lines]
86
+ end
87
+
88
+ it 'before_context is valid' do
89
+ expect(result.before_context).to eql lines[0 , target_line - 1]
90
+ end
91
+ end
92
+
93
+ end
94
+
95
+ context 'when the target line at the beginning ' do
96
+ let(:target_line) { 2 }
97
+
98
+ it 'before_context is valid' do
99
+ expect(result.before_context).to eql lines[0, 1]
100
+ end
101
+
102
+ it 'match_line is valid' do
103
+ expect(result.match_line).to eql lines[target_line - 1]
104
+ end
105
+
106
+ it 'after_context is valid' do
107
+ expect(result.after_context).to eql lines[target_line, after_lines]
108
+ end
109
+
110
+ context 'when after_lines is out scope of file' do
111
+ let(:after_lines) { 30 }
112
+
113
+ it 'after_context is valid' do
114
+ expect(result.after_context).to eql lines[target_line, after_lines]
115
+ end
116
+
117
+ it 'before_context is valid' do
118
+ expect(result.before_context).to eql lines[0, target_line - 1]
119
+ end
120
+ end
121
+
122
+ context 'when before_lines is out scope of file' do
123
+ let(:before_lines) { 30 }
124
+
125
+ it 'after_context is valid' do
126
+ expect(result.after_context).to eql lines[target_line, after_lines]
127
+ end
128
+
129
+ it 'before_context is valid' do
130
+ expect(result.before_context).to eql lines[0 , target_line - 1]
131
+ end
132
+ end
133
+ end
134
+
135
+ end
136
+
137
+ end
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'sq_ruby_grep/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "sq_ruby_grep"
8
+ spec.version = SqRubyGrep::VERSION
9
+ spec.authors = ["coolelvis"]
10
+ spec.email = ["elvisplus2@gmail.com"]
11
+ spec.summary = %q{It just the training project for SQ interview.}
12
+ spec.description = %q{It just the training project for SQ interview.}
13
+ spec.homepage = "https://github.com/CoolElvis/ruby_grep.git"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.required_ruby_version = '~> 2.1.3'
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.7"
24
+ spec.add_development_dependency "rake", "~> 10.0"
25
+ end
@@ -0,0 +1,13 @@
1
+ 1 line
2
+ 2 line
3
+ 3 line
4
+ 4 line
5
+ 5 line
6
+ 6 line
7
+ 7 line
8
+ 8 line
9
+ 9 line
10
+ 10 line
11
+ 11 line
12
+ 12 line
13
+ 13 line
@@ -0,0 +1,13 @@
1
+ line 1 Integer fermentum sem non viverra malesuada.non
2
+ line 2 Vivamus id tortor non metus ornare rutrum.
3
+ line 3 Curabitur vel ex id tellus faucibus lobortis.
4
+ line 4 Cras aliquet orci at accumsan rhoncus.
5
+ line 5 Cras at justo ut risus rutrum posuere.
6
+ line 6 Mauris sit amet eros sed risus accumsan vulputate.
7
+ line 7 Aenean id nulla tempus, blandit nunc lacinia, tincidunt odio.
8
+ line 8 Vestibulum non est eu tortor ullamcorper scelerisque.
9
+ line 9 Duis pharetra nisl at nibh feugiat varius.
10
+ line 10 Praesent vitae magna feugiat lectus aliquet hendrerit ac ut urna.
11
+ line 11 Vivamus sed arcu sit amet orci auctor maximus.
12
+ line 12 Pellentesque vitae purus sagittis, ultrices urna at, porttitor eros.
13
+ line 13 Curabitur id metus egestas, bibendum nisi id, aliquet lacus.
metadata ADDED
@@ -0,0 +1,94 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sq_ruby_grep
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.3
5
+ platform: ruby
6
+ authors:
7
+ - coolelvis
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-04-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.7'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ description: It just the training project for SQ interview.
42
+ email:
43
+ - elvisplus2@gmail.com
44
+ executables:
45
+ - sq_ruby_grep
46
+ extensions: []
47
+ extra_rdoc_files: []
48
+ files:
49
+ - ".gitignore"
50
+ - ".rspec"
51
+ - Gemfile
52
+ - LICENSE.txt
53
+ - README.md
54
+ - Rakefile
55
+ - bin/sq_ruby_grep
56
+ - example.rb
57
+ - lib/sq_ruby_grep.rb
58
+ - lib/sq_ruby_grep/parser.rb
59
+ - lib/sq_ruby_grep/ring_buffer.rb
60
+ - lib/sq_ruby_grep/version.rb
61
+ - spec/spec_helper.rb
62
+ - spec/sq_ruby_grep_spec.rb
63
+ - sq_ruby_grep.gemspec
64
+ - test/fixtures/lines.txt
65
+ - test/fixtures/text.txt
66
+ homepage: https://github.com/CoolElvis/ruby_grep.git
67
+ licenses:
68
+ - MIT
69
+ metadata: {}
70
+ post_install_message:
71
+ rdoc_options: []
72
+ require_paths:
73
+ - lib
74
+ required_ruby_version: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - "~>"
77
+ - !ruby/object:Gem::Version
78
+ version: 2.1.3
79
+ required_rubygems_version: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ requirements: []
85
+ rubyforge_project:
86
+ rubygems_version: 2.2.2
87
+ signing_key:
88
+ specification_version: 4
89
+ summary: It just the training project for SQ interview.
90
+ test_files:
91
+ - spec/spec_helper.rb
92
+ - spec/sq_ruby_grep_spec.rb
93
+ - test/fixtures/lines.txt
94
+ - test/fixtures/text.txt