Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clickable code search results line numbers. #1579

Merged
merged 10 commits into from
Jun 25, 2024
16 changes: 8 additions & 8 deletions UndertaleModCli/Program.UMTLibInherited.cs
Original file line number Diff line number Diff line change
Expand Up @@ -521,13 +521,13 @@ public string SimpleTextInput(string title, string label, string defaultValue, b
}

/// <inheritdoc/>
public async Task ClickableSearchOutput(string title, string query, int resultsCount, IOrderedEnumerable<KeyValuePair<string, List<string>>> resultsDict, bool editorDecompile, IOrderedEnumerable<string> failedList = null)
public async Task ClickableSearchOutput(string title, string query, int resultsCount, IOrderedEnumerable<KeyValuePair<string, List<(int lineNum, string codeLine)>>> resultsDict, bool editorDecompile, IOrderedEnumerable<string> failedList = null)
{
await ClickableSearchOutput(title, query, resultsCount, resultsDict.ToDictionary(pair => pair.Key, pair => pair.Value), editorDecompile, failedList);
}

/// <inheritdoc/>
public async Task ClickableSearchOutput(string title, string query, int resultsCount, IDictionary<string, List<string>> resultsDict, bool editorDecompile, IEnumerable<string> failedList = null)
public async Task ClickableSearchOutput(string title, string query, int resultsCount, IDictionary<string, List<(int lineNum, string codeLine)>> resultsDict, bool editorDecompile, IEnumerable<string> failedList = null)
{
await Task.Delay(1); //dummy await

Expand Down Expand Up @@ -555,17 +555,17 @@ public async Task ClickableSearchOutput(string title, string query, int resultsC
Console.WriteLine();

// Print in a pattern of:
// results in code_file
// line3: code
// line6: code
// Results in code_file
// Line 3: line of code
// Line 6: line of code
//
// results in a codefile2
//etc.
// Results in code_file_1
// etc.
foreach (var dictEntry in resultsDict)
{
Console.WriteLine($"Results in {dictEntry.Key}:");
foreach (var resultEntry in dictEntry.Value)
Console.WriteLine(resultEntry);
Console.WriteLine($"Line {resultEntry.lineNum}: {resultEntry.codeLine}");

Console.WriteLine();
}
Expand Down
26 changes: 4 additions & 22 deletions UndertaleModLib/Scripting/IScriptInterface.cs
Original file line number Diff line number Diff line change
Expand Up @@ -293,20 +293,11 @@
/// <param name="query">The query that was searched for.</param>
/// <param name="resultsCount">How many results have been found.</param>
/// <param name="resultsDict">An <see cref="IOrderedEnumerable{TElement}"/> of type <see cref="KeyValuePair{TKey,TValue}"/>,
/// with TKey being the name of the code entry an TValue being a list of matching code lines with their line number prepended.</param>
/// with TKey being the name of the code entry an TValue being a list of tuples where the first item is the matching code line number and the second one is the code line itself.</param>
/// <param name="showInDecompiledView">Whether to open the "Decompiled" view or the "Disassembly" view when clicking on an entry name.</param>
/// <param name="failedList">A list of code entries that encountered an error while searching.</param>
/// <returns>A task that represents the search output.</returns>
Task ClickableSearchOutput(string title, string query, int resultsCount, IOrderedEnumerable<KeyValuePair<string, List<string>>> resultsDict, bool showInDecompiledView, IOrderedEnumerable<string> failedList = null);

/// <summary>
/// Obsolete.
/// </summary>
[Obsolete("Use ClickableSearchOutput instead!")]
sealed Task ClickableTextOutput(string title, string query, int resultsCount, IOrderedEnumerable<KeyValuePair<string, List<string>>> resultsDict, bool showInDecompiledView, IOrderedEnumerable<string> failedList = null)
{
return ClickableSearchOutput(title, query, resultsCount, resultsDict, showInDecompiledView, failedList);
}
Task ClickableSearchOutput(string title, string query, int resultsCount, IOrderedEnumerable<KeyValuePair<string, List<(int lineNum, string codeLine)>>> resultsDict, bool showInDecompiledView, IOrderedEnumerable<string> failedList = null);

/// <summary>
/// Shows search output with clickable text to the user.
Expand All @@ -315,23 +306,14 @@
/// <param name="query">The query that was searched for.</param>
/// <param name="resultsCount">How many results have been found.</param>
/// <param name="resultsDict">A <see cref="Dictionary{TKey,TValue}"/> with TKey being the name of the code entry and
/// TValue being a list of matching code lines with their line number prepended.</param>
/// TValue being a list of tuples where the first item is the matching code line number and the second one is the code line itself.</param>
/// <param name="showInDecompiledView">Whether to open the "Decompiled" view or the "Disassembly" view when clicking on an entry name.</param>
/// <param name="failedList">A list of code entries that encountered an error while searching.</param>
/// <returns>A task that represents the search output.</returns>
Task ClickableSearchOutput(string title, string query, int resultsCount, IDictionary<string, List<string>> resultsDict, bool showInDecompiledView, IEnumerable<string> failedList = null);

/// <summary>
/// Obsolete.
/// </summary>
[Obsolete("Use ClickableSearchOutput instead!")]
sealed Task ClickableTextOutput(string title, string query, int resultsCount, IDictionary<string, List<string>> resultsDict, bool showInDecompiledView, IEnumerable<string> failedList = null)
{
return ClickableSearchOutput(title, query, resultsCount, resultsDict, showInDecompiledView, failedList);
}
Task ClickableSearchOutput(string title, string query, int resultsCount, IDictionary<string, List<(int lineNum, string codeLine)>> resultsDict, bool showInDecompiledView, IEnumerable<string> failedList = null);

/// <summary>
/// Sets <see cref="isFinishedMessageEnabled"/>.

Check warning on line 316 in UndertaleModLib/Scripting/IScriptInterface.cs

View workflow job for this annotation

GitHub Actions / publish_cli (ubuntu-latest, Debug, false)

XML comment has cref attribute 'isFinishedMessageEnabled' that could not be resolved

Check warning on line 316 in UndertaleModLib/Scripting/IScriptInterface.cs

View workflow job for this annotation

GitHub Actions / publish_cli (ubuntu-latest, Debug, false)

XML comment has cref attribute 'isFinishedMessageEnabled' that could not be resolved

Check warning on line 316 in UndertaleModLib/Scripting/IScriptInterface.cs

View workflow job for this annotation

GitHub Actions / publish_cli (ubuntu-latest, Debug, false)

XML comment has cref attribute 'isFinishedMessageEnabled' that could not be resolved

Check warning on line 316 in UndertaleModLib/Scripting/IScriptInterface.cs

View workflow job for this annotation

GitHub Actions / publish_cli (macOS-latest, Debug, false)

XML comment has cref attribute 'isFinishedMessageEnabled' that could not be resolved

Check warning on line 316 in UndertaleModLib/Scripting/IScriptInterface.cs

View workflow job for this annotation

GitHub Actions / publish_cli (macOS-latest, Debug, false)

XML comment has cref attribute 'isFinishedMessageEnabled' that could not be resolved

Check warning on line 316 in UndertaleModLib/Scripting/IScriptInterface.cs

View workflow job for this annotation

GitHub Actions / publish_cli (macOS-latest, Debug, false)

XML comment has cref attribute 'isFinishedMessageEnabled' that could not be resolved

Check warning on line 316 in UndertaleModLib/Scripting/IScriptInterface.cs

View workflow job for this annotation

GitHub Actions / publish_cli (windows-latest, Debug, false)

XML comment has cref attribute 'isFinishedMessageEnabled' that could not be resolved

Check warning on line 316 in UndertaleModLib/Scripting/IScriptInterface.cs

View workflow job for this annotation

GitHub Actions / publish_cli (windows-latest, Debug, false)

XML comment has cref attribute 'isFinishedMessageEnabled' that could not be resolved

Check warning on line 316 in UndertaleModLib/Scripting/IScriptInterface.cs

View workflow job for this annotation

GitHub Actions / publish_cli (windows-latest, Debug, false)

XML comment has cref attribute 'isFinishedMessageEnabled' that could not be resolved

Check warning on line 316 in UndertaleModLib/Scripting/IScriptInterface.cs

View workflow job for this annotation

GitHub Actions / build_gui (windows-latest, Debug, false, false)

XML comment has cref attribute 'isFinishedMessageEnabled' that could not be resolved

Check warning on line 316 in UndertaleModLib/Scripting/IScriptInterface.cs

View workflow job for this annotation

GitHub Actions / build_gui (windows-latest, Debug, false, false)

XML comment has cref attribute 'isFinishedMessageEnabled' that could not be resolved

Check warning on line 316 in UndertaleModLib/Scripting/IScriptInterface.cs

View workflow job for this annotation

GitHub Actions / build_gui (windows-latest, Debug, false, true)

XML comment has cref attribute 'isFinishedMessageEnabled' that could not be resolved

Check warning on line 316 in UndertaleModLib/Scripting/IScriptInterface.cs

View workflow job for this annotation

GitHub Actions / build_gui (windows-latest, Debug, false, true)

XML comment has cref attribute 'isFinishedMessageEnabled' that could not be resolved
/// </summary>
/// <param name="isFinishedMessageEnabled">The state to set it to.</param>
void SetFinishedMessage(bool isFinishedMessageEnabled);
Expand Down
58 changes: 49 additions & 9 deletions UndertaleModTool/Editors/UndertaleCodeEditor.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
using UndertaleModLib.Compiler;
using UndertaleModLib.Decompiler;
using UndertaleModLib.Models;
using static UndertaleModTool.MainWindow.CodeEditorMode;
using Input = System.Windows.Input;

namespace UndertaleModTool
Expand All @@ -59,14 +58,14 @@ public partial class UndertaleCodeEditor : DataUserControl
public bool DecompiledYet = false;
public bool DecompiledSkipped = false;
public SearchPanel DecompiledSearchPanel;
public static (int Line, int Column, double ScrollPos) OverriddenDecompPos;
public static (int Line, int Column, double ScrollPos) OverriddenDecompPos { get; set; }

public bool DisassemblyFocused = false;
public bool DisassemblyChanged = false;
public bool DisassembledYet = false;
public bool DisassemblySkipped = false;
public SearchPanel DisassemblySearchPanel;
public static (int Line, int Column, double ScrollPos) OverriddenDisasmPos;
public static (int Line, int Column, double ScrollPos) OverriddenDisasmPos { get; set; }

public static RoutedUICommand Compile = new RoutedUICommand("Compile code", "Compile", typeof(UndertaleCodeEditor));

Expand All @@ -75,6 +74,14 @@ public partial class UndertaleCodeEditor : DataUserControl
private static readonly Dictionary<string, UndertaleNamedResource> FunctionsDict = new();
private static readonly Dictionary<string, UndertaleNamedResource> CodeDict = new();

public enum CodeEditorTab
{
Unknown,
Disassembly,
Decompiled
}
public static CodeEditorTab EditorTab { get; set; } = CodeEditorTab.Unknown;

public UndertaleCodeEditor()
{
InitializeComponent();
Expand Down Expand Up @@ -298,25 +305,25 @@ private async void UserControl_DataContextChanged(object sender, DependencyPrope
CurrentDecompiled = null;
CurrentDisassembled = null;

if (MainWindow.CodeEditorDecompile != Unstated) //if opened from the code search results "link"
if (EditorTab != CodeEditorTab.Unknown) // If opened from the code search results "link"
{
if (MainWindow.CodeEditorDecompile == DontDecompile && code != CurrentDisassembled)
if (EditorTab == CodeEditorTab.Disassembly && code != CurrentDisassembled)
{
if (CodeModeTabs.SelectedItem != DisassemblyTab)
CodeModeTabs.SelectedItem = DisassemblyTab;
else
DisassembleCode(code, true);
}

if (MainWindow.CodeEditorDecompile == Decompile && code != CurrentDecompiled)
if (EditorTab == CodeEditorTab.Decompiled && code != CurrentDecompiled)
{
if (CodeModeTabs.SelectedItem != DecompiledTab)
CodeModeTabs.SelectedItem = DecompiledTab;
else
_ = DecompileCode(code, true);
}

MainWindow.CodeEditorDecompile = Unstated;
EditorTab = CodeEditorTab.Unknown;
}
else
FillInCodeViewer(true);
Expand Down Expand Up @@ -367,6 +374,9 @@ private static void RestoreCaretPosition(TextEditor textEditor, int linePos, int
{
if (linePos <= textEditor.LineCount)
{
if (linePos == -1)
linePos = textEditor.Document.LineCount;

int lineLen = textEditor.Document.GetLineByNumber(linePos).Length;
textEditor.TextArea.Caret.Line = linePos;
if (columnPos != -1)
Expand All @@ -375,15 +385,45 @@ private static void RestoreCaretPosition(TextEditor textEditor, int linePos, int
textEditor.TextArea.Caret.Column = lineLen + 1;

textEditor.ScrollToLine(linePos);
textEditor.ScrollToVerticalOffset(scrollPos);
if (scrollPos != -1)
textEditor.ScrollToVerticalOffset(scrollPos);
}
else
{
textEditor.CaretOffset = textEditor.Text.Length;
textEditor.ScrollToEnd();
}
}

public static void ChangeLineNumber(int lineNum, CodeEditorTab editorTab)
{
if (lineNum < 1)
return;

if (editorTab == CodeEditorTab.Unknown)
{
Debug.WriteLine($"The \"{nameof(editorTab)}\" argument of \"{nameof(ChangeLineNumber)}()\" is \"{nameof(CodeEditorTab.Unknown)}\".");
return;
}

if (editorTab == CodeEditorTab.Decompiled)
OverriddenDecompPos = (lineNum, -1, -1);
else
OverriddenDisasmPos = (lineNum, -1, -1);
}
public static void ChangeLineNumber(int lineNum, TextEditor textEditor)
{
if (lineNum < 1)
return;

if (textEditor is null)
{
Debug.WriteLine($"The \"{nameof(textEditor)}\" argument of \"{nameof(ChangeLineNumber)}()\" is null.");
return;
}

RestoreCaretPosition(textEditor, lineNum, -1, -1);
}

private static void FillObjectDicts()
{
var data = mainWindow.Data;
Expand Down
44 changes: 25 additions & 19 deletions UndertaleModTool/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -116,12 +116,6 @@
public string ExePath { get; private set; } = Program.GetExecutableDirectory();
public string ScriptErrorType { get; set; } = "";

public enum CodeEditorMode
{
Unstated,
DontDecompile,
Decompile
}
public enum SaveResult
{
NotSaved,
Expand All @@ -134,9 +128,6 @@
Right
}

// TODO: move this to the code editor
public static CodeEditorMode CodeEditorDecompile { get; set; } = CodeEditorMode.Unstated;

private int progressValue;
private Task updater;
private CancellationTokenSource cts;
Expand Down Expand Up @@ -2430,46 +2421,61 @@
updater.Dispose();
}

public void OpenCodeFile(string name, CodeEditorMode editorDecompile, bool inNewTab = false)
public void OpenCodeEntry(string name, UndertaleCodeEditor.CodeEditorTab editorTab, bool inNewTab = false)
{
OpenCodeEntry(name, -1, editorTab, inNewTab);
}
public void OpenCodeEntry(string name, int lineNum, UndertaleCodeEditor.CodeEditorTab editorTab, bool inNewTab = false)
{
UndertaleCode code = Data.Code.ByName(name);

if (code is not null)
{
Focus();

#pragma warning disable CA1416
if (Selected == code)
{
#pragma warning disable CA1416
var codeEditor = FindVisualChild<UndertaleCodeEditor>(DataEditor);
if (codeEditor is null)
{
Debug.WriteLine("Cannot select the code editor mode tab - its instance is not found.");
Debug.WriteLine("Cannot select the code editor mode tab - the instance is not found.");
}
else
{
if (editorDecompile == CodeEditorMode.Decompile
if (editorTab == UndertaleCodeEditor.CodeEditorTab.Decompiled
&& !codeEditor.DecompiledTab.IsSelected)
{
codeEditor.CodeModeTabs.SelectedItem = codeEditor.DecompiledTab;
}
else if (editorDecompile == CodeEditorMode.DontDecompile
else if (editorTab == UndertaleCodeEditor.CodeEditorTab.Disassembly
&& !codeEditor.DisassemblyTab.IsSelected)
{
codeEditor.CodeModeTabs.SelectedItem = codeEditor.DisassemblyTab;
}

var editor = editorTab == UndertaleCodeEditor.CodeEditorTab.Decompiled
? codeEditor.DecompiledEditor : codeEditor.DisassemblyEditor;
CurrentTab?.SaveTabContentState();
UndertaleCodeEditor.ChangeLineNumber(lineNum, editor);
}
#pragma warning restore CA1416
}
else
CodeEditorDecompile = editorDecompile;
{
if (CurrentTab?.CurrentObject is UndertaleCode)
CurrentTab.SaveTabContentState();

UndertaleCodeEditor.EditorTab = editorTab;
UndertaleCodeEditor.ChangeLineNumber(lineNum, editorTab);
}
#pragma warning restore CA1416

HighlightObject(code);
ChangeSelection(code, inNewTab);
}
else
{
this.ShowError($"Can't find code \"{name}\".\n(probably, different game data was loaded)");
this.ShowError($"Can't find code entry \"{name}\".\n(probably, different game data was loaded)");
}
}

Expand Down Expand Up @@ -2727,7 +2733,7 @@
TextInput textOutput = new TextInput(labelText, titleText, message, isMultiline, true); //read-only mode
textOutput.Show();
}
public async Task ClickableSearchOutput(string title, string query, int resultsCount, IOrderedEnumerable<KeyValuePair<string, List<string>>> resultsDict, bool showInDecompiledView, IOrderedEnumerable<string> failedList = null)
public async Task ClickableSearchOutput(string title, string query, int resultsCount, IOrderedEnumerable<KeyValuePair<string, List<(int lineNum, string codeLine)>>> resultsDict, bool showInDecompiledView, IOrderedEnumerable<string> failedList = null)
{
await Task.Delay(150); //wait until progress bar status is displayed

Expand All @@ -2740,7 +2746,7 @@

PlayInformationSound();
}
public async Task ClickableSearchOutput(string title, string query, int resultsCount, IDictionary<string, List<string>> resultsDict, bool showInDecompiledView, IEnumerable<string> failedList = null)
public async Task ClickableSearchOutput(string title, string query, int resultsCount, IDictionary<string, List<(int lineNum, string codeLine)>> resultsDict, bool showInDecompiledView, IEnumerable<string> failedList = null)
{
await Task.Delay(150);

Expand Down Expand Up @@ -2992,7 +2998,7 @@
PreventClose = true,
Owner = this,
StatusText = "Downloaded MB: 0.00"
};

Check warning on line 3001 in UndertaleModTool/MainWindow.xaml.cs

View workflow job for this annotation

GitHub Actions / build_gui (windows-latest, Debug, false, false)

'WebClient.WebClient()' is obsolete: 'WebRequest, HttpWebRequest, ServicePoint, and WebClient are obsolete. Use HttpClient instead.' (https://aka.ms/dotnet-warnings/SYSLIB0014)

Check warning on line 3001 in UndertaleModTool/MainWindow.xaml.cs

View workflow job for this annotation

GitHub Actions / build_gui (windows-latest, Debug, false, false)

'WebClient.WebClient()' is obsolete: 'WebRequest, HttpWebRequest, ServicePoint, and WebClient are obsolete. Use HttpClient instead.' (https://aka.ms/dotnet-warnings/SYSLIB0014)

Check warning on line 3001 in UndertaleModTool/MainWindow.xaml.cs

View workflow job for this annotation

GitHub Actions / build_gui (windows-latest, Debug, false, true)

'WebClient.WebClient()' is obsolete: 'WebRequest, HttpWebRequest, ServicePoint, and WebClient are obsolete. Use HttpClient instead.' (https://aka.ms/dotnet-warnings/SYSLIB0014)

Check warning on line 3001 in UndertaleModTool/MainWindow.xaml.cs

View workflow job for this annotation

GitHub Actions / build_gui (windows-latest, Debug, false, true)

'WebClient.WebClient()' is obsolete: 'WebRequest, HttpWebRequest, ServicePoint, and WebClient are obsolete. Use HttpClient instead.' (https://aka.ms/dotnet-warnings/SYSLIB0014)
SetProgressBar();

using (WebClient webClient = new())
Expand Down
Loading
Loading