AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

QuoteText parsen?

Ein Thema von Bjoerk · begonnen am 5. Nov 2014 · letzter Beitrag vom 12. Nov 2014
Antwort Antwort
Seite 1 von 4  1 23     Letzte »    
Bjoerk

Registriert seit: 28. Feb 2011
Ort: Mannheim
1.384 Beiträge
 
Delphi 10.4 Sydney
 
#1

QuoteText parsen?

  Alt 5. Nov 2014, 16:41
Delphi-Version: 2007
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)?
  Mit Zitat antworten Zitat
Benutzerbild von haentschman
haentschman

Registriert seit: 24. Okt 2006
Ort: Seifhennersdorf / Sachsen
5.289 Beiträge
 
Delphi 12 Athens
 
#2

AW: QuoteText parsen?

  Alt 5. Nov 2014, 16:56
Moin...

Du möchtest quasi den Text ohne die "[...]"? Dann eine function gebaut welche genau diese Blöcke durch '' ersetzt.
Stichworte:
Copy
PosEx
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.537 Beiträge
 
Delphi 11 Alexandria
 
#3

AW: QuoteText parsen?

  Alt 5. Nov 2014, 17:02
Oder StringReplace oder reguläre Ausdrücke (müssten aber unter Delphi 2007 nachgerüstet werden IIRC).
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
Bjoerk

Registriert seit: 28. Feb 2011
Ort: Mannheim
1.384 Beiträge
 
Delphi 10.4 Sydney
 
#4

AW: QuoteText parsen?

  Alt 5. Nov 2014, 17:13
Moin...

Du möchtest quasi den Text ohne die "[...]"? Dann eine function gebaut welche genau diese Blöcke durch '' ersetzt.
Stichworte:
Copy
PosEx
Fast. Das ganze soll gedruckt werden. Die Quotes verstehen sich als Canvas.Font Attribute.

Delphi-Quellcode:
type
  TWordInfo = record
    Value: string;
    Style: TFontStyles;
    Color: TColor;
    procedure Draw(Canvas: TCanvas; MMX, MMY: double);
  end;

  TWordLine = class
    ..
  end;

Geändert von Bjoerk ( 5. Nov 2014 um 17:15 Uhr) Grund: Some Code
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.115 Beiträge
 
Delphi 12 Athens
 
#5

AW: QuoteText parsen?

  Alt 5. Nov 2014, 17:16
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.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests

Geändert von himitsu ( 5. Nov 2014 um 17:27 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von p80286
p80286

Registriert seit: 28. Apr 2008
Ort: Stolberg (Rhl)
6.659 Beiträge
 
FreePascal / Lazarus
 
#6

AW: QuoteText parsen?

  Alt 5. Nov 2014, 17:21
Delphi-Referenz durchsuchenAnsiReplaceText

Gruß
K-H

Oh Mann vergiß es
Programme gehorchen nicht Deinen Absichten sondern Deinen Anweisungen
R.E.D retired error detector
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#7

AW: QuoteText parsen?

  Alt 5. Nov 2014, 18:23
Nur so zum Starten ein kleiner Parser (als State-Machine) quick und dirty.
Der kann auf jeden Fall das hier produzieren
dp_182623.png
Delphi-Quellcode:
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.
UPDATE
So mit der kleinen Änderung (CommandStack) können jetzt auch verschachtelte Commands verarbeitet werden.
So z.B.
Code:
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
Ist dann das gleiche Ergebnis:
Zitat:
normal rot grün wieder rot normal
normal fett fett-kursiv fett-kursiv-durchgestrichen fett-kursiv-durchgestrichen-unterstrichen kursiv-durchgestrichen-unterstrichen durchgestrichen-unterstrichen unterstrichen normal
wie hier mit den BBCodes
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
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)

Geändert von Sir Rufo ( 5. Nov 2014 um 18:51 Uhr)
  Mit Zitat antworten Zitat
Bjoerk

Registriert seit: 28. Feb 2011
Ort: Mannheim
1.384 Beiträge
 
Delphi 10.4 Sydney
 
#8

AW: QuoteText parsen?

  Alt 5. Nov 2014, 20:52
Thanx. Wie immer genial deine Posts. Aber, den Code hab ich fast Null verstanden. Und Generics und TStringBuilder hab ich nich..
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#9

AW: QuoteText parsen?

  Alt 5. Nov 2014, 21:33
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:
  • Ein Parser geht Zeichen für Zeichen durch den String -> Wir brauchen eine Methode die einen Char entgegennimmt. Da aber je nach Status eine andere Methode benötigt wird brauchen wir erst mal so einen Methodentyp TState = procedure(AChar:Char) of object;
  • Die erste Methode ist ganz simpel, es wird einfach jedes Zeichen an den TextBuffer gehängt (das kann ein einfacher String sein, ein TStringBuilder ist dafür nur schneller, mehr nicht). Nennen wir die einfach mal ParseText . Trifft man hier nun auf das Zeichen '[' , dann kommt jetzt ein Kommando. Also müssen wir ab nun das aus einer anderen Sicht betrachten, denn der Status hat sich geändert. Wir parsen jetzt ein Kommando, also eine weitere Methode ParseCommand
  • In parseCommand werden alle eingehenden Zeichen an den CommandBuffer gehängt, bis wir auf das Zeichen ']' treffen.
  • Für weitere Stati verfährt man genauso und baut diese Schritt für Schritt auf.
Eigentlich ist es ein ganz stupides Abarbeiten der Vorgaben. Interessant wird dann der Teil, wo die Commands in den CommandStack ein- und ausgetragen werden und darüber der aktuelle Font "errechnet" wird.

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:
a[b]c[d]e[/b]f[/d]g
und gehe den Code auf dem Papier durch, dann sollte auch die Erkenntnis kommen
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Jens01

Registriert seit: 14. Apr 2009
670 Beiträge
 
#10

AW: QuoteText parsen?

  Alt 5. Nov 2014, 22:18
Meinst Du das?
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.
Achtung: Bin kein Informatiker sondern komme vom Bau.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 4  1 23     Letzte »    


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:11 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz