Skip to content

Alternative for shell placeholders #3631

@past-gen

Description

@past-gen

yazi --debug output

Yazi
    Version: 26.1.22 (24c6041 2026-01-27)
    Debug  : false
    Triple : x86_64-pc-windows-msvc (windows-x86_64)
    Rustc  : 1.93.0 (254b5960 2026-01-19)

Ya
    Version: 26.1.22 (24c6041 2026-01-27)

Config
    Init             : C:\Users\Admin\AppData\Roaming\yazi\config\init.lua (6049 chars)
    Yazi             : C:\Users\Admin\AppData\Roaming\yazi\config\yazi.toml (9635 chars)
    Keymap           : C:\Users\Admin\AppData\Roaming\yazi\config\keymap.toml (27884 chars)
    Theme            : C:\Users\Admin\AppData\Roaming\yazi\config\theme.toml (41069 chars)
    VFS              : C:\Users\Admin\AppData\Roaming\yazi\config\vfs.toml (The system cannot find the file specified. (os error 2))
    Package          : C:\Users\Admin\AppData\Roaming\yazi\config\package.toml (2660 chars)
    Dark/light flavor: "" / ""

Emulator
    TERM                : Some("wezterm")
    TERM_PROGRAM        : Some("WezTerm")
    TERM_PROGRAM_VERSION: Some("20251025-070338-b6e75fd7")
    Brand.from_env      : Some(WezTerm)
    Emulator.detect     : Emulator { kind: Left(WezTerm), version: "WezTerm 20251025-070338-b6e75fd7", light: false, csi_16t: (9, 20), force_16t: true }

Adapter
    Adapter.matches    : Iip
    Dimension.available: Dimension { rows: 37, columns: 151, width: 0, height: 0 }

Desktop
    XDG_SESSION_TYPE           : None
    WAYLAND_DISPLAY            : None
    DISPLAY                    : None
    SWAYSOCK                   : None
    HYPRLAND_INSTANCE_SIGNATURE: None
    WAYFIRE_SOCKET             : None

SSH
    shared.in_ssh_connection: false

WSL
    WSL: false

Variables
    SHELL              : Some("X:\\Apps\\Portable\\.cli\\nu.exe")
    EDITOR             : Some("X:/Apps/Portable/.cli/mc.exe")
    VISUAL             : Some("X:/Apps/Portable/Sublime/sublime_text.exe")
    YAZI_FILE_ONE      : Some("X:\\Apps\\.System\\GnuWin32\\bin\\file.exe")
    YAZI_CONFIG_HOME   : None
    YAZI_ZOXIDE_OPTS   : None
    FZF_DEFAULT_OPTS   : None
    FZF_DEFAULT_COMMAND: None

Text Opener
    default     : Some(OpenerRule { run: "set YaziS=%s && nu --no-std-lib -c \"%YaziS% | save -f %d1/env.text\"", block: false, orphan: false, desc: "[Test] Env", for: None, spread: true })
    block-create: Some(OpenerRule { run: "mc %s", block: true, orphan: false, desc: "Micro", for: None, spread: true })
    block-rename: Some(OpenerRule { run: "mc %s", block: true, orphan: false, desc: "Micro", for: None, spread: true })

Multiplexers
    TMUX               : false
    tmux version       : program not found
    tmux build flags   : enable-sixel=Unknown
    ZELLIJ_SESSION_NAME: None
    Zellij version     : program not found

Dependencies
    file          : ExitStatus(ExitStatus(1)), "X:\\Apps\\.System\\GnuWin32\\bin\\file.exe-5.03\r\nmagic file from X:\\Apps\\.System\\GnuWin32/share/misc/magic\r\n"
    ueberzugpp    : program not found
    ffmpeg/ffprobe: ffmpeg version N-120352-gda18c2a373-20250722 Copyright (c) 2000-2025 the FFmpeg developers / ffprobe version N-120352-gda18c2a373-20250722 Copyright (c) 2007-2025 the FFmpeg developers
    pdftoppm      : program not found
    magick        : 7.1.2-13
    fzf           : 0.64.0
    fd/fdfind     : 10.2.0 / program not found
    rg            : 14.1.1
    chafa         : program not found
    zoxide        : 0.9.8
    7zz/7z        : program not found / 25.01
    resvg         : program not found
    jq            : 1.8.1

Clipboard
    wl-copy/paste: program not found / program not found
    xclip        : program not found
    xsel         : program not found

Routine
    `file -bL --mime-type`:

Please describe the problem you're trying to solve

Following that line of thought #3626 , where @sxyazi helped me realise that the actual escaping logic has little to do with the described issue, I came up with a more practical and concise solution that eliminates the need for it altogether.

The issue at hand:

  • nu -c "action %s1 | save -f %d1"
    With the placeholder being part of an existing quoted sequence, any additional formatting that Yazi may, or may not, apply would break the "top-level" command formatting, as the user has likely initially written it with all necessary formatting in mind.
  • command $s1 >> %d1/log/goo.die 2>> "%d1/error log/bad.die"
    Assuming that %d1 has spaces in it, the result would be something like \"'\"escaped path\"'/error log/bad.die\" or similar gibberish.
  • the length of the shell command itself isn't limitless, if my memory serves me right, so depending on how lengthy its final version is going to be, command may not be able to run at all.
  • ...

Would you be willing to contribute this feature?

  • Yes, I'll give it a shot

Describe the solution you'd like

As an alternative to "hot replacement" at the shell command formatting stage, add the required values to the environment and allow the scripts/apps to access them at the execution stage instead.

This way, depending on preference, one can write custom handlers or use local existing scripts without worrying about the correct escaping, formatting, and whatnots. Without any need of .lua plugins as well.

With Nushell in my case , nu -c "[ %s ] | process somehow | par-each { do something }" turns into either:

  • nu --config ~/.nu/yazi.nu -c yazi-specific-action-handler, where all required data acquired and handled internally
  • nu -c "any common action $env.YA_s1 | save -f $'($env.YA_d1)/formatted/h o w e/v.er'", where it's internally interpreted

From Yazi perspective - an additional parameter env wherever run is used, like opener or hotkey events ( would be useful for custom-shell.yazi I think ), that would be either:

  • a boolean value, to expose all shell's placeholders to ENV as variables
  • compound set of all required placeholder names to extend ENV with

While it technically can be done by spamming set var=%... into run command, it'd cause unnecessary complication, and as mentioned, the shell command's length isn't limitless. So delegating this task to Yazi internals seems like solid idea.

Additional context

No response

Checklist

  • I have searched the existing issues/discussions
  • The latest nightly build doesn't already have this feature

Metadata

Metadata

Assignees

No one assigned

    Labels

    featureNew feature request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions