2009-09-11 8 views
33

Ich habe einen Python-Editor, in dem der Benutzer ein Skript oder einen Code eingeben, der dann in ein Hauptverfahren hinter den Kulissen gelegt wird, während auch eingekerbt jede Zeile mit. Das Problem besteht darin, dass, wenn ein Benutzer eine mehrzeilige Zeichenfolge hat, die Einrückung, die für das gesamte Skript vorgenommen wird, die Zeichenfolge beeinflusst, indem eine Registerkarte in jeden Bereich eingefügt wird. Ein Problem Skript würde etwas so einfach wie sein:Wie kann man die zusätzliche Einrückung von mehrzeiligen Python-Dreifachziffern entfernen?

"""foo 
bar 
foo2""" 

Also, wenn im Hauptverfahren es aussehen würde:

def main(): 
    """foo 
    bar 
    foo2""" 

und die Saite jetzt eine zusätzliche Registerkarte am Anfang jeder Zeile hätte .

+0

http://codereview.stackexchange.com/questions/60366/avoiding-python-multiline-string-indentation –

Antwort

0

Also, wenn ich es richtig zu erhalten, nehmen Sie unabhängig von den Benutzereingaben, es richtig einrücken und an den Rest des Programms wird (und dann das ganze Programm ausführen).

So, nachdem Sie die Benutzereingabe in das Programm setzen, könnten Sie einen regulären Ausdruck ausführen, die im Grunde zurück, dass Zwang Einzug nimmt. So etwas wie: Ersetzen Sie in drei Anführungszeichen alle neuen Zeilenmarkierungen, gefolgt von vier Leerzeichen (oder einer Registerkarte) mit nur einer neuen Zeilenmarkierung.

+0

ja genau. Das ist die einzige mögliche Lösung, die ich mir ausgedacht habe. Ich bin mir nicht sicher, warum ich nicht weitergemacht habe ... Ich denke, ich muss das vielleicht tun, wenn nichts Besseres kommt. –

+12

@ thraxils Vorschlag, textwrap.dedent zu verwenden, ist der richtige Weg. Überlege dir, deine akzeptierte Antwort zu ändern. –

1

Der einzige Weg, i sehen - ist ersten n Laschen für jede Zeile mit dem zweiten Ausgangs abzustreifen, wobei n identation der Hauptverfahren bekannt ist.

Wenn das identation nicht vorher bekannt - Sie hinzufügen können Newline Hinter, bevor sie und Streifen Anzahl der Registerkarten aus der letzten Zeile ...

Die dritte Lösung eingefügt ist, Daten zu analysieren und zu Beginn des mehrzeiligen Angebot zu finden und Fügen Sie Ihre Identität nicht jeder Zeile hinzu, bis sie geschlossen wird.

Denken gibt es eine bessere Lösung ..

+0

Danke für die Antwort. Sie schlagen also vor, jede Zeile des eingefügten Einzugs zu entfernen? Ich bin verwirrt ... –

15

Was die erste Zeile einer mehrzeiligen Zeichenfolge folgt, ist Teil der Zeichenfolge und nicht als Einschnitt durch den Parser behandelt. Sie können frei schreiben:

def main(): 
    """foo 
bar 
foo2""" 
    pass 

und es wird das Richtige tun.

Auf der anderen Seite, das ist nicht lesbar, und Python weiß es. Wenn also ein docstring Leerzeichen enthält es Sekunden Linie ist, wird die Menge von Leerzeichen abgezogen, wenn Sie help() verwenden, um das docstring anzuzeigen. So help(main) und die unter help(main2) produzieren die gleiche Hilfe Info.

def main2(): 
    """foo 
    bar 
    foo2""" 
    pass 
+0

Danke für die Antwort.Leider ist der Einzug vollständig automatisiert, da mein Code das Skript als String (in Java) einliest und jede Zeile in diesem String einrückt. –

+0

Ah ich sehe. Dafür kann ich leider keine Hilfe gebrauchen ... aber danke! –

79

textwrap.dedent aus der Standardbibliothek ist es da, um die verrückte Einrückung automatisch rückgängig zu machen.

+1

ordentlich .. wusste nicht darüber .. :) – Macke

+1

Die Standard-Bibliothek hört nie auf Überraschungen zu halten. – thraxil

+0

sehr coole Info. Ich kann es aber nicht benutzen. –

4

Von was ich sehe, eine bessere Antwort hier könnte inspect.cleandoc sein, die funktionell was textwrap.dedent tut tut aber auch die Probleme behebt, die textwrap.dedent mit der führenden Linie hat. Das folgende Beispiel zeigt die Unterschiede:

>>> import textwrap 
    >>> import inspect 
    >>> x = """foo bar 
     baz 
     foobar 
     foobaz 
     """ 
    >>> inspect.cleandoc(x) 
    'foo bar\nbaz\nfoobar\nfoobaz' 
    >>> textwrap.dedent(x) 
    'foo bar\n baz\n foobar\n foobaz\n' 
    >>> y = """ 
    ...  foo 
    ...  bar 
    ... """ 
    >>> textwrap.dedent(y) 
    '\nfoo\nbar\n' 
    >>> inspect.cleandoc(y) 
    'foo\nbar'