Files
AX-Copilot-Codex/.decompiledproj/AxCopilot/Handlers/ScaffoldHandler.cs

165 lines
6.1 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Serialization;
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 ScaffoldHandler : IActionHandler
{
internal record ScaffoldTemplate([property: JsonPropertyName("name")] string Name, [property: JsonPropertyName("description")] string Description, [property: JsonPropertyName("paths")] string[] Paths);
private static readonly string TemplateDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "AxCopilot", "templates");
private static readonly ScaffoldTemplate[] BuiltInTemplates = new ScaffoldTemplate[5]
{
new ScaffoldTemplate("webapi", "Web API 프로젝트", new string[8] { "src/Controllers/", "src/Models/", "src/Services/", "src/Middleware/", "tests/", "docs/", "README.md", ".gitignore" }),
new ScaffoldTemplate("console", "콘솔 애플리케이션", new string[5] { "src/", "src/Core/", "src/Services/", "tests/", "README.md" }),
new ScaffoldTemplate("wpf", "WPF 데스크톱 앱", new string[8] { "src/Views/", "src/ViewModels/", "src/Models/", "src/Services/", "src/Themes/", "src/Assets/", "tests/", "docs/" }),
new ScaffoldTemplate("data", "데이터 파이프라인", new string[9] { "src/Extractors/", "src/Transformers/", "src/Loaders/", "config/", "scripts/", "tests/", "data/input/", "data/output/", "README.md" }),
new ScaffoldTemplate("docs", "문서 프로젝트", new string[5] { "docs/", "images/", "templates/", "README.md", "CHANGELOG.md" })
};
public string? Prefix => "scaffold";
public PluginMetadata Metadata => new PluginMetadata("Scaffold", "프로젝트 스캐폴딩 — scaffold", "1.0", "AX");
public Task<IEnumerable<LauncherItem>> GetItemsAsync(string query, CancellationToken ct)
{
string q = query.Trim();
IEnumerable<ScaffoldTemplate> second = LoadUserTemplates();
List<ScaffoldTemplate> list = BuiltInTemplates.Concat(second).ToList();
if (string.IsNullOrWhiteSpace(q))
{
List<LauncherItem> list2 = list.Select((ScaffoldTemplate t) => new LauncherItem("[" + t.Name + "] " + t.Description, $"{t.Paths.Length}개 폴더/파일 · Enter → 대상 경로 입력 후 생성", null, t, null, "\ue8b7")).ToList();
list2.Insert(0, new LauncherItem("프로젝트 스캐폴딩", $"총 {list.Count}개 템플릿 · 이름을 입력해 필터링", null, null, null, "\ue946"));
return Task.FromResult((IEnumerable<LauncherItem>)list2);
}
if (q.Contains('\\') || q.Contains('/'))
{
int num = q.LastIndexOf(' ');
if (num > 0)
{
string text = q.Substring(0, num).Trim();
string text2 = q;
int num2 = num + 1;
string templateName = text2.Substring(num2, text2.Length - num2).Trim();
ScaffoldTemplate scaffoldTemplate = list.FirstOrDefault((ScaffoldTemplate t) => t.Name.Equals(templateName, StringComparison.OrdinalIgnoreCase));
if (scaffoldTemplate != null)
{
return Task.FromResult((IEnumerable<LauncherItem>)new _003C_003Ez__ReadOnlySingleElementList<LauncherItem>(new LauncherItem("[" + scaffoldTemplate.Name + "] → " + text, $"{scaffoldTemplate.Paths.Length}개 폴더/파일 생성 · Enter로 실행", null, ValueTuple.Create(text, scaffoldTemplate), null, "\ue74e")));
}
}
}
IEnumerable<ScaffoldTemplate> source = list.Where((ScaffoldTemplate t) => t.Name.Contains(q, StringComparison.OrdinalIgnoreCase) || t.Description.Contains(q, StringComparison.OrdinalIgnoreCase));
List<LauncherItem> list3 = source.Select(delegate(ScaffoldTemplate t)
{
string text3 = string.Join(", ", t.Paths.Take(4));
if (t.Paths.Length > 4)
{
text3 += $" ... (+{t.Paths.Length - 4})";
}
return new LauncherItem("[" + t.Name + "] " + t.Description, text3 + " · 사용법: scaffold [대상경로] " + t.Name, null, t, null, "\ue8b7");
}).ToList();
if (!list3.Any())
{
list3.Add(new LauncherItem("'" + q + "'에 해당하는 템플릿 없음", "scaffold 으로 전체 목록 확인", null, null, null, "\ue7ba"));
}
return Task.FromResult((IEnumerable<LauncherItem>)list3);
}
public Task ExecuteAsync(LauncherItem item, CancellationToken ct)
{
if (!(item.Data is (string, ScaffoldTemplate) tuple))
{
if (item.Data is ScaffoldTemplate scaffoldTemplate)
{
string usage = "scaffold [대상경로] " + scaffoldTemplate.Name;
try
{
Application current = Application.Current;
if (current != null)
{
((DispatcherObject)current).Dispatcher.Invoke((Action)delegate
{
Clipboard.SetText(usage);
});
}
}
catch
{
}
}
return Task.CompletedTask;
}
var (basePath, template) = tuple;
return CreateStructure(basePath, template);
}
private static Task CreateStructure(string basePath, ScaffoldTemplate template)
{
try
{
int num = 0;
string[] paths = template.Paths;
foreach (string text in paths)
{
string path = Path.Combine(basePath, text.Replace('/', Path.DirectorySeparatorChar));
if (text.EndsWith('/') || text.EndsWith('\\') || !Path.HasExtension(text))
{
Directory.CreateDirectory(path);
}
else
{
Directory.CreateDirectory(Path.GetDirectoryName(path));
if (!File.Exists(path))
{
File.WriteAllText(path, "");
}
}
num++;
}
NotificationService.Notify("스캐폴딩 완료", $"[{template.Name}] {num}개 항목 생성 → {basePath}");
}
catch (Exception ex)
{
LogService.Error("스캐폴딩 실패: " + ex.Message);
NotificationService.Notify("AX Copilot", "스캐폴딩 실패: " + ex.Message);
}
return Task.CompletedTask;
}
private static IEnumerable<ScaffoldTemplate> LoadUserTemplates()
{
if (!Directory.Exists(TemplateDir))
{
yield break;
}
string[] files = Directory.GetFiles(TemplateDir, "*.json");
foreach (string file in files)
{
ScaffoldTemplate tmpl = null;
try
{
string json = File.ReadAllText(file);
tmpl = JsonSerializer.Deserialize<ScaffoldTemplate>(json);
}
catch
{
}
if (tmpl != null)
{
yield return tmpl;
}
}
}
}