Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 33 additions & 2 deletions src/StructuredLogViewer/Controls/BuildControl.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
using Microsoft.Build.Logging.StructuredLogger;
using Microsoft.Language.Xml;
using Mono.Cecil;
using StructuredLogViewer.Core.ProjectGraph;
using TPLTask = System.Threading.Tasks.Task;

namespace StructuredLogViewer.Controls
Expand Down Expand Up @@ -2047,7 +2046,7 @@ private void SelectItemByKey(char ch)

var items = selectedItem.EnumerateSiblingsCycle();

search:
search:
foreach (var item in items)
{
var text = GetText(item);
Expand Down Expand Up @@ -2654,8 +2653,24 @@ private bool ViewFullText(BaseNode treeNode)
switch (treeNode)
{
case NameValueNode nameValueNode when nameValueNode.IsValueShortened:
if (nameValueNode.Name == Strings.CommandLineArguments)
{
return DisplayCommandLine(nameValueNode.Value, nameValueNode.Name);
}

return DisplayText(nameValueNode.Value, nameValueNode.Name);
case TextNode textNode when textNode.IsTextShortened:
if (textNode.Text.StartsWith(Strings.CommandLineArguments))
{
// Search panel stores the Command Line as ProxyNode/TextNode.
if (textNode is ProxyNode proxyNode &&
proxyNode.OriginalType == Strings.Property &&
proxyNode.Original is Property property)
{
return DisplayCommandLine(property.Value, Strings.CommandLineArguments);
}
}

return DisplayText(textNode.Text, textNode.ShortenedText ?? textNode.TypeName);
case NamedNode namedNode when namedNode.IsNameShortened:
return DisplayText(namedNode.Name, namedNode.ShortenedName ?? namedNode.TypeName);
Expand Down Expand Up @@ -2868,6 +2883,8 @@ public bool DisplayFile(string sourceFilePath, int lineNumber = 0, int column =
text.Text,
lineNumber,
column,
null,
null,
preprocess,
navigationHelper,
editorExtension);
Expand All @@ -2881,6 +2898,20 @@ public bool DisplayText(string text, string caption = null)
return true;
}

public bool DisplayCommandLine(string commandLine, string title)
{
title = TextUtilities.SanitizeFileName(title);
int hash = TextUtilities.GetHashCode(title, commandLine);
documentWell.DisplaySource(title,
commandLine,
actionName: "Compare",
actionToolTip: "Open command line comparison tool",
action: () => { documentWell.DisplayCommandLineDiffer("Command Line Diff Tool", commandLine); },
displayPath: false,
tabHash: hash);
return true;
}

private bool DisplayAddRemoveItem(TreeNode parent, int line)
{
if (parent is not Target target)
Expand Down
106 changes: 106 additions & 0 deletions src/StructuredLogViewer/Controls/CommandLineDiffControl.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
<UserControl x:Class="StructuredLogViewer.Controls.CommandLineDiffControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:StructuredLogViewer.Controls"
xmlns:a="http://icsharpcode.net/sharpdevelop/avalonedit"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>

<Grid.RowDefinitions>
<RowDefinition Height="Auto" /> <!-- Top Bar-->
<RowDefinition /> <!-- Top TextBox -->
<RowDefinition Height="5"/> <!-- Splitter -->
<RowDefinition />
<RowDefinition Height="Auto" /> <!-- Center Menu -->
<RowDefinition /> <!-- Result TextBox -->
</Grid.RowDefinitions>

<DockPanel Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"
x:Name="topMenuBar"
Grid.Row="0">
<Button x:Name="TopCompareButton"
Content="Compare"
Padding="6,3,6,3"
Click="CompareNow_Click"
BorderThickness="0"
Background="Transparent"
VerticalAlignment="Center"
DockPanel.Dock="Left"
ToolTip="Compare command lines."/>
<CheckBox x:Name="caseSensitiveCheckBox"
Margin="4"
VerticalAlignment="Center"
DockPanel.Dock="Left"
Content="Case Sensitive"/>
<CheckBox x:Name="wordWrap"
Margin="4"
VerticalAlignment="Center"
DockPanel.Dock="Left"
Content="Word Wrap"
Checked="wordWrap_Checked"
Unchecked="wordWrap_Unchecked"/>
</DockPanel>

<a:TextEditor x:Name="textEditorLeft"
FontFamily="Consolas"
Grid.Row="1"
ShowLineNumbers="True"
LineNumbersForeground="Teal"
FontSize="14"
TextChanged="textEditorLeft_TextChanged">
<a:TextEditor.ContextMenu>
<ContextMenu>
<MenuItem Header="Copy" Click="copyMenu_Click" />
</ContextMenu>
</a:TextEditor.ContextMenu>
</a:TextEditor>

<GridSplitter Grid.Row="2" Height="5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ResizeBehavior="PreviousAndNext" />

<a:TextEditor x:Name="textEditorRight"
FontFamily="Consolas"
Grid.Row="3"
ShowLineNumbers="True"
LineNumbersForeground="Teal"
FontSize="14"
TextChanged="textEditorLeft_TextChanged">
<a:TextEditor.ContextMenu>
<ContextMenu>
<MenuItem Header="Copy" Click="copyMenu_Click" />
</ContextMenu>
</a:TextEditor.ContextMenu>
</a:TextEditor>

<DockPanel x:Name="middleMenuBar"
Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"
Grid.Row="4">
<Button x:Name="CompareButton"
Content="Compare"
Padding="6,3,6,3"
Click="CompareNow_Click"
BorderThickness="0"
Background="Transparent"
VerticalAlignment="Center"
DockPanel.Dock="Left"
ToolTip="Compare command lines."/>
</DockPanel>

<a:TextEditor x:Name="textEditorResult"
FontFamily="Consolas"
Grid.Row="5"
ShowLineNumbers="True"
LineNumbersForeground="Teal"
FontSize="14"
WordWrap="false"
IsReadOnly="true">
<a:TextEditor.ContextMenu>
<ContextMenu>
<MenuItem Header="Copy" Click="copyMenu_Click" />
</ContextMenu>
</a:TextEditor.ContextMenu>
</a:TextEditor>
</Grid>
</UserControl>
184 changes: 184 additions & 0 deletions src/StructuredLogViewer/Controls/CommandLineDiffControl.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
using System;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using ICSharpCode.AvalonEdit;
using ICSharpCode.AvalonEdit.Search;
using StructuredLogger;

namespace StructuredLogViewer.Controls
{

/// <summary>
/// Interaction logic for CommandLineDiffControl.xaml
/// </summary>
public partial class CommandLineDiffControl : UserControl
{
private string CompareButtonText = "Click to compare.";
private string originalCommandLine = "";
private CommandLineDiffer.CommandLineDiffSetting setting = new();

public CommandLineDiffControl()
{
InitializeComponent();

caseSensitiveCheckBox.IsChecked = true;
wordWrap.IsChecked = false;

SetTextEditorTheme(this.textEditorLeft);
SetTextEditorTheme(this.textEditorRight);
SetTextEditorTheme(this.textEditorResult);
}

private void SetTextEditorTheme(TextEditor textEditor)
{
var textArea = textEditor.TextArea;
SearchPanel.Install(textArea);

var textView = textArea.TextView;
textView.Options.HighlightCurrentLine = true;
textView.Options.EnableEmailHyperlinks = false;
textView.Options.EnableHyperlinks = false;

if (SettingsService.UseDarkTheme)
{
textEditor.Background = ThemeManager.BackgroundBrush;
textEditor.Foreground = ThemeManager.ControlTextBrush;
textView.CurrentLineBackground = (Brush)new BrushConverter().ConvertFromString("#505050");
textArea.SelectionBrush = (Brush)new BrushConverter().ConvertFromString("#264F78");
textArea.SelectionForeground = (Brush)new BrushConverter().ConvertFromString("#C8C8C8");
}
else
{
textView.CurrentLineBackground = new SolidColorBrush(Color.FromRgb(224, 224, 224));
textView.CurrentLineBorder = new Pen(Brushes.Transparent, 0);
}

textEditor.ApplyTemplate();
}

public void Initialize(string cmdLine)
{

originalCommandLine = cmdLine;
if (StructuredLogger.CommandLineDiffer.TryParseCommandLine(cmdLine, out var parameters))
{
StringBuilder sbWithNewLine = new StringBuilder();
foreach (var parameter in parameters)
{
sbWithNewLine.AppendLine(parameter);
}

textEditorLeft.Text = sbWithNewLine.ToString();
}
else
{
textEditorLeft.Text = cmdLine;
}
}

private void CompareNow_Click(object sender, RoutedEventArgs e)
{
setting.CaseSensitive = caseSensitiveCheckBox.IsChecked == true;
string left = textEditorLeft.Text;
string right = textEditorRight.Text;

CommandLineDiffer.TryCompare(left, right, out var leftRemainder, out var rightRemainder, setting);

string leftCombined = left.Replace(Environment.NewLine, " ");
string rightCombined = right.Replace(Environment.NewLine, " ");
int indexOfDiff = CommandLineDiffer.GetIndexOfFirstDifference(leftCombined, rightCombined, setting.CaseSensitive);
StringBuilder sb = new StringBuilder();

if (leftRemainder.Count + rightRemainder.Count == 0 && indexOfDiff == -1)
{
sb.Append("No differences found.");
}
else
{
if (indexOfDiff >= 0)
{
// AvalonEdit.TextEditor will still wrap after 10,000 characters even when "WordWrap" is false.
// As a workaround, limit the number of characters printed.

// Print -20 and +100 characters from the indexOfDiff
const int prefixChars = 20;
const int suffixChars = 100;
int startIndex = indexOfDiff - prefixChars;
if (startIndex < 0) { startIndex = 0; }

int endIndexLeft = indexOfDiff + suffixChars;
if (endIndexLeft > leftCombined.Length) { endIndexLeft = leftCombined.Length; }

int endIndexRight = indexOfDiff + suffixChars;
if (endIndexRight > rightCombined.Length) { endIndexRight = rightCombined.Length; }

int lineIndexOfDiff = CommandLineDiffer.GetIndexOfFirstDifference(left, right, setting.CaseSensitive);
int lineOfDiffLeft = CommandLineDiffer.CountOccurrences(left, Environment.NewLine, lineIndexOfDiff);
int lineOfDiffRight = CommandLineDiffer.CountOccurrences(right, Environment.NewLine, lineIndexOfDiff);

sb.AppendLine($"Text difference start at line {lineOfDiffRight + 1}:");
sb.AppendLine(endIndexLeft == -1 ? "" : leftCombined.Substring(startIndex, endIndexLeft - startIndex));
sb.AppendLine(endIndexRight == -1 ? "" : rightCombined.Substring(startIndex, endIndexRight - startIndex));
sb.Append(new String('-', indexOfDiff - startIndex));
sb.AppendLine("^\n");
}


if (leftRemainder.Count + rightRemainder.Count == 0)
{
sb.Append("Command Line Analyzer found no differences.");
}
else
{
sb.AppendLine("Command Line Analyzer found differences:");
sb.AppendLine("Top:");

foreach (var line in leftRemainder)
{
sb.AppendLine(line);
}

sb.AppendLine("\nBottom:");

foreach (var line in rightRemainder)
{
sb.AppendLine(line);
}
}
}

textEditorResult.Text = sb.ToString();
CompareButton.Content = CompareButtonText;
}

private void copyMenu_Click(object sender, RoutedEventArgs e)
{
if (sender is MenuItem menuItem &&
menuItem.Parent is ContextMenu contextMenu &&
contextMenu.PlacementTarget is TextEditor textEditor)
{
textEditor.Copy();
}
}

private void textEditorLeft_TextChanged(object sender, EventArgs e)
{
// Any text changed, update the "Compare" button.
CompareButton.Content = $"{CompareButtonText} (edited)";
}

private void wordWrap_Checked(object sender, RoutedEventArgs e)
{
textEditorLeft.WordWrap = true;
textEditorRight.WordWrap = true;
}

private void wordWrap_Unchecked(object sender, RoutedEventArgs e)
{
textEditorLeft.WordWrap = false;
textEditorRight.WordWrap = false;
}
}
}
8 changes: 5 additions & 3 deletions src/StructuredLogViewer/Controls/DocumentOutline.cs
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ private void TryUpdateToolTipText(TextViewerControl textViewerControl, System.Wi

tooltip.HorizontalOffset = mousePosition.X;
tooltip.VerticalOffset = mousePosition.Y;
tooltip.Content = $"{content}";
tooltip.Content = content;

if (!tooltip.IsOpen)
{
Expand All @@ -123,8 +123,10 @@ private void TryUpdateToolTipText(TextViewerControl textViewerControl, System.Wi

void CloseToolTip()
{
tooltip.IsOpen = false;
tooltip.Content = string.Empty;
if (tooltip.IsOpen)
{
tooltip.IsOpen = false;
}
}
}

Expand Down
Loading