feat(copy): allow osc52 copy destination configuration (#1022)
add copy_cliboard option to allow configuring copy destination to primary selection instead of default clipboard
This commit is contained in:
parent
2799eb9160
commit
18709acde9
12 changed files with 189 additions and 110 deletions
|
|
@ -24,7 +24,7 @@ struct State {
|
||||||
tabs: Vec<TabInfo>,
|
tabs: Vec<TabInfo>,
|
||||||
tip_name: String,
|
tip_name: String,
|
||||||
mode_info: ModeInfo,
|
mode_info: ModeInfo,
|
||||||
diplay_text_copied_hint: bool,
|
text_copy_destination: Option<CopyDestination>,
|
||||||
display_system_clipboard_failure: bool,
|
display_system_clipboard_failure: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -156,14 +156,14 @@ impl ZellijPlugin for State {
|
||||||
Event::TabUpdate(tabs) => {
|
Event::TabUpdate(tabs) => {
|
||||||
self.tabs = tabs;
|
self.tabs = tabs;
|
||||||
}
|
}
|
||||||
Event::CopyToClipboard => {
|
Event::CopyToClipboard(copy_destination) => {
|
||||||
self.diplay_text_copied_hint = true;
|
self.text_copy_destination = Some(copy_destination);
|
||||||
}
|
}
|
||||||
Event::SystemClipboardFailure => {
|
Event::SystemClipboardFailure => {
|
||||||
self.display_system_clipboard_failure = true;
|
self.display_system_clipboard_failure = true;
|
||||||
}
|
}
|
||||||
Event::InputReceived => {
|
Event::InputReceived => {
|
||||||
self.diplay_text_copied_hint = false;
|
self.text_copy_destination = None;
|
||||||
self.display_system_clipboard_failure = false;
|
self.display_system_clipboard_failure = false;
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
|
@ -186,64 +186,7 @@ impl ZellijPlugin for State {
|
||||||
);
|
);
|
||||||
|
|
||||||
let first_line = format!("{}{}", superkey, ctrl_keys);
|
let first_line = format!("{}{}", superkey, ctrl_keys);
|
||||||
|
let second_line = self.second_line(cols);
|
||||||
let mut second_line = LinePart::default();
|
|
||||||
for t in &mut self.tabs {
|
|
||||||
if t.active {
|
|
||||||
match self.mode_info.mode {
|
|
||||||
InputMode::Normal => {
|
|
||||||
if t.is_fullscreen_active {
|
|
||||||
second_line = if self.diplay_text_copied_hint {
|
|
||||||
text_copied_hint(&self.mode_info.palette)
|
|
||||||
} else if self.display_system_clipboard_failure {
|
|
||||||
system_clipboard_error(&self.mode_info.palette)
|
|
||||||
} else {
|
|
||||||
fullscreen_panes_to_hide(&self.mode_info.palette, t.panes_to_hide)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
second_line = if self.diplay_text_copied_hint {
|
|
||||||
text_copied_hint(&self.mode_info.palette)
|
|
||||||
} else if self.display_system_clipboard_failure {
|
|
||||||
system_clipboard_error(&self.mode_info.palette)
|
|
||||||
} else {
|
|
||||||
keybinds(&self.mode_info, &self.tip_name, cols)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
InputMode::Locked => {
|
|
||||||
if t.is_fullscreen_active {
|
|
||||||
second_line = if self.diplay_text_copied_hint {
|
|
||||||
text_copied_hint(&self.mode_info.palette)
|
|
||||||
} else if self.display_system_clipboard_failure {
|
|
||||||
system_clipboard_error(&self.mode_info.palette)
|
|
||||||
} else {
|
|
||||||
locked_fullscreen_panes_to_hide(
|
|
||||||
&self.mode_info.palette,
|
|
||||||
t.panes_to_hide,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
second_line = if self.diplay_text_copied_hint {
|
|
||||||
text_copied_hint(&self.mode_info.palette)
|
|
||||||
} else if self.display_system_clipboard_failure {
|
|
||||||
system_clipboard_error(&self.mode_info.palette)
|
|
||||||
} else {
|
|
||||||
keybinds(&self.mode_info, &self.tip_name, cols)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
second_line = if self.diplay_text_copied_hint {
|
|
||||||
text_copied_hint(&self.mode_info.palette)
|
|
||||||
} else if self.display_system_clipboard_failure {
|
|
||||||
system_clipboard_error(&self.mode_info.palette)
|
|
||||||
} else {
|
|
||||||
keybinds(&self.mode_info, &self.tip_name, cols)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// [48;5;238m is gray background, [0K is so that it fills the rest of the line
|
// [48;5;238m is gray background, [0K is so that it fills the rest of the line
|
||||||
// [m is background reset, [0K is so that it clears the rest of the line
|
// [m is background reset, [0K is so that it clears the rest of the line
|
||||||
|
|
@ -258,3 +201,32 @@ impl ZellijPlugin for State {
|
||||||
println!("\u{1b}[m{}\u{1b}[0K", second_line);
|
println!("\u{1b}[m{}\u{1b}[0K", second_line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl State {
|
||||||
|
fn second_line(&self, cols: usize) -> LinePart {
|
||||||
|
let active_tab = self.tabs.iter().find(|t| t.active);
|
||||||
|
|
||||||
|
if let Some(copy_destination) = self.text_copy_destination {
|
||||||
|
text_copied_hint(&self.mode_info.palette, copy_destination)
|
||||||
|
} else if self.display_system_clipboard_failure {
|
||||||
|
system_clipboard_error(&self.mode_info.palette)
|
||||||
|
} else if let Some(active_tab) = active_tab {
|
||||||
|
if active_tab.is_fullscreen_active {
|
||||||
|
match self.mode_info.mode {
|
||||||
|
InputMode::Normal => {
|
||||||
|
fullscreen_panes_to_hide(&self.mode_info.palette, active_tab.panes_to_hide)
|
||||||
|
}
|
||||||
|
InputMode::Locked => locked_fullscreen_panes_to_hide(
|
||||||
|
&self.mode_info.palette,
|
||||||
|
active_tab.panes_to_hide,
|
||||||
|
),
|
||||||
|
_ => keybinds(&self.mode_info, &self.tip_name, cols),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
keybinds(&self.mode_info, &self.tip_name, cols)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LinePart::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -229,12 +229,19 @@ pub fn keybinds(help: &ModeInfo, tip_name: &str, max_width: usize) -> LinePart {
|
||||||
best_effort_shortcut_list(help, tip_body.short, max_width)
|
best_effort_shortcut_list(help, tip_body.short, max_width)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn text_copied_hint(palette: &Palette) -> LinePart {
|
pub fn text_copied_hint(palette: &Palette, copy_destination: CopyDestination) -> LinePart {
|
||||||
let hint = " Text copied to clipboard";
|
|
||||||
let green_color = match palette.green {
|
let green_color = match palette.green {
|
||||||
PaletteColor::Rgb((r, g, b)) => RGB(r, g, b),
|
PaletteColor::Rgb((r, g, b)) => RGB(r, g, b),
|
||||||
PaletteColor::EightBit(color) => Fixed(color),
|
PaletteColor::EightBit(color) => Fixed(color),
|
||||||
};
|
};
|
||||||
|
let hint = match copy_destination {
|
||||||
|
CopyDestination::Command => "Text piped to external command",
|
||||||
|
#[cfg(not(target_os = "macos"))]
|
||||||
|
CopyDestination::Primary => "Text copied to primary selection",
|
||||||
|
#[cfg(target_os = "macos")] // primary selection does not exist on macos
|
||||||
|
CopyDestination::Primary => "Text copied to clipboard",
|
||||||
|
CopyDestination::System => "Text copied to clipboard",
|
||||||
|
};
|
||||||
LinePart {
|
LinePart {
|
||||||
part: Style::new().fg(green_color).bold().paint(hint).to_string(),
|
part: Style::new().fg(green_color).bold().paint(hint).to_string(),
|
||||||
len: hint.len(),
|
len: hint.len(),
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ use std::os::unix::io::RawFd;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::str;
|
use std::str;
|
||||||
|
|
||||||
|
use zellij_utils::input::options::Clipboard;
|
||||||
use zellij_utils::pane_size::Size;
|
use zellij_utils::pane_size::Size;
|
||||||
use zellij_utils::{input::layout::Layout, position::Position, zellij_tile};
|
use zellij_utils::{input::layout::Layout, position::Position, zellij_tile};
|
||||||
|
|
||||||
|
|
@ -194,10 +195,12 @@ pub(crate) struct Screen {
|
||||||
draw_pane_frames: bool,
|
draw_pane_frames: bool,
|
||||||
session_is_mirrored: bool,
|
session_is_mirrored: bool,
|
||||||
copy_command: Option<String>,
|
copy_command: Option<String>,
|
||||||
|
copy_clipboard: Clipboard,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Screen {
|
impl Screen {
|
||||||
/// Creates and returns a new [`Screen`].
|
/// Creates and returns a new [`Screen`].
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
bus: Bus<ScreenInstruction>,
|
bus: Bus<ScreenInstruction>,
|
||||||
client_attributes: &ClientAttributes,
|
client_attributes: &ClientAttributes,
|
||||||
|
|
@ -206,6 +209,7 @@ impl Screen {
|
||||||
draw_pane_frames: bool,
|
draw_pane_frames: bool,
|
||||||
session_is_mirrored: bool,
|
session_is_mirrored: bool,
|
||||||
copy_command: Option<String>,
|
copy_command: Option<String>,
|
||||||
|
copy_clipboard: Clipboard,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Screen {
|
Screen {
|
||||||
bus,
|
bus,
|
||||||
|
|
@ -222,6 +226,7 @@ impl Screen {
|
||||||
draw_pane_frames,
|
draw_pane_frames,
|
||||||
session_is_mirrored,
|
session_is_mirrored,
|
||||||
copy_command,
|
copy_command,
|
||||||
|
copy_clipboard,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -495,6 +500,7 @@ impl Screen {
|
||||||
self.session_is_mirrored,
|
self.session_is_mirrored,
|
||||||
client_id,
|
client_id,
|
||||||
self.copy_command.clone(),
|
self.copy_command.clone(),
|
||||||
|
self.copy_clipboard.clone(),
|
||||||
);
|
);
|
||||||
tab.apply_layout(layout, new_pids, tab_index, client_id);
|
tab.apply_layout(layout, new_pids, tab_index, client_id);
|
||||||
if self.session_is_mirrored {
|
if self.session_is_mirrored {
|
||||||
|
|
@ -700,6 +706,7 @@ pub(crate) fn screen_thread_main(
|
||||||
draw_pane_frames,
|
draw_pane_frames,
|
||||||
session_is_mirrored,
|
session_is_mirrored,
|
||||||
config_options.copy_command,
|
config_options.copy_command,
|
||||||
|
config_options.copy_clipboard.unwrap_or_default(),
|
||||||
);
|
);
|
||||||
loop {
|
loop {
|
||||||
let (event, mut err_ctx) = screen
|
let (event, mut err_ctx) = screen
|
||||||
|
|
|
||||||
50
zellij-server/src/tab/clipboard.rs
Normal file
50
zellij-server/src/tab/clipboard.rs
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
use zellij_tile::prelude::CopyDestination;
|
||||||
|
use zellij_utils::{anyhow::Result, input::options::Clipboard};
|
||||||
|
|
||||||
|
use crate::ClientId;
|
||||||
|
|
||||||
|
use super::{copy_command::CopyCommand, Output};
|
||||||
|
|
||||||
|
pub(crate) enum ClipboardProvider {
|
||||||
|
Command(CopyCommand),
|
||||||
|
Osc52(Clipboard),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ClipboardProvider {
|
||||||
|
pub(crate) fn set_content(
|
||||||
|
&self,
|
||||||
|
content: &str,
|
||||||
|
output: &mut Output,
|
||||||
|
client_ids: impl Iterator<Item = ClientId>,
|
||||||
|
) -> Result<()> {
|
||||||
|
match &self {
|
||||||
|
ClipboardProvider::Command(command) => {
|
||||||
|
command.set(content.to_string())?;
|
||||||
|
}
|
||||||
|
ClipboardProvider::Osc52(clipboard) => {
|
||||||
|
let dest = match clipboard {
|
||||||
|
#[cfg(not(target_os = "macos"))]
|
||||||
|
Clipboard::Primary => 'p',
|
||||||
|
#[cfg(target_os = "macos")] // primary selection does not exist on macos
|
||||||
|
Clipboard::Primary => 'c',
|
||||||
|
Clipboard::System => 'c',
|
||||||
|
};
|
||||||
|
output.push_str_to_multiple_clients(
|
||||||
|
&format!("\u{1b}]52;{};{}\u{1b}\\", dest, base64::encode(content)),
|
||||||
|
client_ids,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn as_copy_destination(&self) -> CopyDestination {
|
||||||
|
match self {
|
||||||
|
ClipboardProvider::Command(_) => CopyDestination::Command,
|
||||||
|
ClipboardProvider::Osc52(clipboard) => match clipboard {
|
||||||
|
Clipboard::Primary => CopyDestination::Primary,
|
||||||
|
Clipboard::System => CopyDestination::System,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
use std::process::{Command, Stdio};
|
use std::process::{Command, Stdio};
|
||||||
|
|
||||||
|
use zellij_utils::anyhow::{Context, Result};
|
||||||
|
|
||||||
pub struct CopyCommand {
|
pub struct CopyCommand {
|
||||||
command: String,
|
command: String,
|
||||||
args: Vec<String>,
|
args: Vec<String>,
|
||||||
|
|
@ -15,25 +17,18 @@ impl CopyCommand {
|
||||||
args: command_with_args.collect(),
|
args: command_with_args.collect(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn set(&self, value: String) -> bool {
|
pub fn set(&self, value: String) -> Result<()> {
|
||||||
let process = match Command::new(self.command.clone())
|
let process = Command::new(self.command.clone())
|
||||||
.args(self.args.clone())
|
.args(self.args.clone())
|
||||||
.stdin(Stdio::piped())
|
.stdin(Stdio::piped())
|
||||||
.spawn()
|
.spawn()
|
||||||
{
|
.with_context(|| format!("couldn't spawn {}", self.command))?;
|
||||||
Err(why) => {
|
process
|
||||||
eprintln!("couldn't spawn {}: {}", self.command, why);
|
.stdin
|
||||||
return false;
|
.context("could not get stdin")?
|
||||||
}
|
.write_all(value.as_bytes())
|
||||||
Ok(process) => process,
|
.with_context(|| format!("couldn't write to {} stdin", self.command))?;
|
||||||
};
|
|
||||||
|
|
||||||
match process.stdin.unwrap().write_all(value.as_bytes()) {
|
Ok(())
|
||||||
Err(why) => {
|
|
||||||
eprintln!("couldn't write to {} stdin: {}", self.command, why);
|
|
||||||
false
|
|
||||||
}
|
|
||||||
Ok(_) => true,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,13 @@
|
||||||
//! `Tab`s holds multiple panes. It tracks their coordinates (x/y) and size,
|
//! `Tab`s holds multiple panes. It tracks their coordinates (x/y) and size,
|
||||||
//! as well as how they should be resized
|
//! as well as how they should be resized
|
||||||
|
|
||||||
|
mod clipboard;
|
||||||
mod copy_command;
|
mod copy_command;
|
||||||
mod pane_grid;
|
mod pane_grid;
|
||||||
mod pane_resizer;
|
mod pane_resizer;
|
||||||
|
|
||||||
use copy_command::CopyCommand;
|
use copy_command::CopyCommand;
|
||||||
|
use zellij_utils::input::options::Clipboard;
|
||||||
use zellij_utils::position::{Column, Line};
|
use zellij_utils::position::{Column, Line};
|
||||||
use zellij_utils::{position::Position, serde, zellij_tile};
|
use zellij_utils::{position::Position, serde, zellij_tile};
|
||||||
|
|
||||||
|
|
@ -41,6 +43,8 @@ use zellij_utils::{
|
||||||
pane_size::{Offset, PaneGeom, Size, Viewport},
|
pane_size::{Offset, PaneGeom, Size, Viewport},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use self::clipboard::ClipboardProvider;
|
||||||
|
|
||||||
// FIXME: This should be replaced by `RESIZE_PERCENT` at some point
|
// FIXME: This should be replaced by `RESIZE_PERCENT` at some point
|
||||||
const MIN_TERMINAL_HEIGHT: usize = 5;
|
const MIN_TERMINAL_HEIGHT: usize = 5;
|
||||||
const MIN_TERMINAL_WIDTH: usize = 5;
|
const MIN_TERMINAL_WIDTH: usize = 5;
|
||||||
|
|
@ -121,7 +125,7 @@ pub(crate) struct Tab {
|
||||||
session_is_mirrored: bool,
|
session_is_mirrored: bool,
|
||||||
pending_vte_events: HashMap<RawFd, Vec<VteBytes>>,
|
pending_vte_events: HashMap<RawFd, Vec<VteBytes>>,
|
||||||
selecting_with_mouse: bool,
|
selecting_with_mouse: bool,
|
||||||
copy_command: Option<String>,
|
clipboard_provider: ClipboardProvider,
|
||||||
// TODO: used only to focus the pane when the layout is loaded
|
// TODO: used only to focus the pane when the layout is loaded
|
||||||
// it seems that optimization is possible using `active_panes`
|
// it seems that optimization is possible using `active_panes`
|
||||||
focus_pane_id: Option<PaneId>,
|
focus_pane_id: Option<PaneId>,
|
||||||
|
|
@ -306,6 +310,7 @@ impl Tab {
|
||||||
session_is_mirrored: bool,
|
session_is_mirrored: bool,
|
||||||
client_id: ClientId,
|
client_id: ClientId,
|
||||||
copy_command: Option<String>,
|
copy_command: Option<String>,
|
||||||
|
copy_clipboard: Clipboard,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let panes = BTreeMap::new();
|
let panes = BTreeMap::new();
|
||||||
|
|
||||||
|
|
@ -318,6 +323,11 @@ impl Tab {
|
||||||
let mut connected_clients = HashSet::new();
|
let mut connected_clients = HashSet::new();
|
||||||
connected_clients.insert(client_id);
|
connected_clients.insert(client_id);
|
||||||
|
|
||||||
|
let clipboard_provider = match copy_command {
|
||||||
|
Some(command) => ClipboardProvider::Command(CopyCommand::new(command)),
|
||||||
|
None => ClipboardProvider::Osc52(copy_clipboard),
|
||||||
|
};
|
||||||
|
|
||||||
Tab {
|
Tab {
|
||||||
index,
|
index,
|
||||||
position,
|
position,
|
||||||
|
|
@ -342,7 +352,7 @@ impl Tab {
|
||||||
connected_clients_in_app,
|
connected_clients_in_app,
|
||||||
connected_clients,
|
connected_clients,
|
||||||
selecting_with_mouse: false,
|
selecting_with_mouse: false,
|
||||||
copy_command,
|
clipboard_provider,
|
||||||
focus_pane_id: None,
|
focus_pane_id: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1936,7 +1946,7 @@ impl Tab {
|
||||||
.send_to_plugin(PluginInstruction::Update(
|
.send_to_plugin(PluginInstruction::Update(
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
Event::CopyToClipboard,
|
Event::CopyToClipboard(self.clipboard_provider.as_copy_destination()),
|
||||||
))
|
))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
@ -1944,35 +1954,27 @@ impl Tab {
|
||||||
|
|
||||||
fn write_selection_to_clipboard(&self, selection: &str) {
|
fn write_selection_to_clipboard(&self, selection: &str) {
|
||||||
let mut output = Output::default();
|
let mut output = Output::default();
|
||||||
let mut system_clipboard_failure = false;
|
|
||||||
output.add_clients(&self.connected_clients);
|
output.add_clients(&self.connected_clients);
|
||||||
match self.copy_command.clone() {
|
let client_ids = self.connected_clients.iter().copied();
|
||||||
Some(copy_command) => {
|
|
||||||
let system_clipboard = CopyCommand::new(copy_command);
|
|
||||||
system_clipboard_failure = !system_clipboard.set(selection.to_owned());
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
output.push_str_to_multiple_clients(
|
|
||||||
&format!("\u{1b}]52;c;{}\u{1b}\\", base64::encode(selection)),
|
|
||||||
self.connected_clients.iter().copied(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: ideally we should be sending the Render instruction from the screen
|
let clipboard_event =
|
||||||
self.senders
|
match self
|
||||||
.send_to_server(ServerInstruction::Render(Some(output)))
|
.clipboard_provider
|
||||||
.unwrap();
|
.set_content(selection, &mut output, client_ids)
|
||||||
self.senders
|
{
|
||||||
.send_to_plugin(PluginInstruction::Update(
|
Ok(_) => {
|
||||||
None,
|
self.senders
|
||||||
None,
|
.send_to_server(ServerInstruction::Render(Some(output)))
|
||||||
if system_clipboard_failure {
|
.unwrap();
|
||||||
|
Event::CopyToClipboard(self.clipboard_provider.as_copy_destination())
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
log::error!("could not write selection to clipboard: {}", err);
|
||||||
Event::SystemClipboardFailure
|
Event::SystemClipboardFailure
|
||||||
} else {
|
}
|
||||||
Event::CopyToClipboard
|
};
|
||||||
},
|
self.senders
|
||||||
))
|
.send_to_plugin(PluginInstruction::Update(None, None, clipboard_event))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
fn is_inside_viewport(&self, pane_id: &PaneId) -> bool {
|
fn is_inside_viewport(&self, pane_id: &PaneId) -> bool {
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ use crate::{
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use zellij_utils::input::layout::LayoutTemplate;
|
use zellij_utils::input::layout::LayoutTemplate;
|
||||||
|
use zellij_utils::input::options::Clipboard;
|
||||||
use zellij_utils::ipc::IpcReceiverWithContext;
|
use zellij_utils::ipc::IpcReceiverWithContext;
|
||||||
use zellij_utils::pane_size::Size;
|
use zellij_utils::pane_size::Size;
|
||||||
|
|
||||||
|
|
@ -97,6 +98,7 @@ fn create_new_tab(size: Size) -> Tab {
|
||||||
connected_clients.insert(client_id);
|
connected_clients.insert(client_id);
|
||||||
let connected_clients = Rc::new(RefCell::new(connected_clients));
|
let connected_clients = Rc::new(RefCell::new(connected_clients));
|
||||||
let copy_command = None;
|
let copy_command = None;
|
||||||
|
let copy_clipboard = Clipboard::default();
|
||||||
let mut tab = Tab::new(
|
let mut tab = Tab::new(
|
||||||
index,
|
index,
|
||||||
position,
|
position,
|
||||||
|
|
@ -112,6 +114,7 @@ fn create_new_tab(size: Size) -> Tab {
|
||||||
session_is_mirrored,
|
session_is_mirrored,
|
||||||
client_id,
|
client_id,
|
||||||
copy_command,
|
copy_command,
|
||||||
|
copy_clipboard,
|
||||||
);
|
);
|
||||||
tab.apply_layout(
|
tab.apply_layout(
|
||||||
LayoutTemplate::default().try_into().unwrap(),
|
LayoutTemplate::default().try_into().unwrap(),
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ use std::convert::TryInto;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use zellij_utils::input::command::TerminalAction;
|
use zellij_utils::input::command::TerminalAction;
|
||||||
use zellij_utils::input::layout::LayoutTemplate;
|
use zellij_utils::input::layout::LayoutTemplate;
|
||||||
|
use zellij_utils::input::options::Clipboard;
|
||||||
use zellij_utils::ipc::IpcReceiverWithContext;
|
use zellij_utils::ipc::IpcReceiverWithContext;
|
||||||
use zellij_utils::pane_size::Size;
|
use zellij_utils::pane_size::Size;
|
||||||
|
|
||||||
|
|
@ -92,6 +93,7 @@ fn create_new_screen(size: Size) -> Screen {
|
||||||
let draw_pane_frames = false;
|
let draw_pane_frames = false;
|
||||||
let session_is_mirrored = true;
|
let session_is_mirrored = true;
|
||||||
let copy_command = None;
|
let copy_command = None;
|
||||||
|
let copy_clipboard = Clipboard::default();
|
||||||
Screen::new(
|
Screen::new(
|
||||||
bus,
|
bus,
|
||||||
&client_attributes,
|
&client_attributes,
|
||||||
|
|
@ -100,6 +102,7 @@ fn create_new_screen(size: Size) -> Screen {
|
||||||
draw_pane_frames,
|
draw_pane_frames,
|
||||||
session_is_mirrored,
|
session_is_mirrored,
|
||||||
copy_command,
|
copy_command,
|
||||||
|
copy_clipboard,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ pub enum Event {
|
||||||
Key(Key),
|
Key(Key),
|
||||||
Mouse(Mouse),
|
Mouse(Mouse),
|
||||||
Timer(f64),
|
Timer(f64),
|
||||||
CopyToClipboard,
|
CopyToClipboard(CopyDestination),
|
||||||
SystemClipboardFailure,
|
SystemClipboardFailure,
|
||||||
InputReceived,
|
InputReceived,
|
||||||
Visible(bool),
|
Visible(bool),
|
||||||
|
|
@ -267,3 +267,10 @@ impl Default for PluginCapabilities {
|
||||||
PluginCapabilities { arrow_fonts: true }
|
PluginCapabilities { arrow_fonts: true }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub enum CopyDestination {
|
||||||
|
Command,
|
||||||
|
Primary,
|
||||||
|
System,
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -477,3 +477,11 @@ plugins:
|
||||||
#copy_command: "xclip -selection clipboard" # x11
|
#copy_command: "xclip -selection clipboard" # x11
|
||||||
#copy_command: "wl-copy" # wayland
|
#copy_command: "wl-copy" # wayland
|
||||||
#copy_command: "pbcopy" # osx
|
#copy_command: "pbcopy" # osx
|
||||||
|
|
||||||
|
# Choose the destination for copied text
|
||||||
|
# Allows using the primary selection buffer (on x11/wayland) instead of the system clipboard.
|
||||||
|
# Does not apply when using copy_command.
|
||||||
|
# Options:
|
||||||
|
# - system (default)
|
||||||
|
# - primary
|
||||||
|
# copy_clipboard: primary
|
||||||
|
|
|
||||||
|
|
@ -79,6 +79,25 @@ pub struct Options {
|
||||||
#[clap(long)]
|
#[clap(long)]
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub copy_command: Option<String>,
|
pub copy_command: Option<String>,
|
||||||
|
|
||||||
|
/// OSC52 destination clipboard
|
||||||
|
#[clap(long, arg_enum, ignore_case = true, conflicts_with = "copy-command")]
|
||||||
|
#[serde(default)]
|
||||||
|
pub copy_clipboard: Option<Clipboard>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(ArgEnum, Deserialize, Serialize, Debug, Clone, PartialEq)]
|
||||||
|
pub enum Clipboard {
|
||||||
|
#[serde(alias = "system")]
|
||||||
|
System,
|
||||||
|
#[serde(alias = "primary")]
|
||||||
|
Primary,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Clipboard {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::System
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Options {
|
impl Options {
|
||||||
|
|
@ -105,6 +124,7 @@ impl Options {
|
||||||
let on_force_close = other.on_force_close.or(self.on_force_close);
|
let on_force_close = other.on_force_close.or(self.on_force_close);
|
||||||
let scroll_buffer_size = other.scroll_buffer_size.or(self.scroll_buffer_size);
|
let scroll_buffer_size = other.scroll_buffer_size.or(self.scroll_buffer_size);
|
||||||
let copy_command = other.copy_command.or_else(|| self.copy_command.clone());
|
let copy_command = other.copy_command.or_else(|| self.copy_command.clone());
|
||||||
|
let copy_clipboard = other.copy_clipboard.or_else(|| self.copy_clipboard.clone());
|
||||||
|
|
||||||
Options {
|
Options {
|
||||||
simplified_ui,
|
simplified_ui,
|
||||||
|
|
@ -118,6 +138,7 @@ impl Options {
|
||||||
on_force_close,
|
on_force_close,
|
||||||
scroll_buffer_size,
|
scroll_buffer_size,
|
||||||
copy_command,
|
copy_command,
|
||||||
|
copy_clipboard,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -148,6 +169,7 @@ impl Options {
|
||||||
let on_force_close = other.on_force_close.or(self.on_force_close);
|
let on_force_close = other.on_force_close.or(self.on_force_close);
|
||||||
let scroll_buffer_size = other.scroll_buffer_size.or(self.scroll_buffer_size);
|
let scroll_buffer_size = other.scroll_buffer_size.or(self.scroll_buffer_size);
|
||||||
let copy_command = other.copy_command.or_else(|| self.copy_command.clone());
|
let copy_command = other.copy_command.or_else(|| self.copy_command.clone());
|
||||||
|
let copy_clipboard = other.copy_clipboard.or_else(|| self.copy_clipboard.clone());
|
||||||
|
|
||||||
Options {
|
Options {
|
||||||
simplified_ui,
|
simplified_ui,
|
||||||
|
|
@ -161,6 +183,7 @@ impl Options {
|
||||||
on_force_close,
|
on_force_close,
|
||||||
scroll_buffer_size,
|
scroll_buffer_size,
|
||||||
copy_command,
|
copy_command,
|
||||||
|
copy_clipboard,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -210,6 +233,7 @@ impl From<CliOptions> for Options {
|
||||||
on_force_close: opts.on_force_close,
|
on_force_close: opts.on_force_close,
|
||||||
scroll_buffer_size: opts.scroll_buffer_size,
|
scroll_buffer_size: opts.scroll_buffer_size,
|
||||||
copy_command: opts.copy_command,
|
copy_command: opts.copy_command,
|
||||||
|
copy_clipboard: opts.copy_clipboard,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ pub mod position;
|
||||||
pub mod setup;
|
pub mod setup;
|
||||||
pub mod shared;
|
pub mod shared;
|
||||||
|
|
||||||
|
pub use anyhow;
|
||||||
pub use async_std;
|
pub use async_std;
|
||||||
pub use clap;
|
pub use clap;
|
||||||
pub use interprocess;
|
pub use interprocess;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue