mirror of
https://github.com/asciinema/asciinema.git
synced 2025-12-16 11:48:13 +01:00
119 lines
3.2 KiB
Rust
119 lines
3.2 KiB
Rust
use crate::config::Config;
|
|
use crate::locale;
|
|
use crate::logger;
|
|
use crate::pty;
|
|
use crate::streamer::{self, KeyBindings};
|
|
use crate::tty;
|
|
use anyhow::{anyhow, Result};
|
|
use clap::Args;
|
|
use std::fs;
|
|
use std::net::SocketAddr;
|
|
use std::path::PathBuf;
|
|
|
|
#[derive(Debug, Args)]
|
|
pub struct Cli {
|
|
/// Enable input capture
|
|
#[arg(long, short = 'I', alias = "stdin")]
|
|
input: bool,
|
|
|
|
/// Command to stream [default: $SHELL]
|
|
#[arg(short, long)]
|
|
command: Option<String>,
|
|
|
|
/// HTTP listen address
|
|
#[clap(short, long, default_value = "127.0.0.1:8080")]
|
|
listen_addr: SocketAddr,
|
|
|
|
/// Override terminal size for the session
|
|
#[arg(long, value_name = "COLSxROWS")]
|
|
tty_size: Option<pty::WinsizeOverride>,
|
|
|
|
/// Log file path
|
|
#[arg(long)]
|
|
log_file: Option<PathBuf>,
|
|
}
|
|
|
|
impl Cli {
|
|
pub fn run(self, config: &Config) -> Result<()> {
|
|
locale::check_utf8_locale()?;
|
|
|
|
let command = self.get_command(config);
|
|
let keys = get_key_bindings(config)?;
|
|
let notifier = super::get_notifier(config);
|
|
let record_input = self.input || config.cmd_stream_input();
|
|
let exec_command = super::build_exec_command(command.as_ref().cloned());
|
|
let exec_extra_env = super::build_exec_extra_env();
|
|
let mut streamer = streamer::Streamer::new(self.listen_addr, record_input, keys, notifier);
|
|
|
|
logger::info!(
|
|
"Streaming session started, web server listening on http://{}",
|
|
&self.listen_addr
|
|
);
|
|
|
|
if command.is_none() {
|
|
logger::info!("Press <ctrl+d> or type 'exit' to end");
|
|
}
|
|
|
|
{
|
|
let mut tty: Box<dyn tty::Tty> = if let Ok(dev_tty) = tty::DevTty::open() {
|
|
Box::new(dev_tty)
|
|
} else {
|
|
logger::info!("TTY not available, streaming in headless mode");
|
|
Box::new(tty::NullTty::open()?)
|
|
};
|
|
|
|
self.init_logging()?;
|
|
|
|
pty::exec(
|
|
&exec_command,
|
|
&exec_extra_env,
|
|
&mut *tty,
|
|
self.tty_size,
|
|
&mut streamer,
|
|
)?;
|
|
}
|
|
|
|
logger::info!("Streaming session ended");
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn get_command(&self, config: &Config) -> Option<String> {
|
|
self.command
|
|
.as_ref()
|
|
.cloned()
|
|
.or(config.cmd_stream_command())
|
|
}
|
|
|
|
fn init_logging(&self) -> Result<()> {
|
|
if let Some(path) = self.log_file.as_ref() {
|
|
let file = fs::OpenOptions::new()
|
|
.create(true)
|
|
.append(true)
|
|
.open(path)
|
|
.map_err(|e| anyhow!("cannot open log file {}: {}", path.to_string_lossy(), e))?;
|
|
|
|
tracing_subscriber::fmt()
|
|
.with_env_filter(tracing_subscriber::EnvFilter::from_default_env())
|
|
.with_writer(file)
|
|
.init();
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
fn get_key_bindings(config: &Config) -> Result<KeyBindings> {
|
|
let mut keys = KeyBindings::default();
|
|
|
|
if let Some(key) = config.cmd_stream_prefix_key()? {
|
|
keys.prefix = key;
|
|
}
|
|
|
|
if let Some(key) = config.cmd_stream_pause_key()? {
|
|
keys.pause = key;
|
|
}
|
|
|
|
Ok(keys)
|
|
}
|