using System; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Threading; using AxCopilot.SDK; using AxCopilot.Services; namespace AxCopilot.Handlers; public class BatchTextHandler : IActionHandler { private static readonly (string Cmd, string Desc)[] Commands = new(string, string)[14] { ("prefix [텍스트]", "각 줄 앞에 텍스트 추가"), ("suffix [텍스트]", "각 줄 뒤에 텍스트 추가"), ("wrap [문자]", "각 줄을 지정 문자로 감싸기 (예: wrap \")"), ("number", "줄번호 추가 (1. 2. 3. ...)"), ("sort", "줄 오름차순 정렬"), ("sortd", "줄 내림차순 정렬"), ("reverse", "줄 순서 뒤집기"), ("unique", "중복 줄 제거"), ("trim", "각 줄 앞뒤 공백 제거"), ("replace [A] [B]", "A를 B로 전체 치환"), ("csv", "줄들을 쉼표로 합쳐 한 줄로"), ("split [구분자]", "한 줄을 구분자로 분리하여 여러 줄로"), ("indent [N]", "각 줄 앞에 공백 N개 추가"), ("unindent", "각 줄의 선행 공백/탭 제거") }; public string? Prefix => "batch"; public PluginMetadata Metadata => new PluginMetadata("BatchText", "텍스트 일괄 처리 — batch", "1.0", "AX"); public Task> GetItemsAsync(string query, CancellationToken ct) { string text = query.Trim(); if (string.IsNullOrWhiteSpace(text)) { List list = Commands.Select(((string Cmd, string Desc) c) => new LauncherItem("batch " + c.Cmd, c.Desc, null, null, null, "\ue8d2")).ToList(); list.Insert(0, new LauncherItem("텍스트 일괄 처리", "클립보드 텍스트의 각 줄에 변환 적용 · 명령 입력", null, null, null, "\ue946")); return Task.FromResult((IEnumerable)list); } string text2 = null; try { Application current = Application.Current; if (current != null && ((DispatcherObject)current).Dispatcher.Invoke((Func)(() => Clipboard.ContainsText()))) { text2 = ((DispatcherObject)Application.Current).Dispatcher.Invoke((Func)(() => Clipboard.GetText())); } } catch { } if (string.IsNullOrEmpty(text2)) { return Task.FromResult((IEnumerable)new _003C_003Ez__ReadOnlySingleElementList(new LauncherItem("클립보드에 텍스트가 없습니다", "텍스트를 복사한 후 시도하세요", null, null, null, "\ue7ba"))); } string[] array = (from l in text2.Split('\n') select l.TrimEnd('\r')).ToArray(); string[] array2 = text.Split(' ', 2, StringSplitOptions.TrimEntries); string text3 = array2[0].ToLowerInvariant(); string arg = ((array2.Length > 1) ? array2[1] : ""); string text4 = null; string text5 = null; try { switch (text3) { case "prefix": text4 = string.Join("\n", array.Select((string l) => arg + l)); text5 = "각 줄 앞에 '" + arg + "' 추가"; break; case "suffix": text4 = string.Join("\n", array.Select((string l) => l + arg)); text5 = "각 줄 뒤에 '" + arg + "' 추가"; break; case "wrap": { string w = (string.IsNullOrEmpty(arg) ? "\"" : arg); text4 = string.Join("\n", array.Select((string l) => w + l + w)); text5 = "각 줄을 '" + w + "'로 감싸기"; break; } case "number": text4 = string.Join("\n", array.Select((string l, int i) => $"{i + 1}. {l}")); text5 = "줄번호 추가"; break; case "sort": text4 = string.Join("\n", array.Order()); text5 = "오름차순 정렬"; break; case "sortd": text4 = string.Join("\n", array.OrderDescending()); text5 = "내림차순 정렬"; break; case "reverse": text4 = string.Join("\n", array.Reverse()); text5 = "줄 순서 뒤집기"; break; case "unique": { string[] array4 = array.Distinct().ToArray(); text4 = string.Join("\n", array4); text5 = $"중복 제거: {array.Length}줄 → {array4.Length}줄"; break; } case "trim": text4 = string.Join("\n", array.Select((string l) => l.Trim())); text5 = "각 줄 공백 제거"; break; case "replace": { string[] array3 = arg.Split(' ', 2, StringSplitOptions.TrimEntries); if (array3.Length == 2) { text4 = text2.Replace(array3[0], array3[1]); text5 = $"'{array3[0]}' → '{array3[1]}' 치환"; } break; } case "csv": text4 = string.Join(",", array.Select((string l) => l.Trim())); text5 = $"{array.Length}줄 → CSV 한 줄"; break; case "split": { string text6 = (string.IsNullOrEmpty(arg) ? "," : arg); text4 = string.Join("\n", text2.Split(text6)); text5 = "'" + text6 + "' 기준 분리"; break; } case "indent": { int result; int num = (int.TryParse(arg, out result) ? result : 4); string pad = new string(' ', num); text4 = string.Join("\n", array.Select((string l) => pad + l)); text5 = $"{num}칸 들여쓰기"; break; } case "unindent": text4 = string.Join("\n", array.Select((string l) => l.TrimStart(' ', '\t'))); text5 = "선행 공백 제거"; break; } } catch (Exception ex) { return Task.FromResult((IEnumerable)new _003C_003Ez__ReadOnlySingleElementList(new LauncherItem("처리 오류: " + ex.Message, "입력 데이터를 확인하세요", null, null, null, "\uea39"))); } if (text4 == null) { return Task.FromResult((IEnumerable)new _003C_003Ez__ReadOnlySingleElementList(new LauncherItem("알 수 없는 명령: " + text3, "batch 만 입력하면 전체 명령 목록", null, null, null, "\ue7ba"))); } string text7 = ((text4.Length > 120) ? (text4.Substring(0, 117) + "…") : text4); text7 = text7.Replace("\n", "↵ "); return Task.FromResult((IEnumerable)new _003C_003Ez__ReadOnlySingleElementList(new LauncherItem("[" + text5 + "] → Enter로 클립보드 복사", text7, null, text4, null, "\ue8d2"))); } public Task ExecuteAsync(LauncherItem item, CancellationToken ct) { object data = item.Data; string text = data as string; if (text != null) { try { Application current = Application.Current; if (current != null) { ((DispatcherObject)current).Dispatcher.Invoke((Action)delegate { Clipboard.SetText(text); }); } } catch { } NotificationService.Notify("일괄 처리 완료", "변환 결과가 클립보드에 복사되었습니다"); } return Task.CompletedTask; } }