Skip to main content

JSON editor with vim-style keybindings

Project description

jvim

JSON editor with vim-style keybindings, built with Textual.

한국어

Screenshots

Editor

jvim

Diff Viewer

jvimdiff

Features

  • Vim-style modal editing - Normal, Insert, Command, and Search modes
  • Syntax highlighting - JSON-aware colorization
  • JSON validation - Real-time validation with error reporting
  • JSONPath search - Search using JSONPath expressions ($.foo.bar)
  • JSONL support - Edit JSON Lines files with smart formatting
  • Embedded JSON editing - Edit JSON strings within JSON with nested level support
  • Visual mode - Character-wise (v) and line-wise (V) selection with d/y/c operators
  • Count prefix - Vim-style numeric prefixes (5j, 3dd, d3d) with fold-aware line operations
  • Folding - Collapse/expand JSON blocks and long string values
  • Bracket matching - Jump to matching brackets with %
  • Undo/Redo - Full undo history
  • Substitute - Vim-style :s/old/new/g with regex, range, and flags support
  • Multi-file navigation - Open multiple files and switch with :n, :N, :e#
  • Diff viewer - Side-by-side JSON comparison with scroll/fold sync

Installation

pip install jvim

Usage

# Open a file
jvim data.json

# Open multiple files
jvim a.json b.json c.json

# Open in read-only mode
jvim -R data.json

# Create new file
jvim newfile.json

Also available as jvi and jv shortcuts.

JSONL Support

jvim provides special handling for JSON Lines (.jsonl) files:

  • Pretty-printed editing: Each JSONL record is automatically formatted with indentation for easy reading and editing
  • Compact saving: When you save, each record is minified back to a single line, preserving the JSONL format
  • Record numbers: A second column shows the record number (1, 2, 3...) for easy navigation
  • Floating header: When scrolling through a multi-line record, the physical line number stays visible at the top

Example: A JSONL file with two records:

{"name": "Alice", "age": 30}
{"name": "Bob", "age": 25}

Opens in jvim as:

{
    "name": "Alice",
    "age": 30
}
{
    "name": "Bob",
    "age": 25
}

And saves back to the original compact format.

JSONPath Search

jvim supports powerful JSONPath searching with value filtering.

Basic JSONPath

