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; namespace AxCopilot.Handlers; public class TextStatsHandler : IActionHandler { public string? Prefix => "stats"; public PluginMetadata Metadata => new PluginMetadata("TextStats", "텍스트 통계 분석", "1.0", "AX"); public Task> GetItemsAsync(string query, CancellationToken ct) { string text = null; try { Application current = Application.Current; if (current != null && ((DispatcherObject)current).Dispatcher.Invoke((Func)(() => Clipboard.ContainsText()))) { text = ((DispatcherObject)Application.Current).Dispatcher.Invoke((Func)(() => Clipboard.GetText())); } } catch { } if (string.IsNullOrEmpty(text)) { return Task.FromResult((IEnumerable)new _003C_003Ez__ReadOnlySingleElementList(new LauncherItem("클립보드에 텍스트가 없습니다", "텍스트를 복사한 후 다시 시도하세요", null, null, null, "\ue946"))); } string text2 = query.Trim(); List list = new List(); int length = text.Length; int length2 = text.Replace(" ", "").Replace("\t", "").Replace("\r", "") .Replace("\n", "") .Length; string[] array = (from w in Regex.Split(text, "\\s+", RegexOptions.None, TimeSpan.FromSeconds(1.0)) where !string.IsNullOrWhiteSpace(w) select w).ToArray(); int num = array.Length; string[] array2 = text.Split('\n'); int value = array2.Length; int value2 = array2.Count((string l) => !string.IsNullOrWhiteSpace(l)); int byteCount = Encoding.UTF8.GetByteCount(text); string text3 = $"글자 {length:N0} · 공백 제외 {length2:N0} · 단어 {num:N0} · 줄 {value:N0}"; list.Add(new LauncherItem($"글자 수: {length:N0} ({length2:N0} 공백 제외)", $"UTF-8: {byteCount:N0} bytes · Enter로 결과 복사", null, $"글자 수: {length:N0} (공백 제외: {length2:N0})", null, "\ue8d2")); list.Add(new LauncherItem($"단어 수: {num:N0}", "공백·줄바꿈 기준 분리 · Enter로 결과 복사", null, $"단어 수: {num:N0}", null, "\ue8d2")); list.Add(new LauncherItem($"줄 수: {value:N0} (비어있지 않은 줄: {value2:N0})", "Enter로 결과 복사", null, $"줄 수: {value:N0} (비어있지 않은 줄: {value2:N0})", null, "\ue8d2")); int num2 = text.Count((char c) => c >= '가' && c <= '\ud7af'); double num3 = ((num2 > length / 2) ? ((double)length2 / 500.0) : ((double)num / 200.0)); string text4 = ((num3 < 1.0) ? "1분 미만" : $"약 {Math.Ceiling(num3)}분"); list.Add(new LauncherItem("예상 읽기 시간: " + text4, (num2 > length / 2) ? "한국어 기준 (500자/분)" : "영어 기준 (200단어/분)", null, "예상 읽기 시간: " + text4, null, "\ue823")); if (string.IsNullOrWhiteSpace(text2)) { IEnumerable values = from g in (from w in array where w.Length >= 2 group w by w.ToLowerInvariant() into g orderby g.Count() descending select g).Take(5) select $"{g.Key}({g.Count()})"; string text5 = string.Join(", ", values); if (!string.IsNullOrEmpty(text5)) { list.Add(new LauncherItem("상위 키워드", text5, null, "상위 키워드: " + text5, null, "\ue721")); } } else { try { int count = Regex.Matches(text, Regex.Escape(text2), RegexOptions.IgnoreCase, TimeSpan.FromSeconds(1.0)).Count; list.Insert(0, new LauncherItem($"'{text2}' 출현 횟수: {count}회", "대소문자 무시 검색 · Enter로 결과 복사", null, $"'{text2}' 출현 횟수: {count}회", null, "\ue721")); } catch { } } list.Add(new LauncherItem("전체 요약 복사", text3, null, $"[텍스트 통계]\n{text3}\nUTF-8: {byteCount:N0} bytes\n읽기 시간: {text4}", null, "\ue77f")); return Task.FromResult((IEnumerable)list); } public Task ExecuteAsync(LauncherItem item, CancellationToken ct) { object data = item.Data; string text = data as string; if (text != null && !string.IsNullOrWhiteSpace(text)) { try { Application current = Application.Current; if (current != null) { ((DispatcherObject)current).Dispatcher.Invoke((Action)delegate { Clipboard.SetText(text); }); } } catch { } } return Task.CompletedTask; } }