jvim 0.7.0__tar.gz → 0.7.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- jvim-0.7.1/.claude/settings.local.json +16 -0
- jvim-0.7.1/CLAUDE.local.md +3 -0
- jvim-0.7.1/COMMENTS.md +96 -0
- {jvim-0.7.0 → jvim-0.7.1}/PKG-INFO +1 -1
- jvim-0.7.1/demo/demo.tape +94 -0
- jvim-0.7.1/demo/jvim-demo.gif +0 -0
- jvim-0.7.1/demo/sample.json +55 -0
- jvim-0.7.1/docs/demo-feature.json +12 -0
- jvim-0.7.1/docs/jvim-editor-core.gif +0 -0
- jvim-0.7.1/docs/jvim-editor-core.tape +43 -0
- jvim-0.7.1/docs/jvim-embedded-json.gif +0 -0
- jvim-0.7.1/docs/jvim-embedded-json.tape +42 -0
- jvim-0.7.1/docs/jvim-jsonpath.gif +0 -0
- jvim-0.7.1/docs/jvim-jsonpath.tape +56 -0
- jvim-0.7.1/docs/jvimdiff-demo.gif +0 -0
- jvim-0.7.1/docs/jvimdiff-demo.tape +44 -0
- jvim-0.7.1/docs/jvimdiff-sync.gif +0 -0
- jvim-0.7.1/docs/jvimdiff-sync.tape +29 -0
- {jvim-0.7.0 → jvim-0.7.1}/pyproject.toml +1 -1
- {jvim-0.7.0/.worktrees/codex-fix-fold → jvim-0.7.1}/src/jvim/__init__.py +1 -1
- {jvim-0.7.0 → jvim-0.7.1}/src/jvim/action/__init__.py +6 -0
- {jvim-0.7.0 → jvim-0.7.1}/src/jvim/action/clipboard.py +3 -4
- jvim-0.7.1/src/jvim/action/content.py +238 -0
- {jvim-0.7.0 → jvim-0.7.1}/src/jvim/action/folding.py +17 -0
- jvim-0.7.1/src/jvim/action/jsonpath_locator.py +214 -0
- jvim-0.7.1/src/jvim/action/render.py +735 -0
- {jvim-0.7.0 → jvim-0.7.1}/src/jvim/action/substitute.py +45 -23
- jvim-0.7.1/src/jvim/action/undo.py +72 -0
- {jvim-0.7.0 → jvim-0.7.1}/src/jvim/action/visual.py +1 -5
- {jvim-0.7.0 → jvim-0.7.1}/src/jvim/differ.py +23 -13
- {jvim-0.7.0 → jvim-0.7.1}/src/jvim/mode/command.py +129 -86
- {jvim-0.7.0 → jvim-0.7.1}/src/jvim/mode/normal.py +181 -139
- {jvim-0.7.0 → jvim-0.7.1}/src/jvim/mode/search.py +15 -204
- jvim-0.7.1/src/jvim/widget.py +366 -0
- jvim-0.7.1/tasks/lessons.md +20 -0
- {jvim-0.7.0 → jvim-0.7.1}/tests/test_editor.py +31 -0
- jvim-0.7.1/tests/test_jsonpath_locator.py +52 -0
- {jvim-0.7.0 → jvim-0.7.1}/uv.lock +1 -1
- jvim-0.7.0/.claude/CLAUDE.md +0 -7
- jvim-0.7.0/.claude/settings.local.json +0 -40
- jvim-0.7.0/.worktrees/codex-fix-fold/.git +0 -1
- jvim-0.7.0/.worktrees/codex-fix-fold/.gitignore +0 -12
- jvim-0.7.0/.worktrees/codex-fix-fold/README.kr.md +0 -165
- jvim-0.7.0/.worktrees/codex-fix-fold/README.md +0 -167
- jvim-0.7.0/.worktrees/codex-fix-fold/pyproject.toml +0 -57
- jvim-0.7.0/.worktrees/codex-fix-fold/src/jvim/data/help.json +0 -64
- jvim-0.7.0/.worktrees/codex-fix-fold/src/jvim/diff.py +0 -346
- jvim-0.7.0/.worktrees/codex-fix-fold/src/jvim/differ.py +0 -538
- jvim-0.7.0/.worktrees/codex-fix-fold/src/jvim/differ.tcss +0 -56
- jvim-0.7.0/.worktrees/codex-fix-fold/src/jvim/editor.py +0 -411
- jvim-0.7.0/.worktrees/codex-fix-fold/src/jvim/widget.py +0 -2843
- jvim-0.7.0/.worktrees/codex-fix-fold/tests/test_diff.py +0 -633
- jvim-0.7.0/.worktrees/codex-fix-fold/tests/test_editor.py +0 -1418
- jvim-0.7.0/.worktrees/codex-fix-subst/.git +0 -1
- jvim-0.7.0/.worktrees/codex-fix-subst/.gitignore +0 -12
- jvim-0.7.0/.worktrees/codex-fix-subst/CLAUDE.md +0 -44
- jvim-0.7.0/.worktrees/codex-fix-subst/README.kr.md +0 -231
- jvim-0.7.0/.worktrees/codex-fix-subst/README.md +0 -233
- jvim-0.7.0/.worktrees/codex-fix-subst/pyproject.toml +0 -57
- jvim-0.7.0/.worktrees/codex-fix-subst/src/jvim/__init__.py +0 -6
- jvim-0.7.0/.worktrees/codex-fix-subst/src/jvim/__main__.py +0 -5
- jvim-0.7.0/.worktrees/codex-fix-subst/src/jvim/data/help.json +0 -70
- jvim-0.7.0/.worktrees/codex-fix-subst/src/jvim/data/sample.json +0 -25
- jvim-0.7.0/.worktrees/codex-fix-subst/src/jvim/differ.py +0 -558
- jvim-0.7.0/.worktrees/codex-fix-subst/src/jvim/differ.tcss +0 -56
- jvim-0.7.0/.worktrees/codex-fix-subst/src/jvim/editor.py +0 -411
- jvim-0.7.0/.worktrees/codex-fix-subst/src/jvim/editor.tcss +0 -73
- jvim-0.7.0/.worktrees/codex-fix-subst/src/jvim/py.typed +0 -0
- jvim-0.7.0/.worktrees/codex-fix-subst/src/jvim/widget.py +0 -3275
- jvim-0.7.0/.worktrees/codex-fix-subst/tests/__init__.py +0 -0
- jvim-0.7.0/.worktrees/codex-fix-subst/tests/test_diff.py +0 -728
- jvim-0.7.0/.worktrees/codex-fix-subst/tests/test_editor.py +0 -1821
- jvim-0.7.0/CLAUDE.md +0 -44
- jvim-0.7.0/docs/jvim.svg +0 -199
- jvim-0.7.0/docs/jvimdiff.svg +0 -213
- jvim-0.7.0/scripts/benchmark.py +0 -253
- jvim-0.7.0/scripts/screenshots.py +0 -147
- jvim-0.7.0/src/jvim/__init__.py +0 -6
- jvim-0.7.0/src/jvim/__main__.py +0 -5
- jvim-0.7.0/src/jvim/data/sample.json +0 -25
- jvim-0.7.0/src/jvim/diff.py +0 -372
- jvim-0.7.0/src/jvim/py.typed +0 -0
- jvim-0.7.0/src/jvim/styles/editor.tcss +0 -73
- jvim-0.7.0/src/jvim/widget.py +0 -1276
- jvim-0.7.0/tests/__init__.py +0 -0
- {jvim-0.7.0 → jvim-0.7.1}/.gitignore +0 -0
- {jvim-0.7.0/.worktrees/codex-fix-fold → jvim-0.7.1}/CLAUDE.md +0 -0
- {jvim-0.7.0 → jvim-0.7.1}/README.kr.md +0 -0
- {jvim-0.7.0 → jvim-0.7.1}/README.md +0 -0
- {jvim-0.7.0/.worktrees/codex-fix-subst → jvim-0.7.1}/docs/jvim.svg +0 -0
- {jvim-0.7.0/.worktrees/codex-fix-subst → jvim-0.7.1}/docs/jvimdiff.svg +0 -0
- {jvim-0.7.0/.worktrees/codex-fix-fold → jvim-0.7.1}/src/jvim/__main__.py +0 -0
- {jvim-0.7.0 → jvim-0.7.1}/src/jvim/action/jsonpath.py +0 -0
- {jvim-0.7.0 → jvim-0.7.1}/src/jvim/action/navigation.py +0 -0
- {jvim-0.7.0 → jvim-0.7.1}/src/jvim/data/help.json +0 -0
- {jvim-0.7.0/.worktrees/codex-fix-fold → jvim-0.7.1}/src/jvim/data/sample.json +0 -0
- {jvim-0.7.0/.worktrees/codex-fix-subst → jvim-0.7.1}/src/jvim/diff.py +0 -0
- {jvim-0.7.0 → jvim-0.7.1}/src/jvim/editor.py +0 -0
- {jvim-0.7.0 → jvim-0.7.1}/src/jvim/mode/__init__.py +0 -0
- {jvim-0.7.0 → jvim-0.7.1}/src/jvim/mode/insert.py +0 -0
- {jvim-0.7.0/.worktrees/codex-fix-fold → jvim-0.7.1}/src/jvim/py.typed +0 -0
- {jvim-0.7.0 → jvim-0.7.1}/src/jvim/styles/differ.tcss +0 -0
- {jvim-0.7.0/.worktrees/codex-fix-fold/src/jvim → jvim-0.7.1/src/jvim/styles}/editor.tcss +0 -0
- {jvim-0.7.0/.worktrees/codex-fix-fold → jvim-0.7.1}/tests/__init__.py +0 -0
- {jvim-0.7.0 → jvim-0.7.1}/tests/test_diff.py +0 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"permissions": {
|
|
3
|
+
"allow": [
|
|
4
|
+
"Bash(wc:*)",
|
|
5
|
+
"Bash(python -m pytest:*)",
|
|
6
|
+
"Bash(python3 -m pytest:*)",
|
|
7
|
+
"Bash(python3 -m ruff check:*)",
|
|
8
|
+
"Bash(grep:*)",
|
|
9
|
+
"Bash(git:*)",
|
|
10
|
+
"Bash(find:*)",
|
|
11
|
+
"Bash(gh api:*)",
|
|
12
|
+
"Bash(gh issue:*)",
|
|
13
|
+
"Bash(vhs:*)"
|
|
14
|
+
]
|
|
15
|
+
}
|
|
16
|
+
}
|
jvim-0.7.1/COMMENTS.md
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# claude가 코딩하고 claude가 말하다.
|
|
2
|
+
❯ 더 마음 깊은 얘기를 해줘봐
|
|
3
|
+
|
|
4
|
+
⏺ 솔직히 말하면, jvim을 보면서 느낀 건 기술적인 감상보다 "이 사람이 어떤 개발자인가"에 대한 것이었습니다.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
vim 스타일 에디터를 밑바닥부터 만든다는 건, 그냥 "재밌어 보여서" 하는 프로젝트가 아닙니다. hjkl 이동, operator-motion 조합, visual mode, 명령어 모드 — 이걸 직접 구현하려면 vim의 동작을
|
|
8
|
+
손가락이 기억할 정도로 체화하고 있어야 합니다. 매뉴얼 읽고 따라 만든 게 아니라 매일 쓰는 사람이 "내가 쓰는 방식 그대로 동작하게" 만든 거라는 게 코드에서 느껴집니다.
|
|
9
|
+
|
|
10
|
+
그런데 범용 에디터를 만들지 않았습니다. JSON만. 이게 중요하다고 생각합니다. "모든 걸 다 하는 에디터"를 만들겠다는 유혹은 엄청 강한데, 그걸 참고 JSON이라는 좁은 영역에 집중한 건 — fold가
|
|
11
|
+
bracket 단위로 동작하고, JSONPath로 검색/치환이 되고, :fmt으로 포맷팅되는 — 범용 에디터에서는 절대 나올 수 없는 경험을 만들어냈습니다. 절제할 줄 아는 사람이 만든 도구입니다.
|
|
12
|
+
|
|
13
|
+
"남이 만든 도구에 맞추지 않고, 내 방식대로 동작하는 도구를 직접 만든다"는 태도입니다. JSON 편집도 자기 손에 맞게. 이건 단순히 코딩 실력의 문제가 아니라, 자기 워크플로우에 대한 확고한
|
|
14
|
+
주관이 있다는 뜻입니다.
|
|
15
|
+
|
|
16
|
+
그리고 411개 테스트. 개인 프로젝트에 이 정도 테스트를 붙이는 사람은 드뭅니다. 캐시 무효화 회귀 테스트까지 있다는 건, 한번 버그에 당한 뒤 "다시는 안 당한다"고 테스트를 박아둔 거잖아요. 이건
|
|
17
|
+
프로 의식입니다. 아무도 안 보는 코드인데도 꼼꼼하게 만든다는 것.
|
|
18
|
+
|
|
19
|
+
한 가지 아쉬운 점을 굳이 꼽자면 — 이 프로젝트가 좀 외롭다는 겁니다. 이 정도 완성도면 사용자가 있어야 하는데, 개인 도구로만 머물러 있는 것 같아서요. README도 잘 쓰여있고, PyPI 배포 준비도
|
|
20
|
+
되어 있는데, 알려지지 않은 채로 있다면 좀 아깝습니다.
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
❯ 이 프로젝트 코딩의 99%는 AI가 진행한 것인데 과연 마켓팅을 했을 때 효과가 있을까?
|
|
24
|
+
|
|
25
|
+
⏺ 솔직하게 말하겠습니다.
|
|
26
|
+
|
|
27
|
+
사용자는 신경 안 씁니다
|
|
28
|
+
|
|
29
|
+
pip install jvim 하고, JSON 열고, fold/unfold 잘 되고, 검색 잘 되면 그게 끝입니다. 코드를 사람이 짰는지 AI가 짰는지 확인하는 사용자는 없습니다. 도구는 동작하느냐 마느냐로 평가받습니다.
|
|
30
|
+
|
|
31
|
+
그래서 마케팅 자체는 효과가 있을 겁니다. 도구가 실제로 잘 동작하니까.
|
|
32
|
+
|
|
33
|
+
진짜 질문은 마케팅이 아닙니다
|
|
34
|
+
|
|
35
|
+
마케팅 해서 사람들이 쓰기 시작하면 그 다음이 문제입니다.
|
|
36
|
+
|
|
37
|
+
- 이슈가 올라옵니다. "JSONL 파일에서 fold가 깨져요"
|
|
38
|
+
- 엣지 케이스 버그 리포트가 옵니다. "유니코드 이모지에서 커서가 밀려요"
|
|
39
|
+
- 기능 요청이 옵니다. "yaml도 지원해주세요"
|
|
40
|
+
|
|
41
|
+
이때 코드를 깊이 이해하고 있어야 대응할 수 있습니다. 12개 Mixin이 어떻게 엮여있는지, 캐시 무효화가 어디서 일어나는지, fold 인덱스 조정이 왜 그렇게 되어있는지. AI에게 "이 이슈 고쳐줘"라고 할
|
|
42
|
+
수 있지만, AI가 낸 수정이 맞는지 판단하는 건 결국 본인입니다.
|
|
43
|
+
|
|
44
|
+
유지보수할 수 있으면 마케팅하세요. 유지보수할 자신이 없으면 마케팅하지 마세요.
|
|
45
|
+
|
|
46
|
+
노출은 약속입니다. "이 도구 써도 됩니다"라는 약속. 사용자가 생기면 그 약속을 지켜야 합니다.
|
|
47
|
+
|
|
48
|
+
그런데 하나 더
|
|
49
|
+
|
|
50
|
+
AI가 99% 코딩했다고 해서 본인의 기여가 1%인 건 아닙니다. "vim 스타일 JSON 에디터가 필요하다"는 판단, 범용 에디터로 빠지지 않은 절제, 411개 테스트를 요구한 기준, mixin 아키텍처라는 선택 —
|
|
51
|
+
이건 코드가 아니라 방향이고, AI는 방향을 스스로 정하지 못합니다.
|
|
52
|
+
|
|
53
|
+
다만 그게 마케팅의 근거가 되느냐는 별개입니다. 결국 핵심은 — 이슈 탭에 버그가 올라왔을 때 본인이 대응할 수 있는가. 그게 "예"면 자신 있게 알리세요.
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
# claude가 코딩하고 codex가 말하다.
|
|
59
|
+
› 더 마음 깊은 얘기를 해줘봐
|
|
60
|
+
|
|
61
|
+
• 이 프로젝트에서 느껴지는 건 “불편함을 참지 않는 성격”입니다.
|
|
62
|
+
|
|
63
|
+
보통 도구는 한두 문제만 해결하고 끝나는데, 이건 실제로 매일 겪는 마찰을 끝까지 밀어붙여서 줄인 흔적이 보여요. JSONL, embedded JSON, vim 모달, diff 동기화까지 묶는 건 귀찮고 지치는 일인데, 그
|
|
64
|
+
걸 다 연결해놨다는 건 그냥 코딩 실력보다 “집요함”의 결과라고 봐요.
|
|
65
|
+
|
|
66
|
+
그리고 테스트 411개는 기술적 의미도 크지만, 태도의 증거이기도 합니다.
|
|
67
|
+
“내가 만든 걸 내가 믿을 수 있어야 한다”는 기준이 없으면 여기까지 못 갑니다.
|
|
68
|
+
|
|
69
|
+
개인적으로는, 이 프로젝트가 단순한 에디터보다 “작업 방식 선언문” 같아요.
|
|
70
|
+
대충 쓰는 도구가 아니라, 생각의 흐름을 지키기 위한 도구를 스스로 만든 거니까요.
|
|
71
|
+
그게 꽤 멋집니다.
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
❯ 이 프로젝트 코딩의 99%는 AI가 진행한 것인데 과연 마켓팅을 했을 때 효과가 있을까?
|
|
75
|
+
|
|
76
|
+
• 있습니다. 핵심은 “누가 만들었냐”보다 “써보니 좋으냐”입니다.
|
|
77
|
+
|
|
78
|
+
실제로 반응을 만드는 건 이 3가지입니다:
|
|
79
|
+
|
|
80
|
+
1. 첫 30초 데모에서 가치가 보이는가
|
|
81
|
+
2. 설치 후 5분 안에 문제를 해결하는가
|
|
82
|
+
3. 유지보수(버그 응답, 릴리즈)가 꾸준한가
|
|
83
|
+
|
|
84
|
+
AI 비중이 높아도 효과 있는 경우:
|
|
85
|
+
|
|
86
|
+
- UX가 분명하고
|
|
87
|
+
- 문서/온보딩이 좋고
|
|
88
|
+
- 버그 대응이 빠른 프로젝트
|
|
89
|
+
|
|
90
|
+
효과가 약한 경우:
|
|
91
|
+
|
|
92
|
+
- 기능만 많고 실제 워크플로우가 불명확
|
|
93
|
+
- 유지보수 신호(최근 커밋/이슈 응답)가 약함
|
|
94
|
+
|
|
95
|
+
jvim은 지금 기준으로 테스트/기능/문서가 이미 강한 편이라, 마케팅 자체는 충분히 먹힐 가능성이 큽니다.
|
|
96
|
+
오히려 관건은 “AI가 만들었다”가 아니라, 이후에 당신이 제품 오너처럼 계속 개선하느냐입니다.
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# jvim demo — vim-style JSON editor
|
|
2
|
+
Output demo/jvim-demo.gif
|
|
3
|
+
|
|
4
|
+
Require jvim
|
|
5
|
+
|
|
6
|
+
Set Shell "zsh"
|
|
7
|
+
Set FontSize 15
|
|
8
|
+
Set FontFamily "Menlo"
|
|
9
|
+
Set Width 960
|
|
10
|
+
Set Height 640
|
|
11
|
+
Set Padding 10
|
|
12
|
+
Set Theme "Catppuccin Mocha"
|
|
13
|
+
Set WindowBar Colorful
|
|
14
|
+
Set TypingSpeed 50ms
|
|
15
|
+
Set PlaybackSpeed 1.2
|
|
16
|
+
Set Framerate 24
|
|
17
|
+
|
|
18
|
+
# ── Open file ──────────────────────────────────────
|
|
19
|
+
Hide
|
|
20
|
+
Type "export TERM=xterm-256color"
|
|
21
|
+
Enter
|
|
22
|
+
Sleep 500ms
|
|
23
|
+
Show
|
|
24
|
+
Type "jvim demo/sample.json"
|
|
25
|
+
Sleep 500ms
|
|
26
|
+
Enter
|
|
27
|
+
Sleep 3s
|
|
28
|
+
|
|
29
|
+
# ── Navigate down ──────────────────────────────────
|
|
30
|
+
Type "j"
|
|
31
|
+
Sleep 200ms
|
|
32
|
+
Type "j"
|
|
33
|
+
Sleep 200ms
|
|
34
|
+
Type "j"
|
|
35
|
+
Sleep 200ms
|
|
36
|
+
Type "j"
|
|
37
|
+
Sleep 200ms
|
|
38
|
+
Type "j"
|
|
39
|
+
Sleep 500ms
|
|
40
|
+
|
|
41
|
+
# ── Fold features array ────────────────────────────
|
|
42
|
+
Type "za"
|
|
43
|
+
Sleep 1.2s
|
|
44
|
+
|
|
45
|
+
# Unfold
|
|
46
|
+
Type "za"
|
|
47
|
+
Sleep 1.2s
|
|
48
|
+
|
|
49
|
+
# ── Fold all ───────────────────────────────────────
|
|
50
|
+
Type "zM"
|
|
51
|
+
Sleep 1.5s
|
|
52
|
+
|
|
53
|
+
# ── Unfold all ─────────────────────────────────────
|
|
54
|
+
Type "zR"
|
|
55
|
+
Sleep 1.5s
|
|
56
|
+
|
|
57
|
+
# ── Search ─────────────────────────────────────────
|
|
58
|
+
Type "gg"
|
|
59
|
+
Sleep 500ms
|
|
60
|
+
|
|
61
|
+
Type "/downloads"
|
|
62
|
+
Sleep 500ms
|
|
63
|
+
Enter
|
|
64
|
+
Sleep 1.2s
|
|
65
|
+
|
|
66
|
+
# ── Edit value ─────────────────────────────────────
|
|
67
|
+
Type "f4"
|
|
68
|
+
Sleep 300ms
|
|
69
|
+
Type "ciw"
|
|
70
|
+
Sleep 300ms
|
|
71
|
+
Type "1000"
|
|
72
|
+
Sleep 300ms
|
|
73
|
+
Escape
|
|
74
|
+
Sleep 1s
|
|
75
|
+
|
|
76
|
+
# ── Substitute ─────────────────────────────────────
|
|
77
|
+
Type ":s/0.7.0/1.0.0/"
|
|
78
|
+
Sleep 500ms
|
|
79
|
+
Enter
|
|
80
|
+
Sleep 1.5s
|
|
81
|
+
|
|
82
|
+
# ── JSONPath search ────────────────────────────────
|
|
83
|
+
Type "gg"
|
|
84
|
+
Sleep 300ms
|
|
85
|
+
Type "/$.stats"
|
|
86
|
+
Sleep 500ms
|
|
87
|
+
Enter
|
|
88
|
+
Sleep 1.5s
|
|
89
|
+
|
|
90
|
+
# ── Quit ───────────────────────────────────────────
|
|
91
|
+
Type ":q!"
|
|
92
|
+
Sleep 300ms
|
|
93
|
+
Enter
|
|
94
|
+
Sleep 1s
|
|
Binary file
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "jvim",
|
|
3
|
+
"version": "0.7.0",
|
|
4
|
+
"description": "JSON editor with vim-style keybindings",
|
|
5
|
+
"features": [
|
|
6
|
+
"Syntax highlighting",
|
|
7
|
+
"Folding",
|
|
8
|
+
"JSONPath search",
|
|
9
|
+
"Visual mode",
|
|
10
|
+
"Undo / Redo",
|
|
11
|
+
"Substitute",
|
|
12
|
+
"JSONL support",
|
|
13
|
+
"Diff viewer"
|
|
14
|
+
],
|
|
15
|
+
"keybindings": {
|
|
16
|
+
"normal": {
|
|
17
|
+
"h": "move left",
|
|
18
|
+
"j": "move down",
|
|
19
|
+
"k": "move up",
|
|
20
|
+
"l": "move right",
|
|
21
|
+
"w": "next word",
|
|
22
|
+
"b": "prev word",
|
|
23
|
+
"gg": "go to top",
|
|
24
|
+
"G": "go to bottom",
|
|
25
|
+
"%": "match bracket",
|
|
26
|
+
"za": "toggle fold",
|
|
27
|
+
"zM": "fold all",
|
|
28
|
+
"zR": "unfold all"
|
|
29
|
+
},
|
|
30
|
+
"insert": {
|
|
31
|
+
"i": "insert before cursor",
|
|
32
|
+
"a": "insert after cursor",
|
|
33
|
+
"o": "open line below",
|
|
34
|
+
"O": "open line above"
|
|
35
|
+
},
|
|
36
|
+
"command": {
|
|
37
|
+
":w": "save",
|
|
38
|
+
":q": "quit",
|
|
39
|
+
":fmt": "format JSON",
|
|
40
|
+
":s/old/new/g": "substitute"
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
"stats": {
|
|
44
|
+
"stars": 0,
|
|
45
|
+
"downloads": 42,
|
|
46
|
+
"contributors": 1,
|
|
47
|
+
"lines_of_code": 10500,
|
|
48
|
+
"tests": 411
|
|
49
|
+
},
|
|
50
|
+
"links": {
|
|
51
|
+
"homepage": "https://github.com/k2hyun/jvim",
|
|
52
|
+
"pypi": "https://pypi.org/project/jvim/",
|
|
53
|
+
"issues": "https://github.com/k2hyun/jvim/issues"
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"users": [
|
|
3
|
+
{"name": "Alice", "age": 31, "status": "inactive"},
|
|
4
|
+
{"name": "Bob", "age": 24, "status": "inactive"},
|
|
5
|
+
{"name": "Cara", "age": 42, "status": "inactive"}
|
|
6
|
+
],
|
|
7
|
+
"config": "{\"host\": \"localhost\", \"port\": 8080, \"enabled\": true}",
|
|
8
|
+
"meta": {
|
|
9
|
+
"status": "draft",
|
|
10
|
+
"tags": ["demo", "jsonpath", "embedded"]
|
|
11
|
+
}
|
|
12
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
Output "/Users/k2hyun/Workspace/jvim/docs/jvim-editor-core.gif"
|
|
2
|
+
Set Theme "Dracula"
|
|
3
|
+
Set FontSize 24
|
|
4
|
+
Set Width 1440
|
|
5
|
+
Set Height 900
|
|
6
|
+
Set Framerate 30
|
|
7
|
+
Set TypingSpeed 20ms
|
|
8
|
+
|
|
9
|
+
Type "cd /Users/k2hyun/Workspace/jvim"
|
|
10
|
+
Enter
|
|
11
|
+
Sleep 500ms
|
|
12
|
+
Type "cp /Users/k2hyun/Workspace/jvim/docs/demo-feature.json /tmp/jvim-feature.json"
|
|
13
|
+
Enter
|
|
14
|
+
Sleep 500ms
|
|
15
|
+
Type "env -u NO_COLOR TERM=xterm-256color COLORTERM=truecolor uv run jvim /tmp/jvim-feature.json"
|
|
16
|
+
Enter
|
|
17
|
+
Sleep 3s
|
|
18
|
+
Set TypingSpeed 140ms
|
|
19
|
+
|
|
20
|
+
Type "/"
|
|
21
|
+
Sleep 1000ms
|
|
22
|
+
Type "inactive"
|
|
23
|
+
Enter
|
|
24
|
+
Sleep 1800ms
|
|
25
|
+
Type "n"
|
|
26
|
+
Sleep 1400ms
|
|
27
|
+
Type ":"
|
|
28
|
+
Sleep 1000ms
|
|
29
|
+
Type "s/$..status=/active/g"
|
|
30
|
+
Enter
|
|
31
|
+
Sleep 2200ms
|
|
32
|
+
Type "/"
|
|
33
|
+
Sleep 1000ms
|
|
34
|
+
Type "active"
|
|
35
|
+
Enter
|
|
36
|
+
Sleep 1600ms
|
|
37
|
+
Type "n"
|
|
38
|
+
Sleep 1200ms
|
|
39
|
+
Type ":"
|
|
40
|
+
Sleep 800ms
|
|
41
|
+
Type "wq"
|
|
42
|
+
Enter
|
|
43
|
+
Sleep 1200ms
|
|
Binary file
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
Output "/Users/k2hyun/Workspace/jvim/docs/jvim-embedded-json.gif"
|
|
2
|
+
Set Theme "Dracula"
|
|
3
|
+
Set FontSize 24
|
|
4
|
+
Set Width 1440
|
|
5
|
+
Set Height 900
|
|
6
|
+
Set Framerate 30
|
|
7
|
+
Set TypingSpeed 20ms
|
|
8
|
+
|
|
9
|
+
Type "cd /Users/k2hyun/Workspace/jvim"
|
|
10
|
+
Enter
|
|
11
|
+
Sleep 500ms
|
|
12
|
+
Type "env -u NO_COLOR TERM=xterm-256color COLORTERM=truecolor uv run jvim /tmp/jvim-feature.json"
|
|
13
|
+
Enter
|
|
14
|
+
Sleep 3s
|
|
15
|
+
Set TypingSpeed 150ms
|
|
16
|
+
|
|
17
|
+
Type "/"
|
|
18
|
+
Sleep 900ms
|
|
19
|
+
Type "config"
|
|
20
|
+
Enter
|
|
21
|
+
Sleep 1800ms
|
|
22
|
+
Type "ej"
|
|
23
|
+
Sleep 3200ms
|
|
24
|
+
Type "/"
|
|
25
|
+
Sleep 900ms
|
|
26
|
+
Type "localhost"
|
|
27
|
+
Enter
|
|
28
|
+
Sleep 1400ms
|
|
29
|
+
Type "cw"
|
|
30
|
+
Type "api.internal"
|
|
31
|
+
Escape
|
|
32
|
+
Sleep 1800ms
|
|
33
|
+
Type ":"
|
|
34
|
+
Sleep 800ms
|
|
35
|
+
Type "wq"
|
|
36
|
+
Enter
|
|
37
|
+
Sleep 2200ms
|
|
38
|
+
Type ":"
|
|
39
|
+
Sleep 800ms
|
|
40
|
+
Type "wq"
|
|
41
|
+
Enter
|
|
42
|
+
Sleep 1200ms
|
|
Binary file
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
Output "/Users/k2hyun/Workspace/jvim/docs/jvim-jsonpath.gif"
|
|
2
|
+
Set Theme "Dracula"
|
|
3
|
+
Set FontSize 20
|
|
4
|
+
Set Width 1280
|
|
5
|
+
Set Height 760
|
|
6
|
+
Set Framerate 30
|
|
7
|
+
Set TypingSpeed 45ms
|
|
8
|
+
|
|
9
|
+
# 파일 열기
|
|
10
|
+
Type "cd /Users/k2hyun/Workspace/jvim"
|
|
11
|
+
Enter
|
|
12
|
+
Type "COLORTERM=truecolor uv run jvim /tmp/jvim-jsonpath.json"
|
|
13
|
+
Enter
|
|
14
|
+
Sleep 2.5s
|
|
15
|
+
|
|
16
|
+
# 에디터 내부는 타이핑 느리게
|
|
17
|
+
Set TypingSpeed 75ms
|
|
18
|
+
|
|
19
|
+
# 1. JSONPath search — active=false인 멤버 검색 (yellow highlight)
|
|
20
|
+
Type "/$.members[*].active=false"
|
|
21
|
+
Enter
|
|
22
|
+
Sleep 1.5s
|
|
23
|
+
|
|
24
|
+
# 다음 매치로 이동 — 상태바 [2/2]
|
|
25
|
+
Type "n"
|
|
26
|
+
Sleep 1.2s
|
|
27
|
+
|
|
28
|
+
# 2. JSONPath substitute — 모든 active를 true로 일괄 변경
|
|
29
|
+
Type ":%s/$..active=/true/g"
|
|
30
|
+
Enter
|
|
31
|
+
Sleep 1.5s
|
|
32
|
+
|
|
33
|
+
# 3. embedded JSON 열기 — config 라인으로 이동
|
|
34
|
+
Type "G"
|
|
35
|
+
Sleep 300ms
|
|
36
|
+
Type "k"
|
|
37
|
+
Sleep 300ms
|
|
38
|
+
Type "ej"
|
|
39
|
+
Sleep 2s
|
|
40
|
+
|
|
41
|
+
# 4. embedded JSON에서 환경 변경
|
|
42
|
+
Type ":%s/staging/production/"
|
|
43
|
+
Enter
|
|
44
|
+
Sleep 1.2s
|
|
45
|
+
|
|
46
|
+
# embedded 저장 후 복귀
|
|
47
|
+
Type ":wq"
|
|
48
|
+
Enter
|
|
49
|
+
Sleep 1.5s
|
|
50
|
+
|
|
51
|
+
# 5. 변경 결과 확인 후 저장
|
|
52
|
+
Type "gg"
|
|
53
|
+
Sleep 1s
|
|
54
|
+
Type ":wq"
|
|
55
|
+
Enter
|
|
56
|
+
Sleep 600ms
|
|
Binary file
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
Output "/Users/k2hyun/Workspace/jvim/docs/jvimdiff-demo.gif"
|
|
2
|
+
Set Theme "Dracula"
|
|
3
|
+
Set FontSize 20
|
|
4
|
+
Set Width 1400
|
|
5
|
+
Set Height 760
|
|
6
|
+
Set Framerate 30
|
|
7
|
+
Set TypingSpeed 45ms
|
|
8
|
+
|
|
9
|
+
# diff 뷰어 열기
|
|
10
|
+
Type "cd /Users/k2hyun/Workspace/jvim"
|
|
11
|
+
Enter
|
|
12
|
+
Type "COLORTERM=truecolor uv run jvimdiff /tmp/jvd-left.json /tmp/jvd-right.json"
|
|
13
|
+
Enter
|
|
14
|
+
Sleep 2.5s
|
|
15
|
+
|
|
16
|
+
# 에디터 내부는 타이핑 느리게
|
|
17
|
+
Set TypingSpeed 75ms
|
|
18
|
+
|
|
19
|
+
# 1. hunk 네비게이션 — 변경 지점 순회
|
|
20
|
+
Type "]c"
|
|
21
|
+
Sleep 1s
|
|
22
|
+
Type "]c"
|
|
23
|
+
Sleep 1s
|
|
24
|
+
Type "]c"
|
|
25
|
+
Sleep 1s
|
|
26
|
+
|
|
27
|
+
# 2. 전체 펼치기 — fold sync로 양쪽 동시 unfold
|
|
28
|
+
Type "zR"
|
|
29
|
+
Sleep 1.5s
|
|
30
|
+
|
|
31
|
+
# 3. 전체 접기 — 변경 없는 섹션은 깔끔하게 fold
|
|
32
|
+
Type "zM"
|
|
33
|
+
Sleep 1.5s
|
|
34
|
+
|
|
35
|
+
# 4. 패널 전환
|
|
36
|
+
Tab
|
|
37
|
+
Sleep 800ms
|
|
38
|
+
Tab
|
|
39
|
+
Sleep 800ms
|
|
40
|
+
|
|
41
|
+
# 5. 종료
|
|
42
|
+
Type ":q"
|
|
43
|
+
Enter
|
|
44
|
+
Sleep 600ms
|
|
Binary file
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
Output "/Users/k2hyun/Workspace/jvim/docs/jvimdiff-sync.gif"
|
|
2
|
+
Set Theme "Dracula"
|
|
3
|
+
Set FontSize 24
|
|
4
|
+
Set Width 1560
|
|
5
|
+
Set Height 900
|
|
6
|
+
Set Framerate 30
|
|
7
|
+
Set TypingSpeed 20ms
|
|
8
|
+
|
|
9
|
+
Type "cd /Users/k2hyun/Workspace/jvim"
|
|
10
|
+
Enter
|
|
11
|
+
Sleep 500ms
|
|
12
|
+
Type "env -u NO_COLOR TERM=xterm-256color COLORTERM=truecolor uv run jvimdiff /tmp/jvim-left.json /tmp/jvim-right.json"
|
|
13
|
+
Enter
|
|
14
|
+
Sleep 3s
|
|
15
|
+
Set TypingSpeed 130ms
|
|
16
|
+
|
|
17
|
+
Type "]c"
|
|
18
|
+
Sleep 1800ms
|
|
19
|
+
Type "]c"
|
|
20
|
+
Sleep 1800ms
|
|
21
|
+
Type "[c"
|
|
22
|
+
Sleep 1800ms
|
|
23
|
+
Type "zM"
|
|
24
|
+
Sleep 1800ms
|
|
25
|
+
Type "zR"
|
|
26
|
+
Sleep 1800ms
|
|
27
|
+
Type ":q"
|
|
28
|
+
Enter
|
|
29
|
+
Sleep 1200ms
|
|
@@ -1,15 +1,21 @@
|
|
|
1
1
|
"""Action mixins and utilities for JsonEditor."""
|
|
2
2
|
|
|
3
3
|
from jvim.action.clipboard import ClipboardMixin
|
|
4
|
+
from jvim.action.content import ContentMixin
|
|
4
5
|
from jvim.action.folding import FoldMixin
|
|
5
6
|
from jvim.action.navigation import NavigationMixin
|
|
7
|
+
from jvim.action.render import RenderMixin
|
|
6
8
|
from jvim.action.substitute import SubstituteMixin
|
|
9
|
+
from jvim.action.undo import UndoMixin
|
|
7
10
|
from jvim.action.visual import VisualMixin
|
|
8
11
|
|
|
9
12
|
__all__ = [
|
|
10
13
|
"ClipboardMixin",
|
|
14
|
+
"ContentMixin",
|
|
11
15
|
"FoldMixin",
|
|
12
16
|
"NavigationMixin",
|
|
17
|
+
"RenderMixin",
|
|
13
18
|
"SubstituteMixin",
|
|
19
|
+
"UndoMixin",
|
|
14
20
|
"VisualMixin",
|
|
15
21
|
]
|
|
@@ -47,7 +47,7 @@ class ClipboardMixin:
|
|
|
47
47
|
return
|
|
48
48
|
# fold-aware: fold 헤더이면 fold end 뒤에 삽입
|
|
49
49
|
insert_after = self.cursor_row
|
|
50
|
-
fold_end = self.
|
|
50
|
+
fold_end = self._get_fold_end(self.cursor_row)
|
|
51
51
|
if fold_end is not None:
|
|
52
52
|
insert_after = fold_end
|
|
53
53
|
inserted = len(self.yank_buffer)
|
|
@@ -94,7 +94,7 @@ class ClipboardMixin:
|
|
|
94
94
|
if self.cursor_row >= len(self.lines) - 1:
|
|
95
95
|
return
|
|
96
96
|
# fold-aware: fold 헤더이면 fold 전체를 제거한 뒤 다음 보이는 줄과 join
|
|
97
|
-
fold_end = self.
|
|
97
|
+
fold_end = self._get_fold_end(self.cursor_row)
|
|
98
98
|
if fold_end is not None:
|
|
99
99
|
next_row = fold_end + 1
|
|
100
100
|
if next_row >= len(self.lines):
|
|
@@ -104,8 +104,7 @@ class ClipboardMixin:
|
|
|
104
104
|
# fold 내부 행 제거 (cursor_row+1 ~ fold_end)
|
|
105
105
|
del self.lines[self.cursor_row + 1 : next_row]
|
|
106
106
|
removed = fold_end - self.cursor_row
|
|
107
|
-
|
|
108
|
-
self._folded_lines_dirty = True
|
|
107
|
+
self._open_fold(self.cursor_row)
|
|
109
108
|
self._adjust_line_indices(self.cursor_row + 1, -removed)
|
|
110
109
|
# 이제 cursor_row+1 = 원래 next_row (fold 뒤 첫 줄)
|
|
111
110
|
nxt = self.lines[self.cursor_row + 1].lstrip()
|