mirror of
https://github.com/wez/wezterm.git
synced 2024-12-23 13:21:38 +03:00
write into tmux
This commit is contained in:
parent
3054fd045e
commit
1a73a2feaa
@ -46,12 +46,13 @@ pub(crate) struct TmuxTab {
|
||||
pub panes: HashSet<TmuxPaneId>, // tmux panes within tmux window
|
||||
}
|
||||
|
||||
pub(crate) type TmuxCmdQueue = VecDeque<Box<dyn TmuxCommand>>;
|
||||
pub(crate) struct TmuxDomainState {
|
||||
pub pane_id: PaneId,
|
||||
pub domain_id: DomainId,
|
||||
// parser: RefCell<Parser>,
|
||||
state: RefCell<State>,
|
||||
pub cmd_queue: RefCell<VecDeque<Box<dyn TmuxCommand>>>,
|
||||
pub cmd_queue: Arc<Mutex<TmuxCmdQueue>>,
|
||||
pub gui_window: RefCell<Option<MuxWindowBuilder>>,
|
||||
pub gui_tabs: RefCell<Vec<TmuxTab>>,
|
||||
pub remote_panes: RefCell<HashMap<TmuxPaneId, RefTmuxRemotePane>>,
|
||||
@ -73,7 +74,8 @@ impl TmuxDomainState {
|
||||
*self.state.borrow_mut() = State::Idle;
|
||||
}
|
||||
State::WaitingForResponse => {
|
||||
let cmd = self.cmd_queue.borrow_mut().pop_front().unwrap();
|
||||
let mut cmd_queue = self.cmd_queue.as_ref().lock().unwrap();
|
||||
let cmd = cmd_queue.pop_front().unwrap();
|
||||
let domain_id = self.domain_id;
|
||||
*self.state.borrow_mut() = State::Idle;
|
||||
let resp = response.clone();
|
||||
@ -120,17 +122,9 @@ impl TmuxDomainState {
|
||||
}
|
||||
|
||||
// send pending commands to tmux
|
||||
if *self.state.borrow() == State::Idle && !self.cmd_queue.borrow().is_empty() {
|
||||
let domain_id = self.domain_id;
|
||||
promise::spawn::spawn(async move {
|
||||
let mux = Mux::get().expect("to be called on main thread");
|
||||
if let Some(domain) = mux.get_domain(domain_id) {
|
||||
if let Some(tmux_domain) = domain.downcast_ref::<TmuxDomain>() {
|
||||
tmux_domain.send_next_command();
|
||||
}
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
let cmd_queue = self.cmd_queue.as_ref().lock().unwrap();
|
||||
if *self.state.borrow() == State::Idle && !cmd_queue.is_empty() {
|
||||
TmuxDomainState::kick_off(self.domain_id);
|
||||
}
|
||||
}
|
||||
|
||||
@ -138,7 +132,8 @@ impl TmuxDomainState {
|
||||
if *self.state.borrow() != State::Idle {
|
||||
return;
|
||||
}
|
||||
if let Some(first) = self.cmd_queue.borrow().front() {
|
||||
let cmd_queue = self.cmd_queue.as_ref().lock().unwrap();
|
||||
if let Some(first) = cmd_queue.front() {
|
||||
let cmd = first.get_command();
|
||||
log::error!("sending cmd {:?}", cmd);
|
||||
let mux = Mux::get().expect("to be called on main thread");
|
||||
@ -150,6 +145,18 @@ impl TmuxDomainState {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn kick_off(domain_id: usize) {
|
||||
promise::spawn::spawn_into_main_thread(async move {
|
||||
let mux = Mux::get().expect("to be called on main thread");
|
||||
if let Some(domain) = mux.get_domain(domain_id) {
|
||||
if let Some(tmux_domain) = domain.downcast_ref::<TmuxDomain>() {
|
||||
tmux_domain.send_next_command();
|
||||
}
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
|
||||
pub fn create_gui_window(&self) {
|
||||
if self.gui_window.borrow().is_none() {
|
||||
let mux = Mux::get().expect("should be call at main thread");
|
||||
@ -174,12 +181,13 @@ impl TmuxDomain {
|
||||
pane_id,
|
||||
// parser,
|
||||
state: RefCell::new(State::WaitForInitialGuard),
|
||||
cmd_queue: RefCell::new(cmd_queue),
|
||||
cmd_queue: Arc::new(Mutex::new(cmd_queue)),
|
||||
gui_window: RefCell::new(None),
|
||||
gui_tabs: RefCell::new(Vec::default()),
|
||||
remote_panes: RefCell::new(HashMap::default()),
|
||||
tmux_session: RefCell::new(None),
|
||||
});
|
||||
|
||||
Self { inner }
|
||||
}
|
||||
|
||||
|
@ -9,11 +9,13 @@ use crate::Pane;
|
||||
use anyhow::anyhow;
|
||||
use portable_pty::{MasterPty, PtySize};
|
||||
use std::collections::HashSet;
|
||||
use std::fmt::Debug;
|
||||
use std::fmt::Write;
|
||||
use std::rc::Rc;
|
||||
use std::sync::{Arc, Condvar, Mutex};
|
||||
use tmux_cc::*;
|
||||
|
||||
pub(crate) trait TmuxCommand: Send {
|
||||
pub(crate) trait TmuxCommand: Send + Debug {
|
||||
fn get_command(&self) -> String;
|
||||
fn process_result(&self, domain_id: DomainId, result: &Guarded) -> anyhow::Result<()>;
|
||||
}
|
||||
@ -118,7 +120,9 @@ impl TmuxDomainState {
|
||||
}
|
||||
|
||||
let pane_pty = TmuxPty {
|
||||
domain_id: self.domain_id,
|
||||
rx: channel.1.clone(),
|
||||
cmd_queue: self.cmd_queue.clone(),
|
||||
active_lock: active_lock.clone(),
|
||||
master_pane: ref_pane,
|
||||
};
|
||||
@ -170,6 +174,7 @@ impl TmuxDomainState {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct ListAllPanes;
|
||||
impl TmuxCommand for ListAllPanes {
|
||||
fn get_command(&self) -> String {
|
||||
@ -250,6 +255,7 @@ impl TmuxCommand for ListAllPanes {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct CapturePane(TmuxPaneId);
|
||||
impl TmuxCommand for CapturePane {
|
||||
fn get_command(&self) -> String {
|
||||
@ -276,3 +282,23 @@ impl TmuxCommand for CapturePane {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct SendKeys {
|
||||
pub keys: Vec<u8>,
|
||||
pub pane: TmuxPaneId,
|
||||
}
|
||||
impl TmuxCommand for SendKeys {
|
||||
fn get_command(&self) -> String {
|
||||
let mut s = String::new();
|
||||
for &byte in self.keys.iter() {
|
||||
write!(&mut s, "0x{:X}\r", byte).expect("unable to write key");
|
||||
}
|
||||
format!("send-keys -t {} {}", self.pane, s)
|
||||
// FIXME: An unexpected duplicated command will prompt next line, why?
|
||||
}
|
||||
|
||||
fn process_result(&self, _domain_id: DomainId, _result: &Guarded) -> anyhow::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,7 @@
|
||||
use crate::{
|
||||
tmux::{RefTmuxRemotePane, TmuxCmdQueue, TmuxDomainState},
|
||||
tmux_commands::SendKeys,
|
||||
};
|
||||
use flume;
|
||||
use portable_pty::{Child, ExitStatus, MasterPty};
|
||||
use std::{
|
||||
@ -5,8 +9,6 @@ use std::{
|
||||
sync::{Arc, Condvar, Mutex},
|
||||
};
|
||||
|
||||
use crate::tmux::RefTmuxRemotePane;
|
||||
|
||||
pub(crate) struct TmuxReader {
|
||||
rx: flume::Receiver<String>,
|
||||
}
|
||||
@ -27,15 +29,26 @@ impl Read for TmuxReader {
|
||||
// A local tmux pane(tab) based on a tmux pty
|
||||
#[derive(Debug, Clone)]
|
||||
pub(crate) struct TmuxPty {
|
||||
pub domain_id: usize,
|
||||
pub master_pane: RefTmuxRemotePane,
|
||||
pub rx: flume::Receiver<String>,
|
||||
pub cmd_queue: Arc<Mutex<TmuxCmdQueue>>,
|
||||
pub active_lock: Arc<(Mutex<bool>, Condvar)>,
|
||||
// TODO: wx
|
||||
}
|
||||
|
||||
impl Write for TmuxPty {
|
||||
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
|
||||
// TODO: write to wx of pty
|
||||
let pane_id = {
|
||||
let pane_lock = self.master_pane.lock().unwrap();
|
||||
pane_lock.pane_id
|
||||
};
|
||||
log::info!("pane:{}, content:{:?}", &pane_id, buf);
|
||||
let mut cmd_queue = self.cmd_queue.lock().unwrap();
|
||||
cmd_queue.push_back(Box::new(SendKeys {
|
||||
pane: pane_id,
|
||||
keys: buf.to_vec(),
|
||||
}));
|
||||
TmuxDomainState::kick_off(self.domain_id);
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
@ -91,8 +104,10 @@ impl MasterPty for TmuxPty {
|
||||
|
||||
fn try_clone_writer(&self) -> Result<Box<dyn std::io::Write + Send>, anyhow::Error> {
|
||||
Ok(Box::new(TmuxPty {
|
||||
domain_id: self.domain_id,
|
||||
master_pane: self.master_pane.clone(),
|
||||
rx: self.rx.clone(),
|
||||
cmd_queue: self.cmd_queue.clone(),
|
||||
active_lock: self.active_lock.clone(),
|
||||
}))
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user