www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - To avoid a newline in multi-line strings

reply bearophile <bearophileHUGS lycos.com> writes:
After a short discussion in D.learn I have created a tiny enhancement request:
http://d.puremagic.com/issues/show_bug.cgi?id=6361

I show its text here too. It's not essential, it's a minor thing.

Multi-line strings are handy, but I have a small problem with them. This is an
example, it has a problem, there is an unwanted newline at the beginning (the
situation is the same if you use ` instead of "):

string table = "
- First item:  150
- Second item: 200
- Third item:  105";


(If you are just writing such string then you can use just write() followed by
a flush.)


To avoid it you can write this, but both break the alignment in the source
code, and they are not nice looking:

string table = "- First item:  150
- Second item: 200
- Third item:  105";


string table =
"- First item:  150
- Second item: 200
- Third item:  105";


This solution adds one ending newline instead:

    writeln(q"EOS
- First item:  150
- Second item: 200
- Third item:  105
EOS");



To solve that problem in Python you use this (in Python """ or ''' denote a
multi-line string):

table = """\
- First item:  150
- Second item: 200
- Third item:  105"""


The extra slash at the beginning avoids the start newline.

I think it's worth adding this little Python syntax detail to D too.

-------------

Note: this syntax is not meant to solve the more general problem in presence of
indentation. In this case you probably need a library solution to de-indent,
etc:

void foo()
{
    if(blah)
    {
        writeln("- First item:  150
            - Second item: 200
                -- Subitem 1
                -- Subitem 2
            - Third item:  105");
    }
}


(Thanks to Nick Sabalausky and Andrej Mitrovic for the suggestions and
comments.)

Bye,
bearophile
Jul 23 2011
next sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
import std.algorithm;
import std.stdio;
import std.string;

string stripNewlines(string text)
{
    auto x = text.countUntil("\n");
    auto y = text.lastIndexOf("\n");

    return text[x+1..y];
}

template EOS(string text)
{
    enum EOS = stripNewlines(text);
}

void main()
{
    writeln(EOS!"
    - First item:  150
    - Second item: 200
    - Third item:  105
    ");
}
Jul 23 2011
parent reply bearophile <bearophileHUGS lycos.com> writes:
Andrej Mitrovic:

 import std.algorithm;
 [snip]
Thank you for your code, but I think this code will not be added to Phobos, and even if so, I don't think lot of people will want to use it. Bye, bearophile
Jul 23 2011
parent reply Peter Alexander <peter.alexander.au gmail.com> writes:
On 23/07/11 5:10 PM, bearophile wrote:
 Andrej Mitrovic:

 import std.algorithm;
 [snip]
Thank you for your code, but I think this code will not be added to Phobos, and even if so, I don't think lot of people will want to use it. Bye, bearophile
Doesn't strip work? auto s = strip(" line 1 line 2 line 3 "); http://d-programming-language.org/phobos/std_string.html#strip
 Strips both leading and trailing whitespace.
Jul 23 2011
parent reply bearophile <bearophileHUGS lycos.com> writes:
Peter Alexander:

 Doesn't strip work?
 
 auto s = strip("
 line 1
 line 2
 line 3
 ");
strip works, maybe even at compile-time for enum string literals. With it you have to be a bit careful because if later you want to add leading spaces to the first line, they get removed. The slash is used to not break the lines in the middle of the string too (this is a less common need): string s = "verylongstring\ bar"; Bye, bearophile
Jul 23 2011
parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
strip doesn't work at compile-time anymore.
Jul 23 2011
prev sibling parent reply "Nick Sabalausky" <a a.a> writes:
"bearophile" <bearophileHUGS lycos.com> wrote in message 
news:j0enh7$tec$1 digitalmars.com...
 After a short discussion in D.learn I have created a tiny enhancement 
 request:
 http://d.puremagic.com/issues/show_bug.cgi?id=6361

 I show its text here too. It's not essential, it's a minor thing.
Since this is re-posted here, I'll repost my response. Please note that this does properly handle bearophile's original problem, in addition to indenting. Also, individual parts of the functionality are available a la carte' as stripTop/Bottom/Right, and unindent: I created a (CTFEable) function normalize() (maybe could use a better name?): http://www.dsource.org/projects/semitwist/browser/trunk/src/semitwist/util/text.d#L630 void foo() { if(blah) { // Works properly: writeln(" - First item: 150 - Second item: 200 -- Subitem 1 -- Subitem 2 - Third item: 105 ".normalize()); } } Another example: Do this: -------------------- void foo() { enum codeStr = q{ // Written in the D Programming Langauge // by John Doe int main() { return 0; } }.normalize(); } -------------------- Instead of this: -------------------- void foo() { enum codeStr = q{// Written in the D Programming Langauge // by John Doe int main() { return 0; }}; } -------------------- The resulting string is exactly the same. I'd be happy to work it into something appropriate for Phobos if people are intersted.
Jul 23 2011
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 7/23/2011 1:23 PM, Nick Sabalausky wrote:
 I'd be happy to work it into something appropriate for Phobos if people are
 intersted.
I think you should propose it as a pull request.
Jul 23 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 7/23/11 6:22 PM, Walter Bright wrote:
 On 7/23/2011 1:23 PM, Nick Sabalausky wrote:
 I'd be happy to work it into something appropriate for Phobos if
 people are
 intersted.
I think you should propose it as a pull request.
std.string.outdent Andrei
Jul 23 2011
parent reply "Nick Sabalausky" <a a.a> writes:
"Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message 
news:4E2B5C3E.4090404 erdani.org...
 On 7/23/11 6:22 PM, Walter Bright wrote:
 On 7/23/2011 1:23 PM, Nick Sabalausky wrote:
 I'd be happy to work it into something appropriate for Phobos if
 people are
 intersted.
I think you should propose it as a pull request.
Will do.
 std.string.outdent
It would make sense to name the "unindent" function "outdent", but the "normalize" does more than that: It also removes all whitespace-only lines from the top and bottom ("stripTopBottom") and (though this part is maybe far less important) it does a stripr on each remaining line. The idea is you can call just one CTFEable function on an embedded multiline string, and be able to format the string however looks right and not have to worry about the resulting string having werid whitespace. As a trivial example, suppose you had a program that output the source for a basic hello world: // example.d import std.stdio; void main() { enum helloWorld = q{ import std.stdio; void main() { writeln("Hello World"); } }; } $ dmd example.d $ example > hello.d As it is, making it actually fit nicely into example.d's source results in not just excess indentation in hello.d, but also an excess leading/trailing blank line. So using one function cleans up everything: // example2.d import std.stdio; void main() { enum helloWorld = q{ import std.stdio; void main() { writeln("Hello World"); } }.normalize(); // Bye-bye indents *and* excess leading/trailing lines }
Jul 23 2011
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 07/23/2011 07:40 PM, Nick Sabalausky wrote:
 "Andrei Alexandrescu"<SeeWebsiteForEmail erdani.org>  wrote in message
 std.string.outdent
It would make sense to name the "unindent" function "outdent", but the "normalize" does more than that: It also removes all whitespace-only lines from the top and bottom ("stripTopBottom") and (though this part is maybe far less important) it does a stripr on each remaining line.
It does too much. Just have it do outdenting and call it outdent, it will be useful to many. "Normalized text" means several things in NLP, neither of which is what you mean. Andrei
Jul 23 2011
parent reply "Nick Sabalausky" <a a.a> writes:
"Andrei Alexandrescu" <SeeWebsiteForEmail erdani.org> wrote in message 
news:j0g39q$dr6$1 digitalmars.com...
 On 07/23/2011 07:40 PM, Nick Sabalausky wrote:
 "Andrei Alexandrescu"<SeeWebsiteForEmail erdani.org>  wrote in message
 std.string.outdent
It would make sense to name the "unindent" function "outdent", but the "normalize" does more than that: It also removes all whitespace-only lines from the top and bottom ("stripTopBottom") and (though this part is maybe far less important) it does a stripr on each remaining line.
It does too much. Just have it do outdenting and call it outdent, it will be useful to many. "Normalized text" means several things in NLP, neither of which is what you mean.
I think it's very useful to also have a funct that does all of that, but I agree that normalize is a bad name for it. What do you think about having stripTop and stripBottom functions? (Ie, Removing all white-space-only lines from the top or bottom of a string. assert(stripTop(" \n \t \n\tA") == "\tA") ) If those are there in addition to outdent, then a user could trivially combine them all into one util func if they wanted. In any case, I'll make a pull request for outdent.
Jul 23 2011
parent reply "Nick Sabalausky" <a a.a> writes:
"Nick Sabalausky" <a a.a> wrote in message 
news:j0g4c2$fh6$1 digitalmars.com...
 In any case, I'll make a pull request for outdent.
https://github.com/D-Programming-Language/phobos/pull/156
Jul 24 2011
parent Walter Bright <newshound2 digitalmars.com> writes:
On 7/24/2011 12:40 PM, Nick Sabalausky wrote:
 https://github.com/D-Programming-Language/phobos/pull/156
Thanks, Nick!
Jul 24 2011