bilal-fazlani / commanddotnet

A modern framework for building modern CLI apps
https://commanddotnet.bilal-fazlani.com
MIT License
560 stars 32 forks source link

[Feature Request] Humanizer casing method #456

Closed lonix1 closed 1 year ago

lonix1 commented 1 year ago

I'm using CommandDotNet.NameCasing, and in Program.Main() I specify UseNameCasing(Case.CamelCase).

I have a custom ValidationAttribute with this:

public class MyValidationAttribute : ValidationAttribute {

  // ...

  public override string FormatErrorMessage(string name) {
    return $"Please enter correct value for {name}.";         // 'name' will not be formatted as camel case
  }

}

That name argument should be formatted as camel case too, but isn't. So I must hardcode that... yuck. There are probably other places this happens, too.

Please consider exposing a single method from the CommandDotNet.NameCasing plugin, e.g. (pseudocode):

public string ChangeCase(string input) {
  return Humanizer.Format(input, _caseSpecifiedInMainMethod);
}

Thanks!

drewburlingame commented 1 year ago

HI @lonix1,

Unfortunately we don't have access to change the name at this point.

What I did instead was to replace the member name with the argument name after we get the error messages back. The argument name should have already had it's case changed at this point so it should honor the case.

I took the opportunity to add snake_casing and a test to validate this works as expected.

https://github.com/bilal-fazlani/commanddotnet/pull/457/files#diff-0d094050f47aa4385d59b3c871406d3e135ee7523d209dac8e08d5fd3ebcb5a9

Are you not seeing the name casing in the resulting errors? If so, that is different than the behavior the tests are validating and I'll need more information. How are the errors being reported and what results are you seeing?


Thinking about your suggestion...

public string ChangeCase(string input) {
  return Humanizer.Format(input, _caseSpecifiedInMainMethod);
}

What object would you put this on that would be available where you're using it? I think it would need to be statically accessed. I'm hesitant to store any configuration state statically for various reasons. One of which is parallelized testing of middleware. Another is supporting REPL sessions where commands could be configured with a different AppRunner.

In the case that you're writing your own middleware and can't know the case specified in the app config.... What I did instead was add a CaseChanger service that can be accessed from the AppConfig and CommandContext as shown in its test. In your middleware config, you can get the service after casing is configured. The order the middleware config methods is called would matter.

lonix1 commented 1 year ago

replace the member name with the argument name after we get the error messages back

I'll try do that too, seems like a good idea

What object would you put this on that would be available where you're using it

Yes I take your point. I suppose it could be passed in again:

public string ChangeCase(string input, Case @case)

And it's the user's responsibility to cache it somewhere. That is effectively a method that exposes Humanizer behind a simple facade.

You've given me a lot of info... I think I have enough to tackle this issue. Thanks!