Terminalausgabe bunt machen
Nur hab ich bei PyParsing eben so Dinge wie `nestedExpr()` gesehen. Ich sträube mich ehrlich gesagt ein bißchen, das in regulären Ausdrücken nachzuimplementieren, wenn es doch schon eine Bibliothek gibt, die sowas unterstützt. Sonst heißt es auch immer, man soll das Rad nicht neu erfinden. Bei so ziemlich jedem Thread, der fragt, wie man bestimmte Teile aus dem Quelltext einer Website holen kann, wird sofort auf ElementTree & Co verwiesen und jetzt plötzlich soll es keine gute Idee sein, PyParsing zu verwenden, weil es Overkill ist? Sorry, aber je mehr ich darüber nachdenke, desto weniger kann ich diese Haltung nachvollziehen.
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Naja, ElementTree ist teil der Stdlib, daher kostet die verwendung davon nichts, wohingegen PyParsing ein externes Dependency ist.
Also wenn ich sowas machen sollte würde ich mir inzwischen eher funcparserlib, pyPEG oder picoparse anschauen. Wenn ich unbedingt eine Parser-Library nutzen will.
Also wenn ich sowas machen sollte würde ich mir inzwischen eher funcparserlib, pyPEG oder picoparse anschauen. Wenn ich unbedingt eine Parser-Library nutzen will.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Die Sache ist halt, dass ich reinen Regex-Code persönlich schlecht lesbar und somit auch schlecht wartbar sowie fehleranfällig finde, sobald man dann doch mal irgendeinen Fall vergessen hat. Eben ähnlich wie beim Parsen von HTML. Dass solche Module nicht in der Stdlib integriert sind, ist für mich auch wirklich das einzige Gegenargument. Ich denke aber, man kann vom Benutzer in dem Fall ruhig erwarten, dass er ein Modul via Paketmanager bzw easy_install nachinstalliert, denn das Parsen des Markups ist hier ja ein wesentlicher Bestandteil.
Danke übrigens für die Links. PyParsing hatte ich nur aus dem Grund gewählt, weil mir nichts anderes bekannt war.
Danke übrigens für die Links. PyParsing hatte ich nur aus dem Grund gewählt, weil mir nichts anderes bekannt war.
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Also ich finde meinen Parser in PyParsing direkt noch schlechter lesbar und wartbar, weil der komische Sachen macht und ich immer dem Autor mailen muss, der mir dann ein noch hässlicher ausschauendes Codeschnippsel zurückmailt, das diesen Bug nicht hat.snafu hat geschrieben:Die Sache ist halt, dass ich reinen Regex-Code persönlich schlecht lesbar und somit auch schlecht wartbar sowie fehleranfällig finde, sobald man dann doch mal irgendeinen Fall vergessen hat.
Wie gesagt: nicht begeistert.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Naja, ich werde mir wahrscheinlich `funcparser` näher ansehen. Da gibt es ja sogar ein Tutorial zum Thema Verkettung. Was auch eine Idee wäre: Erstmal mit einem solchen Hilfstool alles aufbauen bis es läuft und anschließend die relevanten Teile rauskopieren. Mir ist besonders beim `picoparser` aufgefallen, dass der relativ simpel strukturiert ist.
Hört sich doch insgesamt ganz okay an.funcparserlib is a library for recursive descent parsing using parser
combinators. The parsers made with its help are LL(*) parsers. It means that
it's very easy to write them without thinking about look-aheads and all that
hardcore parsing stuff. But the recursive descent parsing is a rather slow
method compared to LL(k) or LR(k) algorithms. So the primary domain for
funcparserlib is parsing small languages or external DSLs (domain specific
languages).
Erstens wirst du von mir selten das NIH-Argument hören, denn ich bin im Zweifel lieber für die einfache eigene Lösung als eine Abhängigkeit zu einer anderen Bibliothek und zweitens ist das IMHO nicht vergleichbar, denn das Problem, das in der Realität meist total kaputte HTML zu parsen ist schwer im Vergleich dazu, Sternchen in Escape-Sequenzen zu verwandeln. Und während HTML immer rekursiv ist, würde ich die Escape-Sequenzen nicht schachteln. Da stößt du sowieso an die Grenzen was so ein VT-100-Terminal so kann.snafu hat geschrieben:Bei so ziemlich jedem Thread, der fragt, wie man bestimmte Teile aus dem Quelltext einer Website holen kann, wird sofort auf ElementTree & Co verwiesen und jetzt plötzlich soll es keine gute Idee sein, PyParsing zu verwenden, weil es Overkill ist?
Stefan
Also bisher hat das Terminal kein Problem mit fett blinkend unterstrichen grüner Schrift auf gelbem Hintergrund. Und bei Rekursion wird's echt übel. Da dies an sich nicht in einer Python-Regexp möglich ist, müsste man drum herum bauen. Ich überlege schon, ob ich in diesem Fall nicht lieber Perl nutzen möchte. Letztlich spielt ja das Markup die Hauptrolle und die Definition der SGR-Konstanten ist ja nun nicht sehr Python-spezifisch. Die Beschränkungen von Python sind hier eher hinderlich und ich sehe eigentlich nicht ein, wieso ich auf die Rekursion verzichten sollte, nur weil Python da nicht mitmacht.
Nachdem mir das bisher alles noch nicht so zugesagt hat, werde ich mal einen Blick auf Plex werfen, wo mir vor allem der ereignisorientierte Ansatz gefällt. Eventuell nehme ich die Klamotte am Wochenende nochmal in Angriff. Mal sehen...
Neue Version mit anderem Markup. Farben und Escapen sind noch nicht implementiert.
http://paste.pocoo.org/show/169413/
EDIT: Ich merke gerade, dass das noch nicht mit überlappenden Verschachtelungen klar kommt. Wird also noch geändert.
http://paste.pocoo.org/show/169413/
EDIT: Ich merke gerade, dass das noch nicht mit überlappenden Verschachtelungen klar kommt. Wird also noch geändert.
@snafu:
Falls Du noch an der farbigen Konsolenausgabe interessiert bist, hier mal eine einfache Version für Windows --> http://paste.pocoo.org/show/200261/
Vllt. willst Du ja eine plattformübergreifende Lösung erstellen.
Das Markup ist ziemlich simpel gehalten, da kannst Du sicher nachbessern.
Was geht:
Vordergrund-/Hintergrundfarbe und Intensität setzen (vergleichbar mit bold) und diese wiederzurücksetzen, wobei es keine "inneren" Farbereiche gibt, sondern der Ausgangswert wiederhergestellt wird. Mit '{@' lassen sich die Tags escapen, desweiteren gibts noch eine 'clrscr()'-Methode und eine Methode zum Setzen der Farbe für die gesamte Konsole.
Blinken und Unterstreichen funktioniert in Windows leider nur mit CJK-Schriften, daher hab ichs nicht weiterverfolgt.
Grüße jerch
Falls Du noch an der farbigen Konsolenausgabe interessiert bist, hier mal eine einfache Version für Windows --> http://paste.pocoo.org/show/200261/
Vllt. willst Du ja eine plattformübergreifende Lösung erstellen.
Das Markup ist ziemlich simpel gehalten, da kannst Du sicher nachbessern.
Was geht:
Vordergrund-/Hintergrundfarbe und Intensität setzen (vergleichbar mit bold) und diese wiederzurücksetzen, wobei es keine "inneren" Farbereiche gibt, sondern der Ausgangswert wiederhergestellt wird. Mit '{@' lassen sich die Tags escapen, desweiteren gibts noch eine 'clrscr()'-Methode und eine Methode zum Setzen der Farbe für die gesamte Konsole.
Blinken und Unterstreichen funktioniert in Windows leider nur mit CJK-Schriften, daher hab ichs nicht weiterverfolgt.
Grüße jerch
Das Projekt lebt ürigens noch. Hier nochmal die wichtigsten Attribute auf einem Blick:
Hilfe zum Zusammensetzen:
Ich habe inzwischen auch eine Syntax für die möglichst einfache Anwendung innerhalb von Strings im Kopf:
- Attribute werden in spitzen Klammern geschrieben
- Für die Vordergrundfarbe wird ein `#` vor den Namen geschrieben
- Für die Hintergrundfarbe ein `&`
- Ein `/` vor dem Namen meint das entsprechende "Off-Attribut"
- Ein `/` ohne Namen meint `reset`
- Ein `/#` steht für `default` als Vordergrund
- Analog dazu `/&`
- Mehree Attributnamen werden durch `,` getrennt
- Whitespace zwischen Trenner und Attributnamen wird ignoriert
- Zugriff auf die Namen ist unabhängig von Groß- und Kleinschreibung
- Der Parser ist keine State-Machine, ein `/` ist wie gesagt einfach eine Art Synonym
Beispiele:
'This is a <bold,#red>very</> important thing.'
'<#green,&black>That message from outer space <bold>must</bold> end somehow.</>'
Code: Alles auswählen
states = {
'background': {
'black': 40,
'blue': 104,
'cyan': 106,
'default': 49,
'green': 102,
'magenta': 105,
'red': 101,
'yellow': 103,
'white': 107},
'blink': 5,
'blink_off': 25,
'bold': 1,
'bold_off': 22,
'foreground': {
'black': 30,
'blue': 94,
'cyan': 96,
'default': 39,
'green': 92,
'magenta': 95,
'red': 91,
'yellow': 93,
'white': 97},
'inverse': 7,
'inverse_off': 27,
'reset': 0,
'strike': 9,
'strike_off': 29,
'underline': 4,
'underline_off': 24}
Code: Alles auswählen
ESC = '\x1b'
CSI = ESC + '['
def make_sequence(*num_attrs):
attrs = ';'.join(str(attr) for attr in num_attrs)
return '{0}{1}m'.format(CSI, attrs)
- Attribute werden in spitzen Klammern geschrieben
- Für die Vordergrundfarbe wird ein `#` vor den Namen geschrieben
- Für die Hintergrundfarbe ein `&`
- Ein `/` vor dem Namen meint das entsprechende "Off-Attribut"
- Ein `/` ohne Namen meint `reset`
- Ein `/#` steht für `default` als Vordergrund
- Analog dazu `/&`
- Mehree Attributnamen werden durch `,` getrennt
- Whitespace zwischen Trenner und Attributnamen wird ignoriert
- Zugriff auf die Namen ist unabhängig von Groß- und Kleinschreibung
- Der Parser ist keine State-Machine, ein `/` ist wie gesagt einfach eine Art Synonym
Beispiele:
'This is a <bold,#red>very</> important thing.'
'<#green,&black>That message from outer space <bold>must</bold> end somehow.</>'
Du meinst das jetzt nur wegen den spitzen Klammern und dem Slash, welche den Leser verwirren könnten oder weswegen genau? Ich finde halt, spitze Klammern heben sich besser hervor als eckige.
Und dann noch in die Runde gefragt: Was haltet ihr von der jetzigen Lösung, die ja ohne Verschachtelung und Zuständen auskommen soll?
Und dann noch in die Runde gefragt: Was haltet ihr von der jetzigen Lösung, die ja ohne Verschachtelung und Zuständen auskommen soll?
Habe es jetzt mal als Tefos 0.0.1 rausgebracht. Das Formatting ist natürlich noch sehr beschissen und wird noch den angekündigten Parser bekommen. Auch zusätzliche Farben werden beim nächsten Mal aufgenommen.
Hi, ich finde das Thema Markup recht Interessant.
Um deine Syntax ein bisschen simpler zu halten, wie wäre es wenn du es ähnlich machst wie defnull es schon auf der ersten seite angesprochen hatte, nur halt mit spitzen Klammern: <bold,#red TEXT>
Ich bin der meinung das sich das um ein vielfaches leichter schreiben lässt. Evtl kannst du den Text ja noch mit einer Pipe abgrenzen: <bold,#red|TEXT>
Natürlich hat man auch noch die Möglichkeit zu verschachteln: <bold,#red|ROT <#blue|BLAU>>
Was hälst du von diesem Vorschlag?
#Edit
Ich sehe gerade, jerch hat einen ähnlichen Vorschlag gemacht.
Um deine Syntax ein bisschen simpler zu halten, wie wäre es wenn du es ähnlich machst wie defnull es schon auf der ersten seite angesprochen hatte, nur halt mit spitzen Klammern: <bold,#red TEXT>
Ich bin der meinung das sich das um ein vielfaches leichter schreiben lässt. Evtl kannst du den Text ja noch mit einer Pipe abgrenzen: <bold,#red|TEXT>
Natürlich hat man auch noch die Möglichkeit zu verschachteln: <bold,#red|ROT <#blue|BLAU>>
Was hälst du von diesem Vorschlag?
#Edit
Ich sehe gerade, jerch hat einen ähnlichen Vorschlag gemacht.
Tefos 0.0.2 ist draußen.
Bitte beachtet, dass der Parser entsprechend der Versionierung noch sehr dumm ist. Es werden bisher stumpf Klammernpaare ersetzt. Weder Verschachtelung, noch Escaping klappt derzeit. Wenn man sich genau an die Regeln hält und keine "unerwarteten" Klammern einbaut, läuft es jedoch wie im Beispiel. Weitere Verbesserungen folgen natürlich noch.
Bitte beachtet, dass der Parser entsprechend der Versionierung noch sehr dumm ist. Es werden bisher stumpf Klammernpaare ersetzt. Weder Verschachtelung, noch Escaping klappt derzeit. Wenn man sich genau an die Regeln hält und keine "unerwarteten" Klammern einbaut, läuft es jedoch wie im Beispiel. Weitere Verbesserungen folgen natürlich noch.
- jens
- Python-Forum Veteran
- Beiträge: 8502
- Registriert: Dienstag 10. August 2004, 09:40
- Wohnort: duisburg
- Kontaktdaten:
Hab mir auch was gebastelt, allerdings ohne ein "markup":
http://paste.pocoo.org/show/271344/
sieht dann so aus:
Es wird auch geprüft, ob überhaupt Escape Sequenzen nutzbar sind...
Das ganze ist geklaut von django, siehe: http://code.djangoproject.com/browser/d ... mcolors.py
http://paste.pocoo.org/show/271344/
sieht dann so aus:
Code: Alles auswählen
>>> c = ColorOut()
>>> c.colorize('no color')
'no color'
>>> c.colorize('bold', opts=("bold",))
'\\x1b[1mbold\\x1b[0m'
>>> c.colorize("colors!", foreground="red", background="blue", opts=("bold", "blink"))
'\\x1b[31;44;1;5mcolors!\\x1b[0m'
Das ganze ist geklaut von django, siehe: http://code.djangoproject.com/browser/d ... mcolors.py
Sphinx hat da auch was dabei...
the more they change the more they stay the same