using System.Text; using System.Windows; using AxCopilot.SDK; using AxCopilot.Services; using AxCopilot.Themes; namespace AxCopilot.Handlers; /// /// L10-4: Lorem Ipsum / 더미 텍스트 생성기 핸들러. "lorem" 프리픽스로 사용합니다. /// /// 예: lorem → 1단락 생성 (기본) /// lorem 3 → 3단락 생성 /// lorem words 20 → 단어 20개 /// lorem sentences 5 → 문장 5개 /// lorem ko → 한국어 더미 텍스트 1단락 /// lorem ko 3 → 한국어 더미 텍스트 3단락 /// lorem email 5 → 더미 이메일 주소 5개 /// lorem name 5 → 더미 이름 5개 (한국어) /// Enter → 결과를 클립보드에 복사. /// public class LoremHandler : IActionHandler { public string? Prefix => "lorem"; public PluginMetadata Metadata => new( "Lorem", "더미 텍스트 생성기 — Lorem Ipsum · 한국어 · 이메일 · 이름", "1.0", "AX"); // ── Lorem Ipsum 단어 풀 ───────────────────────────────────────────────── private static readonly string[] LoremWords = [ "lorem", "ipsum", "dolor", "sit", "amet", "consectetur", "adipiscing", "elit", "sed", "do", "eiusmod", "tempor", "incididunt", "ut", "labore", "et", "dolore", "magna", "aliqua", "enim", "ad", "minim", "veniam", "quis", "nostrud", "exercitation", "ullamco", "laboris", "nisi", "aliquip", "ex", "ea", "commodo", "consequat", "duis", "aute", "irure", "in", "reprehenderit", "voluptate", "velit", "esse", "cillum", "eu", "fugiat", "nulla", "pariatur", "excepteur", "sint", "occaecat", "cupidatat", "non", "proident", "sunt", "culpa", "qui", "officia", "deserunt", "mollit", "anim", "id", "est", "laborum", "perspiciatis", "unde", "omnis", "iste", "natus", "error", "voluptatem", "accusantium", "doloremque", "laudantium", "totam", "rem", "aperiam", "eaque", "ipsa", "quae", "ab", "illo", "inventore", "veritatis", "quasi", "architecto", "beatae", "vitae", "dicta", "explicabo", "nemo", "ipsam", "quia", "voluptas", "aspernatur", "aut", "odit", "fugit", "consequuntur", "magni", "dolores", "ratione", "sequi", "nesciunt", "neque", "porro", "quisquam", "dolorem", "numquam", "eius", "modi", "temporibus", "incidunt", "magnam", "aliquam", "quaerat", "minima", "nostrum", "exercitationem", "ullam", "corporis", "suscipit", "laboriosam", "nisi", "aliquid", "commodi", "consequatur", "quidem", "rerum", "facilis", ]; // ── 한국어 더미 단어 풀 ────────────────────────────────────────────────── private static readonly string[] KorWords = [ "가나다라", "마바사아", "자차카타", "파하", "데이터", "처리", "시스템", "네트워크", "소프트웨어", "알고리즘", "데이터베이스", "인터페이스", "프레임워크", "모듈", "클래스", "메서드", "함수", "변수", "구조체", "배열", "목록", "사전", "집합", "스택", "큐", "트리", "그래프", "정렬", "탐색", "분석", "설계", "구현", "테스트", "배포", "운영", "서비스", "플랫폼", "클라우드", "컨테이너", "가상화", "보안", "암호화", "인증", "권한", "로그", "모니터링", "알림", "이벤트", "트랜잭션", "세션", "쿠키", "토큰", "키", "값", "객체", "인스턴스", "프로세스", "스레드", "비동기", "병렬", "동기화", "잠금", "버퍼", "캐시", "인덱스", "쿼리", "뷰", "프로시저", "스키마", "테이블", "컬럼", "행", "열", "기본키", "외래키", "조인", "집계", "필터", "정렬", "그룹화", "분류", ]; private static readonly string[] KorSentenceStarters = [ "이 시스템은", "해당 모듈은", "기능을 구현하면", "데이터를 처리하는", "네트워크 연결이", "서비스가 시작되면", "사용자 인터페이스는", "알고리즘이", "처리 과정에서", "설계 단계에서", "구현 방식은", "테스트 결과", ]; private static readonly string[] KorSentenceEnders = [ "처리됩니다.", "구현되어 있습니다.", "필요합니다.", "중요한 역할을 합니다.", "확인할 수 있습니다.", "설계되어 있습니다.", "활용됩니다.", "반환됩니다.", "저장됩니다.", "업데이트됩니다.", "삭제됩니다.", "초기화됩니다.", ]; // ── 더미 이름/이메일 데이터 ─────────────────────────────────────────────── private static readonly string[] KorLastNames = ["김", "이", "박", "최", "정", "강", "조", "윤", "장", "임", "한", "오", "서", "신", "권", "황", "안", "송", "류", "전"]; private static readonly string[] KorFirstNames = ["민준", "서연", "예준", "서현", "도윤", "지우", "시우", "수아", "지호", "하은", "준서", "하린", "건우", "소연", "현우", "지민", "우진", "지유", "연우", "채원"]; private static readonly string[] EmailDomains = ["example.com", "test.co.kr", "dummy.net", "sample.org", "mock.io", "placeholder.dev"]; private static readonly Random Rng = new(); public Task> GetItemsAsync(string query, CancellationToken ct) { var q = query.Trim(); var items = new List(); if (string.IsNullOrWhiteSpace(q)) { var para = GenerateParagraph(false); items.Add(new LauncherItem( "Lorem Ipsum 1단락", para.Length > 80 ? para[..80] + "…" : para, null, ("copy", para), Symbol: "\uE8BD")); items.Add(new LauncherItem("lorem 3", "3단락 생성", null, null, Symbol: "\uE8BD")); items.Add(new LauncherItem("lorem words 20", "단어 20개", null, null, Symbol: "\uE8BD")); items.Add(new LauncherItem("lorem sentences 3", "문장 3개", null, null, Symbol: "\uE8BD")); items.Add(new LauncherItem("lorem ko", "한국어 더미 텍스트", null, null, Symbol: "\uE8BD")); items.Add(new LauncherItem("lorem email 5", "더미 이메일 5개", null, null, Symbol: "\uE8BD")); items.Add(new LauncherItem("lorem name 5", "더미 이름 5개", null, null, Symbol: "\uE8BD")); return Task.FromResult>(items); } var parts = q.Split(' ', StringSplitOptions.RemoveEmptyEntries); var sub = parts[0].ToLowerInvariant(); switch (sub) { case "words": case "word": case "w": { var cnt = parts.Length > 1 && int.TryParse(parts[1], out var n) ? Math.Clamp(n, 1, 500) : 20; var text = GenerateWords(cnt, false); items.Add(new LauncherItem( $"단어 {cnt}개", text.Length > 80 ? text[..80] + "…" : text, null, ("copy", text), Symbol: "\uE8BD")); break; } case "sentences": case "sentence": case "s": { var cnt = parts.Length > 1 && int.TryParse(parts[1], out var n) ? Math.Clamp(n, 1, 50) : 5; var text = GenerateSentences(cnt, false); items.Add(new LauncherItem( $"문장 {cnt}개", text.Length > 80 ? text[..80] + "…" : text, null, ("copy", text), Symbol: "\uE8BD")); break; } case "ko": case "kor": case "korean": { var cnt = parts.Length > 1 && int.TryParse(parts[1], out var n) ? Math.Clamp(n, 1, 10) : 1; var text = GenerateParagraphs(cnt, true); items.Add(new LauncherItem( $"한국어 더미 텍스트 {cnt}단락", text.Length > 80 ? text[..80] + "…" : text, null, ("copy", text), Symbol: "\uE8BD")); break; } case "email": { var cnt = parts.Length > 1 && int.TryParse(parts[1], out var n) ? Math.Clamp(n, 1, 20) : 5; var emails = Enumerable.Range(0, cnt).Select(_ => GenerateEmail()).ToList(); var all = string.Join("\n", emails); items.Add(new LauncherItem( $"더미 이메일 {cnt}개", "전체 복사: Enter", null, ("copy", all), Symbol: "\uE8BD")); foreach (var email in emails) items.Add(new LauncherItem(email, "Enter 복사", null, ("copy", email), Symbol: "\uE8BD")); break; } case "name": case "names": { var cnt = parts.Length > 1 && int.TryParse(parts[1], out var n) ? Math.Clamp(n, 1, 20) : 5; var names = Enumerable.Range(0, cnt).Select(_ => GenerateKorName()).ToList(); var all = string.Join("\n", names); items.Add(new LauncherItem( $"더미 이름 {cnt}개", "전체 복사: Enter", null, ("copy", all), Symbol: "\uE8BD")); foreach (var name in names) items.Add(new LauncherItem(name, "한국어 이름 · Enter 복사", null, ("copy", name), Symbol: "\uE8BD")); break; } default: { // 숫자 단독 → 단락 수 var cnt = int.TryParse(sub, out var n) ? Math.Clamp(n, 1, 10) : 1; var text = GenerateParagraphs(cnt, false); items.Add(new LauncherItem( $"Lorem Ipsum {cnt}단락", text.Length > 80 ? text[..80] + "…" : text, null, ("copy", text), Symbol: "\uE8BD")); break; } } return Task.FromResult>(items); } public Task ExecuteAsync(LauncherItem item, CancellationToken ct) { if (item.Data is ("copy", string text)) { try { System.Windows.Application.Current.Dispatcher.Invoke( () => Clipboard.SetText(text)); NotificationService.Notify("Lorem", "클립보드에 복사했습니다."); } catch { /* 비핵심 */ } } return Task.CompletedTask; } // ── 생성 헬퍼 ───────────────────────────────────────────────────────────── private static string GenerateParagraphs(int count, bool korean) { var paras = Enumerable.Range(0, count).Select(_ => GenerateParagraph(korean)); return string.Join("\n\n", paras); } private static string GenerateParagraph(bool korean) { var sentenceCount = Rng.Next(4, 8); return GenerateSentences(sentenceCount, korean); } private static string GenerateSentences(int count, bool korean) { var sb = new StringBuilder(); for (var i = 0; i < count; i++) { if (i > 0) sb.Append(' '); sb.Append(GenerateSentence(korean)); } return sb.ToString(); } private static string GenerateSentence(bool korean) { if (korean) { var starter = KorSentenceStarters[Rng.Next(KorSentenceStarters.Length)]; var wordCnt = Rng.Next(3, 8); var words = Enumerable.Range(0, wordCnt).Select(_ => KorWords[Rng.Next(KorWords.Length)]); var ender = KorSentenceEnders[Rng.Next(KorSentenceEnders.Length)]; return $"{starter} {string.Join(" ", words)} {ender}"; } else { var wordCnt = Rng.Next(6, 15); var words = Enumerable.Range(0, wordCnt).Select((_, idx) => { var w = LoremWords[Rng.Next(LoremWords.Length)]; return idx == 0 ? char.ToUpper(w[0]) + w[1..] : w; }); return string.Join(" ", words) + "."; } } private static string GenerateWords(int count, bool korean) { var pool = korean ? KorWords : LoremWords; return string.Join(" ", Enumerable.Range(0, count).Select(_ => pool[Rng.Next(pool.Length)])); } private static string GenerateEmail() { var first = LoremWords[Rng.Next(LoremWords.Length)]; var second = LoremWords[Rng.Next(LoremWords.Length)]; var num = Rng.Next(10, 999); var domain = EmailDomains[Rng.Next(EmailDomains.Length)]; return $"{first}.{second}{num}@{domain}"; } private static string GenerateKorName() { var last = KorLastNames[Rng.Next(KorLastNames.Length)]; var first = KorFirstNames[Rng.Next(KorFirstNames.Length)]; return last + first; } }