core: fix typos in union_find
[nit.git] / lib / core / text / string_search.nit
index 22d8af3..7648816 100644 (file)
@@ -112,12 +112,12 @@ class BM_Pattern
                var j = from
                while j < n - m + 1 do
                        var i = m - 1 # Cursor in the pattern
-                       while i >= 0 and _motif.chars[i] == s.chars[i + j] do i -= 1
+                       while i >= 0 and _motif[i] == s[i + j] do i -= 1
                        if i < 0 then
                                return j
                        else
                                var gs = _gs[i] # Good shift
-                               var bc = bc(s.chars[i+j]) - m + 1 + i # Bad char
+                               var bc = bc(s[i+j]) - m + 1 + i # Bad char
                                # Both are true, do move to the best
                                if gs > bc then
                                        j += gs
@@ -237,21 +237,62 @@ end
 # Matches are a part of a `Text` found by a `Pattern`.
 class Match
        # The base string matched
+       #
+       # ~~~
+       # var m = "hello world".search("lo")
+       # assert m.string == "hello world"
+       # ~~~
        var string: String
 
        # The starting position in the string
+       #
+       # ~~~
+       # var m = "hello world".search("lo")
+       # assert m.from == 3
+       # ~~~
        var from: Int
 
        # The length of the matching part
+       #
+       # ~~~
+       # var m = "hello world".search("lo")
+       # assert m.length == 2
+       # ~~~
        var length: Int
 
        # The position of the first character just after the matching part.
        # May be out of the base string
+       #
+       # ~~~
+       # var m = "hello world".search("lo")
+       # assert m.after == 5
+       # ~~~
        fun after: Int do return from + length
 
        # The contents of the matching part
+       #
+       # ~~~
+       # var m = "hello world".search("lo")
+       # assert m.to_s == "lo"
+       # ~~~
        redef fun to_s do return string.substring(from,length)
 
+       # The content of `string` before the match
+       #
+       # ~~~
+       # var m = "hello world".search("lo")
+       # assert m.text_before == "hel"
+       # ~~~
+       fun text_before: String do return string.substring(0, from)
+
+       # The content of `string` after the match
+       #
+       # ~~~
+       # var m = "hello world".search("lo")
+       # assert m.text_after == " world"
+       # ~~~
+       fun text_after: String do return string.substring_from(after)
+
        init
        do
                assert positive_length: length >= 0
@@ -267,7 +308,7 @@ redef class Char
        do
                var stop = s.length
                while from < stop do
-                       if s.chars[from] == self then return from
+                       if s[from] == self then return from
                        from += 1
                end
                return -1
@@ -293,7 +334,7 @@ redef class Text
                var stop = s.length - length + 1
                while from < stop do
                        var i = length - 1
-                       while i >= 0 and self.chars[i] == s.chars[i + from] do i -= 1
+                       while i >= 0 and self[i] == s[i + from] do i -= 1
                        # Test if we found
                        if i < 0 then return from
                        # Not found so try next one
@@ -312,20 +353,20 @@ redef class Text
                end
        end
 
-       # Search the first occurence of the pattern `p`.
+       # Search the first occurence of `pattern`.
        # Return null if not found.
        #
        #     assert "I say hello to the world!".search("hello").from  == 6
        #     assert "I say goodbye to the world!".search("hello")     == null
-       fun search(p: Pattern): nullable Match do return p.search_in(self, 0)
+       fun search(pattern: Pattern): nullable Match do return pattern.search_in(self, 0)
 
-       # Search the first occurence of the pattern `p` after `from`.
+       # Search the first occurence of `pattern` after `from`.
        # The search starts at `from`.
        # Return null if not found.
        #
        #     assert "I say hello to the world!".search_from("hello",4).from  == 6
        #     assert "I say hello to the world!".search_from("hello",7)       == null
-       fun search_from(p: Pattern, from: Int): nullable Match do return p.search_in(self, from)
+       fun search_from(pattern: Pattern, from: Int): nullable Match do return pattern.search_in(self, from)
 
        # Search the last occurence of the text `t`.
        #
@@ -358,36 +399,67 @@ redef class Text
                return null
        end
 
