Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Include directive to reduce repetition between layout files #3835

Open
brandondrew opened this issue Dec 5, 2024 · 1 comment
Open

Include directive to reduce repetition between layout files #3835

brandondrew opened this issue Dec 5, 2024 · 1 comment

Comments

@brandondrew
Copy link

To give a simple example, I have a number of different layout files that I use for different purposes, but pretty much all of them have the following configurations:

  pane_template name="tab-bar-pane" borderless=true { plugin location="zellij:tab-bar"; }
  pane_template name="status-bar-pane" borderless=true { plugin location="zellij:status-bar"; }

  default_tab_template {
    tab-bar-pane size=1
    children
    status-bar-pane size=2
  }

It would be nice to put all of these in something like layouts/shared/framing.kdl and then just add include "../shared/framing.kdl" in my layout files.

There's probably a lot more repetition than that, but for the sake of keeping it simple, that's enough to illustrate the benefit.

@librolibro
Copy link

librolibro commented Dec 8, 2024

Same feelings here. When I just started to use Zellij I found zjstatus plugin - and its configuration took about 25-30 lines in my case. When I found about layouts and realized that now I need not only to copy this config to every layout but also to change these simultaneously...

P.S. Last month I started to use Zellij much much frequently, and these is a shell workaround I'm using (someone might find it useful too):

  1. The only layout I'm using is the default one. Note the commented line // {layout here} - this is the place where I'm pasting pane/tab config via scripts.
layout {
    default_tab_template {
        pane size=1 borderless=true {
            plugin location="file:~/Projects/my-zellij-plugins/statusbar/zig-out/bin/zigzellij-statusbar.wasm" {
                // 20+ lines of my statusbar config ...
            }
        }
        children
        // Another oneline plugin at the bottom of the tab
    }

    // THE MOST IMPORTANT STRING:
    // {layout here}

    swap_tiled_layout name="vertical" {
        tab max_panes=4 {
            pane split_direction="vertical" {
                pane
                pane { children; }
            }
        }
        tab max_panes=7 {
            pane split_direction="vertical" {
                pane { children; }
                pane { pane; pane; pane; }
            }
        }
    }

    // more swap layouts here ...

}
  1. I have a script that prints the tab/pane config into the stdout (the whole output will be pasted instead of the comment I mentioned above):
#!/usr/bin/env zsh
# ~/.config/zellij/layout-presets/my.kdl.sh
if [ $# -eq 0 ]; then
    >&2 echo "No arguments passed"
    exit 1
fi

# I'm using assotiative arrays here to preverse
# the order and also to avoid duplicates
declare -A tabs_to_show
declare -a key_order

while [ $# -gt 0 ]; do
    case "$1" in
        sb|statusbar)
            if [ -z "${tabs_to_show[sb]}" ]; then
                # Open two panes to work on my plugin (with plugin project as cwd)
                tabs_to_show[sb]="\
tab name=\"sb codin'\" cwd=\"~/Projects/my-zellij-plugins/statusbar\" {
    pane split_direction=\"vertical\" {
        pane
        pane
    }
}
"
                key_order+=( sb )
            fi
            ;;
        notes)
            # Open my neorg notes
            if [ -z "${tabs_to_show[notes]}" ]; then
                tabs_to_show[notes]="\
tab name=\"takin' notes\" cwd=\"~/.local/share/norg/notes\" {
    pane {
        command \"nvim\"
        args \"+e zellij.norg\" \"+vnew nvim.norg\" \"+new shell.norg\"
        close_on_exit false
    }
}
"
                key_order+=( notes )
            fi
            ;;
        music)
            # Open my TUI music player
            if [ -z "${tabs_to_show[music]}" ]; then
                tabs_to_show[music]="\
tab name=\"listenin'\" cwd=\"~\" {
    pane {
        command "ncmpcpp"
        close_on_exit false
    }
}
"
                key_order+=( music )
            fi
            ;;
        *)
            >&2 echo "Invalid argument: $1"
            exit 1
            ;;
    esac
    shift
done

for k in "${key_order[@]}"; do
    echo "${tabs_to_show[$k]}"
done
exit 0

So running script with music and notes arguments will print me two tabs` layout configuration (1st tab: one pane with music player, 2nd tab: vim instance with multiple splits inside):

> # This is the output I want to paste inside my default layout
> ./this_script.kdl.sh music notes

tab name="listenin'" cwd="~" {
    pane {
        command ncmpcpp
        close_on_exit false
    }
}

tab name="takin' notes" cwd="~/.local/share/norg/notes" {
    pane {
        command "nvim"
        args "+e zellij.norg" "+vnew nvim.norg" "+new shell.norg"
        close_on_exit false
    }
}
  1. The zsh function that will combine my default layout and the config printed in script above (p.2):
#!/usr/bin/env zsh
# There's only the most important parts of my function,
# I have lots of check etc. Too much to paste it here
zjL() {
    # Default layout
    default_layout_fn="${XDG_CONFIG_HOME}/zellij/layouts/default.kdl"
    # Find the commented "anchor line" for the replacement
    lineno="$(awk '/\{layout here\}/{print NR; exit;}' "${default_layout_fn}")"

    # I have more than one .kdl.sh file, for this example it's hardcoded here
    preset_fn="${XDG_CONFIG_HOME}/zellij/layout_presets/my.kdl.sh"
    # Execute this file with passed arguments, capture stdout and ensure than exitcode=0
    layout_to_insert="$("${preset_fn}" "$@")"; exitcode=$?
    if [ "${exitcode}" -ne 0 ]; then
        >&2 echo "Script '${preset_fn}' exited with code=${exitcode}"
        return 1
    fi

    # And finally - merge default layout and the script output
    command zellij --layout =(
        # Get everything from the default layout above the "anchor line"
        head -n+"$((lineno-1))" "${default_layout_fn}"
        # Between we are pasting the script output
        echo "${layout_to_insert}"
        # Get everything from the default layout below the "anchor line"
        tail -n+"$((lineno+1))" "${default_layout_fn}"
    )
}
> # call example
> zjL notes music

I found this (extremely hacky IMO) way of layout managing much more flexible, because:

  1. I don't need to constantly repeat the statusbar/other plugins` config
  2. I don't need to repeat my swap layouts
  3. In my script I can easily specify which tabs do I want to open (I don't need to make a layout file for every combination, I can just choose it via zjL function arguments)

Feature like "include" and "import" would be definitely useful. E.g. in Alacritty terminal emulator (in their TOML config) you can specify "import" array with the files you want to include to your config, which is very useful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants