* feat(tab-bar): add option to hide prefix (#2172) * feat(tab-bar): only hide session_name * fix(snapshots): update snapshots with new config-var naming --------- Co-authored-by: Marcel Baur <marcel@baur.gg>
738 lines
24 KiB
Rust
738 lines
24 KiB
Rust
use crate::input::actions::Action;
|
|
use crate::input::config::ConversionError;
|
|
use clap::ArgEnum;
|
|
use serde::{Deserialize, Serialize};
|
|
use std::fmt;
|
|
use std::str::FromStr;
|
|
use strum_macros::{EnumDiscriminants, EnumIter, EnumString, ToString};
|
|
|
|
pub type ClientId = u16; // TODO: merge with crate type?
|
|
|
|
pub fn client_id_to_colors(
|
|
client_id: ClientId,
|
|
colors: Palette,
|
|
) -> Option<(PaletteColor, PaletteColor)> {
|
|
// (primary color, secondary color)
|
|
match client_id {
|
|
1 => Some((colors.magenta, colors.black)),
|
|
2 => Some((colors.blue, colors.black)),
|
|
3 => Some((colors.purple, colors.black)),
|
|
4 => Some((colors.yellow, colors.black)),
|
|
5 => Some((colors.cyan, colors.black)),
|
|
6 => Some((colors.gold, colors.black)),
|
|
7 => Some((colors.red, colors.black)),
|
|
8 => Some((colors.silver, colors.black)),
|
|
9 => Some((colors.pink, colors.black)),
|
|
10 => Some((colors.brown, colors.black)),
|
|
_ => None,
|
|
}
|
|
}
|
|
|
|
pub fn single_client_color(colors: Palette) -> (PaletteColor, PaletteColor) {
|
|
(colors.green, colors.black)
|
|
}
|
|
|
|
// TODO: Add a shortened string representation (beyond `Display::fmt` below) that can be used when
|
|
// screen space is scarce. Useful for e.g. "ENTER", "SPACE", "TAB" to display as Unicode
|
|
// representations instead.
|
|
// NOTE: Do not reorder the key variants since that influences what the `status_bar` plugin
|
|
// displays!
|
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
|
|
pub enum Key {
|
|
PageDown,
|
|
PageUp,
|
|
Left,
|
|
Down,
|
|
Up,
|
|
Right,
|
|
Home,
|
|
End,
|
|
Backspace,
|
|
Delete,
|
|
Insert,
|
|
F(u8),
|
|
Char(char),
|
|
Alt(CharOrArrow),
|
|
Ctrl(char),
|
|
BackTab,
|
|
Null,
|
|
Esc,
|
|
}
|
|
|
|
impl FromStr for Key {
|
|
type Err = Box<dyn std::error::Error>;
|
|
fn from_str(key_str: &str) -> Result<Self, Self::Err> {
|
|
let mut modifier: Option<&str> = None;
|
|
let mut main_key: Option<&str> = None;
|
|
for (index, part) in key_str.split_ascii_whitespace().enumerate() {
|
|
if index == 0 && (part == "Ctrl" || part == "Alt") {
|
|
modifier = Some(part);
|
|
} else if main_key.is_none() {
|
|
main_key = Some(part)
|
|
}
|
|
}
|
|
match (modifier, main_key) {
|
|
(Some("Ctrl"), Some(main_key)) => {
|
|
let mut key_chars = main_key.chars();
|
|
let key_count = main_key.chars().count();
|
|
if key_count == 1 {
|
|
let key_char = key_chars.next().unwrap();
|
|
Ok(Key::Ctrl(key_char))
|
|
} else {
|
|
Err(format!("Failed to parse key: {}", key_str).into())
|
|
}
|
|
},
|
|
(Some("Alt"), Some(main_key)) => {
|
|
match main_key {
|
|
// why crate::data::Direction and not just Direction?
|
|
// Because it's a different type that we export in this wasm mandated soup - we
|
|
// don't like it either! This will be solved as we chip away at our tech-debt
|
|
"Left" => Ok(Key::Alt(CharOrArrow::Direction(Direction::Left))),
|
|
"Right" => Ok(Key::Alt(CharOrArrow::Direction(Direction::Right))),
|
|
"Up" => Ok(Key::Alt(CharOrArrow::Direction(Direction::Up))),
|
|
"Down" => Ok(Key::Alt(CharOrArrow::Direction(Direction::Down))),
|
|
_ => {
|
|
let mut key_chars = main_key.chars();
|
|
let key_count = main_key.chars().count();
|
|
if key_count == 1 {
|
|
let key_char = key_chars.next().unwrap();
|
|
Ok(Key::Alt(CharOrArrow::Char(key_char)))
|
|
} else {
|
|
Err(format!("Failed to parse key: {}", key_str).into())
|
|
}
|
|
},
|
|
}
|
|
},
|
|
(None, Some(main_key)) => match main_key {
|
|
"Backspace" => Ok(Key::Backspace),
|
|
"Left" => Ok(Key::Left),
|
|
"Right" => Ok(Key::Right),
|
|
"Up" => Ok(Key::Up),
|
|
"Down" => Ok(Key::Down),
|
|
"Home" => Ok(Key::Home),
|
|
"End" => Ok(Key::End),
|
|
"PageUp" => Ok(Key::PageUp),
|
|
"PageDown" => Ok(Key::PageDown),
|
|
"Tab" => Ok(Key::BackTab),
|
|
"Delete" => Ok(Key::Delete),
|
|
"Insert" => Ok(Key::Insert),
|
|
"Space" => Ok(Key::Char(' ')),
|
|
"Enter" => Ok(Key::Char('\n')),
|
|
"Esc" => Ok(Key::Esc),
|
|
_ => {
|
|
let mut key_chars = main_key.chars();
|
|
let key_count = main_key.chars().count();
|
|
if key_count == 1 {
|
|
let key_char = key_chars.next().unwrap();
|
|
Ok(Key::Char(key_char))
|
|
} else if key_count > 1 {
|
|
if let Some(first_char) = key_chars.next() {
|
|
if first_char == 'F' {
|
|
let f_index: String = key_chars.collect();
|
|
let f_index: u8 = f_index
|
|
.parse()
|
|
.map_err(|e| format!("Failed to parse F index: {}", e))?;
|
|
if f_index >= 1 && f_index <= 12 {
|
|
return Ok(Key::F(f_index));
|
|
}
|
|
}
|
|
}
|
|
Err(format!("Failed to parse key: {}", key_str).into())
|
|
} else {
|
|
Err(format!("Failed to parse key: {}", key_str).into())
|
|
}
|
|
},
|
|
},
|
|
_ => Err(format!("Failed to parse key: {}", key_str).into()),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl fmt::Display for Key {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
match self {
|
|
Key::Backspace => write!(f, "BACKSPACE"),
|
|
Key::Left => write!(f, "{}", Direction::Left),
|
|
Key::Right => write!(f, "{}", Direction::Right),
|
|
Key::Up => write!(f, "{}", Direction::Up),
|
|
Key::Down => write!(f, "{}", Direction::Down),
|
|
Key::Home => write!(f, "HOME"),
|
|
Key::End => write!(f, "END"),
|
|
Key::PageUp => write!(f, "PgUp"),
|
|
Key::PageDown => write!(f, "PgDn"),
|
|
Key::BackTab => write!(f, "TAB"),
|
|
Key::Delete => write!(f, "DEL"),
|
|
Key::Insert => write!(f, "INS"),
|
|
Key::F(n) => write!(f, "F{}", n),
|
|
Key::Char(c) => match c {
|
|
'\n' => write!(f, "ENTER"),
|
|
'\t' => write!(f, "TAB"),
|
|
' ' => write!(f, "SPACE"),
|
|
_ => write!(f, "{}", c),
|
|
},
|
|
Key::Alt(c) => write!(f, "Alt+{}", c),
|
|
Key::Ctrl(c) => write!(f, "Ctrl+{}", Key::Char(*c)),
|
|
Key::Null => write!(f, "NULL"),
|
|
Key::Esc => write!(f, "ESC"),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
|
|
#[serde(untagged)]
|
|
pub enum CharOrArrow {
|
|
Char(char),
|
|
Direction(Direction),
|
|
}
|
|
|
|
impl fmt::Display for CharOrArrow {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
match self {
|
|
CharOrArrow::Char(c) => write!(f, "{}", Key::Char(*c)),
|
|
CharOrArrow::Direction(d) => write!(f, "{}", d),
|
|
}
|
|
}
|
|
}
|
|
|
|
/// The four directions (left, right, up, down).
|
|
#[derive(Eq, Clone, Copy, Debug, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)]
|
|
pub enum Direction {
|
|
Left,
|
|
Right,
|
|
Up,
|
|
Down,
|
|
}
|
|
|
|
impl Direction {
|
|
pub fn invert(&self) -> Direction {
|
|
match *self {
|
|
Direction::Left => Direction::Right,
|
|
Direction::Down => Direction::Up,
|
|
Direction::Up => Direction::Down,
|
|
Direction::Right => Direction::Left,
|
|
}
|
|
}
|
|
|
|
pub fn is_horizontal(&self) -> bool {
|
|
matches!(self, Direction::Left | Direction::Right)
|
|
}
|
|
|
|
pub fn is_vertical(&self) -> bool {
|
|
matches!(self, Direction::Down | Direction::Up)
|
|
}
|
|
}
|
|
|
|
impl fmt::Display for Direction {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
match self {
|
|
Direction::Left => write!(f, "←"),
|
|
Direction::Right => write!(f, "→"),
|
|
Direction::Up => write!(f, "↑"),
|
|
Direction::Down => write!(f, "↓"),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl FromStr for Direction {
|
|
type Err = String;
|
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
match s {
|
|
"Left" | "left" => Ok(Direction::Left),
|
|
"Right" | "right" => Ok(Direction::Right),
|
|
"Up" | "up" => Ok(Direction::Up),
|
|
"Down" | "down" => Ok(Direction::Down),
|
|
_ => Err(format!(
|
|
"Failed to parse Direction. Unknown Direction: {}",
|
|
s
|
|
)),
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Resize operation to perform.
|
|
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Deserialize, Serialize)]
|
|
pub enum Resize {
|
|
Increase,
|
|
Decrease,
|
|
}
|
|
|
|
impl Resize {
|
|
pub fn invert(&self) -> Self {
|
|
match self {
|
|
Resize::Increase => Resize::Decrease,
|
|
Resize::Decrease => Resize::Increase,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl fmt::Display for Resize {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
match self {
|
|
Resize::Increase => write!(f, "+"),
|
|
Resize::Decrease => write!(f, "-"),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl FromStr for Resize {
|
|
type Err = String;
|
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
match s {
|
|
"Increase" | "increase" | "+" => Ok(Resize::Increase),
|
|
"Decrease" | "decrease" | "-" => Ok(Resize::Decrease),
|
|
_ => Err(format!(
|
|
"failed to parse resize type. Unknown specifier '{}'",
|
|
s
|
|
)),
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Container type that fully describes resize operations.
|
|
///
|
|
/// This is best thought of as follows:
|
|
///
|
|
/// - `resize` commands how the total *area* of the pane will change as part of this resize
|
|
/// operation.
|
|
/// - `direction` has two meanings:
|
|
/// - `None` means to resize all borders equally
|
|
/// - Anything else means to move the named border to achieve the change in area
|
|
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Deserialize, Serialize)]
|
|
pub struct ResizeStrategy {
|
|
/// Whether to increase or resize total area
|
|
pub resize: Resize,
|
|
/// With which border, if any, to change area
|
|
pub direction: Option<Direction>,
|
|
/// If set to true (default), increasing resizes towards a viewport border will be inverted.
|
|
/// I.e. a scenario like this ("increase right"):
|
|
///
|
|
/// ```text
|
|
/// +---+---+
|
|
/// | | X |->
|
|
/// +---+---+
|
|
/// ```
|
|
///
|
|
/// turns into this ("decrease left"):
|
|
///
|
|
/// ```text
|
|
/// +---+---+
|
|
/// | |-> |
|
|
/// +---+---+
|
|
/// ```
|
|
pub invert_on_boundaries: bool,
|
|
}
|
|
|
|
impl From<Direction> for ResizeStrategy {
|
|
fn from(direction: Direction) -> Self {
|
|
ResizeStrategy::new(Resize::Increase, Some(direction))
|
|
}
|
|
}
|
|
|
|
impl From<Resize> for ResizeStrategy {
|
|
fn from(resize: Resize) -> Self {
|
|
ResizeStrategy::new(resize, None)
|
|
}
|
|
}
|
|
|
|
impl ResizeStrategy {
|
|
pub fn new(resize: Resize, direction: Option<Direction>) -> Self {
|
|
ResizeStrategy {
|
|
resize,
|
|
direction,
|
|
invert_on_boundaries: true,
|
|
}
|
|
}
|
|
|
|
pub fn invert(&self) -> ResizeStrategy {
|
|
let resize = match self.resize {
|
|
Resize::Increase => Resize::Decrease,
|
|
Resize::Decrease => Resize::Increase,
|
|
};
|
|
let direction = match self.direction {
|
|
Some(direction) => Some(direction.invert()),
|
|
None => None,
|
|
};
|
|
|
|
ResizeStrategy::new(resize, direction)
|
|
}
|
|
|
|
pub fn resize_type(&self) -> Resize {
|
|
self.resize
|
|
}
|
|
|
|
pub fn direction(&self) -> Option<Direction> {
|
|
self.direction
|
|
}
|
|
|
|
pub fn direction_horizontal(&self) -> bool {
|
|
matches!(
|
|
self.direction,
|
|
Some(Direction::Left) | Some(Direction::Right)
|
|
)
|
|
}
|
|
|
|
pub fn direction_vertical(&self) -> bool {
|
|
matches!(self.direction, Some(Direction::Up) | Some(Direction::Down))
|
|
}
|
|
|
|
pub fn resize_increase(&self) -> bool {
|
|
self.resize == Resize::Increase
|
|
}
|
|
|
|
pub fn resize_decrease(&self) -> bool {
|
|
self.resize == Resize::Decrease
|
|
}
|
|
|
|
pub fn move_left_border_left(&self) -> bool {
|
|
(self.resize == Resize::Increase) && (self.direction == Some(Direction::Left))
|
|
}
|
|
|
|
pub fn move_left_border_right(&self) -> bool {
|
|
(self.resize == Resize::Decrease) && (self.direction == Some(Direction::Left))
|
|
}
|
|
|
|
pub fn move_lower_border_down(&self) -> bool {
|
|
(self.resize == Resize::Increase) && (self.direction == Some(Direction::Down))
|
|
}
|
|
|
|
pub fn move_lower_border_up(&self) -> bool {
|
|
(self.resize == Resize::Decrease) && (self.direction == Some(Direction::Down))
|
|
}
|
|
|
|
pub fn move_upper_border_up(&self) -> bool {
|
|
(self.resize == Resize::Increase) && (self.direction == Some(Direction::Up))
|
|
}
|
|
|
|
pub fn move_upper_border_down(&self) -> bool {
|
|
(self.resize == Resize::Decrease) && (self.direction == Some(Direction::Up))
|
|
}
|
|
|
|
pub fn move_right_border_right(&self) -> bool {
|
|
(self.resize == Resize::Increase) && (self.direction == Some(Direction::Right))
|
|
}
|
|
|
|
pub fn move_right_border_left(&self) -> bool {
|
|
(self.resize == Resize::Decrease) && (self.direction == Some(Direction::Right))
|
|
}
|
|
|
|
pub fn move_all_borders_out(&self) -> bool {
|
|
(self.resize == Resize::Increase) && (self.direction == None)
|
|
}
|
|
|
|
pub fn move_all_borders_in(&self) -> bool {
|
|
(self.resize == Resize::Decrease) && (self.direction == None)
|
|
}
|
|
}
|
|
|
|
impl fmt::Display for ResizeStrategy {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
let resize = match self.resize {
|
|
Resize::Increase => "increase",
|
|
Resize::Decrease => "decrease",
|
|
};
|
|
let border = match self.direction {
|
|
Some(Direction::Left) => "left",
|
|
Some(Direction::Down) => "bottom",
|
|
Some(Direction::Up) => "top",
|
|
Some(Direction::Right) => "right",
|
|
None => "every",
|
|
};
|
|
|
|
write!(f, "{} size on {} border", resize, border)
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
|
// FIXME: This should be extended to handle different button clicks (not just
|
|
// left click) and the `ScrollUp` and `ScrollDown` events could probably be
|
|
// merged into a single `Scroll(isize)` event.
|
|
pub enum Mouse {
|
|
ScrollUp(usize), // number of lines
|
|
ScrollDown(usize), // number of lines
|
|
LeftClick(isize, usize), // line and column
|
|
RightClick(isize, usize), // line and column
|
|
Hold(isize, usize), // line and column
|
|
Release(isize, usize), // line and column
|
|
}
|
|
|
|
#[derive(Debug, Clone, PartialEq, EnumDiscriminants, ToString, Serialize, Deserialize)]
|
|
#[strum_discriminants(derive(EnumString, Hash, Serialize, Deserialize))]
|
|
#[strum_discriminants(name(EventType))]
|
|
#[non_exhaustive]
|
|
pub enum Event {
|
|
ModeUpdate(ModeInfo),
|
|
TabUpdate(Vec<TabInfo>),
|
|
Key(Key),
|
|
Mouse(Mouse),
|
|
Timer(f64),
|
|
CopyToClipboard(CopyDestination),
|
|
SystemClipboardFailure,
|
|
InputReceived,
|
|
Visible(bool),
|
|
}
|
|
|
|
/// Describes the different input modes, which change the way that keystrokes will be interpreted.
|
|
#[derive(
|
|
Debug,
|
|
PartialEq,
|
|
Eq,
|
|
Hash,
|
|
Copy,
|
|
Clone,
|
|
EnumIter,
|
|
Serialize,
|
|
Deserialize,
|
|
ArgEnum,
|
|
PartialOrd,
|
|
Ord,
|
|
)]
|
|
pub enum InputMode {
|
|
/// In `Normal` mode, input is always written to the terminal, except for the shortcuts leading
|
|
/// to other modes
|
|
#[serde(alias = "normal")]
|
|
Normal,
|
|
/// In `Locked` mode, input is always written to the terminal and all shortcuts are disabled
|
|
/// except the one leading back to normal mode
|
|
#[serde(alias = "locked")]
|
|
Locked,
|
|
/// `Resize` mode allows resizing the different existing panes.
|
|
#[serde(alias = "resize")]
|
|
Resize,
|
|
/// `Pane` mode allows creating and closing panes, as well as moving between them.
|
|
#[serde(alias = "pane")]
|
|
Pane,
|
|
/// `Tab` mode allows creating and closing tabs, as well as moving between them.
|
|
#[serde(alias = "tab")]
|
|
Tab,
|
|
/// `Scroll` mode allows scrolling up and down within a pane.
|
|
#[serde(alias = "scroll")]
|
|
Scroll,
|
|
/// `EnterSearch` mode allows for typing in the needle for a search in the scroll buffer of a pane.
|
|
#[serde(alias = "entersearch")]
|
|
EnterSearch,
|
|
/// `Search` mode allows for searching a term in a pane (superset of `Scroll`).
|
|
#[serde(alias = "search")]
|
|
Search,
|
|
/// `RenameTab` mode allows assigning a new name to a tab.
|
|
#[serde(alias = "renametab")]
|
|
RenameTab,
|
|
/// `RenamePane` mode allows assigning a new name to a pane.
|
|
#[serde(alias = "renamepane")]
|
|
RenamePane,
|
|
/// `Session` mode allows detaching sessions
|
|
#[serde(alias = "session")]
|
|
Session,
|
|
/// `Move` mode allows moving the different existing panes within a tab
|
|
#[serde(alias = "move")]
|
|
Move,
|
|
/// `Prompt` mode allows interacting with active prompts.
|
|
#[serde(alias = "prompt")]
|
|
Prompt,
|
|
/// `Tmux` mode allows for basic tmux keybindings functionality
|
|
#[serde(alias = "tmux")]
|
|
Tmux,
|
|
}
|
|
|
|
// impl TryFrom<&str> for InputMode {
|
|
// type Error = String;
|
|
// fn try_from(mode: &str) -> Result<Self, String> {
|
|
// match mode {
|
|
// "normal" | "Normal" => Ok(InputMode::Normal),
|
|
// "locked" | "Locked" => Ok(InputMode::Locked),
|
|
// "resize" | "Resize" => Ok(InputMode::Resize),
|
|
// "pane" | "Pane" => Ok(InputMode::Pane),
|
|
// "tab" | "Tab" => Ok(InputMode::Tab),
|
|
// "search" | "Search" => Ok(InputMode::Search),
|
|
// "renametab" | "RenameTab" => Ok(InputMode::RenameTab),
|
|
// "renamepane" | "RenamePane" => Ok(InputMode::RenamePane),
|
|
// "session" | "Session" => Ok(InputMode::Session),
|
|
// "move" | "Move" => Ok(InputMode::Move),
|
|
// "prompt" | "Prompt" => Ok(InputMode::Prompt),
|
|
// "tmux" | "Tmux" => Ok(InputMode::Tmux),
|
|
// _ => Err(format!("Unrecognized mode: {}", mode)),
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
impl Default for InputMode {
|
|
fn default() -> InputMode {
|
|
InputMode::Normal
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
|
|
pub enum ThemeHue {
|
|
Light,
|
|
Dark,
|
|
}
|
|
impl Default for ThemeHue {
|
|
fn default() -> ThemeHue {
|
|
ThemeHue::Dark
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
|
|
pub enum PaletteColor {
|
|
Rgb((u8, u8, u8)),
|
|
EightBit(u8),
|
|
}
|
|
impl Default for PaletteColor {
|
|
fn default() -> PaletteColor {
|
|
PaletteColor::EightBit(0)
|
|
}
|
|
}
|
|
|
|
impl FromStr for InputMode {
|
|
type Err = ConversionError;
|
|
|
|
fn from_str(s: &str) -> Result<Self, ConversionError> {
|
|
match s {
|
|
"normal" | "Normal" => Ok(InputMode::Normal),
|
|
"locked" | "Locked" => Ok(InputMode::Locked),
|
|
"resize" | "Resize" => Ok(InputMode::Resize),
|
|
"pane" | "Pane" => Ok(InputMode::Pane),
|
|
"tab" | "Tab" => Ok(InputMode::Tab),
|
|
"search" | "Search" => Ok(InputMode::Search),
|
|
"scroll" | "Scroll" => Ok(InputMode::Scroll),
|
|
"renametab" | "RenameTab" => Ok(InputMode::RenameTab),
|
|
"renamepane" | "RenamePane" => Ok(InputMode::RenamePane),
|
|
"session" | "Session" => Ok(InputMode::Session),
|
|
"move" | "Move" => Ok(InputMode::Move),
|
|
"prompt" | "Prompt" => Ok(InputMode::Prompt),
|
|
"tmux" | "Tmux" => Ok(InputMode::Tmux),
|
|
"entersearch" | "Entersearch" | "EnterSearch" => Ok(InputMode::EnterSearch),
|
|
e => Err(ConversionError::UnknownInputMode(e.into())),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
|
|
pub enum PaletteSource {
|
|
Default,
|
|
Xresources,
|
|
}
|
|
impl Default for PaletteSource {
|
|
fn default() -> PaletteSource {
|
|
PaletteSource::Default
|
|
}
|
|
}
|
|
#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq, Hash, Default)]
|
|
pub struct Palette {
|
|
pub source: PaletteSource,
|
|
pub theme_hue: ThemeHue,
|
|
pub fg: PaletteColor,
|
|
pub bg: PaletteColor,
|
|
pub black: PaletteColor,
|
|
pub red: PaletteColor,
|
|
pub green: PaletteColor,
|
|
pub yellow: PaletteColor,
|
|
pub blue: PaletteColor,
|
|
pub magenta: PaletteColor,
|
|
pub cyan: PaletteColor,
|
|
pub white: PaletteColor,
|
|
pub orange: PaletteColor,
|
|
pub gray: PaletteColor,
|
|
pub purple: PaletteColor,
|
|
pub gold: PaletteColor,
|
|
pub silver: PaletteColor,
|
|
pub pink: PaletteColor,
|
|
pub brown: PaletteColor,
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default, Serialize, Deserialize)]
|
|
pub struct Style {
|
|
pub colors: Palette,
|
|
pub rounded_corners: bool,
|
|
pub hide_session_name: bool,
|
|
}
|
|
|
|
// FIXME: Poor devs hashtable since HashTable can't derive `Default`...
|
|
pub type KeybindsVec = Vec<(InputMode, Vec<(Key, Vec<Action>)>)>;
|
|
|
|
/// Represents the contents of the help message that is printed in the status bar,
|
|
/// which indicates the current [`InputMode`] and what the keybinds for that mode
|
|
/// are. Related to the default `status-bar` plugin.
|
|
#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
|
pub struct ModeInfo {
|
|
pub mode: InputMode,
|
|
pub keybinds: KeybindsVec,
|
|
pub style: Style,
|
|
pub capabilities: PluginCapabilities,
|
|
pub session_name: Option<String>,
|
|
}
|
|
|
|
impl ModeInfo {
|
|
pub fn get_mode_keybinds(&self) -> Vec<(Key, Vec<Action>)> {
|
|
self.get_keybinds_for_mode(self.mode)
|
|
}
|
|
|
|
pub fn get_keybinds_for_mode(&self, mode: InputMode) -> Vec<(Key, Vec<Action>)> {
|
|
for (vec_mode, map) in &self.keybinds {
|
|
if mode == *vec_mode {
|
|
return map.to_vec();
|
|
}
|
|
}
|
|
vec![]
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Default, Clone, PartialEq, Eq, Hash, Deserialize, Serialize)]
|
|
pub struct TabInfo {
|
|
/* subset of fields to publish to plugins */
|
|
pub position: usize,
|
|
pub name: String,
|
|
pub active: bool,
|
|
pub panes_to_hide: usize,
|
|
pub is_fullscreen_active: bool,
|
|
pub is_sync_panes_active: bool,
|
|
pub are_floating_panes_visible: bool,
|
|
pub other_focused_clients: Vec<ClientId>,
|
|
pub active_swap_layout_name: Option<String>,
|
|
pub is_swap_layout_dirty: bool,
|
|
}
|
|
|
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Deserialize, Serialize)]
|
|
pub struct PluginIds {
|
|
pub plugin_id: u32,
|
|
pub zellij_pid: u32,
|
|
}
|
|
|
|
/// Tag used to identify the plugin in layout and config yaml files
|
|
#[derive(Debug, Default, Clone, PartialEq, Eq, Hash, Deserialize, Serialize, PartialOrd, Ord)]
|
|
pub struct PluginTag(String);
|
|
|
|
impl PluginTag {
|
|
pub fn new(url: impl Into<String>) -> Self {
|
|
PluginTag(url.into())
|
|
}
|
|
}
|
|
|
|
impl From<PluginTag> for String {
|
|
fn from(tag: PluginTag) -> Self {
|
|
tag.0
|
|
}
|
|
}
|
|
|
|
impl fmt::Display for PluginTag {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
write!(f, "{}", self.0)
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Deserialize, Serialize)]
|
|
pub struct PluginCapabilities {
|
|
pub arrow_fonts: bool,
|
|
}
|
|
|
|
impl Default for PluginCapabilities {
|
|
fn default() -> PluginCapabilities {
|
|
PluginCapabilities { arrow_fonts: true }
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
|
|
pub enum CopyDestination {
|
|
Command,
|
|
Primary,
|
|
System,
|
|
}
|