Merge branch 'main' into resize-overhaul

This commit is contained in:
Brooks J Rady 2021-06-01 18:05:32 +01:00
commit 98c29832e1
15 changed files with 226 additions and 30 deletions

View file

@ -12,6 +12,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
* Fix(ui): session mode should be disabled in locked mode (https://github.com/zellij-org/zellij/pull/548) * Fix(ui): session mode should be disabled in locked mode (https://github.com/zellij-org/zellij/pull/548)
* Add option to start in arbitrary modes (https://github.com/zellij-org/zellij/pull/513) * Add option to start in arbitrary modes (https://github.com/zellij-org/zellij/pull/513)
* Attaching to a session respects the `default_mode` setting of the client (https://github.com/zellij-org/zellij/pull/549) * Attaching to a session respects the `default_mode` setting of the client (https://github.com/zellij-org/zellij/pull/549)
* Add option to specify a color theme in the config (https://github.com/zellij-org/zellij/pull/550)
* Fix config options to not depend on `simplified_ui` (https://github.com/zellij-org/zellij/pull/556)
* Don't rename `unnamed` tabs upon deletion of other tabs (https://github.com/zellij-org/zellij/pull/554)
* Add layout to disable the status bar (https://github.com/zellij-org/zellij/pull/555)
## [0.12.1] - 2021-05-28 ## [0.12.1] - 2021-05-28
* HOTFIX: fix Zellij not responding to input on certain terminals (https://github.com/zellij-org/zellij/issues/538) * HOTFIX: fix Zellij not responding to input on certain terminals (https://github.com/zellij-org/zellij/issues/538)

View file

@ -0,0 +1,8 @@
---
direction: Horizontal
parts:
- direction: Vertical
split_size:
Fixed: 1
plugin: tab-bar
- direction: Vertical

View file

@ -46,11 +46,7 @@ pub fn tab_style(
capabilities: PluginCapabilities, capabilities: PluginCapabilities,
) -> LinePart { ) -> LinePart {
let separator = tab_separator(capabilities); let separator = tab_separator(capabilities);
let mut tab_text = if text.is_empty() { let mut tab_text = text;
format!("Tab #{}", position + 1)
} else {
text
};
if is_sync_panes_active { if is_sync_panes_active {
tab_text.push_str(" (Sync)"); tab_text.push_str(" (Sync)");
} }

View file

@ -13,6 +13,9 @@ and screen), but this is merely its infrastructure layer.
Zellij includes a layout system, and a plugin system allowing one to create Zellij includes a layout system, and a plugin system allowing one to create
plugins in any language that compiles to WebAssembly. plugins in any language that compiles to WebAssembly.
To list currently running sessions run: `zellij list-sessions`
To attach to a currently running session run: `zellij attach [session-name]`
OPTIONS OPTIONS
======= =======
@ -24,9 +27,12 @@ CONFIGURATION
Zellij looks for configuration file in the following order: Zellij looks for configuration file in the following order:
1. the file provided with _--config_ 1. the file provided with _--config_
2. under the path provided in *ZELLIJ_CONFIG* environment variable 2. under the path provided in *ZELLIJ_CONFIG_FILE* environment variable
3. the default location (see FILES section) 3. the default location (see FILES section)
4. the system location
Run `zellij setup --check` in order to see possible issues with the
configuration.
LAYOUTS LAYOUTS
======= =======
@ -85,7 +91,7 @@ KEYBINDINGS
=========== ===========
Zellij comes with a default set of keybindings which aims to fit as many users Zellij comes with a default set of keybindings which aims to fit as many users
as possible but that behaviour can be overidden or modified in user as possible but that behaviour can be overridden or modified in user
configuration files. The information about bindings is available in the configuration files. The information about bindings is available in the
_keybinds_ section of configuration. For example, to introduce a keybinding that _keybinds_ section of configuration. For example, to introduce a keybinding that
will create a new tab and go to tab 1 after pressing 'c' one can write: will create a new tab and go to tab 1 after pressing 'c' one can write:
@ -147,6 +153,8 @@ ACTIONS
Right, Up, Down). Right, Up, Down).
* __ScrollUp__ - scrolls up 1 line in the focused pane. * __ScrollUp__ - scrolls up 1 line in the focused pane.
* __ScrollDown__ - scrolls down 1 line in the focused pane. * __ScrollDown__ - scrolls down 1 line in the focused pane.
* __PageScrollUp__ - scrolls up 1 page in the focused pane.
* __PageScrollDown__ - scrolls down 1 page in the focused pane.
* __ToggleFocusFullscreen__ - toggles between fullscreen focus pane and normal * __ToggleFocusFullscreen__ - toggles between fullscreen focus pane and normal
layout. layout.
* __NewPane: <Direction\>__ - opens a new pane in the specified direction (Left, * __NewPane: <Direction\>__ - opens a new pane in the specified direction (Left,
@ -157,6 +165,10 @@ ACTIONS
* __GoToPreviousTab__ - goes to previous tab. * __GoToPreviousTab__ - goes to previous tab.
* __CloseTab__ - closes current tab. * __CloseTab__ - closes current tab.
* __GoToTab: <Index\>__ - goes to the tab with the specified index number. * __GoToTab: <Index\>__ - goes to the tab with the specified index number.
* __Detach__ - detach session and exit.
* __ToggleActiveSyncTab__ - toggle between sending text commands to all panes
on the current tab and normal mode.
KEYS KEYS
---- ----
@ -190,8 +202,45 @@ MODES
moving, closing). moving, closing).
* __resize__ - allows resizing of the focused pane. * __resize__ - allows resizing of the focused pane.
* __scroll__ - allows scrolling within the focused pane. * __scroll__ - allows scrolling within the focused pane.
* __RenameTab__ - is a "hidden" mode that can be passed to _SwitchToMode_ * __renametab__ - is a "hidden" mode that can be passed to _SwitchToMode_
action. It will trigger renaming of a tab. action. It will trigger renaming of a tab.
* __session__ - allows detaching from a session.
Theme
=====
A color theme can be defined either in truecolor, or 256 format.
Truecolor:
```
fg: [0, 0, 0]
```
256:
```
fg: 0
```
The color theme can be specified in the following way:
```
themes:
default:
fg: [0,0,0]
bg: [0,0,0]
black: [0,0,0]
red: [0,0,0]
green: [0,0,0]
yellow: [0,0,0]
blue: [0,0,0]
magenta: [0,0,0]
cyan: [0,0,0]
white: [0,0,0]
orange: [0,0,0]
```
If the theme is called `default`, then zellij will pick it on startup.
To specify a different theme, run zellij with:
```
zellij options --theme [NAME]
```
or put the name in the configuration file with `theme: [NAME]`.
PLUGINS PLUGINS
======= =======
@ -210,8 +259,11 @@ Default user configuration file location:
ENVIRONMENT ENVIRONMENT
=========== ===========
ZELLIJ_CONFIG ZELLIJ_CONFIG_FILE
Path of Zellij config to load. Path of Zellij config to load.
ZELLIJ_CONFIG_DIR
Path of the Zellij config directory.
NOTES NOTES

View file

@ -19,6 +19,7 @@ pub(crate) fn populate_data_dir(data_dir: &Path) {
let mut assets = asset_map! { let mut assets = asset_map! {
"assets/layouts/default.yaml" => "layouts/default.yaml", "assets/layouts/default.yaml" => "layouts/default.yaml",
"assets/layouts/strider.yaml" => "layouts/strider.yaml", "assets/layouts/strider.yaml" => "layouts/strider.yaml",
"assets/layouts/disable-status-bar.yaml" => "layouts/disable-status-bar.yaml",
}; };
assets.extend(asset_map! { assets.extend(asset_map! {
"assets/plugins/status-bar.wasm" => "plugins/status-bar.wasm", "assets/plugins/status-bar.wasm" => "plugins/status-bar.wasm",

View file

@ -91,7 +91,14 @@ pub fn start_client(
let take_snapshot = "\u{1b}[?1049h"; let take_snapshot = "\u{1b}[?1049h";
let bracketed_paste = "\u{1b}[?2004h"; let bracketed_paste = "\u{1b}[?2004h";
os_input.unset_raw_mode(0); os_input.unset_raw_mode(0);
let palette = os_input.load_palette(); let config_options = Options::from_cli(&config.options, opts.command.clone());
let palette = config.themes.clone().map_or_else(
|| os_input.load_palette(),
|t| {
t.theme_config(&config_options)
.unwrap_or_else(|| os_input.load_palette())
},
);
let _ = os_input let _ = os_input
.get_stdout_writer() .get_stdout_writer()
.write(take_snapshot.as_bytes()) .write(take_snapshot.as_bytes())
@ -102,8 +109,6 @@ pub fn start_client(
.unwrap(); .unwrap();
std::env::set_var(&"ZELLIJ", "0"); std::env::set_var(&"ZELLIJ", "0");
let config_options = Options::from_cli(&config.options, opts.command.clone());
let full_screen_ws = os_input.get_terminal_size_using_fd(0); let full_screen_ws = os_input.get_terminal_size_using_fd(0);
let client_attributes = ClientAttributes { let client_attributes = ClientAttributes {
position_and_size: full_screen_ws, position_and_size: full_screen_ws,

View file

@ -15,7 +15,7 @@ use std::path::PathBuf;
use std::sync::{Arc, Mutex, RwLock}; use std::sync::{Arc, Mutex, RwLock};
use std::thread; use std::thread;
use wasmer::Store; use wasmer::Store;
use zellij_tile::data::{Event, PluginCapabilities}; use zellij_tile::data::{Event, Palette, PluginCapabilities};
use crate::{ use crate::{
os_input_output::ServerOsApi, os_input_output::ServerOsApi,
@ -84,6 +84,7 @@ impl ErrorInstruction for ServerInstruction {
pub(crate) struct SessionMetaData { pub(crate) struct SessionMetaData {
pub senders: ThreadSenders, pub senders: ThreadSenders,
pub capabilities: PluginCapabilities, pub capabilities: PluginCapabilities,
pub palette: Palette,
screen_thread: Option<thread::JoinHandle<()>>, screen_thread: Option<thread::JoinHandle<()>>,
pty_thread: Option<thread::JoinHandle<()>>, pty_thread: Option<thread::JoinHandle<()>>,
wasm_thread: Option<thread::JoinHandle<()>>, wasm_thread: Option<thread::JoinHandle<()>>,
@ -403,6 +404,7 @@ fn init_session(
to_server: None, to_server: None,
}, },
capabilities, capabilities,
palette: client_attributes.palette,
screen_thread: Some(screen_thread), screen_thread: Some(screen_thread),
pty_thread: Some(pty_thread), pty_thread: Some(pty_thread),
wasm_thread: Some(wasm_thread), wasm_thread: Some(wasm_thread),

View file

@ -18,7 +18,7 @@ use zellij_utils::{
fn route_action( fn route_action(
action: Action, action: Action,
session: &SessionMetaData, session: &SessionMetaData,
os_input: &dyn ServerOsApi, _os_input: &dyn ServerOsApi,
to_server: &SenderWithContext<ServerInstruction>, to_server: &SenderWithContext<ServerInstruction>,
) -> bool { ) -> bool {
let mut should_break = false; let mut should_break = false;
@ -34,7 +34,7 @@ fn route_action(
.unwrap(); .unwrap();
} }
Action::SwitchToMode(mode) => { Action::SwitchToMode(mode) => {
let palette = os_input.load_palette(); let palette = session.palette;
// TODO: use the palette from the client and remove it from the server os api // TODO: use the palette from the client and remove it from the server os api
// this is left here as a stop gap measure until we shift some code around // this is left here as a stop gap measure until we shift some code around
// to allow for this // to allow for this

View file

@ -246,6 +246,13 @@ impl Tab {
} else { } else {
BTreeMap::new() BTreeMap::new()
}; };
let name = if name.is_empty() {
format!("Tab #{}", position + 1)
} else {
name
};
Tab { Tab {
index, index,
position, position,

View file

@ -72,13 +72,13 @@ impl Default for InputMode {
} }
#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)] #[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub enum Theme { pub enum ThemeHue {
Light, Light,
Dark, Dark,
} }
impl Default for Theme { impl Default for ThemeHue {
fn default() -> Theme { fn default() -> ThemeHue {
Theme::Dark ThemeHue::Dark
} }
} }
@ -105,6 +105,7 @@ impl FromStr for InputMode {
"tab" => Ok(InputMode::Tab), "tab" => Ok(InputMode::Tab),
"scroll" => Ok(InputMode::Scroll), "scroll" => Ok(InputMode::Scroll),
"renametab" => Ok(InputMode::RenameTab), "renametab" => Ok(InputMode::RenameTab),
"session" => Ok(InputMode::Session),
e => Err(e.to_string().into()), e => Err(e.to_string().into()),
} }
} }
@ -123,7 +124,7 @@ impl Default for PaletteSource {
#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq, Hash, Default)] #[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq, Hash, Default)]
pub struct Palette { pub struct Palette {
pub source: PaletteSource, pub source: PaletteSource,
pub theme: Theme, pub theme_hue: ThemeHue,
pub fg: PaletteColor, pub fg: PaletteColor,
pub bg: PaletteColor, pub bg: PaletteColor,
pub black: PaletteColor, pub black: PaletteColor,

View file

@ -7,6 +7,7 @@ use std::path::{Path, PathBuf};
use super::keybinds::{Keybinds, KeybindsFromYaml}; use super::keybinds::{Keybinds, KeybindsFromYaml};
use super::options::Options; use super::options::Options;
use super::theme::ThemesFromYaml;
use crate::cli::{CliArgs, Command}; use crate::cli::{CliArgs, Command};
use crate::setup; use crate::setup;
@ -23,6 +24,7 @@ pub struct ConfigFromYaml {
#[serde(flatten)] #[serde(flatten)]
pub options: Option<Options>, pub options: Option<Options>,
pub keybinds: Option<KeybindsFromYaml>, pub keybinds: Option<KeybindsFromYaml>,
pub themes: Option<ThemesFromYaml>,
} }
/// Main configuration. /// Main configuration.
@ -30,6 +32,7 @@ pub struct ConfigFromYaml {
pub struct Config { pub struct Config {
pub keybinds: Keybinds, pub keybinds: Keybinds,
pub options: Options, pub options: Options,
pub themes: Option<ThemesFromYaml>,
} }
#[derive(Debug)] #[derive(Debug)]
@ -48,7 +51,13 @@ impl Default for Config {
fn default() -> Self { fn default() -> Self {
let keybinds = Keybinds::default(); let keybinds = Keybinds::default();
let options = Options::default(); let options = Options::default();
Config { keybinds, options } let themes = None;
Config {
keybinds,
options,
themes,
}
} }
} }
@ -90,7 +99,13 @@ impl Config {
let config_from_yaml: ConfigFromYaml = serde_yaml::from_str(&yaml_config)?; let config_from_yaml: ConfigFromYaml = serde_yaml::from_str(&yaml_config)?;
let keybinds = Keybinds::get_default_keybinds_with_config(config_from_yaml.keybinds); let keybinds = Keybinds::get_default_keybinds_with_config(config_from_yaml.keybinds);
let options = Options::from_yaml(config_from_yaml.options); let options = Options::from_yaml(config_from_yaml.options);
Ok(Config { keybinds, options }) let themes = config_from_yaml.themes;
Ok(Config {
keybinds,
options,
themes,
})
} }
/// Deserializes from given path. /// Deserializes from given path.

View file

@ -4,6 +4,7 @@ pub mod actions;
pub mod config; pub mod config;
pub mod keybinds; pub mod keybinds;
pub mod options; pub mod options;
pub mod theme;
use termion::input::TermRead; use termion::input::TermRead;
use zellij_tile::data::{InputMode, Key, ModeInfo, Palette, PluginCapabilities}; use zellij_tile::data::{InputMode, Key, ModeInfo, Palette, PluginCapabilities};

View file

@ -11,8 +11,12 @@ pub struct Options {
/// Allow plugins to use a more simplified layout /// Allow plugins to use a more simplified layout
/// that is compatible with more fonts /// that is compatible with more fonts
#[structopt(long)] #[structopt(long)]
#[serde(default)]
pub simplified_ui: bool, pub simplified_ui: bool,
/// Allows to specify the default mode /// Set the default theme
#[structopt(long)]
pub theme: Option<String>,
/// Set the default mode
#[structopt(long)] #[structopt(long)]
pub default_mode: Option<InputMode>, pub default_mode: Option<InputMode>,
} }
@ -41,8 +45,14 @@ impl Options {
other => other, other => other,
}; };
let theme = match other.theme {
None => self.theme.clone(),
other => other,
};
Options { Options {
simplified_ui, simplified_ui,
theme,
default_mode, default_mode,
} }
} }

View file

@ -0,0 +1,94 @@
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use super::options::Options;
use zellij_tile::data::{Palette, PaletteColor};
/// Intermediate deserialization of themes
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
pub struct ThemesFromYaml(HashMap<String, Theme>);
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
struct Theme {
#[serde(flatten)]
palette: PaletteFromYaml,
}
/// Intermediate deserialization struct
#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq, Hash, Default)]
pub struct PaletteFromYaml {
pub fg: PaletteColorFromYaml,
pub bg: PaletteColorFromYaml,
pub black: PaletteColorFromYaml,
pub red: PaletteColorFromYaml,
pub green: PaletteColorFromYaml,
pub yellow: PaletteColorFromYaml,
pub blue: PaletteColorFromYaml,
pub magenta: PaletteColorFromYaml,
pub cyan: PaletteColorFromYaml,
pub white: PaletteColorFromYaml,
pub orange: PaletteColorFromYaml,
}
/// Intermediate deserialization enum
// This is here in order to make the untagged enum work
#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
#[serde(untagged)]
pub enum PaletteColorFromYaml {
Rgb((u8, u8, u8)),
EightBit(u8),
}
impl Default for PaletteColorFromYaml {
fn default() -> Self {
PaletteColorFromYaml::EightBit(0)
}
}
impl ThemesFromYaml {
pub fn theme_config(self, opts: &Options) -> Option<Palette> {
let mut from_yaml = self;
match &opts.theme {
Some(theme) => from_yaml.from_default_theme(theme.to_owned()),
None => from_yaml.from_default_theme("default".into()),
}
}
fn get_theme(&mut self, theme: String) -> Option<Theme> {
self.0.remove(&theme)
}
fn from_default_theme(&mut self, theme: String) -> Option<Palette> {
self.clone()
.get_theme(theme)
.map(|t| Palette::from(t.palette))
}
}
impl From<PaletteFromYaml> for Palette {
fn from(yaml: PaletteFromYaml) -> Self {
Palette {
fg: yaml.fg.into(),
bg: yaml.fg.into(),
black: yaml.black.into(),
red: yaml.red.into(),
green: yaml.green.into(),
yellow: yaml.yellow.into(),
blue: yaml.blue.into(),
magenta: yaml.magenta.into(),
cyan: yaml.cyan.into(),
white: yaml.white.into(),
orange: yaml.orange.into(),
..Palette::default()
}
}
}
impl From<PaletteColorFromYaml> for PaletteColor {
fn from(yaml: PaletteColorFromYaml) -> Self {
match yaml {
PaletteColorFromYaml::Rgb(color) => PaletteColor::Rgb(color),
PaletteColorFromYaml::EightBit(color) => PaletteColor::EightBit(color),
}
}
}

View file

@ -8,7 +8,7 @@ use colors_transform::{Color, Rgb};
use std::os::unix::fs::PermissionsExt; use std::os::unix::fs::PermissionsExt;
use std::path::Path; use std::path::Path;
use std::{fs, io}; use std::{fs, io};
use zellij_tile::data::{Palette, PaletteColor, PaletteSource, Theme}; use zellij_tile::data::{Palette, PaletteColor, PaletteSource, ThemeHue};
const UNIX_PERMISSIONS: u32 = 0o700; const UNIX_PERMISSIONS: u32 = 0o700;
@ -64,7 +64,7 @@ pub fn _hex_to_rgb(hex: &str) -> (u8, u8, u8) {
pub fn default_palette() -> Palette { pub fn default_palette() -> Palette {
Palette { Palette {
source: PaletteSource::Default, source: PaletteSource::Default,
theme: Theme::Dark, theme_hue: ThemeHue::Dark,
fg: PaletteColor::EightBit(colors::BRIGHT_GRAY), fg: PaletteColor::EightBit(colors::BRIGHT_GRAY),
bg: PaletteColor::EightBit(colors::GRAY), bg: PaletteColor::EightBit(colors::GRAY),
black: PaletteColor::EightBit(colors::BLACK), black: PaletteColor::EightBit(colors::BLACK),
@ -80,7 +80,7 @@ pub fn default_palette() -> Palette {
} }
// Dark magic // Dark magic
pub fn _detect_theme(bg: PaletteColor) -> Theme { pub fn _detect_theme_hue(bg: PaletteColor) -> ThemeHue {
match bg { match bg {
PaletteColor::Rgb((r, g, b)) => { PaletteColor::Rgb((r, g, b)) => {
// HSP, P stands for perceived brightness // HSP, P stands for perceived brightness
@ -89,11 +89,11 @@ pub fn _detect_theme(bg: PaletteColor) -> Theme {
+ 0.114 * (b as f64 * b as f64)) + 0.114 * (b as f64 * b as f64))
.sqrt(); .sqrt();
match hsp > 127.5 { match hsp > 127.5 {
true => Theme::Light, true => ThemeHue::Light,
false => Theme::Dark, false => ThemeHue::Dark,
} }
} }
_ => Theme::Dark, _ => ThemeHue::Dark,
} }
} }