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

How to use user input project name in template.json #1667

Closed
WeihanLi opened this issue Sep 26, 2018 · 14 comments
Closed

How to use user input project name in template.json #1667

WeihanLi opened this issue Sep 26, 2018 · 14 comments

Comments

@WeihanLi
Copy link

How to use user input project name in template.json?

I wanna rename some variables by project name, how can I get project name?

I've tried to use (name),but it did not work.

@seancpeters
Copy link
Contributor

In your template.json, if you define a "sourceName", the value of the sourceName is what is replaced by the value of the --name input.

For example, take a look at the CSharp 2.2 console template. The template.json, here:
https://github.com/dotnet/templating/blob/stabilize/template_feed/Microsoft.DotNet.Common.ProjectTemplates.2.2/content/ConsoleApplication-CSharp/.template.config/template.json
contains this line:
"sourceName": "Company.ConsoleApplication1",

So with that specification in the template.json, the value of the input name will replace Company.ConsoleApplication1.

In that template, the Program.cs, here:
https://github.com/dotnet/templating/blob/stabilize/template_feed/Microsoft.DotNet.Common.ProjectTemplates.2.2/content/ConsoleApplication-CSharp/Program.cs
contains this:
namespace Company.ConsoleApplication1

If the input name value is not a valid symbol or namespace name, template processing attempts to modify the value so it's valid. To help template processing correctly do that, we recommend using a sourceName value structured like above - so that it includes periods and numbers. Something like Company.ConsoleApplication.1 is even better.

@WeihanLi
Copy link
Author

WeihanLi commented Sep 27, 2018

Thanks @seancpeters , I've known this, what I wanna know is how to use symbols in template.json,
I wanna to return a symbols that depend on user input name,what should I do?

for examples:

 "fullName": {
      "type": "parameter",
      "datatype": "text",
      "replaces": "ServiceName",
      "defaultValue": "'Service.'+$(sourceName)"
   }

@seancpeters
Copy link
Contributor

Ah ok, for something like this, you should use a "derived" type symbol. #1066 has a good explanation of how they work. For your specific situation, something like this should work:

"symbols": {
  "fullName": {
      "type": "derived",
      "valueSource": "name",  // "fullName" value will be derived from "name" value.
      "valueTransform": "prepend",  // the form to use to transform the value.
      "replaces": "ServiceName",
   }
},  // end of symbols section
"forms": {  // forms is a top level element
    "prepend": {
       "identifier": "replace",
       "pattern": "(?<=^)",  // match the start of the string. The lookbehind is probably unnecessary in this case.
       "replacement": "Service."  // replace what was matched by pattern with this value.
    }
}

A simpler method that might work (depending on your situation) is to have the literal "Service." in your template content. For example if your sourceName = "Company.Application1", in the content you could have something like this:

Service.Company.Application1

When the file is processed, Company.Application1 will be replaced by the value of the name parameter, but Service. will stay as is.

@WeihanLi
Copy link
Author

@seancpeters Thanks for your solution 👍

@WeihanLi
Copy link
Author

Is there any way for a conditional replace?

@seancpeters
Copy link
Contributor

@WeihanLi - yes this is possible. There is a way to cause the template processing to turn specific operations on or off for part of a file. Here is an example of causing conditional replacement of the string ThingToReplace, based on the value of the Boolean input dontReplace:

            #if (dontReplace)
            //-:replacements:noEmit
            #endif
            
            Console.WriteLine("Conditionally replace ThingToReplace");
            
            #if (dontReplace)
            //+:replacements:noEmit
            #endif

            Console.WriteLine("Always replace ThingToReplace");

This //-:replacements:noEmit and //+:replacements:noEmit are the important pieces. Note that they differ from each other by one character, the first one has - and the second one has +. The - means to turn off an operation. The : is a separator. replacements is a keyword for turning replacement operations on or off. The :noEmit part tells template processing to not include this directive in the processed output.

When dontReplace is true, then #if (dontReplace) is true and so the content inside the if block is processed - the first one causes replacements to be turned off, the second one causes them to be turned back on. If dontReplace is false, then the content inside the if block is not processed, and replacements
are not temporarily turned off.

@WeihanLi
Copy link
Author

WeihanLi commented Oct 8, 2018

I wanna use the symbol more flexible,like dynamic replace filename and code just like sourceName, is there a document or sample? How do I use source.rename?

@WeihanLi WeihanLi reopened this Oct 8, 2018
@seancpeters
Copy link
Contributor

#1553 might be what you're looking for. If not, could you elaborate on what you're trying to accomplish?

@WeihanLi
Copy link
Author

WeihanLi commented Oct 9, 2018

my samples template.json file is as follows:

{
    "$schema": "http://json.schemastore.org/template",
    "author": "Zhongyi dev team",
    "classifications": [ "Web" ], 
    "name": "MockingJ Service",
    "shortName": "mkj",
    "tags": {
      "language": "C#",
      "type":"project"
    },
    "sourceName": "TServiceName",
    "preferNameDirectory": true,
    "symbols":{
      "includeTest": {
        "type": "parameter",
        "datatype": "bool",
        "defaultValue": "true"
      },
      "svcType": {
        "type": "parameter",
        "datatype": "choice",
        "defaultValue": "service",
        "choices":[
          {
            "choice": "service",
            "description": "service"
          },
          {
            "choice": "business",
            "description":"business"
          }
        ]
      },
      "fullName": {
        "type": "derived",
        "valueSource": "name",
        "valueTransform": "prepend",
        "replaces": "FullServiceName"
     }
    },
    "forms": {
      "prepend": {
         "identifier": "replace",
         "pattern": "(?<=^)",
         "replacement": "MockingJ.Services."
      }
    },
    "sources":[{
      "modifiers": [
          {
            "condition": "(!includeTest)",
            "exclude": [ "MockingJ.Services.TServiceName.Test/**/*"]
          },
          {
            "condition": "(svcType=='business')",
            "rename":{
              "MockingJ.Services.TServiceName":"MockingJ.Business.TServiceName"
            },
            "exclude": [ "MockingJ.Services.TServiceName.Business/**/*"]
          },
          {
            "condition": "(svcType=='service')",
            "exclude": [ "MockingJ.Business.TServiceName/**/*"]
          }
      ]
    }]
  }

and my files structure like:

image

I wanna to generate file content depend on the choice serviceType, when serviceType is service,file content maybe:

image

when business

image

Use the template.json above, I can generate the files correctly but when business, the file content will not be replace,such as namespace etc.

When serviceType is business, the namespace I want should be MockingJ.Business.TServiceName but got MockingJ.Services.TServiceName.

Can I replace the files name and file content in some file at the same time via sources>modifiers > rename or can I replace the full service Name conditionally depend on the serviceType?

@seancpeters
Copy link
Contributor

Sources > Modifiers > Rename only deals with changing file names.

For replacing content within the files, you'll need to use symbol replacements.

@WeihanLi
Copy link
Author

Thanks @seancpeters , is symbol's replace behind the sourceName replace?
If yes, is there a option for symbol's replace before the sourceName replace?

I'm trying to transform the namespace etc with a generator symbols,but not as I expected,I got MockingJ.Business.TServiceName.

"fullNameTransform": {
        "type": "generated",
        "generator": "switch",
        "datatype": "string",
        "parameters": {
          "cases":  [
            {
              "condition": "(svcType!='business')",
              "value": "MockingJ.Services.TServiceName"
            },
            {
              "condition": "(svcType=='business')",
              "value": "MockingJ.Business.TServiceName"
            }
          ]
        },
       "replaces": "MockingJ.Services.TServiceName"
     }

@WeihanLi
Copy link
Author

I set each *.cs files namespace and *.csproj file reference depend on my symbol svcType,
what I modified are as follows:

#if (svcType=='service')
namespace MockingJ.Services.TServiceName.Web
#else
namespace MockingJ.Business.TServiceName.Web
#endif

@TWiesendanger
Copy link

Is there a way to use -o input from the user to replace something?

@kish14all
Copy link

WeihanLi

Hi did you able to get user input project name, solution name and path? my scenario is I need to get those values and replace other values, I know sourcename will replace but i need to replace other things aswell with those names.

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

No branches or pull requests

4 participants