Files
AX-Copilot-Codex/src/AxCopilot/Handlers/HelpHandler.cs
T

444 lines
22 KiB
C#

using System.Windows;
using System.Windows.Media;
using AxCopilot.SDK;
using AxCopilot.Themes;
using AxCopilot.Views;
namespace AxCopilot.Handlers;
/// <summary>
/// 간편 사용 설명서 핸들러. "help" 프리픽스로 사용합니다.
/// 예: help → 전체 명령어 카드 목록
/// help 계산 → "계산" 관련 명령어 필터
/// help clip → 클립보드 관련 명령어 필터
/// Enter 시 해당 예시를 클립보드에 복사합니다.
/// </summary>
public class HelpHandler : IActionHandler
{
private readonly AxCopilot.Services.SettingsService? _settings;
public HelpHandler(AxCopilot.Services.SettingsService? settings = null)
{
_settings = settings;
}
public string? Prefix => "help";
public PluginMetadata Metadata => new(
"Help",
"AX Commander 사용 설명서",
"1.0",
"AX");
/// <summary>설정에서 변경된 프리픽스와 핫키를 실시간 반영한 항목 목록을 반환합니다.</summary>
private HelpEntry[] GetEntries()
{
var capPrefix = _settings?.Settings.ScreenCapture.Prefix ?? "cap";
if (string.IsNullOrWhiteSpace(capPrefix)) capPrefix = "cap";
var hotkey = _settings?.Settings.Hotkey ?? "Alt+Space";
var entries = (HelpEntry[])_baseEntries.Clone();
for (int i = 0; i < entries.Length; i++)
{
// cap 프리픽스 동적 반영
if (entries[i].Title == "스크린샷 캡처 (예약어 변경 가능)")
{
entries[i] = entries[i] with
{
Command = capPrefix,
Example = $"{capPrefix} screen / {capPrefix} window / {capPrefix} region / {capPrefix} scroll / (설정 → 캡처 탭)"
};
}
// 글로벌 핫키 동적 반영
if (entries[i].Title == "AX Commander 열기 / 닫기")
{
entries[i] = entries[i] with
{
Command = hotkey,
Example = "설정 → 핫키에서 변경 가능"
};
}
}
return entries;
}
// ─── 명령어 카드 데이터 ────────────────────────────────────────────────────
// (카테고리, 예약어/명령, 제목, 설명, 예시, 심볼, 색)
private static readonly HelpEntry[] _baseEntries =
[
// ── 검색 ────────────────────────────────────────────────────────────────
new("검색", "", "앱 · 파일 · 북마크 퍼지 검색",
"앱 이름, 파일명, 한국어 초성, Chrome·Edge 북마크를 통합 검색",
"chrome / 보고서 / ㅅㄷ (설정) / 북마크 제목",
Symbols.Search, "#0078D4"),
// ── 계산 & 변환 ──────────────────────────────────────────────────────────
new("계산", "=", "계산기",
"수식 계산 · 단위 변환 · 실시간 환율",
"= sqrt(144) / = 100 USD to KRW / = 15km to miles",
Symbols.Calculator, "#4B5EFC"),
// ── 웹 검색 ──────────────────────────────────────────────────────────────
new("검색", "?", "웹 검색 (10개 엔진)",
"?n 네이버 · ?g 구글 · ?y 유튜브 · ?gh 깃허브 · ?d DuckDuckGo · ?w 위키피디아 · ?nw 나무위키 · ?nm 네이버지도 · ?ni 네이버이미지 · ?gi 구글이미지",
"? 오늘 날씨 / ?n 뉴스 / ?g python / ?nw 검색어 / ?y 음악 / ?gh axios",
Symbols.Globe, "#006EAF"),
// ── 클립보드 ─────────────────────────────────────────────────────────────
new("클립보드", "#", "클립보드 히스토리",
"복사 이력 검색 & 재사용 · Shift+↑↓로 여러 항목 병합",
"# / # 회의록 / (Shift+↑↓ 선택 후 Shift+Enter 병합)",
Symbols.History, "#B7791F"),
new("클립보드", "$", "클립보드 텍스트 변환 (12종)",
"현재 클립보드 내용을 즉시 변환",
"$json / $b64e / $upper / $url / $md5 / $trim",
Symbols.Clipboard, "#8764B8"),
// ── 텍스트 스니펫 ────────────────────────────────────────────────────────
new("텍스트", ";", "텍스트 스니펫",
"저장된 템플릿 불러오기 · 변수 치환 지원",
";addr / ;sig / ;greet",
Symbols.Snippet, "#0F6CBD"),
// ── 단축키 ───────────────────────────────────────────────────────────────
new("단축키", "@", "URL 단축키",
"저장해둔 URL을 키워드로 바로 열기",
"@gh / @notion / @jira",
Symbols.Globe, "#0078D4"),
new("단축키", "cd", "폴더 단축키",
"저장해둔 폴더를 키워드로 바로 열기",
"cd dl / cd work / cd desktop",
Symbols.Folder, "#107C10"),
new("단축키", ">", "터미널 명령 실행",
"PowerShell 명령을 AX Commander에서 직접 실행",
"> git status / > ipconfig / > cls",
Symbols.Terminal, "#323130"),
// ── 워크스페이스 ──────────────────────────────────────────────────────────
new("창관리", "~", "워크스페이스 저장·복원",
"현재 창 배치를 스냅샷으로 저장하고 언제든 복원",
"~save 업무 / ~restore 업무 / ~list",
Symbols.Workspace, "#C50F1F"),
new("창관리", "snap", "창 분할 레이아웃",
"창을 화면의 특정 영역에 즉시 스냅",
"snap left / snap right / snap tl / snap full",
Symbols.SnapLayout, "#B45309"),
new("창관리", "cap", "스크린샷 캡처 (예약어 변경 가능)",
"영역 선택 · 활성 창 · 스크롤 · 전체 화면. Shift+Enter로 지연 캡처(3/5/10초 타이머). 결과는 클립보드에 복사. 글로벌 단축키(PrintScreen 등)로 바로 캡처 가능. 설정 → 캡처 탭에서 예약어·단축키·스크롤 속도 변경",
"cap region / cap window / cap scroll / cap screen / Shift+Enter → 지연 캡처",
Symbols.CaptureIcon, "#BE185D"),
// ── 시스템 명령 ───────────────────────────────────────────────────────────
new("시스템", "/", "시스템 명령",
"잠금·절전·재시작·종료·타이머·알람",
"/lock / /sleep / /shutdown / /timer 5m / /alarm 14:30",
Symbols.Power, "#4A4A4A"),
new("시스템", "info · *", "시스템 정보",
"IP · 배터리 · 볼륨 · 가동시간 · CPU · 디스크. `*` 입력으로도 동일하게 사용 가능",
"info / info ip / info battery / * / * ip",
Symbols.Computer, "#5B4E7E"),
new("알림", "", "잠금 해제 사용시간 알림",
"PC 잠금 해제 시 오늘 누적 사용 시간과 격려 문구·명언 팝업 표시. 설정 → 알림 탭에서 활성화",
"설정 → 알림 탭: 활성화 토글 / 표시 위치(4방향) / 표시 간격(30분~4시간) / 자동 닫힘(5초~3분)",
Symbols.ReminderBell, "#EA8F00"),
new("시스템", "kill", "프로세스 종료",
"프로세스 이름으로 검색 후 강제 종료",
"kill chrome / kill node / kill teams",
Symbols.Error, "#CC2222"),
new("시스템", "media", "미디어 제어",
"재생·일시정지·이전·다음·볼륨 조절",
"media play / media next / media vol+ / media mute",
Symbols.MediaPlay, "#1A6B3C"),
// ── 개발자 도구 ───────────────────────────────────────────────────────────
new("개발", "json", "JSON 포맷 · 검증",
"클립보드의 JSON을 정렬·압축·유효성 검사",
"json → format / minify / validate",
Symbols.JsonValid, "#D97706"),
new("개발", "encode", "인코딩 · 해싱",
"Base64 · URL · HTML · UTF-8 · MD5 · SHA256",
"encode base64 / encode url / encode sha256",
Symbols.EncodeIcon, "#6366F1"),
new("개발", "color", "색상 변환",
"HEX ↔ RGB ↔ HSL ↔ HSV 변환 및 색상명 지원",
"color #FF5733 / color 255,87,51 / color red",
Symbols.ColorPicker, "#EC4899"),
new("개발", "port", "포트 · 프로세스 조회",
"포트 번호로 점유 프로세스 확인",
"port 3000 / port 8080 / port 443",
Symbols.PortIcon, "#006699"),
new("개발", "env", "환경변수 조회",
"시스템 환경변수 검색 및 클립보드 복사",
"env / env PATH / env JAVA",
Symbols.EnvVar, "#0D9488"),
// ── 앱 관리 ───────────────────────────────────────────────────────────────
new("앱", "emoji", "이모지 피커",
"300개+ 이모지 검색 · Enter로 클립보드 복사",
"emoji / emoji 하트 / emoji wave / emoji 불꽃",
Symbols.Emoji, "#F59E0B"),
new("앱", "recent", "최근 파일",
"Windows 최근 파일 목록 검색 & 바로 열기",
"recent / recent 보고서 / recent xlsx",
Symbols.RecentFiles, "#059669"),
new("앱", "note", "빠른 메모",
"간단한 메모를 저장하고 불러오기",
"note 내일 회의 10시 / note",
Symbols.Note, "#7C3AED"),
new("앱", "uninstall","앱 제거",
"설치된 앱 검색 후 제거",
"uninstall / uninstall kakao / uninstall zoom",
Symbols.Uninstall, "#DC2626"),
// ── 유틸리티 ────────────────────────────────────────────────────────────
new("유틸", "pick", "스포이드 색상 추출",
"화면 아무 곳을 클릭하여 HEX 색상 코드 추출 · 돋보기로 실시간 미리보기 · 결과 반투명 창 5초 표시",
"pick → 스포이드 모드 진입 → 클릭으로 색상 추출",
Symbols.ColorPicker, "#EC4899"),
new("유틸", "date", "날짜 계산 · D-day · 타임스탬프",
"날짜 가감(+30d), D-day 계산, Unix ↔ 날짜 변환, 요일·ISO 주차 조회",
"date / date +30d / date 2026-12-25 / date 1711584000 / date unix",
Symbols.DateIcon, "#0EA5E9"),
new("시스템", "svc", "서비스 관리",
"Windows 서비스 검색·시작·중지·재시작 + AX 클립보드 서비스 강제 재시작",
"svc / svc spooler / svc restart clipboard",
Symbols.ServiceIcon, "#6366F1"),
new("유틸", "pipe", "클립보드 파이프라인",
"변환을 > 로 체이닝: 대문자→공백제거→Base64 등 19종 필터 한 번에 적용",
"pipe upper > trim > b64e / pipe sort > unique > number",
Symbols.PipeIcon, "#8B5CF6"),
new("유틸", "journal", "업무 일지 자동 생성",
"오늘 사용한 앱·명령어·활성 시간을 마크다운 요약으로 자동 생성. 스탠드업/일일 보고에 바로 사용",
"journal / journal 2026-03-25",
Symbols.JournalIcon, "#0EA5E9"),
new("유틸", "routine", "루틴 자동화",
"등록된 루틴(앱·폴더·URL 조합)을 한 번에 순서대로 실행. 출근/퇴근/회의 전 세팅",
"routine / routine morning / routine endofday",
Symbols.RoutineIcon, "#F59E0B"),
new("유틸", "batch", "텍스트 일괄 처리",
"클립보드 각 줄에 동시 적용: 접두사·접미사·줄번호·정렬·중복제거·따옴표·치환·CSV 변환",
"batch number / batch prefix >> / batch sort / batch replace A B",
Symbols.BatchIcon, "#10B981"),
new("유틸", "diff", "텍스트/파일 비교",
"클립보드 최근 2개 텍스트 또는 파일 2개를 줄 단위 비교. 추가·삭제·동일 줄 하이라이트",
"diff / diff C:\\a.txt C:\\b.txt",
Symbols.DiffIcon, "#EF4444"),
new("유틸", "win", "윈도우 포커스 스위처",
"열린 창을 타이틀·프로세스명으로 검색하여 Alt+Tab 없이 즉시 전환",
"win / win chrome / win 보고서",
Symbols.WindowIcon, "#6366F1"),
new("시스템", "^", "Windows 실행 명령",
"Win+R 실행 창과 동일하게 명령어 실행. notepad, calc, cmd, control, mstsc 등 모든 Windows 실행 명령 지원",
"^ notepad / ^ cmd / ^ calc / ^ control / ^ mspaint",
Symbols.LaunchIcon, "#E08850"),
new("유틸", "stats", "텍스트 통계 분석",
"클립보드 텍스트 글자·단어·줄 수, 키워드 빈도, 읽기 시간 추정",
"stats / stats 키워드 (클립보드 텍스트 분석)",
Symbols.TextStats, "#6366F1"),
new("유틸", "fav", "즐겨찾기 (파일·폴더)",
"자주 쓰는 경로를 등록하고 빠르게 열기",
"fav / fav add 보고서 C:\\work\\report.xlsx / fav del 보고서",
Symbols.Favorite, "#F59E0B"),
new("유틸", "rename", "파일 일괄 이름변경",
"폴더 내 파일을 패턴·변수로 일괄 이름변경. {n}순번 {date}날짜 {orig}원본명",
"rename C:\\work\\*.xlsx 보고서_{n}",
Symbols.RenameIcon, "#8B5CF6"),
new("유틸", "monitor", "시스템 리소스 모니터",
"CPU·메모리·디스크·프로세스 실시간 현황 조회",
"monitor / monitor cpu / monitor mem / monitor disk",
Symbols.MonitorIcon, "#10B981"),
new("유틸", "scaffold", "프로젝트 스캐폴딩",
"내장/사용자 템플릿으로 프로젝트 폴더 구조 일괄 생성",
"scaffold / scaffold webapi / scaffold C:\\new-project webapi",
Symbols.ScaffoldIcon,"#0EA5E9"),
// ── 단축키 ───────────────────────────────────────────────────────────────
new("키보드", "Alt+Space", "AX Commander 열기 / 닫기",
"어디서든 AX Commander를 토글",
"설정 → 핫키에서 변경 가능",
Symbols.Info, "#6B7280"),
new("키보드", "Enter", "실행",
"선택된 항목 실행",
"",
Symbols.Info, "#6B7280"),
new("키보드", "Shift+Enter", "Large Type / 병합 실행 / 지연 캡처",
"텍스트를 전체화면으로 표시 · 클립보드 항목 병합 · 캡처 모드에서는 지연 캡처(3초/5초/10초) 타이머 선택",
"(#모드) Shift+↑↓ 선택 후 Shift+Enter 병합 / (cap모드) Shift+Enter → 타이머 선택",
Symbols.Info, "#6B7280"),
new("키보드", "Tab", "자동완성",
"선택 항목으로 입력 자동완성",
"",
Symbols.Info, "#6B7280"),
new("키보드", "→ (커서 끝)", "파일 액션 메뉴",
"앱·파일 선택 후 → 키: 경로복사 · 탐색기 · 관리자 · 터미널",
"",
Symbols.Info, "#6B7280"),
new("키보드", "Ctrl+,", "설정 열기",
"AX Copilot 설정 창",
"",
Symbols.Info, "#6B7280"),
];
// ─── GetItemsAsync ─────────────────────────────────────────────────────────
public Task<IEnumerable<LauncherItem>> GetItemsAsync(string query, CancellationToken ct)
{
var q = query.Trim();
var allEntries = GetEntries();
// 쿼리 없이 "help"만 입력한 경우: 전체 기능 창 여는 항목 하나만 표시
if (string.IsNullOrEmpty(q))
{
var cmdCount = allEntries.Count(e => e.Category != "키보드");
var keyCount = allEntries.Count(e => e.Category == "키보드");
return Task.FromResult<IEnumerable<LauncherItem>>(
[
new LauncherItem(
"AX Commander — 전체 기능 목록 보기",
$"총 {cmdCount}개 명령어 · {keyCount}개 단축키 · Enter → 기능 설명 창 열기",
null, "__HELP_OVERVIEW__",
Symbol: "\uE946")
]);
}
// "help 검색어" 형태: 일치하는 항목 리스트 표시
var filtered = allEntries.Where(e =>
e.Category.Contains(q, StringComparison.OrdinalIgnoreCase) ||
e.Command.Contains(q, StringComparison.OrdinalIgnoreCase) ||
e.Title.Contains(q, StringComparison.OrdinalIgnoreCase) ||
e.Description.Contains(q, StringComparison.OrdinalIgnoreCase));
var items = filtered
.Select(e => new LauncherItem(
FormatTitle(e),
FormatSubtitle(e),
null,
e.Example,
Symbol: e.Symbol))
.ToList<LauncherItem>();
if (items.Count == 0)
{
items.Add(new LauncherItem(
$"'{q}'에 해당하는 명령어가 없습니다",
"help만 입력하면 전체 기능 창을 열 수 있어요",
null, null,
Symbol: Symbols.Info));
}
return Task.FromResult<IEnumerable<LauncherItem>>(items);
}
// ─── ExecuteAsync ──────────────────────────────────────────────────────────
public Task ExecuteAsync(LauncherItem item, CancellationToken ct)
{
if (item.Data is not string s) return Task.CompletedTask;
if (s == "__HELP_OVERVIEW__")
{
// 전체 기능 창 열기
Application.Current.Dispatcher.Invoke(() =>
{
var currentEntries = GetEntries();
var models = currentEntries.Select(e => new HelpItemModel
{
Category = e.Category,
Command = string.IsNullOrEmpty(e.Command) ? "(퍼지 검색)" : e.Command,
Title = e.Title,
Description = e.Description,
Example = e.Example,
Symbol = e.Symbol,
ColorBrush = ParseColor(e.ColorHex)
});
var globalHotkey = _settings?.Settings.Hotkey ?? "Alt+Space";
new HelpDetailWindow(models, currentEntries.Count(e => e.Category != "키보드"), globalHotkey).Show();
});
return Task.CompletedTask;
}
// 일반 항목: 예시를 클립보드에 복사
if (!string.IsNullOrWhiteSpace(s))
{
try { Application.Current.Dispatcher.Invoke(() => Clipboard.SetText(s)); }
catch { /* 무시 */ }
}
return Task.CompletedTask;
}
private static SolidColorBrush ParseColor(string hex)
{
try
{
var color = (System.Windows.Media.Color)
System.Windows.Media.ColorConverter.ConvertFromString(hex);
return new SolidColorBrush(color);
}
catch { return new SolidColorBrush(System.Windows.Media.Colors.Gray); }
}
// ─── 헬퍼 ─────────────────────────────────────────────────────────────────
private static string FormatTitle(HelpEntry e)
{
var prefix = string.IsNullOrEmpty(e.Command)
? $"[{e.Category}]"
: $"[{e.Category}] {e.Command}";
return $"{prefix} — {e.Title}";
}
private static string FormatSubtitle(HelpEntry e)
{
var parts = new List<string> { e.Description };
if (!string.IsNullOrEmpty(e.Example))
parts.Add($"예) {e.Example}");
return string.Join(" · ", parts);
}
// ─── 데이터 모델 ───────────────────────────────────────────────────────────
private record HelpEntry(
string Category,
string Command,
string Title,
string Description,
string Example,
string Symbol,
string ColorHex);
}