Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Functional rewrite #197

Closed
wants to merge 14 commits into from

Conversation

jehna
Copy link
Contributor

@jehna jehna commented Jul 20, 2019

Work related to issue #196

This is a functional style rewrite from the v1.0 JSVerbalExpressions. The main difference is that the v1.0 had a builder-like interface:

const tester = VerEx()
    .startOfLine()
    .then('http')
    .maybe('s')
    .then('://')
    .maybe('www.')
    .anythingBut(' ')
    .endOfLine();

And the new version is just a bunch of functions that output regular expressions:

const tester = VerEx(
  startOfLine,
  "http",
  maybe("s"),
  "://",
  maybe("www."),
  anythingBut(" "),
  endOfLine
);

All of the functions output valid regular expressions, and all the constants are valid regular expressions. So for example or('foo', 'bar') outputs a normal regular expression /(?:foo)|(?:bar)/.

This branch is still a draft/WIP

jehna added 14 commits July 19, 2019 21:41
The new version will be written directly with Typescript, so we'll start
by having a simple, blank Typescript project base.
Extracted "simplifyExpression" helper function to its own file
Extracted `simpleExp` function so we can easily compile expressions that
only add something to the input
Changed all functions to return regular expressions. This way we use
regexp as the sanitized form and strings are always unsanitized
@jehna jehna changed the title Functional rewrite WIP: Functional rewrite Jul 20, 2019
@jehna jehna mentioned this pull request Jul 20, 2019
@shreyasminocha shreyasminocha marked this pull request as ready for review July 21, 2019 07:17
@shreyasminocha
Copy link
Member

Apologies, didn't mean to mark as "ready for review", but wanted to leave a review.

Copy link
Member

@shreyasminocha shreyasminocha left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we also move tests into their own directory test?

minTimes?: number,
maxTimes?: number
) {
const output = minTimes
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's try to support:

  • multiple('foo')foo*
  • multiple('foo', 2)foo{2}
  • multiple('foo', 2, 5)foo{2, 5}
  • multiple('foo', 2, Infinity)foo{2,}

import { Expression } from "./types";
import { compile } from "./verbalexpressions";

export default function group(...inputs: Expression[]) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice to have group support the following:

  • group('foo') — functionally identical to group.capturing
  • group.capturing('foo')
  • group.nonCapturing('foo')

@@ -0,0 +1,4 @@
import { simpleExp } from "./utils";

const anythingBut = simpleExp<string>(exp => `[^${exp}]*`);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This deviates a bit from the old API, but I feel renaming this function to anyCharacterBut making it output [^${exp}] would make the API more intuitive.

@@ -0,0 +1,3 @@
export default function anyOf(input: string) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This deviates a bit from the old API, but I feel renaming this function to anyCharacterFrom would make the API more intuitive.

@@ -0,0 +1,3 @@
export default function anyOf(input: string) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should accept an array of (characters | 2 length arrays). The two-length arrays would be a tuple of start and end characters. Here's an example:

anyOf(['a', 'b', 'c', ['0', '9'], ['A', 'Z']])

Implementation stub:

const charOrRange = string | [string, string];
export default function anyOf(input: Array<charOrRange>) {
  
}

Maybe we could force the strings in charOrRange to be of length one with fancier typescript constructs.

@@ -0,0 +1,27 @@
import { Expression } from "./types";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we move each of these into their own files in a src/util folder?

@@ -0,0 +1 @@
export type Expression = RegExp | string | number;
Copy link
Member

@shreyasminocha shreyasminocha Jul 21, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we move each of these into their own files in a src/types folder?

@shreyasminocha
Copy link
Member

shreyasminocha commented Jul 21, 2019

I could add lookaround(), lookaround.ahead() and lookaround.behind(). lookaround() would be identical to lookaround.ahead().

@shreyasminocha
Copy link
Member

shreyasminocha commented Jul 21, 2019

Slightly offtopic, but Docz would be perfect for docs. I could work on those.

@shreyasminocha shreyasminocha added this to the 2.0.0 milestone Jul 21, 2019
@shreyasminocha
Copy link
Member

Rather than passing RegExps around, having SimpleExp etc, could we have a type called RawString, which will essentially be a string, but it'll help us distinguish built regex expressions from input strings?

@shreyasminocha
Copy link
Member

shreyasminocha commented Jul 21, 2019

Please let me know if you want me to implement any of the things I've pointed out. I'd be more than happy to contribute/split_the_work.

@jehna
Copy link
Contributor Author

jehna commented Jul 29, 2019

@shreyasminocha thank you for taking time to review! You have good points, and I'll address these comments as soon as possible.

I'd also like to hear your honest opinion about the high-level approach — how do you like using plain functions versus using a builder-like object to generate regular expressions? Do you think this this is the right direction for JSVerbalExpressions? Do you think these changes make the library simpler/better to use/more extensible — or the contrary?

I think now would be a good time to discuss these kind of high-level questions so we can still change things radically if better ideas arise

@shreyasminocha
Copy link
Member

Do you think this this is the right direction for JSVerbalExpressions?

Yes, I think this is a good idea. However, since the semantics of usage will change, we should not be afraid to change the names of API methods where necessary to make the API more intuitive.

Do you think these changes make the library simpler/better to use/more extensible — or the contrary?

I think that they do make it more intuitive, more flexible and more powerful 🚀.

I'd also like to hear your honest opinion about the high-level approach — how do you like using plain functions versus using a builder-like object to generate regular expressions?

If I understand you correctly, I prefer the idea of plain functions (like the second example in #197) to a builder pattern.

On the implementation side of things, like I highlighted in the review, I think the functions should each return vanilla strings like [a-z] (or maybe a custom type—also essentially a string—to distinguish them from stuff that needs to be sanitized). VerEx would accept an arbitrary number of such strings, and generate a RegExp. Also, I don't think we should support mutability of the returned object. Maybe that would have the side-effect of allowing us to avoid calling the deprecated compile.

@shreyasminocha
Copy link
Member

shreyasminocha commented Sep 22, 2019

Hey @jehna.

I've done some work off your branch. I think the best way to go about this is to create a 2.0.0 branch on VerbalExpressions/JSVerbalExpressions and work there.

Update: Created a 2.0.0 branch as well as a 2.0.0 project.

I'm not sure if GitHub allows you to, but can you change the branch linked with this PR to the new one?

@jehna
Copy link
Contributor Author

jehna commented Sep 23, 2019

Great, thank you! Sorry for not having that much time to work on this project :/

I'm not sure if GitHub allows you to, but can you change the branch linked with this PR to the new one?

Unfortunately you need to close this one and open up another if you want to change the source branch. And that's okay for me :)

@shreyasminocha
Copy link
Member

Discussion will continue in #198.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants