Initial commit to new repository
This commit is contained in:
100
src/AxCopilot/Handlers/EnvHandler.cs
Normal file
100
src/AxCopilot/Handlers/EnvHandler.cs
Normal file
@@ -0,0 +1,100 @@
|
||||
using AxCopilot.SDK;
|
||||
using AxCopilot.Themes;
|
||||
|
||||
namespace AxCopilot.Handlers;
|
||||
|
||||
/// <summary>
|
||||
/// 환경변수 조회 핸들러. "env" 프리픽스로 사용합니다.
|
||||
/// 예: env → 자주 쓰는 환경변수 목록
|
||||
/// env PATH → PATH 값 표시 (Enter로 복사)
|
||||
/// env java → 이름에 "java" 포함된 환경변수 검색
|
||||
/// </summary>
|
||||
public class EnvHandler : IActionHandler
|
||||
{
|
||||
public string? Prefix => "env";
|
||||
|
||||
public PluginMetadata Metadata => new(
|
||||
"EnvVars",
|
||||
"환경변수 조회 — env 뒤에 변수명 입력",
|
||||
"1.0",
|
||||
"AX");
|
||||
|
||||
// 자주 쓰는 환경변수 우선 표시 순서
|
||||
private static readonly string[] _priorityKeys =
|
||||
[
|
||||
"PATH", "JAVA_HOME", "PYTHON_HOME", "NODE_HOME", "GOPATH", "GOROOT",
|
||||
"USERPROFILE", "APPDATA", "LOCALAPPDATA", "TEMP", "TMP",
|
||||
"COMPUTERNAME", "USERNAME", "USERDOMAIN", "OS", "PROCESSOR_ARCHITECTURE",
|
||||
"SYSTEMROOT", "WINDIR", "PROGRAMFILES", "PROGRAMFILES(X86)",
|
||||
"COMMONPROGRAMFILES", "NUMBER_OF_PROCESSORS"
|
||||
];
|
||||
|
||||
public Task<IEnumerable<LauncherItem>> GetItemsAsync(string query, CancellationToken ct)
|
||||
{
|
||||
var q = query.Trim();
|
||||
|
||||
var allVars = Environment.GetEnvironmentVariables()
|
||||
.Cast<System.Collections.DictionaryEntry>()
|
||||
.Select(e => (Key: e.Key?.ToString() ?? "", Value: e.Value?.ToString() ?? ""))
|
||||
.Where(x => !string.IsNullOrEmpty(x.Key))
|
||||
.ToList();
|
||||
|
||||
IEnumerable<(string Key, string Value)> filtered;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(q))
|
||||
{
|
||||
// 우선순위 키를 앞에, 나머지 알파벳 순
|
||||
var prioritySet = new HashSet<string>(_priorityKeys, StringComparer.OrdinalIgnoreCase);
|
||||
var prioritized = _priorityKeys
|
||||
.Where(k => allVars.Any(v => string.Equals(v.Key, k, StringComparison.OrdinalIgnoreCase)))
|
||||
.Select(k => allVars.First(v => string.Equals(v.Key, k, StringComparison.OrdinalIgnoreCase)));
|
||||
var rest = allVars
|
||||
.Where(v => !prioritySet.Contains(v.Key))
|
||||
.OrderBy(v => v.Key);
|
||||
filtered = prioritized.Concat(rest).Take(20);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 키 또는 값에 쿼리 포함 검색
|
||||
filtered = allVars
|
||||
.Where(v => v.Key.Contains(q, StringComparison.OrdinalIgnoreCase)
|
||||
|| v.Value.Contains(q, StringComparison.OrdinalIgnoreCase))
|
||||
.OrderBy(v => v.Key.StartsWith(q, StringComparison.OrdinalIgnoreCase) ? 0 : 1)
|
||||
.ThenBy(v => v.Key)
|
||||
.Take(20);
|
||||
}
|
||||
|
||||
var items = filtered.Select(v =>
|
||||
{
|
||||
// PATH처럼 긴 값은 첫 경로만 미리보기
|
||||
var preview = v.Value.Length > 80 ? v.Value[..77] + "…" : v.Value;
|
||||
// PATH 변수는 세미콜론으로 분할하여 첫 항목만 표시
|
||||
if (v.Key.Equals("PATH", StringComparison.OrdinalIgnoreCase) && v.Value.Contains(';'))
|
||||
preview = v.Value.Split(';')[0] + $" (외 {v.Value.Split(';').Length - 1}개)";
|
||||
|
||||
return new LauncherItem(
|
||||
v.Key,
|
||||
$"{preview} · Enter로 값 복사",
|
||||
null,
|
||||
v.Value,
|
||||
Symbol: Symbols.EnvVar);
|
||||
}).ToList<LauncherItem>();
|
||||
|
||||
if (!items.Any())
|
||||
items.Add(new LauncherItem(
|
||||
$"'{q}' — 환경변수 없음",
|
||||
"해당 이름의 환경변수를 찾을 수 없습니다",
|
||||
null, null, Symbol: Symbols.Warning));
|
||||
|
||||
return Task.FromResult<IEnumerable<LauncherItem>>(items);
|
||||
}
|
||||
|
||||
public Task ExecuteAsync(LauncherItem item, CancellationToken ct)
|
||||
{
|
||||
if (item.Data is string value)
|
||||
{
|
||||
try { System.Windows.Clipboard.SetText(value); } catch (Exception) { }
|
||||
}
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user