using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Text.RegularExpressions; 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 ClipboardPipeHandler : IActionHandler { private static readonly Dictionary Fn)> Filters = new Dictionary)>(StringComparer.OrdinalIgnoreCase) { ["upper"] = ("대문자 변환", (string s) => s.ToUpperInvariant()), ["lower"] = ("소문자 변환", (string s) => s.ToLowerInvariant()), ["trim"] = ("앞뒤 공백 제거", (string s) => s.Trim()), ["trimall"] = ("모든 공백 제거", (string s) => Regex.Replace(s, "\\s+", "", RegexOptions.None, TimeSpan.FromSeconds(1.0))), ["sort"] = ("줄 정렬 (오름차순)", (string s) => string.Join("\n", s.Split('\n').Order())), ["sortd"] = ("줄 정렬 (내림차순)", (string s) => string.Join("\n", s.Split('\n').OrderDescending())), ["unique"] = ("중복 줄 제거", (string s) => string.Join("\n", s.Split('\n').Distinct())), ["reverse"] = ("줄 순서 뒤집기", (string s) => string.Join("\n", s.Split('\n').Reverse())), ["number"] = ("줄번호 추가", (string s) => string.Join("\n", s.Split('\n').Select((string l, int i) => $"{i + 1}. {l}"))), ["quote"] = ("각 줄 따옴표 감싸기", (string s) => string.Join("\n", from l in s.Split('\n') select "\"" + l + "\"")), ["b64e"] = ("Base64 인코딩", (string s) => Convert.ToBase64String(Encoding.UTF8.GetBytes(s))), ["b64d"] = ("Base64 디코딩", (string s) => Encoding.UTF8.GetString(Convert.FromBase64String(s.Trim()))), ["urle"] = ("URL 인코딩", (string s) => Uri.EscapeDataString(s)), ["urld"] = ("URL 디코딩", (string s) => Uri.UnescapeDataString(s)), ["md"] = ("마크다운 제거", (string s) => Regex.Replace(s, "[#*_`~\\[\\]()]", "", RegexOptions.None, TimeSpan.FromSeconds(1.0))), ["lines"] = ("빈 줄 제거", (string s) => string.Join("\n", from l in s.Split('\n') where !string.IsNullOrWhiteSpace(l) select l)), ["count"] = ("글자/단어/줄 수", (string s) => $"글자: {s.Length} 단어: {s.Split((char[]?)null, StringSplitOptions.RemoveEmptyEntries).Length} 줄: {s.Split('\n').Length}"), ["csv"] = ("CSV → 탭 변환", (string s) => s.Replace(',', '\t')), ["tab"] = ("탭 → CSV 변환", (string s) => s.Replace('\t', ',')) }; public string? Prefix => "pipe"; public PluginMetadata Metadata => new PluginMetadata("ClipboardPipe", "클립보드 파이프라인 — pipe", "1.0", "AX"); public Task> GetItemsAsync(string query, CancellationToken ct) { string text = query.Trim(); if (string.IsNullOrWhiteSpace(text)) { List list = Filters.Select)>, LauncherItem>((KeyValuePair Fn)> kv) => new LauncherItem(kv.Key, kv.Value.Desc, null, null, null, "\ue77f")).ToList(); list.Insert(0, new LauncherItem("클립보드 파이프라인", "필터를 > 로 연결: pipe upper > trim > b64e", null, null, null, "\ue946")); return Task.FromResult((IEnumerable)list); } string[] array = (from s in text.Split('>') select s.Trim() into s where !string.IsNullOrEmpty(s) select s).ToArray(); string[] array2 = array.Where((string s) => !Filters.ContainsKey(s)).ToArray(); if (array2.Length != 0) { return Task.FromResult(new LauncherItem[1] { new LauncherItem("알 수 없는 필터: " + string.Join(", ", array2), "사용 가능: " + string.Join(", ", Filters.Keys.Take(10)) + " ...", null, null, null, "\ue7ba") }.AsEnumerable()); } 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(new LauncherItem[1] { new LauncherItem("클립보드에 텍스트가 없습니다", "텍스트를 복사한 후 시도하세요", null, null, null, "\ue7ba") }.AsEnumerable()); } string text3 = text2; List list2 = new List(); try { string[] array3 = array; foreach (string key in array3) { text3 = Filters[key].Fn(text3); list2.Add(Filters[key].Desc); } } catch (Exception ex) { return Task.FromResult(new LauncherItem[1] { new LauncherItem("파이프라인 실행 오류: " + ex.Message, "입력 데이터를 확인하세요", null, null, null, "\uea39") }.AsEnumerable()); } string text4 = ((text3.Length > 100) ? (text3.Substring(0, 97) + "…") : text3); text4 = text4.Replace("\r\n", "↵ ").Replace("\n", "↵ "); return Task.FromResult(new LauncherItem[1] { new LauncherItem("[" + string.Join(" → ", array) + "] 결과 적용", text4 + " · Enter로 클립보드 복사", null, text3, null, "\ue77f") }.AsEnumerable()); } 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; } }