Ctrl K
ComunidadGuías…

docs/adding-a-shell-integration-checklist.md

Rama master · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# App-side checklist: adding a new shell to shell integration

Use this when adding support for any new shell to iTerm2's shell
integration. Throughout, `<shell>` is the lowercase shell name (as it
appears in `ShellIntegrationVersion=...;shell=<shell>`), and `Xxx` is
the corresponding capitalized name used in enum cases and class names.

The most complete precedent is the xonsh work in these two commits;
consult them when a step is unclear:

- `1bf85d898` "Add xonsh as a supported shell for shell integration"
- `1e4ee607b` "Add xonsh shell integration"

Line numbers below are approximate and drift over time; grep for the
neighboring symbol.

## Prerequisites

- The shell-integration script itself lives in the
  `iTerm2-shell-integration` submodule (a separate repo). It must be
  merged there and the script bundled (see "Bundling the script")
  before the app-side steps that read from it will work.
- Decide how the script is loaded automatically. Shells fall into two
  broad shapes:
  - dotfile shells (bash/zsh/tcsh): the installer appends a `source`
    line to a dotfile.
  - autoload shells (fish/xonsh, and similar): the shell auto-sources
    scripts from a directory, so no dotfile edit is needed. Injection
    is done by setting a marker/config env var (xonsh: `XONSHRC`
    pointing at the script; others may set a directory the shell
    autoloads from). Know which env var your shell uses before starting
    - several steps below key off it.

## Bundling the script

- [ ] `tools/copy_shell_integration.sh` - add a `cp` line copying
      `$SUBMODULE/shell_integration/<shell>` to
      `Resources/shell_integration/iterm2_shell_integration.<shell>`.
- [ ] `submodules/iTerm2-shell-integration` - bump the submodule pointer
      to the commit containing the new script.
- [ ] `iTerm2.xcodeproj/project.pbxproj` - add
      `iterm2_shell_integration.<shell>` as a file reference and into
      the Resources build phase of each target that bundles the other
      shell scripts (xonsh added one PBXFileReference + three "in
      Resources" build files). Use `tools/add_file_to_xcodeproj.rb`, not
      hand-editing.
- [ ] `sources/ShellIntegration/iTermLatestVersionByShell.h` -
      DO NOT hand-edit. Its first line is
      `// DO NOT MODIFY - Generated by tools/copy_shell_integration.sh`,
      and `copy_shell_integration.sh` regenerates it by grepping
      `ShellIntegrationVersion=` out of every bundled
      `Resources/shell_integration/iterm2_shell_integration.*` script:

          grep ShellIntegrationVersion= ... | sed -n 's/^.*ShellIntegrationVersion=\([^;]*\).*shell=\([a-z]*\).*$/    @"\2": @\1,/p'

      The `@"<shell>"` entry appears automatically once the script is
      bundled and the generator runs; its value is whatever the script
      announces (do not assume 1 - e.g. xonsh reads `@2` today, not the
      `@1` its original commit added, because the script was bumped and
      the header re-derived).
      Precondition on the script: it MUST emit a token matching the
      generator regex, i.e. contain
      `ShellIntegrationVersion=<N>;shell=<shell>` with a lowercase
      `[a-z]*` shell name (xonsh does this in a comment:
      `# ShellIntegrationVersion=2;shell=xonsh`). If the script omits
      that token or names the shell differently, the header entry is
      silently dropped and the shell falls back to no version tracking.
      Verify the bundled script contains this before relying on the
      header.

## Enum / shell registry

- [ ] `sources/ShellIntegrationInstaller/iTermShellIntegrationInstaller.h`
      - add `iTermShellIntegrationShellXxx` to the
      `iTermShellIntegrationShell` enum.
      (Note: the version header `iTermLatestVersionByShell.h` is NOT
      edited here - it is generated. See "Bundling the script".)
- [ ] `sources/ShellIntegrationInstaller/iTermShellIntegrationWindowController.m`
      - (a) `iTermShellIntegrationShellString`: return `@"<shell>"`; (b)
      the shell-name to enum `map` (~line 610): add
      `@"<shell>": @(iTermShellIntegrationShellXxx)`.

## Shell version-notification table

- [ ] `sources/VT100Screen/VT100ScreenMutableState+TerminalDelegate.m`
      `terminalSetShellIntegrationVersion:` - update the stale shell-name
      comment (~line 2704) to include the new shell. Do NOT add the shell
      to the hardcoded critical-updates dict unless it has a version
      users must be nagged off of even in "only critical updates" mode;
      a brand-new shell should be omitted (its latest version already
      comes from the generated header on the non-critical path).

## Automatic injection (login shell + SSH)

- [ ] `sources/ShellIntegration/ShellIntegrationInjection.swift` - (a)
      add `local("iterm2_shell_integration.<shell>")` to the resource
      list (~line 167); (b) add `case xxx = "<shell>"` to the `Shell`
      enum and its factory switch; (c) add an
      `XxxShellIntegrationInjection` class that sets the shell's
      marker/config env var so the shell autoloads the script (xonsh
      appends the script path to `XONSHRC`; a directory-autoload shell
      sets its autoload-dir env var to a dir containing the script -
      confirm that dir actually contains a correctly-named script the
      shell will source). INVARIANT: `computeModified(env:argv:)` must
      return `argv` UNCHANGED (env-only injection), exactly like the
      xonsh class (`return (modifiedEnvironment(...), argv)`). If it
      ever mutates argv, the Conductor empty-argv SSH branch (below) no
      longer applies and integration silently fails to load over SSH.
      (If your shell genuinely requires argv changes - like bash's
      `--posix` - then the Conductor branch must name the shell
      explicitly; see that code.)
- [ ] `sources/SSH/Conductor.swift` - two edits:
  - `alwaysSupported` (~line 2080): add `"<shell>"` so SSH injection is
    offered for that remote login shell.
  - the comment enumerating env-only-injection shells (~line 2344)
    reads "(zsh/fish/xonsh add no argv)". If your shell is purely
    env-based, add it to that list. This documents why the empty-argv
    branch (~lines 2332-2344) is correct - which holds only if the
    injection class honors the argv-unchanged invariant above.

## Manual installer UI flow

- [ ] `sources/ShellIntegrationInstaller/iTermShellIntegrationWindowController.m`
      - dotfile shells mostly work through the existing switches; an
      autoload shell needs the xonsh-style "no dotfile" special-casing.
      Points to cover:
  - `shellIntegrationPath` -> where the script is written (dotfile
    shells: `~/.iterm2_shell_integration.<shell>`; autoload shells: the
    autoload path, e.g. xonsh returns `~/.config/xonsh/rc.d/iterm2.xsh`;
    mind any macOS-vs-Linux config-dir differences your shell has).
  - utilities: dotfile shells add aliases; PATH-style shells add a PATH
    line instead (xonsh: `$PATH.insert(...)`) and return `nil` in the
    alias builder's `case ...Xxx:`.
  - `shell_and`/quoting switch (~line 331): add `case ...Xxx:` in the
    arm matching the shell's `&&`/quoting behavior.
  - if autoload: `mkdir -p <autoload dir>` step (xonsh added
    `mkdir -p ~/.config/xonsh/rc.d`) in both the string builder
    (~line 413) and the `reallySend` path (~line 516).
  - `launchBashString` / `exitBashString` single-bash special case
    (only if the shell needs the same prompt-setup workaround xonsh
    did).
  - `modifyStartupScriptsAndProceedTo:` early-return no-op + the two
    `finishSendShellCommandsInstall` shortcuts (~lines 648, 709, 721)
    for autoload shells that skip the dotfile step.
- [ ] `sources/ShellIntegrationInstaller/iTermShellIntegrationPasteShellCommandsViewController.m`
      - (a) update the "not supported" message to list the shell; (b)
      for autoload shells, add the "auto-loads ... no dotfile update
      needed" step and the `isDone` shortcut (xonsh: ~lines 64, 131).

## Other shell-list touchpoints

- [ ] `sources/API/iTermAPIScriptLauncher.m` - add `@"<shell>"` to
      `knownShells` (~line 818) so API scripts run through that login
      shell. Only do this if `<shell> -c 'echo /tmp/a\ b'` prints
      `/tmp/a b`: the command is built with POSIX backslash escaping, so
      a shell that keeps the backslash (nushell does) splits paths with
      spaces and every API script fails to launch. Leave such shells
      out; they fall back to `/bin/bash`.
- [ ] `sources/Settings/ProfilesGeneralPreferencesViewController.m` -
      TWO lists here, both updated by the xonsh commit:
  - the `shells` array (~line 743, code) that enables "Load shell
    integration automatically" for a custom command.
  - the SSH-command-type reason string (~line 786), currently
    `@"Requires bash, fish, tcsh, xonsh, or zsh.";` (user-visible). Add
    the shell in alphabetical order. If you add it only to the array,
    the SSH help text will wrongly claim the shell is unsupported.
- [ ] `OtherResources/framer.py` - `get_env_var` (~line 596) detects
      the shell from `os.environ.get('SHELL')`. Two edits:
  - add `<shell>` to `known_shells` (~line 604).
  - add a `$SHELL` override mirroring the xonsh one (~lines 601-602),
    keyed off the shell's marker env var:

          if os.environ.get('<MARKER_ENV_VAR>', ''):
              user_shell = '<shell>'

    This is REQUIRED for any non-POSIX / non-login-shell case, not
    optional: when the shell is launched as a custom profile command,
    over SSH, or any path where it is not the login shell, `$SHELL`
    still points at the user's POSIX login shell (e.g. `/bin/zsh`), so
    `basename($SHELL)` misdetects. xonsh needed this override (keyed off
    `XONSHRC`) for exactly this reason. Verify by launching the shell as
    a non-login custom command and confirming framer reports
    `shell=<shell>`.
- [ ] `sources/AITerm/RemoteCommand.swift` - update the `getShellType`
      help string example list (cosmetic).
- [ ] `sources/Settings/PreferencePanel.xib` - update the "Load shell
      integration automatically" tooltip shell list (cosmetic).

## Tests & docs

- [ ] `ModernTests/ShellIntegrationLiveHarness.swift` - add the shell to
      every switch in the `SupportedShell` enum (xonsh touched five):
  - the enum `case` list (~line 94).
  - executable candidates (~line 103).
  - `arguments(for:)` launch args (~line 108) - route the shell
    deliberately, not by falling into a combined arm meant for other
    shells.
  - resource name (~line 124).
  - `sourceCommand(integrationPath:)` (~line 128) - the switch is
    exhaustive with no default, so it will not compile without an arm
    for the new shell. Use the shell's own sourcing syntax (zsh/bash/
    fish/tcsh use `source <path>`; xonsh uses
    `execx(open('<path>').read())`; others differ - watch for shells
    where `source` requires a parse-time-constant path).
  - if the shell's line editor sends a cursor-position report
    (`CSI 6n`) before sourcing (as xonsh's prompt_toolkit does), the
    harness must answer it or the shell stalls; xonsh is currently
    `XCTSkip`ped for this, so a new such shell likely needs the same
    skip or a CPR responder.
- [ ] `docs/notes-3.7.txt` - add a release-note line, max 50 cols
      (xonsh: "xonsh is now a supported shell.").

## Not needed / verify only

- `sources/Settings/Profiles/ITAddressBookMgr.m` has shell-name
  mentions in comments only - optionally extend them, no code change.
- The quote-escaping commit (`9aff539d4`) was a general enabler for
  shells whose syntax breaks backslash escaping (xonsh); check whether
  any installer command string emitted for the new shell needs similar
  treatment.