Merge branch 'main' of https://github.com/zellij-org/zellij into tab-layout
This commit is contained in:
commit
fc7bc3cc8b
13 changed files with 196 additions and 89 deletions
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
49
src/main.rs
49
src/main.rs
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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) => {
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ 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),
|
||||||
|
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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,]
|
||||||
|
|
|
||||||
|
|
@ -202,6 +202,7 @@ pub enum ScreenContext {
|
||||||
ScrollUpAt,
|
ScrollUpAt,
|
||||||
ScrollDown,
|
ScrollDown,
|
||||||
ScrollDownAt,
|
ScrollDownAt,
|
||||||
|
ScrollToBottom,
|
||||||
PageScrollUp,
|
PageScrollUp,
|
||||||
PageScrollDown,
|
PageScrollDown,
|
||||||
ClearScroll,
|
ClearScroll,
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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"),
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue