NORMAL ~/wkd/p/data/help :set skin=modern utf-8

data.txt

Format and filter JSON/YAML/XML in Neovim — data.nvim

doc/data.txt — rendered from the plugin's own vimdoc

*data.txt*                          Format and filter JSON/YAML/XML in Neovim
                                                                    *data.nvim*

CONTENTS *data-contents*

  1. Introduction ............................. |data-introduction|
  2. Setup .................................... |data-setup|
  3. Commands .................................. |data-commands|
  4. Configuration ............................ |data-config|
  5. Scope ..................................... |data-scope|
  6. Health .................................... |data-health|
  7. lib.nvim integration ...................... |data-lib|
  8. Integrations .............................. |data-integrations|

1. INTRODUCTION *data-introduction*

data.nvim reformats structured data (JSON, YAML, XML) in place, either the
whole buffer or a Visual selection: pretty-print, collapse to one line
(JSON/XML), or flatten nested keys onto one path: value line each. The
input can also come from a register instead of the buffer, and the result
can go to a scratch split or another register -- see |data-scope|.

Requires Neovim 0.9+ and lib.nvim (hard dependency).

2. SETUP *data-setup*

                                                                *data.setup()*
    require("data").setup({
      json = { indent = 2, sep = "." },
    })
Calling setup() merges your options over the defaults and defines the
:JSON/:YAML/:XML/:Data user commands. setup() is safe to call once.

3. COMMANDS *data-commands*

                                                *:JSON* *:YAML* *:XML* *:Data*
:[range]JSON [action] [args] [flags]
:[range]YAML [action] [args] [flags]
:[range]XML  [action] [args] [flags]
:[range]Data [action] [args] [flags]

Range-aware: no range acts on the whole buffer, a Visual selection or an
explicit :N,M range acts only on those lines.

    :JSON / :YAML / :XML         same as pretty
    pretty [indent]               pretty-print (default 2-space indent)
    compact                        collapse onto one line (JSON/XML only)
    lines [--sep=X]                one "path: value" per leaf, dotted keys
    keys [--sep=X]                 only the (dotted) key paths, no values
    sort [indent]                  pretty-print with sorted object keys
    ndjson [indent]                :JSON only: pretty-print each line as its own object
    to yaml                        :JSON only: convert the scope to YAML
    to json                        :YAML only: convert the scope to JSON
    filter [--sep=X]                interactively filter path/value entries (needs pickers.nvim)

                                                        *data-preview* *:JSON-filter---preview*
filter takes two more flags of its own:

    --preview                      show the result as a before/after diff and
                                    ask before replacing the scope
    --no-preview                   skip that, overriding preview.filter = true

Backed by diff.nvim (optional). --preview is a filter flag only -- on any
other action it is an unknown-flag error rather than a flag that does nothing:
filter is the one action that loses information, and the one already built
to survive an arbitrarily long gap between resolving a scope and writing it.

Asked for with diff.nvim missing, NOTHING is written -- a preview that
silently skips the preview would defeat the point of the flag. It applies to
an in-place result only; --split/--out-reg leave the scope where it is, so
there is nothing to preview against, and combining them warns.

                                            *data-flags* *:JSON---reg* *:JSON---split*
Every action of every verb additionally accepts four source/target flags:

    --reg[=<name>]                 read the input from a register instead of
                                    the buffer (bare form: register.default)
    --inplace                      write the result over the buffer scope
    --split                        write the result to a scratch split
    --out-reg[=<name>]             write the result into a register

The defaults follow the source: a buffer or Visual scope replaces itself,
a register source opens a split. So :JSON pretty --reg=+ formats the
system clipboard into a new split and never touches the current buffer.

The three target flags are mutually exclusive. --reg --inplace also
requires an explicit range or Visual selection -- without one, "in place"
would mean the whole buffer, and replacing a whole file with register
contents should not be possible by accident. --out-reg refuses Vim's
read-only registers (: . % # =) by name, and reports how many
lines it wrote, since a register write is otherwise invisible. --reg== is
refused too, separately: reading the expression register would EVALUATE its
contents, and --reg should not be the one read that runs code.

Register input is CRLF-normalized -- clipboard text is usually CRLF-terminated
and a stray carriage return is an artifact, not content. A CR in the middle of
a line stays.

A read-only buffer is still a valid source for --split/--out-reg; only
the in-place write needs 'modifiable'.

Bare :JSON/:YAML/:XML/:Data (no action) stays whole-buffer, in-place
pretty-printing -- flags need an explicit action, e.g. :JSON pretty --split.

:Data offers pretty/lines/keys/sort/filter with the format auto-detected
(fenced block under the cursor, the register's own first non-blank line
under --reg, else the buffer's 'filetype') instead of named by the
command -- no compact/ndjson/to, since those already require knowing the
format. A clear error, not a guess, when no signal maps to json/yaml/xml.

lines/keys render exactly one line per leaf, so control characters in a
value are escaped: a newline as \n, a tab as \t, anything else in C0 as \xNN.
Backslashes are deliberately NOT escaped, so a Windows path stays readable --
lines is a human-readable summary, not JSON to parse back.

sort and pretty are currently identical output for all three formats:
neither JSON's nor YAML's decoder preserves the source's original key order
and both encoders sort keys by default; XML's encoder always sorts
attributes and never reorders elements. See |data-lib| and each
data.format.* module's own doc comment.

Malformed input in the resolved scope leaves the buffer untouched and
reports an error notification instead of partially overwriting anything.

Full cheatsheet (including <Tab> completion behavior): docs/BINDINGS.md.

4. CONFIGURATION *data-config*

    require("data").setup({
      json = {
        indent = 2,   -- default indent for :JSON pretty/sort
        sep = ".",    -- default path separator for :JSON lines/keys
      },
      yaml = {
        indent = 2,   -- default indent for :YAML pretty/sort
        sep = ".",    -- default path separator for :YAML lines/keys
      },
      xml = {
        indent = 2,   -- default indent for :XML pretty/sort
        sep = ".",    -- default path separator for :XML lines/keys
      },
      fenced_scope = {
        enable = true, -- see |data-integrations|
      },
      register = {
        default = "+", -- register a bare --reg / --out-reg uses
      },
      target = {
        split = "right", -- where --split opens: above|below|left|right|auto
      },
      preview = {
        filter = false,  -- diff before an in-place `filter` replaces the scope
        view = "inline", -- inline|float|vsplit|split|tab
      },
      keymaps = {
        preset = false, -- reserved; no default keymap preset exists yet
      },
    })
indent/sep are also overridable per invocation (:JSON pretty 4,
:YAML lines --sep=/) — the config values are only the fallback.

register.default is what a bare --reg/--out-reg resolves to; + is
the system clipboard. On a Neovim with no clipboard provider a BARE --reg
falls back to " and says so, while an explicitly typed --reg=+ is left
alone and fails with the ordinary "register is empty" message instead.
target.split picks the direction --split opens in; "auto" (or anything
that is not one of the four directions) honors your own 'splitbelow'/
'splitright'. preview.filter makes |data-preview| the default for every
in-place filter; preview.view takes any of diff.nvim's five views. The
side-by-side three ("vsplit"/"split"/"tab") need diff.nvim ff2f424 or newer --
before it, :Diff ignored source= for those views and put the wrong buffer
on the left. Nothing here can detect an older diff.nvim, so "inline" is the
default. See docs/integrations.md.

5. SCOPE *data-scope*

  - A range (:5,12JSON compact) or a Visual selection ('<,'>JSON lines)
    always wins -> only those lines are decoded and replaced.
  - Otherwise, with the cursor inside a matching fenced code block and
    color_my_ascii.nvim installed -> that block's interior (|data-integrations|).
  - Otherwise -> the whole current buffer.
  - --reg[=<name>] replaces all of the above as the INPUT: the buffer is
    not read at all, and a range (if any) then only says where an
    --inplace result would go. See |data-flags|.

Where the result goes is a separate decision from where the input came
from: --inplace, --split, --out-reg[=<name>], defaulting to whichever
matches the source. See |data-flags|.

6. HEALTH *data-health*

:checkhealth data reports Neovim version, whether lib.nvim is installed
(required), and whether it ships lib.lua.tables.path_flatten (required by
lines/keys), lib.lua.yaml.encode (required by :YAML),
lib.lua.xml (required by :XML), and lib.nvim.window.open_scratch_split
(required by --split). It also reports, informationally only, whether the
three optional plugins are present: color_my_ascii (fenced-block scope),
pickers.nvim (filter) and diff.nvim (filter --preview).

7. LIB.NVIM INTEGRATION *data-lib*

data.nvim is a thin editor layer: JSON decode/encode
(lib.nvim.json, lib.lua.json.encode), YAML decode/encode
(lib.lua.yaml), XML decode/encode (lib.lua.xml), the shared null
sentinel (lib.lua.null), and the recursive path-flattening lines/keys
need (lib.lua.tables.path_flatten) all live in
https://github.com/StefanBartl/lib.nvim, not in this plugin. The
:JSON/:YAML/:XML/:Data commands themselves are built on
lib.nvim.bindings.usercmd.composer.

8. INTEGRATIONS *data-integrations*

color_my_ascii.nvim (optional): when installed and the cursor sits inside a
fenced code block tagged ``json/`yaml/``xml with no explicit range given,
that block's interior becomes the scope instead of the whole buffer. A total
no-op without it. Disable with fenced_scope.enable = false. See
docs/integrations.md.

pickers.nvim (optional, required for filter specifically): backs
:JSON/:YAML/:XML filter via pickers.refine. Every other command works
without it; filter fails with a clear notification instead. See
docs/integrations.md.

diff.nvim (optional, required for filter --preview specifically): renders
the before/after diff |data-preview| shows before an in-place filter
replaces the scope, via diff.nvim's public require("diff").run() API. Plain
filter and every other command work without it; --preview with diff.nvim
missing writes nothing and says so. See docs/integrations.md.

keys

j / k
next / previous line
gg / G
first / last line
⏎
open the line under the cursor
/
search the plugins
:
command line — Tab completes
:help x
vimdoc of a plugin (:e x = plugin page)
:ls · :log · :stack
plugin list · activity stream · dependency graph
:colo x
colorscheme
:set skin=
modern | tui
?
this help
esc
close