Fix clipboard for Linux, use xclip on this platform
This commit is contained in:
parent
d0cbf800f2
commit
f11eabf868
6 changed files with 79 additions and 16 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -358,7 +358,6 @@ dependencies = [
|
|||
"derive_builder 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"directories 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ffsend-api 0.0.1",
|
||||
"fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
|
|
@ -3,8 +3,6 @@ The first release used for gathering feedback on the application by selected
|
|||
people.
|
||||
|
||||
Features:
|
||||
- Allow unarchiving on download
|
||||
- Use clipboard through `xclip` on Linux if available for persistence
|
||||
- Write complete README
|
||||
- Polish command outputs, make it consistent (format, color)
|
||||
- Automated releases through CI
|
||||
|
|
|
@ -27,12 +27,10 @@ no-color = ["colored/no-color"]
|
|||
[dependencies]
|
||||
chrono = "0.4"
|
||||
clap = "2.31"
|
||||
clipboard = { version = "0.4", optional = true }
|
||||
colored = "1.6"
|
||||
derive_builder = "0.5"
|
||||
directories = "0.10"
|
||||
failure = "0.1"
|
||||
failure_derive = "0.1"
|
||||
ffsend-api = { version = "*", path = "../api" }
|
||||
fs2 = "0.4"
|
||||
lazy_static = "1.0"
|
||||
|
@ -46,3 +44,6 @@ tar = { version = "0.4", optional = true }
|
|||
tempfile = "3"
|
||||
toml = "0.4"
|
||||
version-compare = "0.0.6"
|
||||
|
||||
[target.'cfg(not(target_os = "linux"))'.dependencies]
|
||||
clipboard = { version = "0.4", optional = true }
|
||||
|
|
|
@ -248,8 +248,10 @@ impl<'a> Upload<'a> {
|
|||
|
||||
// Copy the URL in the user's clipboard
|
||||
#[cfg(feature = "clipboard")] {
|
||||
if matcher_upload.copy() && set_clipboard(url.as_str().to_owned()).is_err() {
|
||||
print_error_msg("failed to copy the URL to the clipboard");
|
||||
if matcher_upload.copy() {
|
||||
if let Err(err) = set_clipboard(url.as_str().to_owned()) {
|
||||
print_error(err.context("failed to copy the URL to the clipboard, ignoring"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,9 +3,8 @@ extern crate chrono;
|
|||
extern crate clap;
|
||||
#[macro_use]
|
||||
extern crate derive_builder;
|
||||
extern crate failure;
|
||||
#[macro_use]
|
||||
extern crate failure_derive;
|
||||
extern crate failure;
|
||||
extern crate ffsend_api;
|
||||
#[cfg(feature = "history")]
|
||||
#[macro_use]
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#[cfg(feature = "clipboard")]
|
||||
#[cfg(all(feature = "clipboard", not(target_os = "linux")))]
|
||||
extern crate clipboard;
|
||||
extern crate colored;
|
||||
extern crate directories;
|
||||
|
@ -7,8 +7,6 @@ extern crate open;
|
|||
|
||||
use std::borrow::Borrow;
|
||||
use std::env::{current_exe, var_os};
|
||||
#[cfg(feature = "clipboard")]
|
||||
use std::error::Error as StdError;
|
||||
use std::ffi::OsStr;
|
||||
use std::fmt::{Debug, Display};
|
||||
use std::io::{
|
||||
|
@ -17,16 +15,22 @@ use std::io::{
|
|||
stderr,
|
||||
Write,
|
||||
};
|
||||
#[cfg(feature = "clipboard")]
|
||||
use std::io::ErrorKind as IoErrorKind;
|
||||
use std::path::Path;
|
||||
#[cfg(feature = "history")]
|
||||
use std::path::PathBuf;
|
||||
use std::process::{exit, ExitStatus};
|
||||
#[cfg(all(feature = "clipboard", target_os = "linux"))]
|
||||
use std::process::{Command, Stdio};
|
||||
|
||||
use chrono::Duration;
|
||||
use failure::{err_msg, Fail};
|
||||
#[cfg(all(feature = "clipboard", not(target_os = "linux")))]
|
||||
use failure::{Compat, Error};
|
||||
use ffsend_api::url::Url;
|
||||
use rpassword::prompt_password_stderr;
|
||||
#[cfg(feature = "clipboard")]
|
||||
#[cfg(all(feature = "clipboard", not(target_os = "linux")))]
|
||||
use self::clipboard::{ClipboardContext, ClipboardProvider};
|
||||
use self::colored::*;
|
||||
#[cfg(feature = "history")]
|
||||
|
@ -262,9 +266,69 @@ pub fn open_path(path: &str) -> Result<ExitStatus, IoError> {
|
|||
|
||||
/// Set the clipboard of the user to the given `content` string.
|
||||
#[cfg(feature = "clipboard")]
|
||||
pub fn set_clipboard(content: String) -> Result<(), Box<StdError>> {
|
||||
let mut context: ClipboardContext = ClipboardProvider::new()?;
|
||||
context.set_contents(content)
|
||||
pub fn set_clipboard(content: String) -> Result<(), ClipboardError> {
|
||||
#[cfg(not(target_os = "linux"))] {
|
||||
ClipboardProvider::new()
|
||||
.and_then(|mut context: ClipboardContext| context.set_contents(content))
|
||||
.map_err(|err| format_err!("{}", err).compat())
|
||||
.map_err(ClipboardError::Generic)
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")] {
|
||||
// Open an xclip process
|
||||
let mut process = match Command::new("xclip")
|
||||
.arg("-sel")
|
||||
.arg("clip")
|
||||
.stdin(Stdio::piped())
|
||||
.spawn()
|
||||
{
|
||||
Ok(process) => process,
|
||||
Err(err) => return Err(match err.kind() {
|
||||
IoErrorKind::NotFound => ClipboardError::NoXclip,
|
||||
_ => ClipboardError::Xclip(err),
|
||||
}),
|
||||
};
|
||||
|
||||
// Write the contents to the xclip process
|
||||
process.stdin.as_mut().unwrap()
|
||||
.write_all(content.as_bytes())
|
||||
.map_err(ClipboardError::Xclip)?;
|
||||
|
||||
// Wait for xclip to exit
|
||||
let status = process.wait()
|
||||
.map_err(ClipboardError::Xclip)?;
|
||||
if !status.success() {
|
||||
return Err(ClipboardError::XclipStatus(status.code().unwrap_or(0)));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "clipboard")]
|
||||
#[derive(Debug, Fail)]
|
||||
pub enum ClipboardError {
|
||||
/// A generic error occurred while setting the clipboard contents
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
#[fail(display = "failed to access clipboard")]
|
||||
Generic(#[cause] Compat<Error>),
|
||||
|
||||
/// Xclip is not installed on the system, which is required for clipboard support.
|
||||
#[cfg(target_os = "linux")]
|
||||
#[fail(display = "failed to access clipboard, xclip is not installed")]
|
||||
NoXclip,
|
||||
|
||||
/// An error occurred while using xclip to set the clipboard contents.
|
||||
/// This problem probably occurred when stargin the xclip process, or while piping the
|
||||
/// clipboard contents to the process.
|
||||
#[cfg(target_os = "linux")]
|
||||
#[fail(display = "failed to access clipboard using xclip")]
|
||||
Xclip(#[cause] IoError),
|
||||
|
||||
/// Xclip unexpectetly exited with a non-successful status code.
|
||||
#[cfg(target_os = "linux")]
|
||||
#[fail(display = "failed to use clipboard, xclip exited with status code {}", _0)]
|
||||
XclipStatus(i32),
|
||||
}
|
||||
|
||||
/// Check for an emtpy password in the given `password`.
|
||||
|
|
Loading…
Add table
Reference in a new issue