Kevin Li
Kevin Li

Reputation: 1538

Python Block Formatting

How do I indent a multiline string in the context of string formatting? e.g.

'''
<
     %s
>
''' % (paragraph)

where paragraph contains newlines. ('foo\nbar')

If I use the above code, I get output like this:

'''
<
    foo
bar
>
'''

when I really want this:

'''
<
    foo
    bar
>
'''

I know I could do something like:

'''
<
%s
>
''' % (paragraph)

but this breaks readability for my purposes.

I also realize I could just write some code to indent all but the first line by 1 indent, but this isn't really an extensible solution (what if I have 2 indents? or 3? etc.)

EDIT: Before you post an answer, consider how your solution works with something like this:

'''
<
    %s
    <
        %s
        %s
        <
            %s
        >
    >
>
''' % (p1, p2, p3, p4)

Upvotes: 3

Views: 4476

Answers (4)

MattH
MattH

Reputation: 38245

Okay, the simple doesn't suit your purposes. Either you need to use a document object model and a flattening system with appropriate indentation.

Or, you could do something fairly hacky to detect the amount of whitespace before each substitution. This is pretty fragile:

import re

def ind_sbt(text,indent='\t'):
    return text.replace('\n','\n%s' % (indent,))

def adjust_indents(fmtstr,*args):
    """Hacky, crude detection of identation level"""
    indented_substitutions = re.compile(r'\n(\s+)%s')
    return fmtstr % tuple([ ind_sbt(arg,indent=i) for (arg,i) in zip(args,indented_substitutions.findall(fmtstr))])

p1 = p2 = p3 = p4 = "foo\nbar"

print adjust_indents('''
<
    %s
    <
        %s
        %s
        <
            %s
        >
    >
>
''',p1,p2,p3,p4)

Yielding:

<
        foo
        bar
        <
                foo
                bar
                foo
                bar
                <
                        foo
                        bar
                >
        >
>

Upvotes: 1

Michael
Michael

Reputation: 9068

Python's textwrap module is your friend, especially its initial_indent and subsequent_indent parameters.

Upvotes: 1

Tim Pietzcker
Tim Pietzcker

Reputation: 336418

How about this:

'''
<
   %s
>
''' % ("\n   ".join(paragraph.split("\n")))

Result:

<
   foo
   bar
>

The string used in the .join() method must contain the same whitespace (plus a \n at the start) as whatever comes before %s in your string.

Upvotes: 2

Yuval Adam
Yuval Adam

Reputation: 165292

You can't expect the Python interpreter to automagically indent your paragraph. Would you want the interpreter messing around with your data? (Hint: NO.)

What you can do is inject whitespace:

'''
<
    %s
>
''' % (paragraph.replace('\n','\n    ')) # assuming 4 space soft tabs

But I would very much refrain from that unless you absolutely have to, since you have no idea which line endings you might be dealing with, and generally feels kind of awkward.

Upvotes: 1

Related Questions