delphivcltrichedit

How to highlight only the lines contain the 'MyString' in a RichEdit?


I have created a small program the read a text file.

Once the text file is opened in a RichEdit, I want to change the background color of lines that contain a certain string, or to hide all lines that do not contain the string. Is it possible?

I have tried to search for the string, but I haven't any idea of how to do what I'm asking for.

function SearchText(Control: TCustomEdit; Search: string; SearchOptions: TSearchOptions): Boolean;
var
  Text: string;
  Index: Integer;
begin
  if soIgnoreCase in SearchOptions then
  begin
    Search := UpperCase(Search);
    Text := UpperCase(Control.Text);
  end
  else
    Text := Control.Text;

  Index := 0;
  if not (soFromStart in SearchOptions) then
    Index := PosEx(Search, Text, Control.SelStart + Control.SelLength + 1);
  if (Index = 0) and
      ((soFromStart in SearchOptions) or
       (soWrap in SearchOptions)) then
    Index := PosEx(Search, Text, 1);
  Result := Index > 0;
  if Result then
  begin
    Control.SelStart := Index - 1;
    Control.SelLength := Length(Search);
  end;
end;

Solution

  • This is kind of a poor SO question, because it is a bit like "please write the code for me".

    The natural approach would be to find the independent parts of the problem:

    1. How to represent an array of strings (lines) in Delphi?

    2. How to load a text file in Delphi into some in-memory array of strings?

    3. How to search for a substring in a string in Delphi?

    4. How to filter a Delphi in-memory array of strings? [This is trivial if you know 1 and has heard of loops. Doing it efficiently is slightly more interesting.]

    5. How to populate a Delphi TRichEdit control?

    Indeed, if you know the answers to 1--5, doing what you want is trivial!

    I might seem like a very grumpy old man now, but I think I do have a very important point about how to approach a programming problem.

    Anyhow, let us address one issue at a time:

    1. The old-school approach of a array of string, today written TArray<string> works. This is a dynamic array of strings. Since Delphi dynamic arrays are managed by the compiler, they are convenient because you don't need to create and free them manually. However, they are a bit low-level and are sometimes misused.

      Probably a better alternative for you is to use the TStringList class.

    2. In IOUtils, you find TFile.ReadAllLines which takes a file name and returns the contents of the (text) file as an array of strings.

      Or use TStringList.LoadFromFile if you have a TStringList.

    3. Traditionally, you would use the Pos function. But today you can use the string helper: MyString.Contains(). Obviously, you need to decide if you want to treat CAPITALS and small letters as identical or not.

    4. Use a trivial for or for in loop to populate a second array from the original array, based on the test from 3.

    5. If you have a TStringList, just use TRichEdit.Lines.Assign.

    Putting it all together, using a fairly smart combination of string arrays and TStringList:

    procedure TForm1.Button1Click(Sender: TObject);
    begin
    
      var Lines := TFile.ReadAllLines('K:\test.txt');
    
      var FilteredLines := TStringList.Create;
      try
    
        for var Line in Lines do
          if Line.Contains('MyString') then
            FilteredLines.Add(Line);
    
        RichEdit1.Lines.Assign(FilteredLines);
    
      finally
        FilteredLines.Free;
      end;
    
    end;