2009-09-11 14 views
33

Mam edytor python, w którym użytkownik wprowadza skrypt lub kod, który następnie jest wprowadzany do głównej metody za kulisami, a jednocześnie ma wszystkie wcięte wiersze. Problem polega na tym, że jeśli użytkownik ma ciąg wieloliniowy, wcięcie do całego skryptu wpływa na ciąg znaków, wstawiając tabulator w każdej przestrzeni. Skrypt problemem byłoby coś tak prostego jak:Jak usunąć dodatkowe wcięcie potrójnych cytowanych ciągów wieloliniowych Pythona?

"""foo 
bar 
foo2""" 

Więc kiedy w głównym sposobem to będzie wyglądać:

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

i ciąg będzie teraz mieć dodatkową kartę na początku każdej linii .

+0

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

Odpowiedz

0

Więc jeśli mogę go poprawnie, podjąć wszelkie dane wprowadzane przez użytkownika, wciąć go prawidłowo i dodać go do końca swojego programu (a następnie uruchomić ten cały program).

Po wprowadzeniu danych użytkownika do programu można uruchomić wyrażenie regularne, które w zasadzie powoduje powrót do wymuszonego wcięcia. Coś jak: w trzech cytatach, zamień wszystkie "nowe znaczniki linii", a następnie cztery spacje (lub tabulator) z tylko "nowym znacznikiem linii".

+0

tak, dokładnie. To jedyne możliwe rozwiązanie, które wymyśliłem. Nie wiem, dlaczego nie poszedłem na przód ... Myślę, że być może będę musiał to zrobić, jeśli nic lepszego nie wyjdzie. –

+12

@ Thraxil's sugestia użycia textwrap.dedent jest drogą do zrobienia. Zastanów się nad zmianą zaakceptowanej odpowiedzi. –

1

Jedyny sposób, w jaki widzę - to usuwanie pierwszych n zakładek dla każdej linii zaczynającej się od drugiej, gdzie n jest znaną identyfikacją głównej metody.

Jeśli wcięć nie jest znana wcześniej - można dodać spływu przełamane przed włożeniem go i numer pasek zakładek z ostatniej linii ...

Trzecim rozwiązaniem jest do analizowania danych i znaleźć początek i wielowierszowego cytatem nie dodawaj swojej tożsamości do każdej linii, dopóki nie zostanie zamknięta.

że istnieje lepsze rozwiązanie ..

+0

Dzięki za odpowiedź. Sugerujesz więc, że usuwam każdą linię wcięcia, która została wstawiona? Jestem zdezorientowany ... –

15

Poniżej pierwszą linię wielowierszowego łańcucha jest częścią łańcucha, a nie traktowane jako wcięcia przez parser. możesz swobodnie napisać:

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

i zrobi to, co trzeba.

Z drugiej strony nie można tego odczytać, a python to wie. Jeśli więc docstring zawiera biały znak w jego linii sekund, ta biała spacja jest usuwana, gdy używasz help() do wyświetlania docstringu. Tak więc help(main) i poniżej help(main2) generują te same informacje pomocy.

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

Dzięki za odpowiedź.Niestety wcięcie jest całkowicie zautomatyzowane, ponieważ mój kod czyta się w skrypcie jako ciąg (w Javie) i wcina każdy wiersz w tym łańcuchu. –

+0

Ah Widzę. Nie mogę jednak pomóc w tej sprawie ... dzięki! –

79

textwrap.dedent ze standardowej biblioteki jest tam, aby automatycznie cofnąć zwariowane wcięcie.

+1

schludny .. nie wiedziałem o tym .. :) – Macke

+1

Standardowa biblioteka nigdy nie przestaje posiadać niespodzianek. – thraxil

+0

bardzo fajne informacje. Nie mogę tego jednak użyć. –

4

Z tego, co widzę, lepszą odpowiedzią tutaj może być inspect.cleandoc, która funkcjonalnie wykonuje to, co textwrap.dedent, ale także rozwiązuje problemy, które ma textwrap.dedent z wiodącą linią. Poniższy przykład pokazuje różnice:

>>> 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' 
Powiązane problemy