Add template section in layout file
It works as follows:
```
---
template:
direction: Horizontal
parts:
- direction: Vertical
split_size:
Fixed: 1
run:
plugin: tab-bar
- direction: Vertical
body: true
- direction: Vertical
split_size:
Fixed: 2
run:
plugin: status-bar
tabs:
- direction: Vertical
```
The tabs are created in the body section of the template.
This commit is contained in:
parent
2e17756785
commit
88b4063879
17 changed files with 484 additions and 428 deletions
|
|
@ -19,7 +19,7 @@ use zellij_utils::{
|
||||||
channels::{self, ChannelWithContext, SenderWithContext},
|
channels::{self, ChannelWithContext, SenderWithContext},
|
||||||
consts::{SESSION_NAME, ZELLIJ_IPC_PIPE},
|
consts::{SESSION_NAME, ZELLIJ_IPC_PIPE},
|
||||||
errors::{ClientContext, ContextType, ErrorInstruction},
|
errors::{ClientContext, ContextType, ErrorInstruction},
|
||||||
input::{actions::Action, config::Config, layout::MainLayout, options::Options},
|
input::{actions::Action, config::Config, layout::LayoutTemplate, options::Options},
|
||||||
ipc::{ClientAttributes, ClientToServerMsg, ExitReason, ServerToClientMsg},
|
ipc::{ClientAttributes, ClientToServerMsg, ExitReason, ServerToClientMsg},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -87,7 +87,7 @@ pub fn start_client(
|
||||||
opts: CliArgs,
|
opts: CliArgs,
|
||||||
config: Config,
|
config: Config,
|
||||||
info: ClientInfo,
|
info: ClientInfo,
|
||||||
layout: Option<MainLayout>,
|
layout: Option<LayoutTemplate>,
|
||||||
) {
|
) {
|
||||||
info!("Starting Zellij client!");
|
info!("Starting Zellij client!");
|
||||||
let clear_client_terminal_attributes = "\u{1b}[?1l\u{1b}=\u{1b}[r\u{1b}12l\u{1b}[?1000l\u{1b}[?1002l\u{1b}[?1003l\u{1b}[?1005l\u{1b}[?1006l\u{1b}[?12l";
|
let clear_client_terminal_attributes = "\u{1b}[?1l\u{1b}=\u{1b}[r\u{1b}12l\u{1b}[?1000l\u{1b}[?1002l\u{1b}[?1003l\u{1b}[?1005l\u{1b}[?1006l\u{1b}[?12l";
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ use zellij_utils::{
|
||||||
input::{
|
input::{
|
||||||
command::{RunCommand, TerminalAction},
|
command::{RunCommand, TerminalAction},
|
||||||
get_mode_info,
|
get_mode_info,
|
||||||
layout::MainLayout,
|
layout::LayoutTemplate,
|
||||||
options::Options,
|
options::Options,
|
||||||
},
|
},
|
||||||
ipc::{ClientAttributes, ClientToServerMsg, ExitReason, ServerToClientMsg},
|
ipc::{ClientAttributes, ClientToServerMsg, ExitReason, ServerToClientMsg},
|
||||||
|
|
@ -50,7 +50,7 @@ pub(crate) enum ServerInstruction {
|
||||||
ClientAttributes,
|
ClientAttributes,
|
||||||
Box<CliArgs>,
|
Box<CliArgs>,
|
||||||
Box<Options>,
|
Box<Options>,
|
||||||
Option<MainLayout>,
|
Option<LayoutTemplate>,
|
||||||
),
|
),
|
||||||
Render(Option<String>),
|
Render(Option<String>),
|
||||||
UnblockInputThread,
|
UnblockInputThread,
|
||||||
|
|
@ -329,7 +329,7 @@ fn init_session(
|
||||||
to_server: SenderWithContext<ServerInstruction>,
|
to_server: SenderWithContext<ServerInstruction>,
|
||||||
client_attributes: ClientAttributes,
|
client_attributes: ClientAttributes,
|
||||||
session_state: Arc<RwLock<SessionState>>,
|
session_state: Arc<RwLock<SessionState>>,
|
||||||
layout: Option<MainLayout>,
|
layout: Option<LayoutTemplate>,
|
||||||
) -> SessionMetaData {
|
) -> SessionMetaData {
|
||||||
let (to_screen, screen_receiver): ChannelWithContext<ScreenInstruction> = channels::unbounded();
|
let (to_screen, screen_receiver): ChannelWithContext<ScreenInstruction> = channels::unbounded();
|
||||||
let to_screen = SenderWithContext::new(to_screen);
|
let to_screen = SenderWithContext::new(to_screen);
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ use zellij_utils::{
|
||||||
errors::{get_current_ctx, ContextType, PtyContext},
|
errors::{get_current_ctx, ContextType, PtyContext},
|
||||||
input::{
|
input::{
|
||||||
command::TerminalAction,
|
command::TerminalAction,
|
||||||
layout::{Layout, MainLayout, Run, TabLayout},
|
layout::{Layout, LayoutTemplate, Run, TabLayout},
|
||||||
},
|
},
|
||||||
logging::debug_to_file,
|
logging::debug_to_file,
|
||||||
};
|
};
|
||||||
|
|
@ -60,7 +60,7 @@ pub(crate) struct Pty {
|
||||||
task_handles: HashMap<RawFd, JoinHandle<()>>,
|
task_handles: HashMap<RawFd, JoinHandle<()>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn pty_thread_main(mut pty: Pty, maybe_layout: Option<MainLayout>) {
|
pub(crate) fn pty_thread_main(mut pty: Pty, maybe_layout: Option<LayoutTemplate>) {
|
||||||
loop {
|
loop {
|
||||||
let (event, mut err_ctx) = pty.bus.recv().expect("failed to receive event on channel");
|
let (event, mut err_ctx) = pty.bus.recv().expect("failed to receive event on channel");
|
||||||
err_ctx.add_call(ContextType::Pty((&event).into()));
|
err_ctx.add_call(ContextType::Pty((&event).into()));
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
---
|
---
|
||||||
|
template:
|
||||||
direction: Horizontal
|
direction: Horizontal
|
||||||
parts:
|
parts:
|
||||||
- direction: Vertical
|
- direction: Vertical
|
||||||
|
|
@ -7,10 +8,11 @@ parts:
|
||||||
run:
|
run:
|
||||||
plugin: tab-bar
|
plugin: tab-bar
|
||||||
- direction: Vertical
|
- direction: Vertical
|
||||||
tabs:
|
body: true
|
||||||
- direction: Vertical
|
|
||||||
- direction: Vertical
|
- direction: Vertical
|
||||||
split_size:
|
split_size:
|
||||||
Fixed: 2
|
Fixed: 2
|
||||||
run:
|
run:
|
||||||
plugin: status-bar
|
plugin: status-bar
|
||||||
|
tabs:
|
||||||
|
- direction: Vertical
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
---
|
---
|
||||||
|
template:
|
||||||
direction: Horizontal
|
direction: Horizontal
|
||||||
parts:
|
parts:
|
||||||
- direction: Vertical
|
- direction: Vertical
|
||||||
|
|
@ -7,5 +8,4 @@ parts:
|
||||||
run:
|
run:
|
||||||
plugin: tab-bar
|
plugin: tab-bar
|
||||||
- direction: Vertical
|
- direction: Vertical
|
||||||
tabs:
|
body: true
|
||||||
- direction: Vertical
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
---
|
---
|
||||||
|
template:
|
||||||
direction: Horizontal
|
direction: Horizontal
|
||||||
parts:
|
parts:
|
||||||
- direction: Vertical
|
- direction: Vertical
|
||||||
|
|
@ -7,6 +8,12 @@ parts:
|
||||||
run:
|
run:
|
||||||
plugin: tab-bar
|
plugin: tab-bar
|
||||||
- direction: Vertical
|
- direction: Vertical
|
||||||
|
body: true
|
||||||
|
- direction: Vertical
|
||||||
|
split_size:
|
||||||
|
Fixed: 2
|
||||||
|
run:
|
||||||
|
plugin: status-bar
|
||||||
tabs:
|
tabs:
|
||||||
- direction: Vertical
|
- direction: Vertical
|
||||||
parts:
|
parts:
|
||||||
|
|
@ -16,8 +23,3 @@ parts:
|
||||||
run:
|
run:
|
||||||
plugin: strider
|
plugin: strider
|
||||||
- direction: Horizontal
|
- direction: Horizontal
|
||||||
- direction: Vertical
|
|
||||||
split_size:
|
|
||||||
Fixed: 2
|
|
||||||
run:
|
|
||||||
plugin: status-bar
|
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,159 @@ pub struct Layout {
|
||||||
pub run: Option<Run>,
|
pub run: Option<Run>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The struct that is used to deserialize the layout from
|
||||||
|
// a yaml configuration file
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
|
||||||
|
#[serde(crate = "self::serde")]
|
||||||
|
pub struct LayoutFromYaml {
|
||||||
|
//#[serde(default)]
|
||||||
|
pub template: LayoutTemplateFromYaml,
|
||||||
|
#[serde(default)]
|
||||||
|
pub tabs: Vec<TabLayout>,
|
||||||
|
}
|
||||||
|
|
||||||
|
type LayoutFromYamlResult = Result<LayoutFromYaml, ConfigError>;
|
||||||
|
|
||||||
|
impl LayoutFromYaml {
|
||||||
|
pub fn new(layout_path: &Path) -> LayoutFromYamlResult {
|
||||||
|
let mut layout_file = File::open(&layout_path)
|
||||||
|
.or_else(|_| File::open(&layout_path.with_extension("yaml")))
|
||||||
|
.map_err(|e| ConfigError::IoPath(e, layout_path.into()))?;
|
||||||
|
|
||||||
|
let mut layout = String::new();
|
||||||
|
layout_file.read_to_string(&mut layout)?;
|
||||||
|
let layout: LayoutFromYaml = serde_yaml::from_str(&layout)?;
|
||||||
|
Ok(layout)
|
||||||
|
}
|
||||||
|
|
||||||
|
// It wants to use Path here, but that doesn't compile.
|
||||||
|
#[allow(clippy::ptr_arg)]
|
||||||
|
pub fn from_dir(layout: &PathBuf, layout_dir: Option<&PathBuf>) -> LayoutFromYamlResult {
|
||||||
|
match layout_dir {
|
||||||
|
Some(dir) => Self::new(&dir.join(layout))
|
||||||
|
.or_else(|_| Self::from_default_assets(layout.as_path())),
|
||||||
|
None => Self::from_default_assets(layout.as_path()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_path_or_default(
|
||||||
|
layout: Option<&PathBuf>,
|
||||||
|
layout_path: Option<&PathBuf>,
|
||||||
|
layout_dir: Option<PathBuf>,
|
||||||
|
) -> Option<LayoutFromYamlResult> {
|
||||||
|
layout
|
||||||
|
.map(|p| LayoutFromYaml::from_dir(p, layout_dir.as_ref()))
|
||||||
|
.or_else(|| layout_path.map(|p| LayoutFromYaml::new(p)))
|
||||||
|
.or_else(|| {
|
||||||
|
Some(LayoutFromYaml::from_dir(
|
||||||
|
&std::path::PathBuf::from("default"),
|
||||||
|
layout_dir.as_ref(),
|
||||||
|
))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn construct_layout_template(&self) -> LayoutTemplate {
|
||||||
|
let (pre_tab, post_tab) = self.template.split_template().unwrap();
|
||||||
|
LayoutTemplate {
|
||||||
|
pre_tab: pre_tab.into(),
|
||||||
|
post_tab: Layout::from_vec_template_layout(post_tab),
|
||||||
|
tabs: self.tabs.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Currently still needed but on nightly
|
||||||
|
// this is already possible:
|
||||||
|
// HashMap<&'static str, Vec<u8>>
|
||||||
|
pub fn from_default_assets(path: &Path) -> LayoutFromYamlResult {
|
||||||
|
match path.to_str() {
|
||||||
|
Some("default") => Self::default_from_assets(),
|
||||||
|
Some("strider") => Self::strider_from_assets(),
|
||||||
|
Some("disable-status-bar") => Self::disable_status_from_assets(),
|
||||||
|
None | Some(_) => Err(ConfigError::IoPath(
|
||||||
|
std::io::Error::new(std::io::ErrorKind::Other, "The layout was not found"),
|
||||||
|
path.into(),
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO Deserialize the assets from bytes &[u8],
|
||||||
|
// once serde-yaml supports zero-copy
|
||||||
|
pub fn default_from_assets() -> LayoutFromYamlResult {
|
||||||
|
let layout: LayoutFromYaml =
|
||||||
|
serde_yaml::from_str(String::from_utf8(setup::DEFAULT_LAYOUT.to_vec())?.as_str())?;
|
||||||
|
Ok(layout)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn strider_from_assets() -> LayoutFromYamlResult {
|
||||||
|
let layout: LayoutFromYaml =
|
||||||
|
serde_yaml::from_str(String::from_utf8(setup::STRIDER_LAYOUT.to_vec())?.as_str())?;
|
||||||
|
Ok(layout)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn disable_status_from_assets() -> LayoutFromYamlResult {
|
||||||
|
let layout: LayoutFromYaml =
|
||||||
|
serde_yaml::from_str(String::from_utf8(setup::NO_STATUS_LAYOUT.to_vec())?.as_str())?;
|
||||||
|
Ok(layout)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The struct that carries the information template that is used to
|
||||||
|
// construct the layout
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
|
||||||
|
#[serde(crate = "self::serde")]
|
||||||
|
pub struct LayoutTemplateFromYaml {
|
||||||
|
pub direction: Direction,
|
||||||
|
#[serde(default)]
|
||||||
|
pub parts: Vec<LayoutTemplateFromYaml>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub body: bool,
|
||||||
|
pub split_size: Option<SplitSize>,
|
||||||
|
pub run: Option<Run>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LayoutTemplateFromYaml {
|
||||||
|
// Split the layout into parts that can be reassebled per tab
|
||||||
|
// returns the layout pre tab and the parts post tab
|
||||||
|
pub fn split_template(
|
||||||
|
&self,
|
||||||
|
) -> Result<(LayoutTemplateFromYaml, Vec<LayoutTemplateFromYaml>), LayoutPartAndTabError> {
|
||||||
|
let mut main_layout = self.clone();
|
||||||
|
let mut pre_tab_layout = self.clone();
|
||||||
|
let mut post_tab_layout = vec![];
|
||||||
|
let mut post_tab = false;
|
||||||
|
|
||||||
|
pre_tab_layout.parts.clear();
|
||||||
|
|
||||||
|
if main_layout.body {
|
||||||
|
post_tab = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for part in main_layout.parts.drain(..) {
|
||||||
|
let (curr_pre_layout, mut curr_post_layout) = part.split_template()?;
|
||||||
|
|
||||||
|
// Leaf
|
||||||
|
if !post_tab && !part.body {
|
||||||
|
pre_tab_layout.parts.push(curr_pre_layout);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Node
|
||||||
|
if part.body {
|
||||||
|
post_tab = true;
|
||||||
|
// Leaf
|
||||||
|
} else if post_tab {
|
||||||
|
if curr_post_layout.is_empty() {
|
||||||
|
let mut part_no_tab = part.clone();
|
||||||
|
part_no_tab.parts.clear();
|
||||||
|
post_tab_layout.push(part_no_tab);
|
||||||
|
} else {
|
||||||
|
post_tab_layout.append(&mut curr_post_layout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok((pre_tab_layout, post_tab_layout))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// The tab-layout struct used to specify each individual tab.
|
// The tab-layout struct used to specify each individual tab.
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
|
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
|
||||||
#[serde(crate = "self::serde")]
|
#[serde(crate = "self::serde")]
|
||||||
|
|
@ -69,17 +222,17 @@ pub struct TabLayout {
|
||||||
pub run: Option<Run>,
|
pub run: Option<Run>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Main layout struct, that carries information based on position of tabs
|
// Main template layout struct, that carries information based on position of
|
||||||
// in relation to the whole layout.
|
// tabs in relation to the whole layout.
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
|
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
|
||||||
#[serde(crate = "self::serde")]
|
#[serde(crate = "self::serde")]
|
||||||
pub struct MainLayout {
|
pub struct LayoutTemplate {
|
||||||
pub pre_tab: Layout,
|
pub pre_tab: Layout,
|
||||||
pub post_tab: Vec<Layout>,
|
pub post_tab: Vec<Layout>,
|
||||||
pub tabs: Vec<TabLayout>,
|
pub tabs: Vec<TabLayout>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MainLayout {
|
impl LayoutTemplate {
|
||||||
pub fn construct_tab_layout(&self, tab_layout: Option<TabLayout>) -> Layout {
|
pub fn construct_tab_layout(&self, tab_layout: Option<TabLayout>) -> Layout {
|
||||||
if let Some(tab_layout) = tab_layout {
|
if let Some(tab_layout) = tab_layout {
|
||||||
let mut pre_tab_layout = self.pre_tab.clone();
|
let mut pre_tab_layout = self.pre_tab.clone();
|
||||||
|
|
@ -98,81 +251,7 @@ impl MainLayout {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type LayoutResult = Result<Layout, ConfigError>;
|
|
||||||
|
|
||||||
impl Layout {
|
impl Layout {
|
||||||
pub fn new(layout_path: &Path) -> LayoutResult {
|
|
||||||
let mut layout_file = File::open(&layout_path)
|
|
||||||
.or_else(|_| File::open(&layout_path.with_extension("yaml")))
|
|
||||||
.map_err(|e| ConfigError::IoPath(e, layout_path.into()))?;
|
|
||||||
|
|
||||||
let mut layout = String::new();
|
|
||||||
layout_file.read_to_string(&mut layout)?;
|
|
||||||
let layout: Layout = serde_yaml::from_str(&layout)?;
|
|
||||||
Ok(layout)
|
|
||||||
}
|
|
||||||
|
|
||||||
// It wants to use Path here, but that doesn't compile.
|
|
||||||
#[allow(clippy::ptr_arg)]
|
|
||||||
pub fn from_dir(layout: &PathBuf, layout_dir: Option<&PathBuf>) -> LayoutResult {
|
|
||||||
match layout_dir {
|
|
||||||
Some(dir) => Self::new(&dir.join(layout))
|
|
||||||
.or_else(|_| Self::from_default_assets(layout.as_path())),
|
|
||||||
None => Self::from_default_assets(layout.as_path()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn from_path_or_default(
|
|
||||||
layout: Option<&PathBuf>,
|
|
||||||
layout_path: Option<&PathBuf>,
|
|
||||||
layout_dir: Option<PathBuf>,
|
|
||||||
) -> Option<Result<Layout, ConfigError>> {
|
|
||||||
layout
|
|
||||||
.map(|p| Layout::from_dir(p, layout_dir.as_ref()))
|
|
||||||
.or_else(|| layout_path.map(|p| Layout::new(p)))
|
|
||||||
.or_else(|| {
|
|
||||||
Some(Layout::from_dir(
|
|
||||||
&std::path::PathBuf::from("default"),
|
|
||||||
layout_dir.as_ref(),
|
|
||||||
))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Currently still needed but on nightly
|
|
||||||
// this is already possible:
|
|
||||||
// HashMap<&'static str, Vec<u8>>
|
|
||||||
pub fn from_default_assets(path: &Path) -> LayoutResult {
|
|
||||||
match path.to_str() {
|
|
||||||
Some("default") => Self::default_from_assets(),
|
|
||||||
Some("strider") => Self::strider_from_assets(),
|
|
||||||
Some("disable-status-bar") => Self::disable_status_from_assets(),
|
|
||||||
None | Some(_) => Err(ConfigError::IoPath(
|
|
||||||
std::io::Error::new(std::io::ErrorKind::Other, "The layout was not found"),
|
|
||||||
path.into(),
|
|
||||||
)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO Deserialize the assets from bytes &[u8],
|
|
||||||
// once serde-yaml supports zero-copy
|
|
||||||
pub fn default_from_assets() -> LayoutResult {
|
|
||||||
let layout: Layout =
|
|
||||||
serde_yaml::from_str(String::from_utf8(setup::DEFAULT_LAYOUT.to_vec())?.as_str())?;
|
|
||||||
Ok(layout)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn strider_from_assets() -> LayoutResult {
|
|
||||||
let layout: Layout =
|
|
||||||
serde_yaml::from_str(String::from_utf8(setup::STRIDER_LAYOUT.to_vec())?.as_str())?;
|
|
||||||
Ok(layout)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn disable_status_from_assets() -> LayoutResult {
|
|
||||||
let layout: Layout =
|
|
||||||
serde_yaml::from_str(String::from_utf8(setup::NO_STATUS_LAYOUT.to_vec())?.as_str())?;
|
|
||||||
Ok(layout)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn total_terminal_panes(&self) -> usize {
|
pub fn total_terminal_panes(&self) -> usize {
|
||||||
let mut total_panes = 0;
|
let mut total_panes = 0;
|
||||||
total_panes += self.parts.len();
|
total_panes += self.parts.len();
|
||||||
|
|
@ -273,28 +352,14 @@ impl Layout {
|
||||||
self.parts.append(&mut parts);
|
self.parts.append(&mut parts);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn construct_full_layout(&self, tab_layout: Option<TabLayout>) -> Self {
|
pub fn construct_layout_template(&self) -> Result<LayoutTemplate, ConfigError> {
|
||||||
// The `split_main_and_tab_layout()` error should have returned
|
|
||||||
// already from deserialisation, so we can assume it is `Ok()`.
|
|
||||||
let (mut pre_tab_layout, post_tab_layout, _) = self.split_main_and_tab_layout().unwrap();
|
|
||||||
if let Some(tab_layout) = tab_layout {
|
|
||||||
pre_tab_layout.merge_tab_layout(tab_layout);
|
|
||||||
} else {
|
|
||||||
let default_tab_layout = TabLayout::default();
|
|
||||||
pre_tab_layout.merge_tab_layout(default_tab_layout);
|
|
||||||
}
|
|
||||||
pre_tab_layout.merge_layout_parts(post_tab_layout);
|
|
||||||
pre_tab_layout
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn construct_main_layout(&self) -> Result<MainLayout, ConfigError> {
|
|
||||||
let (pre_tab, post_tab, tabs) = self.split_main_and_tab_layout()?;
|
let (pre_tab, post_tab, tabs) = self.split_main_and_tab_layout()?;
|
||||||
|
|
||||||
if tabs.is_empty() {
|
if tabs.is_empty() {
|
||||||
return Err(ConfigError::Layout(LayoutMissingTabSectionError));
|
return Err(ConfigError::Layout(LayoutMissingTabSectionError));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(MainLayout {
|
Ok(LayoutTemplate {
|
||||||
pre_tab,
|
pre_tab,
|
||||||
post_tab,
|
post_tab,
|
||||||
tabs,
|
tabs,
|
||||||
|
|
@ -307,6 +372,13 @@ impl Layout {
|
||||||
.map(|tab_layout| Layout::from(tab_layout.to_owned()))
|
.map(|tab_layout| Layout::from(tab_layout.to_owned()))
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn from_vec_template_layout(layout_template: Vec<LayoutTemplateFromYaml>) -> Vec<Self> {
|
||||||
|
layout_template
|
||||||
|
.iter()
|
||||||
|
.map(|layout_template| Layout::from(layout_template.to_owned()))
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn split_space_to_parts_vertically(
|
fn split_space_to_parts_vertically(
|
||||||
|
|
@ -474,6 +546,18 @@ impl From<TabLayout> for Layout {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<LayoutTemplateFromYaml> for Layout {
|
||||||
|
fn from(template: LayoutTemplateFromYaml) -> Self {
|
||||||
|
Layout {
|
||||||
|
direction: template.direction,
|
||||||
|
parts: Layout::from_vec_template_layout(template.parts),
|
||||||
|
tabs: vec![],
|
||||||
|
split_size: template.split_size,
|
||||||
|
run: template.run,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Default for TabLayout {
|
impl Default for TabLayout {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
---
|
---
|
||||||
|
template:
|
||||||
direction: Horizontal
|
direction: Horizontal
|
||||||
parts:
|
parts:
|
||||||
- direction: Vertical
|
- direction: Vertical
|
||||||
|
|
@ -23,10 +24,7 @@ parts:
|
||||||
- direction: Vertical
|
- direction: Vertical
|
||||||
split_size:
|
split_size:
|
||||||
Percent: 77
|
Percent: 77
|
||||||
tabs:
|
body: true
|
||||||
- direction: Horizontal
|
|
||||||
split_size:
|
|
||||||
Percent: 24
|
|
||||||
split_size:
|
split_size:
|
||||||
Percent: 90
|
Percent: 90
|
||||||
- direction: Vertical
|
- direction: Vertical
|
||||||
|
|
@ -38,3 +36,8 @@ parts:
|
||||||
- direction: Vertical
|
- direction: Vertical
|
||||||
split_size:
|
split_size:
|
||||||
Percent: 15
|
Percent: 15
|
||||||
|
|
||||||
|
tabs:
|
||||||
|
- direction: Horizontal
|
||||||
|
split_size:
|
||||||
|
Percent: 24
|
||||||
|
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
---
|
|
||||||
direction: Horizontal
|
|
||||||
parts:
|
|
||||||
- direction: Horizontal
|
|
||||||
parts:
|
|
||||||
- direction: Vertical
|
|
||||||
parts:
|
|
||||||
- direction: Horizontal
|
|
||||||
split_size:
|
|
||||||
Percent: 50
|
|
||||||
- direction: Horizontal
|
|
||||||
parts:
|
|
||||||
- direction: Vertical
|
|
||||||
split_size:
|
|
||||||
Percent: 50
|
|
||||||
- direction: Vertical
|
|
||||||
split_size:
|
|
||||||
Percent: 50
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
---
|
|
||||||
direction: Horizontal
|
|
||||||
parts:
|
|
||||||
- direction: Horizontal
|
|
||||||
tabs:
|
|
||||||
- direction: Vertical
|
|
||||||
parts:
|
|
||||||
- direction: Horizontal
|
|
||||||
split_size:
|
|
||||||
Percent: 50
|
|
||||||
parts:
|
|
||||||
- direction: Vertical
|
|
||||||
split_size:
|
|
||||||
Percent: 50
|
|
||||||
- direction: Vertical
|
|
||||||
split_size:
|
|
||||||
Percent: 50
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
---
|
---
|
||||||
|
template:
|
||||||
direction: Horizontal
|
direction: Horizontal
|
||||||
parts:
|
parts:
|
||||||
- direction: Vertical
|
- direction: Vertical
|
||||||
|
|
@ -7,6 +8,13 @@ parts:
|
||||||
run:
|
run:
|
||||||
plugin: tab-bar
|
plugin: tab-bar
|
||||||
- direction: Horizontal
|
- direction: Horizontal
|
||||||
|
body: true
|
||||||
|
- direction: Vertical
|
||||||
|
split_size:
|
||||||
|
Fixed: 2
|
||||||
|
run:
|
||||||
|
plugin: status-bar
|
||||||
|
|
||||||
tabs:
|
tabs:
|
||||||
- direction: Vertical
|
- direction: Vertical
|
||||||
parts:
|
parts:
|
||||||
|
|
@ -25,8 +33,3 @@ parts:
|
||||||
Percent: 50
|
Percent: 50
|
||||||
run:
|
run:
|
||||||
command: {cmd: htop, args: ["-C"]}
|
command: {cmd: htop, args: ["-C"]}
|
||||||
- direction: Vertical
|
|
||||||
split_size:
|
|
||||||
Fixed: 2
|
|
||||||
run:
|
|
||||||
plugin: status-bar
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
---
|
---
|
||||||
|
template:
|
||||||
direction: Horizontal
|
direction: Horizontal
|
||||||
parts:
|
parts:
|
||||||
- direction: Vertical
|
- direction: Vertical
|
||||||
|
|
@ -7,6 +8,13 @@ parts:
|
||||||
run:
|
run:
|
||||||
plugin: tab-bar
|
plugin: tab-bar
|
||||||
- direction: Horizontal
|
- direction: Horizontal
|
||||||
|
body: true
|
||||||
|
- direction: Vertical
|
||||||
|
split_size:
|
||||||
|
Fixed: 2
|
||||||
|
run:
|
||||||
|
plugin: status-bar
|
||||||
|
|
||||||
tabs:
|
tabs:
|
||||||
- direction: Vertical
|
- direction: Vertical
|
||||||
parts:
|
parts:
|
||||||
|
|
@ -21,8 +29,3 @@ parts:
|
||||||
- direction: Vertical
|
- direction: Vertical
|
||||||
split_size:
|
split_size:
|
||||||
Percent: 50
|
Percent: 50
|
||||||
- direction: Vertical
|
|
||||||
split_size:
|
|
||||||
Fixed: 2
|
|
||||||
run:
|
|
||||||
plugin: status-bar
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,10 @@
|
||||||
---
|
---
|
||||||
|
template:
|
||||||
direction: Horizontal
|
direction: Horizontal
|
||||||
parts:
|
parts:
|
||||||
- direction: Horizontal
|
- direction: Horizontal
|
||||||
|
body: true
|
||||||
|
|
||||||
tabs:
|
tabs:
|
||||||
- direction: Vertical
|
- direction: Vertical
|
||||||
parts:
|
parts:
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,12 @@
|
||||||
---
|
---
|
||||||
|
template:
|
||||||
direction: Vertical
|
direction: Vertical
|
||||||
parts:
|
parts:
|
||||||
- direction: Horizontal
|
- direction: Horizontal
|
||||||
|
body: true
|
||||||
|
- direction: Horizontal
|
||||||
|
|
||||||
|
|
||||||
tabs:
|
tabs:
|
||||||
- direction: Horizontal
|
- direction: Horizontal
|
||||||
split_size:
|
split_size:
|
||||||
|
|
@ -22,4 +27,3 @@ parts:
|
||||||
split_size:
|
split_size:
|
||||||
Percent: 50
|
Percent: 50
|
||||||
- direction: Horizontal
|
- direction: Horizontal
|
||||||
- direction: Horizontal
|
|
||||||
|
|
|
||||||
|
|
@ -15,40 +15,43 @@ fn default_layout_dir(layout: String) -> PathBuf {
|
||||||
#[test]
|
#[test]
|
||||||
fn default_layout_is_ok() {
|
fn default_layout_is_ok() {
|
||||||
let path = default_layout_dir("default.yaml".into());
|
let path = default_layout_dir("default.yaml".into());
|
||||||
let layout = Layout::new(&path);
|
let layout = LayoutFromYaml::new(&path);
|
||||||
assert!(layout.is_ok());
|
assert!(layout.is_ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn default_layout_has_one_tab() {
|
fn default_layout_has_one_tab() {
|
||||||
let path = default_layout_dir("default.yaml".into());
|
let path = default_layout_dir("default.yaml".into());
|
||||||
let layout = Layout::new(&path);
|
let layout = LayoutFromYaml::new(&path);
|
||||||
let main_layout = layout.as_ref().unwrap().construct_main_layout().unwrap();
|
let layout_template = layout.as_ref().unwrap().construct_layout_template();
|
||||||
assert_eq!(main_layout.tabs.len(), 1);
|
assert_eq!(layout_template.tabs.len(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn default_layout_has_one_pre_tab() {
|
fn default_layout_has_one_pre_tab() {
|
||||||
let path = default_layout_dir("default.yaml".into());
|
let path = default_layout_dir("default.yaml".into());
|
||||||
let layout = Layout::new(&path);
|
let layout = LayoutFromYaml::new(&path);
|
||||||
let main_layout = layout.as_ref().unwrap().construct_main_layout().unwrap();
|
let layout_template = layout.as_ref().unwrap().construct_layout_template();
|
||||||
assert_eq!(main_layout.pre_tab.parts.len(), 1);
|
assert_eq!(layout_template.pre_tab.parts.len(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn default_layout_has_one_post_tab() {
|
fn default_layout_has_one_post_tab() {
|
||||||
let path = default_layout_dir("default.yaml".into());
|
let path = default_layout_dir("default.yaml".into());
|
||||||
let layout = Layout::new(&path);
|
let layout = LayoutFromYaml::new(&path);
|
||||||
let main_layout = layout.as_ref().unwrap().construct_main_layout().unwrap();
|
let layout_template = layout.as_ref().unwrap().construct_layout_template();
|
||||||
assert_eq!(main_layout.post_tab.len(), 1);
|
assert_eq!(layout_template.post_tab.len(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn default_layout_merged_correctly() {
|
fn default_layout_merged_correctly() {
|
||||||
let path = default_layout_dir("default.yaml".into());
|
let path = default_layout_dir("default.yaml".into());
|
||||||
let layout = Layout::new(&path);
|
let layout_from_yaml = LayoutFromYaml::new(&path);
|
||||||
let main_layout = layout.as_ref().unwrap().construct_main_layout().unwrap();
|
let layout_template = layout_from_yaml
|
||||||
let tab_layout = main_layout.construct_tab_layout(Some(main_layout.tabs[0].clone()));
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.construct_layout_template();
|
||||||
|
let tab_layout = layout_template.construct_tab_layout(Some(layout_template.tabs[0].clone()));
|
||||||
let merged_layout = Layout {
|
let merged_layout = Layout {
|
||||||
direction: Direction::Horizontal,
|
direction: Direction::Horizontal,
|
||||||
parts: vec![
|
parts: vec![
|
||||||
|
|
@ -84,9 +87,12 @@ fn default_layout_merged_correctly() {
|
||||||
#[test]
|
#[test]
|
||||||
fn default_layout_new_tab_correct() {
|
fn default_layout_new_tab_correct() {
|
||||||
let path = default_layout_dir("default.yaml".into());
|
let path = default_layout_dir("default.yaml".into());
|
||||||
let layout = Layout::new(&path);
|
let layout_from_yaml = LayoutFromYaml::new(&path);
|
||||||
let main_layout = layout.as_ref().unwrap().construct_main_layout().unwrap();
|
let layout_template = layout_from_yaml
|
||||||
let tab_layout = main_layout.construct_tab_layout(None);
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.construct_layout_template();
|
||||||
|
let tab_layout = layout_template.construct_tab_layout(None);
|
||||||
let merged_layout = Layout {
|
let merged_layout = Layout {
|
||||||
direction: Direction::Horizontal,
|
direction: Direction::Horizontal,
|
||||||
parts: vec![
|
parts: vec![
|
||||||
|
|
@ -122,78 +128,84 @@ fn default_layout_new_tab_correct() {
|
||||||
#[test]
|
#[test]
|
||||||
fn default_strider_layout_is_ok() {
|
fn default_strider_layout_is_ok() {
|
||||||
let path = default_layout_dir("strider.yaml".into());
|
let path = default_layout_dir("strider.yaml".into());
|
||||||
let layout = Layout::new(&path);
|
let layout_from_yaml = LayoutFromYaml::new(&path);
|
||||||
assert!(layout.is_ok());
|
assert!(layout_from_yaml.is_ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn default_disable_status_layout_is_ok() {
|
fn default_disable_status_layout_is_ok() {
|
||||||
let path = default_layout_dir("disable-status-bar.yaml".into());
|
let path = default_layout_dir("disable-status-bar.yaml".into());
|
||||||
let layout = Layout::new(&path);
|
let layout_from_yaml = LayoutFromYaml::new(&path);
|
||||||
assert!(layout.is_ok());
|
assert!(layout_from_yaml.is_ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn default_disable_status_layout_has_one_tab() {
|
fn default_disable_status_layout_has_no_tab() {
|
||||||
let path = default_layout_dir("disable-status-bar.yaml".into());
|
let path = default_layout_dir("disable-status-bar.yaml".into());
|
||||||
let layout = Layout::new(&path);
|
let layout_from_yaml = LayoutFromYaml::new(&path);
|
||||||
let main_layout = layout.as_ref().unwrap().construct_main_layout().unwrap();
|
let layout_template = layout_from_yaml
|
||||||
assert_eq!(main_layout.tabs.len(), 1);
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.construct_layout_template();
|
||||||
|
assert_eq!(layout_template.tabs.len(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn default_disable_status_layout_has_one_pre_tab() {
|
fn default_disable_status_layout_has_one_pre_tab() {
|
||||||
let path = default_layout_dir("disable-status-bar.yaml".into());
|
let path = default_layout_dir("disable-status-bar.yaml".into());
|
||||||
let layout = Layout::new(&path);
|
let layout_from_yaml = LayoutFromYaml::new(&path);
|
||||||
let main_layout = layout.as_ref().unwrap().construct_main_layout().unwrap();
|
let layout_template = layout_from_yaml
|
||||||
assert_eq!(main_layout.pre_tab.parts.len(), 1);
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.construct_layout_template();
|
||||||
|
assert_eq!(layout_template.pre_tab.parts.len(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn default_disable_status_layout_has_no_post_tab() {
|
fn default_disable_status_layout_has_no_post_tab() {
|
||||||
let path = default_layout_dir("disable-status-bar.yaml".into());
|
let path = default_layout_dir("disable-status-bar.yaml".into());
|
||||||
let layout = Layout::new(&path);
|
let layout = LayoutFromYaml::new(&path);
|
||||||
let main_layout = layout.as_ref().unwrap().construct_main_layout().unwrap();
|
let layout_template = layout.as_ref().unwrap().construct_layout_template();
|
||||||
assert!(main_layout.post_tab.is_empty());
|
assert!(layout_template.post_tab.is_empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn three_panes_with_tab_is_ok() {
|
fn three_panes_with_tab_is_ok() {
|
||||||
let path = layout_test_dir("three-panes-with-tab.yaml".into());
|
let path = layout_test_dir("three-panes-with-tab.yaml".into());
|
||||||
let layout = Layout::new(&path);
|
let layout = LayoutFromYaml::new(&path);
|
||||||
assert!(layout.is_ok());
|
assert!(layout.is_ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn three_panes_with_tab_has_one_tab() {
|
fn three_panes_with_tab_has_one_tab() {
|
||||||
let path = layout_test_dir("three-panes-with-tab.yaml".into());
|
let path = layout_test_dir("three-panes-with-tab.yaml".into());
|
||||||
let layout = Layout::new(&path);
|
let layout = LayoutFromYaml::new(&path);
|
||||||
let main_layout = layout.unwrap().construct_main_layout().unwrap();
|
let layout_template = layout.unwrap().construct_layout_template();
|
||||||
assert_eq!(main_layout.tabs.len(), 1);
|
assert_eq!(layout_template.tabs.len(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn three_panes_with_tab_no_post_tab() {
|
fn three_panes_with_tab_no_post_tab() {
|
||||||
let path = layout_test_dir("three-panes-with-tab.yaml".into());
|
let path = layout_test_dir("three-panes-with-tab.yaml".into());
|
||||||
let layout = Layout::new(&path);
|
let layout = LayoutFromYaml::new(&path);
|
||||||
let main_layout = layout.unwrap().construct_main_layout().unwrap();
|
let layout_template = layout.unwrap().construct_layout_template();
|
||||||
assert!(main_layout.post_tab.is_empty());
|
assert!(layout_template.post_tab.is_empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn three_panes_with_tab_no_pre_tab() {
|
fn three_panes_with_tab_no_pre_tab() {
|
||||||
let path = layout_test_dir("three-panes-with-tab.yaml".into());
|
let path = layout_test_dir("three-panes-with-tab.yaml".into());
|
||||||
let layout = Layout::new(&path);
|
let layout = LayoutFromYaml::new(&path);
|
||||||
let main_layout = layout.unwrap().construct_main_layout().unwrap();
|
let layout_template = layout.unwrap().construct_layout_template();
|
||||||
assert!(main_layout.pre_tab.parts.is_empty());
|
assert!(layout_template.pre_tab.parts.is_empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn three_panes_with_tab_merged_correctly() {
|
fn three_panes_with_tab_merged_correctly() {
|
||||||
let path = layout_test_dir("three-panes-with-tab.yaml".into());
|
let path = layout_test_dir("three-panes-with-tab.yaml".into());
|
||||||
let layout = Layout::new(&path);
|
let layout = LayoutFromYaml::new(&path);
|
||||||
let main_layout = layout.as_ref().unwrap().construct_main_layout().unwrap();
|
let layout_template = layout.as_ref().unwrap().construct_layout_template();
|
||||||
let tab_layout = main_layout.construct_tab_layout(Some(main_layout.tabs[0].clone()));
|
let tab_layout = layout_template.construct_tab_layout(Some(layout_template.tabs[0].clone()));
|
||||||
let merged_layout = Layout {
|
let merged_layout = Layout {
|
||||||
direction: Direction::Horizontal,
|
direction: Direction::Horizontal,
|
||||||
parts: vec![Layout {
|
parts: vec![Layout {
|
||||||
|
|
@ -243,9 +255,9 @@ fn three_panes_with_tab_merged_correctly() {
|
||||||
#[test]
|
#[test]
|
||||||
fn three_panes_with_tab_new_tab_is_correct() {
|
fn three_panes_with_tab_new_tab_is_correct() {
|
||||||
let path = layout_test_dir("three-panes-with-tab.yaml".into());
|
let path = layout_test_dir("three-panes-with-tab.yaml".into());
|
||||||
let layout = Layout::new(&path);
|
let layout = LayoutFromYaml::new(&path);
|
||||||
let main_layout = layout.as_ref().unwrap().construct_main_layout().unwrap();
|
let layout_template = layout.as_ref().unwrap().construct_layout_template();
|
||||||
let tab_layout = main_layout.construct_tab_layout(None);
|
let tab_layout = layout_template.construct_tab_layout(None);
|
||||||
let merged_layout = Layout {
|
let merged_layout = Layout {
|
||||||
direction: Direction::Horizontal,
|
direction: Direction::Horizontal,
|
||||||
parts: vec![Layout {
|
parts: vec![Layout {
|
||||||
|
|
@ -265,40 +277,40 @@ fn three_panes_with_tab_new_tab_is_correct() {
|
||||||
#[test]
|
#[test]
|
||||||
fn three_panes_with_tab_and_default_plugins_is_ok() {
|
fn three_panes_with_tab_and_default_plugins_is_ok() {
|
||||||
let path = layout_test_dir("three-panes-with-tab-and-default-plugins.yaml".into());
|
let path = layout_test_dir("three-panes-with-tab-and-default-plugins.yaml".into());
|
||||||
let layout = Layout::new(&path);
|
let layout = LayoutFromYaml::new(&path);
|
||||||
assert!(layout.is_ok());
|
assert!(layout.is_ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn three_panes_with_tab_and_default_plugins_has_one_tab() {
|
fn three_panes_with_tab_and_default_plugins_has_one_tab() {
|
||||||
let path = layout_test_dir("three-panes-with-tab-and-default-plugins.yaml".into());
|
let path = layout_test_dir("three-panes-with-tab-and-default-plugins.yaml".into());
|
||||||
let layout = Layout::new(&path);
|
let layout = LayoutFromYaml::new(&path);
|
||||||
let main_layout = layout.unwrap().construct_main_layout().unwrap();
|
let layout_template = layout.unwrap().construct_layout_template();
|
||||||
assert_eq!(main_layout.tabs.len(), 1);
|
assert_eq!(layout_template.tabs.len(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn three_panes_with_tab_and_default_plugins_one_post_tab() {
|
fn three_panes_with_tab_and_default_plugins_one_post_tab() {
|
||||||
let path = layout_test_dir("three-panes-with-tab-and-default-plugins.yaml".into());
|
let path = layout_test_dir("three-panes-with-tab-and-default-plugins.yaml".into());
|
||||||
let layout = Layout::new(&path);
|
let layout = LayoutFromYaml::new(&path);
|
||||||
let main_layout = layout.unwrap().construct_main_layout().unwrap();
|
let layout_template = layout.unwrap().construct_layout_template();
|
||||||
assert_eq!(main_layout.post_tab.len(), 1);
|
assert_eq!(layout_template.post_tab.len(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn three_panes_with_tab_and_default_plugins_has_pre_tab() {
|
fn three_panes_with_tab_and_default_plugins_has_pre_tab() {
|
||||||
let path = layout_test_dir("three-panes-with-tab-and-default-plugins.yaml".into());
|
let path = layout_test_dir("three-panes-with-tab-and-default-plugins.yaml".into());
|
||||||
let layout = Layout::new(&path);
|
let layout = LayoutFromYaml::new(&path);
|
||||||
let main_layout = layout.unwrap().construct_main_layout().unwrap();
|
let layout_template = layout.unwrap().construct_layout_template();
|
||||||
assert!(!main_layout.pre_tab.parts.is_empty());
|
assert!(!layout_template.pre_tab.parts.is_empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn three_panes_with_tab_and_default_plugins_merged_correctly() {
|
fn three_panes_with_tab_and_default_plugins_merged_correctly() {
|
||||||
let path = layout_test_dir("three-panes-with-tab-and-default-plugins.yaml".into());
|
let path = layout_test_dir("three-panes-with-tab-and-default-plugins.yaml".into());
|
||||||
let layout = Layout::new(&path);
|
let layout = LayoutFromYaml::new(&path);
|
||||||
let main_layout = layout.as_ref().unwrap().construct_main_layout().unwrap();
|
let layout_template = layout.as_ref().unwrap().construct_layout_template();
|
||||||
let tab_layout = main_layout.construct_tab_layout(Some(main_layout.tabs[0].clone()));
|
let tab_layout = layout_template.construct_tab_layout(Some(layout_template.tabs[0].clone()));
|
||||||
let merged_layout = Layout {
|
let merged_layout = Layout {
|
||||||
direction: Direction::Horizontal,
|
direction: Direction::Horizontal,
|
||||||
parts: vec![
|
parts: vec![
|
||||||
|
|
@ -364,9 +376,9 @@ fn three_panes_with_tab_and_default_plugins_merged_correctly() {
|
||||||
#[test]
|
#[test]
|
||||||
fn three_panes_with_tab_and_default_plugins_new_tab_is_correct() {
|
fn three_panes_with_tab_and_default_plugins_new_tab_is_correct() {
|
||||||
let path = layout_test_dir("three-panes-with-tab-and-default-plugins.yaml".into());
|
let path = layout_test_dir("three-panes-with-tab-and-default-plugins.yaml".into());
|
||||||
let layout = Layout::new(&path);
|
let layout = LayoutFromYaml::new(&path);
|
||||||
let main_layout = layout.as_ref().unwrap().construct_main_layout().unwrap();
|
let layout_template = layout.as_ref().unwrap().construct_layout_template();
|
||||||
let tab_layout = main_layout.construct_tab_layout(None);
|
let tab_layout = layout_template.construct_tab_layout(None);
|
||||||
let merged_layout = Layout {
|
let merged_layout = Layout {
|
||||||
direction: Direction::Horizontal,
|
direction: Direction::Horizontal,
|
||||||
parts: vec![
|
parts: vec![
|
||||||
|
|
@ -402,40 +414,40 @@ fn three_panes_with_tab_and_default_plugins_new_tab_is_correct() {
|
||||||
#[test]
|
#[test]
|
||||||
fn deeply_nested_tab_is_ok() {
|
fn deeply_nested_tab_is_ok() {
|
||||||
let path = layout_test_dir("deeply-nested-tab-layout.yaml".into());
|
let path = layout_test_dir("deeply-nested-tab-layout.yaml".into());
|
||||||
let layout = Layout::new(&path);
|
let layout = LayoutFromYaml::new(&path);
|
||||||
assert!(layout.is_ok());
|
assert!(layout.is_ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn deeply_nested_tab_has_one_tab() {
|
fn deeply_nested_tab_has_one_tab() {
|
||||||
let path = layout_test_dir("deeply-nested-tab-layout.yaml".into());
|
let path = layout_test_dir("deeply-nested-tab-layout.yaml".into());
|
||||||
let layout = Layout::new(&path);
|
let layout = LayoutFromYaml::new(&path);
|
||||||
let main_layout = layout.unwrap().construct_main_layout().unwrap();
|
let layout_template = layout.unwrap().construct_layout_template();
|
||||||
assert_eq!(main_layout.tabs.len(), 1);
|
assert_eq!(layout_template.tabs.len(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn deeply_nested_tab_three_post_tab() {
|
fn deeply_nested_tab_three_post_tab() {
|
||||||
let path = layout_test_dir("deeply-nested-tab-layout.yaml".into());
|
let path = layout_test_dir("deeply-nested-tab-layout.yaml".into());
|
||||||
let layout = Layout::new(&path);
|
let layout = LayoutFromYaml::new(&path);
|
||||||
let main_layout = layout.unwrap().construct_main_layout().unwrap();
|
let layout_template = layout.unwrap().construct_layout_template();
|
||||||
assert_eq!(main_layout.post_tab.len(), 3);
|
assert_eq!(layout_template.post_tab.len(), 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn deeply_nested_tab_has_many_pre_tab() {
|
fn deeply_nested_tab_has_many_pre_tab() {
|
||||||
let path = layout_test_dir("deeply-nested-tab-layout.yaml".into());
|
let path = layout_test_dir("deeply-nested-tab-layout.yaml".into());
|
||||||
let layout = Layout::new(&path);
|
let layout = LayoutFromYaml::new(&path);
|
||||||
let main_layout = layout.unwrap().construct_main_layout().unwrap();
|
let layout_template = layout.unwrap().construct_layout_template();
|
||||||
assert!(!main_layout.pre_tab.parts.is_empty());
|
assert!(!layout_template.pre_tab.parts.is_empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn deeply_nested_tab_merged_correctly() {
|
fn deeply_nested_tab_merged_correctly() {
|
||||||
let path = layout_test_dir("deeply-nested-tab-layout.yaml".into());
|
let path = layout_test_dir("deeply-nested-tab-layout.yaml".into());
|
||||||
let layout = Layout::new(&path);
|
let layout = LayoutFromYaml::new(&path);
|
||||||
let main_layout = layout.as_ref().unwrap().construct_main_layout().unwrap();
|
let layout_template = layout.as_ref().unwrap().construct_layout_template();
|
||||||
let tab_layout = main_layout.construct_tab_layout(Some(main_layout.tabs[0].clone()));
|
let tab_layout = layout_template.construct_tab_layout(Some(layout_template.tabs[0].clone()));
|
||||||
let merged_layout = Layout {
|
let merged_layout = Layout {
|
||||||
direction: Direction::Horizontal,
|
direction: Direction::Horizontal,
|
||||||
parts: vec![
|
parts: vec![
|
||||||
|
|
@ -518,58 +530,38 @@ fn deeply_nested_tab_merged_correctly() {
|
||||||
assert_eq!(merged_layout, tab_layout);
|
assert_eq!(merged_layout, tab_layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn no_tabs_specified_should_err() {
|
|
||||||
let path = layout_test_dir("no-tabs-should-error.yaml".into());
|
|
||||||
let layout = Layout::new(&path);
|
|
||||||
let main_layout = layout.unwrap().construct_main_layout();
|
|
||||||
assert!(main_layout.is_err());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn tabs_and_parts_specified_together_should_should_err() {
|
|
||||||
let path = layout_test_dir("tabs-and-parts-together-should-error.yaml".into());
|
|
||||||
let layout = Layout::new(&path);
|
|
||||||
let main_layout = layout.unwrap().construct_main_layout();
|
|
||||||
assert!(main_layout.is_err());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn multiple_tabs_specified_should_not_err() {
|
|
||||||
let path = layout_test_dir("multiple-tabs-should-not-error.yaml".into());
|
|
||||||
let layout = Layout::new(&path);
|
|
||||||
let main_layout = layout.unwrap().construct_main_layout();
|
|
||||||
assert!(main_layout.is_ok())
|
|
||||||
}
|
|
||||||
#[test]
|
#[test]
|
||||||
fn three_tabs_is_ok() {
|
fn three_tabs_is_ok() {
|
||||||
let path = layout_test_dir("three-tabs-merged-correctly.yaml".into());
|
let path = layout_test_dir("three-tabs-merged-correctly.yaml".into());
|
||||||
let layout = Layout::new(&path);
|
let layout_from_yaml = LayoutFromYaml::new(&path);
|
||||||
assert!(layout.is_ok());
|
assert!(layout_from_yaml.is_ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn three_tabs_has_three_tabs() {
|
fn three_tabs_has_three_tabs() {
|
||||||
let path = layout_test_dir("three-tabs-merged-correctly.yaml".into());
|
let path = layout_test_dir("three-tabs-merged-correctly.yaml".into());
|
||||||
let layout = Layout::new(&path);
|
let layout_from_yaml = LayoutFromYaml::new(&path);
|
||||||
let main_layout = layout.unwrap().construct_main_layout().unwrap();
|
let layout_template = layout_from_yaml.unwrap().construct_layout_template();
|
||||||
assert_eq!(main_layout.tabs.len(), 3);
|
assert_eq!(layout_template.tabs.len(), 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn three_tabs_has_one_post_tab() {
|
fn three_tabs_has_one_post_tab() {
|
||||||
let path = layout_test_dir("three-tabs-merged-correctly.yaml".into());
|
let path = layout_test_dir("three-tabs-merged-correctly.yaml".into());
|
||||||
let layout = Layout::new(&path);
|
let layout_from_yaml = LayoutFromYaml::new(&path);
|
||||||
let main_layout = layout.unwrap().construct_main_layout().unwrap();
|
let layout_template = layout_from_yaml.unwrap().construct_layout_template();
|
||||||
assert_eq!(main_layout.post_tab.len(), 1);
|
assert_eq!(layout_template.post_tab.len(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn three_tabs_tab_one_merged_correctly() {
|
fn three_tabs_tab_one_merged_correctly() {
|
||||||
let path = layout_test_dir("three-tabs-merged-correctly.yaml".into());
|
let path = layout_test_dir("three-tabs-merged-correctly.yaml".into());
|
||||||
let layout = Layout::new(&path);
|
let layout_from_yaml = LayoutFromYaml::new(&path);
|
||||||
let main_layout = layout.as_ref().unwrap().construct_main_layout().unwrap();
|
let layout_template = layout_from_yaml
|
||||||
let tab_layout = main_layout.construct_tab_layout(Some(main_layout.tabs[0].clone()));
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.construct_layout_template();
|
||||||
|
let tab_layout = layout_template.construct_tab_layout(Some(layout_template.tabs[0].clone()));
|
||||||
let merged_layout = Layout {
|
let merged_layout = Layout {
|
||||||
direction: Direction::Vertical,
|
direction: Direction::Vertical,
|
||||||
parts: vec![
|
parts: vec![
|
||||||
|
|
@ -599,9 +591,12 @@ fn three_tabs_tab_one_merged_correctly() {
|
||||||
#[test]
|
#[test]
|
||||||
fn three_tabs_tab_two_merged_correctly() {
|
fn three_tabs_tab_two_merged_correctly() {
|
||||||
let path = layout_test_dir("three-tabs-merged-correctly.yaml".into());
|
let path = layout_test_dir("three-tabs-merged-correctly.yaml".into());
|
||||||
let layout = Layout::new(&path);
|
let layout_from_yaml = LayoutFromYaml::new(&path);
|
||||||
let main_layout = layout.as_ref().unwrap().construct_main_layout().unwrap();
|
let layout_template = layout_from_yaml
|
||||||
let tab_layout = main_layout.construct_tab_layout(Some(main_layout.tabs[1].clone()));
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.construct_layout_template();
|
||||||
|
let tab_layout = layout_template.construct_tab_layout(Some(layout_template.tabs[1].clone()));
|
||||||
let merged_layout = Layout {
|
let merged_layout = Layout {
|
||||||
direction: Direction::Vertical,
|
direction: Direction::Vertical,
|
||||||
parts: vec![
|
parts: vec![
|
||||||
|
|
@ -646,9 +641,9 @@ fn three_tabs_tab_two_merged_correctly() {
|
||||||
#[test]
|
#[test]
|
||||||
fn three_tabs_tab_three_merged_correctly() {
|
fn three_tabs_tab_three_merged_correctly() {
|
||||||
let path = layout_test_dir("three-tabs-merged-correctly.yaml".into());
|
let path = layout_test_dir("three-tabs-merged-correctly.yaml".into());
|
||||||
let layout = Layout::new(&path);
|
let layout = LayoutFromYaml::new(&path);
|
||||||
let main_layout = layout.as_ref().unwrap().construct_main_layout().unwrap();
|
let layout_template = layout.as_ref().unwrap().construct_layout_template();
|
||||||
let tab_layout = main_layout.construct_tab_layout(Some(main_layout.tabs[2].clone()));
|
let tab_layout = layout_template.construct_tab_layout(Some(layout_template.tabs[2].clone()));
|
||||||
let merged_layout = Layout {
|
let merged_layout = Layout {
|
||||||
direction: Direction::Vertical,
|
direction: Direction::Vertical,
|
||||||
parts: vec![
|
parts: vec![
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
cli::CliArgs,
|
cli::CliArgs,
|
||||||
errors::{get_current_ctx, ErrorContext},
|
errors::{get_current_ctx, ErrorContext},
|
||||||
input::{actions::Action, layout::MainLayout, options::Options},
|
input::{actions::Action, layout::LayoutTemplate, options::Options},
|
||||||
pane_size::PositionAndSize,
|
pane_size::PositionAndSize,
|
||||||
};
|
};
|
||||||
use interprocess::local_socket::LocalSocketStream;
|
use interprocess::local_socket::LocalSocketStream;
|
||||||
|
|
@ -62,7 +62,7 @@ pub enum ClientToServerMsg {
|
||||||
ClientAttributes,
|
ClientAttributes,
|
||||||
Box<CliArgs>,
|
Box<CliArgs>,
|
||||||
Box<Options>,
|
Box<Options>,
|
||||||
Option<MainLayout>,
|
Option<LayoutTemplate>,
|
||||||
),
|
),
|
||||||
AttachClient(ClientAttributes, bool, Options),
|
AttachClient(ClientAttributes, bool, Options),
|
||||||
Action(Action),
|
Action(Action),
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ use crate::{
|
||||||
},
|
},
|
||||||
input::{
|
input::{
|
||||||
config::{Config, ConfigError},
|
config::{Config, ConfigError},
|
||||||
layout::{Layout, MainLayout},
|
layout::{LayoutFromYaml, LayoutTemplate},
|
||||||
options::Options,
|
options::Options,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
@ -153,7 +153,7 @@ impl Setup {
|
||||||
/// 2. config options (`config.yaml`)
|
/// 2. config options (`config.yaml`)
|
||||||
pub fn from_options(
|
pub fn from_options(
|
||||||
opts: &CliArgs,
|
opts: &CliArgs,
|
||||||
) -> Result<(Config, Option<MainLayout>, Options), ConfigError> {
|
) -> Result<(Config, Option<LayoutTemplate>, Options), ConfigError> {
|
||||||
let clean = match &opts.command {
|
let clean = match &opts.command {
|
||||||
Some(Command::Setup(ref setup)) => setup.clean,
|
Some(Command::Setup(ref setup)) => setup.clean,
|
||||||
_ => false,
|
_ => false,
|
||||||
|
|
@ -176,7 +176,7 @@ impl Setup {
|
||||||
.layout_dir
|
.layout_dir
|
||||||
.clone()
|
.clone()
|
||||||
.or_else(|| get_layout_dir(opts.config_dir.clone().or_else(find_default_config_dir)));
|
.or_else(|| get_layout_dir(opts.config_dir.clone().or_else(find_default_config_dir)));
|
||||||
let layout_result = Layout::from_path_or_default(
|
let layout_result = LayoutFromYaml::from_path_or_default(
|
||||||
opts.layout.as_ref(),
|
opts.layout.as_ref(),
|
||||||
opts.layout_path.as_ref(),
|
opts.layout_path.as_ref(),
|
||||||
layout_dir,
|
layout_dir,
|
||||||
|
|
@ -188,15 +188,7 @@ impl Setup {
|
||||||
return Err(e);
|
return Err(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.map(|layout| layout.construct_main_layout());
|
.map(|layout| layout.construct_layout_template());
|
||||||
|
|
||||||
let layout = match layout {
|
|
||||||
None => None,
|
|
||||||
Some(Ok(layout)) => Some(layout),
|
|
||||||
Some(Err(e)) => {
|
|
||||||
return Err(e);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(Command::Setup(ref setup)) = &opts.command {
|
if let Some(Command::Setup(ref setup)) = &opts.command {
|
||||||
setup.from_cli(opts, &config_options).map_or_else(
|
setup.from_cli(opts, &config_options).map_or_else(
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue