Skip to content

Commit

Permalink
feat(ux): first run setup-wizard (zellij-org#3556)
Browse files Browse the repository at this point in the history
* separate saved/runtime structure, kind of working

* serializing config

* work

* work

* save config through the configuration screen

* work

* startup wizard

* style(code): cleanups

* fix(session): reload config from disk when switching sessions

* style(fmt): rustfmt

* fix(config): propagate cli config options to screen

* style(fmt): rustfmt
  • Loading branch information
imsnif authored and Tomcat-42 committed Nov 9, 2024
1 parent 9059c9a commit a600c85
Show file tree
Hide file tree
Showing 53 changed files with 4,981 additions and 310 deletions.
385 changes: 315 additions & 70 deletions default-plugins/configuration/src/main.rs

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions default-plugins/fixture-plugin-for-tests/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,7 @@ impl ZellijPlugin for State {
);
},
BareKey::Char('0') if key.has_modifiers(&[KeyModifier::Ctrl]) => {
let write_to_disk = true;
reconfigure(
"
keybinds {
Expand All @@ -341,6 +342,7 @@ impl ZellijPlugin for State {
}
"
.to_owned(),
write_to_disk,
);
},
BareKey::Char('a') if key.has_modifiers(&[KeyModifier::Alt]) => {
Expand Down
53 changes: 40 additions & 13 deletions src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -386,19 +386,25 @@ fn attach_with_session_name(
pub(crate) fn start_client(opts: CliArgs) {
// look for old YAML config/layout/theme files and convert them to KDL
convert_old_yaml_files(&opts);
let (config, layout, config_options, config_without_layout, config_options_without_layout) =
match Setup::from_cli_args(&opts) {
Ok(results) => results,
Err(e) => {
if let ConfigError::KdlError(error) = e {
let report: Report = error.into();
eprintln!("{:?}", report);
} else {
eprintln!("{}", e);
}
process::exit(1);
},
};
let (
config,
layout,
config_options,
mut config_without_layout,
mut config_options_without_layout,
) = match Setup::from_cli_args(&opts) {
Ok(results) => results,
Err(e) => {
if let ConfigError::KdlError(error) = e {
let report: Report = error.into();
eprintln!("{:?}", report);
} else {
eprintln!("{}", e);
}
process::exit(1);
},
};

let mut reconnect_to_session: Option<ConnectToSession> = None;
let os_input = get_os_input(get_client_os_input);
loop {
Expand All @@ -415,6 +421,11 @@ pub(crate) fn start_client(opts: CliArgs) {
// untested and pretty involved function
//
// ideally, we should write tests for this whole function and refctor it
reload_config_from_disk(
&mut config_without_layout,
&mut config_options_without_layout,
&opts,
);
if reconnect_to_session.name.is_some() {
opts.command = Some(Command::Sessions(Sessions::Attach {
session_name: reconnect_to_session.name.clone(),
Expand Down Expand Up @@ -711,3 +722,19 @@ pub(crate) fn list_aliases(opts: CliArgs) {
}
process::exit(0);
}

fn reload_config_from_disk(
config_without_layout: &mut Config,
config_options_without_layout: &mut Options,
opts: &CliArgs,
) {
match Setup::from_cli_args(&opts) {
Ok((_, _, _, reloaded_config_without_layout, reloaded_config_options_without_layout)) => {
*config_without_layout = reloaded_config_without_layout;
*config_options_without_layout = reloaded_config_options_without_layout;
},
Err(e) => {
log::error!("Failed to reload config: {}", e);
},
};
}
49 changes: 43 additions & 6 deletions zellij-client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use log::info;
use std::env::current_exe;
use std::io::{self, Write};
use std::path::Path;
use std::path::PathBuf;
use std::process::Command;
use std::sync::{Arc, Mutex};
use std::thread;
Expand Down Expand Up @@ -53,6 +54,7 @@ pub(crate) enum ClientInstruction {
UnblockCliPipeInput(String), // String -> pipe name
CliPipeOutput(String, String), // String -> pipe name, String -> output
QueryTerminalSize,
WriteConfigToDisk { config: String },
}

impl From<ServerToClientMsg> for ClientInstruction {
Expand All @@ -75,6 +77,9 @@ impl From<ServerToClientMsg> for ClientInstruction {
ClientInstruction::CliPipeOutput(pipe_name, output)
},
ServerToClientMsg::QueryTerminalSize => ClientInstruction::QueryTerminalSize,
ServerToClientMsg::WriteConfigToDisk { config } => {
ClientInstruction::WriteConfigToDisk { config }
},
}
}
}
Expand All @@ -97,6 +102,7 @@ impl From<&ClientInstruction> for ClientContext {
ClientInstruction::UnblockCliPipeInput(..) => ClientContext::UnblockCliPipeInput,
ClientInstruction::CliPipeOutput(..) => ClientContext::CliPipeOutput,
ClientInstruction::QueryTerminalSize => ClientContext::QueryTerminalSize,
ClientInstruction::WriteConfigToDisk { .. } => ClientContext::WriteConfigToDisk,
}
}
}
Expand Down Expand Up @@ -158,8 +164,8 @@ pub(crate) enum InputInstruction {
pub fn start_client(
mut os_input: Box<dyn ClientOsApi>,
opts: CliArgs,
config: Config,
config_options: Options,
config: Config, // saved to disk (or default?)
config_options: Options, // CLI options merged into (getting priority over) saved config options
info: ClientInfo,
layout: Option<Layout>,
tab_position_to_focus: Option<usize>,
Expand Down Expand Up @@ -219,7 +225,6 @@ pub fn start_client(
rounded_corners: config.ui.pane_frames.rounded_corners,
hide_session_name: config.ui.pane_frames.hide_session_name,
},
keybinds: config.keybinds.clone(),
};

let create_ipc_pipe = || -> std::path::PathBuf {
Expand All @@ -239,7 +244,8 @@ pub fn start_client(
(
ClientToServerMsg::AttachClient(
client_attributes,
config_options,
config.clone(),
config_options.clone(),
tab_position_to_focus,
pane_id_to_focus,
),
Expand All @@ -252,14 +258,25 @@ pub fn start_client(
let ipc_pipe = create_ipc_pipe();

spawn_server(&*ipc_pipe, opts.debug).unwrap();
let successfully_written_config =
Config::write_config_to_disk_if_it_does_not_exist(config.to_string(true), &opts);
// if we successfully wrote the config to disk, it means two things:
// 1. It did not exist beforehand
// 2. The config folder is writeable
//
// If these two are true, we should launch the setup wizard, if even one of them is
// false, we should never launch it.
let should_launch_setup_wizard = successfully_written_config;

(
ClientToServerMsg::NewClient(
client_attributes,
Box::new(opts),
Box::new(opts.clone()),
Box::new(config.clone()),
Box::new(config_options.clone()),
Box::new(layout.unwrap()),
Box::new(config.plugins.clone()),
should_launch_setup_wizard,
),
ipc_pipe,
)
Expand Down Expand Up @@ -531,6 +548,23 @@ pub fn start_client(
os_input.get_terminal_size_using_fd(0),
));
},
ClientInstruction::WriteConfigToDisk { config } => {
match Config::write_config_to_disk(config, &opts) {
Ok(written_config) => {
let _ = os_input
.send_to_server(ClientToServerMsg::ConfigWrittenToDisk(written_config));
},
Err(e) => {
let error_path = e
.as_ref()
.map(|p| p.display().to_string())
.unwrap_or_else(String::new);
log::error!("Failed to write config to disk: {}", error_path);
let _ = os_input
.send_to_server(ClientToServerMsg::FailedToWriteConfigToDisk(e));
},
}
},
_ => {},
}
}
Expand Down Expand Up @@ -593,7 +627,6 @@ pub fn start_server_detached(
rounded_corners: config.ui.pane_frames.rounded_corners,
hide_session_name: config.ui.pane_frames.hide_session_name,
},
keybinds: config.keybinds.clone(),
};

let create_ipc_pipe = || -> std::path::PathBuf {
Expand All @@ -611,14 +644,18 @@ pub fn start_server_detached(
let ipc_pipe = create_ipc_pipe();

spawn_server(&*ipc_pipe, opts.debug).unwrap();
let should_launch_setup_wizard = false; // no setup wizard when starting a detached
// server

(
ClientToServerMsg::NewClient(
client_attributes,
Box::new(opts),
Box::new(config.clone()),
Box::new(config_options.clone()),
Box::new(layout.unwrap()),
Box::new(config.plugins.clone()),
should_launch_setup_wizard,
),
ipc_pipe,
)
Expand Down
Loading

0 comments on commit a600c85

Please sign in to comment.