Skip to content

Commit 189bf0b

Browse files
committed
Add support for piped output
1 parent 90bc0fd commit 189bf0b

File tree

1 file changed

+72
-15
lines changed

1 file changed

+72
-15
lines changed

gnuplot/src/figure.rs

Lines changed: 72 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use crate::options::{GnuplotVersion, MultiplotFillDirection, MultiplotFillOrder}
1212
use crate::util::escape;
1313
use crate::writer::Writer;
1414
use std::fs::File;
15-
use std::io::{BufWriter, Write};
15+
use std::io::{BufWriter, Read, Write};
1616
use std::path::{Path, PathBuf};
1717
use std::process::{Child, Command, Stdio};
1818
use std::str;
@@ -99,6 +99,11 @@ impl CloseSentinel
9999
CloseSentinel { gnuplot }
100100
}
101101

102+
pub fn stdout(&mut self) -> Option<impl Read>
103+
{
104+
self.gnuplot.stdout.take()
105+
}
106+
102107
/// Waits until the gnuplot process exits. See `std::process::Child::wait`.
103108
pub fn wait(&mut self) -> std::io::Result<std::process::ExitStatus>
104109
{
@@ -121,13 +126,20 @@ impl Drop for CloseSentinel
121126
}
122127
}
123128

129+
pub enum OutPutStream
130+
{
131+
Inherit,
132+
Piped,
133+
}
134+
124135
/// A figure that may contain multiple axes.
125136
pub struct Figure
126137
{
127138
axes: Vec<AxesVariant>,
128139
terminal: String,
129140
enhanced_text: bool,
130141
output_file: Option<PathBuf>,
142+
output_stream: OutPutStream,
131143
post_commands: String,
132144
pre_commands: String,
133145
// RefCell so that we can echo to it
@@ -165,6 +177,7 @@ impl Figure
165177
terminal: "".into(),
166178
enhanced_text: true,
167179
output_file: None,
180+
output_stream: OutPutStream::Inherit,
168181
gnuplot: None,
169182
post_commands: "".into(),
170183
pre_commands: "".into(),
@@ -233,6 +246,13 @@ impl Figure
233246
self
234247
}
235248

249+
// Set where gnuplot output should be streamed to
250+
pub fn set_output_stream(&mut self, output_stream: OutPutStream) -> &mut Figure
251+
{
252+
self.output_stream = output_stream;
253+
self
254+
}
255+
236256
/// Set or unset text enhancements
237257
pub fn set_enhanced_text(&mut self, enhanced: bool) -> &mut Figure
238258
{
@@ -382,6 +402,23 @@ impl Figure
382402
self
383403
}
384404

405+
fn update_cached_version(&mut self) -> std::io::Result<()>
406+
{
407+
let output = Command::new("gnuplot").arg("--version").output()?;
408+
if let Ok(version_string) = str::from_utf8(&output.stdout)
409+
{
410+
let parts: Vec<_> = version_string.split([' ', '.']).collect();
411+
if parts.len() > 2 && parts[0] == "gnuplot"
412+
{
413+
if let (Ok(major), Ok(minor)) = (parts[1].parse::<i32>(), parts[2].parse::<i32>())
414+
{
415+
self.version = Some(GnuplotVersion { major, minor });
416+
}
417+
}
418+
}
419+
Ok(())
420+
}
421+
385422
/// Launch a gnuplot process, if it hasn't been spawned already by a call to
386423
/// this function, and display the figure on it.
387424
///
@@ -397,20 +434,7 @@ impl Figure
397434

398435
if self.version.is_none()
399436
{
400-
let output = Command::new("gnuplot").arg("--version").output()?;
401-
402-
if let Ok(version_string) = str::from_utf8(&output.stdout)
403-
{
404-
let parts: Vec<_> = version_string.split([' ', '.']).collect();
405-
if parts.len() > 2 && parts[0] == "gnuplot"
406-
{
407-
if let (Ok(major), Ok(minor)) =
408-
(parts[1].parse::<i32>(), parts[2].parse::<i32>())
409-
{
410-
self.version = Some(GnuplotVersion { major, minor });
411-
}
412-
}
413-
}
437+
self.update_cached_version()?
414438
}
415439

416440
if self.gnuplot.is_none()
@@ -419,6 +443,11 @@ impl Figure
419443
Command::new("gnuplot")
420444
.arg("-p")
421445
.stdin(Stdio::piped())
446+
.stdout(match self.output_stream
447+
{
448+
OutPutStream::Inherit => Stdio::inherit(),
449+
OutPutStream::Piped => Stdio::piped(),
450+
})
422451
.spawn()
423452
.expect(
424453
"Couldn't spawn gnuplot. Make sure it is installed and available in PATH.",
@@ -458,6 +487,34 @@ impl Figure
458487
Ok(CloseSentinel::new(gnuplot))
459488
}
460489

490+
pub fn output_string(&mut self) -> Result<String, GnuplotInitError>
491+
{
492+
if self.axes.is_empty()
493+
{
494+
return Ok("".to_string());
495+
}
496+
497+
if self.version.is_none()
498+
{
499+
self.update_cached_version()?
500+
}
501+
502+
let mut gnuplot = Command::new("gnuplot")
503+
.arg("-p")
504+
.stdin(Stdio::piped())
505+
.stdout(Stdio::piped())
506+
.spawn()
507+
.expect("Couldn't spawn gnuplot. Make sure it is installed and available in PATH.");
508+
509+
let stdin = gnuplot.stdin.as_mut().expect("No stdin!?");
510+
self.echo(stdin);
511+
stdin.flush();
512+
513+
let output = gnuplot.wait_with_output()?;
514+
let o = output.stdout.as_slice();
515+
Ok(String::from_utf8_lossy(o).to_string())
516+
}
517+
461518
/// Save the figure to a png file.
462519
///
463520
/// # Arguments

0 commit comments

Comments
 (0)