mirror of
https://github.com/wez/wezterm.git
synced 2024-12-23 21:32:13 +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 panes: HashSet<TmuxPaneId>, // tmux panes within tmux window
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) type TmuxCmdQueue = VecDeque<Box<dyn TmuxCommand>>;
|
||||||
pub(crate) struct TmuxDomainState {
|
pub(crate) struct TmuxDomainState {
|
||||||
pub pane_id: PaneId,
|
pub pane_id: PaneId,
|
||||||
pub domain_id: DomainId,
|
pub domain_id: DomainId,
|
||||||
// parser: RefCell<Parser>,
|
// parser: RefCell<Parser>,
|
||||||
state: RefCell<State>,
|
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_window: RefCell<Option<MuxWindowBuilder>>,
|
||||||
pub gui_tabs: RefCell<Vec<TmuxTab>>,
|
pub gui_tabs: RefCell<Vec<TmuxTab>>,
|
||||||
pub remote_panes: RefCell<HashMap<TmuxPaneId, RefTmuxRemotePane>>,
|
pub remote_panes: RefCell<HashMap<TmuxPaneId, RefTmuxRemotePane>>,
|
||||||
@ -73,7 +74,8 @@ impl TmuxDomainState {
|
|||||||
*self.state.borrow_mut() = State::Idle;
|
*self.state.borrow_mut() = State::Idle;
|
||||||
}
|
}
|
||||||
State::WaitingForResponse => {
|
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;
|
let domain_id = self.domain_id;
|
||||||
*self.state.borrow_mut() = State::Idle;
|
*self.state.borrow_mut() = State::Idle;
|
||||||
let resp = response.clone();
|
let resp = response.clone();
|
||||||
@ -120,17 +122,9 @@ impl TmuxDomainState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// send pending commands to tmux
|
// send pending commands to tmux
|
||||||
if *self.state.borrow() == State::Idle && !self.cmd_queue.borrow().is_empty() {
|
let cmd_queue = self.cmd_queue.as_ref().lock().unwrap();
|
||||||
let domain_id = self.domain_id;
|
if *self.state.borrow() == State::Idle && !cmd_queue.is_empty() {
|
||||||
promise::spawn::spawn(async move {
|
TmuxDomainState::kick_off(self.domain_id);
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,7 +132,8 @@ impl TmuxDomainState {
|
|||||||
if *self.state.borrow() != State::Idle {
|
if *self.state.borrow() != State::Idle {
|
||||||
return;
|
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();
|
let cmd = first.get_command();
|
||||||
log::error!("sending cmd {:?}", cmd);
|
log::error!("sending cmd {:?}", cmd);
|
||||||
let mux = Mux::get().expect("to be called on main thread");
|
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) {
|
pub fn create_gui_window(&self) {
|
||||||
if self.gui_window.borrow().is_none() {
|
if self.gui_window.borrow().is_none() {
|
||||||
let mux = Mux::get().expect("should be call at main thread");
|
let mux = Mux::get().expect("should be call at main thread");
|
||||||
@ -174,12 +181,13 @@ impl TmuxDomain {
|
|||||||
pane_id,
|
pane_id,
|
||||||
// parser,
|
// parser,
|
||||||
state: RefCell::new(State::WaitForInitialGuard),
|
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_window: RefCell::new(None),
|
||||||
gui_tabs: RefCell::new(Vec::default()),
|
gui_tabs: RefCell::new(Vec::default()),
|
||||||
remote_panes: RefCell::new(HashMap::default()),
|
remote_panes: RefCell::new(HashMap::default()),
|
||||||
tmux_session: RefCell::new(None),
|
tmux_session: RefCell::new(None),
|
||||||
});
|
});
|
||||||
|
|
||||||
Self { inner }
|
Self { inner }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,11 +9,13 @@ use crate::Pane;
|
|||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use portable_pty::{MasterPty, PtySize};
|
use portable_pty::{MasterPty, PtySize};
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
use std::fmt::Debug;
|
||||||
|
use std::fmt::Write;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::{Arc, Condvar, Mutex};
|
use std::sync::{Arc, Condvar, Mutex};
|
||||||
use tmux_cc::*;
|
use tmux_cc::*;
|
||||||
|
|
||||||
pub(crate) trait TmuxCommand: Send {
|
pub(crate) trait TmuxCommand: Send + Debug {
|
||||||
fn get_command(&self) -> String;
|
fn get_command(&self) -> String;
|
||||||
fn process_result(&self, domain_id: DomainId, result: &Guarded) -> anyhow::Result<()>;
|
fn process_result(&self, domain_id: DomainId, result: &Guarded) -> anyhow::Result<()>;
|
||||||
}
|
}
|
||||||
@ -118,7 +120,9 @@ impl TmuxDomainState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let pane_pty = TmuxPty {
|
let pane_pty = TmuxPty {
|
||||||
|
domain_id: self.domain_id,
|
||||||
rx: channel.1.clone(),
|
rx: channel.1.clone(),
|
||||||
|
cmd_queue: self.cmd_queue.clone(),
|
||||||
active_lock: active_lock.clone(),
|
active_lock: active_lock.clone(),
|
||||||
master_pane: ref_pane,
|
master_pane: ref_pane,
|
||||||
};
|
};
|
||||||
@ -170,6 +174,7 @@ impl TmuxDomainState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub(crate) struct ListAllPanes;
|
pub(crate) struct ListAllPanes;
|
||||||
impl TmuxCommand for ListAllPanes {
|
impl TmuxCommand for ListAllPanes {
|
||||||
fn get_command(&self) -> String {
|
fn get_command(&self) -> String {
|
||||||
@ -250,6 +255,7 @@ impl TmuxCommand for ListAllPanes {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub(crate) struct CapturePane(TmuxPaneId);
|
pub(crate) struct CapturePane(TmuxPaneId);
|
||||||
impl TmuxCommand for CapturePane {
|
impl TmuxCommand for CapturePane {
|
||||||
fn get_command(&self) -> String {
|
fn get_command(&self) -> String {
|
||||||
@ -276,3 +282,23 @@ impl TmuxCommand for CapturePane {
|
|||||||
Ok(())
|
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 flume;
|
||||||
use portable_pty::{Child, ExitStatus, MasterPty};
|
use portable_pty::{Child, ExitStatus, MasterPty};
|
||||||
use std::{
|
use std::{
|
||||||
@ -5,8 +9,6 @@ use std::{
|
|||||||
sync::{Arc, Condvar, Mutex},
|
sync::{Arc, Condvar, Mutex},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::tmux::RefTmuxRemotePane;
|
|
||||||
|
|
||||||
pub(crate) struct TmuxReader {
|
pub(crate) struct TmuxReader {
|
||||||
rx: flume::Receiver<String>,
|
rx: flume::Receiver<String>,
|
||||||
}
|
}
|
||||||
@ -27,15 +29,26 @@ impl Read for TmuxReader {
|
|||||||
// A local tmux pane(tab) based on a tmux pty
|
// A local tmux pane(tab) based on a tmux pty
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub(crate) struct TmuxPty {
|
pub(crate) struct TmuxPty {
|
||||||
|
pub domain_id: usize,
|
||||||
pub master_pane: RefTmuxRemotePane,
|
pub master_pane: RefTmuxRemotePane,
|
||||||
pub rx: flume::Receiver<String>,
|
pub rx: flume::Receiver<String>,
|
||||||
|
pub cmd_queue: Arc<Mutex<TmuxCmdQueue>>,
|
||||||
pub active_lock: Arc<(Mutex<bool>, Condvar)>,
|
pub active_lock: Arc<(Mutex<bool>, Condvar)>,
|
||||||
// TODO: wx
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Write for TmuxPty {
|
impl Write for TmuxPty {
|
||||||
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
|
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)
|
Ok(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,8 +104,10 @@ impl MasterPty for TmuxPty {
|
|||||||
|
|
||||||
fn try_clone_writer(&self) -> Result<Box<dyn std::io::Write + Send>, anyhow::Error> {
|
fn try_clone_writer(&self) -> Result<Box<dyn std::io::Write + Send>, anyhow::Error> {
|
||||||
Ok(Box::new(TmuxPty {
|
Ok(Box::new(TmuxPty {
|
||||||
|
domain_id: self.domain_id,
|
||||||
master_pane: self.master_pane.clone(),
|
master_pane: self.master_pane.clone(),
|
||||||
rx: self.rx.clone(),
|
rx: self.rx.clone(),
|
||||||
|
cmd_queue: self.cmd_queue.clone(),
|
||||||
active_lock: self.active_lock.clone(),
|
active_lock: self.active_lock.clone(),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user