summaryrefslogtreecommitdiffstats
path: root/zellij-utils/src/kdl/mod.rs
diff options
context:
space:
mode:
authorAram Drevekenin <aram@poor.dev>2022-10-05 07:44:00 +0200
committerGitHub <noreply@github.com>2022-10-05 07:44:00 +0200
commit79bf6ab868cbdab1f9a3827c9b70198f54548b44 (patch)
tree2d6fc4c1d8a79ebd727a1a5f8b6406617dd0de55 /zellij-utils/src/kdl/mod.rs
parent917e9b2ff0f583183c0155060d243afd295770b9 (diff)
feat(config): switch to kdl (#1759)
* chore(config): default kdl keybindings config * tests * work * refactor(config): move stuff around * work * tab merge layout * work * work * layouts working * work * layout tests * work * work * feat(parsing): kdl layouts without config * refactor(kdl): move stuff around * work * tests(layout): add cases and fix bugs * work * fix(kdl): various bugs * chore(layouts): move all layouts to kdl * feat(kdl): shared keybidns * fix(layout): do not count fixed panes toward percentile * fix(keybinds): missing keybinds and actions * fix(config): adjust default tips * refactor(config): move stuff around * fix(tests): make e2e tests pass * fix(kdl): add verbose parsing errors * fix(kdl): focused tab * fix(layout): corret default_tab_template behavior * style(code): fix compile warnings * feat(cli): send actions through the cli * fix(cli): exit only when action is done * fix(cli): open embedded pane from floating pane * fix(cli): send actions to other sessions * feat(cli): command alias * feat(converter): convert old config * feat(converter): convert old layout and theme files * feat(kdl): pretty errors * feat(client): convert old YAML files on startup * fix: various bugs and styling issues * fix: e2e tests * fix(screen): propagate errors after merge * style(clippy): lower clippy level * fix(tests): own session_name variable * style(fmt): rustfmt * fix(cli): various action fixes * style(fmt): rustfmt * fix(themes): loading of theme files * style(fmt): rustfmt * fix(tests): theme fixtures * fix(layouts): better errors on unknown nodes * fix(kdl): clarify valid node terminator error * fix(e2e): adjust close tab test * fix(e2e): adjust close tab test again * style(code): cleanup some comments
Diffstat (limited to 'zellij-utils/src/kdl/mod.rs')
-rw-r--r--zellij-utils/src/kdl/mod.rs1626
1 files changed, 1626 insertions, 0 deletions
diff --git a/zellij-utils/src/kdl/mod.rs b/zellij-utils/src/kdl/mod.rs
new file mode 100644
index 000000000..7092653c6
--- /dev/null
+++ b/zellij-utils/src/kdl/mod.rs
@@ -0,0 +1,1626 @@
+mod kdl_layout_parser;
+use crate::data::{InputMode, Key, Palette, PaletteColor};
+use crate::envs::EnvironmentVariables;
+use crate::input::command::RunCommand;
+use crate::input::config::{Config, ConfigError, KdlError};
+use crate::input::keybinds::Keybinds;
+use crate::input::layout::{Layout, RunPlugin, RunPluginLocation};
+use crate::input::options::{Clipboard, OnForceClose, Options};
+use crate::input::plugins::{PluginConfig, PluginTag, PluginType, PluginsConfig};
+use crate::input::theme::{FrameConfig, Theme, Themes, UiConfig};
+use kdl_layout_parser::KdlLayoutParser;
+use std::collections::HashMap;
+use std::fs::File;
+use std::io::Read;
+use strum::IntoEnumIterator;
+use url::Url;
+
+use miette::NamedSource;
+
+use kdl::{KdlDocument, KdlEntry, KdlNode};
+
+use std::path::PathBuf;
+use std::str::FromStr;
+
+use crate::input::actions::{Action, Direction, ResizeDirection, SearchDirection, SearchOption};
+use crate::input::command::RunCommandAction;
+
+#[macro_export]
+macro_rules! parse_kdl_action_arguments {
+ ( $action_name:expr, $action_arguments:expr, $action_node:expr ) => {{
+ if !$action_arguments.is_empty() {
+ Err(ConfigError::new_kdl_error(
+ format!("Action '{}' must have arguments", $action_name),
+ $action_node.span().offset(),
+ $action_node.span().len(),
+ ))
+ } else {
+ match $action_name {
+ "Quit" => Ok(Action::Quit),
+ "FocusNextPane" => Ok(Action::FocusNextPane),
+ "FocusPreviousPane" => Ok(Action::FocusPreviousPane),
+ "SwitchFocus" => Ok(Action::SwitchFocus),
+ "EditScrollback" => Ok(Action::EditScrollback),
+ "ScrollUp" => Ok(Action::ScrollUp),
+ "ScrollDown" => Ok(Action::ScrollDown),
+ "ScrollToBottom" => Ok(Action::ScrollToBottom),
+ "PageScrollUp" => Ok(Action::PageScrollUp),
+ "PageScrollDown" => Ok(Action::PageScrollDown),
+ "HalfPageScrollUp" => Ok(Action::HalfPageScrollUp),
+ "HalfPageScrollDown" => Ok(Action::HalfPageScrollDown),
+ "ToggleFocusFullscreen" => Ok(Action::ToggleFocusFullscreen),
+ "TogglePaneFrames" => Ok(Action::TogglePaneFrames),
+ "ToggleActiveSyncTab" => Ok(Action::ToggleActiveSyncTab),
+ "TogglePaneEmbedOrFloating" => Ok(Action::TogglePaneEmbedOrFloating),
+ "ToggleFloatingPanes" => Ok(Action::ToggleFloatingPanes),
+ "CloseFocus" => Ok(Action::CloseFocus),
+ "UndoRenamePane" => Ok(Action::UndoRenamePane),
+ "NoOp" => Ok(Action::NoOp),
+ "GoToNextTab" => Ok(Action::GoToNextTab),
+ "GoToPreviousTab" => Ok(Action::GoToPreviousTab),
+ "CloseTab" => Ok(Action::CloseTab),
+ "ToggleTab" => Ok(Action::ToggleTab),
+ "UndoRenameTab" => Ok(Action::UndoRenameTab),
+ "Detach" => Ok(Action::Detach),
+ "Copy" => Ok(Action::Copy),
+ "Confirm" => Ok(Action::Confirm),
+ "Deny" => Ok(Action::Deny),
+ _ => Err(ConfigError::new_kdl_error(
+ format!("Unsupported action: {:?}", $action_name),
+ $action_node.span().offset(),
+ $action_node.span().len(),
+ )),
+ }
+ }
+ }};
+}
+
+#[macro_export]
+macro_rules! parse_kdl_action_u8_arguments {
+ ( $action_name:expr, $action_arguments:expr, $action_node:expr ) => {{
+ let mut bytes = vec![];
+ for kdl_entry in $action_arguments.iter() {
+ match kdl_entry.value().as_i64() {
+ Some(int_value) => bytes.push(int_value as u8),
+ None => {
+ return Err(ConfigError::new_kdl_error(
+ format!("Arguments for '{}' must be integers", $action_name),
+ kdl_entry.span().offset(),
+ kdl_entry.span().len(),
+ ));
+ },
+ }
+ }
+ Action::new_from_bytes($action_name, bytes, $action_node)
+ }};
+}
+
+#[macro_export]
+macro_rules! kdl_parsing_error {
+ ( $message:expr, $entry:expr ) => {
+ ConfigError::new_kdl_error($message, $entry.span().offset(), $entry.span().len())
+ };
+}
+
+#[macro_export]
+macro_rules! kdl_entries_as_i64 {
+ ( $node:expr ) => {
+ $node
+ .entries()
+ .iter()
+ .map(|kdl_node| kdl_node.value().as_i64())
+ };
+}
+
+#[macro_export]
+macro_rules! kdl_first_entry_as_string {
+ ( $node:expr ) => {
+ $node
+ .entries()
+ .iter()
+ .next()
+ .and_then(|s| s.value().as_string())
+ };
+}
+
+#[macro_export]
+macro_rules! kdl_first_entry_as_i64 {
+ ( $node:expr ) => {
+ $node
+ .entries()
+ .iter()
+ .next()
+ .and_then(|i| i.value().as_i64())
+ };
+}
+
+#[macro_export]
+macro_rules! entry_count {
+ ( $node:expr ) => {{
+ $node.entries().iter().len()
+ }};
+}
+
+#[macro_export]
+macro_rules! parse_kdl_action_char_or_string_arguments {
+ ( $action_name:expr, $action_arguments:expr, $action_node:expr ) => {{
+ let mut chars_to_write = String::new();
+ for kdl_entry in $action_arguments.iter() {
+ match kdl_entry.value().as_string() {
+ Some(string_value) => chars_to_write.push_str(string_value),
+ None => {
+ return Err(ConfigError::new_kdl_error(
+ format!("All entries for action '{}' must be strings", $action_name),
+ kdl_entry.span().offset(),
+ kdl_entry.span().len(),
+ ))
+ },
+ }
+ }
+ Action::new_from_string($action_name, chars_to_write, $action_node)
+ }};
+}
+
+#[macro_export]
+macro_rules! kdl_arg_is_truthy {
+ ( $kdl_node:expr, $arg_name:expr ) => {
+ match $kdl_node.get($arg_name) {
+ Some(arg) => match arg.value().as_bool() {
+ Some(value) => value,
+ None => {
+ return Err(ConfigError::new_kdl_error(
+ format!("Argument must be true or false, found: {}", arg.value()),
+ arg.span().offset(),
+ arg.span().len(),
+ ))
+ },
+ },
+ None => false,
+ }
+ };
+}
+
+#[macro_export]
+macro_rules! kdl_children_nodes_or_error {
+ ( $kdl_node:expr, $error:expr ) => {
+ $kdl_node
+ .children()
+ .ok_or(ConfigError::new_kdl_error(
+ $error.into(),
+ $kdl_node.span().offset(),
+ $kdl_node.span().len(),
+ ))?
+ .nodes()
+ };
+}
+
+#[macro_export]
+macro_rules! kdl_children_nodes {
+ ( $kdl_node:expr ) => {
+ $kdl_node.children().map(|c| c.nodes())
+ };
+}
+
+#[macro_export]
+macro_rules! kdl_property_nodes {
+ ( $kdl_node:expr ) => {{
+ $kdl_node
+ .entries()
+ .iter()
+ .filter_map(|e| e.name())
+ .map(|e| e.value())
+ }};
+}
+
+#[macro_export]
+macro_rules! kdl_children_or_error {
+ ( $kdl_node:expr, $error:expr ) => {
+ $kdl_node.children().ok_or(ConfigError::new_kdl_error(
+ $error.into(),
+ $kdl_node.span().offset(),
+ $kdl_node.span().len(),
+ ))?
+ };
+}
+
+#[macro_export]
+macro_rules! kdl_children {
+ ( $kdl_node:expr ) => {
+ $kdl_node.children().iter().copied().collect()
+ };
+}
+
+#[macro_export]
+macro_rules! kdl_string_arguments {
+ ( $kdl_node:expr ) => {{
+ let res: Result<Vec<_>, _> = $kdl_node
+ .entries()
+ .iter()
+ .map(|e| {
+ e.value().as_string().ok_or(ConfigError::new_kdl_error(
+ "Not a string".into(),
+ e.span().offset(),
+ e.span().len(),
+ ))
+ })
+ .collect();
+ res?
+ }};
+}
+
+#[macro_export]
+macro_rules! kdl_property_names {
+ ( $kdl_node:expr ) => {{
+ $kdl_node
+ .entries()
+ .iter()
+ .filter_map(|e| e.name())
+ .map(|e| e.value())
+ }};
+}
+
+#[macro_export]
+macro_rules! kdl_argument_values {
+ ( $kdl_node:expr ) => {
+ $kdl_node.entries().iter().collect()
+ };
+}
+
+#[macro_export]
+macro_rules! kdl_name {
+ ( $kdl_node:expr ) => {
+ $kdl_node.name().value()
+ };
+}
+
+#[macro_export]
+macro_rules! kdl_document_name {
+ ( $kdl_node:expr ) => {
+ $kdl_node.node().name().value()
+ };
+}
+
+#[macro_export]
+macro_rules! keys_from_kdl {
+ ( $kdl_node:expr ) => {
+ kdl_string_arguments!($kdl_node)
+ .iter()
+ .map(|k| {
+ Key::from_str(k).map_err(|_| {
+ ConfigError::new_kdl_error(
+ format!("Invalid key: '{}'", k),
+ $kdl_node.span().offset(),
+ $kdl_node.span().len(),
+ )
+ })
+ })
+ .collect::<Result<_, _>>()?
+ };
+}
+
+#[macro_export]
+macro_rules! actions_from_kdl {
+ ( $kdl_node:expr ) => {
+ kdl_children_nodes_or_error!($kdl_node, "no actions found for key_block")
+ .iter()
+ .map(|kdl_action| Action::try_from(kdl_action))
+ .collect::<Result<_, _>>()?
+ };
+}
+
+pub fn kdl_arguments_that_are_strings<'a>(
+ arguments: impl Iterator<Item = &'a KdlEntry>,
+) -> Result<Vec<String>, ConfigError> {
+ // pub fn kdl_arguments_that_are_strings <'a>(arguments: impl Iterator<Item=&'a KdlValue>) -> Result<Vec<String>, ConfigError> {
+ let mut args: Vec<String> = vec![];
+ for kdl_entry in arguments {
+ match kdl_entry.value().as_string() {
+ Some(string_value) => args.push(string_value.to_string()),
+ None => {
+ return Err(ConfigError::new_kdl_error(
+ format!("Argument must be a string"),
+ kdl_entry.span().offset(),
+ kdl_entry.span().len(),
+ ));
+ },
+ }
+ }
+ Ok(args)
+}
+
+pub fn kdl_child_string_value_for_entry<'a>(
+ command_metadata: &'a KdlDocument,
+ entry_name: &'a str,
+) -> Option<&'a str> {
+ command_metadata
+ .get(entry_name)
+ .and_then(|cwd| cwd.entries().iter().next())
+ .and_then(|cwd_value| cwd_value.value().as_string())
+}
+
+impl Action {
+ pub fn new_from_bytes(
+ action_name: &str,
+ bytes: Vec<u8>,
+ action_node: &KdlNode,
+ ) -> Result<Self, ConfigError> {
+ match action_name {
+ "Write" => Ok(Action::Write(bytes)),
+ "PaneNameInput" => Ok(Action::PaneNameInput(bytes)),
+ "TabNameInput" => Ok(Action::TabNameInput(bytes)),
+ "SearchInput" => Ok(Action::SearchInput(bytes)),
+ "GoToTab" => {
+ let tab_index = *bytes.get(0).ok_or_else(|| {
+ ConfigError::new_kdl_error(
+ format!("Missing tab index"),
+ action_node.span().offset(),
+ action_node.span().len(),
+ )
+ })? as u32;
+ Ok(Action::GoToTab(tab_index))
+ },
+ _ => Err(ConfigError::new_kdl_error(
+ "Failed to parse action".into(),
+ action_node.span().offset(),
+ action_node.span().len(),
+ )),
+ }
+ }
+ pub fn new_from_string(
+ action_name: &str,
+ string: String,
+ action_node: &KdlNode,
+ ) -> Result<Self, ConfigError> {
+ match action_name {
+ "WriteChars" => Ok(Action::WriteChars(string)),
+ "SwitchToMode" => match InputMode::from_str(string.as_str()) {
+ Ok(input_mode) => Ok(Action::SwitchToMode(input_mode)),
+ Err(_e) => {
+ return Err(ConfigError::new_kdl_error(
+ format!("Unknown InputMode '{}'", string),
+ action_node.span().offset(),
+ action_node.span().len(),
+ ))
+ },
+ },
+ "Resize" => {
+ let direction = ResizeDirection::from_str(string.as_str()).map_err(|_| {
+ ConfigError::new_kdl_error(
+ format!("Invalid direction: '{}'", string),
+ action_node.span().offset(),
+ action_node.span().len(),
+ )
+ })?;
+ Ok(Action::Resize(direction))
+ },
+ "MoveFocus" => {
+ let direction = Direction::from_str(string.as_str()).map_err(|_| {
+ ConfigError::new_kdl_error(
+ format!("Invalid direction: '{}'", string),
+ action_node.span().offset(),
+ action_node.span().len(),
+ )
+ })?;
+ Ok(Action::MoveFocus(direction))
+ },
+ "MoveFocusOrTab" => {
+ let direction = Direction::from_str(string.as_str()).map_err(|_| {
+ ConfigError::new_kdl_error(
+ format!("Invalid direction: '{}'", string),
+ action_node.span().offset(),
+ action_node.span().len(),
+ )
+ })?;
+ Ok(Action::MoveFocusOrTab(direction))
+ },
+ "MovePane" => {
+ if string.is_empty() {
+ return Ok(Action::MovePane(None));
+ } else {
+ let direction = Direction::from_str(string.as_str()).map_err(|_| {
+ ConfigError::new_kdl_error(
+ format!("Invalid direction: '{}'", string),
+ action_node.span().offset(),
+ action_node.span().len(),
+ )
+ })?;
+ Ok(Action::MovePane(Some(direction)))
+ }
+ },
+ "DumpScreen" => Ok(Action::DumpScreen(string)),
+ "NewPane" => {
+ if string.is_empty() {
+ return Ok(Action::NewPane(None));
+ } else {
+ let direction = Direction::from_str(string.as_str()).map_err(|_| {
+ ConfigError::new_kdl_error(
+ format!("Invalid direction: '{}'", string),
+ action_node.span().offset(),
+ action_node.span().len(),
+ )
+ })?;
+ Ok(Action::NewPane(Some(direction)))
+ }
+ },
+ "SearchToggleOption" => {
+ let toggle_option = SearchOption::from_str(string.as_str()).map_err(|_| {
+ ConfigError::new_kdl_error(
+ format!("Invalid direction: '{}'", string),
+ action_node.span().offset(),
+ action_node.span().len(),
+ )
+ })?;
+ Ok(Action::SearchToggleOption(toggle_option))
+ },
+ "Search" => {
+ let search_direction =
+ SearchDirection::from_str(string.as_str()).map_err(|_| {
+ ConfigError::new_kdl_error(
+ format!("Invalid direction: '{}'", string),
+ action_node.span().offset(),
+ action_node.span().len(),
+ )
+ })?;
+ Ok(Action::Search(search_direction))
+ },
+ _ => Err(ConfigError::new_kdl_error(
+ format!("Unsupported action: {}", action_name),
+ action_node.span().offset(),
+ action_node.span().len(),
+ )),
+ }
+ }
+}
+
+impl TryFrom<(&str, &KdlDocument)> for PaletteColor {
+ type Error = ConfigError;
+
+ fn try_from(
+ (color_name, theme_colors): (&str, &KdlDocument),
+ ) -> Result<PaletteColor, Self::Error> {
+ let color = theme_colors
+ .get(color_name)
+ .ok_or(ConfigError::new_kdl_error(
+ format!("Missing theme color: {}", color_name),
+ theme_colors.span().offset(),
+ theme_colors.span().len(),
+ ))?;
+ let entry_count = entry_count!(color);
+ let is_rgb = || entry_count == 3;
+ let is_three_digit_hex = || {
+ match kdl_first_entry_as_string!(color) {
+ // 4 including the '#' character
+ Some(s) => entry_count == 1 && s.starts_with('#') && s.len() == 4,
+ None => false,
+ }
+ };
+ let is_six_digit_hex = || {
+ match kdl_first_entry_as_string!(color) {
+ // 7 including the '#' character
+ Some(s) => entry_count == 1 && s.starts_with('#') && s.len() == 7,
+ None => false,
+ }
+ };
+ let is_eight_bit = || kdl_first_entry_as_i64!(color).is_some() && entry_count == 1;
+ if is_rgb() {
+ let mut channels = kdl_entries_as_i64!(color);
+ let r = channels.next().unwrap().ok_or(ConfigError::new_kdl_error(
+ format!("invalid rgb color"),
+ color.span().offset(),
+ color.span().len(),
+ ))? as u8;
+ let g = channels.next().unwrap().ok_or(ConfigError::new_kdl_error(
+ format!("invalid rgb color"),
+ color.span().offset(),
+ color.span().len(),
+ ))? as u8;
+ let b = channels.next().unwrap().ok_or(ConfigError::new_kdl_error(
+ format!("invalid rgb color"),
+ color.span().offset(),
+ color.span().len(),
+ ))? as u8;
+ Ok(PaletteColor::Rgb((r, g, b)))
+ } else if is_three_digit_hex() {
+ // eg. #fff (hex, will be converted to rgb)
+ let mut s = String::from(kdl_first_entry_as_string!(color).unwrap());
+ s.remove(0);
+ let r = u8::from_str_radix(&s[0..1], 16).map_err(|_| {
+ ConfigError::new_kdl_error(
+ "Failed to parse hex color".into(),
+ color.span().offset(),
+ color.span().len(),
+ )
+ })? * 0x11;
+ let g = u8::from_str_radix(&s[1..2], 16).map_err(|_| {
+ ConfigError::new_kdl_error(
+ "Failed to parse hex color".into(),
+ color.span().offset(),
+ color.span().len(),
+ )
+ })? * 0x11;
+ let b = u8::from_str_radix(&s[2..3], 16).map_err(|_| {
+ ConfigError::new_kdl_error(
+ "Failed to parse hex color".into(),
+ color.span().offset(),
+ color.span().len(),
+ )
+ })? * 0x11;
+ Ok(PaletteColor::Rgb((r, g, b)))
+ } else if is_six_digit_hex() {
+ // eg. #ffffff (hex, will be converted to rgb)
+ let mut s = String::from(kdl_first_entry_as_string!(color).unwrap());
+ s.remove(0);
+ let r = u8::from_str_radix(&s[0..2], 16).map_err(|_| {
+ ConfigError::new_kdl_error(
+ "Failed to parse hex color".into(),
+ color.span().offset(),
+ color.span().len(),
+ )
+ })?;
+ let g = u8::from_str_radix(&s[2..4], 16).map_err(|_| {
+ ConfigError::new_kdl_error(
+ "Failed to parse hex color".into(),
+ color.span().offset(),
+ color.span().len(),
+ )
+ })?;
+ let b = u8::from_str_radix(&s[4..6], 16).map_err(|_| {
+ ConfigError::new_kdl_error(
+ "Failed to parse hex color".into(),
+ color.span().offset(),
+ color.span().len(),
+ )
+ })?;
+ Ok(PaletteColor::Rgb((r, g, b)))
+ } else if is_eight_bit() {
+ let n = kdl_first_entry_as_i64!(color).ok_or(ConfigError::new_kdl_error(
+ "Failed to parse color".into(),
+ color.span().offset(),
+ color.span().len(),
+ ))?;
+ Ok(PaletteColor::EightBit(n as u8))
+ } else {
+ Err(ConfigError::new_kdl_error(
+ "Failed to parse color".into(),
+ color.span().offset(),
+ color.span().len(),
+ ))
+ }
+ }
+}
+
+impl TryFrom<&KdlNode> for Action {
+ // type Error = Box<dyn std::error::Error>;
+ type Error = ConfigError;
+ fn try_from(kdl_action: &KdlNode) -> Result<Self, Self::Error> {
+ let action_name = kdl_name!(kdl_action);
+ let action_arguments: Vec<&KdlEntry> = kdl_argument_values!(kdl_action);
+ // let action_arguments: Vec<&KdlValue> = kdl_argument_values!(kdl_action);
+ let action_children: Vec<&KdlDocument> = kdl_children!(kdl_action);
+ match action_name {
+ "Quit" => parse_kdl_action_arguments!(action_name, action_arguments, kdl_action),
+ "FocusNextPane" => {
+ parse_kdl_action_arguments!(action_name, action_arguments, kdl_action)
+ },
+ "FocusPreviousPane" => {
+ parse_kdl_action_arguments!(action_name, action_arguments, kdl_action)
+ },
+ "SwitchFocus" => parse_kdl_action_arguments!(action_name, action_arguments, kdl_action),
+ "EditScrollback" => {
+ parse_kdl_action_arguments!(action_name, action_arguments, kdl_action)
+ },
+ "ScrollUp" => parse_kdl_action_arguments!(action_name, action_arguments, kdl_action),
+ "ScrollDown" => parse_kdl_action_arguments!(action_name, action_arguments, kdl_action),
+ "ScrollToBottom" => {
+ parse_kdl_action_arguments!(action_name, action_arguments, kdl_action)
+ },
+ "PageScrollUp" => {
+ parse_kdl_action_arguments!(action_name, action_arguments, kdl_action)
+ },
+ "PageScrollDown" => {
+ parse_kdl_action_arguments!(action_name, action_arguments, kdl_action)
+ },
+ "HalfPageScrollUp" => {
+ parse_kdl_action_arguments!(action_name, action_arguments, kdl_action)
+ },
+ "HalfPageScrollDown" => {
+ parse_kdl_action_arguments!(action_name, action_arguments, kdl_action)
+ },
+ "ToggleFocusFullscreen" => {
+ parse_kdl_action_arguments!(action_name, action_arguments, kdl_action)
+ },
+ "TogglePaneFrames" => {
+ parse_kdl_action_arguments!(action_name, action_arguments, kdl_action)
+ },
+ "ToggleActiveSyncTab" => {
+ parse_kdl_action_arguments!(action_name, action_arguments, kdl_action)
+ },
+ "TogglePaneEmbedOrFloating" => {
+ parse_kdl_action_arguments!(action_name, action_arguments, kdl_action)
+ },
+ "ToggleFloatingPanes" => {
+ parse_kdl_action_arguments!(action_name, action_arguments, kdl_action)
+ },
+ "CloseFocus" => parse_kdl_action_arguments!(action_name, action_arguments, kdl_action),
+ "UndoRenamePane" => {
+ parse_kdl_action_arguments!(action_name, action_arguments, kdl_action)
+ },
+ "NoOp" => parse_kdl_action_arguments!(action_name, action_arguments, kdl_action),
+ "GoToNextTab" => parse_kdl_action_arguments!(action_name, action_arguments, kdl_action),
+ "GoToPreviousTab" => {
+ parse_kdl_action_arguments!(action_name, action_arguments, kdl_action)
+ },
+ "CloseTab" => parse_kdl_action_arguments!(action_name, action_arguments, kdl_action),
+ "ToggleTab" => parse_kdl_action_arguments!(action_name, action_arguments, kdl_action),
+ "UndoRenameTab" => {
+ parse_kdl_action_arguments!(action_name, action_arguments, kdl_action)
+ },
+ "Detach" => parse_kdl_action_arguments!(action_name, action_arguments, kdl_action),
+ "Copy" => parse_kdl_action_arguments!(action_name, action_arguments, kdl_action),
+ "Confirm" => parse_kdl_action_arguments!(action_name, action_arguments, kdl_action),
+ "Deny" => parse_kdl_action_arguments!(action_name, action_arguments, kdl_action),
+ "Write" => parse_kdl_action_u8_arguments!(action_name, action_arguments, kdl_action),
+ "WriteChars" => parse_kdl_action_char_or_string_arguments!(
+ action_name,
+ action_arguments,
+ kdl_action
+ ),
+ "SwitchToMode" => parse_kdl_action_char_or_string_arguments!(
+ action_name,
+ action_arguments,
+ kdl_action
+ ),
+ "Search" => parse_kdl_action_char_or_string_arguments!(
+ action_name,
+ action_arguments,
+ kdl_action
+ ),
+ "Resize" => parse_kdl_action_char_or_string_arguments!(
+ action_name,
+ action_arguments,
+ kdl_action
+ )