Add --raw switch to print for binary data (#13597)

# Description

Something I meant to add a long time ago. We currently don't have a
convenient way to print raw binary data intentionally. You can pipe it
through `cat` to turn it into an unknown stream, or write it to a file
and read it again, but we can't really just e.g. generate msgpack and
write it to stdout without this. For example:

```nushell
[abc def] | to msgpack | print --raw
```

This is useful for nushell scripts that will be piped into something
else. It also means that `nu_plugin_nu_example` probably doesn't need to
do this anymore, but I haven't adjusted it yet:

```nushell
def tell_nushell_encoding [] {
  print -n "\u{0004}json"
}
```

This happens to work because 0x04 is a valid UTF-8 character, but it
wouldn't be possible if it were something above 0x80.

`--raw` also formats other things without `table`, I figured the two
things kind of go together. The output is kind of like `to text`.
Debatable whether that should share the same flag, but it was easier
that way and seemed reasonable.

# User-Facing Changes
- `print` new flag: `--raw`

# Tests + Formatting
Added tests.

# After Submitting
- [ ] release notes (command modified)
This commit is contained in:
Devyn Cairns
2024-08-12 02:29:25 -07:00
committed by GitHub
parent 18772b73b3
commit 4e205cd9a7
3 changed files with 60 additions and 3 deletions

View File

@ -604,6 +604,31 @@ impl PipelineData {
}
}
/// Consume and print self data without any extra formatting.
///
/// This does not use the `table` command to format data, and also prints binary values and
/// streams in their raw format without generating a hexdump first.
///
/// `no_newline` controls if we need to attach newline character to output.
/// `to_stderr` controls if data is output to stderr, when the value is false, the data is output to stdout.
pub fn print_raw(
self,
engine_state: &EngineState,
no_newline: bool,
to_stderr: bool,
) -> Result<Option<ExitStatus>, ShellError> {
if let PipelineData::Value(Value::Binary { val: bytes, .. }, _) = self {
if to_stderr {
stderr_write_all_and_flush(bytes)?;
} else {
stdout_write_all_and_flush(bytes)?;
}
Ok(None)
} else {
self.write_all_and_flush(engine_state, no_newline, to_stderr)
}
}
fn write_all_and_flush(
self,
engine_state: &EngineState,