Merge branch 'main' of https://github.com/zellij-org/zellij into tab-layout

This commit is contained in:
a-kenji 2021-08-01 20:25:33 +02:00
commit fc7bc3cc8b
13 changed files with 196 additions and 89 deletions

View file

@ -12,6 +12,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
* Add displaying of the `session-name` to the `tab-bar` (https://github.com/zellij-org/zellij/pull/608) * Add displaying of the `session-name` to the `tab-bar` (https://github.com/zellij-org/zellij/pull/608)
* Add command to dump `layouts` to stdout (https://github.com/zellij-org/zellij/pull/623) * Add command to dump `layouts` to stdout (https://github.com/zellij-org/zellij/pull/623)
* `zellij setup --dump-layout [LAYOUT]` [default, strider, disable-status] * `zellij setup --dump-layout [LAYOUT]` [default, strider, disable-status]
* Add `action`: `ScrollToBottom` (https://github.com/zellij-org/zellij/pull/626)
* Bound by default to `^c` in `scroll` mode, scrolls to bottom and exists the scroll mode
* Simplify deserialization slightly (https://github.com/zellij-org/zellij/pull/633)
* Fix update plugin attributes on inactive tab (https://github.com/zellij-org/zellij/pull/634)
## [0.15.0] - 2021-07-19 ## [0.15.0] - 2021-07-19
* Kill children properly (https://github.com/zellij-org/zellij/pull/601) * Kill children properly (https://github.com/zellij-org/zellij/pull/601)

View file

@ -29,3 +29,4 @@ Once the organization reaches 10 members, a reasonable and achievable process mu
* Roee Shapira <ro33.sha@gmail.com> * Roee Shapira <ro33.sha@gmail.com>
* Alex Kenji Berthold <aks.kenji@protonmail.com> * Alex Kenji Berthold <aks.kenji@protonmail.com>
* Kyle Sutherland-Cash <kyle.sutherlandcash@gmail.com> * Kyle Sutherland-Cash <kyle.sutherlandcash@gmail.com>
* Dante Pippi <dante.dpf@gmail.com>

View file

@ -5,16 +5,14 @@ mod tests;
use crate::install::populate_data_dir; use crate::install::populate_data_dir;
use sessions::{assert_session, assert_session_ne, get_active_session, list_sessions}; use sessions::{assert_session, assert_session_ne, get_active_session, list_sessions};
use std::convert::TryFrom;
use std::process; use std::process;
use zellij_client::{os_input_output::get_client_os_input, start_client, ClientInfo}; use zellij_client::{os_input_output::get_client_os_input, start_client, ClientInfo};
use zellij_server::{os_input_output::get_server_os_input, start_server}; use zellij_server::{os_input_output::get_server_os_input, start_server};
use zellij_utils::{ use zellij_utils::{
cli::{CliArgs, Command, Sessions}, cli::{CliArgs, Command, Sessions},
consts::{ZELLIJ_TMP_DIR, ZELLIJ_TMP_LOG_DIR}, consts::{ZELLIJ_TMP_DIR, ZELLIJ_TMP_LOG_DIR},
input::{config::Config, layout::Layout, options::Options},
logging::*, logging::*,
setup::{find_default_config_dir, get_default_data_dir, get_layout_dir, Setup}, setup::{get_default_data_dir, Setup},
structopt::StructOpt, structopt::StructOpt,
}; };
@ -26,25 +24,6 @@ pub fn main() {
list_sessions(); list_sessions();
} }
let config = match Config::try_from(&opts) {
Ok(config) => config,
Err(e) => {
eprintln!("There was an error in the config file:\n{}", e);
process::exit(1);
}
};
let config_options = Options::from_cli(&config.options, opts.command.clone());
if let Some(Command::Setup(ref setup)) = opts.command {
Setup::from_cli(setup, &opts, &config_options).map_or_else(
|e| {
eprintln!("{:?}", e);
process::exit(1);
},
|_| {},
);
};
atomic_create_dir(&*ZELLIJ_TMP_DIR).unwrap(); atomic_create_dir(&*ZELLIJ_TMP_DIR).unwrap();
atomic_create_dir(&*ZELLIJ_TMP_LOG_DIR).unwrap(); atomic_create_dir(&*ZELLIJ_TMP_LOG_DIR).unwrap();
if let Some(path) = opts.server { if let Some(path) = opts.server {
@ -75,6 +54,14 @@ pub fn main() {
session_name = Some(get_active_session()); session_name = Some(get_active_session());
} }
let (config, _, config_options) = match Setup::from_options(&opts) {
Ok(results) => results,
Err(e) => {
eprintln!("{}", e);
process::exit(1);
}
};
start_client( start_client(
Box::new(os_input), Box::new(os_input),
opts, opts,
@ -83,6 +70,14 @@ pub fn main() {
None, None,
); );
} else { } else {
let (config, layout, _) = match Setup::from_options(&opts) {
Ok(results) => results,
Err(e) => {
eprintln!("{}", e);
process::exit(1);
}
};
let session_name = opts let session_name = opts
.session .session
.clone() .clone()
@ -94,16 +89,6 @@ pub fn main() {
#[cfg(not(disable_automatic_asset_installation))] #[cfg(not(disable_automatic_asset_installation))]
populate_data_dir(&data_dir); populate_data_dir(&data_dir);
let layout_dir = config_options.layout_dir.or_else(|| {
get_layout_dir(opts.config_dir.clone().or_else(find_default_config_dir))
});
let layout = Layout::from_path_or_default(
opts.layout.as_ref(),
opts.layout_path.as_ref(),
layout_dir,
)
.map(|layout| layout.construct_main_layout());
start_client( start_client(
Box::new(os_input), Box::new(os_input),
opts, opts,

View file

@ -127,6 +127,12 @@ fn route_action(
.send_to_screen(ScreenInstruction::ScrollDownAt(point)) .send_to_screen(ScreenInstruction::ScrollDownAt(point))
.unwrap(); .unwrap();
} }
Action::ScrollToBottom => {
session
.senders
.send_to_screen(ScreenInstruction::ScrollToBottom)
.unwrap();
}
Action::PageScrollUp => { Action::PageScrollUp => {
session session
.senders .senders

View file

@ -50,15 +50,16 @@ pub(crate) enum ScreenInstruction {
ScrollUpAt(Position), ScrollUpAt(Position),
ScrollDown, ScrollDown,
ScrollDownAt(Position), ScrollDownAt(Position),
ScrollToBottom,
PageScrollUp, PageScrollUp,
PageScrollDown, PageScrollDown,
ClearScroll, ClearScroll,
CloseFocusedPane, CloseFocusedPane,
ToggleActiveTerminalFullscreen, ToggleActiveTerminalFullscreen,
SetSelectable(PaneId, bool), SetSelectable(PaneId, bool, usize),
SetFixedHeight(PaneId, usize), SetFixedHeight(PaneId, usize, usize),
SetFixedWidth(PaneId, usize), SetFixedWidth(PaneId, usize, usize),
SetInvisibleBorders(PaneId, bool), SetInvisibleBorders(PaneId, bool, usize),
ClosePane(PaneId), ClosePane(PaneId),
ApplyLayout(Layout, Vec<RawFd>), ApplyLayout(Layout, Vec<RawFd>),
NewTab(RawFd), NewTab(RawFd),
@ -103,6 +104,7 @@ impl From<&ScreenInstruction> for ScreenContext {
ScreenInstruction::Exit => ScreenContext::Exit, ScreenInstruction::Exit => ScreenContext::Exit,
ScreenInstruction::ScrollUp => ScreenContext::ScrollUp, ScreenInstruction::ScrollUp => ScreenContext::ScrollUp,
ScreenInstruction::ScrollDown => ScreenContext::ScrollDown, ScreenInstruction::ScrollDown => ScreenContext::ScrollDown,
ScreenInstruction::ScrollToBottom => ScreenContext::ScrollToBottom,
ScreenInstruction::PageScrollUp => ScreenContext::PageScrollUp, ScreenInstruction::PageScrollUp => ScreenContext::PageScrollUp,
ScreenInstruction::PageScrollDown => ScreenContext::PageScrollDown, ScreenInstruction::PageScrollDown => ScreenContext::PageScrollDown,
ScreenInstruction::ClearScroll => ScreenContext::ClearScroll, ScreenInstruction::ClearScroll => ScreenContext::ClearScroll,
@ -335,6 +337,11 @@ impl Screen {
} }
} }
/// Returns a mutable reference to this [`Screen`]'s indexed [`Tab`].
pub fn get_indexed_tab_mut(&mut self, tab_index: usize) -> Option<&mut Tab> {
self.get_tabs_mut().get_mut(&tab_index)
}
/// Creates a new [`Tab`] in this [`Screen`], applying the specified [`Layout`] /// Creates a new [`Tab`] in this [`Screen`], applying the specified [`Layout`]
/// and switching to it. /// and switching to it.
pub fn apply_layout(&mut self, layout: Layout, new_pids: Vec<RawFd>) { pub fn apply_layout(&mut self, layout: Layout, new_pids: Vec<RawFd>) {
@ -353,7 +360,7 @@ impl Screen {
self.colors, self.colors,
self.session_state.clone(), self.session_state.clone(),
); );
tab.apply_layout(layout, new_pids); tab.apply_layout(layout, new_pids, tab_index);
self.active_tab_index = Some(tab_index); self.active_tab_index = Some(tab_index);
self.tabs.insert(tab_index, tab); self.tabs.insert(tab_index, tab);
self.update_tabs(); self.update_tabs();
@ -569,6 +576,12 @@ pub(crate) fn screen_thread_main(
.unwrap() .unwrap()
.scroll_terminal_down(&point, 3); .scroll_terminal_down(&point, 3);
} }
ScreenInstruction::ScrollToBottom => {
screen
.get_active_tab_mut()
.unwrap()
.scroll_active_terminal_to_bottom();
}
ScreenInstruction::PageScrollUp => { ScreenInstruction::PageScrollUp => {
screen screen
.get_active_tab_mut() .get_active_tab_mut()
@ -591,29 +604,53 @@ pub(crate) fn screen_thread_main(
screen.get_active_tab_mut().unwrap().close_focused_pane(); screen.get_active_tab_mut().unwrap().close_focused_pane();
screen.render(); screen.render();
} }
ScreenInstruction::SetSelectable(id, selectable) => { ScreenInstruction::SetSelectable(id, selectable, tab_index) => {
screen screen.get_indexed_tab_mut(tab_index).map_or_else(
.get_active_tab_mut() || {
.unwrap() log::warn!(
.set_pane_selectable(id, selectable); "Tab index #{} not found, could not set selectable for plugin #{:?}.",
tab_index,
id
)
},
|tab| tab.set_pane_selectable(id, selectable),
);
} }
ScreenInstruction::SetFixedHeight(id, fixed_height) => { ScreenInstruction::SetFixedHeight(id, fixed_height, tab_index) => {
screen screen.get_indexed_tab_mut(tab_index).map_or_else(
.get_active_tab_mut() || {
.unwrap() log::warn!(
.set_pane_fixed_height(id, fixed_height); "Tab index #{} not found, could not set fixed height for plugin #{:?}.",
tab_index,
id
)
},
|tab| tab.set_pane_fixed_height(id, fixed_height),
);
} }
ScreenInstruction::SetFixedWidth(id, fixed_width) => { ScreenInstruction::SetFixedWidth(id, fixed_width, tab_index) => {
screen screen.get_indexed_tab_mut(tab_index).map_or_else(
.get_active_tab_mut() || {
.unwrap() log::warn!(
.set_pane_fixed_width(id, fixed_width); "Tab index #{} not found, could not set fixed width for plugin #{:?}.",
tab_index,
id
)
},
|tab| tab.set_pane_fixed_width(id, fixed_width),
);
} }
ScreenInstruction::SetInvisibleBorders(id, invisible_borders) => { ScreenInstruction::SetInvisibleBorders(id, invisible_borders, tab_index) => {
screen screen.get_indexed_tab_mut(tab_index).map_or_else(
.get_active_tab_mut() || {
.unwrap() log::warn!(
.set_pane_invisible_borders(id, invisible_borders); r#"Tab index #{} not found, could not set invisible borders for plugin #{:?}."#,
tab_index,
id
)
},
|tab| tab.set_pane_invisible_borders(id, invisible_borders),
);
screen.render(); screen.render();
} }
ScreenInstruction::ClosePane(id) => { ScreenInstruction::ClosePane(id) => {

View file

@ -301,7 +301,7 @@ impl Tab {
} }
} }
pub fn apply_layout(&mut self, layout: Layout, new_pids: Vec<RawFd>) { pub fn apply_layout(&mut self, layout: Layout, new_pids: Vec<RawFd>, tab_index: usize) {
// TODO: this should be an attribute on Screen instead of full_screen_ws // TODO: this should be an attribute on Screen instead of full_screen_ws
let free_space = PositionAndSize { let free_space = PositionAndSize {
x: 0, x: 0,
@ -340,7 +340,7 @@ impl Tab {
if let Some(Run::Plugin(Some(plugin))) = &layout.run { if let Some(Run::Plugin(Some(plugin))) = &layout.run {
let (pid_tx, pid_rx) = channel(); let (pid_tx, pid_rx) = channel();
self.senders self.senders
.send_to_plugin(PluginInstruction::Load(pid_tx, plugin.clone())) .send_to_plugin(PluginInstruction::Load(pid_tx, plugin.clone(), tab_index))
.unwrap(); .unwrap();
let pid = pid_rx.recv().unwrap(); let pid = pid_rx.recv().unwrap();
let new_plugin = PluginPane::new( let new_plugin = PluginPane::new(
@ -2280,6 +2280,16 @@ impl Tab {
self.render(); self.render();
} }
} }
pub fn scroll_active_terminal_to_bottom(&mut self) {
if let Some(active_terminal_id) = self.get_active_terminal_id() {
let active_terminal = self
.panes
.get_mut(&PaneId::Terminal(active_terminal_id))
.unwrap();
active_terminal.clear_scroll();
self.render();
}
}
pub fn clear_active_terminal_scroll(&mut self) { pub fn clear_active_terminal_scroll(&mut self) {
if let Some(active_terminal_id) = self.get_active_terminal_id() { if let Some(active_terminal_id) = self.get_active_terminal_id() {
let active_terminal = self let active_terminal = self

View file

@ -28,8 +28,8 @@ use zellij_utils::{input::command::TerminalAction, serde, zellij_tile};
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub(crate) enum PluginInstruction { pub(crate) enum PluginInstruction {
Load(Sender<u32>, PathBuf), Load(Sender<u32>, PathBuf, usize), // tx_pid, path_of_plugin , tab_index
Update(Option<u32>, Event), // Focused plugin / broadcast, event data Update(Option<u32>, Event), // Focused plugin / broadcast, event data
Render(Sender<String>, u32, usize, usize), // String buffer, plugin id, rows, cols Render(Sender<String>, u32, usize, usize), // String buffer, plugin id, rows, cols
Unload(u32), Unload(u32),
Exit, Exit,
@ -50,6 +50,7 @@ impl From<&PluginInstruction> for PluginContext {
#[derive(WasmerEnv, Clone)] #[derive(WasmerEnv, Clone)]
pub(crate) struct PluginEnv { pub(crate) struct PluginEnv {
pub plugin_id: u32, pub plugin_id: u32,
pub tab_index: usize,
pub senders: ThreadSenders, pub senders: ThreadSenders,
pub wasi_env: WasiEnv, pub wasi_env: WasiEnv,
pub subscriptions: Arc<Mutex<HashSet<EventType>>>, pub subscriptions: Arc<Mutex<HashSet<EventType>>>,
@ -64,7 +65,7 @@ pub(crate) fn wasm_thread_main(bus: Bus<PluginInstruction>, store: Store, data_d
let (event, mut err_ctx) = bus.recv().expect("failed to receive event on channel"); let (event, mut err_ctx) = bus.recv().expect("failed to receive event on channel");
err_ctx.add_call(ContextType::Plugin((&event).into())); err_ctx.add_call(ContextType::Plugin((&event).into()));
match event { match event {
PluginInstruction::Load(pid_tx, path) => { PluginInstruction::Load(pid_tx, path, tab_index) => {
let plugin_dir = data_dir.join("plugins/"); let plugin_dir = data_dir.join("plugins/");
let wasm_bytes = fs::read(&path) let wasm_bytes = fs::read(&path)
.or_else(|_| fs::read(&path.with_extension("wasm"))) .or_else(|_| fs::read(&path.with_extension("wasm")))
@ -100,6 +101,7 @@ pub(crate) fn wasm_thread_main(bus: Bus<PluginInstruction>, store: Store, data_d
let plugin_env = PluginEnv { let plugin_env = PluginEnv {
plugin_id, plugin_id,
tab_index,
senders: bus.senders.clone(), senders: bus.senders.clone(),
wasi_env, wasi_env,
subscriptions: Arc::new(Mutex::new(HashSet::new())), subscriptions: Arc::new(Mutex::new(HashSet::new())),
@ -193,6 +195,7 @@ fn host_set_selectable(plugin_env: &PluginEnv, selectable: i32) {
.send_to_screen(ScreenInstruction::SetSelectable( .send_to_screen(ScreenInstruction::SetSelectable(
PaneId::Plugin(plugin_env.plugin_id), PaneId::Plugin(plugin_env.plugin_id),
selectable, selectable,
plugin_env.tab_index,
)) ))
.unwrap() .unwrap()
} }
@ -204,6 +207,7 @@ fn host_set_fixed_height(plugin_env: &PluginEnv, fixed_height: i32) {
.send_to_screen(ScreenInstruction::SetFixedHeight( .send_to_screen(ScreenInstruction::SetFixedHeight(
PaneId::Plugin(plugin_env.plugin_id), PaneId::Plugin(plugin_env.plugin_id),
fixed_height, fixed_height,
plugin_env.tab_index,
)) ))
.unwrap() .unwrap()
} }
@ -215,6 +219,7 @@ fn host_set_fixed_width(plugin_env: &PluginEnv, fixed_width: i32) {
.send_to_screen(ScreenInstruction::SetFixedWidth( .send_to_screen(ScreenInstruction::SetFixedWidth(
PaneId::Plugin(plugin_env.plugin_id), PaneId::Plugin(plugin_env.plugin_id),
fixed_width, fixed_width,
plugin_env.tab_index,
)) ))
.unwrap() .unwrap()
} }
@ -226,6 +231,7 @@ fn host_set_invisible_borders(plugin_env: &PluginEnv, invisible_borders: i32) {
.send_to_screen(ScreenInstruction::SetInvisibleBorders( .send_to_screen(ScreenInstruction::SetInvisibleBorders(
PaneId::Plugin(plugin_env.plugin_id), PaneId::Plugin(plugin_env.plugin_id),
invisible_borders, invisible_borders,
plugin_env.tab_index,
)) ))
.unwrap() .unwrap()
} }

View file

@ -178,6 +178,8 @@ keybinds:
key: [Ctrl: 'p',] key: [Ctrl: 'p',]
- action: [SwitchToMode: Session,] - action: [SwitchToMode: Session,]
key: [Ctrl: 'o',] key: [Ctrl: 'o',]
- action: [ScrollToBottom, SwitchToMode: Normal,]
key: [Ctrl: 'c',]
- action: [Quit,] - action: [Quit,]
key: [Ctrl: 'q',] key: [Ctrl: 'q',]
- action: [ScrollDown,] - action: [ScrollDown,]

View file

@ -202,6 +202,7 @@ pub enum ScreenContext {
ScrollUpAt, ScrollUpAt,
ScrollDown, ScrollDown,
ScrollDownAt, ScrollDownAt,
ScrollToBottom,
PageScrollUp, PageScrollUp,
PageScrollDown, PageScrollDown,
ClearScroll, ClearScroll,

View file

@ -49,6 +49,8 @@ pub enum Action {
ScrollDown, ScrollDown,
/// Scroll down at point /// Scroll down at point
ScrollDownAt(Position), ScrollDownAt(Position),
/// Scroll down to bottom in focus pane.
ScrollToBottom,
/// Scroll up one page in focus pane. /// Scroll up one page in focus pane.
PageScrollUp, PageScrollUp,
/// Scroll down one page in focus pane. /// Scroll down one page in focus pane.

View file

@ -123,8 +123,8 @@ impl Layout {
layout: Option<&PathBuf>, layout: Option<&PathBuf>,
layout_path: Option<&PathBuf>, layout_path: Option<&PathBuf>,
layout_dir: Option<PathBuf>, layout_dir: Option<PathBuf>,
) -> Option<Layout> { ) -> Option<Result<Layout, ConfigError>> {
let layout_result = layout layout
.map(|p| Layout::from_dir(p, layout_dir.as_ref())) .map(|p| Layout::from_dir(p, layout_dir.as_ref()))
.or_else(|| layout_path.map(|p| Layout::new(p))) .or_else(|| layout_path.map(|p| Layout::new(p)))
.or_else(|| { .or_else(|| {
@ -132,16 +132,7 @@ impl Layout {
&std::path::PathBuf::from("default"), &std::path::PathBuf::from("default"),
layout_dir.as_ref(), layout_dir.as_ref(),
)) ))
}); })
match layout_result {
None => None,
Some(Ok(layout)) => Some(layout),
Some(Err(e)) => {
eprintln!("There was an error in the layout file:\n{}", e);
std::process::exit(1);
}
}
} }
// Currently still needed but on nightly // Currently still needed but on nightly
@ -297,12 +288,9 @@ impl Layout {
pub fn construct_main_layout(&self) -> MainLayout { pub fn construct_main_layout(&self) -> MainLayout {
let (pre_tab, post_tab, tabs) = self.split_main_and_tab_layout(); let (pre_tab, post_tab, tabs) = self.split_main_and_tab_layout();
// Todo: A proper LayoutError
if tabs.is_empty() { if tabs.is_empty() {
panic!("The layout file should have a `tabs` section specified"); panic!("The layout file should have a [`tabs`] section specified");
}
if tabs.len() > 1 {
panic!("The layout file should have one single tab in the `tabs` section specified");
} }
MainLayout { MainLayout {

View file

@ -528,10 +528,7 @@ fn no_tabs_specified_should_panic() {
} }
#[test] #[test]
#[should_panic] fn multiple_tabs_specified_should_not_panic() {
// TODO Make error out of this
// Only untill #631 is fixed
fn multiple_tabs_specified_should_panic() {
let path = layout_test_dir("multiple-tabs-should-panic.yaml".into()); let path = layout_test_dir("multiple-tabs-should-panic.yaml".into());
let layout = Layout::new(&path); let layout = Layout::new(&path);
let _main_layout = layout.unwrap().construct_main_layout(); let _main_layout = layout.unwrap().construct_main_layout();

View file

@ -1,11 +1,18 @@
use crate::cli::CliArgs; use crate::{
use crate::consts::{ cli::{CliArgs, Command},
FEATURES, SYSTEM_DEFAULT_CONFIG_DIR, SYSTEM_DEFAULT_DATA_DIR_PREFIX, VERSION, ZELLIJ_PROJ_DIR, consts::{
FEATURES, SYSTEM_DEFAULT_CONFIG_DIR, SYSTEM_DEFAULT_DATA_DIR_PREFIX, VERSION,
ZELLIJ_PROJ_DIR,
},
input::{
config::{Config, ConfigError},
layout::{Layout, MainLayout},
options::Options,
},
}; };
use crate::input::options::Options;
use directories_next::BaseDirs; use directories_next::BaseDirs;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::{io::Write, path::Path, path::PathBuf}; use std::{convert::TryFrom, io::Write, path::Path, path::PathBuf, process};
use structopt::StructOpt; use structopt::StructOpt;
const CONFIG_LOCATION: &str = ".config/zellij"; const CONFIG_LOCATION: &str = ".config/zellij";
@ -139,6 +146,68 @@ pub struct Setup {
impl Setup { impl Setup {
/// Entrypoint from main /// Entrypoint from main
/// Merges options from the config file and the command line options
/// into `[Options]`, the command line options superceding the config
/// file options:
/// 1. command line options (`zellij options`)
/// 2. config options (`config.yaml`)
pub fn from_options(
opts: &CliArgs,
) -> Result<(Config, Option<MainLayout>, Options), ConfigError> {
let clean = match &opts.command {
Some(Command::Setup(ref setup)) => setup.clean,
_ => false,
};
log::info!("{:?}", clean);
let config = if !clean {
match Config::try_from(opts) {
Ok(config) => config,
Err(e) => {
eprintln!("There was an error in the config file:");
return Err(e);
}
}
} else {
Config::default()
};
let config_options = Options::from_cli(&config.options, opts.command.clone());
let layout_dir = config_options
.layout_dir
.clone()
.or_else(|| get_layout_dir(opts.config_dir.clone().or_else(find_default_config_dir)));
let layout_result = Layout::from_path_or_default(
opts.layout.as_ref(),
opts.layout_path.as_ref(),
layout_dir,
);
let layout = match layout_result {
None => None,
Some(Ok(layout)) => Some(layout),
Some(Err(e)) => {
eprintln!("There was an error in the layout file:");
return Err(e);
}
}
.map(|layout| layout.construct_main_layout());
if let Some(Command::Setup(ref setup)) = &opts.command {
setup.from_cli(opts, &config_options).map_or_else(
|e| {
eprintln!("{:?}", e);
process::exit(1);
},
|_| {},
);
};
Ok((config, layout, config_options))
}
/// General setup helpers
pub fn from_cli(&self, opts: &CliArgs, config_options: &Options) -> std::io::Result<()> { pub fn from_cli(&self, opts: &CliArgs, config_options: &Options) -> std::io::Result<()> {
if self.clean { if self.clean {
return Ok(()); return Ok(());
@ -201,7 +270,6 @@ impl Setup {
} }
} }
if let Some(config_file) = config_file { if let Some(config_file) = config_file {
use crate::input::config::Config;
message.push_str(&format!("[CONFIG FILE]: {:?}\n", config_file)); message.push_str(&format!("[CONFIG FILE]: {:?}\n", config_file));
match Config::new(&config_file) { match Config::new(&config_file) {
Ok(_) => message.push_str("[CONFIG FILE]: Well defined.\n"), Ok(_) => message.push_str("[CONFIG FILE]: Well defined.\n"),