@wangyaoshen/remux 0.3.8-dev.29e114b
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/ISSUE_TEMPLATE/bug_report.md +47 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +38 -0
- package/.github/PULL_REQUEST_TEMPLATE.md +28 -0
- package/.github/dependabot.yml +33 -0
- package/.github/workflows/ci.yml +65 -0
- package/.github/workflows/deploy.yml +65 -0
- package/.github/workflows/publish.yml +312 -0
- package/.github/workflows/release-please.yml +21 -0
- package/.gitmodules +3 -0
- package/.nvmrc +1 -0
- package/.release-please-manifest.json +3 -0
- package/CLAUDE.md +104 -0
- package/Dockerfile +23 -0
- package/LICENSE +21 -0
- package/README.md +120 -0
- package/apps/ios/Config/signing.xcconfig +4 -0
- package/apps/ios/Package.swift +26 -0
- package/apps/ios/Remux.xcodeproj/project.pbxproj +477 -0
- package/apps/ios/Remux.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
- package/apps/ios/Sources/Remux/Assets.xcassets/AppIcon.appiconset/Contents.json +23 -0
- package/apps/ios/Sources/Remux/Assets.xcassets/AppIcon.appiconset/icon_1024x1024.png +0 -0
- package/apps/ios/Sources/Remux/Assets.xcassets/AppIcon.appiconset/icon_120x120.png +0 -0
- package/apps/ios/Sources/Remux/Assets.xcassets/AppIcon.appiconset/icon_152x152.png +0 -0
- package/apps/ios/Sources/Remux/Assets.xcassets/AppIcon.appiconset/icon_167x167.png +0 -0
- package/apps/ios/Sources/Remux/Assets.xcassets/AppIcon.appiconset/icon_180x180.png +0 -0
- package/apps/ios/Sources/Remux/Assets.xcassets/AppIcon.appiconset/icon_20x20.png +0 -0
- package/apps/ios/Sources/Remux/Assets.xcassets/AppIcon.appiconset/icon_29x29.png +0 -0
- package/apps/ios/Sources/Remux/Assets.xcassets/AppIcon.appiconset/icon_40x40.png +0 -0
- package/apps/ios/Sources/Remux/Assets.xcassets/AppIcon.appiconset/icon_58x58.png +0 -0
- package/apps/ios/Sources/Remux/Assets.xcassets/AppIcon.appiconset/icon_60x60.png +0 -0
- package/apps/ios/Sources/Remux/Assets.xcassets/AppIcon.appiconset/icon_76x76.png +0 -0
- package/apps/ios/Sources/Remux/Assets.xcassets/AppIcon.appiconset/icon_80x80.png +0 -0
- package/apps/ios/Sources/Remux/Assets.xcassets/AppIcon.appiconset/icon_87x87.png +0 -0
- package/apps/ios/Sources/Remux/Assets.xcassets/Contents.json +6 -0
- package/apps/ios/Sources/Remux/Extensions/FaceIDManager.swift +29 -0
- package/apps/ios/Sources/Remux/Extensions/InspectCache.swift +66 -0
- package/apps/ios/Sources/Remux/MainTabView.swift +32 -0
- package/apps/ios/Sources/Remux/Remux.entitlements +8 -0
- package/apps/ios/Sources/Remux/RemuxiOSApp.swift +14 -0
- package/apps/ios/Sources/Remux/RootView.swift +130 -0
- package/apps/ios/Sources/Remux/Views/Control/ControlView.swift +102 -0
- package/apps/ios/Sources/Remux/Views/Inspect/InspectView.swift +98 -0
- package/apps/ios/Sources/Remux/Views/Live/LiveTerminalView.swift +132 -0
- package/apps/ios/Sources/Remux/Views/Now/NowView.swift +173 -0
- package/apps/ios/Sources/Remux/Views/Onboarding/ManualConnectView.swift +55 -0
- package/apps/ios/Sources/Remux/Views/Onboarding/OnboardingView.swift +70 -0
- package/apps/ios/Sources/Remux/Views/Onboarding/QRScannerView.swift +92 -0
- package/apps/ios/Sources/Remux/Views/Settings/MeView.swift +136 -0
- package/apps/macos/Package.swift +37 -0
- package/apps/macos/Resources/shell-integration/bash/bash-preexec.sh +382 -0
- package/apps/macos/Resources/shell-integration/bash/ghostty.bash +315 -0
- package/apps/macos/Resources/shell-integration/elvish/lib/ghostty-integration.elv +191 -0
- package/apps/macos/Resources/shell-integration/fish/vendor_conf.d/ghostty-shell-integration.fish +246 -0
- package/apps/macos/Resources/shell-integration/nushell/vendor/autoload/ghostty.nu +110 -0
- package/apps/macos/Resources/shell-integration/zsh/.zshenv +61 -0
- package/apps/macos/Resources/shell-integration/zsh/ghostty-integration +458 -0
- package/apps/macos/Resources/terminfo/67/ghostty +0 -0
- package/apps/macos/Resources/terminfo/78/xterm-ghostty +0 -0
- package/apps/macos/Sources/Remux/AppDelegate.swift +257 -0
- package/apps/macos/Sources/Remux/CrashReporter.swift +210 -0
- package/apps/macos/Sources/Remux/FinderIntegration.swift +117 -0
- package/apps/macos/Sources/Remux/GhosttyConfig.swift +311 -0
- package/apps/macos/Sources/Remux/KeyboardShortcuts/ShortcutAction.swift +115 -0
- package/apps/macos/Sources/Remux/KeyboardShortcuts/ShortcutSettingsView.swift +271 -0
- package/apps/macos/Sources/Remux/KeyboardShortcuts/StoredShortcut.swift +149 -0
- package/apps/macos/Sources/Remux/MainContentView.swift +308 -0
- package/apps/macos/Sources/Remux/MenuBarManager.swift +275 -0
- package/apps/macos/Sources/Remux/NotificationManager.swift +145 -0
- package/apps/macos/Sources/Remux/PortScanner.swift +152 -0
- package/apps/macos/Sources/Remux/RemuxApp.swift +13 -0
- package/apps/macos/Sources/Remux/SSHDetector.swift +151 -0
- package/apps/macos/Sources/Remux/SessionPersistence.swift +226 -0
- package/apps/macos/Sources/Remux/SocketController.swift +258 -0
- package/apps/macos/Sources/Remux/UpdateChecker.swift +152 -0
- package/apps/macos/Sources/Remux/Views/CommandPalette.swift +198 -0
- package/apps/macos/Sources/Remux/Views/ConnectionView.swift +84 -0
- package/apps/macos/Sources/Remux/Views/InspectView.swift +127 -0
- package/apps/macos/Sources/Remux/Views/SettingsView.swift +77 -0
- package/apps/macos/Sources/Remux/Views/Sidebar/SidebarView.swift +410 -0
- package/apps/macos/Sources/Remux/Views/SplitTree/BrowserPanel.swift +193 -0
- package/apps/macos/Sources/Remux/Views/SplitTree/MarkdownPanel.swift +277 -0
- package/apps/macos/Sources/Remux/Views/SplitTree/PanelProtocol.swift +14 -0
- package/apps/macos/Sources/Remux/Views/SplitTree/SplitNode.swift +149 -0
- package/apps/macos/Sources/Remux/Views/SplitTree/SplitView.swift +234 -0
- package/apps/macos/Sources/Remux/Views/SplitTree/TerminalPanel.swift +26 -0
- package/apps/macos/Sources/Remux/Views/TabBarView.swift +94 -0
- package/apps/macos/Sources/Remux/Views/Terminal/ClipboardHelper.swift +101 -0
- package/apps/macos/Sources/Remux/Views/Terminal/CopyModeOverlay.swift +325 -0
- package/apps/macos/Sources/Remux/Views/Terminal/GhosttyNativeTerminalView.swift +39 -0
- package/apps/macos/Sources/Remux/Views/Terminal/GhosttyNativeView.swift +559 -0
- package/apps/macos/Sources/Remux/Views/Terminal/SurfaceSearchOverlay.swift +109 -0
- package/apps/macos/Sources/Remux/Views/Terminal/TerminalContainerView.swift +95 -0
- package/apps/macos/Sources/Remux/Views/Terminal/TerminalRelay.swift +117 -0
- package/build.mjs +33 -0
- package/native/android/DecodeGoldenPayloads.kt +487 -0
- package/native/android/ProtocolModels.kt +188 -0
- package/native/ios/DecodeGoldenPayloads.swift +711 -0
- package/native/ios/ProtocolModels.swift +200 -0
- package/package.json +45 -0
- package/packages/RemuxKit/Package.swift +27 -0
- package/packages/RemuxKit/Sources/RemuxKit/Device/DeviceManager.swift +27 -0
- package/packages/RemuxKit/Sources/RemuxKit/Models/ProtocolModels.swift +206 -0
- package/packages/RemuxKit/Sources/RemuxKit/Networking/MessageRouter.swift +108 -0
- package/packages/RemuxKit/Sources/RemuxKit/Networking/RemuxConnection.swift +395 -0
- package/packages/RemuxKit/Sources/RemuxKit/State/RemuxState.swift +188 -0
- package/packages/RemuxKit/Sources/RemuxKit/Storage/KeychainStore.swift +142 -0
- package/packages/RemuxKit/Sources/RemuxKit/Terminal/GhosttyBridge.swift +145 -0
- package/packages/RemuxKit/Sources/RemuxKit/Terminal/GhosttyTerminalView.swift +35 -0
- package/packages/RemuxKit/Sources/RemuxKit/Terminal/Resources/ghostty-terminal.html +91 -0
- package/packages/RemuxKit/Tests/RemuxKitTests/ConnectionIntegrationTest.swift +74 -0
- package/packages/RemuxKit/Tests/RemuxKitTests/KeychainStoreTests.swift +81 -0
- package/packages/RemuxKit/Tests/RemuxKitTests/ProtocolModelsTests.swift +179 -0
- package/packages/RemuxKit/Tests/RemuxKitTests/RemuxStateTests.swift +62 -0
- package/playwright.config.ts +17 -0
- package/pnpm-lock.yaml +1588 -0
- package/pty-daemon.js +303 -0
- package/release-please-config.json +14 -0
- package/scripts/auto-deploy.sh +46 -0
- package/scripts/build-dmg.sh +121 -0
- package/scripts/build-ghostty-kit.sh +43 -0
- package/scripts/check-active-terminology.mjs +132 -0
- package/scripts/setup-ci-secrets.sh +80 -0
- package/scripts/sync-ghostty-web.sh +28 -0
- package/scripts/upload-testflight.sh +100 -0
- package/server.js +7074 -0
- package/src/adapters/agent-events.ts +246 -0
- package/src/adapters/claude-code.ts +158 -0
- package/src/adapters/codex.ts +210 -0
- package/src/adapters/generic-shell.ts +58 -0
- package/src/adapters/index.ts +15 -0
- package/src/adapters/registry.ts +99 -0
- package/src/adapters/types.ts +41 -0
- package/src/auth.ts +174 -0
- package/src/e2ee.ts +236 -0
- package/src/git-service.ts +168 -0
- package/src/message-buffer.ts +137 -0
- package/src/pty-daemon.ts +357 -0
- package/src/push.ts +127 -0
- package/src/renderers.ts +455 -0
- package/src/server.ts +2407 -0
- package/src/service.ts +226 -0
- package/src/session.ts +978 -0
- package/src/store.ts +1422 -0
- package/src/team.ts +123 -0
- package/src/tunnel.ts +126 -0
- package/src/types.d.ts +50 -0
- package/src/vt-tracker.ts +188 -0
- package/src/workspace-head.ts +144 -0
- package/src/workspace.ts +153 -0
- package/src/ws-handler.ts +1526 -0
- package/start.ps1 +83 -0
- package/tests/adapters.test.js +171 -0
- package/tests/auth.test.js +243 -0
- package/tests/codex-adapter.test.js +535 -0
- package/tests/durable-stream.test.js +153 -0
- package/tests/e2e/app.spec.js +530 -0
- package/tests/e2ee.test.js +325 -0
- package/tests/message-buffer.test.js +245 -0
- package/tests/message-routing.test.js +305 -0
- package/tests/pty-daemon.test.js +346 -0
- package/tests/push.test.js +281 -0
- package/tests/renderers.test.js +391 -0
- package/tests/search-shell.test.js +499 -0
- package/tests/server.test.js +882 -0
- package/tests/service.test.js +267 -0
- package/tests/store.test.js +369 -0
- package/tests/tunnel.test.js +67 -0
- package/tests/workspace-head.test.js +116 -0
- package/tests/workspace.test.js +417 -0
- package/tsconfig.backend.json +11 -0
- package/tsconfig.json +15 -0
- package/tui/client/client_test.go +125 -0
- package/tui/client/connection.go +342 -0
- package/tui/client/host_manager.go +141 -0
- package/tui/config/cache.go +81 -0
- package/tui/config/config.go +53 -0
- package/tui/config/config_test.go +89 -0
- package/tui/go.mod +32 -0
- package/tui/go.sum +50 -0
- package/tui/main.go +261 -0
- package/tui/tests/integration_test.go +283 -0
- package/tui/ui/model.go +310 -0
- package/vitest.config.js +10 -0
|
@@ -0,0 +1,458 @@
|
|
|
1
|
+
# vim:ft=zsh
|
|
2
|
+
#
|
|
3
|
+
# Based on (started as) a copy of Kitty's zsh integration. Kitty is
|
|
4
|
+
# distributed under GPLv3, so this file is also distributed under GPLv3.
|
|
5
|
+
# The license header is reproduced below:
|
|
6
|
+
#
|
|
7
|
+
# This program is free software: you can redistribute it and/or modify
|
|
8
|
+
# it under the terms of the GNU General Public License as published by
|
|
9
|
+
# the Free Software Foundation, either version 3 of the License, or
|
|
10
|
+
# (at your option) any later version.
|
|
11
|
+
#
|
|
12
|
+
# This program is distributed in the hope that it will be useful,
|
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15
|
+
# GNU General Public License for more details.
|
|
16
|
+
#
|
|
17
|
+
# You should have received a copy of the GNU General Public License
|
|
18
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
19
|
+
|
|
20
|
+
#
|
|
21
|
+
# Enables integration between zsh and ghostty.
|
|
22
|
+
#
|
|
23
|
+
# This is an autoloadable function. It's invoked automatically in shells
|
|
24
|
+
# directly spawned by Ghostty but not in any other shells. For example, running
|
|
25
|
+
# `exec zsh`, `sudo -E zsh`, `tmux`, or plain `zsh` will create a shell where
|
|
26
|
+
# ghostty-integration won't automatically run. Zsh users who want integration with
|
|
27
|
+
# Ghostty in all shells should add the following lines to their .zshrc:
|
|
28
|
+
#
|
|
29
|
+
# if [[ -n $GHOSTTY_RESOURCES_DIR ]]; then
|
|
30
|
+
# source "$GHOSTTY_RESOURCES_DIR"/shell-integration/zsh/ghostty-integration
|
|
31
|
+
# fi
|
|
32
|
+
#
|
|
33
|
+
# Implementation note: We can assume that alias expansion is disabled in this
|
|
34
|
+
# file, so no need to quote defensively. We still have to defensively prefix all
|
|
35
|
+
# builtins with `builtin` to avoid accidentally invoking user-defined functions.
|
|
36
|
+
# We avoid `function` reserved word as an additional defensive measure.
|
|
37
|
+
|
|
38
|
+
# Note that updating options with `builtin emulate -L zsh` affects the global options
|
|
39
|
+
# if it's called outside of a function. So nearly all code has to be in functions.
|
|
40
|
+
_entrypoint() {
|
|
41
|
+
builtin emulate -L zsh -o no_warn_create_global -o no_aliases
|
|
42
|
+
|
|
43
|
+
[[ -o interactive ]] || builtin return 0 # non-interactive shell
|
|
44
|
+
(( ! $+_ghostty_state )) || builtin return 0 # already initialized
|
|
45
|
+
|
|
46
|
+
# We require zsh 5.1+ (released Sept 2015) for features like functions_source,
|
|
47
|
+
# introspection arrays, and array pattern substitution.
|
|
48
|
+
if ! { builtin autoload -- is-at-least 2>/dev/null && is-at-least 5.1; }; then
|
|
49
|
+
builtin echo "Zsh ${ZSH_VERSION} is too old for ghostty shell integration (5.1+ required)" >&2
|
|
50
|
+
builtin return 1
|
|
51
|
+
fi
|
|
52
|
+
|
|
53
|
+
# 0: no OSC 133 [AC] marks have been written yet.
|
|
54
|
+
# 1: the last written OSC 133 C has not been closed with D yet.
|
|
55
|
+
# 2: none of the above.
|
|
56
|
+
builtin typeset -gi _ghostty_state
|
|
57
|
+
|
|
58
|
+
# Attempt to create a writable file descriptor to the TTY so that we can print
|
|
59
|
+
# to the TTY later even when STDOUT is redirected. This code is fairly subtle.
|
|
60
|
+
#
|
|
61
|
+
# - It's tempting to do `[[ -t 1 ]] && exec {_ghostty_state}>&1` but we cannot do this
|
|
62
|
+
# because it'll create a file descriptor >= 10 without O_CLOEXEC. This file
|
|
63
|
+
# descriptor will leak to child processes.
|
|
64
|
+
# - If we do `exec {3}>&1`, the file descriptor won't leak to the child processes
|
|
65
|
+
# but it'll still leak if the current process is replaced with another. In
|
|
66
|
+
# addition, it'll break user code that relies on fd 3 being available.
|
|
67
|
+
# - Zsh doesn't expose dup3, which would have allowed us to copy STDOUT with
|
|
68
|
+
# O_CLOEXEC. The only way to create a file descriptor with O_CLOEXEC is via
|
|
69
|
+
# sysopen.
|
|
70
|
+
# - `zmodload zsh/system` and `sysopen -o cloexec -wu _ghostty_fd -- /dev/tty` can
|
|
71
|
+
# fail with an error message to STDERR (the latter can happen even if /dev/tty
|
|
72
|
+
# is writable), hence the redirection of STDERR. We do it for the whole block
|
|
73
|
+
# for performance reasons (redirections are slow).
|
|
74
|
+
# - We must open the file descriptor right here rather than in _ghostty_deferred_init
|
|
75
|
+
# because there are broken zsh plugins out there that run `exec {fd}< <(cmd)`
|
|
76
|
+
# and then close the file descriptor more than once while suppressing errors.
|
|
77
|
+
# This could end up closing our file descriptor if we opened it in
|
|
78
|
+
# _ghostty_deferred_init.
|
|
79
|
+
typeset -gi _ghostty_fd
|
|
80
|
+
{
|
|
81
|
+
builtin zmodload zsh/system && (( $+builtins[sysopen] )) && {
|
|
82
|
+
{ [[ -w $TTY ]] && builtin sysopen -o cloexec -wu _ghostty_fd -- $TTY } ||
|
|
83
|
+
{ [[ -w /dev/tty ]] && builtin sysopen -o cloexec -wu _ghostty_fd -- /dev/tty }
|
|
84
|
+
}
|
|
85
|
+
} 2>/dev/null || (( _ghostty_fd = 1 ))
|
|
86
|
+
|
|
87
|
+
# Defer initialization so that other zsh init files can be configure
|
|
88
|
+
# the integration.
|
|
89
|
+
builtin typeset -ag precmd_functions
|
|
90
|
+
precmd_functions+=(_ghostty_deferred_init)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
_ghostty_deferred_init() {
|
|
94
|
+
builtin emulate -L zsh -o no_warn_create_global -o no_aliases
|
|
95
|
+
|
|
96
|
+
# Enable semantic markup with OSC 133.
|
|
97
|
+
_ghostty_precmd() {
|
|
98
|
+
builtin local -i cmd_status=$?
|
|
99
|
+
builtin emulate -L zsh -o no_warn_create_global -o no_aliases
|
|
100
|
+
|
|
101
|
+
# Don't write OSC 133 D when our precmd handler is invoked from zle.
|
|
102
|
+
# Some plugins do that to update prompt on cd.
|
|
103
|
+
if ! builtin zle; then
|
|
104
|
+
# This code works incorrectly in the presence of a precmd or chpwd
|
|
105
|
+
# hook that prints. For example, sindresorhus/pure prints an empty
|
|
106
|
+
# line on precmd and marlonrichert/zsh-snap prints $PWD on chpwd.
|
|
107
|
+
# We'll end up writing our OSC 133 D mark too late.
|
|
108
|
+
#
|
|
109
|
+
# Another failure mode is when the output of a command doesn't end
|
|
110
|
+
# with LF and prompst_sp is set (it is by default). In this case
|
|
111
|
+
# we'll incorrectly state that '%' from prompt_sp is a part of the
|
|
112
|
+
# command's output.
|
|
113
|
+
if (( _ghostty_state == 1 )); then
|
|
114
|
+
# The last written OSC 133 C has not been closed with D yet.
|
|
115
|
+
# Close it and supply status.
|
|
116
|
+
builtin print -nu $_ghostty_fd '\e]133;D;'$cmd_status'\a'
|
|
117
|
+
(( _ghostty_state = 2 ))
|
|
118
|
+
elif (( _ghostty_state == 2 )); then
|
|
119
|
+
# There might be an unclosed OSC 133 C. Close that.
|
|
120
|
+
builtin print -nu $_ghostty_fd '\e]133;D\a'
|
|
121
|
+
fi
|
|
122
|
+
fi
|
|
123
|
+
|
|
124
|
+
builtin local mark1=$'%{\e]133;A;cl=line\a%}'
|
|
125
|
+
if [[ -o prompt_percent ]]; then
|
|
126
|
+
builtin typeset -g precmd_functions
|
|
127
|
+
if [[ ${precmd_functions[-1]} == _ghostty_precmd ]]; then
|
|
128
|
+
# This is the best case for us: we can add our marks to PS1 and
|
|
129
|
+
# PS2. This way our marks will be printed whenever zsh
|
|
130
|
+
# redisplays prompt: on reset-prompt, on SIGWINCH, and on
|
|
131
|
+
# SIGCHLD if notify is set. Themes that update prompt
|
|
132
|
+
# asynchronously from a `zle -F` handler might still remove our
|
|
133
|
+
# marks. Oh well.
|
|
134
|
+
|
|
135
|
+
# Restore PS1/PS2 to their pre-mark state if nothing else has
|
|
136
|
+
# modified them since we last added marks. This avoids exposing
|
|
137
|
+
# PS1 with our marks to other hooks (which can break themes like
|
|
138
|
+
# Pure that use pattern matching to strip/rebuild the prompt).
|
|
139
|
+
# If PS1 was modified (by a theme, async update, etc.), we
|
|
140
|
+
# keep the modified version, prioritizing the theme's changes.
|
|
141
|
+
builtin local ps1_changed=0
|
|
142
|
+
if [[ -n ${_ghostty_saved_ps1+x} ]]; then
|
|
143
|
+
if [[ $PS1 == $_ghostty_marked_ps1 ]]; then
|
|
144
|
+
PS1=$_ghostty_saved_ps1
|
|
145
|
+
PS2=$_ghostty_saved_ps2
|
|
146
|
+
elif [[ $PS1 != $_ghostty_saved_ps1 ]]; then
|
|
147
|
+
ps1_changed=1
|
|
148
|
+
fi
|
|
149
|
+
fi
|
|
150
|
+
|
|
151
|
+
# Save the clean PS1/PS2 before we add marks.
|
|
152
|
+
_ghostty_saved_ps1=$PS1
|
|
153
|
+
_ghostty_saved_ps2=$PS2
|
|
154
|
+
|
|
155
|
+
# Add our marks. Since we always start from a clean PS1
|
|
156
|
+
# (either restored above or freshly set by a theme), we can
|
|
157
|
+
# unconditionally add mark1 and markB.
|
|
158
|
+
builtin local mark2=$'%{\e]133;A;k=s\a%}'
|
|
159
|
+
builtin local markB=$'%{\e]133;B\a%}'
|
|
160
|
+
PS1=${mark1}${PS1}${markB}
|
|
161
|
+
|
|
162
|
+
# Handle multiline prompts by marking newline-separated
|
|
163
|
+
# continuation lines with k=s (mark2). We skip the newline
|
|
164
|
+
# immediately after mark1 to avoid introducing a double
|
|
165
|
+
# newline due to OSC 133;A's fresh-line behavior.
|
|
166
|
+
#
|
|
167
|
+
# We skip this when PS1 changed because injecting marks into
|
|
168
|
+
# newlines can break pattern matching in themes that
|
|
169
|
+
# strip/rebuild the prompt dynamically (e.g., Pure).
|
|
170
|
+
if (( ! ps1_changed )) && [[ $PS1 == *$'\n'* ]]; then
|
|
171
|
+
if [[ $PS1 == ${mark1}$'\n'* ]]; then
|
|
172
|
+
builtin local rest=${PS1#${mark1}$'\n'}
|
|
173
|
+
if [[ $rest == *$'\n'* ]]; then
|
|
174
|
+
PS1=${mark1}$'\n'${rest//$'\n'/$'\n'${mark2}}
|
|
175
|
+
fi
|
|
176
|
+
else
|
|
177
|
+
PS1=${PS1//$'\n'/$'\n'${mark2}}
|
|
178
|
+
fi
|
|
179
|
+
fi
|
|
180
|
+
|
|
181
|
+
# PS2 mark is needed when clearing the prompt on resize
|
|
182
|
+
PS2=${mark2}${PS2}${markB}
|
|
183
|
+
|
|
184
|
+
# Save the marked PS1 so we can detect modifications
|
|
185
|
+
# by other hooks in the next cycle.
|
|
186
|
+
_ghostty_marked_ps1=$PS1
|
|
187
|
+
(( _ghostty_state = 2 ))
|
|
188
|
+
else
|
|
189
|
+
# If our precmd hook is not the last, we cannot rely on prompt
|
|
190
|
+
# changes to stick, so we don't even try. At least we can move
|
|
191
|
+
# our hook to the end to have better luck next time. If there is
|
|
192
|
+
# another piece of code that wants to take this privileged
|
|
193
|
+
# position, this won't work well. We'll break them as much as
|
|
194
|
+
# they are breaking us.
|
|
195
|
+
precmd_functions=(${precmd_functions:#_ghostty_precmd} _ghostty_precmd)
|
|
196
|
+
# Plugins that invoke precmd hooks from zle do that before zle
|
|
197
|
+
# is trashed. This means that the cursor is in the middle of
|
|
198
|
+
# BUFFER and we cannot print our mark there. Prompt might
|
|
199
|
+
# already have a mark, so the following reset-prompt will write
|
|
200
|
+
# it. If it doesn't, there is nothing we can do.
|
|
201
|
+
if ! builtin zle; then
|
|
202
|
+
builtin print -rnu $_ghostty_fd -- $mark1[3,-3]
|
|
203
|
+
(( _ghostty_state = 2 ))
|
|
204
|
+
fi
|
|
205
|
+
fi
|
|
206
|
+
elif ! builtin zle; then
|
|
207
|
+
# Without prompt_percent we cannot patch prompt. Just print the
|
|
208
|
+
# mark, except when we are invoked from zle. In the latter case we
|
|
209
|
+
# cannot do anything.
|
|
210
|
+
builtin print -rnu $_ghostty_fd -- $mark1[3,-3]
|
|
211
|
+
(( _ghostty_state = 2 ))
|
|
212
|
+
fi
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
_ghostty_preexec() {
|
|
216
|
+
builtin emulate -L zsh -o no_warn_create_global -o no_aliases
|
|
217
|
+
|
|
218
|
+
# Restore the original PS1/PS2 if nothing else has modified them
|
|
219
|
+
# since our precmd added marks. This ensures other preexec hooks
|
|
220
|
+
# see a clean PS1 without our marks. If PS1 was modified (e.g.,
|
|
221
|
+
# by an async theme update), we leave it alone.
|
|
222
|
+
if [[ -n ${_ghostty_saved_ps1+x} && $PS1 == $_ghostty_marked_ps1 ]]; then
|
|
223
|
+
PS1=$_ghostty_saved_ps1
|
|
224
|
+
PS2=$_ghostty_saved_ps2
|
|
225
|
+
fi
|
|
226
|
+
|
|
227
|
+
# This will work incorrectly in the presence of a preexec hook that
|
|
228
|
+
# prints. For example, if MichaelAquilina/zsh-you-should-use installs
|
|
229
|
+
# its preexec hook before us, we'll incorrectly mark its output as
|
|
230
|
+
# belonging to the command (as if the user typed it into zle) rather
|
|
231
|
+
# than command output.
|
|
232
|
+
builtin print -nu $_ghostty_fd '\e]133;C\a'
|
|
233
|
+
(( _ghostty_state = 1 ))
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
# Enable reporting current working dir to terminal. Ghostty supports
|
|
237
|
+
# the kitty-shell-cwd format.
|
|
238
|
+
_ghostty_report_pwd() { builtin print -nu $_ghostty_fd '\e]7;kitty-shell-cwd://'"$HOST""$PWD"'\a'; }
|
|
239
|
+
chpwd_functions=(${chpwd_functions[@]} "_ghostty_report_pwd")
|
|
240
|
+
# An executed program could change cwd and report the changed cwd, so also report cwd at each new prompt
|
|
241
|
+
# as in this case chpwd_functions is insufficient. chpwd_functions is still needed for things like: cd x && something
|
|
242
|
+
functions[_ghostty_precmd]+="
|
|
243
|
+
_ghostty_report_pwd"
|
|
244
|
+
_ghostty_report_pwd
|
|
245
|
+
|
|
246
|
+
if [[ "$GHOSTTY_SHELL_FEATURES" == *"title"* ]]; then
|
|
247
|
+
# Enable terminal title changes, formatted for user-friendly display.
|
|
248
|
+
functions[_ghostty_precmd]+="
|
|
249
|
+
builtin print -rnu $_ghostty_fd \$'\\e]2;'\"\${(%):-%(4~|…/%3~|%~)}\"\$'\\a'"
|
|
250
|
+
functions[_ghostty_preexec]+="
|
|
251
|
+
builtin print -rnu $_ghostty_fd \$'\\e]2;'\"\${1//[[:cntrl:]]}\"\$'\\a'"
|
|
252
|
+
fi
|
|
253
|
+
|
|
254
|
+
if [[ "$GHOSTTY_SHELL_FEATURES" == *"cursor"* ]]; then
|
|
255
|
+
# Enable cursor shape changes depending on the current keymap.
|
|
256
|
+
# This implementation leaks blinking block cursor into external commands
|
|
257
|
+
# executed from zle. For example, users of fzf-based widgets may find
|
|
258
|
+
# themselves with a blinking block cursor within fzf.
|
|
259
|
+
_ghostty_zle_line_init _ghostty_zle_line_finish _ghostty_zle_keymap_select() {
|
|
260
|
+
builtin local steady=0
|
|
261
|
+
[[ "$GHOSTTY_SHELL_FEATURES" == *"cursor:steady"* ]] && steady=1
|
|
262
|
+
case ${KEYMAP-} in
|
|
263
|
+
vicmd|visual) builtin print -nu "$_ghostty_fd" "\e[$(( 1 + steady )) q" ;; # block
|
|
264
|
+
*) builtin print -nu "$_ghostty_fd" "\e[$(( 5 + steady )) q" ;; # bar
|
|
265
|
+
esac
|
|
266
|
+
}
|
|
267
|
+
# Restore the default shape before executing an external command
|
|
268
|
+
functions[_ghostty_preexec]+="
|
|
269
|
+
builtin print -rnu $_ghostty_fd \$'\\e[0 q'"
|
|
270
|
+
fi
|
|
271
|
+
|
|
272
|
+
# Emit semantic prompt markers at line-init if PS1 doesn't contain our
|
|
273
|
+
# marks. This ensures the terminal sees prompt markers even if another
|
|
274
|
+
# plugin (like zinit or oh-my-posh) regenerated PS1 after our precmd ran.
|
|
275
|
+
# We use 133;P instead of 133;A to avoid fresh-line behavior which would
|
|
276
|
+
# disrupt the display since the prompt has already been drawn. We also
|
|
277
|
+
# emit 133;B to mark the input area, which is needed for click-to-move.
|
|
278
|
+
(( $+functions[_ghostty_zle_line_init] )) || _ghostty_zle_line_init() { builtin true; }
|
|
279
|
+
functions[_ghostty_zle_line_init]="
|
|
280
|
+
if [[ \$PS1 != *$'%{\\e]133;A'* ]]; then
|
|
281
|
+
builtin print -nu \$_ghostty_fd '\\e]133;P;k=i\\a\\e]133;B\\a'
|
|
282
|
+
fi
|
|
283
|
+
"${functions[_ghostty_zle_line_init]}
|
|
284
|
+
|
|
285
|
+
# Add Ghostty binary to PATH if the path feature is enabled
|
|
286
|
+
if [[ "$GHOSTTY_SHELL_FEATURES" == *"path"* ]] && [[ -n "$GHOSTTY_BIN_DIR" ]]; then
|
|
287
|
+
if [[ ":$PATH:" != *":$GHOSTTY_BIN_DIR:"* ]]; then
|
|
288
|
+
builtin export PATH="$PATH:$GHOSTTY_BIN_DIR"
|
|
289
|
+
fi
|
|
290
|
+
fi
|
|
291
|
+
|
|
292
|
+
# Sudo
|
|
293
|
+
if [[ "$GHOSTTY_SHELL_FEATURES" == *"sudo"* ]] && [[ -n "$TERMINFO" ]]; then
|
|
294
|
+
# Wrap `sudo` command to ensure Ghostty terminfo is preserved
|
|
295
|
+
function sudo() {
|
|
296
|
+
builtin local sudo_has_sudoedit_flags="no"
|
|
297
|
+
for arg in "$@"; do
|
|
298
|
+
# Check if argument is '-e' or '--edit' (sudoedit flags)
|
|
299
|
+
if [[ "$arg" == "-e" || $arg == "--edit" ]]; then
|
|
300
|
+
sudo_has_sudoedit_flags="yes"
|
|
301
|
+
builtin break
|
|
302
|
+
fi
|
|
303
|
+
# Check if argument is neither an option nor a key-value pair
|
|
304
|
+
if [[ "$arg" != -* && "$arg" != *=* ]]; then
|
|
305
|
+
builtin break
|
|
306
|
+
fi
|
|
307
|
+
done
|
|
308
|
+
if [[ "$sudo_has_sudoedit_flags" == "yes" ]]; then
|
|
309
|
+
builtin command sudo "$@";
|
|
310
|
+
else
|
|
311
|
+
builtin command sudo --preserve-env=TERMINFO "$@";
|
|
312
|
+
fi
|
|
313
|
+
}
|
|
314
|
+
fi
|
|
315
|
+
|
|
316
|
+
# SSH Integration
|
|
317
|
+
if [[ "$GHOSTTY_SHELL_FEATURES" == *ssh-* ]]; then
|
|
318
|
+
function ssh() {
|
|
319
|
+
emulate -L zsh
|
|
320
|
+
setopt local_options no_glob_subst
|
|
321
|
+
|
|
322
|
+
local ssh_term ssh_opts
|
|
323
|
+
ssh_term="xterm-256color"
|
|
324
|
+
ssh_opts=()
|
|
325
|
+
|
|
326
|
+
# Configure environment variables for remote session
|
|
327
|
+
if [[ "$GHOSTTY_SHELL_FEATURES" == *ssh-env* ]]; then
|
|
328
|
+
ssh_opts+=(-o "SetEnv COLORTERM=truecolor")
|
|
329
|
+
ssh_opts+=(-o "SendEnv TERM_PROGRAM TERM_PROGRAM_VERSION")
|
|
330
|
+
fi
|
|
331
|
+
|
|
332
|
+
# Install terminfo on remote host if needed
|
|
333
|
+
if [[ "$GHOSTTY_SHELL_FEATURES" == *ssh-terminfo* ]]; then
|
|
334
|
+
local ssh_user ssh_hostname
|
|
335
|
+
|
|
336
|
+
while IFS=' ' read -r ssh_key ssh_value; do
|
|
337
|
+
case "$ssh_key" in
|
|
338
|
+
user) ssh_user="$ssh_value" ;;
|
|
339
|
+
hostname) ssh_hostname="$ssh_value" ;;
|
|
340
|
+
esac
|
|
341
|
+
[[ -n "$ssh_user" && -n "$ssh_hostname" ]] && break
|
|
342
|
+
done < <(command ssh -G "$@" 2>/dev/null)
|
|
343
|
+
|
|
344
|
+
if [[ -n "$ssh_hostname" ]]; then
|
|
345
|
+
local ssh_target="${ssh_user}@${ssh_hostname}"
|
|
346
|
+
|
|
347
|
+
# Check if terminfo is already cached
|
|
348
|
+
if "$GHOSTTY_BIN_DIR/ghostty" +ssh-cache --host="$ssh_target" >/dev/null 2>&1; then
|
|
349
|
+
ssh_term="xterm-ghostty"
|
|
350
|
+
elif (( $+commands[infocmp] )); then
|
|
351
|
+
local ssh_terminfo ssh_cpath_dir ssh_cpath
|
|
352
|
+
|
|
353
|
+
ssh_terminfo=$(infocmp -0 -x xterm-ghostty 2>/dev/null)
|
|
354
|
+
|
|
355
|
+
if [[ -n "$ssh_terminfo" ]]; then
|
|
356
|
+
print "Setting up xterm-ghostty terminfo on $ssh_hostname..." >&2
|
|
357
|
+
|
|
358
|
+
ssh_cpath_dir=$(mktemp -d "/tmp/ghostty-ssh-$ssh_user.XXXXXX" 2>/dev/null) || ssh_cpath_dir="/tmp/ghostty-ssh-$ssh_user.$$"
|
|
359
|
+
ssh_cpath="$ssh_cpath_dir/socket"
|
|
360
|
+
|
|
361
|
+
if builtin print -r "$ssh_terminfo" | command ssh "${ssh_opts[@]}" -o ControlMaster=yes -o ControlPath="$ssh_cpath" -o ControlPersist=60s "$@" '
|
|
362
|
+
infocmp xterm-ghostty >/dev/null 2>&1 && exit 0
|
|
363
|
+
command -v tic >/dev/null 2>&1 || exit 1
|
|
364
|
+
mkdir -p ~/.terminfo 2>/dev/null && tic -x - 2>/dev/null && exit 0
|
|
365
|
+
exit 1
|
|
366
|
+
' 2>/dev/null; then
|
|
367
|
+
ssh_term="xterm-ghostty"
|
|
368
|
+
ssh_opts+=(-o "ControlPath=$ssh_cpath")
|
|
369
|
+
|
|
370
|
+
# Cache successful installation
|
|
371
|
+
"$GHOSTTY_BIN_DIR/ghostty" +ssh-cache --add="$ssh_target" >/dev/null 2>&1 || true
|
|
372
|
+
else
|
|
373
|
+
print "Warning: Failed to install terminfo." >&2
|
|
374
|
+
fi
|
|
375
|
+
else
|
|
376
|
+
print "Warning: Could not generate terminfo data." >&2
|
|
377
|
+
fi
|
|
378
|
+
else
|
|
379
|
+
print "Warning: ghostty command not available for cache management." >&2
|
|
380
|
+
fi
|
|
381
|
+
fi
|
|
382
|
+
fi
|
|
383
|
+
|
|
384
|
+
# Execute SSH with TERM environment variable
|
|
385
|
+
TERM="$ssh_term" command ssh "${ssh_opts[@]}" "$@"
|
|
386
|
+
}
|
|
387
|
+
fi
|
|
388
|
+
|
|
389
|
+
# Some zsh users manually run `source ~/.zshrc` in order to apply rc file
|
|
390
|
+
# changes to the current shell. This is a terrible practice that breaks many
|
|
391
|
+
# things, including our shell integration. For example, Oh My Zsh and Prezto
|
|
392
|
+
# (both very popular among zsh users) will remove zle-line-init and
|
|
393
|
+
# zle-line-finish hooks if .zshrc is manually sourced. Prezto will also remove
|
|
394
|
+
# zle-keymap-select.
|
|
395
|
+
#
|
|
396
|
+
# Another common (and much more robust) way to apply rc file changes to the
|
|
397
|
+
# current shell is `exec zsh`. This will remove our integration from the shell
|
|
398
|
+
# unless it's explicitly invoked from .zshrc. This is not an issue with
|
|
399
|
+
# `exec zsh` but rather with our implementation of automatic shell integration.
|
|
400
|
+
|
|
401
|
+
# In the ideal world we would use add-zle-hook-widget to hook zle-line-init
|
|
402
|
+
# and similar widget. This breaks user configs though, so we have do this
|
|
403
|
+
# horrible thing instead.
|
|
404
|
+
builtin local hook func widget orig_widget flag
|
|
405
|
+
for hook in line-init line-finish keymap-select; do
|
|
406
|
+
func=_ghostty_zle_${hook/-/_}
|
|
407
|
+
(( $+functions[$func] )) || builtin continue
|
|
408
|
+
widget=zle-$hook
|
|
409
|
+
if [[ $widgets[$widget] == user:azhw:* &&
|
|
410
|
+
$+functions[add-zle-hook-widget] -eq 1 ]]; then
|
|
411
|
+
# If the widget is already hooked by add-zle-hook-widget at the top
|
|
412
|
+
# level, add our hook at the end. We MUST do it this way. We cannot
|
|
413
|
+
# just wrap the widget ourselves in this case because it would
|
|
414
|
+
# trigger bugs in add-zle-hook-widget.
|
|
415
|
+
add-zle-hook-widget $hook $func
|
|
416
|
+
else
|
|
417
|
+
if (( $+widgets[$widget] )); then
|
|
418
|
+
# There is a widget but it's not from add-zle-hook-widget. We
|
|
419
|
+
# can rename the original widget, install our own and invoke
|
|
420
|
+
# the original when we are called.
|
|
421
|
+
#
|
|
422
|
+
# Note: The leading dot is to work around bugs in
|
|
423
|
+
# zsh-syntax-highlighting.
|
|
424
|
+
orig_widget=._ghostty_orig_$widget
|
|
425
|
+
builtin zle -A $widget $orig_widget
|
|
426
|
+
if [[ $widgets[$widget] == user:* ]]; then
|
|
427
|
+
# No -w here to preserve $WIDGET within the original widget.
|
|
428
|
+
flag=
|
|
429
|
+
else
|
|
430
|
+
flag=w
|
|
431
|
+
fi
|
|
432
|
+
functions[$func]+="
|
|
433
|
+
builtin zle $orig_widget -N$flag -- \"\$@\""
|
|
434
|
+
fi
|
|
435
|
+
builtin zle -N $widget $func
|
|
436
|
+
fi
|
|
437
|
+
done
|
|
438
|
+
|
|
439
|
+
if (( $+functions[_ghostty_preexec] )); then
|
|
440
|
+
builtin typeset -ag preexec_functions
|
|
441
|
+
preexec_functions+=(_ghostty_preexec)
|
|
442
|
+
fi
|
|
443
|
+
|
|
444
|
+
builtin typeset -ag precmd_functions
|
|
445
|
+
if (( $+functions[_ghostty_precmd] )); then
|
|
446
|
+
precmd_functions=(${precmd_functions:#_ghostty_deferred_init} _ghostty_precmd)
|
|
447
|
+
_ghostty_precmd
|
|
448
|
+
else
|
|
449
|
+
precmd_functions=(${precmd_functions:#_ghostty_deferred_init})
|
|
450
|
+
fi
|
|
451
|
+
|
|
452
|
+
# Unfunction _ghostty_deferred_init to save memory. Don't unfunction
|
|
453
|
+
# ghostty-integration though because decent public functions aren't supposed to
|
|
454
|
+
# to unfunction themselves when invoked. Unfunctioning is done by calling code.
|
|
455
|
+
builtin unfunction _ghostty_deferred_init
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
_entrypoint
|
|
Binary file
|
|
Binary file
|