zellij icon indicating copy to clipboard operation
zellij copied to clipboard

Switch Session

Open fedoranvar opened this issue 3 years ago • 17 comments

Good day to you!

I have written script-binary for attaching session

#!/usr/bin/env zsh

Z_DIR=~/.config/zellij

SESSION=$(
    FZF_DEFAULT_OPTS="$FZF_DEFAULT_OPTS
--header='F1 - choose session
F2 - list active sessions
F3 - create session

'
"
    [[ ! -z $1 ]] && (
        echo $1
    ) || (
        cd $Z_DIR/layouts
        fd 'yaml' | sd '(.+)(\..+)' '$1' | fzf
    )
)

LAYOUT_PATH="$Z_DIR/layouts/$SESSION.yaml"

# echo $LAYOUT_PATH
[[ -z $SESSION ]] && return 1
zellij --layout-path $LAYOUT_PATH

and mapped detaching in Zellij.

To switch session, i'm detaching from curent session and execute script.

Is it possible to run script after detaching or is there action for switching session?

      - action: [Detach, Run: {cmd: session-man}]
        key: [Alt: 'D',]

Thank you!

fedoranvar avatar Nov 19 '21 09:11 fedoranvar

Hey, thanks for taking the time in writing this issue.

This shouldn't be possible currently, since we don't handle the client once the session is detached.

A hack that would work currently would to specify, in a state directory before detaching, that you detached from the session. And wrap the calling of zellij, that runs the script if it detect a 1 at the location for example. Once it exits. This is super hacky.

I have started to collect some possible locations we would want to run actions on in #851I do think on_attach and on_detach could be valuable points there.

It is also planned to integrate session switching directly in the UI at some point.

a-kenji avatar Nov 19 '21 11:11 a-kenji

current workaround:

  • create keybinding in shell (ctrl-z) for script-switching session
  • and create keybinding for running wtype (xdotool-like for wayland) before detaching
    - action:
        [
          Run:
            {
              cmd: setsid,
              args: ["wtype", "-M", "ctrl", "-P", "z"],
            },
          Detach,
        ]
      key: [Alt: "D"]

fedoranvar avatar Feb 24 '22 17:02 fedoranvar

@a-kenji Is this work in progress? I want a session-switch interface just like tmux, but it seems has not. I need typing many words when I try to attach a session. just like this:

> zellij list-sessions                                                                                                                          
unequaled-flowers
calm-guide
hot-beam
> zellij attach hot-beam

And there has no completion for sessions. 图片

cathaysia avatar Apr 27 '22 14:04 cathaysia

@cathaysia,

This is not a wip yet. We would accept pr's for that.

And there has no completion for sessions.

This depends on the shell, if you use fish, you should get these completions. image

I need typing many words when I try to attach a session. just like this:

If you look at our integration section in the docs, you could already save a lot of typing by using one of the simplest shell scripts:

https://zellij.dev/documentation/integration.html#list-current-sessions

Obviously that is not as nice as tmux's session switching.

a-kenji avatar Apr 27 '22 15:04 a-kenji

I borrowed the code from List current sessions and wrapped it around with loop, it almost works same like tmux session switch, except single session case is tricky.

instead of start zellij, you start this Z script

#!/usr/bin/env bash
while true; do
   ZJ_SESSIONS=$(zellij list-sessions)
   NO_SESSIONS=$(echo "${ZJ_SESSIONS}"  wc -l)

   if [ "${NO_SESSIONS}" -ge 2 ]; then
      SESSION=$(echo "${ZJ_SESSIONS}"  | fzf)
      if [ $? -eq 0 ]; then
         zellij attach $SESSION
      else
         exit 0
      fi
   else
      SESSION=$ZJ_SESSIONS
      zellij attach -c
   fi
   echo "detach/quit SESSION=$SESSION"
done                                  

When you want to switch while inside zellij session, just detach (you can bind to tmux session switch key), then you will see fzf provide session list again, that you can select and switch to. And finally when you want to quit, just Ctrl-C/ESC on fzf selection screen. (or if zellij can provide different exit code for quit/detach, then we can detect and exit too w/o prompt list)

ryanhuanli avatar Sep 19 '22 02:09 ryanhuanli

I did an ad-hoc one for personal usage: https://github.com/alex35mil/dotfiles/tree/master/user/bin/zellij/runner

https://user-images.githubusercontent.com/4244251/214125080-e106749d-b891-4f3f-ac81-e6b79ad89ab7.mp4

alex35mil avatar Jan 23 '23 18:01 alex35mil

Even though the previous version worked, its UI was crap and not really pleasant to use. I rewrote it and abstracted away all (🤞) hardcoded stuff specific to my system. Published to the crates.io. Source is here.

https://user-images.githubusercontent.com/4244251/221366175-6c3ae4fd-985a-491b-9d26-255cdf03def5.mov

alex35mil avatar Feb 25 '23 15:02 alex35mil

Even though the previous version worked, its UI was crap and not really pleasant to use. I rewrote it and abstracted away all (🤞) hardcoded stuff specific to my system. Published to the crates.io. Source is here.

This looks brutal 👍. Is there a way to install it other than using cargo? Like some executable or binary file which can be downloaded from github releases?

mabasic avatar Feb 25 '23 17:02 mabasic

@mabasic Sorry, nope. I just cargo publish it from the depths of my dotfiles repo.

FWIW Installing Rust/Cargo is the breeziest experience unless you’re concerned with having Rust toolchain on your machine.

alex35mil avatar Feb 26 '23 15:02 alex35mil

@mabasic Sorry, nope. I just cargo publish it from the depths of my dotfiles repo.

FWIW Installing Rust/Cargo is the breeziest experience unless you’re concerned with having Rust toolchain on your machine.

Have you tried installing Rust/Cargo on Windows xD (not wsl) You select the wrong option during the install and you get yourself whole Visual Studio installed cca 4GB. I have once managed to install it manually without having VS installed in the process 😄

It can be done but it is not a breeze. That is why I would have preferred a single binary instead, but never mind I will get around the issue.

mabasic avatar Feb 26 '23 16:02 mabasic

Ah, sorry, not a windows user 😳

alex35mil avatar Feb 26 '23 16:02 alex35mil

Similarly i have a "zellij runner" type code that loosely manages the sessions. Its mean to help to switch between different sessions, create new ones with zoxide results. I also have some code in my .zshrc that automatically connects to a default zellij session using this runner.

I'd love for this to be built in by default into zellij itself someday.

# connect to default zellij session if not already in one
if [ -z "$ZELLIJ_SESSION_NAME" ]; then
    zr default
