4

I am trying to create a template project for the dotnet CLI and I have a need to alter the format of the project name for some replacements. Specifically, convention within our domain uses a camel-case version of the project name as an identifier that needs to be stored in a configuration file.

Normally the templates perform what appears to be a pretty straightforward search/replace of the template project name to the name of the project you are creating with dotnet new. This search is case-sensitive, so it will only pick up instances of the name with the exact same casing.

However in my case, I need it to match a camel case version of the name as well, and replace it with a camel case version of the new name. Is this possible?

This reference has quite a bit of information, and this shows that there is a parameter generator that supports upper and lower case conversions, but specifically says it does not support camel casing. All I really need is the ability to change the first character from upper to lower case.

Any idea how I might be able to insert a camel case version of the project name?

Here is my experimental template.json for the upper and lower case, and command line parameter, but obviously nothing for the camel casing.

{
  "$schema": "http://json.schemastore.org/template",
  "identity": "TemplateTest.CSharp",
  "groupIdentity": "TemplateTest.Console",
  "author": "TemplateTest",
  "classifications": [ "Common", "Console" ],
  "name": "TemplateTest console template",
  "shortName": "test",
  "preferNameDirectory": true,
  "tags": {
    "language": "C#"
  },
  "sourceName": "TemplateTest",
  "symbols": {
    "apiname": {
      "type": "parameter",
      "datatype": "text",
      "defaultValue": "##FIX THIS##",
      "replaces": "templateTest"
    },
    "nameUpper": {
      "type": "generated",
      "generator": "casing",
      "parameters": {
        "source": "name",
        "toLower": false
      },
      "replaces": "TEMPLATETEST"
    },
    "nameLower": {
      "type": "generated",
      "generator": "casing",
      "parameters": {
        "source": "name",
        "toLower": true
      },
      "replaces": "templatetest"
    }
  }
}
Steve In CO
  • 5,746
  • 2
  • 21
  • 32

2 Answers2

8

Pull request #1723 introduced a(n as-yet undocumented) join generator. With this, and the also-undocumented derived symbols, you can separate the project name into [first letter] and [the rest], convert [first letter] to lowercase, and re-join them. Assuming you are starting with PascalCase, this gives you the name in camelCase.

There is another option to define regexes which replace each individual uppercase letter.

Below, the symbol temp1 passes the project name to the custom transform lowerCaseFirstLetter, which is itself a combination of the custom transforms firstLetter and lowerCase. The symbol temp2 passes the name through transform afterFirstLetter.

firstLetter and afterFirstLetter use the same regex to capture the first letter as $1 and the rest as $2, but return only the first and second capturing group respectively.

Finally, the symbol apiname concatenates temp1 and temp2, and uses the result to replace instances of templateTest in the template content.

"symbols": {
  "temp1": {
    "type": "derived",
    "valueSource": "name",
    "valueTransform": "lowerCaseFirstLetter"
  },
  "temp2": {
    "type": "derived",
    "valueSource": "name",
    "valueTransform": "afterFirstLetter"
  },
  "apiname": {
    "type": "generated",
    "generator": "join",
    "replaces": "templateTest",
    "parameters": {
      "symbols": [
        {
          "type": "ref",
          "value": "temp1"
        },
        {
          "type": "ref",
          "value": "temp2"
        }
      ]
    }
  }
},
"forms": {
  "lowerCaseFirstLetter": {
    "identifier": "chain",
    "steps": [
      "firstLetter",
      "lowerCase"
    ]
  },
  "firstLetter": {
    "identifier": "replace",
    "pattern": "^(.)(.*)",
    "replacement": "$1"
  },
  "afterFirstLetter": {
    "identifier": "replace",
    "pattern": "^(.)(.*)",
    "replacement": "$2"
  },
  "lowerCase": {
    "identifier": "lowerCase"
  }
}
Daniel Smith
  • 438
  • 4
  • 7
0

Since .NET 5.0.300 there is a transform "firstLowerCase" and "firstLowerCaseInvariant" you can use.

"symbols": {
    "appNameCamelCase": {
        "type": "derived",
        "valueSource": "name",
        "valueTransform": "firstLowerCase"
    }
}

Peter Hedberg
  • 3,487
  • 2
  • 28
  • 36