mod emit;
mod expand;
mod keys;
mod locate;
mod merge;
mod parse;
mod values;
use std::path::PathBuf;
use std::time::Duration;
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum ConfigError {
#[error("cannot read workspace file {}", path.display())]
Read {
path: PathBuf,
source: std::io::Error,
},
#[error("workspace configuration is not valid YAML at line {line}, column {column}: {reason}")]
Yaml {
line: usize,
column: usize,
reason: String,
},
#[error("expected exactly one workspace document, found {found}")]
DocumentCount {
found: usize,
},
#[error("workspace configuration is invalid at line {line}, column {column}: {path} {reason}")]
Invalid {
path: String,
line: usize,
column: usize,
reason: String,
},
}
impl From<yaml_rust2::ScanError> for ConfigError {
fn from(error: yaml_rust2::ScanError) -> Self {
let mark = error.marker();
Self::Yaml {
line: mark.line(),
column: mark.col() + 1,
reason: error.info().to_owned(),
}
}
}
#[derive(Debug)]
struct Problem {
path: String,
reason: String,
}
impl Problem {
fn new(path: impl Into<String>, reason: impl Into<String>) -> Self {
Self {
path: path.into(),
reason: reason.into(),
}
}
fn locate(self, source: &str) -> ConfigError {
let (line, column) = locate::locate(source, &self.path);
ConfigError::Invalid {
path: self.path,
line,
column,
reason: self.reason,
}
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Workspace {
pub session_name: String,
pub start_directory: Option<PathBuf>,
pub environment: Vec<(String, String)>,
pub options: Vec<(String, String)>,
pub global_options: Vec<(String, String)>,
pub shell_command_before: Vec<ShellCommand>,
pub suppress_history: bool,
pub windows: Vec<WindowConfig>,
pub unsupported_keys: Vec<String>,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct WindowConfig {
pub window_name: Option<String>,
pub window_index: Option<i32>,
pub window_shell: Option<String>,
pub environment: Vec<(String, String)>,
pub layout: Option<String>,
pub start_directory: Option<PathBuf>,
pub focus: bool,
pub options: Vec<(String, String)>,
pub shell_command_before: Vec<ShellCommand>,
pub suppress_history: Option<bool>,
pub panes: Vec<PaneConfig>,
pub unsupported_keys: Vec<String>,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct PaneConfig {
pub shell_command_before: Vec<ShellCommand>,
pub shell_commands: Vec<ShellCommand>,
pub environment: Option<Vec<(String, String)>>,
pub start_directory: Option<PathBuf>,
pub focus: bool,
pub shell: Option<String>,
pub enter: bool,
pub sleep_before: Option<Duration>,
pub sleep_after: Option<Duration>,
pub suppress_history: Option<bool>,
pub unsupported_keys: Vec<String>,
}
impl Default for PaneConfig {
fn default() -> Self {
Self {
shell_command_before: Vec::new(),
shell_commands: Vec::new(),
environment: None,
start_directory: None,
focus: false,
shell: None,
enter: true,
sleep_before: None,
sleep_after: None,
suppress_history: None,
unsupported_keys: Vec::new(),
}
}
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct ShellCommand {
pub cmd: String,
pub enter: Option<bool>,
pub sleep_before: Option<Duration>,
pub sleep_after: Option<Duration>,
}
impl ShellCommand {
#[must_use]
pub fn new(cmd: impl Into<String>) -> Self {
Self {
cmd: cmd.into(),
..Self::default()
}
}
const fn is_plain(&self) -> bool {
self.enter.is_none() && self.sleep_before.is_none() && self.sleep_after.is_none()
}
}