fi
function zr() {
  # If a session name is provided as an argument, attach to or create it
  if [[ -n $1 ]]; then
      if zellij ls | grep -E -q "^$1( \(current\))?$"; then
        # Attach to the specified session if it exists
        zellij a "$1"
      else
        # Create a new session with the specified name if it doesn't exist
        zellij -s "$1"
      fi
  fi

  while true; do
    local sessions_list=("New session" "Exit")
    local existing_sessions=($(zellij ls | sed 's/ (current)//'))

    if [[ ${#existing_sessions[@]} -gt 0 ]]; then
      sessions_list=("${existing_sessions[@]}" "${sessions_list[@]}")
    fi

    local choice=$(printf '%s\n' "${sessions_list[@]}" | fzf --prompt="Select an option: ")

    # If the choice is empty, assume the user wants to exit
    if [[ -z $choice ]]; then
      break
    fi

    case $choice in
      "New session")
        local dir_options=("No directory" "Exit")
        local dirs=($(zoxide query -l))
        if [[ ${#dirs[@]} -gt 0 ]]; then
          dir_options=("${dirs[@]}" "${dir_options[@]}")
        fi
        local dir_choice=$(printf '%s\n' "${dir_options[@]}" | fzf --prompt="Select a directory or choose 'No directory': ")

        # If the dir_choice is empty or invalid, continue to the next iteration of the loop
        if [[ -z $dir_choice || $dir_choice == "Exit" ]]; then
          continue
        fi

        case $dir_choice in
          "No directory")
            zellij
            ;;
          *)
            local session_name="$(basename $dir_choice)"
            if [[ " ${existing_sessions[@]} " =~ " ${session_name} " ]]; then
              # Attach to existing session
              zellij a $session_name
            else
              # Create new session and change directory
              (cd "$dir_choice" && zellij -s "$session_name")
            fi
            ;;
        esac
        ;;
      "Exit")
        break
        ;;
      *)
        zellij a $choice
        ;;
    esac
  done
}

arnm avatar Apr 24 '23 03:04 arnm

@mabasic Sorry, nope. I just cargo publish it from the depths of my dotfiles repo. FWIW Installing Rust/Cargo is the breeziest experience unless you’re concerned with having Rust toolchain on your machine.

Have you tried installing Rust/Cargo on Windows xD (not wsl) You select the wrong option during the install and you get yourself whole Visual Studio installed cca 4GB. I have once managed to install it manually without having VS installed in the process 😄

It can be done but it is not a breeze. That is why I would have preferred a single binary instead, but never mind I will get around the issue.

But why would you want to install zellij-runner on windows (not WSL)? I thought zellij didn't compile on windows natively?

KSaiAkshit avatar Jun 27 '23 13:06 KSaiAkshit

My version: zellij-sessionizer thanks to @ryanhuanli for inspiration https://github.com/zellij-org/zellij/issues/884#issuecomment-1250483279 here's my version for another use case:

  • it's implementation of ThePrimeagen tmux-sessionizer https://github.com/ThePrimeagen/.dotfiles/blob/602019e902634188ab06ea31251c01c1a43d1621/bin/.local/scripts/tmux-sessionizer . I short, it allows to create sessions in predefined set of folders, like all children folders in ~/projects, ~/.config ~/work.
  • so in select screen I need completely different approach, I don't show currently existing sessions or controls to create new empty session, who needs it anyway?
  • not selecting anything (Esc or Ctrl-C): will restore previous session

difference from tmux-sessionizer comes from script running as a wrapper for zellij:

  • obvious for those who read this thread:
    • this script is zellij manager, user starts this script and it's running zellij for you
    • to switch sessions, user just need to detach from current zellij session, instead of terminal he will see sessionizer menu to select folder for new session
  • I'm adding menu item Quit that will terminate zellij-sessionizer - the only way to terminate script otherwise is to kill it.

zellij-sessionizer:

#!/usr/bin/env bash

# set your own root folders, all children folders will become options for in sessionizer menu
root_folders="$HOME/projects $HOME/work $HOME/.config"

function attach_session() {
    local session_root=$1
    local session_name=$(basename "$session_root" | tr . _)
    cd $session_root
    zellij attach --create $session_name
}

quit_option="=== Quit sessionizer ==="
last_session=""
while true; do
    selected_option=$( (echo $quit_option && find $root_folders -mindepth 1 -maxdepth 1 -type d) | fzf)

    if [[ $selected_option == $quit_option ]]; then
        exit 0
    fi
    
    if [[ -z $selected_option && -z $last_session ]]; then
        exit 0
    fi

    if [[ -z $selected_option ]]; then
        attach_session $last_session
    else
        last_session=$selected_option
        attach_session $selected_option
    fi
done

aimestereo avatar Aug 05 '23 18:08 aimestereo

I don't have anything as sophisticated as the scripts above. but I wanted to add a functionality to my script where it could be executed within a zellij session, and if there was a session with the same name as SESSION_TITLE the script would switch to that session. but for that I would need some command line argument similar to tmux switch -t <session-name>. Are there any plans for something similar to be implemented?

#! /usr/bin/env sh

# select a directory using zoxide
ZOXIDE_RESULT=$(zoxide query --interactive)
# checks whether a directory has been selected
if [[ -z "$ZOXIDE_RESULT" ]]; then
  # if there was no directory, select returns without executing
  exit 0
fi
# extracts the directory name from the absolute path
SESSION_TITLE=$(echo "$ZOXIDE_RESULT" | sed 's#.*/##')

# get the list of sessions
SESSION_LIST=$(zellij list-sessions -n | awk '{print $1}')

# checks if SESSION_TITLE is in the session list
if echo "$SESSION_LIST" | grep -q "^${SESSION_TITLE}$"; then
  # if so, attach to existing session
  zellij attach "${SESSION_TITLE}"
else
  # if not, create a new session 
  zellij attach -c "${SESSION_TITLE}"
fi

emersonfbarros avatar Dec 12 '23 01:12 emersonfbarros

IMO, you suggestion is quite attractive and good. I think that will be a good workflow! I have a small question.

get the list of sessions

SESSION_LIST=$(zellij list-sessions -n | awk '{print $1}')

I just want to know the "-n" option in this scripts. In my machine, -n omit all the color of the output which is much easier for later process. Can you explain further what it means? Better to provide link in the doc. I searched and found nothing. Thank you!

meicale avatar Feb 05 '24 13:02 meicale

I just want to know the "-n" option in this scripts. In my machine, -n omit all the color of the output which is much easier for later process. Can you explain further what it means? Better to provide link in the doc. I searched and found nothing. Thank you!

Type zellij list-sessions -h and press enter. this will show information about the flags that can be passed to the list-sessions command, including the -n flag, which without abbreviation becomes --no-formatting. All zellij commands have their own list of help information, which is very useful.

emersonfbarros avatar Feb 05 '24 13:02 emersonfbarros