diff --git a/content/news/welcome-screen-pipes-filepicker.md b/content/news/welcome-screen-pipes-filepicker.md new file mode 100644 index 0000000..dbd6160 --- /dev/null +++ b/content/news/welcome-screen-pipes-filepicker.md @@ -0,0 +1,104 @@ +--- +author: "Aram Drevekenin" +authorlink: "https://hachyderm.io/@imsnif" +date: 2024-16-04 +linktitle: "Zellij 0.40.0: Welcome Screen, Filepicker, Pipes, Plugin Aliases" +type: +- post +- posts +title: "Zellij 0.40.0: Welcome Screen, Filepicker, Pipes, Plugin Aliases" +type: +images: ["/img/welcome-screen-preview.png"] +description: "A new welcome screen to facilitate session management, a new filepicker, a powerful new concept called pipes and lots of long awaited features" +alttext: "An image of the Zellij welcome screen with the Zellij filepicker opened to select the location of the session" +weight: 10 +--- +{{
}} +Zellij 0.40.0 has just been released! [Grab it while it's hot!](https://github.com/zellij-org/zellij/releases/tag/v0.40.0) + +Some highlights: +- [Welcome Screen](#welcome-screen) +- [New Filepicker](#new-strider--filepicker) +- [Pipes](#pipes) +- [Open Floating Panes at Specific Coordinates](#open-floating-panes-at-specific-coordinates) +- [Rearrange Tabs](#rearrange-tabs) +- [Disconnect other Clients](#disconnect-other-clients) +- [Plugin Aliases](#plugin-aliases) +- [New Possible Keys to Bind](#new-possible-keys-to-bind) +- [Start session in the background](#start-session-in-the-background) +- [Performance Improvements](#performance-improvements) +- [Do you like Zellij?](#do-you-like-zellij-) ❤️ + +## Welcome Screen +{{
}} +This new release introduces the "welcome screen". The welcome screen is a friendly menu, intended to be run on terminal startup and allow users to either: +1. Start a new session (optionally with a specific name or in a chosen folder) +2. Attach to a running session +3. Resurrect an exited session + +Learn more about [session management](/tutorials/session-management). + +## New Strider / Filepicker +{{
}} +This release includes a complete rework of Zellij's built-in filepicker, Strider. The filepicker allows users to quickly browse through their filesystem, opening files in their default editor in new Zellij panes or opening a terminal in a specific location. + +With the help of [pipes](#pipes), one can use this filepicker to interactively choose a file or folder in the filesystem and pipe the result to another command through a traditional shell pipe. For example: + +```bash +zpipe filepicker | xargs -i cp {} my-chosen-file +``` + +The filepicker can also be used from within other plugins to offload filepicking functionality rather than have the plugin implement it on its own. In fact, this is exactly what the welcome screen does in the example at the top of this post. + +Learn more about [the filepicker](/tutorials/filepicker). + +## Pipes +Zellij pipes are a new way to send messages to plugins and allow plugins to communicate with each other. + +Messages can be sent to plugins through the CLI: (eg. `zpipe my-plugin hi!`), from a keybinding or indeed from another plugin. A destination plugin that does not exist will be loaded on the first pipe message. + +Pipes also integrate seamlessly with existing shell pipes, providing flow control and giving plugin authors the ability to visualize data from the command line, allow users to pause a command line pipe mid-stream on certain messages or on a keystroke. We believe this functionality will help utilize the full 2 dimensions of the terminal window as never before, popping up floating panes in certain conditions and creating a many-to-many windowed pipeline. We look forward to seeing what plugin authors come up with! + +[Learn more about Pipes](/documentation/plugin-pipes.html) + +## Open Floating Panes at Specific Coordinates +A much requested feature after the introduction of floating panes, was to be able to open floating panes at specific coordinates and at specific sizes. Ths is now possible from the CLI, from plugins or from a keybinding (either with fixed numbers or percentage of the viewport): + +```sh +zellij run --floating --width 50 --height 20% -x 10% -y 50% -- htop +``` + +## Rearrange Tabs +Thanks to a community contribution, it's now possible to change the position of tabs. One can move the active tab left or right, by default with `Alt i` or `Alt o`. + +## Disconnect other Clients +Zellij, as a true multiplayer application, allows more than one user to attach to a running session. When this happens, each user gets their own cursor and the UI indicates in which pane or tab they are focused. + +Since by necessity the smallest screen width/height is used in such cases, it is sometimes desirable to log out other users from the session. + +This is now possible through the `session-manager`: `Ctrl o` to open the session manager, and then `Ctrl x` to disconnect other users. + +## Plugin Aliases +This version introduces "Plugin Aliases" which are a way to shorten the long plugin URLs (eg. `https://example.com/my-plugin.wasm`, or `file:/home/aram/code/plugin/my-plugin.wasm`) to something more memorable (eg. `filter` or `filepicker`). These aliases can be defined in the [configuration file](/documentation/configuration.html), and used wherever plugin URLs can be used: to launch plugins from the CLI, from layouts or from other plugins. + +Aliases can also be a convenient way to swap in the built-in plugins for a custom implementation (eg. using the excellent [zjstatus](https://github.com/dj95/zjstatus), instead of the built-in `compact` bar). Indeed, the `filepicker` described above is an internal alias for the built-in `Strider` plugin, and can be swapped out for a custom implementation of the filepicker using the same [contract](/documentation/filepicker-alias.html). + +Read more about [Plugin Aliases](/documentation/plugin-aliases.html). + +## New Possible Keys to Bind +Thanks to some community contributions, it is now possible to bind `Ctrl`/`Alt` + Function keys (eg. `Ctrl F1`), as well as `Ctrl Space`. We as Zellij maintainers are aware that colliding keybindings are a big problem for many users and intend to fully and finally address this issue in the next version after this one. + +## Start session in the background +nother much requested feature was added in this release: it's now possible to start a new Zellij session in the background with the new `zellij attach --create-background` flag. + +## Performance Improvements +This version introduces two major performance improvements: +* Line wrapping of extremely long (10M+) lines is now significantly faster thanks to a community contribution. +* Rendering of full-screen terminal applications is now much smoother thanks to the implementation of CSI 2026 (synchronized renders) in those terminals that support it. + +## Do you like Zellij? ❤️ +Me too! So much so that I spend 100% of my time developing and maintaining it and have no other income. + +Zellij will always be free and open-source. Zellij will never contain ads or collect your data. + +So if the tool gives you value and you are able, please consider [a recurring monthly donation](https://github.com/sponsors/imsnif) of 5-10$ to help me pay my bills. There are Zellij stickers in it for you! diff --git a/content/screencasts.md b/content/screencasts.md index 28d0caf..4bf8d6a 100644 --- a/content/screencasts.md +++ b/content/screencasts.md @@ -18,3 +18,15 @@ Finally, we'll talk about editing a pane's scrollback with our own `$EDITOR` This tutorial walks you through creating Zellij [layouts](/documentation/creating-a-layout.html) to automate tasks and workflows. Layouts describe a pre-defined set of panes and tabs with different terminals, commands and plugins. They can be great to automate and formalize workflows and tasks. + +### [Session Management](/tutorials/session-management) +[{{
}}](/tutorials/session-management) +Do you find yourself jumping between tasks a lot? + +When using the terminal, we often open new terminal windows for different tasks, ending up with a mess of open terminals. This can lead to difficulty and overhead when switching contexts: we often end up searching for commands through our shell history, keeping complex notes and having to rebuild our environment every time we return to a task. Zellij can solve these problems and more for us with the `session-manager` and `welcome-screen`. + +### [Filepicker](/tutorials/filepicker) +[{{
}}](/tutorials/filepicker) +Stop wasting time traversing through your filesystem manually! + +Use the Zellij filepicker to get a dynamic file exploration experience, complete with fuzzy-finding and autocompletion right in your terminal. diff --git a/content/tutorials/basic-functionality.md b/content/tutorials/basic-functionality.md index 44d1f27..ebd5b2c 100644 --- a/content/tutorials/basic-functionality.md +++ b/content/tutorials/basic-functionality.md @@ -17,6 +17,7 @@ You need not be a terminal developer to benefit from this tutorial. - [Using Floating Panes](#using-floating-panes) - [Starting Command Panes from the CLI](#starting-command-panes-from-the-cli) - [Editing Pane Scrollback with your own $EDITOR](#editing-the-scrollback-with-your-own-editor) +- [Do you like Zellij?](#do-you-like-zellij-) ## Getting Started {{
}} @@ -77,4 +78,9 @@ Then, let's save the resulting lines to a different file (in vim: `:s /tmp/my-ot ## Finally Here we learned the very basics of Zellij usage. Be they classic multiplexer features such as splitting panes or slightly more advanced workspace features such as managing Command Panes and editing scrollback. -If you liked this tutorial, consider starring us on [*Github*](https://github.com/zellij-org/zellij) or following us [*Twitter*](https://twitter.com/Zellij_dev). +## Do you like Zellij? ❤️ +Me too. So much so that I spend 100% of my time developing and maintaining it and have no other income. + +Zellij will always be free and open-source. Zellij will never contain ads or collect your data. + +If the tool gives you value and you are able, please consider [a recurring monthly donation](https://github.com/sponsors/imsnif) of 5-10$ to help me pay my bills. There are Zellij stickers in it for you! diff --git a/content/tutorials/filepicker.md b/content/tutorials/filepicker.md new file mode 100644 index 0000000..740640d --- /dev/null +++ b/content/tutorials/filepicker.md @@ -0,0 +1,94 @@ +--- +title: "The Zellij Filepicker" +images: ["/img/tutorial-4-preview.png"] +description: "How to use Zellij to manage your sessions in the terminal" +linktitle: "How to use Zellij to manage your sessions in the terminal" +--- +{{}} + +This tutorial shows how to use the Zellij filepicker, also known as Strider. + +*The video screencast and the tutorial contain the same content, with the video screencast also containing some concrete examples of the subject material for inspiration.* + +## Why use the Zellij filepicker? +The Zellij filepicker is a built-in plugin that will allow you to dynamically traverse your filesystem, optionally using fuzzy finding to look for files or folders in a deterministic way. It's much faster than doing the usual cycle of "cd", "ls", look for folder, "cd" and "ls" again. + +It's also versatile: you can launch the filepicker directly and close it once you've chosen a file, you can keep it open to open multiple files and you can even insert it into traditional shell pipelines to pipe your chosen path into a different command. + +## What we'll cover +- [Basic usage of the filepicker](#basic-usage-of-the-filepicker) +- [How to launch the filepicker through a keybinding](#how-to-launch-the-filepicker-through-a-keybinding) +- [How to launch the filepicker from the command line](#how-to-launch-the-filepicker-from-the-command-line) +- [How to get an IDE-like experience with the filepicker](#how-to-get-an-ide-like-experience-with-the-filepicker) +- [How to pipe the filepicker's output to another command](#how-to-pipe-the-filepickers-output-to-another-command) +- [Do you like Zellij?](#do-you-like-zellij-) + +## Basic usage of the filepicker +{{
}} +When launching the filepicker, it will start in the working directory of the focused pane. We are presented with a list of the files and folders, allowing us to traverse through them with the arrow keys, backspace and tab. + +When we select a file or folder (either with the right arrow or with ``), it will be added to our `PATH:`. When we press ``, the filepicker will open whatever is in the `PATH:` either in our default editor if it's a file or open a terminal to this location if it's a folder. + +We can toggle hidden files on and off with `Ctrl e`. + +## How to launch the filepicker through a keybinding +To launch the filepicker through a keyboard shortcut, we'll need to add the following lines (starting from `bind`) to the `shared_except "locked"` section of our `keybindings` in the [configuration file](/documentation/configuration.html). + +For more info, please see [configuring keybindings](/documentation/keybindings.html). + +```javascript +shared_except "locked" { +// ... + bind "Alt f" { + LaunchPlugin "filepicker" { + // floating true // uncomment this to have the filepicker opened in a floating window + close_on_selection true // comment this out to have the filepicker remain open even after selecting a file + }; + } +} +``` + +## How to launch the filepicker from the command line +To launch the filepicker from the command line: +```bash +zellij plugin -- filepicker +``` + +## How to get an IDE-like experience with the filepicker +{{
}} +We can get an "IDE-like" experience of having the filepicker always open on the side by using the "strider" built in layout. + +We can either start a session with it from the command line: +```bash +zellij -l strider +``` + +Start a session with it through the [welcome screen](/tutorials/session-management). + +Or, we could open a new tab with it in an existing session: +```bash +zellij action new-tab -l strider +``` + +## How to pipe the filepicker's output to another command +We can also pipe the output of the filepicker - our chosen file or folder - into another command with a traditional CLI pipeline. + +To do this, we launch the filepicker through the `zpipe` alias (or using `zellij pipe`): +```bash +zpipe filepicker +zellij pipe -p filepicker +``` +This will open the filepicker, allowing us to choose a file or folder. Once we press ``, the filepicker will close and print our chosen path to `STDOUT`. This means that we can use it to select paths dynamically and send them to other commands, for example: + +```bash +zpipe filepicker | xargs -i cp {} my-chosen-file +``` +This will open the filepicker so that we can select a file and then copy this file to `my-chosen-file` in our local directory. + + +## Do you like Zellij? ❤️ +Me too. So much so that I spend 100% of my time developing and maintaining it and have no other income. + +Zellij will always be free and open-source. Zellij will never contain ads or collect your data. + +If the tool gives you value and you are able, please consider [a recurring monthly donation](https://github.com/sponsors/imsnif) of 5-10$ to help me pay my bills. There are Zellij stickers in it for you! diff --git a/content/tutorials/layouts.md b/content/tutorials/layouts.md index 4e38cf7..492b0f7 100644 --- a/content/tutorials/layouts.md +++ b/content/tutorials/layouts.md @@ -25,6 +25,7 @@ The layout we're creating is for a default Rust project. Rust is used as an exam - [Edit and Command Panes](#edit-and-command-panes) - [Changing Pane Orientation](#changing-pane-orientation) - [Avoiding Repetition with Pane Templates](#avoiding-repetition-with-pane-templates) +- [Do you like Zellij?](#do-you-like-zellij-) ## Getting Started To follow along, you can clone [the repository](https://github.com/imsnif/zellij-screencast-2). @@ -221,3 +222,10 @@ layout { ## Conclusion and Further Reading Here we learned how to create a basic layout to facilitate working with a Rust project through the terminal. There are plenty additional layout features to explore, such as tabs, tab_templates and cwd composition. Check out more in the [official docs](/documentation/creating-a-layout.html). + +## Do you like Zellij? ❤️ +Me too. So much so that I spend 100% of my time developing and maintaining it and have no other income. + +Zellij will always be free and open-source. Zellij will never contain ads or collect your data. + +If the tool gives you value and you are able, please consider [a recurring monthly donation](https://github.com/sponsors/imsnif) of 5-10$ to help me pay my bills. There are Zellij stickers in it for you! diff --git a/content/tutorials/session-management.md b/content/tutorials/session-management.md new file mode 100644 index 0000000..c0f4cde --- /dev/null +++ b/content/tutorials/session-management.md @@ -0,0 +1,94 @@ +--- +title: "Session Management with Zellij" +images: ["/img/tutorial-3-preview.png"] +description: "How to use Zellij to manage your sessions in the terminal" +linktitle: "How to use Zellij to manage your sessions in the terminal" +--- +{{}} + +This tutorial shows how to use Zellij to manage sessions in the terminal. + +*The video screencast and the tutorial contain the same content, with the video screencast also containing some concrete examples of the subject material for inspiration.* + +## Why use Zellij to manage sessions? +Do you find yourself jumping between tasks a lot? + +When using the terminal, we often open new terminal windows for different tasks, ending up with a mess of open terminals. This can lead to difficulty and overhead when switching contexts: we often end up searching for commands through our shell history, keeping complex notes and having to rebuild our environment every time we return to a task. Zellij can solve these problems and more for us with the `session-manager` and `welcome-screen`. + +## What we'll cover +- [The Zellij Welcome Screen](#the-zellij-welcome-screen) +- [Setting up the Welcome Screen to Open on Terminal Startup](#setting-up-the-welcome-screen-to-open-on-terminal-startup) +- [Starting a new session in a specific folder](#starting-a-new-session-in-a-specific-folder) +- [Starting a new session in a specific folder and layout from the session-manager](#starting-a-new-session-in-a-specific-folder-and-layout-from-the-session-manager) +- [Switching between running sessions to manage context](#switching-between-running-sessions-to-manage-context) +- [Resurrecting exited sessions to revive old contexts](#resurrecting-exited-sessions-to-revive-old-contexts) +- [Do you like Zellij?](#do-you-like-zellij-) + +## The Zellij Welcome Screen +{{
}} +The Zellij `welcome-screen` is a friendly start-up menu that allows users to: +1. Start a new sessions, optionally in a specific folder and/or with a specific [layout](/tutorials/layouts). +2. Attach to currently running sessions and switch between them. +3. Resurrect exited sessions, creating a new session from old context. + +## Setting up the Welcome Screen to open on Terminal startup +In most terminals, it's possible to set up the Zellij `welcome-screen` to start up every time the terminal window is opened. Doing this will create a powerful integration between Zellij and your favorite terminal, allowing Zellij to manage not only your panes, layouts and tabs - but also your sessions and contexts. + +### In Alacritty +Open the Alacritty [configuration file](https://github.com/alacritty/alacritty?tab=readme-ov-file#configuration) and replace the `[shell]` section with the following: +```toml +[shell] +program = "zellij" +args = ["-l", "welcome"] +``` + +### In gnome-terminal +Follow [these instructions](https://help.gnome.org/users/gnome-terminal/stable/pref-custom-command.html.en) and pass the command `zellij -l welcome`. + +### In Konsole +In the Settings menu, start a new `profile` and set the command to be `zellij -l welcome`. Set it as the Default profile and restart Konsole. + +### In WezTerm +Set the `config.default_prog` to: +```lua +config.default_prog = { 'zellij', '-l', 'welcome' } +``` +[See the WezTerm documentation](https://wezfurlong.org/wezterm/config/launch.html#changing-the-default-program) for more information. + +## Starting a new session in a specific folder +{{
}} +To start a new session in a specific folder, we: +1. Optionally type in a session name +2. Press `Ctrl-f` to open up the `filepicker`, explore our filesystem to search for the new folder, entering folders with `` and once we're inside the folder we want, pressing ``. The folder will appear in the `New session folder:` section on the bottom of the `New session` form. +3. We choose a [layout](/tutorials/layouts) or stick with the `default` layout. +4. Press `` to start the new session + +## Starting a new session in a specific folder and layout from the session-manager +{{
}} + +Similarly, to start a new session with a specific layout - we follow the above steps but choose a different layout instead of the `default` one. + +We could either choose one of the built-in layouts (for example: `compact`), or one of our custom layouts that we saved to the `layouts` subfolder of the [Zellij configuration](https://zellij.dev/documentation/configuration#where-does-zellij-look-for-the-config-file). For more info on creating layouts, please see the [layout screencast and tutorial](/tutorials/layouts). + +## Switching between running sessions to manage context +{{
}} +It's possible to attach to a currently running session either from the `welcome-screen` or from the `session-manager` (exactly like the `welcome-screen` only running inside an existing Zellij session). To launch the `session-manager`, press `Ctrl o` + `w`. + +In the menu, navigate with `` to `Attach to Session` and select the session you would like to attach to from the list. + +It's very helpful to keep different context for different tasks in separate sessions, thus allowing you to label them, switch between them at will and even resurrect them after a reboot. + +## Resurrecting exited sessions to revive old contexts +{{
}} +When a Zellij session exits, Zellij keeps its metadata around: meaning the layout of the panes and tabs as well as which program was running in each pane or tab. This can be very useful to label and keep around old contexts. + +Imagine you were in a debugging session and opened several panes, each one with a specific command that helped you discover a problem in your system. Once you've solved this problem, instead of closing the session immediately, you can rename: start the `session-manager` with `Ctrl o` + `w`, rename the session with `Ctrl r` to a descriptive name and then quit Zellij with `Ctrl q`. + +You can then in the future open a new terminal window to the `welcome-screen`, press `` until you reach `Resurrect Session`, search through your sessions for the descriptive name you gave the old session and press `` to have Zellij resurrect ths session and rebuild your own context. Allowing you to solve the same problem again rather than struggling to remember your steps from the past. + +## Do you like Zellij? ❤️ +Me too. So much so that I spend 100% of my time developing and maintaining it and have no other income. + +Zellij will always be free and open-source. Zellij will never contain ads or collect your data. + +If the tool gives you value and you are able, please consider [a recurring monthly donation](https://github.com/sponsors/imsnif) of 5-10$ to help me pay my bills. There are Zellij stickers in it for you! diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md index 1953c1d..a5a514f 100644 --- a/docs/src/SUMMARY.md +++ b/docs/src/SUMMARY.md @@ -23,6 +23,7 @@ - [Zellij Edit](./zellij-edit.md) - [Zellij Action](./cli-actions.md) - [Zellij Plugin](./zellij-plugin.md) + - [Zellij Pipe](./zellij-pipe.md) - [Layouts](./layouts.md) - [Creating a Layout](./creating-a-layout.md) - [Swap Layouts](./swap-layouts.md) @@ -40,11 +41,20 @@ - [Reading from the Filesystem](./plugin-api-file-system.md) - [Logging](./plugin-api-logging.md) - [Workers for Async Tasks](./plugin-api-workers.md) + - [Pipes for communicating with and between plugins](./plugin-pipes.md) - [Developing a Plugin](./plugin-development.md) - [Development Environment](./plugin-dev-env.md) - [Plugin Lifecycle](./plugin-lifecycle.md) - [Rendering a UI](./plugin-ui-rendering.md) - [Upgrading and Backwards Compatibility](./plugin-upgrading.md) + - [Plugin Aliases](./plugin-aliases.md) + - [The tab-bar alias](./tab-bar-alias.md) + - [The status-bar alias](./status-bar-alias.md) + - [The strider alias](./strider-alias.md) + - [The compact-bar alias](./compact-bar-alias.md) + - [The session-manager alias](./session-manager-alias.md) + - [The welcome-screen alias](./welcome-screen-alias.md) + - [The filepicker alias](./filepicker-alias.md) - [Example Plugins](./plugin-examples.md) - [Developing a Plugin in Other Languages](./plugin-other-languages.md) - [Plugin Upgrade Guide for version 0.38.0](./plugin-upgrade-0.38.0.md) diff --git a/docs/src/compact-bar-alias.md b/docs/src/compact-bar-alias.md new file mode 100644 index 0000000..761fdbb --- /dev/null +++ b/docs/src/compact-bar-alias.md @@ -0,0 +1,6 @@ +# The compact-bar alias + +This alias, by default translated to the internal `zellij:compact-bar` plugin url, represents the compact-bar loaded in the compact layout on the bottom of the screen. + +## Contract +Zellij loads this compact bar with a height of `1` and a width the size of the user's full screen. Zellij has no other expectations from this plugin, even though users will probably expect at least the input mode and the tabs be shown. diff --git a/docs/src/controlling-zellij-through-cli.md b/docs/src/controlling-zellij-through-cli.md index 9e909a7..01d2477 100644 --- a/docs/src/controlling-zellij-through-cli.md +++ b/docs/src/controlling-zellij-through-cli.md @@ -18,6 +18,8 @@ For starting commands in a new pane, see [Zellij Run](./zellij-run.md). For editing a file in a new pane with your own editor, see [Zellij Edit](./zellij-edit.md). +For loading and controlling plugins, see [Zellij Plugin](./zellij-plugin.md) and [Zellij Pipe](./zellij-pipe.md). + ### Completions For convenience, zellij provides cli completions for popular shells. diff --git a/docs/src/filepicker-alias.md b/docs/src/filepicker-alias.md new file mode 100644 index 0000000..dd32beb --- /dev/null +++ b/docs/src/filepicker-alias.md @@ -0,0 +1,27 @@ +# The filepicker alias + +This alias, by default translated to the internal `zellij:strider` plugin url with the `cwd "/"` configuration, is used by various plugins to allow users to traverse their filesystem and select files or folders for various purposes. + +For example, the [session-manager](./session-manager-alias.md) and [welcome-screen](./welcome-screen-alias.md) use the filepicker to allow users to choose the working directory for the new session they would like to start. + +## Contract +Zellij loads the filepicker using a [pipe](./plugin-pipes.md). It sends it a private message with the `filepicker` message name. + +### If the message originates from another plugin +Zellij expects the filepicker to: +1. Open a new pipe with the originating plugin's ID (it receives this ID as part of the `PipeMessage`) as its destination. +2. The message name should be `filepicker_result` +3. The message `args` should be the same args sent in the original message (if any). +4. The message payload should be the path the user chose as clear text. + +### If the message originates from the CLI +Zellij expects the filepicker to: +1. Block the CLI pipe input to give the user time to choose a file using [`block_cli_pipe_input`](./plugin-api-commands.md#block_cli_pipe_input). +2. Output the the path the user chose as clear text with the [`cli_pipe_output`](./plugin-api-commands.md#cli_pipe_output) command. +3. Unblock the CLI pipe input once the user chose a path with [`unblock_cli_pipe_input`](./plugin-api-commands.md#unblock_cli_pipe_input). + +## User expectations +The user will likely expect the plugin to either close itself or hide itself once the file has been chosen, so their focus will return the pane which originated this request (be it another plugin or a terminal if this request was made through a CLI pipe). + +## Example +See [the strider plugin's implementation](https://github.com/zellij-org/zellij/blob/main/default-plugins/strider/src/main.rs#L129). diff --git a/docs/src/keybindings-possible-actions.md b/docs/src/keybindings-possible-actions.md index cd0d467..ef8fba6 100644 --- a/docs/src/keybindings-possible-actions.md +++ b/docs/src/keybindings-possible-actions.md @@ -446,3 +446,13 @@ or: ```javascript bind "a" { WriteChars "hi there!"; } ``` + +## `MoveTab` + + Change the position of the active tab either left or right. + +**Required arguments**: the direction, either "Left" or "Right" + +```javascript + bind "a" { MoveTab "Left"; } +``` diff --git a/docs/src/plugin-aliases.md b/docs/src/plugin-aliases.md new file mode 100644 index 0000000..0e74cd3 --- /dev/null +++ b/docs/src/plugin-aliases.md @@ -0,0 +1,24 @@ +# Plugin Aliases +Plugin aliases are a dictionary between an arbitrary string (eg. `filepicker`) and a non-alias [plugin url](./plugin-loading.md), with optional [plugin configuration](./plugin-api-configuration.md). They can be configured in the [Zellij configuration file](./configuration.md) under the `plugins` block. + +Here's the default aliases: +```javascript +plugins { + tab-bar location="zellij:tab-bar" + status-bar location="zellij:status-bar" + strider location="zellij:strider" + compact-bar location="zellij:compact-bar" + session-manager location="zellij:session-manager" + welcome-screen location="zellij:session-manager" { + welcome_screen true + } + filepicker location="zellij:strider" { + cwd "/" + } +} +``` +With this plugins block, whenever the bare `tab-bar` is used to refer to a plugin (be it in a [layout](./layouts.md), from the [command line](./zellij-plugin.md), from a [keybinding](./keybindings.md) or from [another plugin](./plugin-pipes.md)), Zellij will translate it to the internal `zellij:tab-bar` url. Whenever the bare `filepicker` url is used to refer to a plugin, Zellij will translate it to the built-in `zellij:strider` url will be used with the `cwd "/"` configuration. + +Aliases can be added to this block or changed to swap the default built-in plugins to other implementations. Removing the default aliases entirely might cause Zellij not to function as expected. + +When swapping the default aliases for custom plugins, it's important that these plugins implement the basic contract Zellij (and indeed, other plugins) expect of them. The following sections describe the contract for each default alias. diff --git a/docs/src/plugin-api-commands.md b/docs/src/plugin-api-commands.md index d2ea8f6..72f27fc 100644 --- a/docs/src/plugin-api-commands.md +++ b/docs/src/plugin-api-commands.md @@ -319,9 +319,72 @@ Changes the name (the title that appears in the UI) of the tab with the specifie ## switch_session * Requires the `ChangeApplicationState` [permission](./plugin-api-permissions.md) -Change the session to the specified one +Change the session to the specified one, creating it if it does not exist ## switch_session_with_focus * Requires the `ChangeApplicationState` [permission](./plugin-api-permissions.md) -Change the session to the specified one, focusing on a tab or a pane inside that session +Change the session to the specified one (creating it if it does not exist), if it does exist - focusing on a tab or a pane inside that session + +## switch_session_with_layout +* Requires the `ChangeApplicationState` [permission](./plugin-api-permissions.md) + +Change the session to the specified one, creating it if it does not exist, using a specified layout and optionally also a cwd (working directory). + +## block_cli_pipe_input +* Requires the `ReadCliPipes` [permission](./plugin-api-permissions.md) + +Block the input side of a pipe, will only be released once this or another plugin unblocks it + +(By default, pipes are unblocked after a plugin has handled a message unless this method is explicitly called). + +## unblock_cli_pipe_input +* Requires the `ReadCliPipes` [permission](./plugin-api-permissions.md) + +Unblock the input side of a pipe, requesting the next message be sent if there is one + +## cli_pipe_output +* Requires the `ReadCliPipes` [permission](./plugin-api-permissions.md) + +Send output to the output side of a pipe, ths does not affect the input side of same pipe + +## pipe_message_to_plugin +* Requires the `MessageAndLaunchOtherPlugins` [permission](./plugin-api-permissions.md) + +Send a message to a plugin, it will be launched if it is not already running + +## delete_dead_session +* Requires the `ChangeApplicationState` [permission](./plugin-api-permissions.md) + +Delete a dead session (one that is not running but can be resurrected) with a specific name + +## delete_all_dead_sessions +* Requires the `ChangeApplicationState` [permission](./plugin-api-permissions.md) + +Delete all dead sessions (sessions that are not running but can be resurrected) + +## rename_session +* Requires the `ChangeApplicationState` [permission](./plugin-api-permissions.md) + +Rename the current session to a specific name + +## disconnect_other_clients +* Requires the `ChangeApplicationState` [permission](./plugin-api-permissions.md) + +Disconnect all other clients attached to this session except the one making this call + +## kill_sessions +* Requires the `ChangeApplicationState` [permission](./plugin-api-permissions.md) + +Kill all Zellij sessions in the list (can contain one or more session names) + +## scan_host_folder +This is a stop-gap method that allows plugins to scan a folder on the `/host` [filesystem](./plugin-api-file-system.md) and get back a list of files. The reason this is done through the API is that at the time of development, doing this through our WASI runtime is extremely slow. We hope this method will not be needed in the future. + +## dump_session_layout +* Requires the `ReadApplicationState` [permission](./plugin-api-permissions.md) + +Request Zellij send back the serialized layout (in KDL format) of the current session. The layout will be sent back as a [`CustomMessage`](./plugin-api-events.md#custom-message) with the `session_layout` name and the stringified layout as the message payload. + +## close_self +Will close the plugin and its pane. If the plugin is the only selectable pane in the session, the session will also exit. diff --git a/docs/src/plugin-loading.md b/docs/src/plugin-loading.md index 18e5228..8b74129 100644 --- a/docs/src/plugin-loading.md +++ b/docs/src/plugin-loading.md @@ -1,8 +1,9 @@ # Loading Plugins -Plugins can either be loaded through a [Layout](./creating-a-layout.md#plugin), through the [command line](./cli-actions.md#launch-or-focus-plugin), or from a [keybinding](keybindings-possible-actions.md#launchorfocusplugin). +Plugins can either be loaded through a [Layout](./creating-a-layout.md#plugin), through the [command line](./zellij-plugin.md), or from a [keybinding](keybindings-possible-actions.md#launchorfocusplugin). ## Plugin URL schema -Plugins are referred to by URLs. Currently there are two supported schemas: +Plugins are referred to by URLs. Currently there are four supported schemas: 1. The file schema: `file:/absolute/path/to/my/plugin.wasm` - for reading plugins from the local HD 2. The built-in `zellij:` schema (eg. `zellij:tab-bar`) for loading built-in zellij plugins. 3. Urls (`http(s)://path/to/my/plugin.wasm`) +4. Bare aliases (`filepicker`), see [Plugin Aliases](./plugin-aliases.md) diff --git a/docs/src/plugin-pipes.md b/docs/src/plugin-pipes.md new file mode 100644 index 0000000..7ccea57 --- /dev/null +++ b/docs/src/plugin-pipes.md @@ -0,0 +1,82 @@ +# Pipes for Communicating with and Between plugins +## What are pipes? +A Zellij pipe is a unidirectional communication channel to and/or from a plugin. This communication channel is used to send one or more messages containing arbitrary serializable text, similar to how pipes work in most shells. + +Pipes can have a name (arbitrary string), a payload (arbitrary stringifiable content) and arguments (a dictionary of arbitrary string to arbitrary string). All of these are optional. + +**Pipes that do not have a specific destination are broadcast to all plugins.** The reason for this is in order to facilitate the creation of conventions such as the "notification" pipe that can be handled by multiple different plugins in potentially different ways. + +Pipes that do not have a name will be assigned a random UUID as their name. + +### Pipe destinations +A pipe destination can be any plugin url (eg. https://example.com/my-plugin.wasm, file:/path/to/plugin.wasm, etc.) coupled with a [plugin configuration](./plugin-api-configuration.md). Two plugins with the same URL and different configurations will each be considered a unique plugin destination. + +If a plugin has multiple instances (such as is the case when multiple users are attached to the same session), each instance will receive messages from a pipe directed at this plugin. + +If a destination is specified for a pipe and no such plugin is running, this plugin will be loaded on first message (the pipe will wait until it is loaded and then send it the first message - see [backpressure](#cli-pipes-and-backpressure) below). + +When started from a plugin, a pipe destination can also be the internal unique Zellij id of a specific plugin. This is to facilitate two-way communication between two plugins - see [Pipe sources](#pipe-sources) below. + +### Pipe sources +Pipes can be started either from the CLI, from a keybinding or from another plugin. The source of the pipe will be specified to the plugin (see below). If the source is another plugin, the internal Zellij id of the source plugin will be provided (to allow the plugin to respond in a new pipe if needed). + +If the source is the CLI, the internal pipe-id (a UUID) will be provided to allow plugins to apply backpressure to the CLI pipe as needed (for example, pausing a CLI pipeline until the user presses a specific key). + +### CLI pipes and backpressure +Pipes can be [started from the CLI](./zellij-pipe.md), in which case they can potentially listen to `STDIN` and send multiple messages down the same pipe. It's important to stress that this is usually slower than piping data to other programs, namely because Zellij plugins often render themselves on each pipe message. The `STDIN` buffer is only released after the plugin has been rendered (or has elected not to render itself) in order to apply backpressure. + +Zellij plugins can also elect to entirely block the CLI pipe, releasing it later based on (for example) user input. The same pipe can be blocked/released from any plugin, so long as it knows the CLI pipe ID provided as the [pipe source](#pipe-sources). + +A plugin can also print to the CLI pipe's `STDOUT` (unrelated to the data it gets on `STDIN`) assuming it knows its ID. In fact, multiple plugins (or plugin instances) can print to the `STDOUT` of the same pipe if so desired. + +For more on this, see [block_cli_pipe_input](./plugin-api-commands.md#block_cli_pipe_input), [unblock_cli_pipe_input](./plugin-api-commands.md#unblock_cli_pipe_input) and [cli_pipe_output](./plugin-api-commands.md#cli_pipe_output). + +### The `pipe` lifecycle method +Plugins may listen to pipes by implementing the `pipe` lifecycle method. This method is called every time a message is sent over a pipe to this plugin (whether it's broadcast to all plugins or specifically directed at this one). It receives a `PipeMessage` containing the source of the pipe (CLI, another plugin or a keybinding), as well as information about said source (the plugin id or the CLI pipe id). The `PipeMessage` also contains the name of the pipe (explicitly provided by the user or a random UUID assigned by Zellij), its payload if it has one, its arguments and whether it is private or not (a private message is one directed specifically at this plugin rather than broadcast to all plugins). + +Similar to the [update method](./plugin-lifecycle.md#update), the pipe lifecycle method returns a bool, true if it would like to render itself, in which case the render function will be called as normal. + +Here's a small Rust example: +```rust +fn pipe(&mut self, pipe_message: PipeMessage) -> bool { + let mut should_render = false; + match pipe_message.source { + PipeSource::Cli(input_pipe_id) => { + if let Some(payload) = pipe_message.payload { + self.messages_from_cli.push(payload); + should_render = true; + } + if self.paused { + // backpressure, this will pause data from the CLI pipeline until the unblock_cli_pipe_input method will be called for this id + // from this or another plugin + block_cli_pipe_input(&input_pipe_id); + } + if self.should_print_to_cli_stdout { + // this can happen anywhere, anytime, from multiple plugins and is not tied to data from STDIN + // as long as the pipe is open, plugins with its ID can print arbitrary data to its STDOUT side, even if the input side is blocked + cli_pipe_output(input_pipe_id, &payload); + } + } + PipeSource::Plugin(source_plugin_id) => { + // pipes can also arrive from other plugins + } + } + should_render +} +``` + +### The `pipe_message_to_plugin` plugin API command +This [`pipe_message_to_plugin` API command](./plugin-api-commands.md#pipe_message_to_plugin) allows plugins to start a new pipe to another plugin. It allows spcifying a pipe destination, name, payload, args and also some information to be used in case this message will end up launching a new plugin (for example, the pane title of the new plugin). + +Here's a short Rust example: +```rust +pipe_message_to_plugin( + MessageToPlugin::new("message_name") + .with_plugin_url("https://example.com/my-plugin.wasm") + .new_plugin_instance_should_have_pane_title("new_plugin_pane_title") +); +``` +### The special `zellij:OWN_URL` pipe destination +When plugins open pipes, they can use the special `zellij:OWN_URL` destination url. Zellij will replace this URL with the plugin's own URL. This is useful when plugins want to launch new instances of themselves and communicate with them (for example, in order for the plugin to play different roles or to create a visual pipeline with multiple panes on the user's screen). + +It's important to remember though that if this is used, care needs to be taken to make sure the new plugin's configuration is different from the currently running one - otherwise Zellij will send this message back to the plugin (see plugin uniqueness above). diff --git a/docs/src/plugin-system-status.md b/docs/src/plugin-system-status.md index 4b7f793..923863b 100644 --- a/docs/src/plugin-system-status.md +++ b/docs/src/plugin-system-status.md @@ -2,7 +2,5 @@ While even at this early stage, the Zellij plugin system offers powerful capabilities to plugin developers and users alike, there are a few key missing features that are all currently being addressed. This page lists the major ones: 1. [Filesystem access is not very fast](https://github.com/zellij-org/zellij/issues/2556) -2. [Plugins cannot be loaded from the web and so their distribution is not trivial](https://github.com/zellij-org/zellij/issues/1393) -3. [Plugins cannot communicate with each other](https://github.com/zellij-org/zellij/issues/2557) -4. [Plugin commands are asynchronous and provide no success/failure indication](https://github.com/zellij-org/zellij/issues/2558) -5. [More plugin APIs](https://github.com/zellij-org/zellij/issues/2559) +2. [Plugin commands are asynchronous and provide no success/failure indication](https://github.com/zellij-org/zellij/issues/2558) +3. [More plugin APIs](https://github.com/zellij-org/zellij/issues/2559) diff --git a/docs/src/session-manager-alias.md b/docs/src/session-manager-alias.md new file mode 100644 index 0000000..dfa1212 --- /dev/null +++ b/docs/src/session-manager-alias.md @@ -0,0 +1,15 @@ +# The session-manager alias + +This alias, by default translated to the internal `zellij:session-manager` plugin url, represents the session-manager loaded by default with `Ctrl o` + `w`. + +## Contract +Zellij loads the session-manager as a floating pane as part of the default keybindings. + +## User expectations +Users will likely expect the session-manager to: +1. Allow them to switch between active sessions +2. Allow them to resurrect exited sessions +3. Allow them to start a new session +4. Allow them to rename the current session +5. Allow them to disconnect other users (clients) in the current session +6. Allow them to kill active sessions and permanently delete exited sessions diff --git a/docs/src/status-bar-alias.md b/docs/src/status-bar-alias.md new file mode 100644 index 0000000..e56a96d --- /dev/null +++ b/docs/src/status-bar-alias.md @@ -0,0 +1,6 @@ +# The status-bar alias + +This alias, by default translated to the internal `zellij:status-bar` plugin url, represents the status-bar loaded in the default layout on the bottom of the screen. + +## Contract +Zellij loads this status bar with a height of `2` and a width the size of the user's full screen. Zellij has no other expectations from this plugin, even though users will probably expect at least the input modes and their status be shown. diff --git a/docs/src/strider-alias.md b/docs/src/strider-alias.md new file mode 100644 index 0000000..d32f7ad --- /dev/null +++ b/docs/src/strider-alias.md @@ -0,0 +1,7 @@ +# The strider alias + +This alias, by default translated to the internal `zellij:strider` plugin url, is the default Zellij filesystem explorer. + +## Contract +Zellij loads this plugin in the `strider` layout with a width of 20% of the user's screen and a the full height of the user's screen minus 3 (one for the [tab-bar](./tab-bar-alias.md) and two for the [status-bar](./status-bar-alias.md)). Zellij has no other expectations from this alias, but users will probably expect it to at least show a list of files in the current directory. + diff --git a/docs/src/tab-bar-alias.md b/docs/src/tab-bar-alias.md new file mode 100644 index 0000000..c5ac71d --- /dev/null +++ b/docs/src/tab-bar-alias.md @@ -0,0 +1,6 @@ +# The tab-bar Alias + +This alias, by default translated to the internal `zellij:tab-bar` plugin url, represents the tab bar loaded on the top line of the default layout. + +## Contract +Zellij loads this tab bar with a height of `1` and a width the size of the user's full screen. Zellij has no other expectations from this plugin, even though users will probably expect at least the tabs to be shown. diff --git a/docs/src/welcome-screen-alias.md b/docs/src/welcome-screen-alias.md new file mode 100644 index 0000000..381dfd8 --- /dev/null +++ b/docs/src/welcome-screen-alias.md @@ -0,0 +1,12 @@ +# The welcome-screen alias + +This alias, by default translated to the internal `zellij:session-manager` plugin url with the `welcome_screen true` configuration, is loaded on startup when the built-in `welcome` [layout](./layouts.md) is loaded with `zellij -l welcome`. + +## Contract +Zellij loads the welcome-screen fullscreened without any other UI. It expects the plugin to close itself (and thus the session) once the user starts a new session, switches to a new session or resurrects an exited session. + +## User expectations +Users will likely expect the welcome-screen to: +1. Allow them to attach to an existing session +2. Allow them to resurrect an exited session +3. Allow them to start a new session diff --git a/docs/src/zellij-edit.md b/docs/src/zellij-edit.md index 7196f1a..19936d0 100644 --- a/docs/src/zellij-edit.md +++ b/docs/src/zellij-edit.md @@ -13,9 +13,21 @@ $ zellij edit ./main.rs --line-number 10 # open main.rs pointed at line number 1 **Possible Options**: ``` - -d, --direction - -f, --floating - -l, --line-number + --cwd Change the working directory of the editor + -d, --direction Direction to open the new pane in + -f, --floating Open the new pane in floating mode + -h, --help Print help information + --height The height if the pane is floating as a bare integer (eg. 1) + or percent (eg. 10%) + -i, --in-place Open the new pane in place of the current pane, temporarily + suspending it + -l, --line-number Open the file in the specified line number + --width The width if the pane is floating as a bare integer (eg. 1) + or percent (eg. 10%) + -x, --x The x coordinates if the pane is floating as a bare integer + (eg. 1) or percent (eg. 10%) + -y, --y The y coordinates if the pane is floating as a bare integer + (eg. 1) or percent (eg. 10%) ``` **Note**: The default editor is anything set in `$EDITOR` or `$VISUAL` - alternatively, it can be set explicitly with the [`scrollback_editor` configuration option](./options.md#scrollback_editor). diff --git a/docs/src/zellij-pipe.md b/docs/src/zellij-pipe.md new file mode 100644 index 0000000..25b273a --- /dev/null +++ b/docs/src/zellij-pipe.md @@ -0,0 +1,52 @@ +# Zellij Pipe + +Zellij [pipes](./plugin-pipes.md) provide a way to send messages to one or more plugins, launching them on first-message if they are not running. + +eg. +``` +$ zellij plugin -- https://path/to/my/plugin.wasm +``` + +**USAGE**: +``` +zellij pipe [OPTIONS] [--] + +* Send data to a specific plugin: + +zellij pipe --plugin file:/path/to/my/plugin.wasm --name my_pipe_name -- my_arbitrary_data + +* To all running plugins (that are listening): + +zellij pipe --name my_pipe_name -- my_arbitrary_data + +* Pipe data into this command's STDIN and get output from the plugin on this command's STDOUT + +tail -f /tmp/my-live-logfile | zellij pipe --name logs --plugin https://example.com/my-plugin.wasm | wc -l + zellij plugin [OPTIONS] [--] +``` + +**ARGS**: +``` + The data to send down this pipe (if blank, will listen to STDIN) +``` + +**OPTIONS**: +``` + -n, --name + The name of the pipe + + -a, --args + The args of the pipe + + -p, --plugin + The plugin url (eg. file:/tmp/my-plugin.wasm) to direct this pipe to, if not specified, + will be sent to all plugins, if specified and is not running, the plugin will be + launched + + -c, --plugin-configuration + The plugin configuration (note: the same plugin with different configuration is + considered a different plugin for the purposes of determining the pipe destination) + + -h, --help + Print help information +``` diff --git a/docs/src/zellij-plugin.md b/docs/src/zellij-plugin.md index bdee4e5..84f3b50 100644 --- a/docs/src/zellij-plugin.md +++ b/docs/src/zellij-plugin.md @@ -25,6 +25,24 @@ $ zellij plugin -- https://path/to/my/plugin.wasm -f, --floating Open the new pane in floating mode + -h, --help + Print help information + + --height + The height if the pane is floating as a bare integer (eg. 1) or percent (eg. 10%) + -i, --in-place Open the new pane in place of the current pane, temporarily suspending it + + -s, --skip-plugin-cache + Skip the memory and HD cache and force recompile of the plugin (good for development) + + --width + The width if the pane is floating as a bare integer (eg. 1) or percent (eg. 10%) + + -x, --x + The x coordinates if the pane is floating as a bare integer (eg. 1) or percent (eg. 10%) + + -y, --y + The y coordinates if the pane is floating as a bare integer (eg. 1) or percent (eg. 10%) ``` diff --git a/static/documentation/404.html b/static/documentation/404.html index a902345..5ca96ef 100644 --- a/static/documentation/404.html +++ b/static/documentation/404.html @@ -1,5 +1,5 @@ - + @@ -11,7 +11,7 @@ - + @@ -32,7 +32,7 @@ - +
+ + @@ -117,9 +124,9 @@