dotnet / csharplang

The official repo for the design of the C# programming language
11.38k stars 1.02k forks source link

multiline strings with ignored indent #2176

Closed daveyostcom closed 3 years ago

daveyostcom commented 5 years ago

Simple idea: If a string literal is the first thing on a line, beginning at indent n, then additional lines within the string content ignore initial indent n represented with an identical sequence of whitespace characters. In this example, 8 space characters of indent are ignored:

string text = 
        @"My pensive SARA! thy soft cheek reclined
            Thus on mine arm, most soothing sweet it is
            To sit beside our Cot, ...";
/* Output:
My pensive SARA! thy soft cheek reclined
    Thus on mine arm, most soothing sweet it is
    To sit beside our Cot, ... 
*/

Adapted from: Strings (C# Programming Guide) – Regular and Verbatim String Literals BTW, the example is incorrect. The intent in the string literal doesn't match the indent in the Output in the comment below it.

Also see Looking at and editing string literals could be a lot nicer.

CyrusNajmabadi commented 5 years ago

This would be a breaking change as it would change the meaning (dramatically) of existing programs.

vladd commented 5 years ago

@CyrusNajmabadi An obvious correction would be prepending the string literal with a special character, something like @!"multiline string" or @@"multiline string".

HaloFour commented 5 years ago

Java is proposing handling this via String instance members align and indent:

String html = `
                   <html>
                       <body>
                           <p>Hello World.</p>
                       </body>
                   </html>
              `.align().indent(4);
jnm2 commented 5 years ago

@HaloFour So the adjustment is done at runtime? That would be a nice extension method.

djkrose commented 5 years ago

I happen to have such an extension method, called .Unindent(), here: https://github.com/djkrose/7DTD-ScriptingMod/blob/master/ScriptingMod/Extensions/StringExtensions.cs In function GetHelp() you can seet it being used: https://github.com/djkrose/7DTD-ScriptingMod/blob/master/ScriptingMod/Commands/Export.cs Feel free to take it...

daveyostcom commented 5 years ago

Java is proposing handling this via String instance members align and indent:

String html = `
                   <html>
                       <body>
                           <p>Hello World.</p>
                       </body>
                   </html>
              `.align().indent(4);

Or just .align(4). Pity the poor smart text editor that want's to facilitate editng this string tho.

daveyostcom commented 5 years ago

@CyrusNajmabadi An obvious correction would be prepending the string literal with a special character, something like @!"multiline string" or @@"multiline string".

Even better.

HaloFour commented 5 years ago

@vladd

An obvious correction would be prepending the string literal with a special character, something like @!"multiline string" or @@"multiline string".

var qBertSays = $@!"%{_}&";
arekbal commented 5 years ago

More like Python multiline comments:

'''
This is a multiline
comment.
'''

So something like

string s = 
"""
Hello World
""";

might make sense. But then I am not sure about indentation... in python they care about indentation much more.

erik-kallen commented 5 years ago

And in the same ballpark, it would be great if it were possible to specify the line endings for a multiline string.

CyrusNajmabadi commented 5 years ago

@erik-kallen

  1. you can simply use whatever line ending you want in the string, and the compiler will respect it.
  2. If you want to be resilient to other tools (like git) potentially changing those line endings unintentionally, then you can just write something like @"multi-line-string".UseLF(), which is effectively just a find/replace.
erik-kallen commented 5 years ago

@CyrusNajmabadi I know, but the amount of times I have had to troubleshoot line-ending issues with multi-line string literals happening just on some machines is greater than zero, so it would be nice to have the possibility to avoid it. And sometimes it is useful to have another lineending in a string literal than the source file, which does not work very well with any editor I am aware of (and would also be very easily accidentally broken)

CyrusNajmabadi commented 5 years ago

@CyrusNajmabadi I know, but the amount of times I have had to troubleshoot line-ending issues with multi-line string literals happening just on some machines is greater than zero, so it would be nice to have the possibility to avoid it.

Write an analyzer that finds and reports these problem for you then.

erik-kallen commented 5 years ago

Write an analyzer? Does anyone really do that? That is kind of a no-answer.

Actually, I have tried writing an analyzer once, but it had way too many problems with only running on some machines depending on which version of Visual Studio was installed.

And, additionally, it is not a fit for an analyzer since I don't want diagnostics.

CyrusNajmabadi commented 5 years ago

Does anyone really do that?

Of course :)

