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:
a-kenji 2021-08-21 23:27:23 +02:00
parent 2e17756785
commit 88b4063879
17 changed files with 484 additions and 428 deletions

View file

@ -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";

View file

@ -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);

View file

@ -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()));

View file

@ -1,16 +1,18 @@
--- ---
direction: Horizontal template:
parts: 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 - direction: Vertical
split_size:
Fixed: 1
run:
plugin: tab-bar
- direction: Vertical
tabs:
- direction: Vertical
- direction: Vertical
split_size:
Fixed: 2
run:
plugin: status-bar

View file

@ -1,11 +1,11 @@
--- ---
direction: Horizontal template:
parts: direction: Horizontal
- direction: Vertical parts:
split_size: - direction: Vertical
Fixed: 1 split_size:
run: Fixed: 1
plugin: tab-bar run:
- direction: Vertical plugin: tab-bar
tabs: - direction: Vertical
- direction: Vertical body: true

View file

@ -1,23 +1,25 @@
--- ---
direction: Horizontal template:
parts: 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 - direction: Vertical
split_size: parts:
Fixed: 1 - direction: Horizontal
run: split_size:
plugin: tab-bar Percent: 20
- direction: Vertical run:
tabs: plugin: strider
- direction: Vertical - direction: Horizontal
parts:
- direction: Horizontal
split_size:
Percent: 20
run:
plugin: strider
- direction: Horizontal
- direction: Vertical
split_size:
Fixed: 2
run:
plugin: status-bar

View file

@ -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 {

View file

@ -1,40 +1,43 @@
--- ---
direction: Horizontal template:
parts: direction: Horizontal
- direction: Vertical parts:
parts: - direction: Vertical
- direction: Horizontal parts:
split_size: - direction: Horizontal
Percent: 21 split_size:
- direction: Vertical Percent: 21
split_size: - direction: Vertical
Percent: 79 split_size:
parts: Percent: 79
- direction: Horizontal parts:
split_size: - direction: Horizontal
Percent: 22 split_size:
- direction: Horizontal Percent: 22
split_size: - direction: Horizontal
Percent: 78 split_size:
parts: Percent: 78
- direction: Horizontal parts:
split_size: - direction: Horizontal
Percent: 23 split_size:
- direction: Vertical Percent: 23
split_size: - direction: Vertical
Percent: 77 split_size:
tabs: Percent: 77
- direction: Horizontal body: true
split_size: split_size:
Percent: 24 Percent: 90
- direction: Vertical
split_size:
Percent: 15
- direction: Vertical
split_size:
Percent: 15
- direction: Vertical
split_size:
Percent: 15
tabs:
- direction: Horizontal
split_size: split_size:
Percent: 90 Percent: 24
- direction: Vertical
split_size:
Percent: 15
- direction: Vertical
split_size:
Percent: 15
- direction: Vertical
split_size:
Percent: 15

View file

@ -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

View file

@ -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

View file

@ -1,32 +1,35 @@
--- ---
direction: Horizontal template:
parts: direction: Horizontal
parts:
- direction: Vertical
split_size:
Fixed: 1
run:
plugin: tab-bar
- direction: Horizontal
body: true
- direction: Vertical
split_size:
Fixed: 2
run:
plugin: status-bar
tabs:
- direction: Vertical - direction: Vertical
split_size: parts:
Fixed: 1 - direction: Horizontal
run: split_size:
plugin: tab-bar Percent: 50
- direction: Horizontal - direction: Horizontal
tabs:
- direction: Vertical
parts: parts:
- direction: Horizontal - direction: Vertical
split_size: split_size:
Percent: 50 Percent: 50
- direction: Horizontal run:
parts: command: {cmd: htop}
- direction: Vertical - direction: Vertical
split_size: split_size:
Percent: 50 Percent: 50
run: run:
command: {cmd: htop} command: {cmd: htop, args: ["-C"]}
- direction: Vertical
split_size:
Percent: 50
run:
command: {cmd: htop, args: ["-C"]}
- direction: Vertical
split_size:
Fixed: 2
run:
plugin: status-bar

View file

@ -1,28 +1,31 @@
--- ---
direction: Horizontal template:
parts: direction: Horizontal
parts:
- direction: Vertical
split_size:
Fixed: 1
run:
plugin: tab-bar
- direction: Horizontal
body: true
- direction: Vertical
split_size:
Fixed: 2
run:
plugin: status-bar
tabs:
- direction: Vertical - direction: Vertical
split_size: parts:
Fixed: 1 - direction: Horizontal
run: split_size:
plugin: tab-bar Percent: 50
- direction: Horizontal - direction: Horizontal
tabs:
- direction: Vertical
parts: parts:
- direction: Horizontal - direction: Vertical
split_size:
Percent: 50
- direction: Vertical
split_size: split_size:
Percent: 50 Percent: 50
- direction: Horizontal
parts:
- direction: Vertical
split_size:
Percent: 50
- direction: Vertical
split_size:
Percent: 50
- direction: Vertical
split_size:
Fixed: 2
run:
plugin: status-bar

View file

@ -1,18 +1,21 @@
--- ---
direction: Horizontal template:
parts: direction: Horizontal
- direction: Horizontal parts:
tabs: - direction: Horizontal
- direction: Vertical body: true
tabs:
- direction: Vertical
parts:
- direction: Horizontal
split_size:
Percent: 50
- direction: Horizontal
parts: parts:
- direction: Horizontal - direction: Vertical
split_size:
Percent: 50
- direction: Vertical
split_size: split_size:
Percent: 50 Percent: 50
- direction: Horizontal
parts:
- direction: Vertical
split_size:
Percent: 50
- direction: Vertical
split_size:
Percent: 50

View file

@ -1,25 +1,29 @@
--- ---
direction: Vertical template:
parts: direction: Vertical
parts:
- direction: Horizontal
body: true
- direction: Horizontal
tabs:
- direction: Horizontal - direction: Horizontal
tabs: split_size:
Percent: 50
- direction: Horizontal
split_size:
Percent: 50
parts:
- direction: Horizontal - direction: Horizontal
split_size: split_size:
Percent: 50 Percent: 50
- direction: Horizontal - direction: Horizontal
split_size: - direction: Vertical
Percent: 50 split_size:
parts: Percent: 50
- direction: Horizontal parts:
split_size:
Percent: 50
- direction: Horizontal
- direction: Vertical - direction: Vertical
split_size: split_size:
Percent: 50 Percent: 50
parts: - direction: Horizontal
- direction: Vertical
split_size:
Percent: 50
- direction: Horizontal
- direction: Horizontal

View file

@ -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![

View file

@ -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),

View file

@ -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(