nushell / nushell/nushell

Proposal: plugin json file format

Open
#8,773 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A:plugins category:enhancement
Dominant language
Rust
Stars
40.5k
Forks
2.3k
Avg merge
1d 19h
Merged PRs (30d)
85

Description

Related problem

The nuon file format is nice, but at the moment is only supported by Nushell itself. Also, into nuon fails on some data types. Can it be possible to expose the plugins JSON communication format? It is much easier to implement a parser for a valid JSON in any language than parsing a custom format.

Describe the solution you'd like

I propose exposing the existing plugin JSON communication format and name it nujson. The corresponding commands can be into nujson and from nujson. Here is a plugin implementation in Python:

import json
import sys

sys.stdout.write(chr(4) + "json")
sys.stdout.flush()
first_line = sys.stdin.readline()

if first_line == '"Signature"':
    sys.stdout.write(
        json.dumps(
            {
                "Signature": [
                    {
                        "sig": {
                            "name": "into nujson",
                            "usage": "Expose plugin call in JSON",
                            "extra_usage": "",
                            "input_type": "Any",
                            "output_type": "String",
                            "required_positional": [],
                            "optional_positional": [],
                            "vectorizes_over_list": False,
                            "named": [],
                            "input_output_types": [["Any", "String"]],
                            "allow_variants_without_examples": True,
                            "search_terms": [],
                            "is_filter": False,
                            "creates_scope": False,
                            "allows_unknown_args": False,
                            "category": "Experimental",
                        },
                        "examples": [],
                    },
                    {
                        "sig": {
                            "name": "from nujson",
                            "usage": "Load structured data from plugin JSON format",
                            "extra_usage": "",
                            "input_type": "String",
                            "output_type": "Any",
                            "required_positional": [],
                            "optional_positional": [],
                            "vectorizes_over_list": False,
                            "named": [],
                            "input_output_types": [["String", "Any"]],
                            "allow_variants_without_examples": True,
                            "search_terms": [],
                            "is_filter": False,
                            "creates_scope": False,
                            "allows_unknown_args": False,
                            "category": "Experimental",
                        },
                        "examples": [],
                    },
                ]
            }
        )
    )
else:
    call_str = ",".join([first_line] + sys.stdin.readlines())
    plugin_call = json.loads(call_str)
    command_name = plugin_call["CallInfo"]["name"]
    # sys.stderr.write(f"***{command_name}***\n{call_str}\n\n")
    if command_name == "into nujson":
        sys.stdout.write(
            json.dumps(
                {
                    "Value": {
                        "String": {
                            "span": {"start": 0, "end": 1},
                            "val": json.dumps(
                                plugin_call["CallInfo"]["input"]["Value"]
                            ),
                        }
                    }
                }
            )
        )
    elif command_name == "from nujson":
        sys.stdout.write(
            json.dumps(
                {
                    "Value": json.loads(
                        plugin_call["CallInfo"]["input"]["Value"]["String"]["val"]
                    )
                }
            )
        )
sys.stdout.write("\n")
sys.stdout.flush()

And here how it works:

image

The benefit is that I can write a command between into nujson and from nujson in any language without the need of registering my one-time script as a global command. (It is like a lightweight plugin.)

Describe alternatives you've considered

The existing JSON or NUON or any format cannot handle every type of data. It is not trivial to write a NUON parser.

Additional context and details

No response

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by tracing the existing plugin JSON communication format and the into nuon and from nuon entry points. Determine how the proposed into nujson and from nujson commands should expose that format and preserve supported data types. Done means the format is usable as described for lightweight scripts and the relevant command behavior is covered.

Written by the indexing model from the issue text.

Assessment

Tech stack
json, rust
Domain
api, cli
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.