And, additionally, it is not a fit for an analyzer since I don't want diagnostics.

You said you had problems in the past, presumably something that steers you away from those problems would be desirable :)

yaakov-h commented 5 years ago

Write an analyzer? Does anyone really do that?

👋

I don't want diagnostics.

You don’t want something that can warn you about a possible problem at the earliest possible opportunity, and allow you to easily correct it through your IDE?

Logerfo commented 5 years ago

Actually, I have tried writing an analyzer once, but it had way too many problems with only running on some machines depending on which version of Visual Studio was installed.

So because you have a feature which only runs in a certain version of Visual Studio, you're asking for some other feature which will only run in a certain version of Visual Studio. 🤔

erik-kallen commented 5 years ago

I don't see your point, @Logerfo, I am asking (actually not really asking, more coming up with an idea) for a language feature. They tend to only work in newer versions of the language.

@yaakov-h No, in this case I don't want a diagnostic. The diagnostic cannot possibly know when it needs to warn (other than warning for all multiline strings which seems excessive). Line endings only matter in very few cases from my experience, but when they do, the resulting problems can be hard to find and sometimes only manifest themselves on builds created by some machines.

CyrusNajmabadi commented 5 years ago

I don't see your point, @Logerfo, I am asking (actually not really asking, more coming up with an idea) for a language feature.

I think the point is: There is little need for a language feature as you could pretty easily solve this yourself with existing tools.

There will be little appetite to take this sort of thing given the extremely marginal benefit. Ths sort of thing is more well suited to library methods+analzyers.

CyrusNajmabadi commented 5 years ago

Line endings only matter in very few cases from my experience, but when they do, the resulting problems can be hard to find and sometimes only manifest themselves on builds created by some machines.

Right. So in those cases, mark things up in such a way that your analyzer makes sure there is nothing wrong.

This is what you would need to do anyways if you got a new language feature. You'd have to use that new language feature to get the benefit.

erik-kallen commented 5 years ago

@CyrusNajmabadi I do not see at all how an analyzer could do what I do. It's like that's your hammer that you would use to screw in any screw.

I do agree, though, that the feature is not likely to be worth doing.

CyrusNajmabadi commented 5 years ago

@CyrusNajmabadi I do not see at all how an analyzer could do what I do.

It's pretty trivial. you would annotate the strings that you care about (like all the cases where you would use a new language feature). Then, the analyzer goes and checks the string and tells you if there is a newline problem with them. (i.e. it checks teh strings you've marked against any semantics you care about).

erik-kallen commented 5 years ago

Yes. Or I could just use the .UseLf() extension method suggested above. (and, btw, how would I annotate the strings? A magic comment? Unlike Babel plugins for JS, analyzers can't add new syntax AFAIK.

CyrusNajmabadi commented 5 years ago

(and, btw, how would I annotate the strings? A magic comment?

Whatever way works best for you. You could even have it be something like:

var v = "...".CheckStringAtCompileTime();
//...

static CheckStringAtCompileTime(this string s) =>s ;

And your analyzer would look for calls to that method and would do whatever analysis you wanted.

jrmoreno1 commented 5 years ago

This would be much better as an IDE issue, not language: https://github.com/dotnet/roslyn/issues/34006

yaakov-h commented 5 years ago

The IDE displaying it as indented when it's not is an IDE issue.

The language ignoring equal leading whitespace on each line is still a language issue.

(Although both could theoretically solve the same problem.)

jrmoreno1 commented 5 years ago

@yaakov-h : language ignoring spaces is a huge breaking change without a new syntax. So it’s either new syntax or IDE change, as a breaking change is a non-starter. And why add new syntax for something the IDE can do, and IMO do better?

yaakov-h commented 5 years ago

@jrmoreno1 C# code exists in many varied contexts outside of Visual Studio.

arekbal commented 5 years ago

@erik-kallen if you are afraid of analyzers, start with something as simple as convention test that would just go through the files and fail in case it would find these endings anywhere.

OJacot-Descombes commented 5 years ago

Please see (and upvote) my suggestion for change in the Visual Studio IDE: Indent multi-line verbatim strings.

jrmoreno1 commented 5 years ago

@yaakov-h : I don’t think a new syntax for a display feature is in the cards, it restricts future choices for no real benefit — it would be like adding a keyword that represents syntax coloring.

YairHalberstadt commented 3 years ago

Closing in favor of https://github.com/dotnet/csharplang/issues/4013 which goes into this in more detail