Иногда мы не понимаем как работает регулярное выражение, которое мы составили, и хотим проверить. Есть множество восхитительных приложений встроенных в различные среды или онлайн. Мне захотелось добавить еще одно к этому списку.

В данной статье мы посмотрим, как можно обернуть Regex в кроссплатформенную графику и получить простенькое приложение для теста регулярных выражений.



Начало


Для того, чтобы создать проект с использованием avalonia ui нужно установить шаблоны с GitHub.
И создать проект из шаблона mvvm.

dotnet new avalonia.mvvm -o MyApp

Дизайн и разметка


Для создания основного окна разместим все компоненты внутри грида.

 <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="5" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="5" />
            <RowDefinition Height="*" />
            <RowDefinition Height="5" />
        </Grid.RowDefinitions>
    </Grid>

Наше приложение состоит из 2?х частей: верхнего аналога тулбара и рабочей области.



Рассмотрим верхнюю часть


Тут у нас поле для ввода регулярного выражения, чекбокс, показывающий, как анализировать текст (построчно или как целый фрагмент) и кнопка справки.

В качестве контейнера выступает Док панель. Данный контрол позволяет легко заполнить контейнер элементами, прижимая их к разным сторонам и гарантируя отсутствие свободного места внутри.

 <DockPanel Grid.Row="1">

И заполняем ее полем для ввода текста:

 <TextBox Margin="5, 0, 5, 0" Watermark="Your regexp" AcceptsReturn="False"  Text="{Binding RegText}"/>

Здесь стоит отметить приятную мелочь для Avalonia ui — наличие watermark у текстовых полей.

Добавим на панель чекбокс, имеющий 2 состояния, о чем говорит IsThreeState=«False»:

 <CheckBox DockPanel.Dock="Right" Content="By row" IsThreeState="False" IsChecked="{Binding IsChecked}" ToolTip.Tip="Check for each row" />

И кнопку, отвечающую за вызов справки:

 <Button DockPanel.Dock="Right" Content=" ? " Margin="5, 0, 5, 0" ToolTip.Tip="Show hints" Command="{Binding ShowHelp}" />

Основная часть

Рабочая часть будет помещена в грид:

 <Grid Grid.Row="3">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="Auto" />
                <ColumnDefinition Width="0.75*" />
            </Grid.ColumnDefinitions>
        </Grid>

Поле ввода представлено текст боксом:

 <TextBox Grid.Column="0" AcceptsReturn="True" ScrollViewer.VerticalScrollBarVisibility="Auto" Text="{Binding InputText}"/>

Сплиттер позволяет подобрать удобную визуализацию под свои нужды:

  <GridSplitter Grid.Column="1" />

А поле, отвечающее за отображение результата применения регулярных выражений поместим в бордер так как текст блок не обладает собственной рамкой:

  <Border BorderBrush="Gray" BorderThickness="1" Grid.Column="2">
                <TextBlock  ScrollViewer.VerticalScrollBarVisibility="Auto" Text="{Binding OutputText}" />
            </Border>

Окно справки



для создания нового окна обратимся к терминалу

dotnet new avalonia.window -na MyApp -n MyNewWindow

Данное окно будет содержать лишь справочную информацию и больше ничего, так что, проигнорировав контейнеры, сделаем лист бокс дочерним элементом для данного окна:

 <ListBox ScrollViewer.VerticalScrollBarVisibility="Visible" VirtualizationMode="None">
 </ListBox>

И заполним его одинаковыми элементами по мере необходимости:

     <ListBoxItem>
            <StackPanel Orientation="Horizontal">
                <TextBlock Margin="5"  Text="A single character of: a, b or c" />
                <TextBlock Margin="5"  Classes="green" Text="[abc]" />
            </StackPanel>
        </ListBoxItem>

Разметка достаточно простая: стек панель с 2 полями, единственное что здесь стоит отметить — атрибут Classes, что позволит стилизовать наши окна наподобие css (еще одна приятная фишка Авалонии.

И собственно покрасим сами правила в зеленый цвет:

 <Window.Styles>
        <Style Selector="TextBlock.green">
            <Setter Property="Foreground" Value="Green" />
        </Style>
    </Window.Styles>

Функциональность mvvm


В первую очередь озаботимся полями для всех элементов разметки:

private bool _isChecked;
private string _inputText;
private string _regText;
private string _outputText;

Создадим методы, которые вернут результаты матчинга с исходным тесктом:

private void SetNoRowResult()
        {
            OutputText = string.Join(Environment.NewLine,new Regex(_regText).Matches(_inputText));
        }

И с исходным текстом по линиям, для чего применим Split
 private void SetRowResult()
        {
            var r = new Regex(_regText);
            var s = string.Empty;
            foreach (var line in _inputText.Split( Environment.NewLine,StringSplitOptions.RemoveEmptyEntries))
            {
               
                s += $"--{Environment.NewLine}";
                s+=string.Join(Environment.NewLine,r.Matches(line));
                s += $"{Environment.NewLine}--{Environment.NewLine}";
            }

            OutputText = s;
        }

И добавим метод, отображающий окно справки

public void ShowHelp()
        {
            new HelpWindow().Show();
        }

Свойства и биндинги

Интересной особенностью Авалонии является возможность прибиндить метод напрямую к кнопке:

<Button  Command="{Binding ShowHelp}" />

Чем мы и воспользуемся.

Для остальных полей мы просто прибиндимся к свойствам. Здесь также интересной особенностью является то, что в авалонии обновление привязки происходит при изменении содержимого контрола, что в впф делалось так: UpdateSourceTrigger=PropertyChanged в авалонии работает по умолчанию.

А так как шаблон mvvm авалонии связан с Reactive UI, то и свойства создаются с использованием данной библиотеки:

public string RegText
        {
            get => _regText;
            set
            {
                this.RaiseAndSetIfChanged(ref _regText, value);
                if(_isChecked) SetRowResult();
                else SetNoRowResult();
            }
        }

В заключение

Я надеюсь, что данная статья заинтересует не только тех, кто захочет использовать мой материал и\или как-то улучшить его, но и всех тех, кто знакомится с авалонией или ищет возможности создания кроссплатформенных приложений на c#.

Исходный код (тык).

Хотелось бы сказать спасибо ForNeVeR kekekeks worldbeater
И отметить, что поддержку по c# можно найти тут, а по авалонии вот тут.

Комментарии (13)


  1. WhiteBlackGoose
    01.10.2019 21:43

    Очень мало чего. Это я могу и в np++ сделать. А вот если бы подкрашивать текст в зависимости от паттерна, или что-то типа этого (чтобы отлаживать наши регэкспы)...


    1. Larymar Автор
      01.10.2019 22:29

      Для моих крайне скромных нужд этого хватает)
      Конечно можете и в np++ и в vs, но лично я для себя выбрал тот дизайн который удобнее
      Вы можете поближе познакомится с фреймворком улучшив мою работу или создав свою, не то чтобы подсвечивать очень сложно тык
      Так же для меня очень важно показать достаточно простой и понятный пример, который поможет присоединиться новым пользователям к комьюнити авалонии, и я верю, что в данной статье я выполнил эту задачу


    1. KvanTTT
      01.10.2019 23:23
      +2

      А еще можно обобщить до редактора грамматик. И, не поверите, такой редактор на Avalonia есть: DAGE. Правда использовать его пока что комфортно не получится — в разработке.



  1. WanSpi
    02.10.2019 10:14
    +1

    Иногда мы не понимаем как работает регулярное выражение, которое мы составили, и хотим проверить.
    Это как понять? Как можно написать регулярное выражение, и не понимать как оно работает? Как я понимаю у нас есть задача, и мы случайным образом пишем регулярное выражение, надеясь что оно сработает?

    Ну а если кто хочет в живую протестировать свои регулярки, то давно уже есть онлайновые сервисы, по типу regexr.com


    1. Larymar Автор
      02.10.2019 10:25
      +1

      Выше написали об этом же (тык)
      Есть моного неплохих онлайн сервисов, вы хотите обсудить их достоинства и недостатки?
      Или хотите поговорить о чем на самом деле эта статья?


      1. WanSpi
        02.10.2019 10:28
        +1

        Этот комментарий был написан после моего, я лишь привел пример, что есть удобные сервисы онлайн, минусы и плюсы онлайн сервисов, даже не собирался обсуждать :)


    1. vrnvorona
      02.10.2019 15:07

      regex101.com лучше


      1. WanSpi
        02.10.2019 15:12

        А где вы видите в моих сообщениях что я утверждал что regexr.com является лучшим из себе подобных? Это лишь пример, и я прекрасно знаю что есть лучше сервисы.
        Ну и как я всегда говорю, повторюсь и вам, если захочется написать что тот или иной сервис лучше, то хотя бы приведите примеры, в чем его плюсы, перед другими.


        1. vrnvorona
          02.10.2019 15:57

          Интерфейс в целом

          Из важного: почему-то нет в паттернах lookbehind, а паттерн важный. Точнее он есть, но почему-то в моем хроме он не отображается и пишет что не поддерживается.

          Уже достаточно, меньшая удобность интерфейса и странное поведение с браузерами при одинаковых базовых фичах делает его хуже.


          1. WanSpi
            02.10.2019 16:06

            Интерфейс в целом
            Это субъективщина, мне лично интерфейс regexr.com пожалуй даже поприятней будет.

            Из важного: почему-то нет в паттернах lookbehind, а паттерн важный. Точнее он есть, но почему-то в моем хроме он не отображается и пишет что не поддерживается.
            Спасибо за комментарий, я его редко использую, возможно из-за этого и не заметил, но полезно об этом знать, надо бы попробовать regex101.com, возможно для меня он будет полезнее, хотя сейчас беглым анализом заметил количество шагов при проверке, вот эта функция была бы просто не заменима в оптимализации регулярных выражений.


            1. vrnvorona
              02.10.2019 16:36

              Я не оптимизировал, скорее учился по этому сайту в целом их использовать. Обычные объяснения и запоминание тегов для меня не сработали, а понять обычные конструкции для меня наглядно было полезно. Лично мне просто приятнее интерфейс на 101, он чище и побыстрее, категории выбираются сбоку, а не nested что уменьшает время на поиск «если не туда перешел». По крайней мере мне такой «легкий» quick reference нравится больше чем прямые переходы в одном меню. Ну и размеры, элементы на 101 не такие раздутые и большие. Как бы да, все и там и там видно, но смысл.


  1. alladuh
    02.10.2019 10:23
    +1

    Спасибо за статью!
    Хороший и понятный пример, который позволяет влиться в avalonia