The first thing our plugin must do is write out the desired serialization format, in this case JSON. We do that with the `send_encoder()` method. Then we use `send_hello()` to send our [`Hello`](plugin_protocol_reference.md#hello) message, informing Nu of our compatibility with it, and which is required before we can send any other messages. Then we read the JSON serialized messages that Nu sends us. Since Nu always sends each message on its own line, we simply read each line of input and parse it separately.
Each [`Call`](plugin_protocol_reference.md#call) comes with an ID number, which we must keep for the [`CallResponse`](plugin_protocol_reference.md#callresponse) (including errors).
When we're sent a `Signature` request, we respond with the signature of this plugin, which is a bit of information to tell Nu how the command should be called.
When sent a `Run` request, we parse the supplied JSON and respond to the request
```python
def handle_call(id, call_info):
try:
input = call_info["input"]["Value"]["String"]
output = {
"PipelineData": {
"Value": {
"Int": {
"val": len(input["val"]),
"span": input["span"]
}
}
}
}
send_response(id, output)
except:
send_error(
id,
"Could not process input",
call_info["call"]["head"]["span"]
)
```
The work of processing input is done by this `handle_call` function. Here, we assume we're given strings (we could make this more robust in the future and return meaningful errors otherwise), and then we extract the string we're given. From there, we measure the length of the string and create a new `Int` value for that length.
Finally, we use the same item we were given and replace the payload with this new Int. We do this to reuse the `span` that was passed to us with the string, though this is an optional step. We could have instead opted to create new metadata and passed that out instead.
We have a couple of helpers:
```python
def send_response(id, response):
msg = {
"CallResponse": [id, response]
}
sys.stdout.writelines([json.dumps(msg)])
sys.stdout.flush()
```
`send_response()` formats and writes a [`CallResponse`](plugin_protocol_reference.md#callresponse) with the given id and body.
```python
def send_error(id, error_msg, span):
error = {
"Error": {
"label": "Len Error",
"msg": error_msg,
"span": span,
}
}
send_response(id, error)
```
`send_error()` formats and sends an error response for us.
```python
import json
import sys
```
All of this takes a few imports to accomplish, so we make sure to include them.
```python
#!/usr/local/bin/python3
```
Finally, to make it easier to run our Python, we make this file executable (using something like `chmod +x nu_plugin_len.py`) and add the path to our python at the top. This trick works for Unix-based platforms, for Windows we would need to create an .exe or .bat file that would invoke the python code for us.
Please see the [example Python plugin](https://github.com/nushell/nushell/tree/main/crates/nu_plugin_python) for a comprehensive example on how to implement a Nushell plugin in another language, including Python.