feat(input-bar): wire slash-command callback + AllCommands (J2)

J2 closes the trigger-gap discovered in J review (2026-05-27): J
migrated CommandHelpWindow as a window but the v1.5.6 trigger-path
was never ported. J2 restores it:

- InputBar.cs adds ImGuiInputTextFlags.CallbackEdit + character-level
  callback that reads data.BufTextSpan, detects /-prefix, extracts
  command word, and calls _commandHelpWindow.Value.UpdateContent(desc)
- AllCommands.cs (new file, 1:1 port from v1.5.6) populates a static
  Dictionary<string, TextCommand> from Sheets.TextCommandSheet at
  startup; Plugin.CommandManager.Commands is the fallback for
  non-hardcoded commands
- CommandHelpWindow injected into InputBar via Lazy<T> ctor param to
  break the InputBar <-> CommandHelpWindow circular dep; PluginHostFactory
  DI-reg extended with the Lazy wrapper accordingly

Closes the smoke-step-9 gap. Phase-3 windows are now all reachable
end-to-end (R1 InputPreview, R2 CommandHelpWindow, R3 DebuggerWindow).
This commit is contained in:
2026-05-27 23:19:21 +02:00
parent c652a1c450
commit cba6a16f8e
3 changed files with 72 additions and 3 deletions
+34 -2
View File
@@ -1,10 +1,12 @@
using System.Numerics;
using System.Text;
using Dalamud.Bindings.ImGui;
using Dalamud.Interface;
using Dalamud.Interface.Utility.Raii;
using HellionChat.Code;
using HellionChat.GameFunctions;
using HellionChat.Themes;
using HellionChat.Ui;
using HellionChat.Ui.StyleEngine;
using HellionChat.Util;
using Microsoft.Extensions.Logging;
@@ -31,6 +33,7 @@ internal sealed class InputBar
private readonly TokenResolver _resolver;
private readonly ILogger<InputBar> _logger;
private readonly Action _onOpenSettings;
private readonly Lazy<CommandHelpWindow> _commandHelpWindow;
private string _pendingMessage = string.Empty;
private bool _isFocused;
@@ -45,7 +48,8 @@ internal sealed class InputBar
ThemeRegistry themes,
TokenResolver resolver,
ILogger<InputBar> logger,
Action onOpenSettings
Action onOpenSettings,
Lazy<CommandHelpWindow> commandHelpWindow
)
{
_symbolPicker = symbolPicker;
@@ -54,6 +58,7 @@ internal sealed class InputBar
_resolver = resolver;
_logger = logger;
_onOpenSettings = onOpenSettings;
_commandHelpWindow = commandHelpWindow;
}
public string PendingMessage => _pendingMessage;
@@ -221,15 +226,42 @@ internal sealed class InputBar
"##hellion-input",
ref _pendingMessage,
BufferCapacity,
ImGuiInputTextFlags.EnterReturnsTrue
ImGuiInputTextFlags.EnterReturnsTrue | ImGuiInputTextFlags.CallbackEdit,
SlashCommandCallback
)
)
{
_commandHelpWindow.Value.IsOpen = false;
TrySend(activeTab);
}
_isFocused = ImGui.IsItemFocused();
}
// v1.5.6 character-level slash-detect: fires on every edit so CommandHelpWindow
// stays in sync with what the user is typing without a per-frame poll.
private int SlashCommandCallback(scoped ref ImGuiInputTextCallbackData data)
{
_commandHelpWindow.Value.IsOpen = false;
if (data.BufTextLen == 0)
return 0;
var text = Encoding.UTF8.GetString(data.BufTextSpan);
if (!text.StartsWith('/'))
return 0;
var spaceIdx = text.IndexOf(' ');
var command = spaceIdx > 0 ? text[..spaceIdx] : text;
if (AllCommands.TryGetValue(command, out var textCommand))
_commandHelpWindow.Value.UpdateContent(textCommand.Description);
else if (
Plugin.CommandManager.Commands.TryGetValue(command, out var info) && info.ShowInHelp
)
_commandHelpWindow.Value.UpdateContent(info.HelpMessage);
return 0;
}
private void TrySend(Tab? activeTab)
{
var text = _pendingMessage.Trim();