-
Notifications
You must be signed in to change notification settings - Fork 0
Diff Viewer ko
jvim에는 스크롤 동기화, 접기 동기화, hunk 탐색이 가능한 나란히 비교 diff 뷰어가 포함되어 있습니다.
# 두 JSON 파일 비교
jvimdiff file1.json file2.json
# JSON 정규화 건너뛰기 (원본 텍스트 비교)
jvimdiff --no-normalize file1.json file2.json
# JSONL 파일 비교
jvimdiff --jsonl file1.json file2.jsonjvd 단축 명령도 사용 가능합니다.
기본적으로 jvim은 비교 전 두 파일을 정규화합니다:
- JSON을 파싱하고
indent=4와sort_keys=True로 재직렬화 - 키 순서 차이는 무시됨
- 실제 값 차이만 표시됨
--no-normalize 사용 시:
- JSON이
indent=4로 포맷팅되지만 키는 정렬되지 않음 - 키 순서 차이가 diff로 나타남
- 키 순서가 중요한 워크플로우에 유용
반복적인 구조를 가진 대규모 JSON 파일(예: 객체 배열)에서 jvim은 블록 기반 diff 최적화를 사용합니다:
-
블록 감지: 양쪽 파일에서 같은 들여쓰기 수준의 반복되는
{/[여는 괄호를 스캔 - 최소 임계값: 같은 들여쓰기 수준에 최소 4개 블록이 있어야 블록 모드 활성화
-
세그먼트 구축: 블록 경계(여는
{/[에서 닫는}/]까지)에서 내용을 세그먼트로 분할 -
세그먼트 매칭: 개별 라인 대신 전체 세그먼트(문자열로 결합)에
SequenceMatcher사용 - 세그먼트 내 diff: 매칭되었지만 다른 세그먼트 내에서 라인 단위 diff 수행
다음과 같은 파일에서 diff 품질이 크게 향상됩니다:
{
"users": [
{ "name": "Alice", "age": 30 },
{ "name": "Bob", "age": 25 },
...수백 개 이상...
]
}총 라인 수(좌 + 우)가 50,000줄을 초과하면 diff 엔진은 전체 내용을 단일 REPLACE hunk로 처리합니다. 이는 매우 큰 파일에서의 과도한 계산 시간을 방지합니다.
충분한 블록 구조가 없는 파일에서는 표준 라인별 SequenceMatcher diff가 사용됩니다.
| 색상 | 의미 |
|---|---|
빨간 배경 (#72261a) |
삭제 — 왼쪽 파일에만 존재하는 줄 |
초록 배경 (#1e5c34) |
삽입 — 오른쪽 파일에만 존재하는 줄 |
회색 배경 (#6a6a6a) |
변경 — 파일 간 다른 줄 |
어두운 배경 (#2a2a2a) |
필러 — 정렬을 위해 추가된 패딩 줄 |
필러 줄은 좌우 패널을 수직으로 정렬하기 위해 한쪽에 삽입되는 빈 줄입니다.
양쪽 패널이 자동으로 함께 스크롤되고 이동합니다:
- 포커스된 패널이 스크롤 위치, 커서 행, 커서 열을 주도
- 비포커스 패널이 매 렌더마다
_scroll_top,cursor_row,cursor_col을 미러링 -
cursor_col은 대상 라인 길이에 맞게 클램핑되어 범위 초과 방지 - 이산 이벤트가 아닌 실시간으로 동기화
한쪽 패널의 접기 작업이 다른 쪽에 미러링됩니다:
-
za(토글),zo(열기),zc(닫기): 양쪽 패널에 적용 -
zM(모두 접기),zR(모두 펼치기): 양쪽 패널에 적용 - 접기 상태는
_sync_folds_to_target()API를 통해 동기화
초기 로드 시:
- 모든 구조가 접힘 (
_fold_all_nested()) - Diff 영역이 선택적으로 펼쳐짐:
- 하나 이상의 non-EQUAL 줄을 포함하는 접기가 열림
- diff 내용이 있는 접힌 문자열이 펼쳐짐
- 양쪽 패널이 같은 접기 상태를 받음
기본적으로 변경 부분만 보여주고, 변경되지 않은 섹션은 접혀 있습니다.
| 키 | 동작 |
|---|---|
]c |
다음 diff hunk로 이동 (마지막 이후 첫 번째로 순환) |
[c |
이전 diff hunk로 이동 (첫 번째에서 마지막으로 순환) |
상태 바에 표시: Hunk N/M (현재 hunk / 전체 hunk).
파일이 동일하면: "Files are identical".
| 키 | 동작 |
|---|---|
Tab |
좌우 패널 간 포커스 전환 |
포커스가 전환될 때 동기화 메커니즘을 통해 스크롤 위치가 유지됩니다. 활성 패널은 타이틀 바 색상으로 구분됩니다 — 포커스된 패널은 파란색 타이틀 바, 비활성 패널은 회색 타이틀 바로 표시됩니다.
Diff 뷰어는 메인 에디터와 동일한 거터 시스템을 공유합니다:
- 왼쪽 패널: 논리적 라인 번호와 JSONL 레코드 번호(JSONL인 경우) 표시
- 오른쪽 패널: JSONL 레코드 번호만 표시 (filler 행으로 양쪽 라인 수가 동일하므로 논리적 라인 번호 생략)
Diff 뷰어에서 ej는 양쪽 패널에 동시에 동작합니다:
- 내장 JSON 문자열이 있는 줄에 커서 위치
-
ej입력 — 양쪽 EJ 패널이 열림 - 다른 패널의 같은 행에서 내장 JSON을 확인
- 양쪽 모두 해당 행에 내장 JSON이 있으면:
- 두 내장 JSON 간 diff가 계산됨
- 양쪽 EJ 패널에 색상 코딩된 diff가 표시됨
- 한쪽만 내장 JSON이 있으면:
- 해당 쪽의 EJ 패널만 열리며 내용 표시 (diff 색상 없음)
메인 에디터와 마찬가지로 diff 뷰어도 중첩 EJ 레벨을 지원합니다:
- 각 쪽이 자체 EJ 스택을 유지 (
_left_ej_stack,_right_ej_stack) - 중첩된
ej를 열면 현재 내용이 스택에 푸시 - 닫기(
:q)하면 스택을 팝하고 이전 레벨 복원 - 동기화 유지를 위해 양쪽 스택이 함께 팝
EJ 패널은 메인 패널과 독립적으로 자체 스크롤 및 접기 동기화를 가집니다.
JSONL 파일은 레코드 단위로 diff됩니다:
- 양쪽 파일이 레코드로 분할
- 각 레코드가
indent=4로 포맷팅 (정규화 시sort_keys포함) -
SequenceMatcher가 레코드를 전체 단위로 매칭 - 매칭되었지만 다른 레코드는 내부적으로 라인 단위 diff
- 레코드 사이 빈 줄로 구분하여 표시
- 빈 구분 줄은 주변 내용의 diff 태그를 계승
Diff의 JSONL 모드는 어느 한쪽 파일이 .jsonl 확장자를 가지면 자동 감지됩니다. --jsonl로 강제할 수도 있습니다.
Diff 뷰어는 항상 읽기 전용입니다. 메인 패널과 EJ 패널 모두 read_only=True로 생성됩니다. 탐색, 검색, 접기는 정상적으로 동작하지만 편집 작업은 비활성화됩니다.