nushell/crates/nu-cli/src/commands/clip.rs

114 lines
3.4 KiB
Rust
Raw Normal View History

2019-08-23 05:29:08 +02:00
#[cfg(feature = "clipboard")]
pub mod clipboard {
use crate::commands::WholeStreamCommand;
use crate::context::CommandRegistry;
use crate::prelude::*;
use futures::stream::StreamExt;
use nu_errors::ShellError;
use nu_protocol::{ReturnValue, Signature, Value};
2019-06-07 18:30:50 +02:00
2019-08-23 05:29:08 +02:00
use clipboard::{ClipboardContext, ClipboardProvider};
2019-08-02 21:15:07 +02:00
2019-08-23 05:29:08 +02:00
pub struct Clip;
2019-08-02 21:15:07 +02:00
2019-08-23 05:29:08 +02:00
#[derive(Deserialize)]
pub struct ClipArgs {}
2019-08-02 21:15:07 +02:00
2019-08-23 05:29:08 +02:00
impl WholeStreamCommand for Clip {
fn name(&self) -> &str {
"clip"
}
fn signature(&self) -> Signature {
Signature::build("clip")
}
fn usage(&self) -> &str {
"Copy the contents of the pipeline to the copy/paste buffer"
}
2019-08-23 05:29:08 +02:00
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
args.process(registry, clip)?.run()
}
2020-05-12 03:00:55 +02:00
fn examples(&self) -> &[Example] {
&[Example {
description: "Save text to the clipboard",
example: "echo 'secret value' | clip",
}]
}
2019-08-23 05:29:08 +02:00
}
2019-08-02 21:15:07 +02:00
2019-08-23 05:29:08 +02:00
pub fn clip(
ClipArgs {}: ClipArgs,
RunnableContext { input, name, .. }: RunnableContext,
) -> Result<OutputStream, ShellError> {
2019-09-28 02:05:18 +02:00
let stream = async_stream! {
let values: Vec<Value> = input.collect().await;
2019-08-02 21:15:07 +02:00
2019-09-28 02:05:18 +02:00
let mut clip_stream = inner_clip(values, name).await;
while let Some(value) = clip_stream.next().await {
yield value;
}
2019-08-23 05:29:08 +02:00
};
2019-08-02 21:15:07 +02:00
2019-08-23 05:29:08 +02:00
let stream: BoxStream<'static, ReturnValue> = stream.boxed();
2019-08-02 21:15:07 +02:00
2019-08-23 05:29:08 +02:00
Ok(OutputStream::from(stream))
}
async fn inner_clip(input: Vec<Value>, name: Tag) -> OutputStream {
if let Ok(clip_context) = ClipboardProvider::new() {
let mut clip_context: ClipboardContext = clip_context;
let mut new_copy_data = String::new();
if !input.is_empty() {
let mut first = true;
for i in input.iter() {
if !first {
new_copy_data.push_str("\n");
} else {
first = false;
2019-08-23 05:29:08 +02:00
}
let string: String = match i.as_string() {
Ok(string) => string.to_string(),
Err(_) => {
return OutputStream::one(Err(ShellError::labeled_error(
"Given non-string data",
"expected strings from pipeline",
name,
)))
}
};
new_copy_data.push_str(&string);
}
2019-08-23 05:29:08 +02:00
}
match clip_context.set_contents(new_copy_data) {
Ok(_) => {}
Err(_) => {
return OutputStream::one(Err(ShellError::labeled_error(
"Could not set contents of clipboard",
"could not set contents of clipboard",
name,
)));
}
}
2019-06-07 18:30:50 +02:00
OutputStream::empty()
} else {
OutputStream::one(Err(ShellError::labeled_error(
"Could not open clipboard",
"could not open clipboard",
name,
)))
}
2019-08-23 05:29:08 +02:00
}
2019-06-07 18:30:50 +02:00
}