using System; using System.IO; namespace MergeHub.Services { /// /// 머지로 반영한 줄에 남기는 주석을 만든다. /// /// 원칙 두 가지: /// 1. 설명(사용자 입력)은 선택이지만, **누가·언제 반영했는지는 항상 들어간다.** /// 2. 줄 "위"가 아니라 "끝"에 붙인다 - BASE/LOCAL 을 같은 줄 번호로 나란히 보여주는 구조라 /// 줄을 새로 끼워 넣으면 두 패널의 정렬이 통째로 어긋난다. /// public static class MergeNote { /// 코드와 주석 사이 간격. private const string Gap = " "; /// /// 주석 한 조각을 만든다. 구성은 딱 세 가지 - [사용자] 날짜 설명. /// 설명이 비어 있어도 [사용자]와 날짜는 항상 남는다. /// public static string Build(string? author, DateTime when, string? comment, string? path) { var who = string.IsNullOrWhiteSpace(author) ? Environment.UserName : author!.Trim(); var body = $"[{who}] {when:yyyy-MM-dd}"; var note = comment?.Trim(); if (!string.IsNullOrEmpty(note)) body += $" {note}"; var (open, close) = CommentTokensFor(path); return close is null ? $"{open} {body}" : $"{open} {body} {close}"; } /// 코드 줄 끝에 주석을 붙인다. 줄 끝 공백은 정리한다. public static string Append(string line, string note) { if (string.IsNullOrEmpty(note)) return line; return line.TrimEnd() + Gap + note; } /// 확장자에 맞는 주석 기호. 모르는 확장자는 C 계열(//)로 본다. public static (string Open, string? Close) CommentTokensFor(string? path) { var ext = string.IsNullOrEmpty(path) ? string.Empty : Path.GetExtension(path).ToLowerInvariant(); switch (ext) { case ".py": case ".sh": case ".ps1": case ".psm1": case ".yml": case ".yaml": case ".toml": case ".ini": return ("#", null); case ".xml": case ".xaml": case ".html": case ".htm": case ".csproj": case ".vbproj": case ".config": case ".svg": case ".resx": return (""); case ".sql": case ".lua": return ("--", null); case ".vb": return ("'", null); case ".bat": case ".cmd": return ("REM", null); default: // .cs .cpp .h .hpp .c .java .js .ts .json5 등 C 계열 return ("//", null); } } } }