mirror of
https://github.com/zellij-org/zellij.git
synced 2024-12-26 02:32:21 +03:00
poking
This commit is contained in:
parent
3e0174cc4a
commit
c644a1c243
@ -22,6 +22,8 @@ _zellij() {
|
||||
'--max-panes=[Maximum panes on screen, caution: opening more panes will close old ones]' \
|
||||
'-l+[Path to a layout yaml file]' \
|
||||
'--layout=[Path to a layout yaml file]' \
|
||||
'-c+[Path to the configuration yaml file]' \
|
||||
'--config=[Path to the configuration yaml file]' \
|
||||
'-m[Send "move focused pane" to active zellij session]' \
|
||||
'--move-focus[Send "move focused pane" to active zellij session]' \
|
||||
'-d[]' \
|
||||
|
@ -20,7 +20,7 @@ _zellij() {
|
||||
|
||||
case "${cmd}" in
|
||||
zellij)
|
||||
opts=" -m -d -h -V -s -o -l --move-focus --debug --help --version --split --open-file --max-panes --layout "
|
||||
opts=" -m -d -h -V -s -o -l -c --move-focus --debug --help --version --split --open-file --max-panes --layout --config "
|
||||
if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then
|
||||
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
|
||||
return 0
|
||||
@ -55,6 +55,14 @@ _zellij() {
|
||||
COMPREPLY=($(compgen -f "${cur}"))
|
||||
return 0
|
||||
;;
|
||||
--config)
|
||||
COMPREPLY=($(compgen -f "${cur}"))
|
||||
return 0
|
||||
;;
|
||||
-c)
|
||||
COMPREPLY=($(compgen -f "${cur}"))
|
||||
return 0
|
||||
;;
|
||||
*)
|
||||
COMPREPLY=()
|
||||
;;
|
||||
|
@ -2,6 +2,7 @@ complete -c zellij -n "__fish_use_subcommand" -s s -l split -d 'Send "split (dir
|
||||
complete -c zellij -n "__fish_use_subcommand" -s o -l open-file -d 'Send "open file in new pane" to active zellij session'
|
||||
complete -c zellij -n "__fish_use_subcommand" -l max-panes -d 'Maximum panes on screen, caution: opening more panes will close old ones'
|
||||
complete -c zellij -n "__fish_use_subcommand" -s l -l layout -d 'Path to a layout yaml file'
|
||||
complete -c zellij -n "__fish_use_subcommand" -s c -l config -d 'Path to the configuration yaml file'
|
||||
complete -c zellij -n "__fish_use_subcommand" -s m -l move-focus -d 'Send "move focused pane" to active zellij session'
|
||||
complete -c zellij -n "__fish_use_subcommand" -s d -l debug
|
||||
complete -c zellij -n "__fish_use_subcommand" -s h -l help -d 'Prints help information'
|
||||
|
8
config.yaml
Normal file
8
config.yaml
Normal file
@ -0,0 +1,8 @@
|
||||
---
|
||||
macro:
|
||||
{name:"closePane", sequence: [NewPane: Right,]}
|
||||
|
||||
keybinds:
|
||||
Normal:
|
||||
Backspace: [NewPane:, NewPane:,]
|
||||
{F: 1}: [NewPane:,]
|
@ -24,6 +24,10 @@ pub struct CliArgs {
|
||||
#[structopt(short, long)]
|
||||
pub layout: Option<PathBuf>,
|
||||
|
||||
/// Path to the configuration yaml file
|
||||
#[structopt(short, long)]
|
||||
pub config: Option<PathBuf>,
|
||||
|
||||
#[structopt(short, long)]
|
||||
pub debug: bool,
|
||||
}
|
||||
|
@ -1,14 +1,15 @@
|
||||
//! Deserializes configuration options.
|
||||
use std;
|
||||
use std::collections::HashMap;
|
||||
//use std::collections::HashMap;
|
||||
use std::error;
|
||||
use std::fmt::{self, Display};
|
||||
use std::fs::File;
|
||||
use std::io::{self,Read};
|
||||
use std::io::{self, Read};
|
||||
use std::path::PathBuf;
|
||||
|
||||
use super::input::{keybinds,handler};
|
||||
use super::input::{keybinds, macros};
|
||||
|
||||
use directories_next::ProjectDirs;
|
||||
use serde::Deserialize;
|
||||
|
||||
/// Intermediate struct
|
||||
@ -16,17 +17,17 @@ use serde::Deserialize;
|
||||
|
||||
//}
|
||||
|
||||
|
||||
/// Intermediate struct
|
||||
//#[derive(Debug, Deserialize)]
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct ConfigFromYaml {
|
||||
keybinds: HashMap<handler::InputMode,Vec<keybinds::Keybinds>>,
|
||||
keybinds: Option<keybinds::Keybinds>,
|
||||
macros: Option<Vec<macros::Macro>>,
|
||||
}
|
||||
|
||||
///// Deserialized config state
|
||||
#[derive(Debug, Clone, Default, Deserialize)]
|
||||
pub struct Config {
|
||||
keybinds: Vec<keybinds::Keybinds>,
|
||||
pub keybinds: keybinds::Keybinds,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -43,37 +44,52 @@ pub enum ConfigError {
|
||||
Serde(serde_yaml::Error),
|
||||
//Eof,
|
||||
// io::Error
|
||||
Io(io::Error)
|
||||
Io(io::Error),
|
||||
}
|
||||
|
||||
impl Config {
|
||||
/// Deserializes from given path
|
||||
pub fn new(path: &PathBuf) -> Result<Config,ConfigError> {
|
||||
let config_deserialized: Config;
|
||||
pub fn new(path: &PathBuf) -> Result<Config, ConfigError> {
|
||||
let config: Config;
|
||||
let config_deserialized: ConfigFromYaml;
|
||||
let mut config_string = String::new();
|
||||
|
||||
// TODO fix this unwrap
|
||||
match File::open(path) {
|
||||
Ok(mut file) => {
|
||||
file.read_to_string(&mut config_string)?;
|
||||
config_deserialized = serde_yaml::from_str(&config_string)?;
|
||||
config = Config {
|
||||
keybinds: config_deserialized
|
||||
.keybinds
|
||||
.unwrap_or_else(|| keybinds::get_default_keybinds().unwrap()),
|
||||
}
|
||||
}
|
||||
Err(_) => {
|
||||
Err(e) => {
|
||||
// TODO logging, if a file is not found
|
||||
// at an expected position - should not
|
||||
// panic @a-kenji
|
||||
config_deserialized = Config::default();
|
||||
eprintln!("{}", e);
|
||||
config = Config::default();
|
||||
}
|
||||
}
|
||||
Ok(config_deserialized)
|
||||
Ok(config)
|
||||
}
|
||||
|
||||
pub fn from_option_or_default(option: Option<PathBuf>) -> Result<Config, ConfigError> {
|
||||
let config;
|
||||
if let Some(config_path) = option {
|
||||
config = Config::new(&config_path)?;
|
||||
} else {
|
||||
let project_dirs = ProjectDirs::from("org", "Zellij Contributors", "Zellij").unwrap();
|
||||
//let config_path = PathBuf::from(project_dirs.config_dir().as_os_str());
|
||||
let config_path = project_dirs.config_dir().to_owned().into();
|
||||
config = Config::new(&config_path)?;
|
||||
}
|
||||
return Ok(config);
|
||||
}
|
||||
}
|
||||
|
||||
//impl de::Error for ConfigError {
|
||||
//fn custom<T: Display>(msg: T) -> Self {
|
||||
//ConfigError::Message(msg.to_string())
|
||||
//}
|
||||
//}
|
||||
|
||||
impl Display for ConfigError {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
@ -88,25 +104,17 @@ impl Display for ConfigError {
|
||||
}
|
||||
|
||||
impl std::error::Error for ConfigError {
|
||||
fn description(&self) -> &str {
|
||||
fn cause(&self) -> Option<&dyn error::Error> {
|
||||
match *self {
|
||||
//ConfigError::Message(ref err) => err,
|
||||
ConfigError::Io(ref err) => err.to_string().as_str(),
|
||||
ConfigError::Serde(ref err) => err.to_string().as_str(),
|
||||
// N.B. Both of these implicitly cast `err` from their concrete
|
||||
// types (either `&io::Error` or `&num::ParseIntError`)
|
||||
// to a trait object `&Error`. This works because both error types
|
||||
// implement `Error`.
|
||||
ConfigError::Io(ref err) => Some(err),
|
||||
//ConfigError::Message(ref err) => Some(err),
|
||||
ConfigError::Serde(ref err) => Some(err),
|
||||
}
|
||||
}
|
||||
|
||||
fn cause(&self) -> Option<&dyn error::Error> {
|
||||
match *self {
|
||||
// N.B. Both of these implicitly cast `err` from their concrete
|
||||
// types (either `&io::Error` or `&num::ParseIntError`)
|
||||
// to a trait object `&Error`. This works because both error types
|
||||
// implement `Error`.
|
||||
ConfigError::Io(ref err) => Some(err),
|
||||
//ConfigError::Message(ref err) => Some(err),
|
||||
ConfigError::Serde(ref err) => Some(err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<io::Error> for ConfigError {
|
||||
@ -120,10 +128,3 @@ impl From<serde_yaml::Error> for ConfigError {
|
||||
ConfigError::Serde(err)
|
||||
}
|
||||
}
|
||||
|
||||
//impl From<de::Error::Message> for ConfigError {
|
||||
//fn from(err: de::Error::Message) -> ConfigError {
|
||||
//ConfigError::Message(err)
|
||||
//}
|
||||
//}
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
use super::actions::Action;
|
||||
use super::keybinds::get_default_keybinds;
|
||||
use crate::common::config::Config;
|
||||
use crate::common::{update_state, AppInstruction, AppState, SenderWithContext, OPENCALLS};
|
||||
use crate::errors::ContextType;
|
||||
use crate::os_input_output::OsApi;
|
||||
@ -22,6 +23,7 @@ struct InputHandler {
|
||||
/// The current input mode
|
||||
mode: InputMode,
|
||||
os_input: Box<dyn OsApi>,
|
||||
config: Config,
|
||||
command_is_executing: CommandIsExecuting,
|
||||
send_screen_instructions: SenderWithContext<ScreenInstruction>,
|
||||
send_pty_instructions: SenderWithContext<PtyInstruction>,
|
||||
@ -34,6 +36,7 @@ impl InputHandler {
|
||||
fn new(
|
||||
os_input: Box<dyn OsApi>,
|
||||
command_is_executing: CommandIsExecuting,
|
||||
config: Config,
|
||||
send_screen_instructions: SenderWithContext<ScreenInstruction>,
|
||||
send_pty_instructions: SenderWithContext<PtyInstruction>,
|
||||
send_plugin_instructions: SenderWithContext<PluginInstruction>,
|
||||
@ -42,6 +45,7 @@ impl InputHandler {
|
||||
InputHandler {
|
||||
mode: InputMode::Normal,
|
||||
os_input,
|
||||
config,
|
||||
command_is_executing,
|
||||
send_screen_instructions,
|
||||
send_pty_instructions,
|
||||
@ -59,6 +63,8 @@ impl InputHandler {
|
||||
self.send_app_instructions.update(err_ctx);
|
||||
self.send_screen_instructions.update(err_ctx);
|
||||
if let Ok(keybinds) = get_default_keybinds() {
|
||||
let mut merged_keybinds = keybinds;
|
||||
merged_keybinds.extend(self.config.keybinds.clone().into_iter());
|
||||
'input_loop: loop {
|
||||
//@@@ I think this should actually just iterate over stdin directly
|
||||
let stdin_buffer = self.os_input.read_from_stdin();
|
||||
@ -76,9 +82,14 @@ impl InputHandler {
|
||||
// been revised. Sorry about this (@categorille)
|
||||
if {
|
||||
let mut should_break = false;
|
||||
for action in
|
||||
key_to_actions(&key, raw_bytes, &self.mode, &keybinds)
|
||||
{
|
||||
// Hacked on way to have a means of testing Macros, needs to
|
||||
// get properly integrated
|
||||
for action in key_to_actions(
|
||||
&key,
|
||||
raw_bytes,
|
||||
&self.mode,
|
||||
&merged_keybinds,
|
||||
) {
|
||||
should_break |= self.dispatch_action(action);
|
||||
}
|
||||
should_break
|
||||
@ -324,6 +335,7 @@ pub fn get_help(mode: InputMode) -> Help {
|
||||
/// its [`InputHandler::handle_input()`] loop.
|
||||
pub fn input_loop(
|
||||
os_input: Box<dyn OsApi>,
|
||||
config: Config,
|
||||
command_is_executing: CommandIsExecuting,
|
||||
send_screen_instructions: SenderWithContext<ScreenInstruction>,
|
||||
send_pty_instructions: SenderWithContext<PtyInstruction>,
|
||||
@ -333,6 +345,7 @@ pub fn input_loop(
|
||||
let _handler = InputHandler::new(
|
||||
os_input,
|
||||
command_is_executing,
|
||||
config,
|
||||
send_screen_instructions,
|
||||
send_pty_instructions,
|
||||
send_plugin_instructions,
|
||||
|
@ -23,7 +23,7 @@ pub fn get_default_keybinds() -> Result<Keybinds, String> {
|
||||
Ok(defaults)
|
||||
}
|
||||
|
||||
/// Returns the default keybinds for a givent [`InputMode`].
|
||||
/// Returns the default keybinds for a given [`InputMode`].
|
||||
fn get_defaults_for_mode(mode: &InputMode) -> Result<ModeKeybinds, String> {
|
||||
let mut defaults = ModeKeybinds::new();
|
||||
|
||||
|
@ -8,5 +8,5 @@ use serde::Deserialize;
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct Macro {
|
||||
name: Option<String>,
|
||||
sequence: Vec<Action>
|
||||
sequence: Vec<Action>,
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
pub mod config;
|
||||
pub mod command_is_executing;
|
||||
pub mod config;
|
||||
pub mod errors;
|
||||
pub mod input;
|
||||
pub mod install;
|
||||
@ -46,10 +46,17 @@ pub enum ApiCommand {
|
||||
MoveFocus,
|
||||
}
|
||||
// FIXME: It would be good to add some more things to this over time
|
||||
#[derive(Debug, Clone, Default)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct AppState {
|
||||
pub input_mode: InputMode,
|
||||
pub config : Config,
|
||||
}
|
||||
|
||||
impl Default for AppState {
|
||||
fn default() -> Self {
|
||||
AppState {
|
||||
input_mode: InputMode::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: Make this a method on the big `Communication` struct, so that app_tx can be extracted
|
||||
@ -158,8 +165,13 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) {
|
||||
.get_stdout_writer()
|
||||
.write(take_snapshot.as_bytes())
|
||||
.unwrap();
|
||||
|
||||
let mut app_state = AppState::default();
|
||||
|
||||
let config = Config::from_option_or_default(opts.config)
|
||||
.map_err(|e| eprintln!{"Config Error: {}", e})
|
||||
.unwrap();
|
||||
|
||||
let command_is_executing = CommandIsExecuting::new();
|
||||
|
||||
let full_screen_ws = os_input.get_terminal_size_using_fd(0);
|
||||
@ -638,9 +650,11 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) {
|
||||
let send_pty_instructions = send_pty_instructions.clone();
|
||||
let send_plugin_instructions = send_plugin_instructions.clone();
|
||||
let os_input = os_input.clone();
|
||||
let config = config.clone();
|
||||
move || {
|
||||
input_loop(
|
||||
os_input,
|
||||
config,
|
||||
command_is_executing,
|
||||
send_screen_instructions,
|
||||
send_pty_instructions,
|
||||
|
Loading…
Reference in New Issue
Block a user