chore: painless merge this time

This commit is contained in:
denis 2021-05-01 13:45:01 +03:00
commit eabecde90b
57 changed files with 2921 additions and 702 deletions

View file

@ -1,5 +1,26 @@
---
name: Bug Report
about: Create a bug report
name: "\U0001F41B Bug Report"
about: "If something isn't working as expected."
labels: bug
---
Thank you for taking the time to file an issue!
You can erase any parts of this template not applicable to your issue.
## In Case of Graphical, or Performance Issues
Please run `zellij --debug` and then recreate your issue.
Please attach the files that were created in
`/tmp/zellij/zellij-log/`
To the extent you are comfortable with.
Also please add the size in columns/lines of the terminal in which the bug happened. You can usually find these out with `tput lines` and `tput cols`.
And the name and version of progams you interacted with as well as
the operating system.
## Information
`zellij --version`:

118
.github/workflows/release.yml vendored Normal file
View file

@ -0,0 +1,118 @@
name: Release
on:
push:
tags:
- 'v*.*.*'
workflow_dispatch:
jobs:
build-release:
needs: create-release
name: build-release
runs-on: ${{ matrix.os }}
env:
RUST_BACKTRACE: 1
strategy:
matrix:
build:
- linux musl x64
- linux musl aarch64
- macos x64
- macos aarch64
include:
- build: linux musl x64
os: ubuntu-latest
rust: beta
target: x86_64-unknown-linux-musl
- build: linux musl aarch64
os: ubuntu-latest
rust: beta
target: aarch64-unknown-linux-musl
- build: macos x64
os: macos-latest
rust: beta
target: x86_64-apple-darwin
- build: macos aarch64
os: macos-latest
rust: beta
target: aarch64-apple-darwin
steps:
- name: Set release tag
run: |
if [ "$GITHUB_EVENT_NAME" == 'workflow_dispatch' ]; then
echo "RELEASE_TAG=main" >> $GITHUB_ENV
else
echo "RELEASE_TAG=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV
fi
- name: Checkout repository
uses: actions/checkout@v2
- name: Install Rust
uses: actions-rs/toolchain@v1
with:
toolchain: ${{ matrix.rust }}
profile: minimal
override: true
target: ${{ matrix.target }}
- name: Add WASM target
run: rustup target add wasm32-wasi
- name: Install cargo-make
run: cargo install --debug cargo-make
- name: Install musl-tools
if: matrix.os == 'ubuntu-latest'
run: sudo apt-get install -y --no-install-recommends musl-tools
- name: Install wasm-opt
run: brew install binaryen
# Workaround for <https://github.com/actions/virtual-environments/issues/2557>
- name: Switch Xcode SDK
if: runner.os == 'macos'
run: |
cat <<EOF >> "$GITHUB_ENV"
SDKROOT=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk
EOF
- name: Build release binary
run: cargo make ci-build-release ${{ matrix.target }}
- name: Strip release binary
run: strip "target/${{ matrix.target }}/release/zellij"
- name: Tar release
id: make-artifact
working-directory: ./target/${{ matrix.target }}/release
run: |
name="zellij-${{ matrix.target }}.tar.gz"
tar cvzf "${name}" "zellij"
echo "::set-output name=name::${name}"
- name: Upload release archive
uses: actions/upload-release-asset@v1.0.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ needs.create-release.outputs.upload_url }}
asset_path: ./target/${{ matrix.target }}/release/${{ steps.make-artifact.outputs.name }}
asset_name: zellij-${{matrix.target}}.tar.gz
asset_content_type: application/octet-stream
create-release:
runs-on: ubuntu-latest
outputs:
upload_url: ${{ steps.create_release.outputs.upload_url }}
steps:
- name: create_release
id: create_release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.event_name == 'workflow_dispatch' && '' || github.ref }}
release_name: Release ${{ github.event_name == 'workflow_dispatch' && 'main' || github.ref }}
draft: ${{ github.event_name == 'workflow_dispatch' }}
prerelease: false

1
.gitignore vendored
View file

@ -2,3 +2,4 @@
*.new
.vscode
.vim
.DS_Store

View file

@ -5,7 +5,20 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
## [Unreleased]
* Fix the tab '(Sync)' suffix in named tabs (https://github.com/zellij-org/zellij/pull/410)
* Improve performance when multiple panes are open (https://github.com/zellij-org/zellij/pull/318)
## [0.6.0] - 2021-04-29
* Doesn't quit anymore on single `q` press while in tab mode (https://github.com/zellij-org/zellij/pull/342)
* Completions are not assets anymore, but commands `option --generate-completion [shell]` (https://github.com/zellij-org/zellij/pull/369)
* Fixes in the default configuration `default.yaml` file. Adds initial tmux-compat keybindings `tmux.yaml` (https://github.com/zellij-org/zellij/pull/362)
* Added the `get_plugin_ids()` query function to the plugin API (https://github.com/zellij-org/zellij/pull/392)
* Implemented simple plugin timers via the `set_timeout()` call (https://github.com/zellij-org/zellij/pull/394)
* Added more configuration locations, changed `ZELLIJ_CONFIG` to `ZELLIJ_CONFIG_FILE` (https://github.com/zellij-org/zellij/pull/391)
* Improved keybind handling (https://github.com/zellij-org/zellij/pull/400)
* Added initial screen-compat keybinds `screen.yaml` (https://github.com/zellij-org/zellij/pull/399)
* Added the ability to synchronize input sent to panes (https://github.com/zellij-org/zellij/pull/395)
* Terminal fix: pass vttest 1 (https://github.com/zellij-org/zellij/pull/408)
## [0.5.1] - 2021-04-23
* Change config to flag (https://github.com/zellij-org/zellij/pull/300)

4
Cargo.lock generated
View file

@ -2217,7 +2217,7 @@ dependencies = [
[[package]]
name = "zellij"
version = "0.6.0"
version = "0.7.0"
dependencies = [
"ansi_term 0.12.1",
"async-std",
@ -2252,7 +2252,7 @@ dependencies = [
[[package]]
name = "zellij-tile"
version = "1.0.0"
version = "1.1.0"
dependencies = [
"serde",
"serde_json",

View file

@ -1,13 +1,13 @@
[package]
name = "zellij"
version = "0.6.0"
version = "0.7.0"
authors = ["Aram Drevekenin <aram@poor.dev>"]
edition = "2018"
description = "A terminal workspace with batteries included"
license = "MIT"
repository = "https://github.com/zellij-org/zellij"
homepage = "https://zellij.dev"
include = ["src/**/*", "assets/plugins/*", "assets/layouts/*", "LICENSE.md", "README.md", "!**/*_test.*", "!**/tests/**/*"]
include = ["src/**/*", "assets/plugins/*", "assets/layouts/*", "assets/config/*", "LICENSE.md", "README.md", "!**/*_test.*", "!**/tests/**/*"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -38,7 +38,7 @@ wasmer-wasi = "1.0.0"
interprocess = "1.0.1"
xrdb = "0.1.1"
colors-transform = "0.2.5"
zellij-tile = { path = "zellij-tile/", version = "1.0.0" }
zellij-tile = { path = "zellij-tile/", version = "1.1.0" }
[dependencies.async-std]
version = "1.3.0"

View file

@ -84,9 +84,10 @@ script = '''
plugins = glob_array ${CARGO_TARGET_DIR}/wasm32-wasi/release/*.wasm
for plugin in ${plugins}
mkdir ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/assets/plugins/
plugin_name = basename ${plugin}
plugin_out = set ${CARGO_MAKE_WORKSPACE_WORKING_DIRECTORY}/assets/plugins/${plugin_name}
if is_path_newer ${plugin} ${plugin_out}
if not is_path_exists ${plugin_out} or is_path_newer ${plugin} ${plugin_out}
exec wasm-opt -O ${plugin} -o ${plugin_out}
end
end
@ -95,10 +96,14 @@ end
# CI Releasing Zellij
[tasks.ci-build-release]
workspace = false
dependencies = ["build-plugins-release", "wasm-opt-plugins", "build-release"]
command = "cargo"
dependencies = ["setup-cross-compilation", "build-plugins-release", "wasm-opt-plugins"]
command = "cross"
args = ["build", "--verbose", "--release", "--target", "${CARGO_MAKE_TASK_ARGS}"]
[tasks.setup-cross-compilation]
command = "cargo"
args = ["install", "cross"]
# Publishing Zellij
[tasks.publish]
clear = true

View file

@ -1,90 +0,0 @@
#compdef zellij
autoload -U is-at-least
_zellij() {
typeset -A opt_args
typeset -a _arguments_options
local ret=1
if is-at-least 5.2; then
_arguments_options=(-s -S -C)
else
_arguments_options=(-s -C)
fi
local context curcontext="$curcontext" state line
_arguments "${_arguments_options[@]}" \
'-s+[Send "split (direction h == horizontal / v == vertical)" to active zellij session]' \
'--split=[Send "split (direction h == horizontal / v == vertical)" to active zellij session]' \
'-o+[Send "open file in new pane" to active zellij session]' \
'--open-file=[Send "open file in new pane" to active zellij session]' \
'--max-panes=[Maximum panes on screen, caution: opening more panes will close old ones]' \
'--data-dir=[Change where zellij looks for layouts and plugins]' \
'-l+[Path to a layout yaml file]' \
'--layout=[Path to a layout yaml file]' \
'-c+[Change where zellij looks for the configuration]' \
'--config=[Change where zellij looks for the configuration]' \
'-m[Send "move focused pane" to active zellij session]' \
'--move-focus[Send "move focused pane" to active zellij session]' \
'-d[]' \
'--debug[]' \
'-h[Prints help information]' \
'--help[Prints help information]' \
'-V[Prints version information]' \
'--version[Prints version information]' \
":: :_zellij_commands" \
"*::: :->zellij" \
&& ret=0
case $state in
(zellij)
words=($line[1] "${words[@]}")
(( CURRENT += 1 ))
curcontext="${curcontext%:*:*}:zellij-command-$line[1]:"
case $line[1] in
(option)
_arguments "${_arguments_options[@]}" \
'--clean[Disables loading of configuration file at default location]' \
'-h[Prints help information]' \
'--help[Prints help information]' \
'-V[Prints version information]' \
'--version[Prints version information]' \
&& ret=0
;;
(help)
_arguments "${_arguments_options[@]}" \
'-h[Prints help information]' \
'--help[Prints help information]' \
'-V[Prints version information]' \
'--version[Prints version information]' \
&& ret=0
;;
esac
;;
esac
}
(( $+functions[_zellij_commands] )) ||
_zellij_commands() {
local commands; commands=(
"option:Change the behaviour of zellij" \
"help:Prints this message or the help of the given subcommand(s)" \
)
_describe -t commands 'zellij commands' commands "$@"
}
(( $+functions[_zellij__help_commands] )) ||
_zellij__help_commands() {
local commands; commands=(
)
_describe -t commands 'zellij help commands' commands "$@"
}
(( $+functions[_zellij__option_commands] )) ||
_zellij__option_commands() {
local commands; commands=(
)
_describe -t commands 'zellij option commands' commands "$@"
}
_zellij "$@"

View file

@ -1,117 +0,0 @@
_zellij() {
local i cur prev opts cmds
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
cmd=""
opts=""
for i in ${COMP_WORDS[@]}
do
case "${i}" in
zellij)
cmd="zellij"
;;
help)
cmd+="__help"
;;
option)
cmd+="__option"
;;
*)
;;
esac
done
case "${cmd}" in
zellij)
opts=" -m -d -h -V -s -o -l -c --move-focus --debug --help --version --split --open-file --max-panes --data-dir --layout --config option help"
if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
fi
case "${prev}" in
--split)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
-s)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
--open-file)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
-o)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
--max-panes)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
--data-dir)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
--layout)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
-l)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
--config)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
-c)
COMPREPLY=($(compgen -f "${cur}"))
return 0
;;
*)
COMPREPLY=()
;;
esac
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
;;
zellij__help)
opts=" -h -V --help --version "
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
fi
case "${prev}" in
*)
COMPREPLY=()
;;
esac
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
;;
zellij__option)
opts=" -h -V --clean --help --version "
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
fi
case "${prev}" in
*)
COMPREPLY=()
;;
esac
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
;;
esac
}
complete -F _zellij -o bashdefault -o default zellij

View file

@ -1,17 +0,0 @@
complete -c zellij -n "__fish_use_subcommand" -s s -l split -d 'Send "split (direction h == horizontal / v == vertical)" to active zellij session'
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" -l data-dir -d 'Change where zellij looks for layouts and plugins'
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 'Change where zellij looks for the configuration'
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'
complete -c zellij -n "__fish_use_subcommand" -s V -l version -d 'Prints version information'
complete -c zellij -n "__fish_use_subcommand" -f -a "option" -d 'Change the behaviour of zellij'
complete -c zellij -n "__fish_use_subcommand" -f -a "help" -d 'Prints this message or the help of the given subcommand(s)'
complete -c zellij -n "__fish_seen_subcommand_from option" -l clean -d 'Disables loading of configuration file at default location'
complete -c zellij -n "__fish_seen_subcommand_from option" -s h -l help -d 'Prints help information'
complete -c zellij -n "__fish_seen_subcommand_from option" -s V -l version -d 'Prints version information'
complete -c zellij -n "__fish_seen_subcommand_from help" -s h -l help -d 'Prints help information'
complete -c zellij -n "__fish_seen_subcommand_from help" -s V -l version -d 'Prints version information'

217
assets/config/default.yaml Normal file
View file

@ -0,0 +1,217 @@
---
keybinds:
unbind: true
normal:
- action: [SwitchToMode: Locked,]
key: [Ctrl: 'g',]
- action: [SwitchToMode: Pane,]
key: [Ctrl: 'p',]
- action: [SwitchToMode: Resize,]
key: [Ctrl: 'r',]
- action: [SwitchToMode: Tab,]
key: [Ctrl: 't',]
- action: [SwitchToMode: Scroll,]
key: [Ctrl: 's',]
- action: [Quit,]
key: [Ctrl: 'q',]
- action: [NewPane: ]
key: [ Alt: 'n',]
- action: [MoveFocus: Left,]
key: [ Alt: 'h',]
- action: [MoveFocus: Right,]
key: [ Alt: 'l',]
- action: [MoveFocus: Down,]
key: [ Alt: 'j',]
- action: [MoveFocus: Up,]
key: [ Alt: 'k',]
- action: [FocusPreviousPane,]
key: [ Alt: '[',]
- action: [FocusNextPane,]
key: [ Alt: ']',]
locked:
- action: [SwitchToMode: Normal,]
key: [Ctrl: 'g',]
resize:
- action: [SwitchToMode: Locked,]
key: [Ctrl: 'g']
- action: [SwitchToMode: Pane,]
key: [Ctrl: 'p',]
- action: [SwitchToMode: Tab,]
key: [Ctrl: 't',]
- action: [SwitchToMode: Normal,]
key: [Ctrl: 'r', Char: "\n", Char: ' ',]
- action: [SwitchToMode: Scroll,]
key: [Ctrl: 's']
- action: [Quit]
key: [Ctrl: 'q']
- action: [Resize: Left,]
key: [Char: 'h', Left,]
- action: [Resize: Down,]
key: [Char: 'j', Down,]
- action: [Resize: Up,]
key: [Char: 'k', Up, ]
- action: [Resize: Right,]
key: [Char: 'l', Right,]
- action: [NewPane: ,]
key: [ Alt: 'n',]
- action: [MoveFocus: Left,]
key: [ Alt: 'h', Left,]
- action: [MoveFocus: Right,]
key: [ Alt: 'l', Right,]
- action: [MoveFocus: Down,]
key: [ Alt: 'j', Down,]
- action: [MoveFocus: Up,]
key: [ Alt: 'k', Up,]
- action: [FocusPreviousPane,]
key: [ Alt: '[',]
- action: [FocusNextPane,]
key: [ Alt: ']',]
pane:
- action: [SwitchToMode: Locked,]
key: [Ctrl: 'g']
- action: [SwitchToMode: Resize,]
key: [Ctrl: 'r',]
- action: [SwitchToMode: Tab,]
key: [Ctrl: 't',]
- action: [SwitchToMode: Normal,]
key: [Ctrl: 'p', Char: "\n", Char: ' ',]
- action: [SwitchToMode: Scroll,]
key: [Ctrl: 's']
- action: [Quit,]
key: [Ctrl: 'q',]
- action: [MoveFocus: Left,]
key: [ Char: 'h', Left,]
- action: [MoveFocus: Right,]
key: [ Char: 'l', Right,]
- action: [MoveFocus: Down,]
key: [ Char: 'j', Down,]
- action: [MoveFocus: Up,]
key: [ Char: 'k', Up,]
- action: [SwitchFocus,]
key: [Char: 'p']
- action: [NewPane: ,]
key: [Char: 'n', Alt: 'n',]
- action: [NewPane: Down,]
key: [Char: 'd',]
- action: [NewPane: Right,]
key: [Char: 'r',]
- action: [CloseFocus,]
key: [Char: 'x',]
- action: [ToggleActiveSyncPanes]
key: [Char: 's']
- action: [ToggleFocusFullscreen,]
key: [Char: 'f',]
- action: [FocusPreviousPane,]
key: [ Alt: '[',]
- action: [FocusNextPane,]
key: [ Alt: ']',]
tab:
- action: [SwitchToMode: Locked,]
key: [Ctrl: 'g']
- action: [SwitchToMode: Pane,]
key: [Ctrl: 'p',]
- action: [SwitchToMode: Normal,]
key: [Ctrl: 'r', Ctrl: 't', Char: "\n", Char: ' ',]
- action: [SwitchToMode: Scroll,]
key: [Ctrl: 's']
- action: [SwitchToMode: RenameTab, TabNameInput: [0],]
key: [Char: 'r']
- action: [Quit,]
key: [Ctrl: 'q',]
- action: [FocusPreviousPane,]
key: [ Alt: '[',]
- action: [FocusNextPane,]
key: [ Alt: ']',]
- action: [GoToPreviousTab,]
key: [ Char: 'h',]
- action: [GoToNextTab,]
key: [ Char: 'l',]
- action: [GoToNextTab,]
key: [ Char: 'j',]
- action: [GoToPreviousTab,]
key: [ Char: 'k',]
- action: [NewTab,]
key: [ Char: 'n',]
- action: [CloseTab,]
key: [ Char: 'x',]
- action: [MoveFocus: Left,]
key: [ Alt: 'h',]
- action: [MoveFocus: Right,]
key: [ Alt: 'l',]
- action: [MoveFocus: Down,]
key: [ Alt: 'j',]
- action: [MoveFocus: Up,]
key: [ Alt: 'k',]
- action: [GoToTab: 1,]
key: [ Char: '1',]
- action: [GoToTab: 2,]
key: [ Char: '2',]
- action: [GoToTab: 3,]
key: [ Char: '3',]
- action: [GoToTab: 4,]
key: [ Char: '4',]
- action: [GoToTab: 5,]
key: [ Char: '5',]
- action: [GoToTab: 6,]
key: [ Char: '6',]
- action: [GoToTab: 7,]
key: [ Char: '7',]
- action: [GoToTab: 8,]
key: [ Char: '8',]
- action: [GoToTab: 9,]
key: [ Char: '9',]
scroll:
- action: [SwitchToMode: Normal,]
key: [Ctrl: 'r', Ctrl: 's', Char: ' ',
Char: "\n",]
- action: [SwitchToMode: Tab,]
key: [Ctrl: 't',]
- action: [SwitchToMode: Locked,]
key: [Ctrl: 'g',]
- action: [SwitchToMode: Pane,]
key: [Ctrl: 'p',]
- action: [Quit,]
key: [Ctrl: 'q',]
- action: [ScrollDown,]
key: [Char: 'j', Down,]
- action: [ScrollUp,]
key: [Char: 'k', Up,]
- action: [PageScrollDown,]
key: [Ctrl: 'f', PageDown,]
- action: [PageScrollUp,]
key: [Ctrl: 'b', PageUp,]
- action: [NewPane: ,]
key: [ Alt: 'n',]
- action: [MoveFocus: Left,]
key: [ Alt: 'h',]
- action: [MoveFocus: Right,]
key: [ Alt: 'l',]
- action: [MoveFocus: Down,]
key: [ Alt: 'j',]
- action: [MoveFocus: Up,]
key: [ Alt: 'k',]
- action: [FocusPreviousPane,]
key: [ Alt: '[',]
- action: [FocusNextPane,]
key: [ Alt: ']',]
renametab:
- action: [SwitchToMode: Normal,]
key: [Ctrl: 'r', Ctrl: 's', Char: ' ',]
- action: [SwitchToMode: Tab,]
key: [Char: "\n",]
- action: [TabNameInput: [27] , SwitchToMode: Tab,]
key: [Esc,]
- action: [NewPane: ,]
key: [ Alt: 'n',]
- action: [MoveFocus: Left,]
key: [ Alt: 'h',]
- action: [MoveFocus: Right,]
key: [ Alt: 'l',]
- action: [MoveFocus: Down,]
key: [ Alt: 'j',]
- action: [MoveFocus: Up,]
key: [ Alt: 'k',]
- action: [FocusPreviousPane,]
key: [ Alt: '[',]
- action: [FocusNextPane,]
key: [ Alt: ']',]

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -1,23 +0,0 @@
use std::fs;
use structopt::clap::Shell;
include!("src/cli.rs");
const BIN_NAME: &str = "zellij";
fn main() {
// Generate Shell Completions
let mut clap_app = CliArgs::clap();
println!("cargo:rerun-if-changed=src/cli.rs");
let mut out_dir = std::env::var_os("CARGO_MANIFEST_DIR").unwrap();
out_dir.push("/assets/completions");
println!(
"Completion files will to added to this location: {:?}",
out_dir
);
fs::create_dir_all(&out_dir).unwrap();
clap_app.gen_completions(BIN_NAME, Shell::Bash, &out_dir);
clap_app.gen_completions(BIN_NAME, Shell::Zsh, &out_dir);
clap_app.gen_completions(BIN_NAME, Shell::Fish, &out_dir);
}

View file

@ -54,7 +54,13 @@ impl ZellijPlugin for State {
} else if t.active {
active_tab_index = t.position;
}
let tab = tab_style(tabname, t.active, t.position, self.mode_info.palette);
let tab = tab_style(
tabname,
t.active,
t.position,
t.is_sync_panes_active,
self.mode_info.palette
);
all_tabs.push(tab);
}
let tab_line = tab_line(all_tabs, active_tab_index, cols, self.mode_info.palette);

View file

@ -44,12 +44,21 @@ pub fn non_active_tab(text: String, palette: Palette) -> LinePart {
}
}
pub fn tab_style(text: String, is_active_tab: bool, position: usize, palette: Palette) -> LinePart {
let tab_text = if text.is_empty() {
pub fn tab_style(
text: String,
is_active_tab: bool,
position: usize,
is_sync_panes_active: bool,
palette: Palette
) -> LinePart {
let mut tab_text = if text.is_empty() {
format!("Tab #{}", position + 1)
} else {
text
};
if is_sync_panes_active {
tab_text.push_str(" (Sync)");
}
if is_active_tab {
active_tab(tab_text, palette)
} else {

View file

@ -35,9 +35,9 @@ keybinds:
- action: [SwitchToMode: Locked,]
key: [Ctrl: 'g']
- action: [SwitchToMode: Pane,]
key: [Ctrl: 'p', ]
key: [Ctrl: 'p',]
- action: [SwitchToMode: Tab,]
key: [Ctrl: 't', ]
key: [Ctrl: 't',]
- action: [SwitchToMode: Normal,]
key: [Ctrl: 'r', Char: "\n", Char: ' ',]
- action: [SwitchToMode: Scroll,]
@ -45,13 +45,13 @@ keybinds:
- action: [Quit]
key: [Ctrl: 'q']
- action: [Resize: Left,]
key: [Char: 'h', Left, ]
key: [Char: 'h', Left,]
- action: [Resize: Down,]
key: [Char: 'h', Down, ]
key: [Char: 'j', Down,]
- action: [Resize: Up,]
key: [Char: 'h', Up, ]
key: [Char: 'k', Up, ]
- action: [Resize: Right,]
key: [Char: 'h', Right, ]
key: [Char: 'l', Right,]
- action: [NewPane: ,]
key: [ Alt: 'n',]
- action: [MoveFocus: Left,]
@ -70,9 +70,9 @@ keybinds:
- action: [SwitchToMode: Locked,]
key: [Ctrl: 'g']
- action: [SwitchToMode: Pane,]
key: [Ctrl: 'p', ]
key: [Ctrl: 'p',]
- action: [SwitchToMode: Tab,]
key: [Ctrl: 't', ]
key: [Ctrl: 't',]
- action: [SwitchToMode: Normal,]
key: [Ctrl: 'r', Char: "\n", Char: ' ',]
- action: [SwitchToMode: Scroll,]
@ -92,13 +92,13 @@ keybinds:
- action: [NewPane: ,]
key: [Char: 'n', Alt: 'n',]
- action: [NewPane: Down,]
key: [Char: 'd', ]
key: [Char: 'd',]
- action: [NewPane: Right,]
key: [Char: 'r', ]
key: [Char: 'r',]
- action: [CloseFocus,]
key: [Char: 'x', ]
key: [Char: 'x',]
- action: [ToggleFocusFullscreen,]
key: [Char: 'f', ]
key: [Char: 'f',]
- action: [FocusPreviousPane,]
key: [ Alt: '[',]
- action: [FocusNextPane,]
@ -107,7 +107,7 @@ keybinds:
- action: [SwitchToMode: Locked,]
key: [Ctrl: 'g']
- action: [SwitchToMode: Pane,]
key: [Ctrl: 'p', ]
key: [Ctrl: 'p',]
- action: [SwitchToMode: Normal,]
key: [Ctrl: 'r', Ctrl: 't', Char: "\n", Char: ' ',]
- action: [SwitchToMode: Scroll,]
@ -123,51 +123,51 @@ keybinds:
- action: [GoToPreviousTab,]
key: [ Char: 'h',]
- action: [GoToNextTab,]
key: [ Char: 'l', ]
key: [ Char: 'l',]
- action: [GoToNextTab,]
key: [ Char: 'j', ]
key: [ Char: 'j',]
- action: [GoToPreviousTab,]
key: [ Char: 'k', ]
key: [ Char: 'k',]
- action: [NewTab,]
key: [ Char: 'n', ]
key: [ Char: 'n',]
- action: [CloseTab,]
key: [ Char: 'x', ]
key: [ Char: 'x',]
- action: [MoveFocus: Left,]
key: [ Alt: 'h',]
- action: [MoveFocus: Right,]
key: [ Alt: 'l', ]
key: [ Alt: 'l',]
- action: [MoveFocus: Down,]
key: [ Alt: 'j', ]
key: [ Alt: 'j',]
- action: [MoveFocus: Up,]
key: [ Alt: 'k', ]
key: [ Alt: 'k',]
- action: [GoToTab: 1,]
key: [ Char: '1', ]
key: [ Char: '1',]
- action: [GoToTab: 2,]
key: [ Char: '2', ]
key: [ Char: '2',]
- action: [GoToTab: 3,]
key: [ Char: '3', ]
key: [ Char: '3',]
- action: [GoToTab: 4,]
key: [ Char: '4', ]
key: [ Char: '4',]
- action: [GoToTab: 5,]
key: [ Char: '5', ]
key: [ Char: '5',]
- action: [GoToTab: 6,]
key: [ Char: '6', ]
key: [ Char: '6',]
- action: [GoToTab: 7,]
key: [ Char: '7', ]
key: [ Char: '7',]
- action: [GoToTab: 8,]
key: [ Char: '8', ]
key: [ Char: '8',]
- action: [GoToTab: 9,]
key: [ Char: '9', ]
key: [ Char: '9',]
scroll:
- action: [SwitchToMode: Normal,]
key: [Ctrl: 'r', Ctrl: 's', Char: ' ',
Char: "\n",]
- action: [SwitchToMode: Tab,]
key: [Ctrl: 't', ]
key: [Ctrl: 't',]
- action: [SwitchToMode: Locked,]
key: [Ctrl: 'g', ]
key: [Ctrl: 'g',]
- action: [SwitchToMode: Pane,]
key: [Ctrl: 'p', ]
key: [Ctrl: 'p',]
- action: [Quit,]
key: [Ctrl: 'q',]
- action: [ScrollDown,]
@ -194,7 +194,7 @@ keybinds:
key: [ Alt: ']',]
renametab:
- action: [SwitchToMode: Normal,]
key: [Ctrl: 'r', Ctrl: 's', Char: ' ', Char: 'g',]
key: [Ctrl: 'r', Ctrl: 's', Char: ' ',]
- action: [SwitchToMode: Tab,]
key: [Char: "\n",]
- action: [TabNameInput: [27] , SwitchToMode: Tab,]

View file

@ -0,0 +1,353 @@
---
#This file functions as an overview of using screen binds in place of the lock mode.
#It currently functions fine in Zellij, but doesn't give the user the opportunity to use lock mode.
keybinds:
unbind: true
normal:
- action: [SwitchToMode: Locked,]
key: [Ctrl: 'a',]
- action: [SwitchToMode: Pane,]
key: [Ctrl: 'p',]
- action: [SwitchToMode: Resize,]
key: [Ctrl: 'r',]
- action: [SwitchToMode: Tab,]
key: [Ctrl: 't',]
- action: [SwitchToMode: Scroll,]
key: [Ctrl: 's',]
- action: [Quit,]
key: [Ctrl: 'q',]
- action: [NewPane: ]
key: [ Alt: 'n',]
- action: [MoveFocus: Left,]
key: [ Alt: 'h',]
- action: [MoveFocus: Right,]
key: [ Alt: 'l',]
- action: [MoveFocus: Down,]
key: [ Alt: 'j',]
- action: [MoveFocus: Up,]
key: [ Alt: 'k',]
- action: [FocusPreviousPane,]
key: [ Alt: '[',]
- action: [FocusNextPane,]
key: [ Alt: ']',]
locked:
- action: [SwitchToMode: Normal,]
key: [Ctrl: 'a',]
########################################### List of Screen Commands as implemented in screen.yaml for Zellij ###########################################################
################################################# Commands were gathered from GNU Screen version 4.08.00 ###############################################################
############################ Adapted from the GNU Screen Users Manual here: https://www.gnu.org/software/screen/manual/screen.html#####################################
#- action: [DisplayPaneInformation, SwitchToMode: PaneWindowIndex,]
# key: [ Char: ''',]
#- action: [SwitchToMode: PaneWindowIndex, ]
# key: [ Char: '"',]
- action: [GoToTab: 0, SwitchToMode: Normal,]
key: [ Char: '0',]
- action: [GoToTab: 1, SwitchToMode: Normal,]
key: [ Char: '1',]
- action: [GoToTab: 2, SwitchToMode: Normal,]
key: [ Char: '2',]
- action: [GoToTab: 3, SwitchToMode: Normal,]
key: [ Char: '3',]
- action: [GoToTab: 4, SwitchToMode: Normal,]
key: [ Char: '4',]
- action: [GoToTab: 5, SwitchToMode: Normal,]
key: [ Char: '5',]
- action: [GoToTab: 6, SwitchToMode: Normal,]
key: [ Char: '6',]
- action: [GoToTab: 7, SwitchToMode: Normal,]
key: [ Char: '7',]
- action: [GoToTab: 8, SwitchToMode: Normal,]
key: [ Char: '8',]
- action: [GoToTab: 9, SwitchToMode: Normal,]
key: [ Char: '9',]
#- action: [GoToTab: blank,] #Goes to blank empty window.
# key: [ Char: '-',]
#- action: [FocusNextPane, SwitchToMode: Normal,] #Implemented, however doesn't support current key in this YAML.
# key: [ Tab,]
- action: [GoToPreviousTab, SwitchToMode: Normal,]
key: [ Ctrl: 'a',]
#- action: [SendPrefixKey, SwitchToMode: Normal,]
# key: [Ctrl: 'a',]
- action: [SwitchToMode: RenameTab, TabNameInput: [0],]
key: [Char: 'A']
#- action: [SendBreak, SwitchToMode: Normal,]
# key: [Char: 'b', Ctrl: 'b',]
#- action: [Resetpane, SwitchToMode: Normal,]
# key: [Ctrl: 'B',]
- action: [NewTab, SwitchToMode: Normal,]
key: [ Char: 'c', Ctrl: 'c',]
#- action: [clearpane, SwitchToMode: Normal,]
# key: [Char: 'C',]
#- action: [DetachCurrentPane,]
# key: [ Char: 'd', Ctrl: 'd',]
#- action: [DetachClient, Quit,]
# key: [ Char: 'D'; Char:'D',] #This requires sequential characters note the ;
#- action: [ChangeCycleFlow, SwitchToMode: Normal,] #I have literally no idea what this does.
# key: [ Char: 'f', Ctrl: 'f',]
#- action: [ResizeTerminalToPane, SwitchToMode: Normal,] #Outdated but noted here.
# key: [Char: 'F',]
#- action: [ToggleVisualBell,]
# key: [Ctrl: 'g',]
#- action: [CopyPaneToFile, SwitchToMode: Normal,]
# key: [Ctrl: 'h',]
#- action: [TogglePanelogging,]
# key: [Ctrl: 'H',]
#- action: [ShowTabInfo, SwitchToMode: Normal,]
# key: [Char: 'i', Ctrl: 'i',]
- action: [CloseTab, SwitchToMode: Normal,]
key: [ Char: 'k', Ctrl: 'k',]
#- action: [OrderClientRedraw, SwitchToMode: Normal,]
# key: [Char: 'l', Ctrl: 'l',]
#- action: [ToggleTabLoginState, SwitchToMode: Normal,]
# key: [Char: 'L',]
#- action: [RepeatStatusMessage, SwitchToMode: Normal,]
# key: [Char: 'm', Ctrl: 'm',]
#- action: [TogglePaneMonitoring,]
# key: [Ctrl: 'M',]
#- action: [GoToNextTab, SwitchToMode: Normal,] #Implemented, however doesn't support current key in this YAML.
# key: [Space ,Char: 'n', Ctrl: 'n',]
#- action: [ShowPaneNumbers, SwitchToMode: Normal,]
# key: [ Char: 'N',]
#- action: [GoToNextTab, SwitchToMode: Normal,] #Implemented, however doesn't support current key in this YAML.
# key: [Backspace ,Char: 'p', Ctrl: 'p', Ctrl: 'h',]
#- action: [SendXONToTab, SwitchToMode: Normal,]
# key: [Char: 'q', Ctrl: 'q',]
#- action: [ClosePanesExceptFocus, SwitchToMode: Normal,]
# key: [Char: 'Q',]
#- action: [ToggleLineWrap, SwitchToMode: Normal,]
# key: [Char: 'r', Ctrl: 'r',]
#- action: [SendXOFFToTab, SwitchToMode: Normal,]
# key: [Char: 's', Ctrl: 's',]
- action: [NewPane: Right, SwitchToMode: Normal,]
key: [Char: 'S',]
#- action: [ShowLoadAverages, ShowXref, SwitchToMode: Normal,]
# key: [Char: 't', Ctrl: 't',]
#- action: [DisplayVersionAndCompileDate, SwitchToMode: Normal,]
# key: [Char: 'v',]
#- action: [InputDigraph, SwitchToMode: Normal,]
# key: [Ctrl: 'v',]
#- action: [SelectTabFromIndex, SwitchToMode: Normal,]
# key: [Char: 'w', Ctrl: 'w',]
#- action: [Toggle80And132Columns, SwitchToMode: Normal,]
# key: [Char: 'W',]
#- action: [LockTerminal, SwitchToMode: Normal,]
# key: [Char: 'x', Ctrl: 'x',]
- action: [CloseFocus, SwitchToMode: Normal,]
key: [Char: 'X',]
#- action: [LockTerminal, SwitchToMode: Normal,]
# key: [Char: 'x', Ctrl: 'x',]
#- action: [SuspendZellij, SwitchToMode: Normal,]
# key: [Char: 'z', Ctrl: 'z',]
#- action: [SendReset, SwitchToMode: Normal,]
# key: [Char: 'Z',]
#- action: [DumpTermcap, SwitchToMode: Normal,]
# key: [Char: '.',]
#- action: [ShowKeybinds, SwitchToMode: Normal,]
# key: [Char: '?',]
- action: [Quit,]
key: [Char: '\',]
#- action: [EnterZellijCommandPrompt, SwitchToMode: Normal,]
# key: [ Char: ':',]
#- action: [SwitchToMode: Copy,]
# key: [Escape, Char: '[', Ctrl: '[',]
#- action: [PasteBufferToPane, SwitchToMode: Normal,]
# key: [Char: ']', Ctrl: ']',]
#- action: [CopyCommandFromPasteBuffer, SwitchToMode: Normal,]
# key: [Char: '{', Ctrl: '}',]
#- action: [WritePasteBufferToFile, SwitchToMode: Normal,]
# key: [Char: '>',]
#- action: [ReadPasteBufferToFile, SwitchToMode: Normal,]
# key: [Char: '<',]
#- action: [DeletePasteBufferFile, SwitchToMode: Normal,]
# key: [Char: '=',]
#- action: [TogglePaneMonitoring,]
# key: [Char: '_',]
- action: [NewPane: Down, SwitchToMode: Normal,]
key: [Char: '|',]
#- action: [ShowZellijSoftwareLicense,]
# key: [Char: ',',]
#- action: [ShowAttachedUsers,]
# key: [Char: '*',]
###################################################### End Imported Commands from Screen ###############################################################################
resize:
- action: [SwitchToMode: Locked,]
key: [Ctrl: 'g']
- action: [SwitchToMode: Pane,]
key: [Ctrl: 'p',]
- action: [SwitchToMode: Tab,]
key: [Ctrl: 't',]
- action: [SwitchToMode: Normal,]
key: [Ctrl: 'r', Char: "\n", Char: ' ',]
- action: [SwitchToMode: Scroll,]
key: [Ctrl: 's']
- action: [Quit]
key: [Ctrl: 'q']
- action: [Resize: Left,]
key: [Char: 'h', Left,]
- action: [Resize: Down,]
key: [Char: 'j', Down,]
- action: [Resize: Up,]
key: [Char: 'k', Up, ]
- action: [Resize: Right,]
key: [Char: 'l', Right,]
- action: [NewPane: ,]
key: [ Alt: 'n',]
- action: [MoveFocus: Left,]
key: [ Alt: 'h', Left,]
- action: [MoveFocus: Right,]
key: [ Alt: 'l', Right,]
- action: [MoveFocus: Down,]
key: [ Alt: 'j', Down,]
- action: [MoveFocus: Up,]
key: [ Alt: 'k', Up,]
- action: [FocusPreviousPane,]
key: [ Alt: '[',]
- action: [FocusNextPane,]
key: [ Alt: ']',]
pane:
- action: [SwitchToMode: Locked,]
key: [Ctrl: 'g']
- action: [SwitchToMode: Pane,]
key: [Ctrl: 'p',]
- action: [SwitchToMode: Tab,]
key: [Ctrl: 't',]
- action: [SwitchToMode: Normal,]
key: [Ctrl: 'r', Char: "\n", Char: ' ',]
- action: [SwitchToMode: Scroll,]
key: [Ctrl: 's']
- action: [Quit,]
key: [Ctrl: 'q',]
- action: [MoveFocus: Left,]
key: [ Alt: 'h', Left,]
- action: [MoveFocus: Right,]
key: [ Alt: 'l', Right,]
- action: [MoveFocus: Down,]
key: [ Alt: 'j', Down,]
- action: [MoveFocus: Up,]
key: [ Alt: 'k', Up,]
- action: [SwitchFocus,]
key: [Char: 'p']
- action: [NewPane: ,]
key: [Char: 'n', Alt: 'n',]
- action: [NewPane: Down,]
key: [Char: 'd',]
- action: [NewPane: Right,]
key: [Char: 'r',]
- action: [CloseFocus,]
key: [Char: 'x',]
- action: [ToggleFocusFullscreen,]
key: [Char: 'f',]
- action: [FocusPreviousPane,]
key: [ Alt: '[',]
- action: [FocusNextPane,]
key: [ Alt: ']',]
tab:
- action: [SwitchToMode: Locked,]
key: [Ctrl: 'g']
- action: [SwitchToMode: Pane,]
key: [Ctrl: 'p',]
- action: [SwitchToMode: Normal,]
key: [Ctrl: 'r', Ctrl: 't', Char: "\n", Char: ' ',]
- action: [SwitchToMode: Scroll,]
key: [Ctrl: 's']
- action: [SwitchToMode: RenameTab, TabNameInput: [0],]
key: [Char: 'r']
- action: [Quit,]
key: [Ctrl: 'q',]
- action: [FocusPreviousPane,]
key: [ Alt: '[',]
- action: [FocusNextPane,]
key: [ Alt: ']',]
- action: [GoToPreviousTab,]
key: [ Char: 'h',]
- action: [GoToNextTab,]
key: [ Char: 'l',]
- action: [GoToNextTab,]
key: [ Char: 'j',]
- action: [GoToPreviousTab,]
key: [ Char: 'k',]
- action: [NewTab,]
key: [ Char: 'n',]
- action: [CloseTab,]
key: [ Char: 'x',]
- action: [MoveFocus: Left,]
key: [ Alt: 'h',]
- action: [MoveFocus: Right,]
key: [ Alt: 'l',]
- action: [MoveFocus: Down,]
key: [ Alt: 'j',]
- action: [MoveFocus: Up,]
key: [ Alt: 'k',]
- action: [GoToTab: 1,]
key: [ Char: '1',]
- action: [GoToTab: 2,]
key: [ Char: '2',]
- action: [GoToTab: 3,]
key: [ Char: '3',]
- action: [GoToTab: 4,]
key: [ Char: '4',]
- action: [GoToTab: 5,]
key: [ Char: '5',]
- action: [GoToTab: 6,]
key: [ Char: '6',]
- action: [GoToTab: 7,]
key: [ Char: '7',]
- action: [GoToTab: 8,]
key: [ Char: '8',]
- action: [GoToTab: 9,]
key: [ Char: '9',]
scroll:
- action: [SwitchToMode: Normal,]
key: [Ctrl: 'r', Ctrl: 's', Char: ' ',
Char: "\n",]
- action: [SwitchToMode: Tab,]
key: [Ctrl: 't',]
- action: [SwitchToMode: Locked,]
key: [Ctrl: 'g',]
- action: [SwitchToMode: Pane,]
key: [Ctrl: 'p',]
- action: [Quit,]
key: [Ctrl: 'q',]
- action: [ScrollDown,]
key: [Char: 'j', Down,]
- action: [ScrollUp,]
key: [Char: 'k', Up,]
- action: [PageScrollDown,]
key: [Ctrl: 'f', PageDown,]
- action: [PageScrollUp,]
key: [Ctrl: 'b', PageUp,]
- action: [NewPane: ,]
key: [ Alt: 'n',]
- action: [MoveFocus: Left,]
key: [ Alt: 'h',]
- action: [MoveFocus: Right,]
key: [ Alt: 'l',]
- action: [MoveFocus: Down,]
key: [ Alt: 'j',]
- action: [MoveFocus: Up,]
key: [ Alt: 'k',]
- action: [FocusPreviousPane,]
key: [ Alt: '[',]
- action: [FocusNextPane,]
key: [ Alt: ']',]
renametab:
- action: [SwitchToMode: Normal,]
key: [Ctrl: 'r', Ctrl: 's', Char: ' ',]
- action: [SwitchToMode: Tab,]
key: [Char: "\n",]
- action: [TabNameInput: [27] , SwitchToMode: Tab,]
key: [Esc,]
- action: [NewPane: ,]
key: [ Alt: 'n',]
- action: [MoveFocus: Left,]
key: [ Alt: 'h',]
- action: [MoveFocus: Right,]
key: [ Alt: 'l',]
- action: [MoveFocus: Down,]
key: [ Alt: 'j',]
- action: [MoveFocus: Up,]
key: [ Alt: 'k',]
- action: [FocusPreviousPane,]
key: [ Alt: '[',]
- action: [FocusNextPane,]
key: [ Alt: ']',]

View file

@ -0,0 +1,170 @@
---
#This config will not currently function and will error out until Issue #248 is implemented, or another solution is.
keybinds:
unbind: true
normal:
- action: [SwitchToMode: Locked,]
key: [Ctrl: 'g',]
- action: [SwitchToMode: Pane,]
key: [Ctrl: 'p',]
- action: [SwitchToMode: Resize,]
key: [Ctrl: 'r',]
- action: [SwitchToMode: Tab,]
key: [Ctrl: 't',]
- action: [SwitchToMode: Scroll,]
key: [Ctrl: 's',]
- action: [SwitchToMode: screen,] # This mode doesn't exist and will error out until Issue #248 is addressed, this is the crux of the issue.
key: [Ctrl: 'b',]
- action: [Quit,]
key: [Ctrl: 'q',]
- action: [NewPane: ]
key: [ Alt: 'n',]
- action: [MoveFocus: Left,]
key: [ Alt: 'h',]
- action: [MoveFocus: Right,]
key: [ Alt: 'l',]
- action: [MoveFocus: Down,]
key: [ Alt: 'j',]
- action: [MoveFocus: Up,]
key: [ Alt: 'k',]
- action: [FocusPreviousPane,]
key: [ Alt: '[',]
- action: [FocusNextPane,]
key: [ Alt: ']',]
screen:
########################################### List of Screen Commands as implemented in screen.yaml for Zellij ###########################################################
################################################# Commands were gathered from GNU Screen version 4.08.00 ###############################################################
############################ Adapted from the GNU Screen Users Manual here: https://www.gnu.org/software/screen/manual/screen.html#####################################
#- action: [DisplayPaneInformation, SwitchToMode: PaneWindowIndex,]
# key: [ Char: ''',]
#- action: [SwitchToMode: PaneWindowIndex, ]
# key: [ Char: '"',]
- action: [GoToTab: 0, SwitchToMode: Normal,]
key: [ Char: '0',]
- action: [GoToTab: 1, SwitchToMode: Normal,]
key: [ Char: '1',]
- action: [GoToTab: 2, SwitchToMode: Normal,]
key: [ Char: '2',]
- action: [GoToTab: 3, SwitchToMode: Normal,]
key: [ Char: '3',]
- action: [GoToTab: 4, SwitchToMode: Normal,]
key: [ Char: '4',]
- action: [GoToTab: 5, SwitchToMode: Normal,]
key: [ Char: '5',]
- action: [GoToTab: 6, SwitchToMode: Normal,]
key: [ Char: '6',]
- action: [GoToTab: 7, SwitchToMode: Normal,]
key: [ Char: '7',]
- action: [GoToTab: 8, SwitchToMode: Normal,]
key: [ Char: '8',]
- action: [GoToTab: 9, SwitchToMode: Normal,]
key: [ Char: '9',]
#- action: [GoToTab: blank,] #Goes to blank empty window.
# key: [ Char: '-',]
- action: [NewPane: , SwitchToMode: Normal,]
key: [Ctrl: 'c',]
#- action: [FocusNextPane, SwitchToMode: Normal,] #Implemented, however doesn't support current key in this YAML.
# key: [ Tab,]
- action: [GoToPreviousTab, SwitchToMode: Normal,]
key: [ Ctrl: 'a',]
#- action: [SendPrefixKey, SwitchToMode: Normal,]
# key: [Ctrl: 'a',]
- action: [SwitchToMode: RenameTab, TabNameInput: [0],]
key: [Char: 'A']
#- action: [SendBreak, SwitchToMode: Normal,]
# key: [Char: 'b', Ctrl: 'b',]
#- action: [Resetpane, SwitchToMode: Normal,]
# key: [Ctrl: 'B',]
#- action: [clearpane, SwitchToMode: Normal,]
# key: [Char: 'C',]
#- action: [DetachCurrentPane,]
# key: [ Char: 'd', Ctrl: 'd',]
#- action: [DetachClient, Quit,]
# key: [ Char: 'D'; Char:'D',] #This requires sequential characters note the ;
#- action: [ChangeCycleFlow, SwitchToMode: Normal,] #I have literally no idea what this does.
# key: [ Char: 'f', Ctrl: 'f',]
#- action: [ResizeTerminalToPane, SwitchToMode: Normal,] #Outdated but noted here.
# key: [Char: 'F',]
#- action: [ToggleVisualBell,]
# key: [Ctrl: 'g',]
#- action: [CopyPaneToFile, SwitchToMode: Normal,]
# key: [Ctrl: 'h',]
#- action: [TogglePanelogging,]
# key: [Ctrl: 'H',]
#- action: [ShowTabInfo, SwitchToMode: Normal,]
# key: [Char: 'i', Ctrl: 'i',]
- action: [CloseTab, SwitchToMode: Normal,]
key: [ Char: 'k', Ctrl: 'k',]
#- action: [OrderClientRedraw, SwitchToMode: Normal,]
# key: [Char: 'l', Ctrl: 'l',]
#- action: [ToggleTabLoginState, SwitchToMode: Normal,]
# key: [Char: 'L',]
#- action: [RepeatStatusMessage, SwitchToMode: Normal,]
# key: [Char: 'm', Ctrl: 'm',]
#- action: [TogglePaneMonitoring,]
# key: [Ctrl: 'M',]
#- action: [GoToNextTab, SwitchToMode: Normal,] #Implemented, however doesn't support current key in this YAML.
# key: [Space ,Char: 'n', Ctrl: 'n',]
#- action: [ShowPaneNumbers, SwitchToMode: Normal,]
# key: [ Char: 'N',]
#- action: [GoToNextTab, SwitchToMode: Normal,] #Implemented, however doesn't support current key in this YAML.
# key: [Backspace ,Char: 'p', Ctrl: 'p', Ctrl: 'h',]
#- action: [SendXONToTab, SwitchToMode: Normal,]
# key: [Char: 'q', Ctrl: 'q',]
#- action: [ClosePanesExceptFocus, SwitchToMode: Normal,]
# key: [Char: 'Q',]
#- action: [ToggleLineWrap, SwitchToMode: Normal,]
# key: [Char: 'r', Ctrl: 'r',]
#- action: [SendXOFFToTab, SwitchToMode: Normal,]
# key: [Char: 's', Ctrl: 's',]
- action: [NewPane: Right, SwitchToMode: Normal,]
key: [Char: 'S',]
#- action: [ShowLoadAverages, ShowXref, SwitchToMode: Normal,]
# key: [Char: 't', Ctrl: 't',]
#- action: [DisplayVersionAndCompileDate, SwitchToMode: Normal,]
# key: [Char: 'v',]
#- action: [InputDigraph, SwitchToMode: Normal,]
# key: [Ctrl: 'v',]
#- action: [SelectTabFromIndex, SwitchToMode: Normal,]
# key: [Char: 'w', Ctrl: 'w',]
#- action: [Toggle80And132Columns, SwitchToMode: Normal,]
# key: [Char: 'W',]
#- action: [LockTerminal, SwitchToMode: Normal,]
# key: [Char: 'x', Ctrl: 'x',]
- action: [CloseFocus, SwitchToMode: Normal,]
key: [Char: 'X',]
#- action: [LockTerminal, SwitchToMode: Normal,]
# key: [Char: 'x', Ctrl: 'x',]
#- action: [SuspendZellij, SwitchToMode: Normal,]
# key: [Char: 'z', Ctrl: 'z',]
#- action: [SendReset, SwitchToMode: Normal,]
# key: [Char: 'Z',]
#- action: [DumpTermcap, SwitchToMode: Normal,]
# key: [Char: '.',]
#- action: [ShowKeybinds, SwitchToMode: Normal,]
# key: [Char: '?',]
- action: [Quit,]
key: [Char: '\',]
#- action: [EnterZellijCommandPrompt, SwitchToMode: Normal,]
# key: [ Char: ':',]
#- action: [SwitchToMode: Copy,]
# key: [Escape, Char: '[', Ctrl: '[',]
#- action: [PasteBufferToPane, SwitchToMode: Normal,]
# key: [Char: ']', Ctrl: ']',]
#- action: [CopyCommandFromPasteBuffer, SwitchToMode: Normal,]
# key: [Char: '{', Ctrl: '}',]
#- action: [WritePasteBufferToFile, SwitchToMode: Normal,]
# key: [Char: '>',]
#- action: [ReadPasteBufferToFile, SwitchToMode: Normal,]
# key: [Char: '<',]
#- action: [DeletePasteBufferFile, SwitchToMode: Normal,]
# key: [Char: '=',]
#- action: [TogglePaneMonitoring,]
# key: [Char: '_',]
- action: [NewPane: Down, SwitchToMode: Normal,]
key: [Char: '|',]
#- action: [ShowZellijSoftwareLicense,]
# key: [Char: ',',]
#- action: [ShowAttachedUsers,]
# key: [Char: '*',]
###################################################### End Imported Commands from Screen ###############################################################################

386
example/tmux-overview.yaml Normal file
View file

@ -0,0 +1,386 @@
---
#This file functions as an overview of using tmux binds in place of the lock mode, it currently functions fine in Zellij, but doesn't give the user the opportunity to use lock mode.
keybinds:
unbind: true
normal:
- action: [SwitchToMode: Locked,]
key: [Ctrl: 'b',]
- action: [SwitchToMode: Pane,]
key: [Ctrl: 'p',]
- action: [SwitchToMode: Resize,]
key: [Ctrl: 'r',]
- action: [SwitchToMode: Tab,]
key: [Ctrl: 't',]
- action: [SwitchToMode: Scroll,]
key: [Ctrl: 's',]
- action: [Quit,]
key: [Ctrl: 'q',]
- action: [NewPane: ]
key: [ Alt: 'n',]
- action: [MoveFocus: Left,]
key: [ Alt: 'h',]
- action: [MoveFocus: Right,]
key: [ Alt: 'l',]
- action: [MoveFocus: Down,]
key: [ Alt: 'j',]
- action: [MoveFocus: Up,]
key: [ Alt: 'k',]
- action: [FocusPreviousPane,]
key: [ Alt: '[',]
- action: [FocusNextPane,]
key: [ Alt: ']',]
locked: # Functions as the Tmux Mode for now.
- action: [SwitchToMode: Normal,]
key: [Ctrl: 'c',]
tmux:
######### list of tmux actions starts here in same order as exported from tmux 'C-b ?` command. #########
######### All Commented Commands have placeholder names for the features if they ever get implemented. ##
#- action: [SendPrefixKey,]
# key: [Ctrl: 'b',]
- action: [FocusNextPane, SwitchToMode: Normal,]
key: [Ctrl: 'o',]
#- action: [SuspendCurrentZellijClient, SwitchToMode: Normal,]
# key: [Ctrl: 'z',]
#- action: [SelectNextLayout, SwitchToMode: Normal,]
# key: [Char: ' ']
#- action: [BreakoutPaneToTab, SwitchToMode: Normal,]
# key: [Char: '!',]
- action: [NewPane: Down, SwitchToMode: Normal,]
key: [Char: '"',]
#- action: [ListPasteBuffers,]
# key: [Char: '#',]
#- action: [SwitchToMode: RenameTab, SessionNameInput: [0],]
# key: [Char: '$']
- action: [NewPane: Right, SwitchToMode: Normal,]
key: [Char: '%',]
- action: [CloseTab, SwitchToMode: Normal,]
key: [Char: '&',]
#- action: [PaneSelectionMenu, SwitchToMode: Normal,]
# key: [Char: ''',]
#- action: [SwitchToNextClient, SwitchToMode: Normal,]
# key: [Char: '(',]
#- action: [SwitchToPreviousClient, SwitchToMode: Normal,]
# key: [Char: ')',]
#- action: [Rename, SwitchToMode: Normal,]
# key: [Char: ',',]
- action: [SwitchToMode: RenameTab, TabNameInput: [0],]
key: [Char: ',']
#- action: [DeleteRecentPasteBuffer, SwitchToMode: Normal,]
# key: [Char: '-',]
#- action: [MoveTabIndexPosition, SwitchToMode: Normal,]
# key: [Char: '.',]
#- action: [DisplayKeybindAction, SwitchToMode: Normal,]
# key: [Char: '/',]
- action: [GoToTab: 1, SwitchToMode: Normal,]
key: [ Char: '1',]
- action: [GoToTab: 2, SwitchToMode: Normal,]
key: [ Char: '2',]
- action: [GoToTab: 3, SwitchToMode: Normal,]
key: [ Char: '3',]
- action: [GoToTab: 4, SwitchToMode: Normal,]
key: [ Char: '4',]
- action: [GoToTab: 5, SwitchToMode: Normal,]
key: [ Char: '5',]
- action: [GoToTab: 6, SwitchToMode: Normal,]
key: [ Char: '6',]
- action: [GoToTab: 7, SwitchToMode: Normal,]
key: [ Char: '7',]
- action: [GoToTab: 8, SwitchToMode: Normal,]
key: [ Char: '8',]
- action: [GoToTab: 9, SwitchToMode: Normal,]
key: [ Char: '9',]
- action: [GoToTab: 9, SwitchToMode: Normal,]
key: [ Char: '9',]
#- action: [EnterZellijCommandPrompt, SwitchToMode: Normal,]
# key: [ Char: ':',]
#- action: [GoToLastActivePane, SwitchToMode: Normal,]
# key: [ Char: ';',]
#- action: [ChoosePasteBufferItem, SwitchToMode: Normal,]
# key: [ Char: '=',]
#- action: [ListAllKeyBinds,]
# key: [ Char: '?',]
#- action: [SelectClientFromIndex,]
# key: [ Char: 'D',]
#- action: [EqualizePaneSizes,]
# key: [ Char: 'E',]
#- action: [GoToLastActiveClient, SwitchToMode: Normal,]
# key: [ Char: 'L',]
#- action: [ClearCurrentPaneText, SwitchToMode: Normal,]
# key: [ Char: 'M',]
#- action: [SwitchToMode: Copy,]
# key: [ Char: '[',]
#- action: [PasteMostRecentPasteBufferItem, SwitchToMode: Normal,]
# key: [ Char: ']',]
- action: [NewTab, SwitchToMode: Normal,]
key: [ Char: 'c',]
#- action: [DetachClient, Quit,]
# key: [ Char: 'd',]
#- action: [SwitchToMode: PaneWindowIndex,]
# key: [ Char: 'f',]
#- action: [DisplayPaneInformation, SwitchToMode: Normal,]
# key: [ Char: 'i',]
- action: [GoToPreviousTab, SwitchToMode: Normal,]
key: [ Char: 'l',]
#- action: [TogglePane, SwitchToMode: Normal,]
# key: [ Char: 'm',]
- action: [GoToNextTab, SwitchToMode: Normal,]
key: [ Char: 'n',]
- action: [FocusNextPane, SwitchToMode: Normal,]
key: [ Char: 'o',]
- action: [FocusPreviousPane, SwitchToMode: Normal,]
key: [ Char: 'p',]
#- action: [ShowPaneNumbers, SwitchToMode: Normal,]
# key: [ Char: 'q',]
#- action: [OrderClientRedraw, SwitchToMode: Normal,]
# key: [ Char: 'r',]
#- action: [SelectSessionFromIndex, SwitchToMode: Normal,]
# key: [ Char: 's',]
#- action: [ShowClockOnScreen, SwitchToMode: Normal,]
# key: [ Char: 't',]
#- action: [SelectTabFromIndex, SwitchToMode: Normal,]
# key: [ Char: 'w',]
- action: [CloseFocus, SwitchToMode: Normal,]
key: [Char: 'x',]
#- action: [ZoomToPane, SwitchToMode: Normal,]
# key: [ Char: 'z',]
#- action: [SwapPane: Up, SwitchToMode: Normal,]
# key: [ Char: '{',]
#- action: [SwapPane: Down, SwitchToMode: Normal,]
# key: [ Char: '}',]
#- action: [ShowZellijMessages, SwitchToMode: Normal,]
# key: [ Char: '~',]
#- action: [ResetToVisibleCursor, SwitchToMode: Normal,]
# key: [ 'Delete',]
#- action: [SwitchToMode: Copy, PageScrollUpToTop,]
# key: [ 'PageUp',]
- action: [MoveFocus: Left, SwitchToMode: Normal,]
key: [ 'Left',]
- action: [MoveFocus: Right, SwitchToMode: Normal,]
key: [ 'Right',]
- action: [MoveFocus: Down, SwitchToMode: Normal,]
key: [ 'Down',]
- action: [MoveFocus: Up, SwitchToMode: Normal,]
key: [ 'Up',]
#- action: [EvenOutRankPanes: Horizontally, SwitchToMode: Normal,]
# key: [ Alt: '1',]
#- action: [EvenOutRankPanes: Vertically, SwitchToMode: Normal,]
# key: [ Alt: '2',]
#- action: [SetPaneAsMain: Horizontally, SwitchToMode: Normal,]
# key: [ Alt: '3',]
#- action: [SetPaneAsMain: Vertically, SwitchToMode: Normal,]
# key: [ Alt: '4',]
#- action: [SelectTiledLayout, SwitchToMode: Normal,]
# key: [ Alt: '5',]
#- action: [SelectNextTabWithAlert, SwitchToMode: Normal,]
# key: [ Alt: 'n',]
- action: [FocusPreviousPane, SwitchToMode: Normal,]
key: [ Alt: 'o',]
#- action: [SelectNextTabWithAlert, SwitchToMode: Normal,]
# key: [ Alt: 'p',]
#- action: [ResizeIncremental: Up, SwitchToMode: Normal,]
# key: [Alt: 'Up',]
#- action: [ResizeIncremental: Down, SwitchToMode: Normal,]
# key: [Alt: 'Down',
#- action: [ResizeIncremental: Left, SwitchToMode: Normal,]
# key: [Alt: 'Left',]
#- action: [ResizeIncremental: Right, SwitchToMode: Normal,]
# key: [Alt: 'Right',]
#- action: [Resize: Up,]
# key: [Ctrl: 'Up',]
#- action: [Resize: Down,]
# key: [Ctrl: 'Down',]
#- action: [Resize: Left,]
# key: [Ctrl: 'Left',]
#- action: [Resize: Right,]
# key: [Ctrl: 'Right',]
#- action: [ShiftPartiallyVisibleTab: Up, SwitchToMode: Normal,]
# key: [Shift: 'Up',]
#- action: [ShiftPartiallyVisibleTab: Down, SwitchToMode: Normal,]
# key: [Shift: 'Down',]
#- action: [ShiftPartiallyVisibleTab: Left, SwitchToMode: Normal,]
# key: [Shift: 'Left',]
#- action: [ShiftPartiallyVisibleTab: Right, SwitchToMode: Normal,]
# key: [Shift: 'Right',]
########################################### End Tmux Commands Imported ##################################
resize:
- action: [SwitchToMode: Locked,]
key: [Ctrl: 'g']
- action: [SwitchToMode: Pane,]
key: [Ctrl: 'p',]
- action: [SwitchToMode: Tab,]
key: [Ctrl: 't',]
- action: [SwitchToMode: Normal,]
key: [Ctrl: 'r', Char: "\n", Char: ' ',]
- action: [SwitchToMode: Scroll,]
key: [Ctrl: 's']
- action: [Quit]
key: [Ctrl: 'q']
- action: [Resize: Left,]
key: [Char: 'h', Left, ]
- action: [Resize: Down,]
key: [Char: 'j', Down, ]
- action: [Resize: Up,]
key: [Char: 'k', Up, ]
- action: [Resize: Right,]
key: [Char: 'l', Right, ]
- action: [NewPane: ,]
key: [ Alt: 'n',]
- action: [MoveFocus: Left,]
key: [ Alt: 'h', Left,]
- action: [MoveFocus: Right,]
key: [ Alt: 'l', Right,]
- action: [MoveFocus: Down,]
key: [ Alt: 'j', Down,]
- action: [MoveFocus: Up,]
key: [ Alt: 'k', Up,]
- action: [FocusPreviousPane,]
key: [ Alt: '[',]
- action: [FocusNextPane,]
key: [ Alt: ']',]
pane:
- action: [SwitchToMode: Locked,]
key: [Ctrl: 'g']
- action: [SwitchToMode: Pane,]
key: [Ctrl: 'p',]
- action: [SwitchToMode: Tab,]
key: [Ctrl: 't',]
- action: [SwitchToMode: Normal,]
key: [Ctrl: 'r', Char: "\n", Char: ' ',]
- action: [SwitchToMode: Scroll,]
key: [Ctrl: 's']
- action: [Quit,]
key: [Ctrl: 'q',]
- action: [MoveFocus: Left,]
key: [ Alt: 'h', Left,]
- action: [MoveFocus: Right,]
key: [ Alt: 'l', Right,]
- action: [MoveFocus: Down,]
key: [ Alt: 'j', Down,]
- action: [MoveFocus: Up,]
key: [ Alt: 'k', Up,]
- action: [SwitchFocus,]
key: [Char: 'p']
- action: [NewPane: ,]
key: [Char: 'n', Alt: 'n',]
- action: [NewPane: Down,]
key: [Char: 'd',]
- action: [NewPane: Right,]
key: [Char: 'r',]
- action: [CloseFocus,]
key: [Char: 'x',]
- action: [ToggleFocusFullscreen,]
key: [Char: 'f',]
- action: [FocusPreviousPane,]
key: [ Alt: '[',]
- action: [FocusNextPane,]
key: [ Alt: ']',]
tab:
- action: [SwitchToMode: Locked,]
key: [Ctrl: 'g']
- action: [SwitchToMode: Pane,]
key: [Ctrl: 'p',]
- action: [SwitchToMode: Normal,]
key: [Ctrl: 'r', Ctrl: 't', Char: "\n", Char: ' ',]
- action: [SwitchToMode: Scroll,]
key: [Ctrl: 's']
- action: [SwitchToMode: RenameTab, TabNameInput: [0],]
key: [Char: 'r']
- action: [Quit,]
key: [Ctrl: 'q',]
- action: [FocusPreviousPane,]
key: [ Alt: '[',]
- action: [FocusNextPane,]
key: [ Alt: ']',]
- action: [GoToPreviousTab,]
key: [ Char: 'h',]
- action: [GoToNextTab,]
key: [ Char: 'l',]
- action: [GoToNextTab,]
key: [ Char: 'j',]
- action: [GoToPreviousTab,]
key: [ Char: 'k',]
- action: [NewTab,]
key: [ Char: 'n',]
- action: [CloseTab,]
key: [ Char: 'x',]
- action: [MoveFocus: Left,]
key: [ Alt: 'h',]
- action: [MoveFocus: Right,]
key: [ Alt: 'l',]
- action: [MoveFocus: Down,]
key: [ Alt: 'j',]
- action: [MoveFocus: Up,]
key: [ Alt: 'k',]
- action: [GoToTab: 1,]
key: [ Char: '1',]
- action: [GoToTab: 2,]
key: [ Char: '2',]
- action: [GoToTab: 3,]
key: [ Char: '3',]
- action: [GoToTab: 4,]
key: [ Char: '4',]
- action: [GoToTab: 5,]
key: [ Char: '5',]
- action: [GoToTab: 6,]
key: [ Char: '6',]
- action: [GoToTab: 7,]
key: [ Char: '7',]
- action: [GoToTab: 8,]
key: [ Char: '8',]
- action: [GoToTab: 9,]
key: [ Char: '9',]
scroll:
- action: [SwitchToMode: Normal,]
key: [Ctrl: 'r', Ctrl: 's', Char: ' ',
Char: "\n",]
- action: [SwitchToMode: Tab,]
key: [Ctrl: 't',]
- action: [SwitchToMode: Locked,]
key: [Ctrl: 'g',]
- action: [SwitchToMode: Pane,]
key: [Ctrl: 'p',]
- action: [Quit,]
key: [Ctrl: 'q',]
- action: [ScrollDown,]
key: [Char: 'j', Down,]
- action: [ScrollUp,]
key: [Char: 'k', Up,]
- action: [PageScrollDown,]
key: [Ctrl: 'f', PageDown,]
- action: [PageScrollUp,]
key: [Ctrl: 'b', PageUp,]
- action: [NewPane: ,]
key: [ Alt: 'n',]
- action: [MoveFocus: Left,]
key: [ Alt: 'h',]
- action: [MoveFocus: Right,]
key: [ Alt: 'l',]
- action: [MoveFocus: Down,]
key: [ Alt: 'j',]
- action: [MoveFocus: Up,]
key: [ Alt: 'k',]
- action: [FocusPreviousPane,]
key: [ Alt: '[',]
- action: [FocusNextPane,]
key: [ Alt: ']',]
renametab:
- action: [SwitchToMode: Normal,]
key: [Ctrl: 'r', Ctrl: 's', Char: ' ',]
- action: [SwitchToMode: Tab,]
key: [Char: "\n",]
- action: [TabNameInput: [27] , SwitchToMode: Tab,]
key: [Esc,]
- action: [NewPane: ,]
key: [ Alt: 'n',]
- action: [MoveFocus: Left,]
key: [ Alt: 'h',]
- action: [MoveFocus: Right,]
key: [ Alt: 'l',]
- action: [MoveFocus: Down,]
key: [ Alt: 'j',]
- action: [MoveFocus: Up,]
key: [ Alt: 'k',]
- action: [FocusPreviousPane,]
key: [ Alt: '[',]
- action: [FocusNextPane,]
key: [ Alt: ']',]

203
example/tmux.nonfunctional Normal file
View file

@ -0,0 +1,203 @@
---
#This config will not currently function and will error out until Issue #248 is implemented, or another solution is.
keybinds:
unbind: true
normal:
- action: [SwitchToMode: Locked,]
key: [Ctrl: 'g',]
- action: [SwitchToMode: Pane,]
key: [Ctrl: 'p',]
- action: [SwitchToMode: Resize,]
key: [Ctrl: 'r',]
- action: [SwitchToMode: Tab,]
key: [Ctrl: 't',]
- action: [SwitchToMode: Scroll,]
key: [Ctrl: 's',]
- action: [SwitchToMode: tmux,] # This mode doesn't exist and will error out until Issue #248 is addressed, this is the crux of the issue.
key: [Ctrl: 'b',]
- action: [Quit,]
key: [Ctrl: 'q',]
- action: [NewPane: ]
key: [ Alt: 'n',]
- action: [MoveFocus: Left,]
key: [ Alt: 'h',]
- action: [MoveFocus: Right,]
key: [ Alt: 'l',]
- action: [MoveFocus: Down,]
key: [ Alt: 'j',]
- action: [MoveFocus: Up,]
key: [ Alt: 'k',]
- action: [FocusPreviousPane,]
key: [ Alt: '[',]
- action: [FocusNextPane,]
key: [ Alt: ']',]
tmux:
######### list of tmux actions starts here in same order as exported from tmux 'C-b ?` command. #########
######### All Commented Commands have placeholder names for the features if they ever get implemented. ##
#- action: [SendPrefixKey,]
# key: [Ctrl: 'b',]
- action: [FocusNextPane, SwitchToMode: Normal,]
key: [Ctrl: 'o',]
#- action: [SuspendCurrentZellijClient, SwitchToMode: Normal,]
# key: [Ctrl: 'z',]
#- action: [SelectNextLayout, SwitchToMode: Normal,]
# key: [Char: ' ']
#- action: [BreakoutPaneToTab, SwitchToMode: Normal,]
# key: [Char: '!',]
- action: [NewPane: Down, SwitchToMode: Normal,]
key: [Char: '"',]
#- action: [ListPasteBuffers,]
# key: [Char: '#',]
#- action: [SwitchToMode: RenameTab, SessionNameInput: [0],]
# key: [Char: '$']
- action: [NewPane: Right, SwitchToMode: Normal,]
key: [Char: '%',]
- action: [CloseTab, SwitchToMode: Normal,]
key: [Char: '&',]
#- action: [PaneSelectionMenu, SwitchToMode: Normal,]
# key: [Char: ''',]
#- action: [SwitchToNextClient, SwitchToMode: Normal,]
# key: [Char: '(',]
#- action: [SwitchToPreviousClient, SwitchToMode: Normal,]
# key: [Char: ')',]
#- action: [Rename, SwitchToMode: Normal,]
# key: [Char: ',',]
- action: [SwitchToMode: RenameTab, TabNameInput: [0],]
key: [Char: ',']
#- action: [DeleteRecentPasteBuffer, SwitchToMode: Normal,]
# key: [Char: '-',]
#- action: [MoveTabIndexPosition, SwitchToMode: Normal,]
# key: [Char: '.',]
#- action: [DisplayKeybindAction, SwitchToMode: Normal,]
# key: [Char: '/',]
- action: [GoToTab: 1, SwitchToMode: Normal,]
key: [ Char: '1',]
- action: [GoToTab: 2, SwitchToMode: Normal,]
key: [ Char: '2',]
- action: [GoToTab: 3, SwitchToMode: Normal,]
key: [ Char: '3',]
- action: [GoToTab: 4, SwitchToMode: Normal,]
key: [ Char: '4',]
- action: [GoToTab: 5, SwitchToMode: Normal,]
key: [ Char: '5',]
- action: [GoToTab: 6, SwitchToMode: Normal,]
key: [ Char: '6',]
- action: [GoToTab: 7, SwitchToMode: Normal,]
key: [ Char: '7',]
- action: [GoToTab: 8, SwitchToMode: Normal,]
key: [ Char: '8',]
- action: [GoToTab: 9, SwitchToMode: Normal,]
key: [ Char: '9',]
- action: [GoToTab: 9, SwitchToMode: Normal,]
key: [ Char: '9',]
#- action: [EnterZellijCommandPrompt, SwitchToMode: Normal,]
# key: [ Char: ':',]
#- action: [GoToLastActivePane, SwitchToMode: Normal,]
# key: [ Char: ';',]
#- action: [ChoosePasteBufferItem, SwitchToMode: Normal,]
# key: [ Char: '=',]
#- action: [ListAllKeyBinds,]
# key: [ Char: '?',]
#- action: [SelectClientFromIndex,]
# key: [ Char: 'D',]
#- action: [EqualizePaneSizes,]
# key: [ Char: 'E',]
#- action: [GoToLastActiveClient, SwitchToMode: Normal,]
# key: [ Char: 'L',]
#- action: [ClearCurrentPaneText, SwitchToMode: Normal,]
# key: [ Char: 'M',]
#- action: [SwitchToMode: Copy,]
# key: [ Char: '[',]
#- action: [PasteMostRecentPasteBufferItem, SwitchToMode: Normal,]
# key: [ Char: ']',]
- action: [NewTab, SwitchToMode: Normal,]
key: [ Char: 'c',]
#- action: [DetachClient, Quit,]
# key: [ Char: 'd',]
#- action: [SwitchToMode: PaneWindowIndex,]
# key: [ Char: 'f',]
#- action: [DisplayPaneInformation, SwitchToMode: Normal,]
# key: [ Char: 'i',]
- action: [GoToPreviousTab, SwitchToMode: Normal,]
key: [ Char: 'l',]
#- action: [TogglePane, SwitchToMode: Normal,]
# key: [ Char: 'm',]
- action: [GoToNextTab, SwitchToMode: Normal,]
key: [ Char: 'n',]
- action: [FocusNextPane, SwitchToMode: Normal,]
key: [ Char: 'o',]
- action: [FocusPreviousPane, SwitchToMode: Normal,]
key: [ Char: 'p',]
#- action: [ShowPaneNumbers, SwitchToMode: Normal,]
# key: [ Char: 'q',]
#- action: [OrderClientRedraw, SwitchToMode: Normal,]
# key: [ Char: 'r',]
#- action: [SelectSessionFromIndex, SwitchToMode: Normal,]
# key: [ Char: 's',]
#- action: [ShowClockOnScreen, SwitchToMode: Normal,]
# key: [ Char: 't',]
#- action: [SelectTabFromIndex, SwitchToMode: Normal,]
# key: [ Char: 'w',]
- action: [CloseFocus, SwitchToMode: Normal,]
key: [Char: 'x',]
#- action: [ZoomToPane, SwitchToMode: Normal,]
# key: [ Char: 'z',]
#- action: [SwapPane: Up, SwitchToMode: Normal,]
# key: [ Char: '{',]
#- action: [SwapPane: Down, SwitchToMode: Normal,]
# key: [ Char: '}',]
#- action: [ShowZellijMessages, SwitchToMode: Normal,]
# key: [ Char: '~',]
#- action: [ResetToVisibleCursor, SwitchToMode: Normal,]
# key: [ 'Delete',]
#- action: [SwitchToMode: Copy, PageScrollUpToTop,]
# key: [ 'PageUp',]
- action: [MoveFocus: Left, SwitchToMode: Normal,]
key: [ 'Left',]
- action: [MoveFocus: Right, SwitchToMode: Normal,]
key: [ 'Right',]
- action: [MoveFocus: Down, SwitchToMode: Normal,]
key: [ 'Down',]
- action: [MoveFocus: Up, SwitchToMode: Normal,]
key: [ 'Up',]
#- action: [EvenOutRankPanes: Horizontally, SwitchToMode: Normal,]
# key: [ Alt: '1',]
#- action: [EvenOutRankPanes: Vertically, SwitchToMode: Normal,]
# key: [ Alt: '2',]
#- action: [SetPaneAsMain: Horizontally, SwitchToMode: Normal,]
# key: [ Alt: '3',]
#- action: [SetPaneAsMain: Vertically, SwitchToMode: Normal,]
# key: [ Alt: '4',]
#- action: [SelectTiledLayout, SwitchToMode: Normal,]
# key: [ Alt: '5',]
#- action: [SelectNextTabWithAlert, SwitchToMode: Normal,]
# key: [ Alt: 'n',]
- action: [FocusPreviousPane, SwitchToMode: Normal,]
key: [ Alt: 'o',]
#- action: [SelectNextTabWithAlert, SwitchToMode: Normal,]
# key: [ Alt: 'p',]
#- action: [ResizeIncremental: Up, SwitchToMode: Normal,]
# key: [Alt: 'Up',]
#- action: [ResizeIncremental: Down, SwitchToMode: Normal,]
# key: [Alt: 'Down',
#- action: [ResizeIncremental: Left, SwitchToMode: Normal,]
# key: [Alt: 'Left',]
#- action: [ResizeIncremental: Right, SwitchToMode: Normal,]
# key: [Alt: 'Right',]
#- action: [Resize: Up,]
# key: [Ctrl: 'Up',]
#- action: [Resize: Down,]
# key: [Ctrl: 'Down',]
#- action: [Resize: Left,]
# key: [Ctrl: 'Left',]
#- action: [Resize: Right,]
# key: [Ctrl: 'Right',]
#- action: [ShiftPartiallyVisibleTab: Up, SwitchToMode: Normal,]
# key: [Shift: 'Up',]
#- action: [ShiftPartiallyVisibleTab: Down, SwitchToMode: Normal,]
# key: [Shift: 'Down',]
#- action: [ShiftPartiallyVisibleTab: Left, SwitchToMode: Normal,]
# key: [Shift: 'Left',]
#- action: [ShiftPartiallyVisibleTab: Right, SwitchToMode: Normal,]
# key: [Shift: 'Right',]
########################################### End Tmux Commands Imported ##################################

View file

@ -1,4 +1,4 @@
[toolchain]
channel = "nightly"
channel = "beta"
components = ["rustfmt", "clippy", "rust-analysis"]
targets = ["wasm32-wasi"]

View file

@ -1,9 +1,7 @@
use super::common::utils::consts::{ZELLIJ_CONFIG_DIR_ENV, ZELLIJ_CONFIG_FILE_ENV};
use std::path::PathBuf;
use structopt::StructOpt;
// TODO add to consts.rs
const ZELLIJ_CONFIG_ENV: &str = "ZELLIJ_CONFIG";
#[derive(StructOpt, Default, Debug)]
#[structopt(name = "zellij")]
pub struct CliArgs {
@ -32,9 +30,13 @@ pub struct CliArgs {
pub layout: Option<PathBuf>,
/// Change where zellij looks for the configuration
#[structopt(short, long, env=ZELLIJ_CONFIG_ENV)]
#[structopt(short, long, env=ZELLIJ_CONFIG_FILE_ENV)]
pub config: Option<PathBuf>,
/// Change where zellij looks for the configuration
#[structopt(long, env=ZELLIJ_CONFIG_DIR_ENV)]
pub config_dir: Option<PathBuf>,
#[structopt(subcommand)]
pub option: Option<ConfigCli>,
@ -47,8 +49,19 @@ pub enum ConfigCli {
/// Change the behaviour of zellij
#[structopt(name = "option")]
Config {
#[structopt(long)]
/// Disables loading of configuration file at default location
#[structopt(long)]
clean: bool,
},
#[structopt(name = "generate-completion")]
GenerateCompletion { shell: String },
#[structopt(name = "setup")]
Setup {
/// Disables loading of configuration file at default location
/// Dump the default configuration file to stdout
#[structopt(long)]
dump_config: bool,
},
}

View file

@ -205,6 +205,18 @@ impl Layout {
layout
}
// It wants to use Path here, but that doesn't compile.
#[warn(clippy::ptr_arg)]
pub fn from_defaults(layout_path: &PathBuf, data_dir: &Path) -> Self {
Self::new(
&data_dir
.join("layouts/")
.join(layout_path)
.with_extension("yaml"),
&data_dir,
)
}
pub fn total_terminal_panes(&self) -> usize {
let mut total_panes = 0;
total_panes += self.parts.len();

View file

@ -161,6 +161,7 @@ pub struct Grid {
pending_styles: CharacterStyles,
pub should_render: bool,
pub cursor_key_mode: bool, // DECCKM - when set, cursor keys should send ANSI direction codes (eg. "OD") instead of the arrow keys (eg. "")
pub erasure_mode: bool, // ERM
pub clear_viewport_before_rendering: bool,
pub width: usize,
pub height: usize,
@ -170,9 +171,9 @@ impl Debug for Grid {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
for (i, row) in self.viewport.iter().enumerate() {
if row.is_canonical {
writeln!(f, "{:?} (C): {:?}", i, row)?;
writeln!(f, "{:02?} (C): {:?}", i, row)?;
} else {
writeln!(f, "{:?} (W): {:?}", i, row)?;
writeln!(f, "{:02?} (W): {:?}", i, row)?;
}
}
Ok(())
@ -192,20 +193,23 @@ impl Grid {
pending_styles: CharacterStyles::new(),
should_render: true,
cursor_key_mode: false,
erasure_mode: false,
alternative_lines_above_viewport_and_cursor: None,
clear_viewport_before_rendering: false,
}
}
pub fn contains_widechar(&self) -> bool {
self.viewport.iter().any(|c| c.contains_widechar())
}
pub fn advance_to_next_tabstop(&mut self, styles: CharacterStyles) {
let columns_until_next_tabstop = TABSTOP_WIDTH - (self.cursor.x % TABSTOP_WIDTH);
let columns_until_screen_end = self.width - self.cursor.x;
let columns_until_screen_end = (self.width - self.cursor.x).saturating_sub(1);
let columns_to_advance =
std::cmp::min(columns_until_next_tabstop, columns_until_screen_end);
let mut empty_character = EMPTY_TERMINAL_CHARACTER;
empty_character.styles = styles;
for _ in 0..columns_to_advance {
self.add_character(empty_character)
}
self.cursor.x += columns_to_advance;
self.pad_current_line_until(self.cursor.x);
}
fn cursor_canonical_line_index(&self) -> usize {
let mut cursor_canonical_line_index = 0;
@ -475,6 +479,13 @@ impl Grid {
}
}
}
pub fn fill_viewport(&mut self, character: TerminalCharacter) {
self.viewport.clear();
for _ in 0..self.height {
let columns = vec![character; self.width];
self.viewport.push(Row::from_columns(columns).canonical());
}
}
pub fn add_canonical_line(&mut self) {
if let Some((scroll_region_top, scroll_region_bottom)) = self.scroll_region {
if self.cursor.y == scroll_region_bottom {
@ -490,8 +501,12 @@ impl Grid {
}
self.viewport.remove(scroll_region_top);
let columns = vec![EMPTY_TERMINAL_CHARACTER; self.width];
if self.viewport.len() >= scroll_region_bottom {
self.viewport
.insert(scroll_region_bottom, Row::from_columns(columns).canonical());
} else {
self.viewport.push(Row::from_columns(columns).canonical());
}
return;
}
}
@ -518,13 +533,6 @@ impl Grid {
pub fn move_cursor_to_beginning_of_line(&mut self) {
self.cursor.x = 0;
}
pub fn move_cursor_backwards(&mut self, count: usize) {
if self.cursor.x > count {
self.cursor.x -= count;
} else {
self.cursor.x = 0;
}
}
pub fn insert_character_at_cursor_position(&mut self, terminal_character: TerminalCharacter) {
match self.viewport.get_mut(self.cursor.y) {
Some(row) => {
@ -601,17 +609,13 @@ impl Grid {
}
}
pub fn replace_characters_in_line_before_cursor(&mut self, replace_with: TerminalCharacter) {
let line_part = vec![replace_with; self.cursor.x];
let line_part = vec![replace_with; self.cursor.x + 1];
let row = self.viewport.get_mut(self.cursor.y).unwrap();
row.replace_beginning_with(line_part);
}
pub fn clear_all_after_cursor(&mut self, replace_with: TerminalCharacter) {
if let Some(cursor_row) = self.viewport.get_mut(self.cursor.y).as_mut() {
if let Some(cursor_row) = self.viewport.get_mut(self.cursor.y) {
cursor_row.truncate(self.cursor.x);
let mut replace_with_columns_in_cursor_row =
vec![replace_with; self.width - self.cursor.x];
cursor_row.append(&mut replace_with_columns_in_cursor_row);
let replace_with_columns = vec![replace_with; self.width];
self.replace_characters_in_line_after_cursor(replace_with);
for row in self.viewport.iter_mut().skip(self.cursor.y + 1) {
@ -619,6 +623,15 @@ impl Grid {
}
}
}
pub fn clear_all_before_cursor(&mut self, replace_with: TerminalCharacter) {
if self.viewport.get(self.cursor.y).is_some() {
self.replace_characters_in_line_before_cursor(replace_with);
let replace_with_columns = vec![replace_with; self.width];
for row in self.viewport.iter_mut().take(self.cursor.y) {
row.replace_columns(replace_with_columns.clone());
}
}
}
pub fn clear_cursor_line(&mut self) {
self.viewport.get_mut(self.cursor.y).unwrap().truncate(0);
}
@ -642,11 +655,26 @@ impl Grid {
}
}
pub fn move_cursor_to(&mut self, x: usize, y: usize, pad_character: TerminalCharacter) {
match self.scroll_region {
Some((scroll_region_top, scroll_region_bottom)) => {
self.cursor.x = std::cmp::min(self.width - 1, x);
let y_offset = if self.erasure_mode {
scroll_region_top
} else {
0
};
self.cursor.y = std::cmp::min(scroll_region_bottom, y + y_offset);
self.pad_lines_until(self.cursor.y, pad_character);
self.pad_current_line_until(self.cursor.x);
}
None => {
self.cursor.x = std::cmp::min(self.width - 1, x);
self.cursor.y = std::cmp::min(self.height - 1, y);
self.pad_lines_until(self.cursor.y, pad_character);
self.pad_current_line_until(self.cursor.x);
}
}
}
pub fn move_cursor_up(&mut self, count: usize) {
self.cursor.y = if self.cursor.y < count {
0
@ -690,6 +718,10 @@ impl Grid {
self.pad_lines_until(self.cursor.y, pad_character);
}
pub fn move_cursor_back(&mut self, count: usize) {
if self.cursor.x == self.width {
// on the rightmost screen edge, backspace skips one character
self.cursor.x -= 1;
}
if self.cursor.x < count {
self.cursor.x = 0;
} else {
@ -827,14 +859,15 @@ impl vte::Perform for Grid {
match byte {
8 => {
// backspace
self.move_cursor_backwards(1);
self.move_cursor_back(1);
}
9 => {
// tab
self.advance_to_next_tabstop(self.pending_styles);
}
10 => {
10 | 11 => {
// 0a, newline
// 0b, form-feed
self.add_newline();
}
13 => {
@ -891,11 +924,13 @@ impl vte::Perform for Grid {
char_to_replace.styles = self.pending_styles;
if params[0] == 0 {
self.clear_all_after_cursor(char_to_replace);
} else if params[0] == 1 {
self.clear_all_before_cursor(char_to_replace);
} else if params[0] == 2 {
self.clear_all(char_to_replace);
}
// TODO: implement 1
} else if c == 'H' {
} else if c == 'H' || c == 'f' {
// goto row/col
// we subtract 1 from the row/column because these are 1 indexed
// (except when they are 0, in which case they should be 1
@ -963,6 +998,16 @@ impl vte::Perform for Grid {
Some(&1) => {
self.cursor_key_mode = false;
}
Some(&3) => {
// DECCOLM - only side effects
self.scroll_region = None;
self.clear_all(EMPTY_TERMINAL_CHARACTER);
self.cursor.x = 0;
self.cursor.y = 0;
}
Some(&6) => {
self.erasure_mode = false;
}
_ => {}
};
}
@ -993,6 +1038,16 @@ impl vte::Perform for Grid {
Some(&1) => {
self.cursor_key_mode = true;
}
Some(&3) => {
// DECCOLM - only side effects
self.scroll_region = None;
self.clear_all(EMPTY_TERMINAL_CHARACTER);
self.cursor.x = 0;
self.cursor.y = 0;
}
Some(&6) => {
self.erasure_mode = true;
}
_ => {}
};
}
@ -1098,12 +1153,27 @@ impl vte::Perform for Grid {
fn esc_dispatch(&mut self, intermediates: &[u8], _ignore: bool, byte: u8) {
match (byte, intermediates.get(0)) {
(b'D', None) => {
self.add_newline();
}
(b'E', None) => {
self.add_newline();
self.move_cursor_to_beginning_of_line();
}
(b'M', None) => {
self.move_cursor_up_with_scrolling(1);
}
(b'c', None) => {
self.reset_terminal_state();
}
(b'H', None) => {
self.advance_to_next_tabstop(self.pending_styles);
}
(b'8', Some(b'#')) => {
let mut fill_character = EMPTY_TERMINAL_CHARACTER;
fill_character.character = 'E';
self.fill_viewport(fill_character);
}
_ => {}
}
}
@ -1156,6 +1226,9 @@ impl Row {
self.is_canonical = true;
self
}
pub fn contains_widechar(&self) -> bool {
self.columns.iter().any(|c| c.is_widechar())
}
pub fn add_character_at(&mut self, terminal_character: TerminalCharacter, x: usize) {
match self.columns.len().cmp(&x) {
Ordering::Equal => self.columns.push(terminal_character),
@ -1254,3 +1327,7 @@ impl Cursor {
}
}
}
#[cfg(test)]
#[path = "./unit/grid_tests.rs"]
mod grid_tests;

View file

@ -96,6 +96,9 @@ impl Pane for PluginPane {
fn position_and_size_override(&self) -> Option<PositionAndSize> {
self.position_and_size_override
}
fn contains_widechar(&self) -> bool {
false
}
fn should_render(&self) -> bool {
self.should_render
}

View file

@ -1,3 +1,5 @@
use unicode_width::UnicodeWidthChar;
use crate::utils::logging::debug_log_to_file;
use ::std::fmt::{self, Debug, Display, Formatter};
@ -634,3 +636,13 @@ impl ::std::fmt::Debug for TerminalCharacter {
write!(f, "{}", self.character)
}
}
impl TerminalCharacter {
pub fn width(&self) -> usize {
self.character.width().unwrap_or(0)
}
pub fn is_widechar(&self) -> bool {
self.width() > 1
}
}

View file

@ -87,6 +87,7 @@ impl Pane for TerminalPane {
for byte in bytes.iter() {
self.vte_parser.advance(&mut self.grid, *byte);
}
self.set_should_render(true);
}
fn cursor_coordinates(&self) -> Option<(usize, usize)> {
// (x, y)
@ -138,6 +139,9 @@ impl Pane for TerminalPane {
fn position_and_size_override(&self) -> Option<PositionAndSize> {
self.position_and_size_override
}
fn contains_widechar(&self) -> bool {
self.grid.contains_widechar()
}
fn should_render(&self) -> bool {
self.grid.should_render
}
@ -166,14 +170,7 @@ impl Pane for TerminalPane {
self.max_width
}
fn render(&mut self) -> Option<String> {
// FIXME:
// the below conditional is commented out because it causes several bugs:
// 1. When panes are resized or tabs are switched the previous contents of the screen stick
// around
// 2. When there are wide characters in a pane, since we don't yet handle them properly,
// the spill over to the pane to the right
// if self.should_render || cfg!(test) {
if true {
if self.should_render() {
let mut vte_output = String::new();
let buffer_lines = &self.read_buffer_as_lines();
let display_cols = self.get_columns();
@ -215,7 +212,7 @@ impl Pane for TerminalPane {
}
character_styles.clear();
}
self.grid.should_render = false;
self.set_should_render(false);
Some(vte_output)
} else {
None
@ -274,15 +271,15 @@ impl Pane for TerminalPane {
}
fn scroll_up(&mut self, count: usize) {
self.grid.move_viewport_up(count);
self.grid.should_render = true;
self.set_should_render(true);
}
fn scroll_down(&mut self, count: usize) {
self.grid.move_viewport_down(count);
self.grid.should_render = true;
self.set_should_render(true);
}
fn clear_scroll(&mut self) {
self.grid.reset_viewport();
self.grid.should_render = true;
self.set_should_render(true);
}
fn active_at(&self) -> Instant {
@ -337,6 +334,7 @@ impl TerminalPane {
let rows = self.get_rows();
let columns = self.get_columns();
self.grid.change_size(rows, columns);
self.set_should_render(true);
}
pub fn read_buffer_as_lines(&self) -> Vec<Vec<TerminalCharacter>> {
self.grid.as_character_lines()

View file

@ -0,0 +1,85 @@
use super::super::Grid;
use ::insta::assert_snapshot;
fn read_fixture(fixture_name: &str) -> Vec<u8> {
let mut path_to_file = std::path::PathBuf::new();
path_to_file.push("src");
path_to_file.push("tests");
path_to_file.push("fixtures");
path_to_file.push(fixture_name);
let content = std::fs::read(path_to_file)
.unwrap_or_else(|_| panic!("could not read fixture {:?}", &fixture_name));
content
}
#[test]
fn vttest1_0() {
let mut vte_parser = vte::Parser::new();
let mut grid = Grid::new(41, 110);
let fixture_name = "vttest1-0";
let content = read_fixture(fixture_name);
for byte in content {
vte_parser.advance(&mut grid, byte);
}
assert_snapshot!(format!("{:?}", grid));
}
#[test]
fn vttest1_1() {
let mut vte_parser = vte::Parser::new();
let mut grid = Grid::new(41, 110);
let fixture_name = "vttest1-1";
let content = read_fixture(fixture_name);
for byte in content {
vte_parser.advance(&mut grid, byte);
}
assert_snapshot!(format!("{:?}", grid));
}
#[test]
fn vttest1_2() {
let mut vte_parser = vte::Parser::new();
let mut grid = Grid::new(41, 110);
let fixture_name = "vttest1-2";
let content = read_fixture(fixture_name);
for byte in content {
vte_parser.advance(&mut grid, byte);
}
assert_snapshot!(format!("{:?}", grid));
}
#[test]
fn vttest1_3() {
let mut vte_parser = vte::Parser::new();
let mut grid = Grid::new(41, 110);
let fixture_name = "vttest1-3";
let content = read_fixture(fixture_name);
for byte in content {
vte_parser.advance(&mut grid, byte);
}
assert_snapshot!(format!("{:?}", grid));
}
#[test]
fn vttest1_4() {
let mut vte_parser = vte::Parser::new();
let mut grid = Grid::new(41, 110);
let fixture_name = "vttest1-4";
let content = read_fixture(fixture_name);
for byte in content {
vte_parser.advance(&mut grid, byte);
}
assert_snapshot!(format!("{:?}", grid));
}
#[test]
fn vttest1_5() {
let mut vte_parser = vte::Parser::new();
let mut grid = Grid::new(41, 110);
let fixture_name = "vttest1-5";
let content = read_fixture(fixture_name);
for byte in content {
vte_parser.advance(&mut grid, byte);
}
assert_snapshot!(format!("{:?}", grid));
}

View file

@ -0,0 +1,47 @@
---
source: src/client/panes/grid.rs
expression: "format!(\"{:?}\", grid)"
---
00 (C): ********************************************************************************
01 (C): *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*
02 (C): *+ +*
03 (C): *+ +*
04 (C): *+ +*
05 (C): *+ +*
06 (C): *+ +*
07 (C): *+ +*
08 (C): *+ EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE +*
09 (C): *+ E E +*
10 (C): *+ E The screen should be cleared, and have an unbroken bor- E +*
11 (C): *+ E der of *'s and +'s around the edge, and exactly in the E +*
12 (C): *+ E middle there should be a frame of E's around this text E +*
13 (C): *+ E with one (1) free position around it. Push <RETURN> E +*
14 (C): *+ E E +*
15 (C): *+ EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE +*
16 (C): *+ +*
17 (C): *+ +*
18 (C): *+ +*
19 (C): *+ +*
20 (C): *+ +*
21 (C): *+ +*
22 (C): *+ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
23 (C): ********************************************************************************
24 (C):
25 (C):
26 (C):
27 (C):
28 (C):
29 (C):
30 (C):
31 (C):
32 (C):
33 (C):
34 (C):
35 (C):
36 (C):
37 (C):
38 (C):
39 (C):
40 (C):

View file

@ -0,0 +1,47 @@
---
source: src/client/panes/grid.rs
expression: "format!(\"{:?}\", grid)"
---
00 (C): **************************************************************************************************************
01 (C): *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*
02 (C): *+ +*
03 (C): *+ +*
04 (C): *+ +*
05 (C): *+ +*
06 (C): *+ +*
07 (C): *+ +*
08 (C): *+ EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE +*
09 (C): *+ E E +*
10 (C): *+ E The screen should be cleared, and have an unbroken bor- E +*
11 (C): *+ E der of *'s and +'s around the edge, and exactly in the E +*
12 (C): *+ E middle there should be a frame of E's around this text E +*
13 (C): *+ E with one (1) free position around it. Push <RETURN> E +*
14 (C): *+ E E +*
15 (C): *+ EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE +*
16 (C): *+ +*
17 (C): *+ +*
18 (C): *+ +*
19 (C): *+ +*
20 (C): *+ +*
21 (C): *+ +*
22 (C): ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ *
23 (C): **************************************************************************************************************
24 (C):
25 (C):
26 (C):
27 (C):
28 (C):
29 (C):
30 (C):
31 (C):
32 (C):
33 (C):
34 (C):
35 (C):
36 (C):
37 (C):
38 (C):
39 (C):
40 (C):

View file

@ -0,0 +1,47 @@
---
source: src/client/panes/grid.rs
expression: "format!(\"{:?}\", grid)"
---
00 (C): Test of autowrap, mixing control and print characters.
01 (C): The left/right margins should have letters in order:
02 (C): I iJ
03 (C): j
04 (C): K K k
05 (C): L l
06 (C): M mN
07 (C): n
08 (C): O O o
09 (C): P p
10 (C): Q qR
11 (C): r
12 (C): S S s
13 (C): T t
14 (C): U uV
15 (C): v
16 (C): W W w
17 (C): X x
18 (C): Y yZ
19 (C): z
20 (C):
21 (C): Push <RETURN>
22 (C):
23 (C):
24 (C):
25 (C):
26 (C):
27 (C):
28 (C):
29 (C):
30 (C):
31 (C):
32 (C):
33 (C):
34 (C):
35 (C):
36 (C):
37 (C):
38 (C):
39 (C):
40 (C):

View file

@ -0,0 +1,47 @@
---
source: src/client/panes/grid.rs
expression: "format!(\"{:?}\", grid)"
---
00 (C): Test of autowrap, mixing control and print characters.
01 (C): The left/right margins should have letters in order:
02 (C): I i
03 (C): J j
04 (C): K k
05 (C): L l
06 (C): M m
07 (C): N n
08 (C): O o
09 (C): P p
10 (C): Q q
11 (C): R r
12 (C): S s
13 (C): T t
14 (C): U u
15 (C): V v
16 (C): W w
17 (C): X x
18 (C): Y y
19 (C): Z z
20 (C):
21 (C): Push <RETURN>
22 (C):
23 (C):
24 (C):
25 (C):
26 (C):
27 (C):
28 (C):
29 (C):
30 (C):
31 (C):
32 (C):
33 (C):
34 (C):
35 (C):
36 (C):
37 (C):
38 (C):
39 (C):
40 (C):

View file

@ -0,0 +1,47 @@
---
source: src/client/panes/grid.rs
expression: "format!(\"{:?}\", grid)"
---
00 (C): Test of cursor-control characters inside ESC sequences.
01 (C): Below should be four identical lines:
02 (C):
03 (C): A B C D E F G H I
04 (C): A B C D E F G H I
05 (C): A B C D E F G H I
06 (C): A B C D E F G H I
07 (C):
08 (C): Push <RETURN>
09 (C):
10 (C):
11 (C):
12 (C):
13 (C):
14 (C):
15 (C):
16 (C):
17 (C):
18 (C):
19 (C):
20 (C):
21 (C):
22 (C):
23 (C):
24 (C):
25 (C):
26 (C):
27 (C):
28 (C):
29 (C):
30 (C):
31 (C):
32 (C):
33 (C):
34 (C):
35 (C):
36 (C):
37 (C):
38 (C):
39 (C):
40 (C):

View file

@ -0,0 +1,47 @@
---
source: src/client/panes/grid.rs
expression: "format!(\"{:?}\", grid)"
---
00 (C): Test of leading zeros in ESC sequences.
01 (C): Two lines below you should see the sentence "This is a correct sentence".
02 (C):
03 (C): This is a correct sentence
04 (C):
05 (C):
06 (C):
07 (C):
08 (C):
09 (C):
10 (C):
11 (C):
12 (C):
13 (C):
14 (C):
15 (C):
16 (C):
17 (C):
18 (C):
19 (C): Push <RETURN>
20 (C):
21 (C):
22 (C):
23 (C):
24 (C):
25 (C):
26 (C):
27 (C):
28 (C):
29 (C):
30 (C):
31 (C):
32 (C):
33 (C):
34 (C):
35 (C):
36 (C):
37 (C):
38 (C):
39 (C):
40 (C):

View file

@ -67,6 +67,7 @@ pub struct Tab {
max_panes: Option<usize>,
full_screen_ws: PositionAndSize,
fullscreen_is_active: bool,
synchronize_is_active: bool,
os_api: Box<dyn OsApi>,
pub send_pty_instructions: SenderWithContext<PtyInstruction>,
pub send_plugin_instructions: SenderWithContext<PluginInstruction>,
@ -104,6 +105,9 @@ pub trait Pane {
fn position_and_size_override(&self) -> Option<PositionAndSize>;
fn should_render(&self) -> bool;
fn set_should_render(&mut self, should_render: bool);
// FIXME: this method is used to trigger a force render to hide widechar problem
// it should be removed when we can handle widechars
fn contains_widechar(&self) -> bool;
fn selectable(&self) -> bool;
fn set_selectable(&mut self, selectable: bool);
fn set_invisible_borders(&mut self, invisible_borders: bool);
@ -254,6 +258,7 @@ impl Tab {
active_terminal: pane_id,
full_screen_ws: *full_screen_ws,
fullscreen_is_active: false,
synchronize_is_active: false,
os_api,
send_app_instructions,
send_pty_instructions,
@ -599,6 +604,21 @@ impl Tab {
terminal_output.handle_pty_bytes(bytes);
}
}
pub fn write_to_terminals_on_current_tab(&mut self, input_bytes: Vec<u8>) {
let pane_ids = self.get_pane_ids();
pane_ids.iter().for_each(|pane_id| match pane_id {
PaneId::Terminal(pid) => {
self.write_to_pane_id(input_bytes.clone(), *pid);
}
PaneId::Plugin(_) => {}
});
}
pub fn write_to_pane_id(&mut self, mut input_bytes: Vec<u8>, pid: RawFd) {
self.os_api
.write_to_tty_stdin(pid, &mut input_bytes)
.expect("failed to write to terminal");
self.os_api.tcdrain(pid).expect("failed to drain terminal");
}
pub fn write_to_active_terminal(&mut self, input_bytes: Vec<u8>) {
match self.get_active_pane_id() {
Some(PaneId::Terminal(active_terminal_id)) => {
@ -684,12 +704,31 @@ impl Tab {
pub fn toggle_fullscreen_is_active(&mut self) {
self.fullscreen_is_active = !self.fullscreen_is_active;
}
pub fn set_force_render(&mut self) {
for pane in self.panes.values_mut() {
pane.set_should_render(true);
}
}
pub fn is_sync_panes_active(&self) -> bool {
self.synchronize_is_active
}
pub fn toggle_sync_panes_is_active(&mut self) {
self.synchronize_is_active = !self.synchronize_is_active;
}
pub fn panes_contain_widechar(&self) -> bool {
self.panes.iter().any(|(_, p)| p.contains_widechar())
}
pub fn render(&mut self) {
if self.active_terminal.is_none() {
// we might not have an active terminal if we closed the last pane
// in that case, we should not render as the app is exiting
return;
}
// if any pane contain widechar, all pane in the same row will messup. We should render them every time
// FIXME: remove this when we can handle widechars correctly
if self.panes_contain_widechar() {
self.set_force_render()
}
let mut stdout = self.os_api.get_stdout_writer();
let mut boundaries = Boundaries::new(
self.full_screen_ws.columns as u16,

View file

@ -200,6 +200,7 @@ pub enum ScreenContext {
PageScrollDown,
ClearScroll,
CloseFocusedPane,
ToggleActiveSyncPanes,
ToggleActiveTerminalFullscreen,
SetSelectable,
SetInvisibleBorders,
@ -260,6 +261,7 @@ impl From<&ScreenInstruction> for ScreenContext {
ScreenInstruction::UpdateTabName(_) => ScreenContext::UpdateTabName,
ScreenInstruction::TerminalResize => ScreenContext::TerminalResize,
ScreenInstruction::ChangeMode(_) => ScreenContext::ChangeMode,
ScreenInstruction::ToggleActiveSyncPanes => ScreenContext::ToggleActiveSyncPanes,
}
}
}

View file

@ -39,6 +39,8 @@ pub enum Action {
PageScrollDown,
/// Toggle between fullscreen focus pane and normal layout.
ToggleFocusFullscreen,
/// Toggle between sending text commands to all panes and normal mode.
ToggleActiveSyncPanes,
/// Open a new pane in the specified direction (relative to focus).
/// If no direction is specified, will try to use the biggest available space.
NewPane(Option<Direction>),

View file

@ -7,8 +7,8 @@ use std::path::{Path, PathBuf};
use super::keybinds::{Keybinds, KeybindsFromYaml};
use crate::cli::ConfigCli;
use crate::common::install;
use directories_next::ProjectDirs;
use serde::Deserialize;
type ConfigResult = Result<Config, ConfigError>;
@ -33,6 +33,8 @@ pub enum ConfigError {
Io(io::Error),
// Io error with path context
IoPath(io::Error, PathBuf),
// Internal Deserialisation Error
FromUtf8(std::string::FromUtf8Error),
}
impl Default for Config {
@ -63,18 +65,11 @@ impl Config {
}
}
/// Deserializes the config from a default platform specific path,
/// merges the default configuration - options take precedence.
fn from_default_path() -> ConfigResult {
let project_dirs = ProjectDirs::from("org", "Zellij Contributors", "Zellij").unwrap();
let mut config_path: PathBuf = project_dirs.config_dir().to_owned();
config_path.push("config.yaml");
match Config::new(&config_path) {
Ok(config) => Ok(config),
Err(ConfigError::IoPath(_, _)) => Ok(Config::default()),
Err(e) => Err(e),
}
/// Gets default configuration from assets
// TODO Deserialize the Configuration from bytes &[u8],
// once serde-yaml supports zero-copy
pub fn from_default_assets() -> ConfigResult {
Self::from_yaml(String::from_utf8(install::DEFAULT_CONFIG.to_vec())?.as_str())
}
/// Entry point of the configuration
@ -82,20 +77,37 @@ impl Config {
pub fn from_cli_config(
location: Option<PathBuf>,
cli_config: Option<ConfigCli>,
config_dir: Option<PathBuf>,
) -> ConfigResult {
if let Some(path) = location {
return Config::new(&path);
}
match cli_config {
Some(ConfigCli::Config { clean, .. }) if clean => Ok(Config::default()),
Some(_) | None => Ok(Config::from_default_path()?),
if let Some(ConfigCli::Config { clean, .. }) = cli_config {
if clean {
return Config::from_default_assets();
}
}
if let Some(config) = config_dir {
let path = config.join("config.yaml");
if path.exists() {
Config::new(&path)
} else {
Config::from_default_assets()
}
} else {
Config::from_default_assets()
}
}
/// In order not to mess up tests from changing configurations
#[cfg(test)]
pub fn from_cli_config(_: Option<PathBuf>, _: Option<ConfigCli>) -> ConfigResult {
pub fn from_cli_config(
_: Option<PathBuf>,
_: Option<ConfigCli>,
_: Option<PathBuf>,
) -> ConfigResult {
Ok(Config::default())
}
}
@ -108,6 +120,7 @@ impl Display for ConfigError {
write!(formatter, "IoError: {}, File: {}", err, path.display(),)
}
ConfigError::Serde(ref err) => write!(formatter, "Deserialisation error: {}", err),
ConfigError::FromUtf8(ref err) => write!(formatter, "FromUtf8Error: {}", err),
}
}
}
@ -118,6 +131,7 @@ impl std::error::Error for ConfigError {
ConfigError::Io(ref err) => Some(err),
ConfigError::IoPath(ref err, _) => Some(err),
ConfigError::Serde(ref err) => Some(err),
ConfigError::FromUtf8(ref err) => Some(err),
}
}
}
@ -134,6 +148,12 @@ impl From<serde_yaml::Error> for ConfigError {
}
}
impl From<std::string::FromUtf8Error> for ConfigError {
fn from(err: std::string::FromUtf8Error) -> ConfigError {
ConfigError::FromUtf8(err)
}
}
// The unit test location.
#[cfg(test)]
mod config_test {
@ -142,14 +162,14 @@ mod config_test {
#[test]
fn clean_option_equals_default_config() {
let cli_config = ConfigCli::Config { clean: true };
let config = Config::from_cli_config(None, Some(cli_config)).unwrap();
let config = Config::from_cli_config(None, Some(cli_config), None).unwrap();
let default = Config::default();
assert_eq!(config, default);
}
#[test]
fn no_config_option_file_equals_default_config() {
let config = Config::from_cli_config(None, None).unwrap();
let config = Config::from_cli_config(None, None, None).unwrap();
let default = Config::default();
assert_eq!(config, default);
}

View file

@ -59,7 +59,6 @@ impl InputHandler {
fn handle_input(&mut self) {
let mut err_ctx = OPENCALLS.with(|ctx| *ctx.borrow());
err_ctx.add_call(ContextType::StdinHandler);
let keybinds = self.config.keybinds.clone();
let alt_left_bracket = vec![27, 91];
loop {
if self.should_exit {
@ -71,14 +70,14 @@ impl InputHandler {
Ok((event, raw_bytes)) => match event {
termion::event::Event::Key(key) => {
let key = cast_termion_key(key);
self.handle_key(&key, raw_bytes, &keybinds);
self.handle_key(&key, raw_bytes);
}
termion::event::Event::Unsupported(unsupported_key) => {
// we have to do this because of a bug in termion
// this should be a key event and not an unsupported event
if unsupported_key == alt_left_bracket {
let key = Key::Alt('[');
self.handle_key(&key, raw_bytes, &keybinds);
self.handle_key(&key, raw_bytes);
}
}
termion::event::Event::Mouse(_) => {
@ -91,8 +90,9 @@ impl InputHandler {
}
}
}
fn handle_key(&mut self, key: &Key, raw_bytes: Vec<u8>, keybinds: &Keybinds) {
for action in Keybinds::key_to_actions(&key, raw_bytes, &self.mode, &keybinds) {
fn handle_key(&mut self, key: &Key, raw_bytes: Vec<u8>) {
let keybinds = &self.config.keybinds;
for action in Keybinds::key_to_actions(&key, raw_bytes, &self.mode, keybinds) {
let should_exit = self.dispatch_action(action);
if should_exit {
self.should_exit = true;
@ -245,6 +245,11 @@ impl InputHandler {
.send(ScreenInstruction::SwitchTabPrev)
.unwrap();
}
Action::ToggleActiveSyncPanes => {
self.send_screen_instructions
.send(ScreenInstruction::ToggleActiveSyncPanes)
.unwrap();
}
Action::CloseTab => {
self.command_is_executing.closing_pane();
self.send_screen_instructions
@ -295,6 +300,7 @@ pub fn get_mode_info(mode: InputMode) -> ModeInfo {
keybinds.push(("d".to_string(), "Down split".to_string()));
keybinds.push(("r".to_string(), "Right split".to_string()));
keybinds.push(("x".to_string(), "Close".to_string()));
keybinds.push(("s".to_string(), "Sync".to_string()));
keybinds.push(("f".to_string(), "Fullscreen".to_string()));
}
InputMode::Tab => {

View file

@ -1,7 +1,8 @@
//! Mapping of inputs to sequences of actions.
use std::collections::HashMap;
use super::actions::{Action, Direction};
use super::actions::Action;
use super::config;
use serde::Deserialize;
use strum::IntoEnumIterator;
@ -57,14 +58,9 @@ enum Unbind {
impl Default for Keybinds {
fn default() -> Keybinds {
let mut defaults = Keybinds::new();
for mode in InputMode::iter() {
defaults
.0
.insert(mode, Keybinds::get_defaults_for_mode(&mode));
}
defaults
config::Config::from_default_assets()
.expect("Keybinds from default assets Error")
.keybinds
}
}
@ -109,278 +105,6 @@ impl Keybinds {
keybinds
}
/// Returns the default keybinds for a given [`InputMode`].
fn get_defaults_for_mode(mode: &InputMode) -> ModeKeybinds {
let mut defaults = HashMap::new();
match *mode {
InputMode::Normal => {
defaults.insert(
Key::Ctrl('g'),
vec![Action::SwitchToMode(InputMode::Locked)],
);
defaults.insert(Key::Ctrl('p'), vec![Action::SwitchToMode(InputMode::Pane)]);
defaults.insert(
Key::Ctrl('r'),
vec![Action::SwitchToMode(InputMode::Resize)],
);
defaults.insert(Key::Ctrl('t'), vec![Action::SwitchToMode(InputMode::Tab)]);
defaults.insert(
Key::Ctrl('s'),
vec![Action::SwitchToMode(InputMode::Scroll)],
);
defaults.insert(Key::Ctrl('q'), vec![Action::Quit]);
defaults.insert(Key::Alt('n'), vec![Action::NewPane(None)]);
defaults.insert(Key::Alt('h'), vec![Action::MoveFocus(Direction::Left)]);
defaults.insert(Key::Alt('j'), vec![Action::MoveFocus(Direction::Down)]);
defaults.insert(Key::Alt('k'), vec![Action::MoveFocus(Direction::Up)]);
defaults.insert(Key::Alt('l'), vec![Action::MoveFocus(Direction::Right)]);
defaults.insert(Key::Alt('['), vec![Action::FocusPreviousPane]);
defaults.insert(Key::Alt(']'), vec![Action::FocusNextPane]);
}
InputMode::Locked => {
defaults.insert(
Key::Ctrl('g'),
vec![Action::SwitchToMode(InputMode::Normal)],
);
}
InputMode::Resize => {
defaults.insert(
Key::Ctrl('g'),
vec![Action::SwitchToMode(InputMode::Locked)],
);
defaults.insert(Key::Ctrl('p'), vec![Action::SwitchToMode(InputMode::Pane)]);
defaults.insert(
Key::Ctrl('r'),
vec![Action::SwitchToMode(InputMode::Normal)],
);
defaults.insert(Key::Ctrl('t'), vec![Action::SwitchToMode(InputMode::Tab)]);
defaults.insert(
Key::Ctrl('s'),
vec![Action::SwitchToMode(InputMode::Scroll)],
);
defaults.insert(Key::Ctrl('q'), vec![Action::Quit]);
defaults.insert(Key::Esc, vec![Action::SwitchToMode(InputMode::Normal)]);
defaults.insert(
Key::Char('\n'),
vec![Action::SwitchToMode(InputMode::Normal)],
);
defaults.insert(
Key::Char(' '),
vec![Action::SwitchToMode(InputMode::Normal)],
);
defaults.insert(Key::Char('h'), vec![Action::Resize(Direction::Left)]);
defaults.insert(Key::Char('j'), vec![Action::Resize(Direction::Down)]);
defaults.insert(Key::Char('k'), vec![Action::Resize(Direction::Up)]);
defaults.insert(Key::Char('l'), vec![Action::Resize(Direction::Right)]);
defaults.insert(Key::Left, vec![Action::Resize(Direction::Left)]);
defaults.insert(Key::Down, vec![Action::Resize(Direction::Down)]);
defaults.insert(Key::Up, vec![Action::Resize(Direction::Up)]);
defaults.insert(Key::Right, vec![Action::Resize(Direction::Right)]);
defaults.insert(Key::Alt('n'), vec![Action::NewPane(None)]);
defaults.insert(Key::Alt('h'), vec![Action::MoveFocus(Direction::Left)]);
defaults.insert(Key::Alt('j'), vec![Action::MoveFocus(Direction::Down)]);
defaults.insert(Key::Alt('k'), vec![Action::MoveFocus(Direction::Up)]);
defaults.insert(Key::Alt('l'), vec![Action::MoveFocus(Direction::Right)]);
defaults.insert(Key::Alt('['), vec![Action::FocusPreviousPane]);
defaults.insert(Key::Alt(']'), vec![Action::FocusNextPane]);
}
InputMode::Pane => {
defaults.insert(
Key::Ctrl('g'),
vec![Action::SwitchToMode(InputMode::Locked)],
);
defaults.insert(
Key::Ctrl('p'),
vec![Action::SwitchToMode(InputMode::Normal)],
);
defaults.insert(
Key::Ctrl('r'),
vec![Action::SwitchToMode(InputMode::Resize)],
);
defaults.insert(Key::Ctrl('t'), vec![Action::SwitchToMode(InputMode::Tab)]);
defaults.insert(
Key::Ctrl('s'),
vec![Action::SwitchToMode(InputMode::Scroll)],
);
defaults.insert(Key::Ctrl('q'), vec![Action::Quit]);
defaults.insert(Key::Esc, vec![Action::SwitchToMode(InputMode::Normal)]);
defaults.insert(
Key::Char('\n'),
vec![Action::SwitchToMode(InputMode::Normal)],
);
defaults.insert(
Key::Char(' '),
vec![Action::SwitchToMode(InputMode::Normal)],
);
defaults.insert(Key::Char('h'), vec![Action::MoveFocus(Direction::Left)]);
defaults.insert(Key::Char('j'), vec![Action::MoveFocus(Direction::Down)]);
defaults.insert(Key::Char('k'), vec![Action::MoveFocus(Direction::Up)]);
defaults.insert(Key::Char('l'), vec![Action::MoveFocus(Direction::Right)]);
defaults.insert(Key::Left, vec![Action::MoveFocus(Direction::Left)]);
defaults.insert(Key::Down, vec![Action::MoveFocus(Direction::Down)]);
defaults.insert(Key::Up, vec![Action::MoveFocus(Direction::Up)]);
defaults.insert(Key::Right, vec![Action::MoveFocus(Direction::Right)]);
defaults.insert(Key::Char('p'), vec![Action::SwitchFocus]);
defaults.insert(Key::Char('n'), vec![Action::NewPane(None)]);
defaults.insert(Key::Char('d'), vec![Action::NewPane(Some(Direction::Down))]);
defaults.insert(
Key::Char('r'),
vec![Action::NewPane(Some(Direction::Right))],
);
defaults.insert(Key::Char('x'), vec![Action::CloseFocus]);
defaults.insert(Key::Char('f'), vec![Action::ToggleFocusFullscreen]);
defaults.insert(Key::Alt('n'), vec![Action::NewPane(None)]);
defaults.insert(Key::Alt('h'), vec![Action::MoveFocus(Direction::Left)]);
defaults.insert(Key::Alt('j'), vec![Action::MoveFocus(Direction::Down)]);
defaults.insert(Key::Alt('k'), vec![Action::MoveFocus(Direction::Up)]);
defaults.insert(Key::Alt('l'), vec![Action::MoveFocus(Direction::Right)]);
defaults.insert(Key::Alt('['), vec![Action::FocusPreviousPane]);
defaults.insert(Key::Alt(']'), vec![Action::FocusNextPane]);
}
InputMode::Tab => {
defaults.insert(
Key::Ctrl('g'),
vec![Action::SwitchToMode(InputMode::Locked)],
);
defaults.insert(Key::Ctrl('p'), vec![Action::SwitchToMode(InputMode::Pane)]);
defaults.insert(
Key::Ctrl('r'),
vec![Action::SwitchToMode(InputMode::Resize)],
);
defaults.insert(
Key::Ctrl('t'),
vec![Action::SwitchToMode(InputMode::Normal)],
);
defaults.insert(
Key::Ctrl('s'),
vec![Action::SwitchToMode(InputMode::Scroll)],
);
defaults.insert(Key::Ctrl('q'), vec![Action::Quit]);
defaults.insert(Key::Esc, vec![Action::SwitchToMode(InputMode::Normal)]);
defaults.insert(
Key::Char('\n'),
vec![Action::SwitchToMode(InputMode::Normal)],
);
defaults.insert(
Key::Char(' '),
vec![Action::SwitchToMode(InputMode::Normal)],
);
defaults.insert(Key::Char('h'), vec![Action::GoToPreviousTab]);
defaults.insert(Key::Char('j'), vec![Action::GoToNextTab]);
defaults.insert(Key::Char('k'), vec![Action::GoToPreviousTab]);
defaults.insert(Key::Char('l'), vec![Action::GoToNextTab]);
defaults.insert(Key::Left, vec![Action::GoToPreviousTab]);
defaults.insert(Key::Down, vec![Action::GoToNextTab]);
defaults.insert(Key::Up, vec![Action::GoToPreviousTab]);
defaults.insert(Key::Right, vec![Action::GoToNextTab]);
defaults.insert(Key::Char('n'), vec![Action::NewTab]);
defaults.insert(Key::Char('x'), vec![Action::CloseTab]);
defaults.insert(
Key::Char('r'),
vec![
Action::SwitchToMode(InputMode::RenameTab),
Action::TabNameInput(vec![0]),
],
);
defaults.insert(
Key::Ctrl('g'),
vec![Action::SwitchToMode(InputMode::Normal)],
);
for i in '1'..='9' {
defaults.insert(Key::Char(i), vec![Action::GoToTab(i.to_digit(10).unwrap())]);
}
defaults.insert(Key::Alt('n'), vec![Action::NewPane(None)]);
defaults.insert(Key::Alt('h'), vec![Action::MoveFocus(Direction::Left)]);
defaults.insert(Key::Alt('j'), vec![Action::MoveFocus(Direction::Down)]);
defaults.insert(Key::Alt('k'), vec![Action::MoveFocus(Direction::Up)]);
defaults.insert(Key::Alt('l'), vec![Action::MoveFocus(Direction::Right)]);
defaults.insert(Key::Alt('['), vec![Action::FocusPreviousPane]);
defaults.insert(Key::Alt(']'), vec![Action::FocusNextPane]);
}
InputMode::Scroll => {
defaults.insert(
Key::Ctrl('g'),
vec![Action::SwitchToMode(InputMode::Locked)],
);
defaults.insert(Key::Ctrl('p'), vec![Action::SwitchToMode(InputMode::Pane)]);
defaults.insert(
Key::Ctrl('r'),
vec![Action::SwitchToMode(InputMode::Resize)],
);
defaults.insert(Key::Ctrl('t'), vec![Action::SwitchToMode(InputMode::Tab)]);
defaults.insert(
Key::Ctrl('s'),
vec![Action::SwitchToMode(InputMode::Normal)],
);
defaults.insert(Key::Ctrl('q'), vec![Action::Quit]);
defaults.insert(Key::Esc, vec![Action::SwitchToMode(InputMode::Normal)]);
defaults.insert(
Key::Char('\n'),
vec![Action::SwitchToMode(InputMode::Normal)],
);
defaults.insert(
Key::Char(' '),
vec![Action::SwitchToMode(InputMode::Normal)],
);
defaults.insert(Key::Char('j'), vec![Action::ScrollDown]);
defaults.insert(Key::Char('k'), vec![Action::ScrollUp]);
defaults.insert(Key::Ctrl('f'), vec![Action::PageScrollDown]);
defaults.insert(Key::Ctrl('b'), vec![Action::PageScrollUp]);
defaults.insert(Key::PageDown, vec![Action::PageScrollDown]);
defaults.insert(Key::PageUp, vec![Action::PageScrollUp]);
defaults.insert(Key::Down, vec![Action::ScrollDown]);
defaults.insert(Key::Up, vec![Action::ScrollUp]);
defaults.insert(Key::Alt('n'), vec![Action::NewPane(None)]);
defaults.insert(Key::Alt('h'), vec![Action::MoveFocus(Direction::Left)]);
defaults.insert(Key::Alt('j'), vec![Action::MoveFocus(Direction::Down)]);
defaults.insert(Key::Alt('k'), vec![Action::MoveFocus(Direction::Up)]);
defaults.insert(Key::Alt('l'), vec![Action::MoveFocus(Direction::Right)]);
defaults.insert(Key::Alt('['), vec![Action::FocusPreviousPane]);
defaults.insert(Key::Alt(']'), vec![Action::FocusNextPane]);
}
InputMode::RenameTab => {
defaults.insert(Key::Char('\n'), vec![Action::SwitchToMode(InputMode::Tab)]);
defaults.insert(
Key::Ctrl('g'),
vec![Action::SwitchToMode(InputMode::Normal)],
);
defaults.insert(
Key::Esc,
vec![
Action::TabNameInput(vec![0x1b]),
Action::SwitchToMode(InputMode::Tab),
],
);
defaults.insert(Key::Alt('n'), vec![Action::NewPane(None)]);
defaults.insert(Key::Alt('h'), vec![Action::MoveFocus(Direction::Left)]);
defaults.insert(Key::Alt('j'), vec![Action::MoveFocus(Direction::Down)]);
defaults.insert(Key::Alt('k'), vec![Action::MoveFocus(Direction::Up)]);
defaults.insert(Key::Alt('l'), vec![Action::MoveFocus(Direction::Right)]);
defaults.insert(Key::Alt('['), vec![Action::FocusPreviousPane]);
defaults.insert(Key::Alt(']'), vec![Action::FocusNextPane]);
}
}
ModeKeybinds(defaults)
}
/// Converts a [`Key`] terminal event to a sequence of [`Action`]s according to the current
/// [`InputMode`] and [`Keybinds`].
pub fn key_to_actions(

View file

@ -1,4 +1,7 @@
use std::{fs, path::Path};
use crate::common::utils::consts::SYSTEM_DEFAULT_CONFIG_DIR;
use directories_next::{BaseDirs, ProjectDirs};
use std::io::Write;
use std::{fs, path::Path, path::PathBuf};
const VERSION: &str = env!("CARGO_PKG_VERSION");
@ -39,3 +42,44 @@ pub fn populate_data_dir(data_dir: &Path) {
}
}
}
pub fn default_config_dir() -> Option<PathBuf> {
vec![
Some(xdg_config_dir()),
home_config_dir(),
Some(Path::new(SYSTEM_DEFAULT_CONFIG_DIR).to_path_buf()),
]
.into_iter()
.filter(|p| p.is_some())
.find(|p| p.clone().unwrap().exists())
.flatten()
}
pub fn xdg_config_dir() -> PathBuf {
let project_dirs = ProjectDirs::from("org", "Zellij Contributors", "Zellij").unwrap();
project_dirs.config_dir().to_owned()
}
pub fn home_config_dir() -> Option<PathBuf> {
if let Some(user_dirs) = BaseDirs::new() {
let config_dir = user_dirs.home_dir().join("/.config/zellij");
Some(config_dir)
} else {
None
}
}
pub fn dump_asset(asset: &[u8]) -> std::io::Result<()> {
std::io::stdout().write_all(&asset)?;
Ok(())
}
pub const DEFAULT_CONFIG: &[u8] = include_bytes!(concat!(
env!("CARGO_MANIFEST_DIR"),
"/",
"assets/config/default.yaml"
));
pub fn dump_default_config() -> std::io::Result<()> {
dump_asset(DEFAULT_CONFIG)
}

View file

@ -40,8 +40,7 @@ use pty_bus::{PtyBus, PtyInstruction};
use screen::{Screen, ScreenInstruction};
use serde::{Deserialize, Serialize};
use utils::{consts::ZELLIJ_IPC_PIPE, shared::load_palette};
use wasm_vm::PluginEnv;
use wasm_vm::{wasi_stdout, wasi_write_string, zellij_imports, PluginInstruction};
use wasm_vm::{wasi_read_string, wasi_write_object, zellij_exports, PluginEnv, PluginInstruction};
use wasmer::{ChainableNamedResolver, Instance, Module, Store, Value};
use wasmer_wasi::{Pipe, WasiState};
use zellij_tile::data::{EventType, InputMode, ModeInfo};
@ -131,7 +130,9 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) {
env::set_var(&"ZELLIJ", "0");
let config = Config::from_cli_config(opts.config, opts.option)
let config_dir = opts.config_dir.or_else(install::default_config_dir);
let config = Config::from_cli_config(opts.config, opts.option, config_dir)
.map_err(|e| {
eprintln!("There was an error in the config file:\n{}", e);
std::process::exit(1);
@ -185,8 +186,8 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) {
let default_layout = None;
let maybe_layout = opts
.layout
.or(default_layout)
.map(|p| Layout::new(&p, &data_dir));
.map(|p| Layout::new(&p, &data_dir))
.or_else(|| default_layout.map(|p| Layout::from_defaults(&p, &data_dir)));
#[cfg(not(test))]
std::panic::set_hook({
@ -325,10 +326,11 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) {
command_is_executing.done_opening_new_pane();
}
ScreenInstruction::WriteCharacter(bytes) => {
screen
.get_active_tab_mut()
.unwrap()
.write_to_active_terminal(bytes);
let active_tab = screen.get_active_tab_mut().unwrap();
match active_tab.is_sync_panes_active() {
true => active_tab.write_to_terminals_on_current_tab(bytes),
false => active_tab.write_to_active_terminal(bytes),
}
}
ScreenInstruction::ResizeLeft => {
screen.get_active_tab_mut().unwrap().resize_left();
@ -449,6 +451,13 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) {
ScreenInstruction::ChangeMode(mode_info) => {
screen.change_mode(mode_info);
}
ScreenInstruction::ToggleActiveSyncPanes => {
screen
.get_active_tab_mut()
.unwrap()
.toggle_sync_panes_is_active();
screen.update_tabs();
}
ScreenInstruction::Quit => {
break;
}
@ -464,6 +473,7 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) {
let send_pty_instructions = send_pty_instructions.clone();
let send_screen_instructions = send_screen_instructions.clone();
let send_app_instructions = send_app_instructions.clone();
let send_plugin_instructions = send_plugin_instructions.clone();
let store = Store::default();
let mut plugin_id = 0;
@ -508,16 +518,17 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) {
send_pty_instructions: send_pty_instructions.clone(),
send_screen_instructions: send_screen_instructions.clone(),
send_app_instructions: send_app_instructions.clone(),
send_plugin_instructions: send_plugin_instructions.clone(),
wasi_env,
subscriptions: Arc::new(Mutex::new(HashSet::new())),
};
let zellij = zellij_imports(&store, &plugin_env);
let zellij = zellij_exports(&store, &plugin_env);
let instance = Instance::new(&module, &zellij.chain_back(wasi)).unwrap();
let start = instance.exports.get_function("_start").unwrap();
// This eventually calls the `.init()` method
// This eventually calls the `.load()` method
start.call(&[]).unwrap();
plugin_map.insert(plugin_id, (instance, plugin_env));
@ -531,10 +542,7 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) {
let event_type = EventType::from_str(&event.to_string()).unwrap();
if (pid.is_none() || pid == Some(i)) && subs.contains(&event_type) {
let update = instance.exports.get_function("update").unwrap();
wasi_write_string(
&plugin_env.wasi_env,
&serde_json::to_string(&event).unwrap(),
);
wasi_write_object(&plugin_env.wasi_env, &event);
update.call(&[]).unwrap();
}
}
@ -549,7 +557,7 @@ pub fn start(mut os_input: Box<dyn OsApi>, opts: CliArgs) {
.call(&[Value::I32(rows as i32), Value::I32(cols as i32)])
.unwrap();
buf_tx.send(wasi_stdout(&plugin_env.wasi_env)).unwrap();
buf_tx.send(wasi_read_string(&plugin_env.wasi_env)).unwrap();
}
PluginInstruction::Unload(pid) => drop(plugin_map.remove(&pid)),
PluginInstruction::Quit => break,

View file

@ -51,6 +51,7 @@ pub enum ScreenInstruction {
NewTab(RawFd),
SwitchTabNext,
SwitchTabPrev,
ToggleActiveSyncPanes,
CloseTab,
GoToTab(u32),
UpdateTabName(Vec<u8>),
@ -158,8 +159,9 @@ impl Screen {
let active_tab_pos = self.get_active_tab().unwrap().position;
let new_tab_pos = (active_tab_pos + 1) % self.tabs.len();
for tab in self.tabs.values() {
for tab in self.tabs.values_mut() {
if tab.position == new_tab_pos {
tab.set_force_render();
self.active_tab_index = Some(tab.index);
break;
}
@ -176,8 +178,9 @@ impl Screen {
} else {
active_tab_pos - 1
};
for tab in self.tabs.values() {
for tab in self.tabs.values_mut() {
if tab.position == new_tab_pos {
tab.set_force_render();
self.active_tab_index = Some(tab.index);
break;
}
@ -188,9 +191,10 @@ impl Screen {
pub fn go_to_tab(&mut self, mut tab_index: usize) {
tab_index -= 1;
let active_tab = self.get_active_tab().unwrap();
if let Some(t) = self.tabs.values().find(|t| t.position == tab_index) {
if t.index != active_tab.index {
let active_tab_index = self.get_active_tab().unwrap().index;
if let Some(t) = self.tabs.values_mut().find(|t| t.position == tab_index) {
if t.index != active_tab_index {
t.set_force_render();
self.active_tab_index = Some(t.index);
self.update_tabs();
self.render();
@ -234,6 +238,7 @@ impl Screen {
for (_, tab) in self.tabs.iter_mut() {
tab.resize_whole_tab(new_screen_size);
}
let _ = self.get_active_tab_mut().map(|t| t.set_force_render());
self.render();
}
@ -295,7 +300,7 @@ impl Screen {
self.update_tabs();
}
fn update_tabs(&self) {
pub fn update_tabs(&self) {
let mut tab_data = vec![];
let active_tab_index = self.active_tab_index.unwrap();
for tab in self.tabs.values() {
@ -303,6 +308,7 @@ impl Screen {
position: tab.position,
name: tab.name.clone(),
active: active_tab_index == tab.index,
is_sync_panes_active: tab.is_sync_panes_active(),
});
}
self.send_plugin_instructions

View file

@ -4,3 +4,9 @@ pub const ZELLIJ_TMP_DIR: &str = "/tmp/zellij";
pub const ZELLIJ_TMP_LOG_DIR: &str = "/tmp/zellij/zellij-log";
pub const ZELLIJ_TMP_LOG_FILE: &str = "/tmp/zellij/zellij-log/log.txt";
pub const ZELLIJ_IPC_PIPE: &str = "/tmp/zellij/ipc";
pub const ZELLIJ_CONFIG_FILE_ENV: &str = "ZELLIJ_CONFIG_FILE";
pub const ZELLIJ_CONFIG_DIR_ENV: &str = "ZELLIJ_CONFIG_DIR";
// TODO: ${PREFIX} argument in makefile
pub const SYSTEM_DEFAULT_CONFIG_DIR: &str = "/etc/zellij";

View file

@ -1,11 +1,15 @@
use serde::{de::DeserializeOwned, Serialize};
use std::{
collections::HashSet,
path::PathBuf,
process,
sync::{mpsc::Sender, Arc, Mutex},
thread,
time::{Duration, Instant},
};
use wasmer::{imports, Function, ImportObject, Store, WasmerEnv};
use wasmer_wasi::WasiEnv;
use zellij_tile::data::{Event, EventType};
use zellij_tile::data::{Event, EventType, PluginIds};
use super::{
pty_bus::PtyInstruction, screen::ScreenInstruction, AppInstruction, PaneId, SenderWithContext,
@ -23,48 +27,53 @@ pub enum PluginInstruction {
#[derive(WasmerEnv, Clone)]
pub struct PluginEnv {
pub plugin_id: u32,
// FIXME: This should be a big bundle of all of the channels
pub send_screen_instructions: SenderWithContext<ScreenInstruction>,
pub send_app_instructions: SenderWithContext<AppInstruction>,
pub send_pty_instructions: SenderWithContext<PtyInstruction>, // FIXME: This should be a big bundle of all of the channels
pub send_pty_instructions: SenderWithContext<PtyInstruction>,
pub send_plugin_instructions: SenderWithContext<PluginInstruction>,
pub wasi_env: WasiEnv,
pub subscriptions: Arc<Mutex<HashSet<EventType>>>,
}
// Plugin API ---------------------------------------------------------------------------------------------------------
pub fn zellij_imports(store: &Store, plugin_env: &PluginEnv) -> ImportObject {
pub fn zellij_exports(store: &Store, plugin_env: &PluginEnv) -> ImportObject {
macro_rules! zellij_export {
($($host_function:ident),+ $(,)?) => {
imports! {
"zellij" => {
"host_subscribe" => Function::new_native_with_env(store, plugin_env.clone(), host_subscribe),
"host_unsubscribe" => Function::new_native_with_env(store, plugin_env.clone(), host_unsubscribe),
"host_open_file" => Function::new_native_with_env(store, plugin_env.clone(), host_open_file),
"host_set_invisible_borders" => Function::new_native_with_env(store, plugin_env.clone(), host_set_invisible_borders),
"host_set_max_height" => Function::new_native_with_env(store, plugin_env.clone(), host_set_max_height),
"host_set_selectable" => Function::new_native_with_env(store, plugin_env.clone(), host_set_selectable),
$(stringify!($host_function) =>
Function::new_native_with_env(store, plugin_env.clone(), $host_function),)+
}
}
}
}
zellij_export! {
host_subscribe,
host_unsubscribe,
host_set_invisible_borders,
host_set_max_height,
host_set_selectable,
host_get_plugin_ids,
host_open_file,
host_set_timeout,
}
}
fn host_subscribe(plugin_env: &PluginEnv) {
let mut subscriptions = plugin_env.subscriptions.lock().unwrap();
let new: HashSet<EventType> = serde_json::from_str(&wasi_stdout(&plugin_env.wasi_env)).unwrap();
let new: HashSet<EventType> = wasi_read_object(&plugin_env.wasi_env);
subscriptions.extend(new);
}
fn host_unsubscribe(plugin_env: &PluginEnv) {
let mut subscriptions = plugin_env.subscriptions.lock().unwrap();
let old: HashSet<EventType> = serde_json::from_str(&wasi_stdout(&plugin_env.wasi_env)).unwrap();
let old: HashSet<EventType> = wasi_read_object(&plugin_env.wasi_env);
subscriptions.retain(|k| !old.contains(k));
}
fn host_open_file(plugin_env: &PluginEnv) {
let path = PathBuf::from(wasi_stdout(&plugin_env.wasi_env).lines().next().unwrap());
plugin_env
.send_pty_instructions
.send(PtyInstruction::SpawnTerminal(Some(path)))
.unwrap();
}
fn host_set_selectable(plugin_env: &PluginEnv, selectable: i32) {
let selectable = selectable != 0;
plugin_env
@ -98,10 +107,54 @@ fn host_set_invisible_borders(plugin_env: &PluginEnv, invisible_borders: i32) {
.unwrap()
}
fn host_get_plugin_ids(plugin_env: &PluginEnv) {
let ids = PluginIds {
plugin_id: plugin_env.plugin_id,
zellij_pid: process::id(),
};
wasi_write_object(&plugin_env.wasi_env, &ids);
}
fn host_open_file(plugin_env: &PluginEnv) {
let path: PathBuf = wasi_read_object(&plugin_env.wasi_env);
plugin_env
.send_pty_instructions
.send(PtyInstruction::SpawnTerminal(Some(path)))
.unwrap();
}
fn host_set_timeout(plugin_env: &PluginEnv, secs: f64) {
// There is a fancy, high-performance way to do this with zero additional threads:
// If the plugin thread keeps a BinaryHeap of timer structs, it can manage multiple and easily `.peek()` at the
// next time to trigger in O(1) time. Once the wake-up time is known, the `wasm` thread can use `recv_timeout()`
// to wait for an event with the timeout set to be the time of the next wake up. If events come in in the meantime,
// they are handled, but if the timeout triggers, we replace the event from `recv()` with an
// `Update(pid, TimerEvent)` and pop the timer from the Heap (or reschedule it). No additional threads for as many
// timers as we'd like.
//
// But that's a lot of code, and this is a few lines:
let send_plugin_instructions = plugin_env.send_plugin_instructions.clone();
let update_target = Some(plugin_env.plugin_id);
thread::spawn(move || {
let start_time = Instant::now();
thread::sleep(Duration::from_secs_f64(secs));
// FIXME: The way that elapsed time is being calculated here is not exact; it doesn't take into account the
// time it takes an event to actually reach the plugin after it's sent to the `wasm` thread.
let elapsed_time = Instant::now().duration_since(start_time).as_secs_f64();
send_plugin_instructions
.send(PluginInstruction::Update(
update_target,
Event::Timer(elapsed_time),
))
.unwrap();
});
}
// Helper Functions ---------------------------------------------------------------------------------------------------
// FIXME: Unwrap city
pub fn wasi_stdout(wasi_env: &WasiEnv) -> String {
pub fn wasi_read_string(wasi_env: &WasiEnv) -> String {
let mut state = wasi_env.state();
let wasi_file = state.fs.stdout_mut().unwrap().as_mut().unwrap();
let mut buf = String::new();
@ -114,3 +167,12 @@ pub fn wasi_write_string(wasi_env: &WasiEnv, buf: &str) {
let wasi_file = state.fs.stdin_mut().unwrap().as_mut().unwrap();
writeln!(wasi_file, "{}\r", buf).unwrap();
}
pub fn wasi_write_object(wasi_env: &WasiEnv, object: &impl Serialize) {
wasi_write_string(wasi_env, &serde_json::to_string(&object).unwrap());
}
pub fn wasi_read_object<T: DeserializeOwned>(wasi_env: &WasiEnv) -> T {
let json = wasi_read_string(wasi_env);
serde_json::from_str(&json).unwrap()
}

View file

@ -14,7 +14,7 @@ use crate::utils::{
};
use client::{boundaries, layout, panes, tab};
use common::{
command_is_executing, errors, os_input_output, pty_bus, screen, start, utils, wasm_vm,
command_is_executing, errors, install, os_input_output, pty_bus, screen, start, utils, wasm_vm,
ApiCommand,
};
use std::io::Write;
@ -45,6 +45,23 @@ pub fn main() {
let mut stream = UnixStream::connect(ZELLIJ_IPC_PIPE).unwrap();
let api_command = bincode::serialize(&ApiCommand::OpenFile(file_to_open)).unwrap();
stream.write_all(&api_command).unwrap();
} else if let Some(crate::cli::ConfigCli::GenerateCompletion { shell }) = opts.option {
let shell = match shell.as_ref() {
"bash" => structopt::clap::Shell::Bash,
"fish" => structopt::clap::Shell::Fish,
"zsh" => structopt::clap::Shell::Zsh,
"powerShell" => structopt::clap::Shell::PowerShell,
"elvish" => structopt::clap::Shell::Elvish,
other => {
eprintln!("Unsupported shell: {}", other);
std::process::exit(1);
}
};
let mut out = std::io::stdout();
CliArgs::clap().gen_completions_to("zellij", shell, &mut out);
} else if let Some(crate::cli::ConfigCli::Setup { .. }) = opts.option {
install::dump_default_config().expect("Failed to print to stdout");
std::process::exit(1);
} else {
let os_input = get_os_input();
atomic_create_dir(ZELLIJ_TMP_DIR).unwrap();

34
src/tests/fixtures/vttest1-0 vendored Normal file
View file

@ -0,0 +1,34 @@
⏎(B ⏎ Welcome to fish, the friendly interactive shell
[?2004h]0;fish /home/aram/code/zellij(B⋊>(B ~/c/zellij(B on vttest-1(B 11:25:27(B   v11:25:27(B  v(B11:25:27(B  ttest(B11:25:27(B  ttest(B11:25:27(B  test(B11:25:27(B  est(B11:25:27(B  st(B11:25:27(B  t(B11:25:27(B  vttest(B11:25:27(B  11:25:27(B  
(B[?2004l]0;vttest /home/aram/code/zellij(B [?1l[?3l[?4l[?5l[?6l[?7h[?8l[?40h[?45lVT100 test program, version 2.7 (20210210)Line speed 38400bd Choose test type:

0. Exit
1. Test of cursor movements
2. Test of screen features
3. Test of character sets
4. Test of double-sized characters
5. Test of keyboard
6. Test of terminal reports
7. Test of VT52 mode
8. Test of VT102 features (Insert/Delete Char/Line)
9. Test of known bugs
10. Test of reset and self-test
11. Test non-VT100 (e.g., VT220, XTERM) terminals
12. Modify test-parameters
Enter choice number (0 - 12): 1
[?3l#8****************************************************************************************************************************************************************+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D+M+M+M+M+M+M+M+M+M+M+M+M+M+M+M+M+M+M+M+M+M+M**E**E**E**E**E**E**E**E**
**
**
**
**
**
**
**
**
**
**
**
**
**
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++      The screen should be cleared, and have an unbroken bor-der of *'s and +'s around the edge, and exactly in themiddle there should be a frame of E's around this textwith one (1) free position around it. Push <RETURN>

48
src/tests/fixtures/vttest1-1 vendored Normal file

File diff suppressed because one or more lines are too long

76
src/tests/fixtures/vttest1-2 vendored Normal file

File diff suppressed because one or more lines are too long

137
src/tests/fixtures/vttest1-3 vendored Normal file

File diff suppressed because one or more lines are too long

112
src/tests/fixtures/vttest1-4 vendored Normal file

File diff suppressed because one or more lines are too long

113
src/tests/fixtures/vttest1-5 vendored Normal file

File diff suppressed because one or more lines are too long

View file

@ -1,6 +1,6 @@
[package]
name = "zellij-tile"
version = "1.0.0"
version = "1.1.0"
authors = ["Brooks J Rady <b.j.rady@gmail.com>"]
edition = "2018"
description = "A small client-side library for writing Zellij plugins"

View file

@ -23,13 +23,15 @@ pub enum Key {
Esc,
}
#[derive(Debug, Clone, EnumDiscriminants, ToString, Serialize, Deserialize)]
#[derive(Debug, Clone, PartialEq, EnumDiscriminants, ToString, Serialize, Deserialize)]
#[strum_discriminants(derive(EnumString, Hash, Serialize, Deserialize))]
#[strum_discriminants(name(EventType))]
#[non_exhaustive]
pub enum Event {
ModeUpdate(ModeInfo),
TabUpdate(Vec<TabInfo>),
KeyPress(Key),
Timer(f64),
}
/// Describes the different input modes, which change the way that keystrokes will be interpreted.
@ -126,7 +128,7 @@ impl Default for Palette {
/// Represents the contents of the help message that is printed in the status bar,
/// which indicates the current [`InputMode`] and what the keybinds for that mode
/// are. Related to the default `status-bar` plugin.
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
#[derive(Default, Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct ModeInfo {
pub mode: InputMode,
// FIXME: This should probably return Keys and Actions, then sort out strings plugin-side
@ -134,10 +136,17 @@ pub struct ModeInfo {
pub palette: Palette,
}
#[derive(Debug, Default, Clone, Deserialize, Serialize)]
#[derive(Debug, Default, Clone, PartialEq, Eq, Hash, Deserialize, Serialize)]
pub struct TabInfo {
/* subset of fields to publish to plugins */
pub position: usize,
pub name: String,
pub active: bool,
pub is_sync_panes_active: bool,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Deserialize, Serialize)]
pub struct PluginIds {
pub plugin_id: u32,
pub zellij_pid: u32,
}

View file

@ -1,4 +1,4 @@
use serde::de::DeserializeOwned;
use serde::{de::DeserializeOwned, Serialize};
use std::{io, path::Path};
use crate::data::*;
@ -6,12 +6,12 @@ use crate::data::*;
// Subscription Handling
pub fn subscribe(event_types: &[EventType]) {
println!("{}", serde_json::to_string(event_types).unwrap());
object_to_stdout(&event_types);
unsafe { host_subscribe() };
}
pub fn unsubscribe(event_types: &[EventType]) {
println!("{}", serde_json::to_string(event_types).unwrap());
object_to_stdout(&event_types);
unsafe { host_unsubscribe() };
}
@ -21,21 +21,31 @@ pub fn set_max_height(max_height: i32) {
unsafe { host_set_max_height(max_height) };
}
pub fn set_selectable(selectable: bool) {
unsafe { host_set_selectable(if selectable { 1 } else { 0 }) };
}
pub fn set_invisible_borders(invisible_borders: bool) {
unsafe { host_set_invisible_borders(if invisible_borders { 1 } else { 0 }) };
}
pub fn set_selectable(selectable: bool) {
unsafe { host_set_selectable(if selectable { 1 } else { 0 }) };
// Query Functions
pub fn get_plugin_ids() -> PluginIds {
unsafe { host_get_plugin_ids() };
object_from_stdin()
}
// Host Functions
pub fn open_file(path: &Path) {
println!("{}", path.to_string_lossy());
object_to_stdout(&path);
unsafe { host_open_file() };
}
pub fn set_timeout(secs: f64) {
unsafe { host_set_timeout(secs) };
}
// Internal Functions
#[doc(hidden)]
@ -45,12 +55,19 @@ pub fn object_from_stdin<T: DeserializeOwned>() -> T {
serde_json::from_str(&json).unwrap()
}
#[doc(hidden)]
pub fn object_to_stdout(object: &impl Serialize) {
println!("{}", serde_json::to_string(object).unwrap());
}
#[link(wasm_import_module = "zellij")]
extern "C" {
fn host_subscribe();
fn host_unsubscribe();
fn host_open_file();
fn host_set_max_height(max_height: i32);
fn host_set_selectable(selectable: i32);
fn host_set_invisible_borders(invisible_borders: i32);
fn host_get_plugin_ids();
fn host_open_file();
fn host_set_timeout(secs: f64);
}