T Regx Versions Save

Simple library for regular expressions in PHP.

0.13.5

2 years ago

😎 T-Regx The Dinosaur is really proud to announce its release 0.13.5! We're coming to giga-big-release of 1.0.0 with big steps!

The detailed list of changes is in ChangeLog.md.

  • Breaking changes
    • We refactored Pattern::pcre(), so it's more concise, and doesn't use builder() method.
  • Features
    • Added Pattern::alteration() which allows building Pattern with just an alteration group.
      • For example Pattern::alteration(['foo', 'bar']) is /(?:foo|bar)/
    • Added Pattern::template()->alteration()
  • Bug fixes
    • Fixed a bug, where passing false as an alteration value didn't throw \InvalidArgumentException.

The detailed list of changes is also in ChangeLog.md.

Rawrrrr!

0.13.8

2 years ago

😎 T-Regx The Dinosaur is really proud to announce its release 0.13.8! We're coming to giga-big-release of 1.0.0 with big steps!

In this release, we took a look at how PHP parses the patterns, before passing them to PCRE, and it shocked us! that it does so negligent. Perfectly valid patterns are reported as invalid by PHP, because of improper parsing.

Example:

  • Pattern /\c\/ is marked as invalid in PHP. So is /\Q\/ and other valid patterns (like comment groups and comments in exnteded mode)

In this release we handled this bug, so that pattern(), Pattern::of(), Pattern::mask() and Pattern::template() correctly understand these patterns. We parse the whole pattern, and we guess if it would be reported by PHP, and we fill it with padding, to make it digest by PHP, while keeping the meritoric value. For example, T-Regx changes \c\ to \c\{1} which is the same thing in regular expression, but PHP reports the first as invalid.

You, as a user of T-Regx don't have to worry about it at all. Simply use you regular expression, and let T-Regx handle it for you.

The detailed list of changes is in ChangeLog.md.

  • Bug fixes
    • Fixed a bug, where using Pattern::inject('()(?)') failed parsing
    • Fixed a bug, where using unicode in groups failed parsing
    • Fixed a bug, where using pattern in unclosed comment group failed parsing
    • Added workaround for PHP inconsistencies ragarding backslash in patterns:
      • PHP reports \c\ as invalid entity, all T-Regx entry points correctly recognize it as valid
      • PHP reports \Q\ as invalid entity, all T-Regx entry points correctly recognize it as valid
      • PHP reports (?#\ as invalid entity, all T-Regx entry points correctly recognize it as valid
      • PHP reports #\ as invalid entity in Xtended mode, all T-Regx entry points correctly recognize it as valid
  • Features
    • Added Optional.map(), which resembles Java 8 optionals.
    • pattern()->match()->asInt()->findFirst()->orElse() receive NotMatched argument
    • pattern()->match()->asInt()->findNth()->orElse() receive NotMatched argument
    • pattern()->match()->offsets()->findFirst()->orElse() receive NotMatched argument
    • pattern()->match()->offsets()->findNth()->orElse() receive NotMatched argument

The detailed list of changes is also in ChangeLog.md.

Rawrrrr!

0.14.0

2 years ago

😎 T-Regx The Dinosaur is proud to announce its release 0.14.0! That's a quick release with the update of a few names regarding Pattern::compose(). allMatch() wasn't a really good name, was it?

The detailed list of changes is also in ChangeLog.md.

  • Breaking changes

    • Name Pattern::compose()->allMatch() was horrible, we renamed it to testAll()
    • Name Pattern::compose()->anyMatches() wasn't good either, we renamed it to testAny()

    So, if you want to test a composite pattern, you just type Pattern::compose()->test and choose Any() or All() :)

    • Renamed Pattern::compose()->chainedRemove() to prune(), because "chained remove" was basically prune, just with a more scary name 😨
  • Features

    • Added Pattern::compose()->failAny(), returning true if any of the patterns didn't match the subject
    • Added Pattern::compose()->failAll(), returning true if all the patterns didn't match the subject

    Same as before, if you'd like to check if your composite pattern fails a subject, just type Pattern::compose()->fail and choose Any() or All() :)

The detailed list of changes is also in ChangeLog.md.

Rawrrrr!

0.15.0

2 years ago

😎 T-Regx The Dinosaur is really proud to announce its release 0.15.0! We're coming to giga-big-release of 1.0.0 with really big steps!

This time, we look around our dinosaur friendly projects, and we noticed that most users use Pattern::template() with just one call, and need to call build() at the end. That's not very elegant, T-Regx the dinousaur said, and we agree! That's why we refactored. The API a little bit.

The detailed list of changes is also in ChangeLog.md.

Previously, to create a template, you needed to call Pattern::template()->something()->build(). This is looong and inconvenient. Here's what we did.

  • Breaking changes
    • Renamed Pattern::template() to Pattern::builder(). So if you need to build many elements, you can go
      Pattern::builder($yourTemplateHere)
        ->literal($value)
        ->mask($mask, $keys)
        ->build();
      
  • Features
    • Added Pattern::template(), which works similarly to Pattern::builder() but allows only one chain:
      $pattern = Pattern::template('^@$')->literal('Hi!'); // that's it
      

The detailed list of changes is also in ChangeLog.md.

Rawrrrr!

0.16.0

2 years ago

😎 T-Regx The Dinosaur is really proud to announce its release 0.16.0! This time, we found out that by simplifying T-Regx internal implementation, we can actually simplify the public interface of the library as well! Cool, isn't it? :D

Currently, when you call pattern()->match()->fluent(), you receive FluentMatchPattern (something like Stream from Java8). However, when you call pattern()->match()->asInt() and pattern()->match()->offsets() you also receive FluentMatchPattern, which behaves slightly in a different way (for example throws different exceptions).

We stoped for a minute a thought - waidaminute, something's wrong, I can feel it. So we decided that what must be done is fluent() must be separated from asInt() and offsets(). That's how IntStream was born.

The detailed list of changes is in ChangeLog.md.

  • Breaking changes
    • Methods asInt() and offsets() return IntStream instead of FluentMatchPattern.

    • Removed FluentMatchPatternException. In case of asInt(), InvalidIntegerTypeException is thrown instead.

    • Updated the rules when exceptions are thrown from asInt(), offsets() and fluent():

      • Exceptions thrown from IntStream:
        • pattern()->match()->asInt() throws SubjectNotMatchedException
        • pattern()->match()->offsets() throws SubjectNotMatchedException
        • pattern()->match()->group()->asInt() throws SubjectNotMatchedException or GroupNotMatchedException
        • pattern()->match()->group()->offsets() throws SubjectNotMatchedException or GroupNotMatchedException
      • Exception thrown from FluentMatchPattern:
        • pattern()->match()->fluent() throws NoSuchElementFluentException
        • pattern()->match()->asInt()->fluent() throws NoSuchElementFluentException
        • pattern()->match()->offsets()->fluent() throws NoSuchElementFluentException

      Basically, MatchPattern and IntStream throw match-related exceptions (SubjectNotMatchedException or GroupNotMatchedException), whereas FluentMatchPattern throws fluent-related exception: NoSuchElementFluentException.

    • Updated exception messages from asInt(), offsets() and fluent().

    • MatchPatternInterface is no longer part of T-Regx public API.

The detailed list of changes is also in ChangeLog.md.

Rawrrrr!

0.17.0

2 years ago

😎 T-Regx The Dinosaur is really proud to announce its release 0.17.0! We're coming to giga-big-release of 1.0.0 with big steps!

We noticed that interface of FluentMatchPattern (result of pattern()->match()->fluent()) and its idea, conceptually, is similar to Java8 streams. Semi-functional programming approach, with terminal statements. We decided it was a good idea to make the name more descriptive, so that, if a dinosaur lover knows Java by some accident, he could find similarities here.

So we just renamed FluentMatchPattern to Stream. And also fluent() method to stream().

The detailed list of changes is in ChangeLog.md.

  • Bug fixes
    • Fixed a bug when returning non-string value from orElseCalling() didn't throw InvalidReturnValueException
  • Breaking changes
    • Renamed FluentMatchPattern to Stream, similar to Java 8 streams
    • Renamed fluent() to stream(), similar to Java 8 streams
    • Renamed NoSuchElementFluentException to NoSuchStreamElementException
  • Features
    • Added IntStream.stream()

The detailed list of changes is also in ChangeLog.md.

Rawrrrr!

0.27.0

2 years ago

😎 T-Regx The Dinosaur is really proud to announce its release 0.27.0!

This time we responded to couple of users using array_slice(pattern()->split()) and other magic to mimic, what we think is an idea of limited splits and maybe rsplit() from Python. However Pattern.split() was always supposed to return all of the pieces being split, and frankly, we think that optional arguments in methods is a sign of bad design. Most suggestions were to the sound "just add limit=-1 argument". We decided to go with a cleaner way. First of all, on the quest to defeat optional arguments, and second, because with a limit of cuts, we should decide where to limit them from - the start of the string or the end. Hence splitStart() and splitEnd() with maxSplits argument. The good, old split() continues to split all elements. We think it's a more elegant approach.

The detailed list of changes is in ChangeLog.md.

Summary of changes:

  • Breaking changes
    • Removed Pattern.match().offsets(). Use Pattern.match().map().
    • Removed Pattern.match().group().offsets(). Use Pattern.match().group().map().
    • When using Pattern.split(), previously unmatched separators were represented as an empty string. Now, they're represented as null.
    • Updated flatMap(), see details in ChangeLog.md.
  • Bug fixes
  • Features
    • Added Pattern.splitStart(), which works similarly to Pattern.split() but accepts a non-negative maxSplits argument, which can be used to limit splits from the start of the subject.
    • Added Pattern.splitEnd(), which works similarly to Pattern.split() but accepts a non-negative maxSplits argument, which can be used to limit splits from the end of the subject.
    • Added method Optional.get(). See details in ChangeLog.md.
    • Added methods to Pattern.match(), see ChangeLog.md.
  • Deprecation
    • Deprecated NotMatched passed as findFirst().orElse() argument. Use Pattern.match() functions instead. Everything that NotMatched could be used for, can be got from Pattern.match().

The detailed list of changes is also in ChangeLog.md.

Rawrrrrrrr!

0.25.0

2 years ago

😎 T-Regx The Dinosaur is really proud to announce its release 0.25.0!

Isn't it wierd that using distinct() causes "0" disappear, because there's false in the list as well? Yea, we hate it too. So we fixed it! We made Stream a little bit more like Java8 (yet again), fix nasty bugsies. We're working on the complete rewrite of the internal matching engine, so that T-Regx is a little bit less dependent on the underlying PCRE, but worry not, this will not change the API in any way. While we're working on the refactor, we find and fix stuff in the meantime, so now we decided to release it. After that we'll also refactor the replacing API, which will be quite drastic (a lot of the functions will need updating), but it will be similar. There will be a lot of time for migration.

The detailed list of changes is in ChangeLog.md.

  • Breaking changes
    • Detail.group() no longer implements Optional

    • Detail.usingDuplicateName().group() no longer implements Optional

    • Removed previously deprecated Detail.group().orReturn(). Use or() instead.

    • Removed previously deprecated Detail.group().orElse()

    • Removed previously deprecated Detail.group().orThrow()

    • Removed previously deprecated ReplaceDetail.group().orReturn(). Use or() instead.

    • Removed previously deprecated ReplaceDetail.group().orElse()

    • Removed previously deprecated ReplaceDetail.group().orThrow()

    • Updated how Stream.distinct() removes elements:

      • Now '1' and true are no longer considered equal
      • Now '' and false are no longer considered equal
      • Now 0 and false are no longer considered equal
      • Now 1 and true are no longer considered equal
      • Now 0 and '0' are no longer considered equal
      • Now null and false are no longer considered equal

      For all intents and purposes, now Stream.distinct() works as-if it used strict-comparison ===.

    • Stream.filter() no longer reindexes stream elements. To reindex them, chain the stream with values(). match().filter() still returns a sequential array with reindexed values.

    • Removed Stream.only(). Use Stream.limit().all() instead.

    • Removed IntStream.only(). Use IntStream.limit().all() instead.

    • Renamed Group.textLength() to Group.length().

    • Renamed Group.textByteLength() to Group.byteLength().

    • Renamed Detail.textLength() to Detail.length().

    • Renamed Detail.textByteLength() to Detail.byteLength().

  • Bug fixes
    • Fixed a bug when using Stream.values().keys().first() didn't always reindex to 0.
    • Fixed a bug when using regular groups in stream()->asInt() was allowed, but usingDuplicateName() groups weren't. Now both kinds of groups are correctly passed into stream()->asInt().
    • Fixed a bug when using regular groups in groupByCallback() was allowed, but usingDuplicateName() groups weren't. Now both kinds of groups are correctly passed into groupByCallback().
  • Features
    • Added Detail.group().or() which behaves similarly to orReturn() but only accepts a non-nullable string.
    • Added Stream.limit(), which limits elements present in a stream from the end
    • Added Stream.skip(), which limits elements present in a stream from the start
    • Added IntStream.limit(), which limits elements present in a stream from the end
    • Added IntStream.skip(), which limits elements present in a stream from the start
  • Other
    • Previously, using Stream.keys().first() return 0 for sequential arrays, and T-Regx didn't evaluate previous chains, such as map() or flatMap(). As of this release, they will be called for completeness, even though their results won't be used.

The detailed list of changes is also in ChangeLog.md.

Rawrrrrrrr!

0.23.0

2 years ago

😎 T-Regx The Dinosaur is really proud to announce its release 0.23.0!

This version contains some changes that we were really looking forward to! First of all, hideous findFirst()->orThrow(Exception::class); is gone! We hated that decision, because instantiating exceptions like that hid the stacktrace - the exceptions were opaque, we trully hated using that in production, and were planning on updating that for a long time now. We also made T-Regx a little more robust, by dropping it's reliance on mb_internal_encoding(). Previously, you could actually change how T-Regx works by setting encoding other than UTF-8. Now, you can set mb_internal_encoding() all you want, and T-Regx works without changes. These two changes are marked as breaking changes, for the sake of semantic versioning, but in our eyes these are actually features (we bumped the 0.x version because that's the recommendation of semver).

The detailed list of changes is in ChangeLog.md.

  • Breaking changes
    • Previously deprecated Optional.orThrow() accepted exception class name as string. Currently, orThrow() accepts an instance of \Throwable.
    • Removed ClassExpectedException, which was thrown when an invalid class name was passed to orThrow().
    • Removed NoSuitableConstructorException, which was thrown when an invalid class was passed to orThrow().
    • Previously T-Regx used whatever encoding was set for mb_internal_encoding() for Detail.offset()/tail() /textLength(). Now, T-Regx always uses UTF-8 regardless of mb_internal_encoding(). For byte manipulation in encoding other than UTF-8 use byteOffset()/byteTail()/byteTextLength().
    • Removed previously deprecated Detail.setUserData()/getUserData()
  • Bug fixes
    • Fixed a bug when using match()->groupByCallback() didn't throw InvalidReturnValueException for invalid group value
  • Deprecation
    • Deprecated Detail.limit()

The detailed list of changes is also in ChangeLog.md.

Rawrrrr!

0.21.0

2 years ago

😎 T-Regx The Dinosaur is really proud to announce its release 0.21.0! This time we fixed a bug (yay!), and broke some stuff ;| We found that using nth() method which sometimes throws exception because of subject not matched, and sometimes because of missing items is hard to use. And, it's even not similar to other parts of library - for example all() doesn't throw exception when subject isn't matched. So we decided that nth() should treat all matches equally and not throw a dedicated exception when the subject wasn't matched. And we did the same for stream(). Worry not however, the messages remained the same, so you will know what's the reason for the exception - as a developer. But the API will be more uniform.

The detailed list of changes is in ChangeLog.md.

  • Breaking changes
    • Renamed GroupLimit to GroupMatch.
    • Previously nth()/findNth() threw different exceptions when the subject wasn't matched and when the item was missing. Now they always throw NoSuchNthElementException (regardless of whether the subject was matched or not). Exception messages still remain, to inform you whether there was not enough occurrences or whether the subject wasn't matched.
      • match()->nth() throws NoSuchNthElementException, instead of SubjectNotMatchedException
      • match()->asInt()->nth() throws NoSuchNthElementException, instead of NoSuchStreamElementException
      • match()->stream()->nth() throws NoSuchNthElementException, instead of NoSuchStreamElementException
      • match()->group()->nth() throws NoSuchNthElementException, instead of SubjectNotMatchedException
      • match()->group()->asInt()->nth() throws NoSuchNthElementException, instead of NoSuchStreamElementException
      • match()->group()->stream()->nth() throws NoSuchNthElementException, instead of NoSuchStreamElementException
  • Bug fixes
    • match()->offsets() and match()->group()->offsets() now return offsets as characters. Previously they returned them as bytes.
  • Features
    • Added SubjectNotMatchedException.getSubject()

The detailed list of changes is also in ChangeLog.md.

Rawrrrr!