fish shell integration

This commit is contained in:
Mitchell Hashimoto
2023-07-06 16:10:30 -07:00
parent ae206b2f89
commit ad62e3ac1b
4 changed files with 98 additions and 2 deletions

View File

@ -8,6 +8,7 @@
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
A535B9DA299C569B0017E2E4 /* ErrorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A535B9D9299C569B0017E2E4 /* ErrorView.swift */; }; A535B9DA299C569B0017E2E4 /* ErrorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A535B9D9299C569B0017E2E4 /* ErrorView.swift */; };
A545D1A22A5772CE006E0AE4 /* shell-integration in Resources */ = {isa = PBXBuildFile; fileRef = A545D1A12A5772CE006E0AE4 /* shell-integration */; };
A55685E029A03A9F004303CE /* AppError.swift in Sources */ = {isa = PBXBuildFile; fileRef = A55685DF29A03A9F004303CE /* AppError.swift */; }; A55685E029A03A9F004303CE /* AppError.swift in Sources */ = {isa = PBXBuildFile; fileRef = A55685DF29A03A9F004303CE /* AppError.swift */; };
A55B7BB629B6F47F0055DE60 /* AppState.swift in Sources */ = {isa = PBXBuildFile; fileRef = A55B7BB529B6F47F0055DE60 /* AppState.swift */; }; A55B7BB629B6F47F0055DE60 /* AppState.swift in Sources */ = {isa = PBXBuildFile; fileRef = A55B7BB529B6F47F0055DE60 /* AppState.swift */; };
A55B7BB829B6F53A0055DE60 /* Package.swift in Sources */ = {isa = PBXBuildFile; fileRef = A55B7BB729B6F53A0055DE60 /* Package.swift */; }; A55B7BB829B6F53A0055DE60 /* Package.swift in Sources */ = {isa = PBXBuildFile; fileRef = A55B7BB729B6F53A0055DE60 /* Package.swift */; };
@ -27,6 +28,7 @@
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
A535B9D9299C569B0017E2E4 /* ErrorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorView.swift; sourceTree = "<group>"; }; A535B9D9299C569B0017E2E4 /* ErrorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorView.swift; sourceTree = "<group>"; };
A545D1A12A5772CE006E0AE4 /* shell-integration */ = {isa = PBXFileReference; lastKnownFileType = folder; name = "shell-integration"; path = "../zig-out/share/shell-integration"; sourceTree = "<group>"; };
A55685DF29A03A9F004303CE /* AppError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppError.swift; sourceTree = "<group>"; }; A55685DF29A03A9F004303CE /* AppError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppError.swift; sourceTree = "<group>"; };
A55B7BB529B6F47F0055DE60 /* AppState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppState.swift; sourceTree = "<group>"; }; A55B7BB529B6F47F0055DE60 /* AppState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppState.swift; sourceTree = "<group>"; };
A55B7BB729B6F53A0055DE60 /* Package.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Package.swift; sourceTree = "<group>"; }; A55B7BB729B6F53A0055DE60 /* Package.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Package.swift; sourceTree = "<group>"; };
@ -90,6 +92,7 @@
A5A1F8862A489D7400D1E8BC /* Resources */ = { A5A1F8862A489D7400D1E8BC /* Resources */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
A545D1A12A5772CE006E0AE4 /* shell-integration */,
A5A1F8842A489D6800D1E8BC /* terminfo */, A5A1F8842A489D6800D1E8BC /* terminfo */,
); );
name = Resources; name = Resources;
@ -198,6 +201,7 @@
isa = PBXResourcesBuildPhase; isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
A545D1A22A5772CE006E0AE4 /* shell-integration in Resources */,
A5A1F8852A489D6800D1E8BC /* terminfo in Resources */, A5A1F8852A489D6800D1E8BC /* terminfo in Resources */,
A5B30539299BEAAB0047F10C /* Assets.xcassets in Resources */, A5B30539299BEAAB0047F10C /* Assets.xcassets in Resources */,
); );

View File

@ -1,3 +1,91 @@
#!/bin/fish #!/bin/fish
#
# This shell script aims to be written in a way where it can't really fail
# or all failure scenarios are handled, so that we never leave the shell in
# a weird state. If you find a way to break this, please report a bug!
echo GHOSTTY INTEGRATION LOADING function ghostty_restore_xdg_data_dir -d "restore the original XDG_DATA_DIR value"
# If we don't have our own data dir then we don't need to do anything.
if not set -q GHOSTTY_FISH_XDG_DIR
return
end
# If the data dir isn't set at all then we don't need to do anything.
if not set -q XDG_DATA_DIRS
return
end
# We need to do this so that XDG_DATA_DIRS turns into an array.
set --function --path xdg_data_dirs "$XDG_DATA_DIRS"
# If our data dir is in the list then remove it.
if set --function index (contains --index "$GHOSTTY_FISH_XDG_DIR" $xdg_data_dirs)
set --erase --function xdg_data_dirs[$index]
end
# Re-export our data dir
if set -q xdg_data_dirs[1]
set --global --export --unpath XDG_DATA_DIRS "$xdg_data_dirs"
else
set --erase --global XDG_DATA_DIRS
end
set --erase GHOSTTY_FISH_XDG_DIR
end
function ghostty_exit -d "exit the shell integration setup"
functions -e ghostty_restore_xdg_data_dir
functions -e ghostty_exit
exit 0
end
# We always try to restore the XDG data dir
ghostty_restore_xdg_data_dir
# If we aren't interactive or we've already run, don't run.
status --is-interactive || ghostty_exit
# We do the full setup on the first prompt render. We do this so that other
# shell integrations that setup the prompt and modify things are able to run
# first. We want to run _last_.
function __ghostty_setup --on-event fish_prompt -d "Setup ghostty integration"
functions -e __ghostty_setup
# Change the cursor to a beam on prompt.
function __ghostty_set_cursor_beam --on-event fish_prompt -d "Set cursor shape"
echo -en "\e[5 q"
end
function __ghostty_reset_cursor --on-event fish_preexec -d "Reset cursor shape"
echo -en "\e[0 q"
end
# Setup prompt marking
function __ghostty_mark_prompt_start --on-event fish_prompt --on-event fish_cancel --on-event fish_posterror
# If we never got the output end event, then we need to send it now.
if test "$__ghostty_prompt_state" != prompt-start
echo -en "\e]133;D\a"
end
set --global __ghostty_prompt_state prompt-start
echo -en "\e]133;A\a"
end
function __ghostty_mark_output_start --on-event fish_preexec
set --global __ghostty_prompt_state pre-exec
echo -en "\e]133;C\a"
end
function __ghostty_mark_output_end --on-event fish_postexec
set --global __ghostty_prompt_state post-exec
echo -en "\e]133;D;$status\a"
end
# Enable fish to handle reflow because Ghostty clears the prompt on resize.
set --global fish_handle_reflow 1
# Initial calls for first prompt
__ghostty_set_cursor_beam
__ghostty_mark_prompt_start
end
ghostty_exit

View File

@ -530,6 +530,9 @@ const Subprocess = struct {
// Get our bundled resources directory, if it exists. We use this // Get our bundled resources directory, if it exists. We use this
// for terminfo, shell-integration, etc. // for terminfo, shell-integration, etc.
const resources_dir = try resourcesDir(alloc); const resources_dir = try resourcesDir(alloc);
if (resources_dir) |dir| {
try env.put("GHOSTTY_RESOURCES_DIR", dir);
}
// Set our TERM var. This is a bit complicated because we want to use // Set our TERM var. This is a bit complicated because we want to use
// the ghostty TERM value but we want to only do that if we have // the ghostty TERM value but we want to only do that if we have

View File

@ -46,7 +46,7 @@ fn setupFish(
// Set an env var so we can remove this from XDG_DATA_DIRS later. // Set an env var so we can remove this from XDG_DATA_DIRS later.
// This happens in the shell integration config itself. We do this // This happens in the shell integration config itself. We do this
// so that our modifications don't interfere with other commands. // so that our modifications don't interfere with other commands.
try env.put("GHOSTTY_FISH_DIR", integ_dir); try env.put("GHOSTTY_FISH_XDG_DIR", integ_dir);
if (env.get("XDG_DATA_DIRS")) |old| { if (env.get("XDG_DATA_DIRS")) |old| {
// We have an old value, We need to prepend our value to it. // We have an old value, We need to prepend our value to it.
@ -62,6 +62,7 @@ fn setupFish(
"{s}{c}{s}", "{s}{c}{s}",
.{ integ_dir, std.fs.path.delimiter, old }, .{ integ_dir, std.fs.path.delimiter, old },
); );
try env.put("XDG_DATA_DIRS", prepended); try env.put("XDG_DATA_DIRS", prepended);
} else { } else {
// No XDG_DATA_DIRS set, we just set it our desired value. // No XDG_DATA_DIRS set, we just set it our desired value.