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.
Files changed (105) hide show
  1. jvim-0.7.1/.claude/settings.local.json +16 -0
  2. jvim-0.7.1/CLAUDE.local.md +3 -0
  3. jvim-0.7.1/COMMENTS.md +96 -0
  4. {jvim-0.7.0 → jvim-0.7.1}/PKG-INFO +1 -1
  5. jvim-0.7.1/demo/demo.tape +94 -0
  6. jvim-0.7.1/demo/jvim-demo.gif +0 -0
  7. jvim-0.7.1/demo/sample.json +55 -0
  8. jvim-0.7.1/docs/demo-feature.json +12 -0
  9. jvim-0.7.1/docs/jvim-editor-core.gif +0 -0
  10. jvim-0.7.1/docs/jvim-editor-core.tape +43 -0
  11. jvim-0.7.1/docs/jvim-embedded-json.gif +0 -0
  12. jvim-0.7.1/docs/jvim-embedded-json.tape +42 -0
  13. jvim-0.7.1/docs/jvim-jsonpath.gif +0 -0
  14. jvim-0.7.1/docs/jvim-jsonpath.tape +56 -0
  15. jvim-0.7.1/docs/jvimdiff-demo.gif +0 -0
  16. jvim-0.7.1/docs/jvimdiff-demo.tape +44 -0
  17. jvim-0.7.1/docs/jvimdiff-sync.gif +0 -0
  18. jvim-0.7.1/docs/jvimdiff-sync.tape +29 -0
  19. {jvim-0.7.0 → jvim-0.7.1}/pyproject.toml +1 -1
  20. {jvim-0.7.0/.worktrees/codex-fix-fold → jvim-0.7.1}/src/jvim/__init__.py +1 -1
  21. {jvim-0.7.0 → jvim-0.7.1}/src/jvim/action/__init__.py +6 -0
  22. {jvim-0.7.0 → jvim-0.7.1}/src/jvim/action/clipboard.py +3 -4
  23. jvim-0.7.1/src/jvim/action/content.py +238 -0
  24. {jvim-0.7.0 → jvim-0.7.1}/src/jvim/action/folding.py +17 -0
  25. jvim-0.7.1/src/jvim/action/jsonpath_locator.py +214 -0
  26. jvim-0.7.1/src/jvim/action/render.py +735 -0
  27. {jvim-0.7.0 → jvim-0.7.1}/src/jvim/action/substitute.py +45 -23
  28. jvim-0.7.1/src/jvim/action/undo.py +72 -0
  29. {jvim-0.7.0 → jvim-0.7.1}/src/jvim/action/visual.py +1 -5
  30. {jvim-0.7.0 → jvim-0.7.1}/src/jvim/differ.py +23 -13
  31. {jvim-0.7.0 → jvim-0.7.1}/src/jvim/mode/command.py +129 -86
  32. {jvim-0.7.0 → jvim-0.7.1}/src/jvim/mode/normal.py +181 -139
  33. {jvim-0.7.0 → jvim-0.7.1}/src/jvim/mode/search.py +15 -204
  34. jvim-0.7.1/src/jvim/widget.py +366 -0
  35. jvim-0.7.1/tasks/lessons.md +20 -0
  36. {jvim-0.7.0 → jvim-0.7.1}/tests/test_editor.py +31 -0
  37. jvim-0.7.1/tests/test_jsonpath_locator.py +52 -0
  38. {jvim-0.7.0 → jvim-0.7.1}/uv.lock +1 -1
  39. jvim-0.7.0/.claude/CLAUDE.md +0 -7
  40. jvim-0.7.0/.claude/settings.local.json +0 -40
  41. jvim-0.7.0/.worktrees/codex-fix-fold/.git +0 -1
  42. jvim-0.7.0/.worktrees/codex-fix-fold/.gitignore +0 -12
  43. jvim-0.7.0/.worktrees/codex-fix-fold/README.kr.md +0 -165
  44. jvim-0.7.0/.worktrees/codex-fix-fold/README.md +0 -167
  45. jvim-0.7.0/.worktrees/codex-fix-fold/pyproject.toml +0 -57
  46. jvim-0.7.0/.worktrees/codex-fix-fold/src/jvim/data/help.json +0 -64
  47. jvim-0.7.0/.worktrees/codex-fix-fold/src/jvim/diff.py +0 -346
  48. jvim-0.7.0/.worktrees/codex-fix-fold/src/jvim/differ.py +0 -538
  49. jvim-0.7.0/.worktrees/codex-fix-fold/src/jvim/differ.tcss +0 -56
  50. jvim-0.7.0/.worktrees/codex-fix-fold/src/jvim/editor.py +0 -411
  51. jvim-0.7.0/.worktrees/codex-fix-fold/src/jvim/widget.py +0 -2843
  52. jvim-0.7.0/.worktrees/codex-fix-fold/tests/test_diff.py +0 -633
  53. jvim-0.7.0/.worktrees/codex-fix-fold/tests/test_editor.py +0 -1418
  54. jvim-0.7.0/.worktrees/codex-fix-subst/.git +0 -1
  55. jvim-0.7.0/.worktrees/codex-fix-subst/.gitignore +0 -12
  56. jvim-0.7.0/.worktrees/codex-fix-subst/CLAUDE.md +0 -44
  57. jvim-0.7.0/.worktrees/codex-fix-subst/README.kr.md +0 -231
  58. jvim-0.7.0/.worktrees/codex-fix-subst/README.md +0 -233
  59. jvim-0.7.0/.worktrees/codex-fix-subst/pyproject.toml +0 -57
  60. jvim-0.7.0/.worktrees/codex-fix-subst/src/jvim/__init__.py +0 -6
  61. jvim-0.7.0/.worktrees/codex-fix-subst/src/jvim/__main__.py +0 -5
  62. jvim-0.7.0/.worktrees/codex-fix-subst/src/jvim/data/help.json +0 -70
  63. jvim-0.7.0/.worktrees/codex-fix-subst/src/jvim/data/sample.json +0 -25
  64. jvim-0.7.0/.worktrees/codex-fix-subst/src/jvim/differ.py +0 -558
  65. jvim-0.7.0/.worktrees/codex-fix-subst/src/jvim/differ.tcss +0 -56
  66. jvim-0.7.0/.worktrees/codex-fix-subst/src/jvim/editor.py +0 -411
  67. jvim-0.7.0/.worktrees/codex-fix-subst/src/jvim/editor.tcss +0 -73
  68. jvim-0.7.0/.worktrees/codex-fix-subst/src/jvim/py.typed +0 -0
  69. jvim-0.7.0/.worktrees/codex-fix-subst/src/jvim/widget.py +0 -3275
  70. jvim-0.7.0/.worktrees/codex-fix-subst/tests/__init__.py +0 -0
  71. jvim-0.7.0/.worktrees/codex-fix-subst/tests/test_diff.py +0 -728
  72. jvim-0.7.0/.worktrees/codex-fix-subst/tests/test_editor.py +0 -1821
  73. jvim-0.7.0/CLAUDE.md +0 -44
  74. jvim-0.7.0/docs/jvim.svg +0 -199
  75. jvim-0.7.0/docs/jvimdiff.svg +0 -213
  76. jvim-0.7.0/scripts/benchmark.py +0 -253
  77. jvim-0.7.0/scripts/screenshots.py +0 -147
  78. jvim-0.7.0/src/jvim/__init__.py +0 -6
  79. jvim-0.7.0/src/jvim/__main__.py +0 -5
  80. jvim-0.7.0/src/jvim/data/sample.json +0 -25
  81. jvim-0.7.0/src/jvim/diff.py +0 -372
  82. jvim-0.7.0/src/jvim/py.typed +0 -0
  83. jvim-0.7.0/src/jvim/styles/editor.tcss +0 -73
  84. jvim-0.7.0/src/jvim/widget.py +0 -1276
  85. jvim-0.7.0/tests/__init__.py +0 -0
  86. {jvim-0.7.0 → jvim-0.7.1}/.gitignore +0 -0
  87. {jvim-0.7.0/.worktrees/codex-fix-fold → jvim-0.7.1}/CLAUDE.md +0 -0
  88. {jvim-0.7.0 → jvim-0.7.1}/README.kr.md +0 -0
  89. {jvim-0.7.0 → jvim-0.7.1}/README.md +0 -0
  90. {jvim-0.7.0/.worktrees/codex-fix-subst → jvim-0.7.1}/docs/jvim.svg +0 -0
  91. {jvim-0.7.0/.worktrees/codex-fix-subst → jvim-0.7.1}/docs/jvimdiff.svg +0 -0
  92. {jvim-0.7.0/.worktrees/codex-fix-fold → jvim-0.7.1}/src/jvim/__main__.py +0 -0
  93. {jvim-0.7.0 → jvim-0.7.1}/src/jvim/action/jsonpath.py +0 -0
  94. {jvim-0.7.0 → jvim-0.7.1}/src/jvim/action/navigation.py +0 -0
  95. {jvim-0.7.0 → jvim-0.7.1}/src/jvim/data/help.json +0 -0
  96. {jvim-0.7.0/.worktrees/codex-fix-fold → jvim-0.7.1}/src/jvim/data/sample.json +0 -0
  97. {jvim-0.7.0/.worktrees/codex-fix-subst → jvim-0.7.1}/src/jvim/diff.py +0 -0
  98. {jvim-0.7.0 → jvim-0.7.1}/src/jvim/editor.py +0 -0
  99. {jvim-0.7.0 → jvim-0.7.1}/src/jvim/mode/__init__.py +0 -0
  100. {jvim-0.7.0 → jvim-0.7.1}/src/jvim/mode/insert.py +0 -0
  101. {jvim-0.7.0/.worktrees/codex-fix-fold → jvim-0.7.1}/src/jvim/py.typed +0 -0
  102. {jvim-0.7.0 → jvim-0.7.1}/src/jvim/styles/differ.tcss +0 -0
  103. {jvim-0.7.0/.worktrees/codex-fix-fold/src/jvim → jvim-0.7.1/src/jvim/styles}/editor.tcss +0 -0
  104. {jvim-0.7.0/.worktrees/codex-fix-fold → jvim-0.7.1}/tests/__init__.py +0 -0
  105. {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
+ }
@@ -0,0 +1,3 @@
1
+ # Auto-generated by ~/Workspace/dotfiles/claude/setup.sh
2
+ # 직접 수정하지 마세요. 원본은 dotfiles 리포에서 관리합니다.
3
+ @/Users/k2hyun/Workspace/dotfiles/claude/projects/jvim.md
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가 만들었다”가 아니라, 이후에 당신이 제품 오너처럼 계속 개선하느냐입니다.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: jvim
3
- Version: 0.7.0
3
+ Version: 0.7.1
4
4
  Summary: JSON editor with vim-style keybindings
5
5
  Project-URL: Homepage, https://github.com/k2hyun/jvim
6
6
  Project-URL: Repository, https://github.com/k2hyun/jvim
@@ -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
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "jvim"
7
- version = "0.7.0"
7
+ version = "0.7.1"
8
8
  description = "JSON editor with vim-style keybindings"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -3,4 +3,4 @@
3
3
  from .widget import EditorMode, JsonEditor
4
4
 
5
5
  __all__ = ["EditorMode", "JsonEditor"]
6
- __version__ = "0.3.1"
6
+ __version__ = "0.7.1"
@@ -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._folds.get(self.cursor_row)
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._folds.get(self.cursor_row)
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
- del self._folds[self.cursor_row]
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()