![]() |
Delphi-Version: 2007
QuoteText parsen?
Das ist [clRed]ein[/clRed][fsBold]Test[/fsBold].
Wie soll ich das denn [clBlue][fsBold]machen[/clBlue][/fsBold]? Hat jemand eine Idee wie man sowas elegant splitten kann (Pseudocode reicht völlig)? :gruebel: |
AW: QuoteText parsen?
Moin...
Du möchtest quasi den Text ohne die "[...]"? Dann eine function gebaut welche genau diese Blöcke durch '' ersetzt. Stichworte: Copy PosEx |
AW: QuoteText parsen?
Oder StringReplace oder reguläre Ausdrücke (müssten aber unter Delphi 2007 nachgerüstet werden IIRC).
|
AW: QuoteText parsen?
Zitat:
Delphi-Quellcode:
type
TWordInfo = record Value: string; Style: TFontStyles; Color: TColor; procedure Draw(Canvas: TCanvas; MMX, MMY: double); end; TWordLine = class .. end; |
AW: QuoteText parsen?
Es gibt bestimmt irgendwo einen BBCode-Parser, welcher das in RTF umwandelt, was fertig formatiert gedruckt werden könnte.
Ansonsten gehst du halt hin: * Text suchen, bis zum nächsten [ (bei [ ohne Zugehörigkeit zu einem SteuerCode einen Fehler werfen oder es als Text betrachten und weitersuchen) * den Text drucken * X-Position um Textbreite verschieben * das zwischen [ und ] suchen/auswerten * Font entsprechen umschalten * von vorne beginnen, bis der Text zu Ende ist Wenn es nicht zu viele Steuerbefehle sind und man die mit einem Bit speichern könnte, dann könnte man vorher die Befehle durch jeweils ein Zeichen ersetzen und hat dann beim Drucken weniger Aufwand das zu parsen (z.b. #1=fett #2=nicht mehr fett #3= (bis #31, außer #8, #10 und #13 und in Unicode gibt es ein paar nette freie User-Bereiche) * nächstes Steuerzeichen ode Textende suchen * Text davor drucken und X verschieben * Font umschalten * von vorne beginnen Man kann das auch gerne in einen Baum zerlegen (mit Text/Steuerbefehlen) und den Baum dann abarbeiten, falls man auch auf Rekursionen reagieren will ... ineinander verschachtelte Befehle, bzw man verwendet eine Referenzzählung für das Aktivieren/Deaktivieren, bzw. eine Queue. |
AW: QuoteText parsen?
|
AW: QuoteText parsen?
Liste der Anhänge anzeigen (Anzahl: 1)
Nur so zum Starten ein kleiner Parser (als State-Machine) quick und dirty.
Der kann auf jeden Fall das hier produzieren Anhang 42107
Delphi-Quellcode:
UPDATE
unit Parser.BBCode;
interface uses Vcl.Graphics, System.SysUtils, System.Generics.Collections; type TTextPart = class private FFont: TFont; FText: string; public constructor Create( AFont: TFont; const AText: string ); property Font: TFont read FFont; property Text: string read FText; end; TBBCodeParser = class private type TState = procedure( AChar: Char ) of object; private FParts: TList<TTextPart>; FCommandStack: TList<string>; FDefaultFont: TFont; FState: TState; FFont: TFont; FTextBuffer: TStringBuilder; FCommandBuffer: TStringBuilder; procedure InitParser; procedure ParseText( AChar: Char ); procedure ParseCommand( AChar: Char ); procedure ParseCloseCommand( AChar: Char ); procedure HandleTextBuffer; procedure HandleCommandBuffer( Closing: Boolean = False ); public constructor Create( ADefaultFont: TFont ); destructor Destroy; override; procedure Parse( AText: string ); property Parts: TList<TTextPart> read FParts; end; implementation uses System.StrUtils; { TBBCodeParser } constructor TBBCodeParser.Create( ADefaultFont: TFont ); begin inherited Create; FDefaultFont := ADefaultFont; FFont := TFont.Create; FTextBuffer := TStringBuilder.Create; FCommandBuffer := TStringBuilder.Create; FParts := TObjectList<TTextPart>.Create; FCommandStack := TList<string>.Create; end; destructor TBBCodeParser.Destroy; begin FFont.Free; FTextBuffer.Free; FCommandBuffer.Free; FParts.Free; FCommandStack.Free; inherited; end; procedure TBBCodeParser.HandleCommandBuffer( Closing: Boolean ); const FontStyle: array [TFontStyle] of string = ( 'fsBold', 'fsItalic', 'fsUnderline', 'fsStrikeOut' ); var LCommand: string; LIdx: Integer; begin LCommand := FCommandBuffer.ToString; FCommandBuffer.Clear; if Closing then begin // von hinten aus dem Stack nehmen for LIdx := FCommandStack.Count - 1 downto 0 do if FCommandStack[LIdx] = LCommand then begin FCommandStack.Delete( LIdx ); Break; end; end else // Einfach an den Stack anhängen FCommandStack.Add( LCommand ); // Font einstellen FFont.Assign( FDefaultFont ); for LCommand in FCommandStack do begin LIdx := IndexText( LCommand, FontStyle ); if LIdx >= 0 then FFont.Style := FFont.Style + [TFontStyle( LIdx )]; if LCommand.StartsWith( 'cl', True ) then FFont.Color := StringToColor( LCommand ); end; end; procedure TBBCodeParser.HandleTextBuffer; begin if FTextBuffer.Length > 0 then begin FParts.Add( TTextPart.Create( FFont, FTextBuffer.ToString ) ); FTextBuffer.Clear; end; end; procedure TBBCodeParser.InitParser; begin FFont.Assign( FDefaultFont ); FTextBuffer.Clear; FCommandBuffer.Clear; FCommandStack.Clear; FParts.Clear; FState := ParseText; end; procedure TBBCodeParser.Parse( AText: string ); var LChar: Char; begin InitParser; for LChar in AText do FState( LChar ); HandleTextBuffer; end; procedure TBBCodeParser.ParseCloseCommand( AChar: Char ); begin case AChar of ']': begin HandleTextBuffer; HandleCommandBuffer( True ); FState := ParseText; end; else FCommandBuffer.Append( AChar ); end; end; procedure TBBCodeParser.ParseCommand( AChar: Char ); begin case AChar of ']': begin HandleTextBuffer; HandleCommandBuffer( False ); FState := ParseText; end; '/': FState := ParseCloseCommand; else FCommandBuffer.Append( AChar ); end; end; procedure TBBCodeParser.ParseText( AChar: Char ); begin case AChar of '[': FState := ParseCommand; else FTextBuffer.Append( AChar ); end; end; { TTextPart } constructor TTextPart.Create( AFont: TFont; const AText: string ); begin inherited Create; FFont := TFont.Create; FFont.Assign( AFont ); FText := AText; end; end. So mit der kleinen Änderung (CommandStack) können jetzt auch verschachtelte Commands verarbeitet werden. So z.B.
Code:
Ist dann das gleiche Ergebnis:
normal [clRed]rot [clGreen]grün [/clGreen]wieder rot [/clRed]normal
normal [fsBold]fett [fsItalic]fett-kursiv [fsStrikeOut]fett-kursiv-durchgestrichen [fsUnderline]fett-kursiv-durchgestrichen-unterstrichen [/fsBold]kursiv-durchgestrichen-unterstrichen [/fsItalic]durchgestrichen-unterstrichen [/fsStrikeOut]unterstrichen [/fsUnderline]normal Zitat:
Code:
normal [COLOR="Red"]rot [COLOR="Green"]grün [/COLOR]wieder rot [/COLOR]normal
normal [B]fett [I]fett-kursiv [S]fett-kursiv-durchgestrichen [U]fett-kursiv-durchgestrichen-unterstrichen [/U][/S][/I][/B][I][S][U]kursiv-durchgestrichen-unterstrichen [/U][/S][/I][S][U]durchgestrichen-unterstrichen [/U][/S][U]unterstrichen [/U]normal |
AW: QuoteText parsen?
Thanx. Wie immer genial deine Posts. Aber, den Code hab ich fast Null verstanden. Und Generics und TStringBuilder hab ich nich.. :oops:
|
AW: QuoteText parsen?
Das du das nicht hast weiß ich, aber du willst ja auch etwas selber machen ;)
Eigentlich sind diese State-Machines als Parser super simpel zu erstellen:
Wichtig: Vor jeder Änderung durch ein Command muss der aktuelle TextBuffer mit dem aktuellen Font gespeichert werden (wenn der TextBuffer leer ist, dann brauchen wir auch nichts speichern). Nimm dir am Besten einen kurzen Text
Code:
und gehe den Code auf dem Papier durch, dann sollte auch die Erkenntnis kommen :)
a[b]c[d]e[/b]f[/d]g
|
AW: QuoteText parsen?
Meinst Du
![]() Das Ding hatte ich auch noch ein Stück bei mir erweitert, da ich es aber nicht mehr benötigte, habe ich es weggetan und finde es gerade nicht. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:53 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz