will_scan_string 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.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in will_scan_string.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,20 @@
1
+ Will scan string
2
+ ================
3
+ Multi-pass string replacement has always been fun. I don't know any good way to
4
+ perform multiple replacements on strings, so I made this minor gem.
5
+
6
+ Usage
7
+ -----
8
+ Just don't use this, but if you're curious: Check `spec/lib/will_scan_string`
9
+ for examples and features.
10
+
11
+ Notes
12
+ -----
13
+ This gem is buggy and nowhere friendly to use. It's designed for personal use
14
+ and is very experimental. It uses various hacks to combine multiple regular
15
+ expressions to a single big-ass regular expression and it therefore is quite
16
+ common for 2 regular expressions conflicting each other.
17
+
18
+ Known regexp conflicts and issues
19
+ ---------------------------------
20
+ - The gem does not support named capture groups whatsoever.
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require 'bundler/gem_tasks'
@@ -0,0 +1,12 @@
1
+ module WillScanString
2
+ module RegexpTraits
3
+ CAPTURE_GROUP_PATTERN = /(?<!\\)\((?:\?(?:<([a-z]+)\>|'([a-z]+)')|(?!\?))/i
4
+
5
+ def capture_groups
6
+ c = 0
7
+ r = []
8
+ source.scan(CAPTURE_GROUP_PATTERN) { r.push $+.present? ? $+.to_sym : c+=1 }
9
+ r
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,51 @@
1
+ module WillScanString
2
+ class StringScanner
3
+ def register_replacement( pattern, replacement )
4
+ @replacements = [] if @replacements.nil?
5
+ @replacements << [ pattern, replacement, @replacements.last.present? ? @replacements.last[2] + (@replacements.last[0].is_a?(Regexp) ? @replacements.last[0].capture_groups.length : 0) + 1 : 0 ]
6
+ @replacements_regexp = nil
7
+ end
8
+
9
+ def replace( string )
10
+ string.gsub(replacement_regexp) do
11
+ m, r = *get_match_and_replacement( $~ )
12
+ execute_replacement_with_match r, m
13
+ end
14
+ end
15
+
16
+ protected
17
+ def get_match_and_replacement( m )
18
+ m = m.to_a.tap{ |m| m.shift }
19
+ i = m.find_index{ |v| v.present? }
20
+ r = find_replacement_by_index(i)
21
+ cps = [0] + (r[0].is_a?(Regexp) ? r[0].capture_groups : [])
22
+ m = m[i, cps.length]
23
+ [m, r[1]]
24
+ end
25
+
26
+ def execute_replacement_with_match( r, m )
27
+ r.is_a?(Proc) ? r.call(*m) : r.to_s
28
+ end
29
+
30
+ def find_replacement_by_index( i )
31
+ @replacements.find{ |r| r[2] == i }
32
+ end
33
+
34
+ def replacement_regexp
35
+ @replacements_regexp ||= reconstruct_replacement_regexp
36
+ end
37
+
38
+ private
39
+ def reconstruct_replacement_regexp
40
+ additional_offset = 1
41
+ pattern = @replacements.map(&:first).map{ |pat|
42
+ cpsc = pat.is_a?(Regexp) ? pat.capture_groups.length : 0
43
+ pat = pat.is_a?(Regexp) ? pat.source : Regexp.escape(pat.to_s)
44
+ pat.gsub!(/(?<!\\\\)(?<=\\)(\d+)/){ $1.to_i + additional_offset }
45
+ additional_offset += 1 + cpsc
46
+ "(#{pat})"
47
+ }.join "|"
48
+ /(?:#{pattern})/
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,3 @@
1
+ module WillScanString
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,7 @@
1
+ require "will_scan_string/version"
2
+ require "will_scan_string/string_scanner"
3
+ require "will_scan_string/regexp_traits"
4
+
5
+ module WillScanString
6
+ Regexp.send( :include, RegexpTraits )
7
+ end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper.rb'
2
+
3
+ describe WillScanString::RegexpTraits do
4
+ it "should match regular capture groups" do
5
+ /(a)/.capture_groups.should eql [ 1 ]
6
+ end
7
+
8
+ it "should not match escaped capture groups" do
9
+ /\(\)/.capture_groups.should eql []
10
+ end
11
+
12
+ it "should match named capture groups with less-than & greater-than characters" do
13
+ /(?<a>a)/.capture_groups.should eql [ :a ]
14
+ end
15
+
16
+ it "should match named capture groups with single quotes" do
17
+ /(?'a'a)/.capture_groups.should eql [ :a ]
18
+ end
19
+
20
+ it "should match nested regular capture groups" do
21
+ /(a(b))/.capture_groups.should eql [ 1, 2 ]
22
+ end
23
+
24
+ it "should ignore non-capture groups" do
25
+ /(?:a)/.capture_groups.should eql []
26
+ end
27
+
28
+ it "should ignore look-aheads and look-behinds" do
29
+ /(?=)/.capture_groups.should eql []
30
+ /(?!)/.capture_groups.should eql []
31
+ /(?<=)/.capture_groups.should eql []
32
+ /(?<!)/.capture_groups.should eql []
33
+ end
34
+
35
+ it "should match the capture groups in my bbcode gem's regular expressions" do
36
+ /\[(\/?)([a-z0-9_-]*)(\s*=?(?:(?:\s*(?:(?:[a-z0-9_-]+)|(?<=\=))\s*[:=]\s*)?(?:"[^"\\]*(?:\\[\s\S][^"\\]*)*"|'[^'\\]*(?:\\[\s\S][^'\\]*)*'|[^\]\s,]+|(?<=,)(?=\s*,))\s*,?\s*)*)\]/i.capture_groups.should \
37
+ eql [ 1, 2, 3 ]
38
+ /(?:\s*(?:([a-z0-9_-]+)|^)\s*[:=]\s*)?("[^"\\]*(?:\\[\s\S][^"\\]*)*"|'[^'\\]*(?:\\[\s\S][^'\\]*)*'|[^\]\s,]+|(?<=,)(?=\s*,))\s*,?/i.capture_groups.should \
39
+ eql [ 1, 2 ]
40
+ end
41
+ end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper.rb'
2
+
3
+ describe WillScanString::StringScanner do
4
+ it "should perform a regular replacement" do
5
+ ss = WillScanString::StringScanner.new
6
+ ss.register_replacement ":)", "HAPPY"
7
+ ss.replace(":)").should eql "HAPPY"
8
+ end
9
+
10
+ it "should perform a regexp replacement with a capture group" do
11
+ ss = WillScanString::StringScanner.new
12
+ ss.register_replacement %r{<([a-z]+)>.*?</\1>}, ->(_, tagname){ "#{tagname}" }
13
+ ss.replace("<strong>hi!</strong>").should eql("strong")
14
+ end
15
+
16
+ it "should not replace replaced strings" do
17
+ ss = WillScanString::StringScanner.new
18
+ ss.register_replacement ":)", %{<img src="happy.png" alt=":)" title=":)">}
19
+ ss.register_replacement "<", "&lt;"
20
+ ss.register_replacement ">", "&gt;"
21
+ ss.register_replacement "\"", "&quot;"
22
+ ss.register_replacement "&", "&amp;"
23
+ ss.replace("& :)").should eql %{&amp; <img src="happy.png" alt=":)" title=":)">}
24
+ end
25
+
26
+ it "should be able to use multiple regular expressions to replace with" do
27
+ ss = WillScanString::StringScanner.new
28
+ ss.register_replacement /(a)(b)/, "AB"
29
+ ss.register_replacement /(c)(d)/, "CD"
30
+ ss.replace("abcd").should eql "ABCD"
31
+ end
32
+ end
@@ -0,0 +1,9 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ require 'active_support/all'
4
+
5
+ require 'will_scan_string'
6
+
7
+ RSpec.configure do |config|
8
+ # some (optional) config here
9
+ end
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "will_scan_string/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "will_scan_string"
7
+ s.version = WillScanString::VERSION
8
+ s.authors = ["Toby Hinloopen"]
9
+ s.email = ["toby@kutcomputers.nl"]
10
+ s.homepage = ""
11
+ s.summary = %q{Gem for string replacements using multiple regular expressions in a single pass.}
12
+ s.description = %q{Gem for string replacements using multiple regular expressions in a single pass.}
13
+
14
+ s.rubyforge_project = "will_scan_string"
15
+
16
+ s.add_development_dependency "rspec", "~> 2.6"
17
+ s.add_dependency "activesupport", "~> 3.0.9"
18
+ s.add_dependency "i18n", "~> 0.5.0"
19
+
20
+ s.files = `git ls-files`.split("\n")
21
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
22
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
23
+ s.require_paths = ["lib"]
24
+ end
metadata ADDED
@@ -0,0 +1,95 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: will_scan_string
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Toby Hinloopen
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-11-04 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: &70303473805000 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '2.6'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *70303473805000
25
+ - !ruby/object:Gem::Dependency
26
+ name: activesupport
27
+ requirement: &70303473803740 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ~>
31
+ - !ruby/object:Gem::Version
32
+ version: 3.0.9
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70303473803740
36
+ - !ruby/object:Gem::Dependency
37
+ name: i18n
38
+ requirement: &70303473802140 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ version: 0.5.0
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *70303473802140
47
+ description: Gem for string replacements using multiple regular expressions in a single
48
+ pass.
49
+ email:
50
+ - toby@kutcomputers.nl
51
+ executables: []
52
+ extensions: []
53
+ extra_rdoc_files: []
54
+ files:
55
+ - .gitignore
56
+ - Gemfile
57
+ - README.md
58
+ - Rakefile
59
+ - lib/will_scan_string.rb
60
+ - lib/will_scan_string/regexp_traits.rb
61
+ - lib/will_scan_string/string_scanner.rb
62
+ - lib/will_scan_string/version.rb
63
+ - spec/lib/will_scan_string/regexp_traits_spec.rb
64
+ - spec/lib/will_scan_string/string_scanner_spec.rb
65
+ - spec/spec_helper.rb
66
+ - will_scan_string.gemspec
67
+ homepage: ''
68
+ licenses: []
69
+ post_install_message:
70
+ rdoc_options: []
71
+ require_paths:
72
+ - lib
73
+ required_ruby_version: !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ! '>='
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ required_rubygems_version: !ruby/object:Gem::Requirement
80
+ none: false
81
+ requirements:
82
+ - - ! '>='
83
+ - !ruby/object:Gem::Version
84
+ version: '0'
85
+ requirements: []
86
+ rubyforge_project: will_scan_string
87
+ rubygems_version: 1.8.11
88
+ signing_key:
89
+ specification_version: 3
90
+ summary: Gem for string replacements using multiple regular expressions in a single
91
+ pass.
92
+ test_files:
93
+ - spec/lib/will_scan_string/regexp_traits_spec.rb
94
+ - spec/lib/will_scan_string/string_scanner_spec.rb
95
+ - spec/spec_helper.rb