Dep upgrades for debian (#5420)

* chore(deps): upgrade base64 0.22, colored 3.1, crossterm 0.29, dialoguer 0.11, directories 6.0, highway 1.2, prost 0.12.6, strip-ansi-escapes 0.2.1, suggest 0.5.1

* chore(deps): upgrade miette 7.6, nix 0.30, notify 8.2, notify-debouncer-full 0.5

* vte 0.15

* clap 4.6

* workspaceify plugin deps

* don't send empty fs watch events
This commit is contained in:
Aram Drevekenin
2026-07-28 12:05:38 +02:00
committed by GitHub
parent ea07e2d5b6
commit 9969ed10b2
87 changed files with 857 additions and 1422 deletions
Generated
+325 -431
View File
File diff suppressed because it is too large Load Diff
+17 -15
View File
@@ -30,17 +30,14 @@ suggest = { workspace = true }
thiserror = { workspace = true }
isahc = { workspace = true }
[target.'cfg(unix)'.dependencies]
nix = { workspace = true }
[target.'cfg(windows)'.build-dependencies]
embed-resource = "3"
[dev-dependencies]
insta = { version = "1.6.0", features = ["backtrace"] }
ssh2 = "0.9.1"
rand = "0.8.0"
regex = "1.8.1"
rand = { workspace = true }
regex = { workspace = true }
vte = { workspace = true }
[workspace]
@@ -81,10 +78,12 @@ rust-version = "1.92"
ansi_term = { version = "0.12.1", default-features = false }
anyhow = { version = "1.0.70", default-features = false, features = ["backtrace", "std"] }
async-trait = { version = "0.1", default-features = false }
clap = { version = "3.2.2", default-features = false, features = ["env", "derive", "color", "std", "suggestions"] }
crossterm = { version = "0.28", default-features = false, features = ["windows"] }
chrono = { version = "0.4.19", default-features = false, features = ["std", "clock"] }
clap = { version = "4.6", default-features = false, features = ["std", "color", "help", "usage", "error-context", "suggestions", "wrap_help", "derive", "env"] }
crossterm = { version = "0.29", default-features = false, features = ["windows"] }
daemonize = { package = "daemonix", version = "0.1", default-features = false }
dialoguer = { version = "0.10.4", default-features = false, features = ["password", "completion"] }
dialoguer = { version = "0.11", default-features = false, features = ["password", "completion"] }
fuzzy-matcher = { version = "0.3.7", default-features = false }
humantime = { version = "2.1.0", default-features = false }
interprocess = { version = "2.2", default-features = false, features = ["tokio"] }
isahc = { version = "1.7.2", default-features = false, features = ["http2", "text-decoding"] }
@@ -92,19 +91,22 @@ kdl = { version = "4.5.0", default-features = false, features = ["span"] }
lazy_static = { version = "1.4.0", default-features = false }
libc = { version = "0.2", default-features = false, features = ["std"] }
log = { version = "0.4.17", default-features = false }
miette = { version = "5.7.0", default-features = false, features = ["fancy"] }
nix = { version = "0.23.1", default-features = false }
notify-debouncer-full = { version = "0.3.1", default-features = false }
notify = { version = "6.1.1", default-features = false, features = ["macos_kqueue"] }
miette = { version = "7.6", default-features = false, features = ["derive", "fancy"] }
nix = { version = "0.30", default-features = false }
notify-debouncer-full = { version = "0.5", default-features = false }
notify = { version = "8.2", default-features = false, features = ["macos_kqueue"] }
num_cpus = { version = "1.16", default-features = false }
prost = { version = "0.11.9", default-features = false, features = ["std", "prost-derive"] }
pretty-bytes = { version = "0.2.2", default-features = false }
prost = { version = "0.12.6", default-features = false, features = ["std", "prost-derive"] }
rand = { version = "0.9", default-features = false, features = ["std", "std_rng", "thread_rng"] }
regex = { version = "1.5.5", default-features = false, features = ["perf", "std", "unicode-perl"] }
serde = { version = "1.0", default-features = false, features = ["derive", "std"] }
serde_json = { version = "1.0", default-features = false, features = ["std"] }
signal-hook = { version = "0.3", default-features = false, features = ["iterator"] }
strip-ansi-escapes = { version = "0.2.1", default-features = false }
strum = { version = "0.27.2", default-features = false, features = ["std"] }
strum_macros = { version = "0.27.2", default-features = false }
suggest = { version = "0.4.0", default-features = false }
suggest = { version = "0.5.1", default-features = false }
tempfile = { version = "3.2.0", default-features = false }
tokio = { version = "1.40", default-features = false, features = ["fs", "rt-multi-thread", "macros", "time", "process", "signal", "io-util", "io-std", "net"] }
thiserror = { version = "1.0.40", default-features = false }
@@ -112,7 +114,7 @@ tokio-util = { version = "0.7.15" }
unicode-width = { version = "0.1.8", default-features = false }
url = { version = "2.2.2", default-features = false, features = ["serde"] }
uuid = { version = "1.4.1", default-features = false, features = ["serde", "v4", "std"] }
vte = { version = "0.11.0", default-features = false }
vte = { version = "0.15", default-features = false, features = ["std"] }
windows-sys = { version = "0.59", default-features = false }
names = { version = "0.14.0", default-features = false }
include_dir = { version = "0.7.3", default-features = false }
+1 -1
View File
@@ -7,4 +7,4 @@ license.workspace = true
[dependencies]
zellij-tile = { path = "../../zellij-tile" }
rand = "0.9.0"
rand = { workspace = true }
+2 -3
View File
@@ -6,8 +6,7 @@ edition.workspace = true
license.workspace = true
[dependencies]
colored = "2"
ansi_term = "0.12"
unicode-width = "0.1.8"
ansi_term = { workspace = true }
unicode-width = { workspace = true }
zellij-tile = { path = "../../zellij-tile" }
zellij-tile-utils = { path = "../../zellij-tile-utils" }
-2
View File
@@ -6,6 +6,4 @@ edition.workspace = true
license.workspace = true
[dependencies]
ansi_term = "0.12.1"
zellij-tile = { path = "../../zellij-tile" }
chrono = "0.4.0"
@@ -6,6 +6,5 @@ edition.workspace = true
license.workspace = true
[dependencies]
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
serde = { workspace = true }
zellij-tile = { path = "../../zellij-tile" }
+4 -4
View File
@@ -7,7 +7,7 @@ license.workspace = true
[dependencies]
zellij-tile = { path = "../../zellij-tile" }
miette = { version = "5.7.0", features = ["fancy"] }
strip-ansi-escapes = "0.2"
unicode-width = "0.1"
fuzzy-matcher = "0.3"
miette = { workspace = true }
strip-ansi-escapes = { workspace = true }
unicode-width = { workspace = true }
fuzzy-matcher = { workspace = true }
+2 -2
View File
@@ -6,5 +6,5 @@ edition.workspace = true
[dependencies]
zellij-tile = { path = "../../zellij-tile" }
fuzzy-matcher = "0.3.7"
unicode-width = "0.1.10"
fuzzy-matcher = { workspace = true }
unicode-width = { workspace = true }
@@ -7,4 +7,3 @@ license.workspace = true
[dependencies]
zellij-tile = { path = "../../zellij-tile" }
fuzzy-matcher = "0.3.7"
+2 -2
View File
@@ -5,6 +5,6 @@ authors = ["Aram Drevekenin <[email protected]>"]
edition.workspace = true
[dependencies]
uuid = { version = "1.7.0", features = ["v4"] }
fuzzy-matcher = "0.3.7"
uuid = { workspace = true }
fuzzy-matcher = { workspace = true }
zellij-tile = { path = "../../zellij-tile" }
+4 -6
View File
@@ -5,10 +5,8 @@ authors = ["Aram Drevekenin <[email protected]>"]
edition.workspace = true
[dependencies]
ansi_term = "0.12.1"
zellij-tile = { path = "../../zellij-tile" }
chrono = "0.4.0"
fuzzy-matcher = "0.3.7"
unicode-width = "0.1.10"
humantime = "2.1.0"
uuid = { version = "1.7.0", features = ["v4"] }
fuzzy-matcher = { workspace = true }
unicode-width = { workspace = true }
humantime = { workspace = true }
uuid = { workspace = true }
+1 -2
View File
@@ -7,5 +7,4 @@ license.workspace = true
[dependencies]
zellij-tile = { path = "../../zellij-tile" }
url = "2.0"
rand = "0.9.0"
url = { workspace = true }
+8 -9
View File
@@ -6,16 +6,15 @@ edition.workspace = true
license.workspace = true
[dependencies]
colored = "2"
ansi_term = "0.12"
lazy_static = "1.4.0"
rand = "0.8.4"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
thiserror = "1.0.30"
unicode-width = "0.1.8"
ansi_term = { workspace = true }
lazy_static = { workspace = true }
rand = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
thiserror = { workspace = true }
unicode-width = { workspace = true }
zellij-tile = { path = "../../zellij-tile" }
zellij-tile-utils = { path = "../../zellij-tile-utils" }
[dev-dependencies]
regex = "1"
regex = { workspace = true }
+3 -6
View File
@@ -1,6 +1,6 @@
use std::path::PathBuf;
use rand::prelude::{IteratorRandom, SliceRandom};
use rand::prelude::{IndexedRandom, IteratorRandom};
use zellij_tile::prelude::get_zellij_version;
@@ -15,7 +15,7 @@ macro_rules! get_name_and_caching {
return name;
}};
($cache:expr, $from:expr) => {{
let name = $from.choose(&mut rand::thread_rng()).unwrap().to_string();
let name = $from.choose(&mut rand::rng()).unwrap().to_string();
$cache.caching(name.clone()).unwrap();
return name;
}};
@@ -30,10 +30,7 @@ macro_rules! populate_cache {
}
pub fn get_random_tip_name() -> String {
TIPS.keys()
.choose(&mut rand::thread_rng())
.unwrap()
.to_string()
TIPS.keys().choose(&mut rand::rng()).unwrap().to_string()
}
pub fn get_cached_tip_name() -> String {
+3 -9
View File
@@ -7,13 +7,7 @@ description = "A simplified ranger clone written as a Zellij plugin"
license.workspace = true
[dependencies]
colored = "2.0.0"
zellij-tile = { path = "../../zellij-tile" }
pretty-bytes = "0.2.2"
ignore = "0.4.20"
fuzzy-matcher = "0.3.7"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
unicode-width = "0.1.8"
ansi_term = "0.12.1"
strip-ansi-escapes = "0.1.1"
pretty-bytes = { workspace = true }
fuzzy-matcher = { workspace = true }
unicode-width = { workspace = true }
+2 -3
View File
@@ -6,8 +6,7 @@ edition.workspace = true
license.workspace = true
[dependencies]
colored = "2"
ansi_term = "0.12"
unicode-width = "0.1.8"
ansi_term = { workspace = true }
unicode-width = { workspace = true }
zellij-tile = { path = "../../zellij-tile" }
zellij-tile-utils = { path = "../../zellij-tile-utils" }
+1 -3
View File
@@ -206,9 +206,7 @@ fn read_from_channel(
should_sleep = true;
},
Ok(count) => {
for byte in buf.iter().take(count) {
vte_parser.advance(&mut terminal_output.grid, *byte);
}
vte_parser.advance(&mut terminal_output.grid, &buf[..count]);
let current_snapshot = take_snapshot(&mut terminal_output);
let mut last_snapshot = last_snapshot.lock().unwrap();
*cursor_coordinates.lock().unwrap() = terminal_output
+1 -1
View File
@@ -7,7 +7,7 @@ edition.workspace = true
[dependencies]
anyhow = { workspace = true }
serde_json = { workspace = true }
prost-build = { version = "0.11.9", default-features = false }
prost-build = { version = "0.12.6", default-features = false }
toml = { version = "0.5", default-features = false }
which = { version = "4.2", default-features = false }
xflags = { version = "0.3.2", default-features = false }
+1 -2
View File
@@ -26,7 +26,6 @@ dialoguer = { workspace = true }
interprocess = { workspace = true }
lazy_static = { workspace = true }
log = { workspace = true }
notify = { workspace = true }
num_cpus = { workspace = true }
regex = { workspace = true }
serde = { workspace = true }
@@ -53,7 +52,7 @@ signal-hook = { workspace = true }
[target.'cfg(unix)'.dependencies]
daemonize = { workspace = true }
nix = { workspace = true }
nix = { workspace = true, features = ["fs"] }
[target.'cfg(windows)'.dependencies]
crossterm = { workspace = true }
+8 -2
View File
@@ -115,6 +115,12 @@ fn try_to_connect_with_saved_session_token(
Ok(None)
}
fn dialoguer_error_to_client_error(error: dialoguer::Error) -> RemoteClientError {
match error {
dialoguer::Error::IO(error) => RemoteClientError::IoError(error),
}
}
fn authenticate_with_retry(
runtime: Handle,
remote_session_url: &str,
@@ -136,7 +142,7 @@ fn authenticate_with_retry(
None => Password::new()
.with_prompt("Enter authentication token")
.interact()
.map_err(|e| RemoteClientError::IoError(e))?,
.map_err(dialoguer_error_to_client_error)?,
};
let ca_cert_owned = ca_cert.map(|p| p.to_path_buf());
@@ -182,7 +188,7 @@ fn authenticate_with_retry(
return Err(RemoteClientError::InvalidAuthToken);
},
Err(e) => {
return Err(RemoteClientError::IoError(e));
return Err(dialoguer_error_to_client_error(e));
},
}
},
@@ -276,9 +276,7 @@ impl std::fmt::Display for GridSnapshot {
fn render_bytes(bytes: &[u8], win_size: Size) -> GridSnapshot {
let mut terminal_pane = build_terminal_pane(win_size);
let mut vte_parser = vte::Parser::new();
for &byte in bytes {
vte_parser.advance(&mut terminal_pane.grid, byte);
}
vte_parser.advance(&mut terminal_pane.grid, bytes);
let cursor = terminal_pane
.cursor_coordinates()
+4 -4
View File
@@ -13,12 +13,12 @@ ansi_term = { workspace = true }
anyhow = { workspace = true }
arrayvec = { version = "0.7.2", default-features = false, features = ["std"] }
async-trait = { version = "0.1.50", default-features = false }
base64 = { version = "0.13.0", default-features = false, features = ["std"] }
base64 = { version = "0.22", default-features = false, features = ["std"] }
byteorder = { version = "1.4.3", default-features = false, features = ["std"] }
bytes = { version = "1.6.0", default-features = false, features = ["std"] }
chrono = { version = "0.4.19", default-features = false, features = ["std", "clock"] }
chrono = { workspace = true }
crossbeam = { version = "0.8", default-features = false, features = ["crossbeam-channel", "std"] }
highway = { version = "0.6.4", default-features = false, features = ["std"] }
highway = { version = "=1.2.0", default-features = false, features = ["std"] }
interprocess = { workspace = true }
isahc = { workspace = true }
kasuari = { version = "0.4.12", default-features = false }
@@ -55,7 +55,7 @@ features = ["std"]
close_fds = "0.3.2"
daemonize = { workspace = true }
libc = { workspace = true }
nix = { workspace = true }
nix = { workspace = true, features = ["fs", "process", "signal", "term"] }
signal-hook = { workspace = true }
[target.'cfg(windows)'.dependencies]
+43 -27
View File
@@ -20,7 +20,7 @@ use std::{
collections::BTreeMap,
fs::File,
io,
os::fd::FromRawFd,
os::fd::{BorrowedFd, FromRawFd, IntoRawFd},
os::unix::{
io::{AsRawFd, RawFd},
process::CommandExt,
@@ -53,11 +53,13 @@ struct RawFdAsyncReader {
impl RawFdAsyncReader {
fn new(fd: RawFd) -> io::Result<Self> {
// Set O_NONBLOCK so AsyncFd can use epoll correctly
let flags =
fcntl(fd, FcntlArg::F_GETFL).map_err(|e| io::Error::from_raw_os_error(e as i32))?;
let borrowed_fd = unsafe { BorrowedFd::borrow_raw(fd) };
let flags = fcntl(borrowed_fd, FcntlArg::F_GETFL)
.map_err(|e| io::Error::from_raw_os_error(e as i32))?;
let mut oflags = OFlag::from_bits_truncate(flags);
oflags.insert(OFlag::O_NONBLOCK);
fcntl(fd, FcntlArg::F_SETFL(oflags)).map_err(|e| io::Error::from_raw_os_error(e as i32))?;
fcntl(borrowed_fd, FcntlArg::F_SETFL(oflags))
.map_err(|e| io::Error::from_raw_os_error(e as i32))?;
let file = unsafe { File::from_raw_fd(fd) };
Ok(Self {
@@ -195,8 +197,8 @@ fn handle_openpty(
};
// primary side of pty and child fd
let pid_primary = open_pty_res.master;
let pid_secondary = open_pty_res.slave;
let pid_primary = open_pty_res.master.into_raw_fd();
let pid_secondary = open_pty_res.slave.into_raw_fd();
if !command_exists(&cmd) {
return Err(ZellijError::CommandNotFound {
@@ -291,7 +293,7 @@ pub(crate) struct UnixPtyBackend {
fn try_write_to_fd(fd: RawFd, buf: &[u8]) -> Result<usize> {
let mut written = 0;
while written < buf.len() {
match unistd::write(fd, &buf[written..]) {
match unistd::write(unsafe { BorrowedFd::borrow_raw(fd) }, &buf[written..]) {
Ok(0) => break, // fd returned 0 on non-empty buf; treat like EAGAIN
Ok(n) => written += n,
Err(nix::errno::Errno::EINTR) => continue,
@@ -304,7 +306,7 @@ fn try_write_to_fd(fd: RawFd, buf: &[u8]) -> Result<usize> {
impl UnixPtyBackend {
pub fn new() -> Result<Self, io::Error> {
let current_termios = termios::tcgetattr(0).ok();
let current_termios = termios::tcgetattr(io::stdin()).ok();
if current_termios.is_none() {
log::warn!("Starting a server without a controlling terminal, using the default termios configuration.");
}
@@ -409,14 +411,18 @@ impl UnixPtyBackend {
.with_context(err_context)?
.get(&terminal_id)
{
Some(Some(fd)) => termios::tcdrain(*fd).with_context(err_context),
Some(Some(fd)) => {
termios::tcdrain(unsafe { BorrowedFd::borrow_raw(*fd) }).with_context(err_context)
},
_ => Err(anyhow!("could not find raw file descriptor")).with_context(err_context),
}
}
pub fn tcgetpgrp(&self, terminal_id: u32) -> Option<i32> {
match self.terminal_id_to_raw_fd.lock().ok()?.get(&terminal_id) {
Some(Some(fd)) => unistd::tcgetpgrp(*fd).ok().map(|pgid| pgid.as_raw()),
Some(Some(fd)) => unistd::tcgetpgrp(unsafe { BorrowedFd::borrow_raw(*fd) })
.ok()
.map(|pgid| pgid.as_raw()),
_ => None,
}
}
@@ -475,22 +481,27 @@ mod tests {
#[test]
fn try_write_to_fd_returns_partial_on_full_buffer() {
let pty = openpty(None, &None).expect("openpty failed");
let master_fd = pty.master.into_raw_fd();
let slave_fd = pty.slave.into_raw_fd();
let borrowed_master = unsafe { BorrowedFd::borrow_raw(master_fd) };
let borrowed_slave = unsafe { BorrowedFd::borrow_raw(slave_fd) };
let mut attrs = termios::tcgetattr(pty.slave).expect("tcgetattr failed");
let mut attrs = termios::tcgetattr(borrowed_slave).expect("tcgetattr failed");
termios::cfmakeraw(&mut attrs);
termios::tcsetattr(pty.slave, termios::SetArg::TCSANOW, &attrs).expect("tcsetattr failed");
termios::tcsetattr(borrowed_slave, termios::SetArg::TCSANOW, &attrs)
.expect("tcsetattr failed");
// O_NONBLOCK so write() returns EAGAIN instead of blocking
let flags = fcntl(pty.master, FcntlArg::F_GETFL).expect("F_GETFL");
let flags = fcntl(borrowed_master, FcntlArg::F_GETFL).expect("F_GETFL");
let mut oflags = OFlag::from_bits_truncate(flags);
oflags.insert(OFlag::O_NONBLOCK);
fcntl(pty.master, FcntlArg::F_SETFL(oflags)).expect("F_SETFL");
fcntl(borrowed_master, FcntlArg::F_SETFL(oflags)).expect("F_SETFL");
// Fill most of the buffer, leaving some space
let chunk = vec![0x42u8; 1024];
let mut total_filled = 0;
loop {
match super::try_write_to_fd(pty.master, &chunk) {
match super::try_write_to_fd(master_fd, &chunk) {
Ok(0) => break,
Ok(n) => total_filled += n,
Err(e) => panic!("unexpected error filling buffer: {e}"),
@@ -503,7 +514,7 @@ mod tests {
// Read a small amount from the slave to free partial space
let mut drain = vec![0u8; 512];
let slave_file = unsafe { std::fs::File::from_raw_fd(pty.slave) };
let slave_file = unsafe { std::fs::File::from_raw_fd(slave_fd) };
let mut slave_reader = std::io::BufReader::new(&slave_file);
let drained = slave_reader.read(&mut drain).expect("slave read failed");
assert!(drained > 0, "should have drained some bytes");
@@ -513,7 +524,7 @@ mod tests {
// Now write more than the freed space — should get a partial write
let size = 128 * 1024;
let data: Vec<u8> = (0..size).map(|i| (i % 256) as u8).collect();
let written = super::try_write_to_fd(pty.master, &data)
let written = super::try_write_to_fd(master_fd, &data)
.expect("try_write_to_fd should not error on EAGAIN");
assert!(
@@ -522,8 +533,8 @@ mod tests {
);
unsafe {
libc::close(pty.master);
libc::close(pty.slave);
libc::close(master_fd);
libc::close(slave_fd);
}
}
@@ -532,20 +543,25 @@ mod tests {
#[test]
fn try_write_to_fd_returns_zero_on_stuck_pty() {
let pty = openpty(None, &None).expect("openpty failed");
let master_fd = pty.master.into_raw_fd();
let slave_fd = pty.slave.into_raw_fd();
let borrowed_master = unsafe { BorrowedFd::borrow_raw(master_fd) };
let borrowed_slave = unsafe { BorrowedFd::borrow_raw(slave_fd) };
let mut attrs = termios::tcgetattr(pty.slave).expect("tcgetattr failed");
let mut attrs = termios::tcgetattr(borrowed_slave).expect("tcgetattr failed");
termios::cfmakeraw(&mut attrs);
termios::tcsetattr(pty.slave, termios::SetArg::TCSANOW, &attrs).expect("tcsetattr failed");
termios::tcsetattr(borrowed_slave, termios::SetArg::TCSANOW, &attrs)
.expect("tcsetattr failed");
let flags = fcntl(pty.master, FcntlArg::F_GETFL).expect("F_GETFL");
let flags = fcntl(borrowed_master, FcntlArg::F_GETFL).expect("F_GETFL");
let mut oflags = OFlag::from_bits_truncate(flags);
oflags.insert(OFlag::O_NONBLOCK);
fcntl(pty.master, FcntlArg::F_SETFL(oflags)).expect("F_SETFL");
fcntl(borrowed_master, FcntlArg::F_SETFL(oflags)).expect("F_SETFL");
// Fill the buffer completely — keep writing until we get Ok(0)
let fill = vec![0x42u8; 1024];
loop {
match super::try_write_to_fd(pty.master, &fill) {
match super::try_write_to_fd(master_fd, &fill) {
Ok(0) => break,
Ok(_) => continue,
Err(e) => panic!("unexpected error filling buffer: {e}"),
@@ -553,14 +569,14 @@ mod tests {
}
// Now the buffer is full — next write should return Ok(0)
let written = super::try_write_to_fd(pty.master, &[0x01, 0x02, 0x03])
let written = super::try_write_to_fd(master_fd, &[0x01, 0x02, 0x03])
.expect("try_write_to_fd should not error on EAGAIN");
assert_eq!(written, 0, "expected zero bytes written on full buffer");
unsafe {
libc::close(pty.master);
libc::close(pty.slave);
libc::close(master_fd);
libc::close(slave_fd);
}
}
}
+13 -1
View File
@@ -1,4 +1,7 @@
use super::sixel::{PixelRect, SixelGrid, SixelImageStore};
use base64::alphabet::STANDARD as BASE64_STANDARD_ALPHABET;
use base64::engine::general_purpose::{GeneralPurpose, GeneralPurposeConfig};
use base64::engine::{DecodePaddingMode, Engine as _};
use std::borrow::Cow;
use std::cell::RefCell;
use std::collections::BTreeMap;
@@ -30,6 +33,11 @@ use zellij_utils::{
const TABSTOP_WIDTH: usize = 8; // TODO: is this always right?
pub const MAX_TITLE_STACK_SIZE: usize = 1000;
const BASE64_DECODER: GeneralPurpose = GeneralPurpose::new(
&BASE64_STANDARD_ALPHABET,
GeneralPurposeConfig::new().with_decode_padding_mode(DecodePaddingMode::Indifferent),
);
/// Rewrites OSC 99 metadata for multiplexer forwarding:
///
/// 1. Namespaces the `i=` value with a pane ID prefix and flags so responses
@@ -3740,7 +3748,7 @@ impl Perform for Grid {
// TBD: paste from own clipboard - currently unsupported
},
base64 => {
if let Ok(bytes) = base64::decode(base64) {
if let Ok(bytes) = BASE64_DECODER.decode(base64) {
if let Ok(string) = String::from_utf8(bytes) {
self.pending_clipboard_update = Some(string);
}
@@ -4544,6 +4552,10 @@ impl Perform for Grid {
},
}
}
fn terminated(&self) -> bool {
!self.pending_forwarded_queries.is_empty()
}
}
#[derive(Clone)]
+1 -3
View File
@@ -246,9 +246,7 @@ impl Pane for PluginPane {
.entry(client_id)
.or_insert_with(|| vte::Parser::new());
for &byte in &vte_bytes {
vte_parser.advance(grid, byte);
}
vte_parser.advance(grid, &vte_bytes);
self.should_render.insert(client_id, true);
}
+5 -10
View File
@@ -229,16 +229,11 @@ impl Pane for TerminalPane {
self.pending_pty_input.extend(bytes);
return;
}
let mut iter = bytes.into_iter();
while let Some(byte) = iter.next() {
self.vte_parser.advance(&mut self.grid, byte);
if !self.grid.pending_forwarded_queries.is_empty() {
// Grid produced a forward. Stop feeding; queue the
// un-fed remainder so Tab can replay it after the
// reply.
self.pending_pty_input.extend(iter);
break;
}
let consumed = self
.vte_parser
.advance_until_terminated(&mut self.grid, &bytes);
if consumed < bytes.len() {
self.pending_pty_input.extend(&bytes[consumed..]);
}
}
fn cursor_coordinates(&self, client_id: Option<ClientId>) -> Option<(usize, usize, bool)> {
File diff suppressed because it is too large Load Diff
@@ -3,5 +3,5 @@ source: zellij-server/src/plugins/./unit/plugin_tests.rs
expression: "format!(\"{:#?}\", plugin_bytes_event)"
---
Some(
"Save invalid layout error: Invalid layout KDL: KdlError(KdlError { error_message: \"Failed to deserialize KDL node. \\nPossible reasons:\\n- Missing `;` after a node name, eg. { node; another_node; }\\n- Missing quotations (\\\") around an argument node eg. { first_node \\\"argument_node\\\"; }\\n- Missing an equal sign (=) between node arguments on a title line. eg. argument=\\\"value\\\"\\n- Found an extraneous equal sign (=) between node child arguments and their values. eg. { argument=\\\"value\\\" }\", src: Some(NamedSource { name: \"invalid_layout.kdl\", source: \"<redacted>\"), offset: Some(0), len: Some(4), help_message: None })\n\r",
"Save invalid layout error: Invalid layout KDL: KdlError(KdlError { error_message: \"Failed to deserialize KDL node. \\nPossible reasons:\\n- Missing `;` after a node name, eg. { node; another_node; }\\n- Missing quotations (\\\") around an argument node eg. { first_node \\\"argument_node\\\"; }\\n- Missing an equal sign (=) between node arguments on a title line. eg. argument=\\\"value\\\"\\n- Found an extraneous equal sign (=) between node child arguments and their values. eg. { argument=\\\"value\\\" }\", src: Some(NamedSource { name: \"invalid_layout.kdl\", source: \"<redacted>\", language: None), offset: Some(0), len: Some(4), help_message: None })\n\r",
)
+2 -2
View File
@@ -11,7 +11,7 @@ use crate::plugins::watch_filesystem::watch_filesystem;
use crate::plugins::zellij_exports::{wasi_read_string, wasi_write_object};
use highway::{HighwayHash, PortableHash};
use log::info;
use notify_debouncer_full::{notify::RecommendedWatcher, Debouncer, FileIdMap};
use notify_debouncer_full::{notify::RecommendedWatcher, Debouncer, RecommendedCache};
use std::{
collections::{BTreeMap, HashMap, HashSet},
path::PathBuf,
@@ -185,7 +185,7 @@ pub struct WasmBridge {
loading_plugins: HashSet<(PluginId, RunPlugin)>, // tracks loading plugins without handles
pending_plugin_reloads: HashSet<RunPlugin>,
path_to_default_shell: PathBuf,
watcher: Option<Debouncer<RecommendedWatcher, FileIdMap>>,
watcher: Option<Debouncer<RecommendedWatcher, RecommendedCache>>,
zellij_cwd: PathBuf,
session_env_vars: std::collections::BTreeMap<String, String>,
default_shell: Option<TerminalAction>,
+24 -16
View File
@@ -7,8 +7,8 @@ use std::time::Duration;
use notify_debouncer_full::{
new_debouncer,
notify::{EventKind, RecommendedWatcher, RecursiveMode, Watcher},
DebounceEventResult, Debouncer, FileIdMap,
notify::{EventKind, RecommendedWatcher, RecursiveMode},
DebounceEventResult, Debouncer, RecommendedCache,
};
use zellij_utils::{data::Event, errors::prelude::Result};
@@ -17,7 +17,7 @@ const DEBOUNCE_DURATION_MS: u64 = 400;
pub fn watch_filesystem(
senders: ThreadSenders,
zellij_cwd: &Path,
) -> Result<Debouncer<RecommendedWatcher, FileIdMap>> {
) -> Result<Debouncer<RecommendedWatcher, RecommendedCache>> {
let path_prefix_in_plugins = PathBuf::from("/host");
let current_dir = PathBuf::from(zellij_cwd);
let mut debouncer = new_debouncer(
@@ -93,34 +93,44 @@ pub fn watch_filesystem(
// TODO: at some point we might want to add FileMetadata to these, but right now
// the API is a bit unstable, so let's not rock the boat too much by adding another
// expensive syscall
let _ = senders.send_to_plugin(PluginInstruction::Update(vec![
(
let mut updates = vec![];
if !read_paths.is_empty() {
updates.push((
None,
None,
Event::FileSystemRead(read_paths.into_iter().map(|p| (p, None)).collect()),
),
(
));
}
if !create_paths.is_empty() {
updates.push((
None,
None,
Event::FileSystemCreate(
create_paths.into_iter().map(|p| (p, None)).collect(),
),
),
(
));
}
if !update_paths.is_empty() {
updates.push((
None,
None,
Event::FileSystemUpdate(
update_paths.into_iter().map(|p| (p, None)).collect(),
),
),
(
));
}
if !delete_paths.is_empty() {
updates.push((
None,
None,
Event::FileSystemDelete(
delete_paths.into_iter().map(|p| (p, None)).collect(),
),
),
]));
));
}
if !updates.is_empty() {
let _ = senders.send_to_plugin(PluginInstruction::Update(updates));
}
},
Err(errors) => errors
.iter()
@@ -128,8 +138,6 @@ pub fn watch_filesystem(
},
)?;
debouncer
.watcher()
.watch(zellij_cwd, RecursiveMode::Recursive)?;
debouncer.watch(zellij_cwd, RecursiveMode::Recursive)?;
Ok(debouncer)
}
+7 -1
View File
@@ -1,4 +1,6 @@
use anyhow::Result;
use base64::engine::general_purpose::STANDARD as BASE64_STANDARD;
use base64::engine::Engine as _;
use zellij_utils::{data::CopyDestination, input::options::Clipboard};
use crate::ClientId;
@@ -31,7 +33,11 @@ impl ClipboardProvider {
};
output.add_pre_vte_instruction_to_multiple_clients(
client_ids,
&format!("\u{1b}]52;{};{}\u{1b}\\", dest, base64::encode(content)),
&format!(
"\u{1b}]52;{};{}\u{1b}\\",
dest,
BASE64_STANDARD.encode(content)
),
);
},
};
@@ -1044,9 +1044,7 @@ fn take_snapshot(ansi_instructions: &str, rows: usize, columns: usize, palette:
explicitly_disable_kitty_keyboard_protocol,
);
let mut vte_parser = vte::Parser::new();
for &byte in ansi_instructions.as_bytes() {
vte_parser.advance(&mut grid, byte);
}
vte_parser.advance(&mut grid, ansi_instructions.as_bytes());
format!("{:?}", grid)
}
@@ -1083,9 +1081,7 @@ fn take_snapshot_with_sixel(
explicitly_disable_kitty_keyboard_protocol,
);
let mut vte_parser = vte::Parser::new();
for &byte in ansi_instructions.as_bytes() {
vte_parser.advance(&mut grid, byte);
}
vte_parser.advance(&mut grid, ansi_instructions.as_bytes());
format!("{:?}", grid)
}
@@ -1119,9 +1115,7 @@ fn take_snapshot_and_cursor_position(
explicitly_disable_kitty_keyboard_protocol,
);
let mut vte_parser = vte::Parser::new();
for &byte in ansi_instructions.as_bytes() {
vte_parser.advance(&mut grid, byte);
}
vte_parser.advance(&mut grid, ansi_instructions.as_bytes());
let coords = grid
.cursor_coordinates()
.and_then(|(x, y, visible)| if visible { Some((x, y)) } else { None });
@@ -15364,9 +15358,10 @@ fn osc99_grid_parses_and_stores_notification() {
// Feed OSC 99 through vte parser
let mut vte_parser = vte::Parser::new();
for &byte in b"\x1b]99;i=gridtest:p=title;Grid notification\x07" {
vte_parser.advance(&mut grid, byte);
}
vte_parser.advance(
&mut grid,
b"\x1b]99;i=gridtest:p=title;Grid notification\x07",
);
assert_eq!(
grid.pending_desktop_notifications.len(),
+1 -3
View File
@@ -28,9 +28,7 @@ macro_rules! parse_next_param {
macro_rules! parse_vte_bytes {
($self:expr, $encoded_component:expr) => {{
let mut vte_parser = vte::Parser::new();
for &byte in &$encoded_component {
vte_parser.advance($self.grid, byte);
}
vte_parser.advance($self.grid, &$encoded_component);
}};
}
+1 -3
View File
@@ -57,9 +57,7 @@ fn take_snapshot_and_cursor_coordinates(
grid: &mut Grid,
) -> (Option<(usize, usize)>, String) {
let mut vte_parser = vte::Parser::new();
for &byte in ansi_instructions.as_bytes() {
vte_parser.advance(grid, byte);
}
vte_parser.advance(grid, ansi_instructions.as_bytes());
let coords = grid
.cursor_coordinates()
.and_then(|(x, y, visible)| if visible { Some((x, y)) } else { None });
-1
View File
@@ -7,7 +7,6 @@ description = "A small client-side library for writing Zellij plugins"
license.workspace = true
[dependencies]
clap = { workspace = true }
prost = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
+6 -6
View File
@@ -14,11 +14,11 @@ anyhow = { workspace = true }
backtrace = { version = "0.3.55", default-features = false, features = ["std"] }
bitflags = { version = "2.5.0", default-features = false }
clap = { workspace = true }
clap_complete = { version = "3.2.1", default-features = false }
colored = { version = "2.0.0", default-features = false }
clap_complete = { version = "4.6", default-features = false }
colored = { version = "3.1", default-features = false }
colorsys = { version = "0.6.5", default-features = false, features = ["std"] }
crossbeam = { version = "0.8.1", default-features = false, features = ["alloc", "std"] }
directories = { version = "5.0", default-features = false }
directories = { version = "6.0", default-features = false }
include_dir = { version = "0.7.3", default-features = false }
kdl = { version = "4.5.0", default-features = false, features = ["span"] }
lazy_static = { workspace = true }
@@ -29,7 +29,7 @@ prost = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
shellexpand = { version = "3.0.0", default-features = false, features = ["base-0", "tilde"] }
strip-ansi-escapes = { version = "0.1.0", default-features = false }
strip-ansi-escapes = { workspace = true }
strum = { workspace = true }
strum_macros = { workspace = true }
tempfile = { workspace = true }
@@ -41,7 +41,7 @@ sha2 = { workspace = true }
libc = { workspace = true }
[target.'cfg(not(target_family = "wasm"))'.dependencies]
base64 = { version = "0.13.0", default-features = false, features = ["std"] }
base64 = { version = "0.22", default-features = false, features = ["std"] }
tokio = { workspace = true }
tokio-stream = { version = "0.1" }
tokio-util = { version = "0.7", default-features = false, features = ["compat", "io"] }
@@ -57,7 +57,7 @@ rusqlite = { version = "0.30", default-features = false, features = ["bundled"],
notify = { workspace = true }
[target.'cfg(unix)'.dependencies]
nix = { workspace = true }
nix = { workspace = true, features = ["user"] }
[target.'cfg(windows)'.dependencies]
crossterm = { workspace = true, features = ["events"] }
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1
View File
@@ -1,3 +1,4 @@
// This file is @generated by prost-build.
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct PercentOrFixed {
+1
View File
@@ -1,3 +1,4 @@
// This file is @generated by prost-build.
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct Command {
+1
View File
@@ -1,3 +1,4 @@
// This file is @generated by prost-build.
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct EventNameList {
+1
View File
@@ -1,3 +1,4 @@
// This file is @generated by prost-build.
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct File {
@@ -1,3 +1,4 @@
// This file is @generated by prost-build.
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct InputModeMessage {
+1
View File
@@ -1,3 +1,4 @@
// This file is @generated by prost-build.
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct Key {
+1
View File
@@ -1,3 +1,4 @@
// This file is @generated by prost-build.
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct Message {
@@ -1,3 +1,4 @@
// This file is @generated by prost-build.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
#[repr(i32)]
pub enum PaneFrameStyle {
@@ -1,3 +1,4 @@
// This file is @generated by prost-build.
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct PipeMessage {
@@ -1,3 +1,4 @@
// This file is @generated by prost-build.
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct PluginCommand {
@@ -1,3 +1,4 @@
// This file is @generated by prost-build.
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct PluginIds {
@@ -1,3 +1,4 @@
// This file is @generated by prost-build.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
#[repr(i32)]
pub enum PermissionType {
+1
View File
@@ -1,3 +1,4 @@
// This file is @generated by prost-build.
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct Resize {
+1
View File
@@ -1,3 +1,4 @@
// This file is @generated by prost-build.
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct Style {
@@ -1,3 +1,4 @@
// This file is @generated by prost-build.
pub mod api {
pub mod action {
include!("api.action.rs");
@@ -1,3 +1,4 @@
// This file is @generated by prost-build.
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct Size {
@@ -1993,8 +1994,6 @@ pub struct Options {
pub show_release_notes: ::core::option::Option<bool>,
#[prost(bool, optional, tag="33")]
pub advanced_mouse_actions: ::core::option::Option<bool>,
#[prost(bool, optional, tag="54")]
pub mouse_scroll_resize: ::core::option::Option<bool>,
#[prost(string, optional, tag="34")]
pub web_server_ip: ::core::option::Option<::prost::alloc::string::String>,
#[prost(uint32, optional, tag="35")]
@@ -2035,6 +2034,8 @@ pub struct Options {
pub stacked_pane_list: ::core::option::Option<bool>,
#[prost(enumeration="NestedSessionHandling", optional, tag="53")]
pub nested_session_handling: ::core::option::Option<i32>,
#[prost(bool, optional, tag="54")]
pub mouse_scroll_resize: ::core::option::Option<bool>,
}
/// Pane-targeting action messages
#[allow(clippy::derive_partial_eq_without_eq)]
@@ -1,3 +1,4 @@
// This file is @generated by prost-build.
pub mod client_server_contract {
include!("client_server_contract.rs");
}
@@ -1,3 +1,4 @@
// This file is @generated by prost-build.
pub mod nested_session_contract {
include!("nested_session_contract.rs");
}
@@ -1,3 +1,4 @@
// This file is @generated by prost-build.
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct NestedSessionMessage {
@@ -1,3 +1,4 @@
// This file is @generated by prost-build.
pub mod web_server_contract {
include!("web_server_contract.rs");
}
@@ -1,3 +1,4 @@
// This file is @generated by prost-build.
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct InstructionForWebServer {
+111 -267
View File
@@ -7,12 +7,26 @@ use crate::{
options::{Options, PaneFrameStyle},
},
};
use clap::{ArgEnum, Args, Parser, Subcommand};
use clap::builder::styling::{AnsiColor, Color, Style, Styles};
use clap::{Args, Parser, Subcommand, ValueEnum};
use serde::{Deserialize, Serialize};
use std::net::IpAddr;
use std::path::PathBuf;
use url::Url;
const fn ansi(color: AnsiColor) -> Style {
Style::new().fg_color(Some(Color::Ansi(color)))
}
const CLI_STYLES: Styles = Styles::styled()
.header(ansi(AnsiColor::Yellow))
.usage(ansi(AnsiColor::Yellow))
.literal(ansi(AnsiColor::Green))
.placeholder(Style::new())
.error(ansi(AnsiColor::Red))
.valid(ansi(AnsiColor::Green))
.invalid(ansi(AnsiColor::Yellow));
fn validate_session(name: &str) -> Result<String, String> {
#[cfg(unix)]
{
@@ -38,7 +52,7 @@ fn validate_session(name: &str) -> Result<String, String> {
}
#[derive(Parser, Default, Debug, Clone, Serialize, Deserialize)]
#[clap(version, name = "zellij")]
#[clap(version, name = "zellij", styles = CLI_STYLES, args_override_self = true)]
pub struct CliArgs {
/// Maximum panes on screen, caution: opening more panes will close old ones
#[clap(long, value_parser)]
@@ -65,7 +79,7 @@ pub struct CliArgs {
/// Raw KDL layout string to use directly (instead of a file path)
/// if inside a session (or using the --session flag) will be added to the session as a new tab
/// or tabs, otherwise will start a new session
#[clap(long, value_parser, conflicts_with_all = &["layout", "new-session-with-layout"])]
#[clap(long, value_parser, conflicts_with_all = &["layout", "new_session_with_layout"])]
pub layout_string: Option<String>,
/// Name of a predefined layout inside the layout directory or the path to a layout file
@@ -143,8 +157,7 @@ pub struct SubscribeCli {
short,
long,
required = true,
multiple_values = true,
multiple_occurrences = true
num_args(1..)
)]
pub pane_id: Vec<String>,
@@ -153,22 +166,21 @@ pub struct SubscribeCli {
#[clap(
short,
long,
min_values = 0,
max_values = 1,
default_missing_value = "0"
default_missing_value = "0",
num_args(0..=1)
)]
pub scrollback: Option<usize>,
/// Output format
#[clap(short, long, default_value = "raw", arg_enum)]
#[clap(short, long, default_value = "raw", value_enum)]
pub format: SubscribeFormat,
/// Preserve ANSI styling in the output
#[clap(long, value_parser, default_value("false"), takes_value(false))]
#[clap(long)]
pub ansi: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize, ArgEnum)]
#[derive(Debug, Clone, Serialize, Deserialize, ValueEnum)]
pub enum SubscribeFormat {
Raw,
Json,
@@ -197,7 +209,7 @@ pub struct WebCli {
short,
long,
value_parser,
conflicts_with_all(&["stop", "status", "create-token", "revoke-token", "revoke-all-tokens"]),
conflicts_with_all(&["stop", "status", "create_token", "revoke_token", "revoke_all_tokens"]),
display_order = 5
)]
pub daemonize: bool,
@@ -235,7 +247,7 @@ pub struct WebCli {
#[clap(
long,
value_parser,
conflicts_with_all(&["stop", "create-token", "revoke-token", "revoke-all-tokens"]),
conflicts_with_all(&["stop", "create_token", "revoke_token", "revoke_all_tokens"]),
display_order = 13
)]
pub ip: Option<IpAddr>,
@@ -243,7 +255,7 @@ pub struct WebCli {
#[clap(
long,
value_parser,
conflicts_with_all(&["stop", "create-token", "revoke-token", "revoke-all-tokens"]),
conflicts_with_all(&["stop", "create_token", "revoke_token", "revoke_all_tokens"]),
display_order = 14
)]
pub port: Option<u16>,
@@ -251,7 +263,7 @@ pub struct WebCli {
#[clap(
long,
value_parser,
conflicts_with_all(&["stop", "status", "create-token", "revoke-token", "revoke-all-tokens"]),
conflicts_with_all(&["stop", "status", "create_token", "revoke_token", "revoke_all_tokens"]),
display_order = 15
)]
pub cert: Option<PathBuf>,
@@ -259,7 +271,7 @@ pub struct WebCli {
#[clap(
long,
value_parser,
conflicts_with_all(&["stop", "status", "create-token", "revoke-token", "revoke-all-tokens"]),
conflicts_with_all(&["stop", "status", "create_token", "revoke_token", "revoke_all_tokens"]),
display_order = 16
)]
pub key: Option<PathBuf>,
@@ -291,15 +303,15 @@ pub enum Sessions {
#[clap(visible_alias = "ls")]
ListSessions {
/// Do not add colors and formatting to the list (useful for parsing)
#[clap(short, long, value_parser, takes_value(false), default_value("false"))]
#[clap(short, long)]
no_formatting: bool,
/// Print just the session name
#[clap(short, long, value_parser, takes_value(false), default_value("false"))]
#[clap(short, long)]
short: bool,
/// List the sessions in reverse order (default is ascending order)
#[clap(short, long, value_parser, takes_value(false), default_value("false"))]
#[clap(short, long)]
reverse: bool,
},
/// List existing plugin aliases
@@ -329,7 +341,7 @@ pub enum Sessions {
options: Option<Box<SessionCommand>>,
/// If resurrecting a dead session, immediately run all its commands on startup
#[clap(short, long, value_parser, takes_value(false), default_value("false"))]
#[clap(short, long)]
force_run_commands: bool,
/// Authentication token for remote sessions
@@ -376,7 +388,7 @@ pub enum Sessions {
#[clap(value_parser)]
target_session: Option<String>,
/// Kill the session if it's running before deleting it
#[clap(short, long, value_parser, takes_value(false), default_value("false"))]
#[clap(short, long)]
force: bool,
},
@@ -395,7 +407,7 @@ pub enum Sessions {
#[clap(short, long, value_parser)]
yes: bool,
/// Kill the sessions if they're running before deleting them
#[clap(short, long, value_parser, takes_value(false), default_value("false"))]
#[clap(short, long)]
force: bool,
},
@@ -416,29 +428,15 @@ pub enum Sessions {
cwd: Option<PathBuf>,
/// Open the new pane in floating mode
#[clap(short, long, value_parser, default_value("false"), takes_value(false))]
#[clap(short, long)]
floating: bool,
/// Open the new pane in place of the current pane, temporarily suspending it
#[clap(
short,
long,
value_parser,
default_value("false"),
takes_value(false),
conflicts_with("floating"),
conflicts_with("direction")
)]
#[clap(short, long, conflicts_with("floating"), conflicts_with("direction"))]
in_place: bool,
/// Close the replaced pane instead of suspending it (only effective with --in-place)
#[clap(
long,
value_parser,
default_value("false"),
takes_value(false),
requires("in-place")
)]
#[clap(long, requires("in_place"))]
close_replaced_pane: bool,
/// Name of the new pane
@@ -446,11 +444,11 @@ pub enum Sessions {
name: Option<String>,
/// Close the pane immediately when its command exits
#[clap(short, long, value_parser, default_value("false"), takes_value(false))]
#[clap(short, long)]
close_on_exit: bool,
/// Start the command suspended, only running after you first presses ENTER
#[clap(short, long, value_parser, default_value("false"), takes_value(false))]
#[clap(short, long)]
start_suspended: bool,
/// The x coordinates if the pane is floating as a bare integer (eg. 1) or percent (eg. 10%)
@@ -468,28 +466,18 @@ pub enum Sessions {
/// Whether to pin a floating pane so that it is always on top
#[clap(long, requires("floating"))]
pinned: Option<bool>,
#[clap(
long,
conflicts_with("floating"),
conflicts_with("direction"),
value_parser,
default_value("false"),
takes_value(false)
)]
#[clap(long, conflicts_with("floating"), conflicts_with("direction"))]
stacked: bool,
/// Block until the command has finished and its pane has been closed
#[clap(long, value_parser, default_value("false"), takes_value(false))]
#[clap(long)]
blocking: bool,
/// Block until the command exits successfully (exit status 0) OR its pane has been closed
#[clap(
long,
value_parser,
default_value("false"),
takes_value(false),
conflicts_with("blocking"),
conflicts_with("block-until-exit-failure"),
conflicts_with("block-until-exit")
conflicts_with("block_until_exit_failure"),
conflicts_with("block_until_exit")
)]
block_until_exit_success: bool,
@@ -497,24 +485,18 @@ pub enum Sessions {
/// closed
#[clap(
long,
value_parser,
default_value("false"),
takes_value(false),
conflicts_with("blocking"),
conflicts_with("block-until-exit-success"),
conflicts_with("block-until-exit")
conflicts_with("block_until_exit_success"),
conflicts_with("block_until_exit")
)]
block_until_exit_failure: bool,
/// Block until the command exits (regardless of exit status) OR its pane has been closed
#[clap(
long,
value_parser,
default_value("false"),
takes_value(false),
conflicts_with("blocking"),
conflicts_with("block-until-exit-success"),
conflicts_with("block-until-exit-failure")
conflicts_with("block_until_exit_success"),
conflicts_with("block_until_exit_failure")
)]
block_until_exit: bool,
/// if set, will open the pane near the current one rather than following the user's focus
@@ -533,8 +515,8 @@ pub enum Sessions {
#[clap(
long,
value_parser,
conflicts_with("near-current-pane"),
conflicts_with("in-place")
conflicts_with("near_current_pane"),
conflicts_with("in_place")
)]
tab_id: Option<usize>,
},
@@ -551,32 +533,19 @@ pub enum Sessions {
configuration: Option<PluginUserConfiguration>,
/// Open the new pane in floating mode
#[clap(short, long, value_parser, default_value("false"), takes_value(false))]
#[clap(short, long)]
floating: bool,
/// Open the new pane in place of the current pane, temporarily suspending it
#[clap(
short,
long,
value_parser,
default_value("false"),
takes_value(false),
conflicts_with("floating")
)]
#[clap(short, long, conflicts_with("floating"))]
in_place: bool,
/// Close the replaced pane instead of suspending it (only effective with --in-place)
#[clap(
long,
value_parser,
default_value("false"),
takes_value(false),
requires("in-place")
)]
#[clap(long, requires("in_place"))]
close_replaced_pane: bool,
/// Skip the memory and HD cache and force recompile of the plugin (good for development)
#[clap(short, long, value_parser, default_value("false"), takes_value(false))]
#[clap(short, long)]
skip_plugin_cache: bool,
/// The x coordinates if the pane is floating as a bare integer (eg. 1) or percent (eg. 10%)
#[clap(short, long, requires("floating"))]
@@ -603,7 +572,7 @@ pub enum Sessions {
#[clap(short, long, value_parser)]
borderless: Option<bool>,
/// Target a specific tab by ID
#[clap(long, value_parser, conflicts_with("in-place"))]
#[clap(long, value_parser, conflicts_with("in_place"))]
tab_id: Option<usize>,
},
/// Edit file with default $EDITOR / $VISUAL
@@ -621,29 +590,15 @@ pub enum Sessions {
direction: Option<Direction>,
/// Open the new pane in place of the current pane, temporarily suspending it
#[clap(
short,
long,
value_parser,
default_value("false"),
takes_value(false),
conflicts_with("floating"),
conflicts_with("direction")
)]
#[clap(short, long, conflicts_with("floating"), conflicts_with("direction"))]
in_place: bool,
/// Close the replaced pane instead of suspending it (only effective with --in-place)
#[clap(
long,
value_parser,
default_value("false"),
takes_value(false),
requires("in-place")
)]
#[clap(long, requires("in_place"))]
close_replaced_pane: bool,
/// Open the new pane in floating mode
#[clap(short, long, value_parser, default_value("false"), takes_value(false))]
#[clap(short, long)]
floating: bool,
/// Change the working directory of the editor
@@ -680,8 +635,8 @@ pub enum Sessions {
#[clap(
long,
value_parser,
conflicts_with("near-current-pane"),
conflicts_with("in-place")
conflicts_with("near_current_pane"),
conflicts_with("in_place")
)]
tab_id: Option<usize>,
},
@@ -821,7 +776,7 @@ pub enum CliAction {
path: Option<PathBuf>,
/// Dump the pane with full scrollback
#[clap(short, long, value_parser, default_value("false"), takes_value(false))]
#[clap(short, long)]
full: bool,
/// The pane_id of the pane, eg. terminal_1, plugin_2 or 3 (equivalent to terminal_3). If not specified, dumps the focused pane.
@@ -829,7 +784,7 @@ pub enum CliAction {
pane_id: Option<String>,
/// Preserve ANSI styling in the dump output
#[clap(short, long, value_parser, default_value("false"), takes_value(false))]
#[clap(short, long)]
ansi: bool,
},
/// Dump current layout to stdout
@@ -843,7 +798,7 @@ pub enum CliAction {
pane_id: Option<String>,
/// Preserve ANSI styling in the scrollback dump
#[clap(short, long, value_parser, default_value("false"), takes_value(false))]
#[clap(short, long)]
ansi: bool,
},
/// Scroll up in the focused pane
@@ -915,7 +870,7 @@ pub enum CliAction {
/// Toggle frames around panes in the UI
TogglePaneFrames,
SetPaneFrameStyle {
#[clap(arg_enum, value_parser)]
#[clap(value_enum, value_parser)]
style: PaneFrameStyle,
},
/// Toggle between sending text commands to all panes on the current tab and normal mode.
@@ -943,29 +898,15 @@ pub enum CliAction {
cwd: Option<PathBuf>,
/// Open the new pane in floating mode
#[clap(short, long, value_parser, default_value("false"), takes_value(false))]
#[clap(short, long)]
floating: bool,
/// Open the new pane in place of the current pane, temporarily suspending it
#[clap(
short,
long,
value_parser,
default_value("false"),
takes_value(false),
conflicts_with("floating"),
conflicts_with("direction")
)]
#[clap(short, long, conflicts_with("floating"), conflicts_with("direction"))]
in_place: bool,
/// Close the replaced pane instead of suspending it (only effective with --in-place)
#[clap(
long,
value_parser,
default_value("false"),
takes_value(false),
requires("in-place")
)]
#[clap(long, requires("in_place"))]
close_replaced_pane: bool,
/// The pane to replace when opening in place, eg. terminal_1, plugin_2 or 3 (only
@@ -973,8 +914,8 @@ pub enum CliAction {
#[clap(
long,
value_parser,
requires("in-place"),
conflicts_with("near-current-pane")
requires("in_place"),
conflicts_with("near_current_pane")
)]
pane_id: Option<String>,
@@ -983,24 +924,10 @@ pub enum CliAction {
name: Option<String>,
/// Close the pane immediately when its command exits
#[clap(
short,
long,
value_parser,
default_value("false"),
takes_value(false),
requires("command")
)]
#[clap(short, long, requires("command"))]
close_on_exit: bool,
/// Start the command suspended, only running it after the you first press ENTER
#[clap(
short,
long,
value_parser,
default_value("false"),
takes_value(false),
requires("command")
)]
#[clap(short, long, requires("command"))]
start_suspended: bool,
#[clap(long, value_parser)]
configuration: Option<PluginUserConfiguration>,
@@ -1021,14 +948,7 @@ pub enum CliAction {
/// Whether to pin a floating pane so that it is always on top
#[clap(long, requires("floating"))]
pinned: Option<bool>,
#[clap(
long,
conflicts_with("floating"),
conflicts_with("direction"),
value_parser,
default_value("false"),
takes_value(false)
)]
#[clap(long, conflicts_with("floating"), conflicts_with("direction"))]
stacked: bool,
/// Block until the command has finished and its pane has been closed
#[clap(short, long)]
@@ -1037,12 +957,9 @@ pub enum CliAction {
/// Block until the command exits successfully (exit status 0) OR its pane has been closed
#[clap(
long,
value_parser,
default_value("false"),
takes_value(false),
conflicts_with("blocking"),
conflicts_with("block-until-exit-failure"),
conflicts_with("block-until-exit")
conflicts_with("block_until_exit_failure"),
conflicts_with("block_until_exit")
)]
block_until_exit_success: bool,
@@ -1050,24 +967,18 @@ pub enum CliAction {
/// closed
#[clap(
long,
value_parser,
default_value("false"),
takes_value(false),
conflicts_with("blocking"),
conflicts_with("block-until-exit-success"),
conflicts_with("block-until-exit")
conflicts_with("block_until_exit_success"),
conflicts_with("block_until_exit")
)]
block_until_exit_failure: bool,
/// Block until the command exits (regardless of exit status) OR its pane has been closed
#[clap(
long,
value_parser,
default_value("false"),
takes_value(false),
conflicts_with("blocking"),
conflicts_with("block-until-exit-success"),
conflicts_with("block-until-exit-failure")
conflicts_with("block_until_exit_success"),
conflicts_with("block_until_exit_failure")
)]
block_until_exit: bool,
@@ -1090,8 +1001,8 @@ pub enum CliAction {
#[clap(
long,
value_parser,
conflicts_with("near-current-pane"),
conflicts_with("in-place")
conflicts_with("near_current_pane"),
conflicts_with("in_place")
)]
tab_id: Option<usize>,
},
@@ -1109,29 +1020,15 @@ pub enum CliAction {
line_number: Option<usize>,
/// Open the new pane in floating mode
#[clap(short, long, value_parser, default_value("false"), takes_value(false))]
#[clap(short, long)]
floating: bool,
/// Open the new pane in place of the current pane, temporarily suspending it
#[clap(
short,
long,
value_parser,
default_value("false"),
takes_value(false),
conflicts_with("floating"),
conflicts_with("direction")
)]
#[clap(short, long, conflicts_with("floating"), conflicts_with("direction"))]
in_place: bool,
/// Close the replaced pane instead of suspending it (only effective with --in-place)
#[clap(
long,
value_parser,
default_value("false"),
takes_value(false),
requires("in-place")
)]
#[clap(long, requires("in_place"))]
close_replaced_pane: bool,
/// Change the working directory of the editor
@@ -1168,8 +1065,8 @@ pub enum CliAction {
#[clap(
long,
value_parser,
conflicts_with("near-current-pane"),
conflicts_with("in-place")
conflicts_with("near_current_pane"),
conflicts_with("in_place")
)]
tab_id: Option<usize>,
},
@@ -1284,7 +1181,7 @@ pub enum CliAction {
/// Returns: The created tab's ID as a single number on stdout
NewTab {
/// Layout to use for the new tab
#[clap(short, long, value_parser, conflicts_with = "layout-string")]
#[clap(short, long, value_parser, conflicts_with = "layout_string")]
layout: Option<PathBuf>,
/// Raw KDL layout string to use directly (instead of a layout file path)
@@ -1304,72 +1201,45 @@ pub enum CliAction {
cwd: Option<PathBuf>,
/// Optional initial command to run in the new tab
#[clap(
value_parser,
conflicts_with("initial-plugin"),
multiple_values(true),
takes_value(true),
last(true)
)]
#[clap(value_parser, conflicts_with("initial_plugin"), last(true))]
initial_command: Vec<String>,
/// Initial plugin to load in the new tab
#[clap(long, value_parser, conflicts_with("initial-command"))]
#[clap(long, value_parser, conflicts_with("initial_command"))]
initial_plugin: Option<String>,
/// Close the pane immediately when its command exits
#[clap(
long,
value_parser,
default_value("false"),
takes_value(false),
requires("initial-command")
)]
#[clap(long, requires("initial_command"))]
close_on_exit: bool,
/// Start the command suspended, only running it after you first press ENTER
#[clap(
long,
value_parser,
default_value("false"),
takes_value(false),
requires("initial-command")
)]
#[clap(long, requires("initial_command"))]
start_suspended: bool,
/// Block until the command exits successfully (exit status 0) OR its pane has been closed
#[clap(
long,
value_parser,
default_value("false"),
takes_value(false),
requires("initial-command"),
conflicts_with("block-until-exit-failure"),
conflicts_with("block-until-exit")
requires("initial_command"),
conflicts_with("block_until_exit_failure"),
conflicts_with("block_until_exit")
)]
block_until_exit_success: bool,
/// Block until the command exits with failure (non-zero exit status) OR its pane has been closed
#[clap(
long,
value_parser,
default_value("false"),
takes_value(false),
requires("initial-command"),
conflicts_with("block-until-exit-success"),
conflicts_with("block-until-exit")
requires("initial_command"),
conflicts_with("block_until_exit_success"),
conflicts_with("block_until_exit")
)]
block_until_exit_failure: bool,
/// Block until the command exits (regardless of exit status) OR its pane has been closed
#[clap(
long,
value_parser,
default_value("false"),
takes_value(false),
requires("initial-command"),
conflicts_with("block-until-exit-success"),
conflicts_with("block-until-exit-failure")
requires("initial_command"),
conflicts_with("block_until_exit_success"),
conflicts_with("block_until_exit_failure")
)]
block_until_exit: bool,
@@ -1401,8 +1271,8 @@ pub enum CliAction {
/// Path to the layout file
#[clap(
value_parser,
required_unless_present = "layout-string",
conflicts_with = "layout-string"
required_unless_present = "layout_string",
conflicts_with = "layout_string"
)]
layout: Option<PathBuf>,
@@ -1415,16 +1285,16 @@ pub enum CliAction {
layout_dir: Option<PathBuf>,
/// Retain existing terminal panes that do not fit in the layout (default: false)
#[clap(long, value_parser, takes_value(false), default_value("false"))]
#[clap(long)]
retain_existing_terminal_panes: bool,
/// Retain existing plugin panes that do not fit with the layout default: false)
#[clap(long, value_parser, takes_value(false), default_value("false"))]
#[clap(long)]
retain_existing_plugin_panes: bool,
/// Only apply the layout to the active tab (uses just the first layout tab if it has
/// multiple)
#[clap(long, value_parser, takes_value(false), default_value("false"))]
#[clap(long)]
apply_only_to_active_tab: bool,
},
/// Query all tab names
@@ -1441,13 +1311,7 @@ pub enum CliAction {
#[clap(short, long, value_parser)]
in_place: bool,
/// Close the replaced pane instead of suspending it (only effective with --in-place)
#[clap(
long,
value_parser,
default_value("false"),
takes_value(false),
requires("in-place")
)]
#[clap(long, requires("in_place"))]
close_replaced_pane: bool,
#[clap(short, long, value_parser)]
move_to_focused_tab: bool,
@@ -1457,7 +1321,7 @@ pub enum CliAction {
#[clap(short, long, value_parser)]
skip_plugin_cache: bool,
/// Target a specific tab by ID
#[clap(long, value_parser, conflicts_with("in-place"))]
#[clap(long, value_parser, conflicts_with("in_place"))]
tab_id: Option<usize>,
},
/// Returns: Plugin pane ID (format: plugin_<id>)
@@ -1467,13 +1331,7 @@ pub enum CliAction {
#[clap(short, long, value_parser)]
in_place: bool,
/// Close the replaced pane instead of suspending it (only effective with --in-place)
#[clap(
long,
value_parser,
default_value("false"),
takes_value(false),
requires("in-place")
)]
#[clap(long, requires("in_place"))]
close_replaced_pane: bool,
url: Url,
#[clap(short, long, value_parser)]
@@ -1486,7 +1344,7 @@ pub enum CliAction {
)]
no_focus: bool,
/// Target a specific tab by ID
#[clap(long, value_parser, conflicts_with("in-place"))]
#[clap(long, value_parser, conflicts_with("in_place"))]
tab_id: Option<usize>,
},
RenameSession {
@@ -1529,24 +1387,10 @@ tail -f /tmp/my-live-logfile | zellij action pipe --name logs --plugin https://e
#[clap(short('c'), long, value_parser, display_order(4))]
plugin_configuration: Option<PluginUserConfiguration>,
/// Launch a new plugin even if one is already running
#[clap(
short('l'),
long,
value_parser,
takes_value(false),
default_value("false"),
display_order(5)
)]
#[clap(short('l'), long, display_order(5))]
force_launch_plugin: bool,
/// If launching a new plugin, skip cache and force-compile the plugin
#[clap(
short('s'),
long,
value_parser,
takes_value(false),
default_value("false"),
display_order(6)
)]
#[clap(short('s'), long, display_order(6))]
skip_plugin_cache: bool,
/// If launching a plugin, should it be floating or not, defaults to floating
#[clap(short('f'), long, value_parser, display_order(7))]
@@ -1556,7 +1400,7 @@ tail -f /tmp/my-live-logfile | zellij action pipe --name logs --plugin https://e
short('i'),
long,
value_parser,
conflicts_with("floating-plugin"),
conflicts_with("floating_plugin"),
display_order(8)
)]
in_place_plugin: Option<bool>,
@@ -1705,7 +1549,7 @@ tail -f /tmp/my-live-logfile | zellij action pipe --name logs --plugin https://e
#[clap(long)]
pane_id: Option<String>,
/// Layout to apply when switching to the session (relative paths start at layout-dir)
#[clap(short, long, value_parser, conflicts_with = "layout-string")]
#[clap(short, long, value_parser, conflicts_with = "layout_string")]
layout: Option<PathBuf>,
/// Raw KDL layout string to use directly
#[clap(long, value_parser, conflicts_with = "layout")]
+3 -3
View File
@@ -9,7 +9,7 @@ pub use crate::input::options::PaneFrameStyle;
use crate::pane_size::{PaneGeom, Size};
use crate::position::Position;
use crate::shared::{colors as default_colors, eightbit_to_rgb};
use clap::ArgEnum;
use clap::ValueEnum;
use serde::{Deserialize, Serialize};
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use std::fmt;
@@ -1152,7 +1152,7 @@ impl PluginPermission {
EnumIter,
Serialize,
Deserialize,
ArgEnum,
ValueEnum,
PartialOrd,
Ord,
)]
@@ -3187,7 +3187,7 @@ impl OriginatingPlugin {
}
}
#[derive(ArgEnum, Deserialize, Serialize, Debug, Clone, Copy, PartialEq, Eq)]
#[derive(ValueEnum, Deserialize, Serialize, Debug, Clone, Copy, PartialEq, Eq)]
pub enum WebSharing {
#[serde(alias = "on")]
On,
+1 -1
View File
@@ -44,7 +44,7 @@ pub struct Config {
pub struct KdlError {
pub error_message: String,
#[serde(skip)]
pub src: Option<NamedSource>,
pub src: Option<NamedSource<String>>,
pub offset: Option<usize>,
pub len: Option<usize>,
pub help_message: Option<String>,
+13 -13
View File
@@ -1,14 +1,14 @@
//! Handles cli and configuration options
use crate::cli::Command;
use crate::data::{InputMode, WebSharing};
use clap::{ArgEnum, Args};
use clap::{Args, ValueEnum};
use serde::{Deserialize, Serialize};
use std::path::PathBuf;
use std::str::FromStr;
use std::net::IpAddr;
#[derive(Copy, Clone, Debug, PartialEq, Deserialize, Serialize, ArgEnum)]
#[derive(Copy, Clone, Debug, PartialEq, Deserialize, Serialize, ValueEnum)]
pub enum OnForceClose {
#[serde(alias = "quit")]
Quit,
@@ -16,7 +16,7 @@ pub enum OnForceClose {
Detach,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Deserialize, Serialize, ArgEnum)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Deserialize, Serialize, ValueEnum)]
pub enum MobileLayoutConfiguration {
#[serde(alias = "web")]
Web,
@@ -75,7 +75,7 @@ impl MobileLayoutConfiguration {
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Deserialize, Serialize, ArgEnum)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, Deserialize, Serialize, ValueEnum)]
pub enum NestedSessionHandling {
#[serde(alias = "ask")]
Ask,
@@ -124,7 +124,7 @@ impl FromStr for OnForceClose {
}
}
#[derive(ArgEnum, Clone, Copy, Debug, PartialEq, Eq, Deserialize, Serialize)]
#[derive(ValueEnum, Clone, Copy, Debug, PartialEq, Eq, Deserialize, Serialize)]
#[serde(rename_all = "lowercase")]
pub enum PaneFrameStyle {
Full,
@@ -199,7 +199,7 @@ pub struct Options {
#[clap(long, value_parser)]
pub theme_light: Option<String>,
/// Set the default mode
#[clap(long, arg_enum, hide_possible_values = true, value_parser)]
#[clap(long, value_enum, hide_possible_values = true, value_parser)]
pub default_mode: Option<InputMode>,
/// Set the default shell
#[clap(long, value_parser)]
@@ -227,7 +227,7 @@ pub struct Options {
#[serde(default)]
/// Set display of the pane frames (true or false)
pub pane_frames: Option<bool>,
#[clap(long, arg_enum, hide_possible_values = true, value_parser)]
#[clap(long, value_enum, hide_possible_values = true, value_parser)]
#[serde(default)]
pub pane_frame_style: Option<PaneFrameStyle>,
#[clap(long, value_parser)]
@@ -235,7 +235,7 @@ pub struct Options {
/// Mirror session when multiple users are connected (true or false)
pub mirror_session: Option<bool>,
/// Set behaviour on force close (quit or detach)
#[clap(long, arg_enum, hide_possible_values = true, value_parser)]
#[clap(long, value_enum, hide_possible_values = true, value_parser)]
pub on_force_close: Option<OnForceClose>,
#[clap(long, value_parser)]
pub scroll_buffer_size: Option<usize>,
@@ -248,9 +248,9 @@ pub struct Options {
/// OSC52 destination clipboard
#[clap(
long,
arg_enum,
value_enum,
ignore_case = true,
conflicts_with = "copy-command",
conflicts_with = "copy_command",
value_parser
)]
#[serde(default)]
@@ -433,7 +433,7 @@ pub struct Options {
pub client_async_worker_tasks: Option<usize>,
/// When a newly-attaching client should land in the mobile UI plugin (web, always, never)
#[clap(long, arg_enum, hide_possible_values = true, value_parser)]
#[clap(long, value_enum, hide_possible_values = true, value_parser)]
#[serde(default)]
pub mobile_layout: Option<MobileLayoutConfiguration>,
@@ -449,12 +449,12 @@ pub struct Options {
/// How to handle a nested Zellij session detected inside a pane
/// (ask, fullscreen, descend, never)
#[clap(long, arg_enum, hide_possible_values = true, value_parser)]
#[clap(long, value_enum, hide_possible_values = true, value_parser)]
#[serde(default)]
pub nested_session_handling: Option<NestedSessionHandling>,
}
#[derive(ArgEnum, Deserialize, Serialize, Debug, Clone, Copy, PartialEq)]
#[derive(ValueEnum, Deserialize, Serialize, Debug, Clone, Copy, PartialEq)]
pub enum Clipboard {
#[serde(alias = "system")]
System,
@@ -1,6 +1,5 @@
---
source: zellij-utils/src/input/./unit/layout_test.rs
assertion_line: 1015
expression: "format!(\"{:?}\", layout_error)"
expression: "normalize_layout_debug(format!(\"{:?}\", layout_error))"
---
KdlError(KdlError { error_message: "Only one tab can be focused", src: Some(NamedSource { name: "layout_file_name", source: "<redacted>"), offset: Some(0), len: Some(98), help_message: Some("For more information, please see our layout guide: https://zellij.dev/documentation/creating-a-layout.html") })
KdlError(KdlError { error_message: "Only one tab can be focused", src: Some(NamedSource { name: "layout_file_name", source: "<redacted>", language: None), offset: Some(0), len: Some(98), help_message: Some("For more information, please see our layout guide: https://zellij.dev/documentation/creating-a-layout.html") })
@@ -1,6 +1,5 @@
---
source: zellij-utils/src/input/./unit/layout_test.rs
assertion_line: 901
expression: "format!(\"{:?}\", layout_error)"
expression: "normalize_layout_debug(format!(\"{:?}\", layout_error))"
---
KdlError(KdlError { error_message: "Only one layout node per file allowed", src: Some(NamedSource { name: "layout_file_name", source: "<redacted>"), offset: Some(0), len: Some(31), help_message: Some("For more information, please see our layout guide: https://zellij.dev/documentation/creating-a-layout.html") })
KdlError(KdlError { error_message: "Only one layout node per file allowed", src: Some(NamedSource { name: "layout_file_name", source: "<redacted>", language: None), offset: Some(0), len: Some(31), help_message: Some("For more information, please see our layout guide: https://zellij.dev/documentation/creating-a-layout.html") })
@@ -1,6 +1,5 @@
---
source: zellij-utils/src/input/./unit/layout_test.rs
assertion_line: 985
expression: "format!(\"{:?}\", layout_error)"
expression: "normalize_layout_debug(format!(\"{:?}\", layout_error))"
---
KdlError(KdlError { error_message: "Pane templates must have a name", src: Some(NamedSource { name: "layout_file_name", source: "<redacted>"), offset: Some(30), len: Some(96), help_message: Some("For more information, please see our layout guide: https://zellij.dev/documentation/creating-a-layout.html") })
KdlError(KdlError { error_message: "Pane templates must have a name", src: Some(NamedSource { name: "layout_file_name", source: "<redacted>", language: None), offset: Some(30), len: Some(96), help_message: Some("For more information, please see our layout guide: https://zellij.dev/documentation/creating-a-layout.html") })
@@ -1,6 +1,5 @@
---
source: zellij-utils/src/input/./unit/layout_test.rs
assertion_line: 1002
expression: "format!(\"{:?}\", layout_error)"
expression: "normalize_layout_debug(format!(\"{:?}\", layout_error))"
---
KdlError(KdlError { error_message: "Tab templates must have a name", src: Some(NamedSource { name: "layout_file_name", source: "<redacted>"), offset: Some(30), len: Some(95), help_message: Some("For more information, please see our layout guide: https://zellij.dev/documentation/creating-a-layout.html") })
KdlError(KdlError { error_message: "Tab templates must have a name", src: Some(NamedSource { name: "layout_file_name", source: "<redacted>", language: None), offset: Some(30), len: Some(95), help_message: Some("For more information, please see our layout guide: https://zellij.dev/documentation/creating-a-layout.html") })
@@ -1,6 +1,5 @@
---
source: zellij-utils/src/input/./unit/layout_test.rs
assertion_line: 916
expression: "format!(\"{:?}\", layout_error)"
expression: "normalize_layout_debug(format!(\"{:?}\", layout_error))"
---
KdlError(KdlError { error_message: "Unknown layout node: 'i_am_not_a_proper_node'", src: Some(NamedSource { name: "layout_file_name", source: "<redacted>"), offset: Some(47), len: Some(22), help_message: Some("For more information, please see our layout guide: https://zellij.dev/documentation/creating-a-layout.html") })
KdlError(KdlError { error_message: "Unknown layout node: 'i_am_not_a_proper_node'", src: Some(NamedSource { name: "layout_file_name", source: "<redacted>", language: None), offset: Some(47), len: Some(22), help_message: Some("For more information, please see our layout guide: https://zellij.dev/documentation/creating-a-layout.html") })
@@ -1,6 +1,5 @@
---
source: zellij-utils/src/input/./unit/layout_test.rs
assertion_line: 929
expression: "format!(\"{:?}\", layout_error)"
expression: "normalize_layout_debug(format!(\"{:?}\", layout_error))"
---
KdlError(KdlError { error_message: "Unknown pane property: spit_size", src: Some(NamedSource { name: "layout_file_name", source: "<redacted>"), offset: Some(35), len: Some(11), help_message: Some("For more information, please see our layout guide: https://zellij.dev/documentation/creating-a-layout.html") })
KdlError(KdlError { error_message: "Unknown pane property: spit_size", src: Some(NamedSource { name: "layout_file_name", source: "<redacted>", language: None), offset: Some(35), len: Some(11), help_message: Some("For more information, please see our layout guide: https://zellij.dev/documentation/creating-a-layout.html") })
@@ -1,6 +1,5 @@
---
source: zellij-utils/src/input/./unit/layout_test.rs
assertion_line: 942
expression: "format!(\"{:?}\", layout_error)"
expression: "normalize_layout_debug(format!(\"{:?}\", layout_error))"
---
KdlError(KdlError { error_message: "Unknown pane property: spit_size", src: Some(NamedSource { name: "layout_file_name", source: "<redacted>"), offset: Some(68), len: Some(11), help_message: Some("For more information, please see our layout guide: https://zellij.dev/documentation/creating-a-layout.html") })
KdlError(KdlError { error_message: "Unknown pane property: spit_size", src: Some(NamedSource { name: "layout_file_name", source: "<redacted>", language: None), offset: Some(68), len: Some(11), help_message: Some("For more information, please see our layout guide: https://zellij.dev/documentation/creating-a-layout.html") })
@@ -1,6 +1,5 @@
---
source: zellij-utils/src/input/./unit/layout_test.rs
assertion_line: 955
expression: "format!(\"{:?}\", layout_error)"
expression: "normalize_layout_debug(format!(\"{:?}\", layout_error))"
---
KdlError(KdlError { error_message: "Invalid tab property 'spit_size'", src: Some(NamedSource { name: "layout_file_name", source: "<redacted>"), offset: Some(30), len: Some(15), help_message: Some("For more information, please see our layout guide: https://zellij.dev/documentation/creating-a-layout.html") })
KdlError(KdlError { error_message: "Invalid tab property 'spit_size'", src: Some(NamedSource { name: "layout_file_name", source: "<redacted>", language: None), offset: Some(30), len: Some(15), help_message: Some("For more information, please see our layout guide: https://zellij.dev/documentation/creating-a-layout.html") })
@@ -1,6 +1,5 @@
---
source: zellij-utils/src/input/./unit/layout_test.rs
assertion_line: 968
expression: "format!(\"{:?}\", layout_error)"
expression: "normalize_layout_debug(format!(\"{:?}\", layout_error))"
---
KdlError(KdlError { error_message: "Invalid tab property 'spit_size'", src: Some(NamedSource { name: "layout_file_name", source: "<redacted>"), offset: Some(30), len: Some(48), help_message: Some("For more information, please see our layout guide: https://zellij.dev/documentation/creating-a-layout.html") })
KdlError(KdlError { error_message: "Invalid tab property 'spit_size'", src: Some(NamedSource { name: "layout_file_name", source: "<redacted>", language: None), offset: Some(30), len: Some(48), help_message: Some("For more information, please see our layout guide: https://zellij.dev/documentation/creating-a-layout.html") })
+12 -2
View File
@@ -1,8 +1,18 @@
use crate::data::{Direction, KeyWithModifier};
use crate::nested_session_contract::nested_session_contract as proto;
use base64::alphabet::STANDARD as BASE64_STANDARD_ALPHABET;
use base64::engine::general_purpose::{
GeneralPurpose, GeneralPurposeConfig, STANDARD as BASE64_STANDARD,
};
use base64::engine::{DecodePaddingMode, Engine as _};
use prost::Message;
use std::str::FromStr;
const BASE64_DECODER: GeneralPurpose = GeneralPurpose::new(
&BASE64_STANDARD_ALPHABET,
GeneralPurposeConfig::new().with_decode_padding_mode(DecodePaddingMode::Indifferent),
);
pub const NESTED_DCS_PARAM: u16 = 26661;
pub const NESTED_FRAME_HEADER: &[u8] = b"\x1bP26661n";
pub const NESTED_FRAME_TERMINATOR: &[u8] = b"\x1b\\";
@@ -244,7 +254,7 @@ pub fn encode_frame(message: &NestedSessionMessage) -> Vec<u8> {
}
pub fn encode_frame_from_payload(payload_bytes: &[u8]) -> Vec<u8> {
let encoded = base64::encode(payload_bytes);
let encoded = BASE64_STANDARD.encode(payload_bytes);
let mut frame = Vec::with_capacity(
NESTED_FRAME_HEADER.len() + encoded.len() + NESTED_FRAME_TERMINATOR.len(),
);
@@ -255,7 +265,7 @@ pub fn encode_frame_from_payload(payload_bytes: &[u8]) -> Vec<u8> {
}
pub fn decode_base64(encoded: &[u8]) -> Option<Vec<u8>> {
base64::decode(encoded).ok()
BASE64_DECODER.decode(encoded).ok()
}
const MAX_PARTIAL_FRAME_BYTES: usize = 1024 * 1024;
+2 -3
View File
@@ -14,7 +14,7 @@ use crate::{
options::Options,
},
};
use clap::{Args, IntoApp};
use clap::{Args, CommandFactory};
use clap_complete::Shell;
use log::info;
use serde::{Deserialize, Serialize};
@@ -271,8 +271,7 @@ pub struct Setup {
value_name = "DIR",
value_parser,
exclusive = true,
min_values = 0,
max_values = 1
num_args(0..=1)
)]
pub dump_plugins: Option<Option<PathBuf>>,
+1 -1
View File
@@ -33,7 +33,7 @@ pub fn set_permissions(_path: &std::path::Path, _mode: u32) -> std::io::Result<(
}
pub fn ansi_len(s: &str) -> usize {
from_utf8(&strip(s).unwrap()).unwrap().width()
from_utf8(&strip(s)).unwrap().width()
}
pub fn clean_string_from_control_and_linebreak(input: &str) -> String {