Skip to content

jmcore.tui

jmcore.tui

JoinMarket-NG TUI menu launcher.

Thin entry point that locates and execs menu.joinmarket-ng.sh. It is registered as the jm-ng console script via jmcore's pyproject.toml, so after pip install jmcore users can simply run jm-ng from the terminal.

The launcher resolves the shell script in this order:

  1. $JM_NG_MENU environment variable override.
  2. Package data shipped inside the jmcore wheel (jmcore/data/menu.joinmarket-ng.sh).
  3. Relative to the repo root (editable / development installs).
  4. $HOME/.joinmarket-ng/menu.sh (standalone manual installs).

If whiptail is not found on $PATH the launcher exits with a helpful message.

Functions:

main() -> None

Launch the JoinMarket-NG TUI menu.

Source code in jmcore/src/jmcore/tui.py
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
def main() -> None:
    """Launch the JoinMarket-NG TUI menu."""
    exit_if_version_requested(sys.argv[1:])

    # Pre-flight: whiptail is required
    if not shutil.which("whiptail"):
        print(
            "Error: 'whiptail' is required but not found.\n"
            "Install it with your package manager, e.g.:\n"
            "  sudo apt install whiptail          # Debian/Ubuntu\n"
            "  sudo pacman -S libnewt              # Arch Linux",
            file=sys.stderr,
        )
        raise SystemExit(1)

    script = _find_menu_script()
    if script is None:
        print(
            "Error: Could not locate the TUI menu script.\n"
            "Expected locations:\n"
            "  - jmcore package data (pip install jmcore)\n"
            "  - <repo>/scripts/menu.joinmarket-ng.sh  (development)\n"
            "  - ~/.joinmarket-ng/menu.sh               (standalone install)\n"
            "\n"
            "You can also set the JM_NG_MENU environment variable to the\n"
            "full path of the script.",
            file=sys.stderr,
        )
        raise SystemExit(1)

    # Replace the current process with bash running the script, pinned to this
    # installation (interpreter and console scripts as a pair) so a stale
    # default venv cannot supply older helpers. Without its console scripts the
    # menu keeps its own venv/PATH discovery.
    env = {k: v for k, v in os.environ.items() if k not in ("JM_NG_PYTHON", "JM_NG_SCRIPTS")}
    scripts = _installation_scripts_dir()
    if scripts is not None:
        env.update(JM_NG_PYTHON=sys.executable, JM_NG_SCRIPTS=str(scripts))
    os.execvpe("bash", ["bash", str(script)], env)