Skip to content

Commit

Permalink
Merge pull request #32 from ItsTheSky/features/better-parser
Browse files Browse the repository at this point in the history
Tweaks and QoL adidtions to the parser
  • Loading branch information
NotroDev authored Mar 12, 2024
2 parents 2607159 + bf23c61 commit cc7095d
Show file tree
Hide file tree
Showing 5 changed files with 165 additions and 20 deletions.
65 changes: 51 additions & 14 deletions SkEditor/Controls/Sidebar/CodeParser/ParserSidebarPanel.axaml
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="using:FluentAvalonia.UI.Controls"
xmlns:parser="clr-namespace:SkEditor.Utilities.Parser"
xmlns:viewModels="clr-namespace:SkEditor.Utilities.Parser.ViewModels"
x:Class="SkEditor.Controls.Sidebar.ParserSidebarPanel"
Margin="10,0,0,0">

Expand All @@ -23,24 +22,62 @@

<Border MinWidth="350" Name="ExtendedSideBar" Background="{DynamicResource SkEditorBorderBackground}" CornerRadius="7">

<Grid RowDefinitions="auto,auto,auto,*,auto">
<Grid RowDefinitions="auto,auto,auto,auto,*,auto">
<TextBlock Grid.Row="0" Text="Code Parsing" FontWeight="DemiBold" Margin="20,10,20,10"/>
<Separator Grid.Row="1" Margin="0,0,0,10"/>
<ui:InfoBar Margin="5,0" Grid.Row="2" IsOpen="True" IsClosable="False" Severity="Warning" Message="The code parser is still in beta! Report any bugs found in the Discord server."/>
<StackPanel Margin="10" Name="ParserDisabled" Grid.Row="3" VerticalAlignment="Center" HorizontalAlignment="Stretch" IsVisible="False" Spacing="10">
<StackPanel Margin="10" Name="ParserDisabled" Grid.Row="4" VerticalAlignment="Center" HorizontalAlignment="Stretch" IsVisible="False" Spacing="10">
<TextBlock TextAlignment="Center" TextWrapping="Wrap">The code parser is still in beta and bugs may occur. It is disabled by default but you can enable it using the button below.</TextBlock>
<Button Name="EnableParser" HorizontalAlignment="Center" VerticalAlignment="Center" Classes="accent">Enable</Button>
</StackPanel>
<ScrollViewer Name="ScrollViewer" Grid.Row="3" HorizontalAlignment="Stretch"
<Grid Grid.Row="3" ColumnDefinitions="*,*,auto" Margin="5">
<TextBox Grid.Column="0" x:DataType="viewModels:ParserFilterViewModel"
Watermark="Search ..." Margin="0 0 0 0"
Text="{Binding SearchText}"
Name="SearchBox"
ToolTip.Tip="Filter by section's name"
/>
<ComboBox Margin="5 0" Grid.Column="1" x:DataType="viewModels:ParserFilterViewModel"
SelectedIndex="{Binding SelectedFilterIndex}"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Name="TypeFilterBox"
ToolTip.Tip="Filter the search by type"
>
<ComboBoxItem Content="Any" Tag="-" />

<ComboBoxItem Content="Functions" Tag="functions" />
<ComboBoxItem Content="Events" Tag="events" />
<ComboBoxItem Content="Options" Tag="options" />
<ComboBoxItem Content="Commands" Tag="commands" />
</ComboBox>
<Button Grid.Column="2" Height="30" Width="30" Padding="0" Name="ClearSearch"
ToolTip.Tip="Clear current filters">
<ui:SymbolIcon Symbol="Clear" FontSize="20" Margin="0" />
</Button>
</Grid>
<ScrollViewer Name="ScrollViewer" Grid.Row="4" HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" VerticalContentAlignment="Top"
HorizontalContentAlignment="Center" Margin="5,0">
<ItemsRepeater Name="ItemsRepeater">
<ItemsRepeater.ItemTemplate>
<DataTemplate DataType="parser:CodeSection">
<Expander Margin="0,5">
<Interaction.Behaviors>
<EventTriggerBehavior EventName="PointerEntered">
<EventTriggerBehavior.Actions>
<InvokeCommandAction Command="{Binding OnSectionPointerEntered}" />
</EventTriggerBehavior.Actions>
</EventTriggerBehavior>
<EventTriggerBehavior EventName="PointerExited">
<EventTriggerBehavior.Actions>
<InvokeCommandAction Command="{Binding OnSectionPointerExited}" />
</EventTriggerBehavior.Actions>
</EventTriggerBehavior>
</Interaction.Behaviors>
<Expander.Header>
<StackPanel Orientation="Horizontal">
<ui:IconSourceElement Width="20" Height="20" IconSource="{Binding Icon}"></ui:IconSourceElement>
<ui:IconSourceElement Width="20" Height="20" IconSource="{Binding Icon}" />
<TextBlock Text="{Binding Name}" Margin="10,0,0,0" FontWeight="DemiBold"/>
</StackPanel>
</Expander.Header>
Expand All @@ -65,7 +102,7 @@
<TextBlock TextAlignment="Left" FontWeight="DemiBold" Text="{Binding Name}"/>
<TextBlock Grid.Column="1" TextAlignment="Left" Text="{Binding Type}"/>
<Button Height="28" Width="28" Grid.Column="2" Command="{Binding Rename}" Padding="0" ToolTip.Tip="Rename">
<ui:SymbolIcon Symbol="Rename" FontSize="20" Margin="0"></ui:SymbolIcon>
<ui:SymbolIcon Symbol="Rename" FontSize="20" Margin="0" />
</Button>
</Grid>
</DataTemplate>
Expand All @@ -85,7 +122,7 @@
<Grid ColumnDefinitions="*,Auto" Margin="0,2">
<TextBlock TextAlignment="Left" FontStyle="{Binding Style}" Text="{Binding Name}"/>
<Button Height="28" Width="28" Grid.Column="1" Command="{Binding Rename}" Padding="0" ToolTip.Tip="Rename">
<ui:SymbolIcon Symbol="Rename" FontSize="20" Margin="0"></ui:SymbolIcon>
<ui:SymbolIcon Symbol="Rename" FontSize="20" Margin="0" />
</Button>
</Grid>
</DataTemplate>
Expand All @@ -105,10 +142,10 @@
<Grid ColumnDefinitions="*,Auto,Auto" Margin="0 2">
<TextBlock TextAlignment="Left" VerticalAlignment="Center" HorizontalAlignment="Left" Text="{Binding Name}"/>
<Button Height="28" Width="28" Grid.Column="1" Command="{Binding NavigateToDefinition}" Padding="0" ToolTip.Tip="Navigate to definition">
<ui:SymbolIcon Symbol="Go" FontSize="20" Margin="0"></ui:SymbolIcon>
<ui:SymbolIcon Symbol="Go" FontSize="20" Margin="0" />
</Button>
<Button Height="28" Width="28" Grid.Column="2" Command="{Binding Rename}" Padding="0" Margin="4 0 0 0" ToolTip.Tip="Rename">
<ui:SymbolIcon Symbol="Rename" FontSize="20" Margin="0"></ui:SymbolIcon>
<ui:SymbolIcon Symbol="Rename" FontSize="20" Margin="0" />
</Button>
</Grid>
</DataTemplate>
Expand All @@ -128,7 +165,7 @@
<Grid ColumnDefinitions="*,Auto" Margin="0 2">
<TextBlock TextAlignment="Left" VerticalAlignment="Center" HorizontalAlignment="Left" Text="{Binding Name}"/>
<Button Height="28" Width="28" Grid.Column="2" Command="{Binding Rename}" Padding="0" ToolTip.Tip="Rename">
<ui:SymbolIcon Symbol="Rename" FontSize="20" Margin="0"></ui:SymbolIcon>
<ui:SymbolIcon Symbol="Rename" FontSize="20" Margin="0" />
</Button>
</Grid>
</DataTemplate>
Expand All @@ -143,10 +180,10 @@
</ItemsRepeater.ItemTemplate>
</ItemsRepeater>
</ScrollViewer>
<StackPanel Margin="10" Name="CannotParseInfo" Grid.Row="3" VerticalAlignment="Center" HorizontalAlignment="Stretch" IsVisible="False">
<TextBlock Name="CannotParseInfoText" TextAlignment="Center" TextWrapping="Wrap"></TextBlock>
<StackPanel Margin="10" Name="CannotParseInfo" Grid.Row="4" VerticalAlignment="Center" HorizontalAlignment="Stretch" IsVisible="False">
<TextBlock Name="CannotParseInfoText" TextAlignment="Center" TextWrapping="Wrap" />
</StackPanel>
<StackPanel Grid.Row="4" HorizontalAlignment="Stretch" Margin="10">
<StackPanel Grid.Row="5" HorizontalAlignment="Stretch" Margin="10">
<Button Name="ParseButton" HorizontalAlignment="Center">Parse Code</Button>
</StackPanel>
</Grid>
Expand Down
41 changes: 40 additions & 1 deletion SkEditor/Controls/Sidebar/CodeParser/ParserSidebarPanel.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
using SkEditor.Utilities.Parser;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using Avalonia.Input;
using SkEditor.Utilities.Parser.ViewModels;

namespace SkEditor.Controls.Sidebar;

Expand All @@ -18,14 +21,34 @@ public void Refresh(List<CodeSection> sections)
{
Sections.Clear();
sections.ForEach(Sections.Add);
ItemsRepeater.ItemsSource = Sections;

var viewModel = (ParserFilterViewModel) DataContext;
var filteredSections = Sections
.Where(section => string.IsNullOrWhiteSpace(viewModel.SearchText) || section.Name.Contains(viewModel.SearchText))
.ToList();
if (viewModel.SelectedFilterIndex != 0)
{
var type = viewModel.SelectedFilterIndex switch
{
1 => CodeSection.SectionType.Function,
2 => CodeSection.SectionType.Event,
3 => CodeSection.SectionType.Options,
4 => CodeSection.SectionType.Command,
_ => throw new System.NotImplementedException()
};
filteredSections = filteredSections.Where(section => section.Type == type).ToList();
}
ItemsRepeater.ItemsSource = filteredSections;

UpdateInformationBox();
}

public ParserSidebarPanel()
{
InitializeComponent();

DataContext = new ParserFilterViewModel();

ParserDisabled.IsVisible = !CodeParserEnabled;
ScrollViewer.IsVisible = CodeParserEnabled;
ParseButton.IsEnabled = CodeParserEnabled;
Expand All @@ -46,6 +69,9 @@ public ParserSidebarPanel()
ParseButton.IsEnabled = true;
}
};
ClearSearch.Click += (_, _) => ClearSearchFilter();
SearchBox.KeyUp += (_, _) => UpdateSearchFilter();
TypeFilterBox.SelectionChanged += (_, _) => UpdateSearchFilter();
}

public void ParseCurrentFile()
Expand All @@ -59,6 +85,19 @@ public void ParseCurrentFile()
parser.Parse();
}

public void UpdateSearchFilter()
{
Refresh(Sections.ToList());
}

public void ClearSearchFilter()
{
var viewModel = (ParserFilterViewModel) DataContext;
viewModel.SearchText = "";
viewModel.SelectedFilterIndex = 0;
Refresh(Sections.ToList());
}

public void UpdateInformationBox(bool isToNotifyUnParsing = false)
{
if (!CodeParserEnabled)
Expand Down
65 changes: 60 additions & 5 deletions SkEditor/Utilities/Parser/CodeSection.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
using Avalonia;
using System;
using Avalonia;
using Avalonia.Controls;
using AvaloniaEdit.Editing;
using CommunityToolkit.Mvvm.Input;
using FluentAvalonia.UI.Controls;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using Avalonia.Input;
using Avalonia.Media;
using AvaloniaEdit.Document;
using AvaloniaEdit.Rendering;
using SkEditor.Utilities.Styling;

namespace SkEditor.Utilities.Parser;

Expand All @@ -23,6 +29,7 @@ public partial class CodeSection

public HashSet<CodeVariable> UniqueVariables => GetUniqueVariables();
public HashSet<CodeOptionReference> UniqueOptionReferences => GetUniqueOptionReferences();
public bool IsLocalFunction => Type == SectionType.Function && Lines[0].StartsWith("local ");

public HashSet<CodeFunctionArgument> FunctionArguments { get; set; } = []; // Case of function section

Expand Down Expand Up @@ -51,22 +58,28 @@ public partial class CodeSection
public CodeOption? GetOptionFromCaret(Caret caret)
=> Options.FirstOrDefault(o => o.ContainsCaret(caret));

public LineColorizer Colorizer;
public RelayCommand OnSectionPointerEntered => new(HighlightSection);
public RelayCommand OnSectionPointerExited => new(RemoveHighlight);

public CodeSection(CodeParser parser, int currentLineIndex, List<string> lines)
{
Parser = parser;
Lines = lines;
StartingLineIndex = currentLineIndex;
Parse();

Colorizer = new(StartingLineIndex, EndingLineIndex);
}

public void Parse()
{
var firstLine = Lines[0];
Type = firstLine switch
{
string s when s.StartsWith("command") || s.StartsWith("discord command") => SectionType.Command,
string s when s.StartsWith("options:") => SectionType.Options,
string s when s.StartsWith("function") => SectionType.Function,
{ } s when s.StartsWith("command") || s.StartsWith("discord command") => SectionType.Command,
{ } s when s.StartsWith("options:") => SectionType.Options,
{ } s when s.StartsWith("function") => SectionType.Function,
_ => SectionType.Event,
};

Expand Down Expand Up @@ -239,8 +252,50 @@ private HashSet<CodeOptionReference> GetUniqueOptionReferences()
return uniqueOptionReferences;
}

public void HighlightSection()
{
// TextEditor.TextArea.TextView
var editor = Parser.Editor;
editor.TextArea.TextView.LineTransformers.Add(Colorizer);
}

public void RemoveHighlight()
{
var editor = Parser.Editor;
// Remove every LineColorizer
editor.TextArea.TextView.LineTransformers.Remove(Colorizer);
}

[GeneratedRegex(@"(.*): (.*)")]
private static partial Regex OptionRegex();
[GeneratedRegex(@"(?<=\{)(?!@)_?(.*?)(?=\})")]
[GeneratedRegex(@"(?<=\{)(?!@)_?([A-Za-z.\s_-]+)(?=\})")]
private static partial Regex VariableRegex();

/// <summary>
/// Author: Sky
/// </summary>
public class LineColorizer : DocumentColorizingTransformer
{
int from;
int to;

public LineColorizer(int from, int to)
{
this.from = from;
this.to = to;
}

protected override void ColorizeLine(DocumentLine line)
{
if (!line.IsDeleted && line.LineNumber >= from && line.LineNumber <= to)
{
ChangeLinePart(line.Offset, line.EndOffset, ApplyChanges);
}
}

void ApplyChanges(VisualLineElement element)
{
element.TextRunProperties.SetBackgroundBrush(ThemeEditor.CurrentTheme.SelectionColor);
}
}
}
4 changes: 4 additions & 0 deletions SkEditor/Utilities/Parser/Elements/CodeOptionReference.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,5 +79,9 @@ public void NavigateToDefinition()
editor.CaretOffset = editor.Document.GetOffset(option.Line, option.Column);
editor.Focus();
}
else
{
ApiVault.Get().ShowError("The desired option has no definition.");
}
}
}
10 changes: 10 additions & 0 deletions SkEditor/Utilities/Parser/ViewModels/ParserFilterViewModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using System.Runtime.InteropServices.ObjectiveC;
using CommunityToolkit.Mvvm.ComponentModel;

namespace SkEditor.Utilities.Parser.ViewModels;

public partial class ParserFilterViewModel : ObservableObject
{
[ObservableProperty] private string _searchText = "";
[ObservableProperty] private int _selectedFilterIndex = 0;
}

0 comments on commit cc7095d

Please sign in to comment.