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

Add a "RegEx Formatter" extension #88

Closed
krptodr opened this issue Jun 1, 2017 · 9 comments
Closed

Add a "RegEx Formatter" extension #88

krptodr opened this issue Jun 1, 2017 · 9 comments

Comments

@krptodr
Copy link

krptodr commented Jun 1, 2017

I have a list of nested objects and I'd like to get to provide some sort of condition on it so it knows which list item to grab.

Smart.Format("{User.Address.Where(Zip=55555):{Street}, {City}, {State} {Zip}}", data)

My list can return entirely different things depending on a foreign relationship.

@ericpyle
Copy link

ericpyle commented Jun 2, 2017

I'm trying to do the same thing. I'd like to apply a template to an item in a list depending upon the string value of a property. I can use a choose() to get one item, but if I need more than that I have to repeat the template for each additional comparision.
{mylist:list:{myproperty:choose(val1|val2): <template type="{myproperty}"> <id>{anotherprop}</id> </template>| <template type="{myproperty}"> <id>{anotherprop}</id> </template>}||}

I assumed there was a way to use a complex condition (:cond:) but apparently this only applies to numbers. [0-9.-]+ Could we at least extend :cond: to apply =, !=, & / operators to strings as well?

@axunonb
Copy link
Member

axunonb commented Jun 3, 2017

@krptodr: There is no LINQ implemented into Smart.Format selectors or format strings (if this was your question).

@axunonb
Copy link
Member

axunonb commented Jun 3, 2017

@ericpyle: Yes, definitely. You could do this with an tailored extension similar to the conditional formatter. If you find a general approach, I'm happy to include the new extension to the repository.

@ericpyle
Copy link

ericpyle commented Jun 4, 2017

@axunonb Thanks for the tip. This satisfies my needs for now:

Usage

{value:in(val1|val2|...): format | default}

Or in context of list:

{myList:list:{value:in(val1|val2|...): format | default}||}
        public class InFormatter : IFormatter
        {
            private string[] names = new[] { "in" };
            public string[] Names { get { return names; } set { this.names = value; } }

            public bool TryEvaluateFormat(IFormattingInfo formattingInfo)
            {
                var options = formattingInfo.FormatterOptions.Split('|');
                var formats = formattingInfo.Format.Split('|');
                if (formats.Count == 0)
                    return true;
                if (options.Contains(formattingInfo.CurrentValue))
                    formattingInfo.Write(formats.First(), formattingInfo.CurrentValue);
                else if (formats.Count == 2)
                    formattingInfo.Write(formats.Last(), formattingInfo.CurrentValue);
                return true;
            }
        }`

@axunonb
Copy link
Member

axunonb commented Jun 4, 2017

Cool. Would it be possible to supply a unit test for the InFormatter?

@axunonb axunonb changed the title How to perform LINQ on Nested Objects Add an "InFormatter" extension Jun 23, 2017
@ericpyle
Copy link

ericpyle commented Oct 5, 2017

I've been wondering if a regex value:matches(regex) formatter might be even better. It would even work with "val1|val2" and regex should have decent cross platform support

@axunonb
Copy link
Member

axunonb commented Oct 5, 2017

How would you design it? RegEx groups in connection with lists?

@ericpyle
Copy link

ericpyle commented Oct 11, 2017

@axunonb I wasn't thinking about handling lists directly. I'd do it like this (untested):

Syntax
{value:ismatch(regex): format | default}
Or in context of list:
{myList:list:{value:ismatch(regex): format | default}||}

Where regex can be a simple regex string like ^val1|val2|val3$ (match whole words)

        public class IsMatchFormatter : IFormatter
        {
            private string[] names = new[] { "ismatch" };
            public string[] Names { get { return names; } set { this.names = value; } }

            public bool TryEvaluateFormat(IFormattingInfo formattingInfo)
            {
                var regexStr = formattingInfo.FormatterOptions;
                var formats = formattingInfo.Format.Split('|');
                if (formats.Count == 0)
                    return true;
                var rgx = new Regex(regexStr);
                if (rgx.IsMatch(formattingInfo.CurrentValue))
                    formattingInfo.Write(formats.First(), formattingInfo.CurrentValue);
                else if (formats.Count == 2)
                    formattingInfo.Write(formats.Last(), formattingInfo.CurrentValue);
                return true;
            }
        }`

Thoughts?

@axunonb
Copy link
Member

axunonb commented Oct 18, 2017

Agree this would be quite flexible (even more than your in extension idea) and also available under .NetStandard.
Maybe matches would be better than ismatch?
Would you post a PR?

@axunonb axunonb changed the title Add an "InFormatter" extension Add a "RegEx Formatter" extension Oct 18, 2017
axunonb added a commit that referenced this issue May 19, 2018
@axunonb axunonb closed this as completed May 19, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants