Scripty icon indicating copy to clipboard operation
Scripty copied to clipboard

Add WriteNamespace() and GetNamespace() methods

Open Herdo opened this issue 9 years ago • 6 comments

Add a method to the Output class, that adds the namespace to the output, depending on the current file location.

Example usage:

// This line creates a namespace, taking the location of the the file into account.
Output.CreateNamespace();
{
    /* Content (classes, interfaces, enums and so on) is going inside here */

    // This line creates a nested namespace, taking the existing namespace structure into account.
    // The final segment of the namespace will be called "MyNestedNamespace".
    Output.CreateNamespace("MyNestedNamespace");
}

Depending on the possibilities, the CreateNamespace method should act equal to the folder structure, but take the Namespace Provider flag of the folder into account.

Herdo avatar Jun 15 '16 15:06 Herdo

I like this idea very much. The code wouldn't be very complicated, probably just a single line that operates on ScriptFilePath. However, I would suggest we call it WriteNamespace() to be clear that it's outputting something on the write stream.

daveaglick avatar Jun 15 '16 15:06 daveaglick

Indeed. The WriteNamespace() would fit better to the existing methods Write...(). Handling the Namespace Provider flag might be an issue, I guess?

Herdo avatar Jun 15 '16 15:06 Herdo

Thinking about this even more, we should probably return an IDisposable to automatically open and close the namespace. For example, I don't think the code you provided above would actually do what you intended. The brackets wouldn't make it to the output file, they're just in the script (remember this isn't a templating language like T4 - everything that gets written to the script has to be the result of a call). I'm guessing what you meant is this (with the WriteNamespace naming):

// This line creates a namespace, taking the location of the the file into account.
Output.WriteNamespace();
Output.WriteLine("{");
    /* Content (classes, interfaces, enums and so on) is going inside here */

    // This line creates a nested namespace, taking the existing namespace structure into account.
    // The final segment of the namespace will be called "MyNestedNamespace".
    Output.WriteNamespace("MyNestedNamespace");
    Output.WriteLine("{");
    Output.WriteLine("}");
Output.WriteLine("}");

That's not ideal given the open and close write statements for the braces and the fact that we're now artificially indenting the nested namespace code. If WriteNamespace() returned an IDisposable that wrote the close brace on dispose we could clean things up a little:

// This line creates a namespace, taking the location of the the file into account.
using(Output.WriteNamespace())
{
    /* Content (classes, interfaces, enums and so on) is going inside here */

    // This line creates a nested namespace, taking the existing namespace structure into account.
    // The final segment of the namespace will be called "MyNestedNamespace".
    using(Output.WriteNamespace("MyNestedNamespace"))
    {
    }
}

Of course we could also put this whole thing in an interpolated string, but then we don't want the WriteNamespace() call to actually write to the stream, just return the namespace. This suggests we need a companion method as a global that gets a namespace but doesn't write it:

Output.WriteLine(@$"
using {GetNamespace()}
{
    /* Content (classes, interfaces, enums and so on) is going inside here */

    using {GetNamespace("MyNestedNamespace")}
    {
    }
}
"); // End of the interpolated string in the Output.WriteLine() call

daveaglick avatar Jun 15 '16 15:06 daveaglick

That's what I intended, yeah. The { and } would also belong into the stream, not as code into the scripty file.

The Output.WriteNamespace() method looks fine in your example.

The GetNamespace() example is wrong. It should be like this:

Output.WriteLine(@$"
// This is printed code. Therefore: NO! "using".
// The value returned by GetNamespace is a string, not an IDisposable.
{GetNamespace()}
{
    /* Content (classes, interfaces, enums and so on) is going inside here */

    // Same as above - no using here.
    {GetNamespace("MyNestedNamespace")}
    {
    }
}
"); // End of the interpolated string in the Output.WriteLine() call

However, this won't work due to the missing quotion marks! Like this:

  • Output.WriteLine(@$" with line breaks won't work: string interpolation
  • This will cause a lot of additional quotation marks: correct string interpolation
  • The { and } might to be escaped as well!

Herdo avatar Jun 15 '16 15:06 Herdo

Sorry, got the syntax for verbatim interpolated strings wrong - the reason you're getting so many squigglies is because the ordering of @ and $ matters and I got it backwards. The interpolated version should work as long as the string is prefixed with $@ instead of @$.

daveaglick avatar Jun 15 '16 16:06 daveaglick

Yeah. Then we will end up in the case of escaping the { and }. However, this looks much cleaner than all the quotion marks: string interpolation

This would be an acceptable option for users. Still, got to be careful with the indents there!

Herdo avatar Jun 15 '16 17:06 Herdo