Search patterns starting with $. or $[ are automatically recognized as JSONPath:

/$.name              # Find the "name" field
/$..email            # Find all "email" fields (recursive)
/$.users[0]          # First user
/$.users[*].name     # All user names

Value Filtering

You can filter search results by value using comparison operators:

Operator Description Example
= Equals $.status="active"
!= Not equals $.status!=null
> Greater than $.age>18
< Less than $.price<100
>= Greater or equal $.count>=5
<= Less or equal $.count<=10
~ Regex match $.email~@gmail\.com$

Examples

/$.users[*].age>30           # Users older than 30
/$.items[*].status="active"  # Items with active status
/$..name~^J                  # All names starting with J
/$.price<=1000               # Price 1000 or less
/$.config.enabled=true       # Enabled configs

Search Modifiers

Suffix Description
\j Force JSONPath mode for ambiguous patterns
\c Case insensitive (for regex text search)
\C Case sensitive (for regex text search)

History

Search and command history is automatically saved to ~/.jvim/history.json and restored on next launch. Use arrow keys (/) to navigate history in search (/) and command (:) modes.

Embedded JSON Editing

JSON files often contain escaped JSON strings as values. jvim lets you edit these nested JSON structures naturally.

How it works

  1. Position your cursor on a line containing a JSON string value
  2. Type ej in normal mode
  3. A new editor panel opens with the parsed and formatted JSON
  4. Edit the embedded JSON with full syntax highlighting and validation
  5. Save with :w to update the parent document (minified) or :q to cancel

Nested levels

You can edit embedded JSON within embedded JSON:

  • The panel title shows the current nesting level: Edit Embedded JSON (level 1)
  • A [+] indicator appears when you have unsaved changes
  • :w saves to the parent document and continues editing
  • :wq saves and returns to the previous level
  • :q! discards changes and returns to the previous level

Example

Given this JSON:

{
    "config": "{\"host\": \"localhost\", \"port\": 8080}"
}

Using ej on the config line opens:

{
    "host": "localhost",
    "port": 8080
}

After editing and saving, the parent is updated with the minified result.

Substitute

jvim supports vim-style substitute commands for find-and-replace.

Command Description
:s/old/new/ Replace first match on current line
:s/old/new/g Replace all matches on current line
:%s/old/new/g Replace all matches in entire file
:N,Ms/old/new/g Replace all matches in lines N to M

Features

  • Custom delimiters - Use any character as delimiter: :s#old#new#g, :s|old|new|g
  • Flags - g (global/all matches), i (case insensitive)
  • Regex support - Full regular expressions with group capture (\1, \2)
  • Undo - All substitutions can be undone with u

Examples

:s/foo/bar/           # Replace first "foo" with "bar" on current line
:%s/TODO/DONE/g       # Replace all "TODO" with "DONE" in file
:s/(\w+)/[\1]/g       # Wrap each word in brackets
:%s/old/new/gi        # Case-insensitive replace in entire file
:2,10s/from/to/g      # Replace in lines 2 through 10

JSONPath Substitute

When the find pattern starts with $. or $[, substitute operates on JSON structure. The trailing = determines the mode:

Pattern Mode Description
:s/$.key/newkey/g Key rename Rename JSON keys
:s/$.key=/value/g Value replace Replace all values at path
:s/$.key="old"/new/g Filtered value Replace values matching filter

Key rename

:s/$.name/username/g             # Rename "name" key to "username"
:s/$..name/label/g               # Rename all "name" keys recursively

Value replace

:s/$.name=/Bob/g                 # Replace "name" value with "Bob"
:s/$..status=/active/g           # Replace all "status" values recursively
:s/$.users[*].age=/0/g          # Reset all user ages to 0
:s/$..enabled=/true/g            # Set all "enabled" to true
:s/$..status="draft"/review/g   # Replace only "draft" statuses (filter)

Replacement values are auto-detected: numbers (42), booleans (true/false), null stay as-is; everything else is JSON-encoded as a string.

Multi-file Navigation

Open multiple files and navigate between them using argument list commands:

jvim a.json b.json c.json
Command Description
:n Go to next file
:N Go to previous file
:e# Switch to alternate (previously opened) file

The title bar shows the current position in the file list: a.json [1/3].

Files opened with :e <file> are tracked as the alternate file, so you can switch back with :e#.

Git Difftool Integration

jvimdiff can be used as a git difftool to compare JSON changes in your repository.

Setup

# Register jvimdiff as git difftool
jvimdiff --install-difftool

# Remove registration
jvimdiff --uninstall-difftool

Usage

# Compare using jvimdiff
git difftool -t jvimdiff              # All changed files
git difftool -t jvimdiff file.json    # Specific file
git difftool -t jvimdiff HEAD~3       # Compare with specific commit

# Set as default difftool
git config --global diff.tool jvimdiff
git difftool file.json                # Use without -t flag

Diff Viewer

jvim includes a side-by-side diff viewer for comparing two JSON files.

Usage

# Compare two JSON files
jvimdiff file1.json file2.json

# Skip JSON normalization (compare raw text)
jvimdiff --no-normalize file1.json file2.json

# Compare JSONL files (auto-detected for .jsonl extension)
jvimdiff --jsonl file1.json file2.json

Also available as jvd shortcut.

Features

  • Color-coded diff - Deletions (red), insertions (green), and replacements (gray) are highlighted
  • Scroll sync - Both panels scroll together
  • Fold sync - Folding/unfolding in one panel is mirrored to the other
  • Auto-fold - On load, all structure is folded, then only diff sections are unfolded
  • Hunk navigation - ]c next hunk, [c previous hunk (wraps around)
  • Panel switch - Tab to toggle focus between left and right panels
  • Active panel indicator - Title bar highlights the focused panel
  • Cursor sync - Cursor position syncs between panels
  • Line numbers - Logical line number (left) and JSONL record number (both panels)
  • Embedded JSON diff - ej to diff embedded JSON strings within each panel

Keybindings

Use :help inside jvim to see the full keybinding reference.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

jvim-0.7.0.tar.gz (296.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

jvim-0.7.0-py3-none-any.whl (61.7 kB view details)

Uploaded Python 3

File details

Details for the file jvim-0.7.0.tar.gz.

File metadata

  • Download URL: jvim-0.7.0.tar.gz
  • Upload date:
  • Size: 296.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.2

File hashes

Hashes for jvim-0.7.0.tar.gz
Algorithm Hash digest
SHA256 05caed75772ed2fb3e81c2505412dec14e116817a6e3a6b1033adfeb04eacd3b
MD5 f3e8aabf677c3b4b5d52de293002820f
BLAKE2b-256 082f48b12b0fca568f4a7d39e0afbf0070ed84be57950dc464a88fea3490d19e

See more details on using hashes here.

File details

Details for the file jvim-0.7.0-py3-none-any.whl.

File metadata

  • Download URL: jvim-0.7.0-py3-none-any.whl
  • Upload date:
  • Size: 61.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.2

File hashes

Hashes for jvim-0.7.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a05d542cd1b3b89ad42c705f929967d9e19d2d59b6d4311dc428a7210aceb81d
MD5 97f8f483a34c58b6c19c10f73f6955ea
BLAKE2b-256 06a79455735f0356510f3e369e60854b7de7ca32c34f7c60ab4b9460351be6fb

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page