Initial commit to new repository

This commit is contained in:
2026-04-03 18:22:19 +09:00
commit 4458bb0f52
7672 changed files with 452440 additions and 0 deletions

View File

@@ -0,0 +1,164 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Threading;
using AxCopilot.Models;
using AxCopilot.SDK;
using AxCopilot.Services;
namespace AxCopilot.Handlers;
public class SnippetHandler : IActionHandler
{
private struct INPUT
{
public uint type;
public InputUnion u;
}
[StructLayout(LayoutKind.Explicit)]
private struct InputUnion
{
[FieldOffset(0)]
public KEYBDINPUT ki;
}
private struct KEYBDINPUT
{
public ushort wVk;
public ushort wScan;
public uint dwFlags;
public uint time;
public nint dwExtraInfo;
}
private readonly SettingsService _settings;
public string? Prefix => ";";
public PluginMetadata Metadata => new PluginMetadata("Snippets", "텍스트 스니펫 — ; 뒤에 키워드 입력", "1.0", "AX");
public SnippetHandler(SettingsService settings)
{
_settings = settings;
}
public Task<IEnumerable<LauncherItem>> GetItemsAsync(string query, CancellationToken ct)
{
List<SnippetEntry> snippets = _settings.Settings.Snippets;
if (!snippets.Any())
{
return Task.FromResult((IEnumerable<LauncherItem>)new _003C_003Ez__ReadOnlySingleElementList<LauncherItem>(new LauncherItem("등록된 스니펫이 없습니다", "설정 → 스니펫 탭에서 추가하세요", null, null, null, "\ue70b")));
}
string q = query.Trim().ToLowerInvariant();
List<LauncherItem> list = (from s in snippets
where string.IsNullOrEmpty(q) || s.Key.ToLowerInvariant().Contains(q) || s.Name.ToLowerInvariant().Contains(q)
select new LauncherItem((s.Name.Length > 0) ? s.Name : s.Key, TruncatePreview(s.Content), null, s, null, "\ue70b")).ToList();
if (list.Count == 0)
{
list.Add(new LauncherItem("'" + query + "'에 해당하는 스니펫 없음", "설정에서 새 스니펫을 추가하세요", null, null, null, "\ue70b"));
}
return Task.FromResult((IEnumerable<LauncherItem>)list);
}
public Task ExecuteAsync(LauncherItem item, CancellationToken ct)
{
if (!(item.Data is SnippetEntry snippetEntry))
{
return Task.CompletedTask;
}
try
{
string text = ExpandVariables(snippetEntry.Content);
Clipboard.SetText(text);
Task.Delay(100, ct).ContinueWith(delegate
{
((DispatcherObject)Application.Current).Dispatcher.Invoke((Action)delegate
{
INPUT[] array = new INPUT[4]
{
new INPUT
{
type = 1u,
u = new InputUnion
{
ki = new KEYBDINPUT
{
wVk = 17
}
}
},
new INPUT
{
type = 1u,
u = new InputUnion
{
ki = new KEYBDINPUT
{
wVk = 86
}
}
},
new INPUT
{
type = 1u,
u = new InputUnion
{
ki = new KEYBDINPUT
{
wVk = 86,
dwFlags = 2u
}
}
},
new INPUT
{
type = 1u,
u = new InputUnion
{
ki = new KEYBDINPUT
{
wVk = 17,
dwFlags = 2u
}
}
}
};
SendInput((uint)array.Length, array, Marshal.SizeOf<INPUT>());
});
}, ct, TaskContinuationOptions.OnlyOnRanToCompletion, TaskScheduler.Default);
}
catch (Exception ex)
{
LogService.Warn("스니펫 실행 실패: " + ex.Message);
}
return Task.CompletedTask;
}
private static string ExpandVariables(string content)
{
DateTime now = DateTime.Now;
return content.Replace("{date}", now.ToString("yyyy-MM-dd")).Replace("{time}", now.ToString("HH:mm:ss")).Replace("{datetime}", now.ToString("yyyy-MM-dd HH:mm:ss"))
.Replace("{year}", now.Year.ToString())
.Replace("{month}", now.Month.ToString("D2"))
.Replace("{day}", now.Day.ToString("D2"));
}
private static string TruncatePreview(string content)
{
string text = content.Replace("\r\n", " ").Replace("\n", " ").Replace("\r", " ");
return (text.Length > 60) ? (text.Substring(0, 57) + "…") : text;
}
[DllImport("user32.dll")]
private static extern uint SendInput(uint nInputs, INPUT[] pInputs, int cbSize);
}