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
  • 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.6.0.tar.gz (292.8 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.6.0-py3-none-any.whl (60.1 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for jvim-0.6.0.tar.gz
Algorithm Hash digest
SHA256 2ab35ce1d6645b24772694249c883023436e08a9e0466888e530044c140da101
MD5 a04446ad3e36ef169a969ff6ed5fff7c
BLAKE2b-256 4d4b1c97c0ba4d660e7c16b810ac325305e31d91952eb1ce82ff9f1db8f8d31d

See more details on using hashes here.

File details

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

File metadata

  • Download URL: jvim-0.6.0-py3-none-any.whl
  • Upload date:
  • Size: 60.1 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.6.0-py3-none-any.whl
Algorithm Hash digest
SHA256 ca7f371c7364a2b9048820fcea550d7352a3c693c2bf063203beedc56aa1e139
MD5 121391b552f90993bce9824d50529a10
BLAKE2b-256 af2e46b9b6af10af2a326bbc83cd2b9549e22135d92051ec544af1d9f7a189ff

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