feat: improve editor interactions

- add editor history, word navigation, and undo redo

- preserve overlay cursor focus when editor is open

- demonstrate editor shortcuts in Example
This commit is contained in:
chuan
2026-06-04 00:56:38 +08:00
parent 8a71a27944
commit 47ce443327
8 changed files with 433 additions and 72 deletions
+31 -4
View File
@@ -18,6 +18,7 @@ using var runtime = new TuiRuntime(terminalInput, parser, renderer);
var done = new ManualResetEventSlim();
var eventsText = new Text("最近事件:\n- 无");
var statusText = new Text();
var editorHistory = new List<string> { "history: first command", "history: second command" };
var loader = new Loader(textMeasurer) { Message = "运行中" };
using var loaderCancellation = new CancellationTokenSource();
var input = new TinyTUI.Components.Input(textMeasurer) { Prompt = "请输入: " };
@@ -62,7 +63,7 @@ input.OnSubmitted = value =>
case "/edit":
AddEvent(eventsText, "Overlay: editor opened");
runtime.ShowOverlay(
new EditorOverlay(runtime, message => AddEvent(eventsText, message), textMeasurer),
new EditorOverlay(runtime, editorHistory, message => AddEvent(eventsText, message), textMeasurer),
new OverlayOptions
{
Width = OverlaySize.Percent(70),
@@ -247,21 +248,40 @@ file sealed class SelectOverlay : IInputComponent
file sealed class EditorOverlay : IInputComponent
{
private readonly ITuiRuntime _runtime;
private readonly List<string> _history;
private readonly Action<string> _addEvent;
private readonly Editor _editor;
private readonly Box _box;
public EditorOverlay(ITuiRuntime runtime, Action<string> addEvent, ITextMeasurer textMeasurer)
public EditorOverlay(ITuiRuntime runtime, List<string> history, Action<string> addEvent, ITextMeasurer textMeasurer)
{
_runtime = runtime;
_history = history;
_addEvent = addEvent;
_editor = new Editor(textMeasurer)
{
Height = 6,
Value = "这里可以输入多行文本\nEnter 换行 Esc 提交并关闭",
Placeholder = "这里输入内容",
OnCanceled = SubmitAndClose,
};
_box = new Box(_editor, textMeasurer) { Title = "Editor" };
_editor.SetHistory(_history);
_box = new Box(
new Container
{
Children =
{
new Text(
"Ctrl+A/E 行首行尾 Ctrl+Left/Right 按词移动\n" +
"Ctrl+Backspace/Delete 按词删除 Ctrl+Z/Y 撤销重做\n" +
"空内容时 Up/Down 浏览历史 Esc 提交并关闭"),
new Text(),
_editor,
},
},
textMeasurer)
{
Title = "Editor",
};
}
public IReadOnlyList<string> Render(int width) => _box.Render(width);
@@ -279,6 +299,13 @@ file sealed class EditorOverlay : IInputComponent
private void SubmitAndClose()
{
var value = _editor.Value.Trim();
if (value.Length > 0)
{
_history.Remove(value);
_history.Insert(0, value);
}
_addEvent($"Edited {Math.Max(1, _editor.Value.Split('\n').Length)} line(s)");
_runtime.HideOverlay();
}