결과를 남에게 보내거나 결재에 붙일 때 화면을 캡처하는 것 말고는 방법이 없었다.
캡처는 검색도 안 되고 줄 번호를 짚어 말하기도 어렵다.
Services/CompareReport.cs 신설. 파일 비교와 폴더 비교 양쪽에서 쓴다. 글을
만드는 일만 여기서 하고, 어디에 저장할지 묻는 것은 화면 쪽 일이다. 그래야
화면 없이 검사한다.
파일 쪽은 요약과 다른 줄 목록을 적는다. 줄 번호는 양쪽을 다 적는다. 한쪽에만
있는 줄이 있어 번호가 어긋나므로 하나만 적으면 파일에서 그 줄을 찾을 수 없다.
폴더 쪽은 상태와 상대 경로를 줄마다 적는다. 폴더 자체는 적지 않는다. 그 안의
파일이 이미 다 적혀 있다.
곁들여 요약에 주석만 다른 수를 덧붙였다. "다름 3(주석만 1)". D-1 로 새로 생긴
갈래가 요약에는 안 보였다.
확인: 두 화면에서 각각 뽑아 메모장으로 열었다. ReportTest 23건 신설.
전체 451건 통과.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
WeldController.cpp 를 3-Way 로 열면 BASE 칸이 통째로 비어 보였다. 고장이
아니다. 두 브랜치의 공통 조상(9b48b82)에는 그 파일이 아예 없다. master 와
feature/cpp-tuning 이 각자 새로 만든 파일이라 견줄 조상이 없다. 그래서 모든
줄이 "양쪽에서 새로 넣은 줄"이 되고 충돌 6개가 나온다.
다만 화면이 그 사실을 말해 주지 않았다. 빈 칸은 누가 봐도 고장으로 읽힌다.
BASE 머리글에 "이 파일 없음 - 양쪽에서 새로 만든 파일입니다" 라고 적는다.
조상에 파일이 있으면 지금까지처럼 파일 이름이 나온다.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
D-2. C++ 문법 강조는 이미 되고 있었다. LanguageProfile.CFamily 가 확장자
아홉 가지를 맡고 예약어/주석/문자열도 들어 있다. 빠진 것은 전처리 지시문
하나였다. #include 가 # 과 include 로 쪼개져 보통 낱말처럼 칠해졌다. 줄
첫머리가 # 이면 그 줄 전체를 지시문 색으로 칠한다. C# 쪽과 같은 규칙이다.
언어표에 hasPreprocessor 를 두어 C 계열에서만 켠다.
D-5. 2-Way 는 이미 됐다. 3-Way 가 잘못 동작하고 있었다. 덩어리를 BASE 에서
가져오고 있었는데 3-Way 에서 BASE 는 공통 조상이다. 저쪽(REMOTE)을 가져오는
것이 Take Theirs 이고 덩어리 반영은 그것을 줄 묶음으로 하는 것인데, BASE 를
가져오면 조상으로 되돌리는 셈이라 뜻이 전혀 달라진다. 덩어리를 묶는 기준도
모드에 맞췄다.
확인: 충돌 6개짜리 C++ 파일에서 다음 충돌 -> 이 덩어리 반영 한 번에 네 줄이
REMOTE 값으로 바뀌고 Conflict 6 -> 2. LangTest 12건 추가. 전체 424건 통과.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
E-5. 줄을 반영한 뒤 비교 규칙을 하나 건드리면 초록(머지 반영함)이던 줄이
보라(직접 수정)로 바뀌었다.
반영 표시가 되돌리기 스택에만 있었다. 규칙을 바꾸면 화면을 통째로 다시
만들면서 그 스택을 비운다. 그러면 표시가 사라지고 남는 단서는 "글이 원본과
다르다"뿐이라 직접 수정으로 칠해진다. B-3 에서 Take Mine 이 충돌을 못 지우던
것과 같은 뿌리다.
- 반영할 때 줄 번호로도 남긴다. BASE 줄 번호, 없으면 MINE 줄 번호.
- 다시 만들 때 반영 여부를 먼저 본다. 반영한 줄은 직접 수정 조건에도 걸린다.
- 되돌리면 그 기록도 함께 지운다.
곁들여 머지 주석 줄도 같은 이유로 보라색이 됐다. 주석 줄이라는 표시 역시 줄
객체에만 있어서 다시 만들면 사라진다. 글을 보고 알아보게 했다
(MergeNote.LooksLikeNote).
E-6. Alt+위/아래로 차이를 옮겨 다니면 칸 아래 상태바 위에 코드가 겹쳐
그려졌다. 표시층은 편집기 글자와 눈높이를 맞추려고 RenderTransform 으로 살짝
밀어 두는데, 그건 배치가 아니라 그리기라 칸 밖으로 나가도 막는 것이 없다.
격자의 행도 자기 칸 밖으로 나가는 자식을 자르지 않는다. 코드가 놓이는 자리를
자르는 상자로 감쌌다. 네 칸 모두.
확인: 반영 후 공백/Aa 규칙을 눌러도 머지 반영함 2 · 직접 수정 0 그대로.
Alt+아래 8회, Alt+위 6회 눌러도 마지막 줄이 경계에서 깨끗이 잘린다.
NoteTest 13건 추가. 전체 399 -> 412건 통과.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
B-1. 원본 세 칸에 가로 스크롤 막대 신설.
이 칸들은 ScrollViewer 를 가로로 굴리지 않고(줄 번호까지 밀려 나간다) 글자만
SourceShiftX 로 민다. 그래서 ScrollViewer 가 만드는 막대는 움직이지 않는
막대가 되어 감춰 두고 있었고, 긴 줄이 있다는 사실 자체를 알 수 없었다.
막대를 따로 놓고 SourceShiftX 와 값을 서로 맞춘다.
B-2. 워드랩을 켠 3-Way 에서 세로 스크롤이 아예 안 되던 문제.
원인이 둘이었다.
- 메아리를 막는 자물쇠를 try/finally 로 그 자리에서 풀고 있었다. 목록의 스크롤
알림은 배치가 끝난 다음에 오므로 그때는 이미 열려 있었고, 그 메아리가 다시
편집기를 굴렸다. 이제 그 일로 밀려서 오는 알림이 다 지나간 뒤에 푼다.
- 두 좌표계를 픽셀로 환산하고 있었는데, 목록이 가상화라 안 그려진 행의 높이를
알 수 없어 환산이 어긋났다. 워드랩일 때는 행 단위로 굴려 "몇 번째 행이 맨
위인가"만 주고받는다.
곁들여, 편집기 맨 위 행을 스크롤 값 나눗셈이 아니라 좌표로 물어본다.
B-3. Take Mine 을 눌러도 남은 충돌이 줄지 않던 문제.
"내 것으로 간다"는 결정은 글을 바꾸지 않아 되돌리기 스택에 남지 않는데,
RefreshAppliedFlags 가 스택만 보고 반영 표시를 다시 칠하면서 그 표시를 지웠다.
줄 번호로 기억해 둔 결정을 같이 보도록 고치고, 같은 판단을 IsDecidedAsMine
하나로 합쳤다.
확인: 막대 끌기/가로 휠/워드랩 토글, 워드랩 켠 채 네 칸이 같은 행을 맨 위에
놓는 것, 충돌 6개를 Take Mine/Theirs 번갈아 눌러 "충돌 정리 끝"까지.
테스트 399건 그대로 통과.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
원인은 경로에 섞인 슬래시였다. 폴더 칸에 C:/Users/... 처럼 슬래시가 섞인
값이 들어 있으면 Directory.Exists 는 통과시키지만, 대화상자의
InitialDirectory 는 윈도우 셸(COM)이 그대로 해석하다 ArgumentException 을
던진다. 그 예외는 대입할 때가 아니라 ShowDialog() 안쪽에서 올라오기 때문에
대입 줄만 try 로 감싸 둔 파일 비교 쪽도 똑같이 죽게 돼 있었다.
- Services/PathUtil.cs 신설. 셸에 넘길 경로는 전부 여기를 거친다.
- 폴더·파일 고르기 둘 다 ShowDialog() 를 감쌌다. 끊긴 네트워크 드라이브처럼
정규화로 걸러지지 않는 경우에는 시작 폴더 없이 한 번 더 연다.
- 3차 작업 지시서와 진행 상황 문서 신설·갱신.
검사: PathTest 31건 신설(356 -> 387건). 실제 실행으로 왼쪽·오른쪽 폴더 10회
연속, 파일 비교의 기준·내 파일 각 1회 확인.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
git config 에 mergetool/difftool 로 등록하는 쪽은 전부터 있었는데 정작 그 인자를
받는 쪽이 없어 다리가 반만 놓여 있었다. 나머지 반쪽을 놓는다.
- Services/StartupArgs: 켤 때 넘어온 인자를 읽는다.
이름표 붙은 것(--merge --base B --local L --remote R --merged M)과 그냥 넘어온 경로
둘 다 받는다. 탐색기는 "%1" 하나만 주므로 후자가 그 자리다. 경로가 폴더면 폴더 비교로,
파일이면 파일 비교로 보낸다.
difftool 의 LOCAL/REMOTE 와 탐색기의 "먼저 고른 것/나중 것" 은 뜻이 달라 따로 담는다 -
이 도구의 왼쪽은 늘 "기준"이라 difftool 에서는 REMOTE 가 왼쪽이 된다.
- Services/ShellIntegration: 탐색기 우클릭 메뉴를 파일·폴더·폴더 배경 세 자리에 넣는다.
HKEY_CURRENT_USER 에만 쓰므로 관리자 권한이 필요 없고, 지울 때도 이 사람 것만 지운다 -
사내 PC 에 권한 없이 깔리는 것이 전제다. 셸 확장 DLL 을 만들지 않은 것도 같은 이유로,
DLL 은 탐색기 프로세스 안에서 돌아 잘못되면 탐색기가 통째로 죽는다.
폴더 배경에서는 %1 이 아니라 %V 가 그 폴더다.
- GitWorkspace.RouteStartupArgs 가 요청을 화면으로 보낸다. 창이 다 만들어진 뒤에 탭을
옮겨야 해서(그 전에는 옮길 곳이 없다) ApplicationIdle 로 미루고, 요청 자체는 남겨 두어
늦게 만들어진 화면이 스스로 집어 가게 했다(폴더 비교 쪽도 파일 비교와 같은 방식으로 추가).
- 곁들여: 파일 비교가 "양쪽 경로가 모두 있을 때만" 열리고 있었다. 탐색기는 하나만 주므로
한쪽만 있어도 열도록 고쳤다 - 없는 쪽은 빈 내용이 되어 전부 추가로 보인다.
ArgsTest 26건 신설. 전체 356건 통과.
실행 확인: 폴더 경로로 켜면 폴더 비교 탭에 그 폴더가 왼쪽에, 파일 두 개로 켜면
파일 비교 탭에 나란히. 등록 버튼을 누르면 레지스트리 3개 키가 생기고 버튼 이름이
"탐색기 우클릭 해제" 로 바뀐다.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
"줄 단위로 비교할 수 없습니다" 한 줄로 끝내면 정작 알고 싶은 "같은지 다른지" 를
모른 채 화면을 닫게 된다. 답이 있는 화면으로 바꿨다.
- 크기 · SHA-1 · 처음 갈리는 바이트 위치를 한 줄로 알려 준다. 크기가 같아도 내용이
다를 수 있어 해시로 본다. 앞부분이 같고 길이만 다르면 짧은 쪽이 끝나는 자리가
갈리는 지점이다.
- 그림(.png/.jpg/.bmp/.gif/.ico/.tif)이면 나란히 띄운다 - 16진으로 보는 것보다 훨씬 빠르다.
- 그 밖에는 앞 4KB 를 16진으로 나란히 놓고, 16바이트 단위로 다른 줄에만 색을 준다.
볼 수 있는 글자는 오른쪽 칸에 그대로 적는다 - 16진만 보면 무슨 파일인지 모른다.
수십 MB 짜리를 전부 그리면 화면이 굳으므로 앞부분만 그리고 잘렸다고 알린다.
BinaryTest 25건 신설(같음·가운데 다름·길이 다름·16진 표기·줄 수 제한·글자 칸·
없는 파일·그림 판별). 전체 330건 통과.
실행 확인: .bin 두 개 -> "다릅니다 · 왼쪽 17 B · 오른쪽 19 B · 처음 갈리는 곳 0x10"
+ 16진 두 줄(0x10 줄만 색). .png 두 개 -> 나란히 표시.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- 바꾸기: 찾기 칸 아래에 바꿀 말 줄이 붙는다. Ctrl+F 로 열면 안 뜬다 -
찾기만 할 때 자리를 뺏지 않기 위해서다. "바꾸기" 는 고른 자리가 찾는 말일 때만
바꾸고 다음으로 넘어간다 - 엉뚱한 자리를 덮어쓰는 것보다 한 번 더 누르게 하는 편이 낫다.
"모두" 는 한 번에 바꾸고 몇 개인지 알려 준다(되돌리기는 편집기의 Ctrl+Z 가 맡는다).
- 덩어리 단위 반영: 줄 하나씩만 되면 연속 다섯 줄을 다섯 번 눌러야 한다.
WinMerge·Beyond Compare 가 덩어리를 기본 단위로 쓰는 이유다. 덩어리는
"차이로 잡힌 줄이 이어지는 구간"이고, 캐럿이 그 안에 있을 때만 켜진다. Alt+Shift+→.
- 저장 형식: 사내 소스에 CP949 로 저장된 파일이 섞여 있어 새로 만드는 파일과 형식이
갈린다. 읽어서 보여 주기만 하면 그 갈림을 못 고치므로 저장할 때 고를 수 있게 했다.
기본값 "원본 유지" 라 지금까지와 동작이 같다. Save & Commit 경로도 같은 값을 쓴다
(전에는 File.WriteAllText 로 UTF-8 고정이었다).
실행 확인: PulseUs → PulseMicros 2개 바꿈 · 마지막 차이에서 2줄 한 번에 반영.
단축키 61 → 63건, 전체 305건 통과.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
지금까지는 안 겹치는 변경까지 사람이 하나씩 눌러야 해서, 정작 판단이 필요한
서너 줄이 그 속에 묻혔다. git merge 가 자동으로 해 주는 일을 여기서도 해 준다.
- 자동 병합: 저쪽만 고친 줄(ThreeWayState.RemoteChanged)을 한 번에 가져온다.
충돌과 내가 고친 줄은 건드리지 않는다. 이미 가져온 줄은 더 이상 RemoteChanged 가
아니므로 여러 번 눌러도 안전하다.
- 충돌만 이동: Alt+Shift+↑↓. "다음 차이" 와 달리 아직 안 정한 충돌만 딛는다.
- 완료 판정: ACTIONS 에 "남은 충돌 N개"(빨강) → "충돌 정리 끝"(초록).
판단이 하나 필요했다 - 충돌 여부는 BASE·MINE·REMOTE 를 견주면 저절로 나오지만,
"내 것으로 간다"고 정한 줄은 내용이 그대로라 여전히 충돌로 보인다. 그래서
MergeLine.NeedsDecision(충돌이면서 반영·수정 표시가 없는 줄)을 따로 두었다.
그 결정은 글을 바꾸지 않아 편집 뒤 재정렬하면 사라지므로, 얼어 있는 BASE 줄 번호
(없으면 MINE 줄 번호)로 붙들어 되살린다.
곁들여 고친 것: Take Mine / Take Theirs 버튼이 줄을 옮겨도 켜짐·꺼짐이 그대로였다.
CommunityToolkit 커맨드는 CommandManager 를 구독하지 않는데 이 둘만 갱신 목록에서
빠져 있었다 - 키보드(Alt+←/→)로는 되고 버튼만 안 되던 이유다.
실행 확인(mergehub-demo, 3-Way = feature/cooling): 자동 병합으로 Theirs only 1→0,
다음 충돌+Take Theirs 를 반복해 남은 충돌 3→2→1→"충돌 정리 끝".
테스트 290 → 293건 전부 통과(단축키 3건 추가).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
UbisamBase 플랫폼 위에서 도는 플러그인. 지금까지 만든 것을 그대로 담는다.
- 폴더 비교 / 파일 비교(부분 수용·워드랩·찾기) / 3-Way 병합 / Git 조작
- 비교 엔진: histogram 정렬 · 이동 블록 감지 · 무시 규칙 · 13개 언어 토크나이저
- doc/ 에 작업 지시서와 진행 기록
빌드 산출물(bin/obj)은 추적하지 않는다 - 플랫폼 런타임이 빌드 때마다
D:\UbisamPlatform\bin 에서 복사되어 들어오므로 저장소에 담을 이유가 없다.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>