feat(layout): specify only tab name in tabs section (#722)

Allow specifying only the tab name in the `tabs` section

- For example this is now possible:
```
tabs:
  - name: first
    parts:
      - direction: Vertical
      - direction: Vertical
  - name: second
  - name: third
```
  For that the tab section defaults the direction to
  `direction::Horizontal`

- Adds an error upon specifying a tab name inside the `parts` section
  of the tab-layout
This commit is contained in:
a-kenji 2021-09-21 16:39:37 +02:00 committed by GitHub
parent 71b600b821
commit bbe2583904
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 47 additions and 69 deletions

View File

@ -45,9 +45,8 @@ pub enum ConfigError {
IoPath(io::Error, PathBuf),
// Internal Deserialization Error
FromUtf8(std::string::FromUtf8Error),
// Missing the tab section in the layout.
Layout(LayoutMissingTabSectionError),
LayoutPartAndTab(LayoutPartAndTabError),
// Naming a part in a tab is unsupported
LayoutNameInTab(LayoutNameInTabError),
}
impl Default for Config {
@ -139,70 +138,32 @@ impl Config {
// TODO: Split errors up into separate modules
#[derive(Debug, Clone)]
pub struct LayoutMissingTabSectionError;
#[derive(Debug, Clone)]
pub struct LayoutPartAndTabError;
pub struct LayoutNameInTabError;
impl fmt::Display for LayoutMissingTabSectionError {
impl fmt::Display for LayoutNameInTabError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"MissingTabSectionError:
There needs to be exactly one `tabs` section specified in the layout file, for example:
"LayoutNameInTabError:
The `parts` inside the `tabs` can't be named. For example:
---
direction: Horizontal
parts:
- direction: Vertical
- direction: Vertical
tabs:
- direction: Vertical
- direction: Vertical
- direction: Vertical
"
)
}
}
impl std::error::Error for LayoutMissingTabSectionError {
fn description(&self) -> &str {
"One tab must be specified per Layout."
}
}
impl fmt::Display for LayoutPartAndTabError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"LayoutPartAndTabError:
The `tabs` and `parts` section should not be specified on the same level in the layout file, for example:
---
direction: Horizontal
parts:
- direction: Vertical
- direction: Vertical
tabs:
- direction: Vertical
- direction: Vertical
- direction: Vertical
should rather be specified as:
---
direction: Horizontal
parts:
- direction: Vertical
- direction: Vertical
tabs:
- direction: Vertical
name: main
parts:
- direction: Vertical
name: section # <== The part section can't be named.
- direction: Vertical
- direction: Vertical
name: test
"
)
}
}
impl std::error::Error for LayoutPartAndTabError {
impl std::error::Error for LayoutNameInTabError {
fn description(&self) -> &str {
"The `tabs` and parts section should not be specified on the same level."
"The `parts` inside the `tabs` can't be named."
}
}
@ -215,10 +176,7 @@ impl Display for ConfigError {
}
ConfigError::Serde(ref err) => write!(formatter, "Deserialization error: {}", err),
ConfigError::FromUtf8(ref err) => write!(formatter, "FromUtf8Error: {}", err),
ConfigError::Layout(ref err) => {
write!(formatter, "There was an error in the layout file, {}", err)
}
ConfigError::LayoutPartAndTab(ref err) => {
ConfigError::LayoutNameInTab(ref err) => {
write!(formatter, "There was an error in the layout file, {}", err)
}
}
@ -232,8 +190,7 @@ impl std::error::Error for ConfigError {
ConfigError::IoPath(ref err, _) => Some(err),
ConfigError::Serde(ref err) => Some(err),
ConfigError::FromUtf8(ref err) => Some(err),
ConfigError::Layout(ref err) => Some(err),
ConfigError::LayoutPartAndTab(ref err) => Some(err),
ConfigError::LayoutNameInTab(ref err) => Some(err),
}
}
}
@ -256,15 +213,9 @@ impl From<std::string::FromUtf8Error> for ConfigError {
}
}
impl From<LayoutMissingTabSectionError> for ConfigError {
fn from(err: LayoutMissingTabSectionError) -> ConfigError {
ConfigError::Layout(err)
}
}
impl From<LayoutPartAndTabError> for ConfigError {
fn from(err: LayoutPartAndTabError) -> ConfigError {
ConfigError::LayoutPartAndTab(err)
impl From<LayoutNameInTabError> for ConfigError {
fn from(err: LayoutNameInTabError) -> ConfigError {
ConfigError::LayoutNameInTab(err)
}
}

View File

@ -9,7 +9,10 @@
// If plugins should be able to depend on the layout system
// then [`zellij-utils`] could be a proper place.
use crate::{
input::{command::RunCommand, config::ConfigError},
input::{
command::RunCommand,
config::{ConfigError, LayoutNameInTabError},
},
pane_size::{Dimension, PaneGeom},
setup,
};
@ -106,7 +109,12 @@ impl LayoutFromYaml {
let layout: Option<LayoutFromYaml> = serde_yaml::from_str(&layout)?;
match layout {
Some(layout) => Ok(layout),
Some(layout) => {
for tab in layout.tabs.clone() {
tab.check()?;
}
Ok(layout)
}
None => Ok(LayoutFromYaml::default()),
}
}
@ -220,6 +228,7 @@ impl LayoutTemplate {
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
#[serde(crate = "self::serde")]
pub struct TabLayout {
#[serde(default)]
pub direction: Direction,
#[serde(default)]
pub borderless: bool,
@ -231,6 +240,18 @@ pub struct TabLayout {
pub name: String,
}
impl TabLayout {
fn check(&self) -> Result<TabLayout, ConfigError> {
for part in self.parts.iter() {
part.check()?;
if !part.name.is_empty() {
return Err(ConfigError::LayoutNameInTab(LayoutNameInTabError));
}
}
Ok(self.clone())
}
}
impl Layout {
pub fn total_terminal_panes(&self) -> usize {
let mut total_panes = 0;
@ -467,6 +488,12 @@ impl Default for LayoutFromYaml {
}
}
impl Default for Direction {
fn default() -> Self {
Direction::Horizontal
}
}
// The unit test location.
#[cfg(test)]
#[path = "./unit/layout_test.rs"]