-       # Search all occurrences of p into self.
+       # Extract a given prefix, if any.
+       #
+       # ~~~
+       # var p = "hello world".prefix("hello")
+       # assert p != null
+       # assert p.text_after == " world"
+       # ~~~
+       fun prefix(t: Text): nullable Match do
+               var len = t.length
+               if substring(0, len) == t then
+                       return new Match(self.to_s, 0, len)
+               end
+               return null
+       end
+
+       # Extract a given suffix, if any.
+       #
+       # ~~~
+       # var p = "hello world".suffix("world")
+       # assert p != null
+       # assert p.text_before == "hello "
+       # ~~~
+       fun suffix(t: Text): nullable Match do
+               var len = t.length
+               var from = length - len
+               if substring(from, len) == t then
+                       return new Match(self.to_s, from, len)
+               end
+               return null
+       end
+
+       # Search all occurrences of `pattern` into self.
        #
        #     var a = new Array[Int]
        #     for i in "hello world".search_all('o') do
        #         a.add(i.from)
        #     end
        #     assert a         ==  [4, 7]
-       fun search_all(p: Pattern): Array[Match] do return p.search_all_in(self)
+       fun search_all(pattern: Pattern): Array[Match] do return pattern.search_all_in(self)
 
-       # Split `self` using `p` as separator.
+       # Split `self` using `pattern` as separator.
        #
        #     assert "hello world".split('o')          ==  ["hell", " w", "rld"]
-       fun split(p: Pattern): Array[String]
+       fun split(pattern: Pattern): Array[String]
        do
-               var matches = p.split_in(self)
+               var matches = pattern.split_in(self)
                var res = new Array[String].with_capacity(matches.length)
                for m in matches do res.add(m.to_s)
                return res
        end
 
        # @deprecated alias for `split`
-       fun split_with(p: Pattern): Array[String] do return self.split(p)
+       fun split_with(pattern: Pattern): Array[String] do return self.split(pattern)
 
-       # Split `self` on the first `=`
+       # Split `self` on the first occurence of `pattern`
        #
        #     assert "hello".split_once_on('l') == ["he", "lo"]
        #     assert "a, b, c, d, e".split_once_on(", ") == ["a", "b, c, d, e"]
-       fun split_once_on(p: Pattern): Array[SELFTYPE]
+       fun split_once_on(pattern: Pattern): Array[SELFTYPE]
        do
-               var m = p.search_in(self, 0)
+               var m = pattern.search_in(self, 0)
                var res = new Array[SELFTYPE]
                if m == null then
                        res.add self
@@ -398,13 +470,25 @@ redef class Text
                return res
        end
 
-       # Replace all occurences of a pattern with a string
+       # Replace all occurrences of `pattern` with `string`
+       #
+       #     assert "hlelo".replace("le", "el") == "hello"
+       #     assert "hello".replace('l', "")    == "heo"
        #
-       #     assert "hlelo".replace("le", "el")             ==  "hello"
-       #     assert "hello".replace('l', "")        ==  "heo"
-       fun replace(p: Pattern, string: SELFTYPE): String
+       #     var t: Text = "hello"
+       #     assert t.replace("hello", new FlatBuffer) == ""
+       fun replace(pattern: Pattern, string: Text): String
        do
-               return self.split_with(p).join(string)
+               return self.split_with(pattern).join(string)
+       end
+
+       # Replace the first occurrence of `pattern` with `string`
+       #
+       #     assert "hlelo".replace_first("le", "el") == "hello"
+       #     assert "hello".replace_first('l', "")    == "helo"
+       fun replace_first(pattern: Pattern, string: Text): String
+       do
+               return self.split_once_on(pattern).join(string)
        end
 
        # Does `self` contains at least one instance of `pattern`?
@@ -413,4 +497,11 @@ redef class Text
        #     assert "hello".has("ll")
        #     assert not "hello".has("lll")
        fun has(pattern: Pattern): Bool do return pattern.is_in(self)
+
+       # Returns a copy of `self` minus all occurences of `pattern`
+       #
+       #     assert "__init__".remove_all('_') == "init"
+       #     assert "abcd".remove_all("bc") == "ad"
+       #     assert "abcd".remove_all("[ad]".to_re) == "bc"
+       fun remove_all(pattern: Pattern): String do return split(pattern).join
 end