Initial public release of Warp.
Repo-Sync-Origin: warpdotdev/warp-internal@12af1d983b
|
After Width: | Height: | Size: 793 KiB |
|
After Width: | Height: | Size: 830 KiB |
|
After Width: | Height: | Size: 671 KiB |
|
After Width: | Height: | Size: 716 KiB |
|
After Width: | Height: | Size: 529 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 433 KiB |
|
After Width: | Height: | Size: 422 KiB |
|
After Width: | Height: | Size: 467 KiB |
|
After Width: | Height: | Size: 982 KiB |
|
After Width: | Height: | Size: 723 KiB |
|
After Width: | Height: | Size: 792 KiB |
|
After Width: | Height: | Size: 686 KiB |
|
After Width: | Height: | Size: 1.4 MiB |
|
After Width: | Height: | Size: 321 KiB |
|
After Width: | Height: | Size: 382 KiB |
|
After Width: | Height: | Size: 494 KiB |
|
After Width: | Height: | Size: 299 KiB |
|
After Width: | Height: | Size: 1.3 MiB |
|
After Width: | Height: | Size: 644 KiB |
|
After Width: | Height: | Size: 475 KiB |
|
After Width: | Height: | Size: 272 KiB |
|
After Width: | Height: | Size: 987 KiB |
|
After Width: | Height: | Size: 532 KiB |
|
After Width: | Height: | Size: 777 KiB |
|
After Width: | Height: | Size: 1.4 MiB |
|
After Width: | Height: | Size: 1.5 MiB |
|
After Width: | Height: | Size: 1.2 MiB |
|
After Width: | Height: | Size: 1.2 MiB |
|
After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 1.2 MiB |
|
After Width: | Height: | Size: 1.2 MiB |
|
After Width: | Height: | Size: 896 KiB |
|
After Width: | Height: | Size: 895 KiB |
|
After Width: | Height: | Size: 968 KiB |
|
After Width: | Height: | Size: 959 KiB |
|
After Width: | Height: | Size: 1.0 MiB |
|
After Width: | Height: | Size: 1.0 MiB |
|
After Width: | Height: | Size: 590 KiB |
|
After Width: | Height: | Size: 648 KiB |
|
After Width: | Height: | Size: 539 KiB |
|
After Width: | Height: | Size: 584 KiB |
|
After Width: | Height: | Size: 523 KiB |
|
After Width: | Height: | Size: 583 KiB |
|
After Width: | Height: | Size: 612 KiB |
|
After Width: | Height: | Size: 692 KiB |
|
After Width: | Height: | Size: 124 KiB |
|
After Width: | Height: | Size: 1.8 MiB |
|
After Width: | Height: | Size: 69 KiB |
|
After Width: | Height: | Size: 762 KiB |
|
After Width: | Height: | Size: 1.4 MiB |
|
After Width: | Height: | Size: 822 KiB |
|
After Width: | Height: | Size: 886 KiB |
|
After Width: | Height: | Size: 943 KiB |
|
After Width: | Height: | Size: 1024 KiB |
|
After Width: | Height: | Size: 590 KiB |
|
After Width: | Height: | Size: 663 KiB |
|
After Width: | Height: | Size: 760 KiB |
|
After Width: | Height: | Size: 827 KiB |
|
After Width: | Height: | Size: 194 KiB |
|
After Width: | Height: | Size: 254 KiB |
|
After Width: | Height: | Size: 187 KiB |
|
After Width: | Height: | Size: 226 KiB |
|
After Width: | Height: | Size: 187 KiB |
|
After Width: | Height: | Size: 377 KiB |
|
After Width: | Height: | Size: 504 KiB |
|
After Width: | Height: | Size: 554 KiB |
|
After Width: | Height: | Size: 770 KiB |
|
After Width: | Height: | Size: 871 KiB |
|
After Width: | Height: | Size: 677 KiB |
|
After Width: | Height: | Size: 813 KiB |
|
After Width: | Height: | Size: 724 KiB |
|
After Width: | Height: | Size: 859 KiB |
|
After Width: | Height: | Size: 692 KiB |
|
After Width: | Height: | Size: 504 KiB |
|
After Width: | Height: | Size: 479 KiB |
|
After Width: | Height: | Size: 329 KiB |
|
After Width: | Height: | Size: 877 KiB |
|
After Width: | Height: | Size: 1.1 MiB |
@@ -0,0 +1,21 @@
|
||||
The MIT License
|
||||
|
||||
Copyright (c) 2017 Ryan Caloras and contributors (see https://github.com/rcaloras/bash-preexec)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
@@ -0,0 +1,443 @@
|
||||
# We need to prepend a space to all the top-level commands here to prevent
|
||||
# Warp bootstrap script contents from showing up in the history.
|
||||
|
||||
# Keep track of whether bash-preexec was included in /etc/bash.bashrc.
|
||||
if [[ $bash_preexec_imported == "defined" || $__bp_imported == "defined" ]]; then
|
||||
BASH_PREEXEC_IN_ETC_BASHRC=1
|
||||
fi
|
||||
# Ensure that nothing already loaded by the shell (e.g.: bash-preexec sourced
|
||||
# in /etc/bash.bashrc) unset the HISTCONTROL variable.
|
||||
HISTCONTROL=ignorespace
|
||||
# Unset HISTIGNORE, which we set via the initial bash command in shell.rs, as
|
||||
# we only need it long enough to ensure HISTCONTROL is set to ignorespace.
|
||||
unset HISTIGNORE
|
||||
|
||||
# This function defines all the bash-preexec functions and sets up a bunch of the environment variables.
|
||||
# Another function, install_bashpreexec will actually install the plugin.
|
||||
# Its contents are pretty much pasted from bash-preexec.
|
||||
# The three differences are :
|
||||
# 1. We remove the guard for duplicate inclusion since we have different logic in warp where we execute this function.
|
||||
# 2. As mentioned, we separate the actual installation step to install_bashpreexec. I just took those last three lines
|
||||
# out of bash-preexec and separated them to that different function.
|
||||
# 3. We don't modify the HISTCONTROL var in bp_install to avoid clobbering the variable for users.
|
||||
function define_bashpreexec_functions() {
|
||||
# bash-preexec.sh -- Bash support for ZSH-like 'preexec' and 'precmd' functions.
|
||||
# https://github.com/rcaloras/bash-preexec
|
||||
#
|
||||
#
|
||||
# 'preexec' functions are executed before each interactive command is
|
||||
# executed, with the interactive command as its argument. The 'precmd'
|
||||
# function is executed before each prompt is displayed.
|
||||
#
|
||||
# Author: Ryan Caloras (ryan@bashhub.com)
|
||||
# Forked from Original Author: Glyph Lefkowitz
|
||||
#
|
||||
# V0.4.1
|
||||
#
|
||||
|
||||
# General Usage:
|
||||
#
|
||||
# 1. Source this file at the end of your bash profile so as not to interfere
|
||||
# with anything else that's using PROMPT_COMMAND.
|
||||
#
|
||||
# 2. Add any precmd or preexec functions by appending them to their arrays:
|
||||
# e.g.
|
||||
# precmd_functions+=(my_precmd_function)
|
||||
# precmd_functions+=(some_other_precmd_function)
|
||||
#
|
||||
# preexec_functions+=(my_preexec_function)
|
||||
#
|
||||
# 3. Consider changing anything using the DEBUG trap or PROMPT_COMMAND
|
||||
# to use preexec and precmd instead. Preexisting usages will be
|
||||
# preserved, but doing so manually may be less surprising.
|
||||
#
|
||||
# Note: This module requires two Bash features which you must not otherwise be
|
||||
# using: the "DEBUG" trap, and the "PROMPT_COMMAND" variable. If you override
|
||||
# either of these after bash-preexec has been installed it will most likely break.
|
||||
|
||||
#### In Warp's inclusion of bash-preexec, we don't include these two guards
|
||||
#### at the beginning of the script. Instead, we use bash_preexec_imported and __bp_imported to
|
||||
#### determine whether we want to execute bash-preexec or not.
|
||||
# Make sure this is bash that's running and return otherwise.
|
||||
#if [[ -z "${BASH_VERSION:-}" ]]; then
|
||||
# return 1;
|
||||
#fi
|
||||
#
|
||||
## Avoid duplicate inclusion
|
||||
#if [[ -n "${bash_preexec_imported:-}" ]]; then
|
||||
# return 0
|
||||
#fi
|
||||
#### End of difference 1/4 between Warp and bash-preexec's original source.
|
||||
bash_preexec_imported="defined"
|
||||
|
||||
# WARNING: This variable is no longer used and should not be relied upon.
|
||||
# Use ${bash_preexec_imported} instead.
|
||||
# shellcheck disable=SC2034
|
||||
__bp_imported="${bash_preexec_imported}"
|
||||
|
||||
# Should be available to each precmd and preexec
|
||||
# functions, should they want it. $? and $_ are available as $? and $_, but
|
||||
# $PIPESTATUS is available only in a copy, $BP_PIPESTATUS.
|
||||
# TODO: Figure out how to restore PIPESTATUS before each precmd or preexec
|
||||
# function.
|
||||
__bp_last_ret_value="$?"
|
||||
BP_PIPESTATUS=("${PIPESTATUS[@]}")
|
||||
__bp_last_argument_prev_command="$_"
|
||||
|
||||
__bp_inside_precmd=0
|
||||
__bp_inside_preexec=0
|
||||
|
||||
# Initial PROMPT_COMMAND string that is removed from PROMPT_COMMAND post __bp_install
|
||||
__bp_install_string=$'__bp_trap_string="$(trap -p DEBUG)"\ntrap - DEBUG\n__bp_install'
|
||||
|
||||
# Fails if any of the given variables are readonly
|
||||
# Reference https://stackoverflow.com/a/4441178
|
||||
__bp_require_not_readonly() {
|
||||
local var
|
||||
for var; do
|
||||
if ! ( unset "$var" 2> /dev/null ); then
|
||||
echo "bash-preexec requires write access to ${var}" >&2
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# Remove ignorespace and or replace ignoreboth from HISTCONTROL
|
||||
# so we can accurately invoke preexec with a command from our
|
||||
# history even if it starts with a space.
|
||||
__bp_adjust_histcontrol() {
|
||||
local histcontrol
|
||||
histcontrol="${HISTCONTROL:-}"
|
||||
histcontrol="${histcontrol//ignorespace}"
|
||||
# Replace ignoreboth with ignoredups
|
||||
if [[ "$histcontrol" == *"ignoreboth"* ]]; then
|
||||
histcontrol="ignoredups:${histcontrol//ignoreboth}"
|
||||
fi;
|
||||
export HISTCONTROL="$histcontrol"
|
||||
}
|
||||
|
||||
# This variable describes whether we are currently in "interactive mode";
|
||||
# i.e. whether this shell has just executed a prompt and is waiting for user
|
||||
# input. It documents whether the current command invoked by the trace hook is
|
||||
# run interactively by the user; it's set immediately after the prompt hook,
|
||||
# and unset as soon as the trace hook is run.
|
||||
__bp_preexec_interactive_mode=""
|
||||
|
||||
# These arrays are used to add functions to be run before, or after, prompts.
|
||||
declare -a precmd_functions
|
||||
declare -a preexec_functions
|
||||
|
||||
# Trims leading and trailing whitespace from $2 and writes it to the variable
|
||||
# name passed as $1
|
||||
__bp_trim_whitespace() {
|
||||
local var=${1:?} text=${2:-}
|
||||
text="${text#"${text%%[![:space:]]*}"}" # remove leading whitespace characters
|
||||
text="${text%"${text##*[![:space:]]}"}" # remove trailing whitespace characters
|
||||
printf -v "$var" '%s' "$text"
|
||||
}
|
||||
|
||||
|
||||
# Trims whitespace and removes any leading or trailing semicolons from $2 and
|
||||
# writes the resulting string to the variable name passed as $1. Used for
|
||||
# manipulating substrings in PROMPT_COMMAND
|
||||
__bp_sanitize_string() {
|
||||
local var=${1:?} text=${2:-} sanitized
|
||||
__bp_trim_whitespace sanitized "$text"
|
||||
sanitized=${sanitized%;}
|
||||
sanitized=${sanitized#;}
|
||||
__bp_trim_whitespace sanitized "$sanitized"
|
||||
printf -v "$var" '%s' "$sanitized"
|
||||
}
|
||||
|
||||
# This function is installed as part of the PROMPT_COMMAND;
|
||||
# It sets a variable to indicate that the prompt was just displayed,
|
||||
# to allow the DEBUG trap to know that the next command is likely interactive.
|
||||
__bp_interactive_mode() {
|
||||
__bp_preexec_interactive_mode="on";
|
||||
}
|
||||
|
||||
|
||||
# This function is installed as part of the PROMPT_COMMAND.
|
||||
# It will invoke any functions defined in the precmd_functions array.
|
||||
__bp_precmd_invoke_cmd() {
|
||||
# Save the returned value from our last command, and from each process in
|
||||
# its pipeline. Note: this MUST be the first thing done in this function.
|
||||
# BP_PIPESTATUS may be unused, ignore
|
||||
# shellcheck disable=SC2034
|
||||
|
||||
__bp_last_ret_value="$?" BP_PIPESTATUS=("${PIPESTATUS[@]}")
|
||||
|
||||
# Don't invoke precmds if we are inside an execution of an "original
|
||||
# prompt command" by another precmd execution loop. This avoids infinite
|
||||
# recursion.
|
||||
if (( __bp_inside_precmd > 0 )); then
|
||||
return
|
||||
fi
|
||||
local __bp_inside_precmd=1
|
||||
|
||||
# Invoke every function defined in our function array.
|
||||
local precmd_function
|
||||
for precmd_function in "${precmd_functions[@]}"; do
|
||||
|
||||
# Only execute this function if it actually exists.
|
||||
# Test existence of functions with: declare -[Ff]
|
||||
if type -t "$precmd_function" 1>/dev/null; then
|
||||
__bp_set_ret_value "$__bp_last_ret_value" "$__bp_last_argument_prev_command"
|
||||
# Quote our function invocation to prevent issues with IFS
|
||||
"$precmd_function"
|
||||
fi
|
||||
done
|
||||
|
||||
__bp_set_ret_value "$__bp_last_ret_value"
|
||||
}
|
||||
|
||||
# Sets a return value in $?. We may want to get access to the $? variable in our
|
||||
# precmd functions. This is available for instance in zsh. We can simulate it in bash
|
||||
# by setting the value here.
|
||||
__bp_set_ret_value() {
|
||||
return ${1:+"$1"}
|
||||
}
|
||||
|
||||
__bp_in_prompt_command() {
|
||||
|
||||
local prompt_command_array IFS=$'\n;'
|
||||
read -rd '' -a prompt_command_array <<< "${PROMPT_COMMAND[*]:-}"
|
||||
|
||||
local trimmed_arg
|
||||
__bp_trim_whitespace trimmed_arg "${1:-}"
|
||||
|
||||
local command trimmed_command
|
||||
for command in "${prompt_command_array[@]:-}"; do
|
||||
__bp_trim_whitespace trimmed_command "$command"
|
||||
if [[ "$trimmed_command" == "$trimmed_arg" ]]; then
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
# This function is installed as the DEBUG trap. It is invoked before each
|
||||
# interactive prompt display. Its purpose is to inspect the current
|
||||
# environment to attempt to detect if the current command is being invoked
|
||||
# interactively, and invoke 'preexec' if so.
|
||||
__bp_preexec_invoke_exec() {
|
||||
|
||||
# Save the contents of $_ so that it can be restored later on.
|
||||
# https://stackoverflow.com/questions/40944532/bash-preserve-in-a-debug-trap#40944702
|
||||
__bp_last_argument_prev_command="${1:-}"
|
||||
# Don't invoke preexecs if we are inside of another preexec.
|
||||
if (( __bp_inside_preexec > 0 )); then
|
||||
return
|
||||
fi
|
||||
local __bp_inside_preexec=1
|
||||
|
||||
# Checks if the file descriptor is not standard out (i.e. '1')
|
||||
# __bp_delay_install checks if we're in test. Needed for bats to run.
|
||||
# Prevents preexec from being invoked for functions in PS1
|
||||
if [[ ! -t 1 && -z "${__bp_delay_install:-}" ]]; then
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ -n "${COMP_LINE:-}" ]]; then
|
||||
# We're in the middle of a completer. This obviously can't be
|
||||
# an interactively issued command.
|
||||
return
|
||||
fi
|
||||
|
||||
#### For Warp, the clause below prevents the typeahead readline binding from triggering
|
||||
#### preexec, which would otherwise break the typeahead/background process implementation.
|
||||
if [[ -n "${READLINE_LINE+x}" ]]; then
|
||||
# We're in the middle of a readline binding to a shell command. Since
|
||||
# this means the line editor is active, there can't be an interactive
|
||||
# command running.
|
||||
return
|
||||
fi
|
||||
#### End of difference 2/4 between Warp and bash-preexec's original source.
|
||||
|
||||
if [[ -z "${__bp_preexec_interactive_mode:-}" ]]; then
|
||||
# We're doing something related to displaying the prompt. Let the
|
||||
# prompt set the title instead of me.
|
||||
return
|
||||
else
|
||||
# If we're in a subshell, then the prompt won't be re-displayed to put
|
||||
# us back into interactive mode, so let's not set the variable back.
|
||||
# In other words, if you have a subshell like
|
||||
# (sleep 1; sleep 2)
|
||||
# You want to see the 'sleep 2' as a set_command_title as well.
|
||||
if [[ 0 -eq "${BASH_SUBSHELL:-}" ]]; then
|
||||
__bp_preexec_interactive_mode=""
|
||||
fi
|
||||
fi
|
||||
|
||||
if __bp_in_prompt_command "${BASH_COMMAND:-}"; then
|
||||
# If we're executing something inside our prompt_command then we don't
|
||||
# want to call preexec. Bash prior to 3.1 can't detect this at all :/
|
||||
__bp_preexec_interactive_mode=""
|
||||
return
|
||||
fi
|
||||
|
||||
local this_command
|
||||
this_command=$(
|
||||
export LC_ALL=C
|
||||
HISTTIMEFORMAT='' builtin history 1 | sed '1 s/^ *[0-9][0-9]*[* ] //'
|
||||
)
|
||||
|
||||
# Sanity check to make sure we have something to invoke our function with.
|
||||
if [[ -z "$this_command" ]]; then
|
||||
return
|
||||
fi
|
||||
|
||||
# Invoke every function defined in our function array.
|
||||
local preexec_function
|
||||
local preexec_function_ret_value
|
||||
local preexec_ret_value=0
|
||||
for preexec_function in "${preexec_functions[@]:-}"; do
|
||||
|
||||
# Only execute each function if it actually exists.
|
||||
# Test existence of function with: declare -[fF]
|
||||
if type -t "$preexec_function" 1>/dev/null; then
|
||||
__bp_set_ret_value "${__bp_last_ret_value:-}"
|
||||
# Quote our function invocation to prevent issues with IFS
|
||||
"$preexec_function" "$this_command"
|
||||
preexec_function_ret_value="$?"
|
||||
if [[ "$preexec_function_ret_value" != 0 ]]; then
|
||||
preexec_ret_value="$preexec_function_ret_value"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
# Restore the last argument of the last executed command, and set the return
|
||||
# value of the DEBUG trap to be the return code of the last preexec function
|
||||
# to return an error.
|
||||
# If `extdebug` is enabled a non-zero return value from any preexec function
|
||||
# will cause the user's command not to execute.
|
||||
# Run `shopt -s extdebug` to enable
|
||||
__bp_set_ret_value "$preexec_ret_value" "$__bp_last_argument_prev_command"
|
||||
}
|
||||
|
||||
__bp_install() {
|
||||
# Exit if we already have this installed.
|
||||
if [[ "${PROMPT_COMMAND[*]:-}" == *"__bp_precmd_invoke_cmd"* ]]; then
|
||||
return 1;
|
||||
fi
|
||||
|
||||
trap '__bp_preexec_invoke_exec "$_"' DEBUG
|
||||
|
||||
# Preserve any prior DEBUG trap as a preexec function
|
||||
local prior_trap
|
||||
# we can't easily do this with variable expansion. Leaving as sed command.
|
||||
# shellcheck disable=SC2001
|
||||
prior_trap=$(sed "s/[^']*'\(.*\)'[^']*/\1/" <<<"${__bp_trap_string:-}")
|
||||
unset __bp_trap_string
|
||||
if [[ -n "$prior_trap" ]]; then
|
||||
eval '__bp_original_debug_trap() {
|
||||
'"$prior_trap"'
|
||||
}'
|
||||
preexec_functions+=(__bp_original_debug_trap)
|
||||
fi
|
||||
|
||||
# Note: this method diverges from the bash_preexec script in that
|
||||
# we don't call __bp_adjust_histcontrol because of
|
||||
# https://linear.app/warpdotdev/issue/WAR-2592.
|
||||
# End of difference 3/4 between Warp and bash-preexec's original source.
|
||||
|
||||
# Issue #25. Setting debug trap for subshells causes sessions to exit for
|
||||
# backgrounded subshell commands (e.g. (pwd)& ). Believe this is a bug in Bash.
|
||||
#
|
||||
# Disabling this by default. It can be enabled by setting this variable.
|
||||
if [[ -n "${__bp_enable_subshells:-}" ]]; then
|
||||
|
||||
# Set so debug trap will work be invoked in subshells.
|
||||
set -o functrace > /dev/null 2>&1
|
||||
shopt -s extdebug > /dev/null 2>&1
|
||||
fi;
|
||||
|
||||
local existing_prompt_command
|
||||
# Remove setting our trap install string and sanitize the existing prompt command string
|
||||
existing_prompt_command="${PROMPT_COMMAND:-}"
|
||||
# Edge case of appending to PROMPT_COMMAND
|
||||
existing_prompt_command="${existing_prompt_command//$__bp_install_string/:}" # no-op
|
||||
existing_prompt_command="${existing_prompt_command//$'\n':$'\n'/$'\n'}" # remove known-token only
|
||||
existing_prompt_command="${existing_prompt_command//$'\n':;/$'\n'}" # remove known-token only
|
||||
__bp_sanitize_string existing_prompt_command "$existing_prompt_command"
|
||||
if [[ "${existing_prompt_command:-:}" == ":" ]]; then
|
||||
existing_prompt_command=
|
||||
fi
|
||||
|
||||
# Install our hooks in PROMPT_COMMAND to allow our trap to know when we've
|
||||
# actually entered something.
|
||||
PROMPT_COMMAND='__bp_precmd_invoke_cmd'
|
||||
PROMPT_COMMAND+=${existing_prompt_command:+$'\n'$existing_prompt_command}
|
||||
if (( BASH_VERSINFO[0] > 5 || (BASH_VERSINFO[0] == 5 && BASH_VERSINFO[1] >= 1) )); then
|
||||
PROMPT_COMMAND+=('__bp_interactive_mode')
|
||||
else
|
||||
# shellcheck disable=SC2179 # PROMPT_COMMAND is not an array in bash <= 5.0
|
||||
PROMPT_COMMAND+=$'\n__bp_interactive_mode'
|
||||
fi
|
||||
|
||||
# Add two functions to our arrays for convenience
|
||||
# of definition.
|
||||
precmd_functions+=(precmd)
|
||||
preexec_functions+=(preexec)
|
||||
|
||||
# Invoke our two functions manually that were added to $PROMPT_COMMAND
|
||||
__bp_precmd_invoke_cmd
|
||||
__bp_interactive_mode
|
||||
}
|
||||
|
||||
# Sets an installation string as part of our PROMPT_COMMAND to install
|
||||
# after our session has started. This allows bash-preexec to be included
|
||||
# at any point in our bash profile.
|
||||
__bp_install_after_session_init() {
|
||||
# bash-preexec needs to modify these variables in order to work correctly
|
||||
# if it can't, just stop the installation
|
||||
__bp_require_not_readonly PROMPT_COMMAND HISTCONTROL HISTTIMEFORMAT || return
|
||||
|
||||
local sanitized_prompt_command
|
||||
__bp_sanitize_string sanitized_prompt_command "${PROMPT_COMMAND:-}"
|
||||
if [[ -n "$sanitized_prompt_command" ]]; then
|
||||
# shellcheck disable=SC2178 # PROMPT_COMMAND is not an array in bash <= 5.0
|
||||
PROMPT_COMMAND=${sanitized_prompt_command}$'\n'
|
||||
fi;
|
||||
# shellcheck disable=SC2179 # PROMPT_COMMAND is not an array in bash <= 5.0
|
||||
PROMPT_COMMAND+=${__bp_install_string}
|
||||
}
|
||||
### In Warp, we run this last install step in the install_bashpreexec
|
||||
### function so this is commented out here.
|
||||
## Run our install so long as we're not delaying it.
|
||||
#if [[ -z "${__bp_delay_install:-}" ]]; then
|
||||
# __bp_install_after_session_init
|
||||
#fi;
|
||||
### End of difference 4/4 between Warp and bash-preexec's original source.
|
||||
}
|
||||
|
||||
function install_bashpreexec() {
|
||||
# Run our install so long as we're not delaying it.
|
||||
if [[ -z "${__bp_delay_install:-}" ]]; then
|
||||
__bp_install_after_session_init
|
||||
fi;
|
||||
}
|
||||
|
||||
# This string, after interpolation of the contents of bash_body.sh, contains
|
||||
# the warp bootstrap script. We take over startup from the shell so we have
|
||||
# more control over when the various startup files run. At a high level,
|
||||
# whenever we start a shell, we try and get it to do as little as possible and
|
||||
# then take over when we input these contents into the PTY. We also minimize
|
||||
# the side effects of doing this to give the user a seamless experience.
|
||||
#
|
||||
# Starting a shell happens before this string is evaluated, and that happens either
|
||||
# locally where we create a new PTY, or remotely, in a SSH wrapper. In both cases,
|
||||
# we use the --rcfile option so *no* startup files are evaluated. In our
|
||||
# custom rcfile, we turn off the line editor to work around a bug that
|
||||
# prevented us from reliably inputting our script. And then
|
||||
# we notify the terminal to input these characters in. For the remote case,
|
||||
# we actually start in an interactive non-login shell (i.e. it runs ~/.bashrc),
|
||||
# but it gets replaced by a new shell that we fully control.
|
||||
read -r -d '' WARP_BOOTSTRAP_VAR << 'EOM'
|
||||
#include bundled/bootstrap/bash_body.sh
|
||||
EOM
|
||||
# We need to restore the line editor before we evaluate the bootstrap logic
|
||||
# or everything freezes up
|
||||
stty sane
|
||||
eval "$WARP_BOOTSTRAP_VAR"; unset WARP_BOOTSTRAP_VAR
|
||||
@@ -0,0 +1,15 @@
|
||||
# command -p resolves the given command with the system default PATH, ensuring the shell
|
||||
# can find them even if the user has a clobbered PATH value.
|
||||
command -p stty raw
|
||||
HISTCONTROL=ignorespace
|
||||
HISTIGNORE=" *"
|
||||
WARP_SESSION_ID="$(command -p date +%s)$RANDOM"
|
||||
_hostname=$(command -pv hostname >/dev/null 2>&1 && command -p hostname 2>/dev/null || command -p uname -n)
|
||||
_user=$(command -pv whoami >/dev/null 2>&1 && command -p whoami 2>/dev/null || echo $USER)
|
||||
if [[ "$OS" == Windows_NT ]]; then WARP_IN_MSYS2=true; else WARP_IN_MSYS2=false; fi
|
||||
# If we're in MSYS2, we want to send the hook via key-value pairs.
|
||||
if [ "$WARP_IN_MSYS2" = true ]; then _msg="\e]9278;k;A;InitShell\a\e]9278;k;B;session_id;$WARP_SESSION_ID\a\e]9278;k;B;shell;bash\a\e]9278;k;B;user;$_user\a\e]9278;k;B;hostname;$_hostname\a\e]9278;k;C\a"; else _msg=$(printf "{\"hook\": \"InitShell\", \"value\": {\"session_id\": $WARP_SESSION_ID, \"shell\": \"bash\", \"user\": \"%s\", \"hostname\": \"%s\"}}" "$_user" "$_hostname" | command -p od -An -v -tx1 | command -p tr -d " \n"); fi
|
||||
WARP_USING_WINDOWS_CON_PTY=@@USING_CON_PTY_BOOLEAN@@
|
||||
# We send the InitShell hook via OSCs when on Windows and via DCSs otherwise.
|
||||
if [ "$WARP_USING_WINDOWS_CON_PTY" = true ]; then if [ "$WARP_IN_MSYS2" = true ]; then printf "$_msg"; else printf '\e]9278;d;%s\x07' "$_msg"; fi; else printf '\e\x50\x24\x64%s\x9c' "$_msg"; fi
|
||||
unset _hostname _user _msg
|
||||
@@ -0,0 +1,15 @@
|
||||
# command -p resolves the given command with the system default PATH, ensuring the shell
|
||||
# can find them even if the user has a clobbered PATH value.
|
||||
command -p stty raw
|
||||
unset PROMPT_COMMAND
|
||||
HISTCONTROL=ignorespace
|
||||
HISTIGNORE=" *"
|
||||
WARP_IS_SUBSHELL=1
|
||||
WARP_SESSION_ID="$(command -p date +%s)$RANDOM"
|
||||
_hostname=$(command -pv hostname >/dev/null 2>&1 && command -p hostname 2>/dev/null || command -p uname -n)
|
||||
_user=$(command -pv whoami >/dev/null 2>&1 && command -p whoami 2>/dev/null || echo $USER)
|
||||
_msg=$(printf "{\"hook\": \"InitShell\", \"value\": {\"session_id\": $WARP_SESSION_ID, \"shell\": \"bash\", \"user\": \"%s\", \"hostname\": \"%s\", \"is_subshell\": true}}" "$_user" "$_hostname" | command -p od -An -v -tx1 | command -p tr -d " \n")
|
||||
if [[ "$OS" == Windows_NT ]]; then WARP_IN_MSYS2=true; else WARP_IN_MSYS2=false; fi
|
||||
WARP_USING_WINDOWS_CON_PTY=@@USING_CON_PTY_BOOLEAN@@
|
||||
if [ "$WARP_USING_WINDOWS_CON_PTY" = true ]; then printf '\e]9278;d;%s\x07' "$_msg"; else printf '\e\x50\x24\x64%s\x9c' "$_msg"; fi
|
||||
unset _hostname _user _msg
|
||||
@@ -0,0 +1 @@
|
||||
echo -e '\n# Auto-Warpify\n[[ "$-" == *i* ]] && printf '\''\eP$f{"hook": "SourcedRcFileForWarp", "value": { "shell": "%", "uname": "'$(uname)'"% }}\x9c'\'' ' >> %
|
||||
@@ -0,0 +1,724 @@
|
||||
# Note that WARP_SESSION_ID is expected to have been set when executing commands to
|
||||
# emit the InitShell payload, which includes the session ID.
|
||||
begin
|
||||
# We wrap ourselves in a begin block because these are effectively injected
|
||||
# keystrokes, and we want to execute this whole script as a single command.
|
||||
# Of course we are fish script, not POSIX shell script.
|
||||
# Set fish_private_mode to prevent saving to history.
|
||||
# Note: We don't add a leading space to the `begin` command here because this entire script is
|
||||
# pasted into fish with bracketed paste, and Fish strips out the leading whitespace. Instead,
|
||||
# we insert the space _before_ pasting the script in, which has the same effect
|
||||
set -l saved_fish_private_mode $fish_private_mode
|
||||
set -g fish_private_mode 1
|
||||
|
||||
# Disable fish autosuggestions - because input goes through Warp's editor instead,
|
||||
# they are never actionable, and the extra output can cause problems.
|
||||
set -g fish_autosuggestion_enabled 0
|
||||
|
||||
# Byte sequence used to signal the start of a DCS. ([0x1b, 0x50, 0x24] which
|
||||
# maps to <ESC>, P, $ in ASCII.)
|
||||
set -g DCS_START \u1b\u50\u24
|
||||
|
||||
# Appended to $DCS_START to signal that the following message is JSON-encoded.
|
||||
# The Rust app also receives non-JSON-encoded DCS's sent from
|
||||
# _warp_run_generator_command_internal, which instead end in 'e' (0x65).
|
||||
set -g DCS_JSON_MARKER 'd'
|
||||
|
||||
set -g DCS_END \u9c
|
||||
|
||||
set -g OSC_START (printf '\e]9278;')
|
||||
|
||||
set -g OSC_END (printf '\a')
|
||||
|
||||
set -g OSC_PARAM_SEPARATOR ';'
|
||||
|
||||
set -g RESET_GRID_OSC (printf '\e]9279\a')
|
||||
|
||||
if test -n "$WARP_INITIAL_WORKING_DIR"
|
||||
cd "$WARP_INITIAL_WORKING_DIR" >/dev/null 2>&1
|
||||
set -e WARP_INITIAL_WORKING_DIR
|
||||
end
|
||||
|
||||
# Append additional PATH entries if provided via WARP_PATH_APPEND.
|
||||
if test -n "$WARP_PATH_APPEND"
|
||||
set -gx --path PATH "$PATH:$WARP_PATH_APPEND"
|
||||
set -e WARP_PATH_APPEND
|
||||
end
|
||||
|
||||
function warp_send_json_message
|
||||
# Sends a message to the controlling terminal as a DSC control sequence.
|
||||
set -l escaped_json (warp_hex_encode_string "$argv")
|
||||
if [ "$WARP_USING_WINDOWS_CON_PTY" = true ]
|
||||
echo -n "$OSC_START$DCS_JSON_MARKER$OSC_PARAM_SEPARATOR$escaped_json$OSC_END"
|
||||
else
|
||||
echo -n "$DCS_START$DCS_JSON_MARKER$escaped_json$DCS_END"
|
||||
end
|
||||
end
|
||||
|
||||
function warp_maybe_send_reset_grid_osc
|
||||
# Note that $WARP_USING_WINDOWS_CON_PTY is set in the init shell script.
|
||||
if [ "$WARP_USING_WINDOWS_CON_PTY" = true ]
|
||||
printf $RESET_GRID_OSC
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# warp_hex_encode_string hex-encodes the given string with `od`.
|
||||
function warp_hex_encode_string
|
||||
echo "$argv" | od -An -v -tx1 | command tr -d ' \n'
|
||||
end
|
||||
|
||||
# A list of PIDs for running in-band command(s). This is used to kill running
|
||||
# in-band commands in preexec for a user command, so they do not interfere with
|
||||
# user command output.
|
||||
set -g _warp_generator_pids ''
|
||||
|
||||
# Runs the given command in the background, records its PID in
|
||||
# _WARP_GENERATOR_PIDS_STARTED_TMP_FILE, and adds its PID from the file when
|
||||
# the job is completed.
|
||||
#
|
||||
# Usage:
|
||||
# _warp_run_generator_command_internal <command_id> '<command>'
|
||||
#
|
||||
# The first argument is the command's ID, which is included in the DCS string sent
|
||||
# to the rust app. The second argument is the command string itself.
|
||||
function _warp_run_generator_command_internal
|
||||
set -l command_id $argv[1]
|
||||
set -l command (string join -- ' ' (string escape $argv[2]))
|
||||
# Fish cannot run shell functions in the background, so in order to run
|
||||
# the command in the the background we spawn a fish process, inlining the
|
||||
# code necessary to write the command's output OSC to the rust app. This
|
||||
# differs from the bash and zsh implementations, which rely on running
|
||||
# functions in the background.
|
||||
#
|
||||
# The `IFS` has to be set to the empty string to prevent fish from converting
|
||||
# the command output into a list by splitting output on newlines (fish splits
|
||||
# strings on $IFS into lists). Essentially, setting IFS to the empty string
|
||||
# allows us to preserve newlines in command output (that might be relied
|
||||
# upon) for parsing output.
|
||||
#
|
||||
# N.B. Fish shell variables cannot contain null characters, so the command output must be
|
||||
# immediately hex encoded before being stored in a variable.
|
||||
fish -c "
|
||||
set -l warp_using_windows_con_pty $WARP_USING_WINDOWS_CON_PTY;
|
||||
set -l reset_grid_osc $RESET_GRID_OSC;
|
||||
function warp_maybe_send_reset_grid_osc
|
||||
if [ \"\$warp_using_windows_con_pty\" = true ]
|
||||
printf \$reset_grid_osc
|
||||
end
|
||||
end
|
||||
set -l OSC_START_GENERATOR_OUTPUT \$(printf '\e]9277;A\a')
|
||||
set -l OSC_END_GENERATOR_OUTPUT \$(printf '\e]9277;B\a')
|
||||
set -l command_id $command_id;
|
||||
set -l command $command;
|
||||
set -l IFS;
|
||||
begin
|
||||
echo -n \"\$command_id;\"
|
||||
eval \$command 2>&1
|
||||
echo -n \";\$status\"
|
||||
end | od -An -v -tx1 | command tr -d ' \n' | read -lz hex_encoded_message
|
||||
set -l LC_ALL \"C\"
|
||||
set -l byte_count (string length \"\$hex_encoded_message\")
|
||||
echo -n \"\$OSC_START_GENERATOR_OUTPUT\$byte_count;\$hex_encoded_message\$OSC_END_GENERATOR_OUTPUT\"
|
||||
warp_maybe_send_reset_grid_osc" 2> /dev/null &
|
||||
|
||||
set -l command_pid $last_pid
|
||||
set -a _warp_generator_pids $command_pid
|
||||
|
||||
# Remove the command's PID from _warp_generator_pids when the command exits.
|
||||
function on_command_{$command_pid}_finish --on-process-exit $command_pid --inherit-variable command_pid
|
||||
set -g _warp_generator_pids (string replace $command_pid '' $_warp_generator_pids)
|
||||
|
||||
# Erase this function after the pids list is updated above so we don't create an infinite number of
|
||||
# functions that could pollute the user's context (nested functions are still existing in the global
|
||||
# scope).
|
||||
functions -e on_command_{$command_pid}_finish
|
||||
|
||||
# Note: If we're on windows, we send a reset grid to erase any cursor mutations caused by
|
||||
# the in-band command.
|
||||
warp_maybe_send_reset_grid_osc
|
||||
end
|
||||
end
|
||||
|
||||
# Executes a generator command in the background, where the first argument is
|
||||
# the "command ID" assigned by the Rust app and the second-nth arguments
|
||||
# specify the command to be run.
|
||||
#
|
||||
# Note that the command string should be single-quoted so any variables are
|
||||
# not substituted until the command string is actually evaluated.
|
||||
#
|
||||
# Usage:
|
||||
# warp_run_generator_command <command_id> '<command> <arg1> ... <argn>'
|
||||
function warp_run_generator_command
|
||||
# Setting this environment variable allows warp_precmd to detect if a generator
|
||||
# command or a user command has just completed.
|
||||
set -g _WARP_GENERATOR_COMMAND 1
|
||||
_warp_run_generator_command_internal $argv
|
||||
end
|
||||
|
||||
# Run before a command is executed.
|
||||
function warp_preexec --on-event fish_preexec
|
||||
set -l command (warp_escape_json "$argv")
|
||||
warp_send_json_message "{\"hook\": \"Preexec\", \"value\": {\"command\": \"$command\"}}"
|
||||
warp_maybe_send_reset_grid_osc
|
||||
|
||||
# If this preexec is called for user command, kill ongoing generator command jobs.
|
||||
if test (! string match -q "warp_run_generator_command*" $argv[1])
|
||||
for pid in $_warp_generator_pids
|
||||
# Surpress stderr output; kill writes to stderr if any of the given
|
||||
# PIDS are not running (which might rarely be the case due to race
|
||||
# conditions in checking which PIDS to cancel and this kill command.
|
||||
kill -9 $pids >/dev/null 2>/dev/null
|
||||
end
|
||||
set -g _warp_generator_pids ''
|
||||
end
|
||||
end
|
||||
|
||||
# The git prompts git commands are read-only and should not interfere with
|
||||
# other processes. This environment variable is equivalent to running with `git
|
||||
# --no-optional-locks`, but falls back gracefully for older versions of git.
|
||||
# See git(1) for and git-status(1) for a description of that flag.
|
||||
#
|
||||
# We wrap in a local function instead of exporting the variable directly in
|
||||
# order to avoid interfering with manually-run git commands by the user.
|
||||
function warp_git
|
||||
GIT_OPTIONAL_LOCKS=0 command git $argv
|
||||
end
|
||||
|
||||
# Wrap fish prompt function output with OSC prompt marker sequences,
|
||||
# so that we can direct the prompt bytes to the appropriate grids.
|
||||
function warp_update_prompt_vars
|
||||
# Back up the original fish_prompt if not already done
|
||||
if not functions -q warp_original_fish_prompt
|
||||
functions -c fish_prompt warp_original_fish_prompt
|
||||
end
|
||||
|
||||
# Back up the original fish_right_prompt if it exists and not already backed up
|
||||
if functions -q fish_right_prompt; and not functions -q warp_original_fish_right_prompt
|
||||
functions -c fish_right_prompt warp_original_fish_right_prompt
|
||||
end
|
||||
|
||||
# If not honoring PS1, set both prompts to be empty
|
||||
if test "$WARP_HONOR_PS1" = "0"
|
||||
function fish_prompt; echo -n ""; end
|
||||
function fish_right_prompt; echo -n ""; end
|
||||
# If honoring PS1, add prefix/suffix to both prompts
|
||||
else
|
||||
|
||||
function end_prompt
|
||||
echo -n (printf '\x1b')
|
||||
if test "$WARP_HONOR_PS1" != "1" && [ "$WARP_USING_WINDOWS_CON_PTY" = true ]
|
||||
echo -n "]133;B$RESET_GRID_OSC"
|
||||
else
|
||||
echo -n ']133;B'
|
||||
end
|
||||
echo -n (printf '\x07')
|
||||
end
|
||||
|
||||
# Redefine fish_prompt to include prefix and suffix
|
||||
function fish_prompt
|
||||
echo -n (printf '\x1b')
|
||||
echo -n ']133;A'
|
||||
echo -n (printf '\x07')
|
||||
warp_original_fish_prompt
|
||||
end_prompt
|
||||
end
|
||||
|
||||
# Check if warp_original_fish_right_prompt was backed up before redefining fish_right_prompt
|
||||
if functions -q warp_original_fish_right_prompt
|
||||
function fish_right_prompt
|
||||
echo -n (printf '\x1b')
|
||||
echo -n ']133;P;k=r'
|
||||
echo -n (printf '\x07')
|
||||
warp_original_fish_right_prompt
|
||||
end_prompt
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Changes the WARP_HONOR_PS1 variable to 1, to indicate we want to use the user's custom prompt. Restores
|
||||
# the original fish prompt functions (which we set to empty for Warp prompt) by calling warp_update_prompt_vars
|
||||
# to refresh the prompt. We force a repaint of the prompt to ensure the change is reflected immediately.
|
||||
function warp_change_prompt_modes_to_ps1
|
||||
set -x WARP_HONOR_PS1 "1"
|
||||
|
||||
# Restores fish_prompt and fish_right_prompt.
|
||||
warp_update_prompt_vars
|
||||
# Forces a repaint of the current prompt to ensure the change is reflected immediately.
|
||||
commandline -f repaint
|
||||
end
|
||||
|
||||
# Changes the WARP_HONOR_PS1 variable to 0, to indicate we want to use the Warp prompt. Saves and clears
|
||||
# the fish prompt functions (which we set to empty for Warp prompt) by calling warp_update_prompt_vars
|
||||
# to refresh the prompt. We force a repaint of the prompt to ensure the change is reflected immediately.
|
||||
function warp_change_prompt_modes_to_warp_prompt
|
||||
set -x WARP_HONOR_PS1 "0"
|
||||
|
||||
# Updates fish_prompt and fish_right_prompt to be empty.
|
||||
warp_update_prompt_vars
|
||||
# Forces a repaint of the current prompt to ensure the change is reflected immediately.
|
||||
commandline -f repaint
|
||||
end
|
||||
|
||||
set block_id 0
|
||||
# Run before the prompt is displayed. We also need to trigger this on "fish_posterror", as
|
||||
# submitting a command containing a syntax error will not trigger "fish_preexec" or "fish_prompt".
|
||||
function warp_precmd --on-event fish_prompt --on-event fish_posterror
|
||||
# Handle prompt behavior (we do this first to make sure the exit status is from the command,
|
||||
# rather than from our own code)
|
||||
set -l exit_code $status
|
||||
|
||||
# This function is triggered by both "fish_prompt" and "fish_posterror" events. If it was
|
||||
# "fish_prompt", then $status will be properly set. If it was "fish_posterror", it won't be.
|
||||
# We want to set the exit code to 1 for errors, but there is no direct way to check which event
|
||||
# triggered this function call. The length of $argv actually tells us, as "fish_posterror"
|
||||
# passes the erroneous command while "fish_prompt" passes nothing.
|
||||
if test (count $argv) -gt 0
|
||||
set exit_code 1
|
||||
end
|
||||
|
||||
warp_send_json_message "{\"hook\": \"CommandFinished\", \"value\": {\"exit_code\": $exit_code, \"next_block_id\": \"precmd-$WARP_SESSION_ID-$block_id\"}}"
|
||||
warp_maybe_send_reset_grid_osc
|
||||
|
||||
set block_id (math $block_id + 1)
|
||||
|
||||
if ! test -z $_WARP_GENERATOR_COMMAND
|
||||
set -e _WARP_GENERATOR_COMMAND
|
||||
set -l escaped_json "{\"hook\": \"Precmd\", \"value\": {
|
||||
\"pwd\": \"\",
|
||||
\"ps1\": \"\",
|
||||
\"git_head\": \"\",
|
||||
\"git_branch\": \"\",
|
||||
\"virtual_env\": \"\",
|
||||
\"conda_env\": \"\",
|
||||
\"node_version\": \"\",
|
||||
\"session_id\": $WARP_SESSION_ID,
|
||||
\"is_after_in_band_command\": true
|
||||
}}"
|
||||
warp_send_json_message $escaped_json
|
||||
return 0
|
||||
end
|
||||
|
||||
# Fish's vi mode causes a conflict with the input reporting binding.
|
||||
# Set the bindings back for this session. Note that just calling fish_default_key_bindings
|
||||
# affects other sessions so we do it this way instead.
|
||||
set -g fish_key_bindings fish_default_key_bindings
|
||||
|
||||
# Do not use kill-line because of the kill ring interation.
|
||||
bind \cP "commandline ''"
|
||||
|
||||
# We use the ESC-p bindkey for this ("p" for PS1/custom prompt).
|
||||
bind \ep warp_change_prompt_modes_to_ps1
|
||||
|
||||
# We use the ESC-w bindkey for this ("w" for Warp prompt).
|
||||
bind \ew warp_change_prompt_modes_to_warp_prompt
|
||||
|
||||
bind \ei warp_report_input
|
||||
|
||||
# Define local variables in appropriate outer block for fish variable scoping.
|
||||
# See https://stackoverflow.com/a/53685510.
|
||||
set -l escaped_prompt
|
||||
set -l escaped_right_prompt
|
||||
|
||||
set -l escaped_pwd
|
||||
if set -q WSL_DISTRO_NAME
|
||||
# In WSL, avoid symlinks b/c on Windows `std::fs` is unable to resolve symlink inside WSL containers.
|
||||
set escaped_pwd (warp_escape_json (pwd -P))
|
||||
else
|
||||
set escaped_pwd (warp_escape_json $PWD)
|
||||
end
|
||||
|
||||
set -l escaped_virtual_env ""
|
||||
set -l escaped_conda_env ""
|
||||
set -l escaped_node_version ""
|
||||
set -l escaped_git_head ""
|
||||
set -l escaped_git_branch ""
|
||||
|
||||
# Only fill these fields once we've finished bootstrapping, as the
|
||||
# blocks created during the bootstrap process don't have visible
|
||||
# prompts, and we don't want to invoke `git` before we've sourced the
|
||||
# user's rcfiles and have a fully-populated PATH.
|
||||
if test -n "$WARP_BOOTSTRAPPED"
|
||||
if test -n "$VIRTUAL_ENV"
|
||||
set escaped_virtual_env (warp_escape_json "$VIRTUAL_ENV")
|
||||
end
|
||||
if test -n "$CONDA_DEFAULT_ENV"
|
||||
set escaped_conda_env (warp_escape_json "$CONDA_DEFAULT_ENV")
|
||||
end
|
||||
|
||||
# Get Node.js version if node is available and we're in a Node.js project
|
||||
if command -v node > /dev/null 2>&1
|
||||
# Check for package.json in current directory and parent directories
|
||||
set current_dir (pwd)
|
||||
set found_package_json false
|
||||
set package_json_dir ""
|
||||
while test "$current_dir" != "/"
|
||||
if test -f "$current_dir/package.json"
|
||||
set found_package_json true
|
||||
set package_json_dir "$current_dir"
|
||||
break
|
||||
end
|
||||
set current_dir (dirname "$current_dir")
|
||||
end
|
||||
|
||||
# Only show node version if package.json is within a git repository
|
||||
if test "$found_package_json" = true
|
||||
set git_dir "$package_json_dir"
|
||||
set in_git_repo false
|
||||
while test "$git_dir" != "/"
|
||||
if test -d "$git_dir/.git"
|
||||
set in_git_repo true
|
||||
break
|
||||
end
|
||||
set git_dir (dirname "$git_dir")
|
||||
end
|
||||
|
||||
if test "$in_git_repo" = true
|
||||
set node_version (node --version 2>/dev/null)
|
||||
if test -n "$node_version"
|
||||
set escaped_node_version (warp_escape_json "$node_version")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
set -l git_branch ""
|
||||
set -l git_head ""
|
||||
if command -q git
|
||||
set git_branch (warp_git symbolic-ref --short HEAD 2> /dev/null)
|
||||
if test -z "$git_branch"
|
||||
# Fallback to the git commit hash if we aren't on a named branch.
|
||||
set git_head (warp_git rev-parse --short HEAD 2> /dev/null)
|
||||
else
|
||||
set git_head "$git_branch"
|
||||
end
|
||||
end
|
||||
set escaped_git_head (warp_escape_json "$git_head")
|
||||
set escaped_git_branch (warp_escape_json "$git_branch")
|
||||
end
|
||||
|
||||
warp_update_prompt_vars
|
||||
# This is used solely for prompt previews, when we're using prompt markers with combined grid.
|
||||
# We need to use this since fish does not have a way to ignore printable characters for cursor
|
||||
# positioning (unlike zsh/bash), so we need a separate mechansim to send the prompt to Warp
|
||||
# in the case of Warp prompt (for previewing the PS1). We send an escaped version of the raw prompt
|
||||
# bytes via a hex string (in a JSON payload) to Warp.
|
||||
# Note that we are CALLING the `warp_original_fish_prompt` function on the next line and assigning the
|
||||
# outputted string to the local variable `raw_prompt_for_preview`.
|
||||
set -l raw_prompt_for_preview (warp_original_fish_prompt)
|
||||
# We encode the prompt as a hex string to pass it to Warp.
|
||||
set escaped_prompt (warp_escape_prompt "$raw_prompt_for_preview")
|
||||
|
||||
set -l escaped_json
|
||||
if test "$WARP_HONOR_PS1" = "1"
|
||||
# Don't send lprompt or rprompt in this case - we'll use prompt markers for both directly!
|
||||
set escaped_json "{\"hook\": \"Precmd\", \"value\": {
|
||||
\"pwd\": \"$escaped_pwd\",
|
||||
\"ps1\": \"\",
|
||||
\"rprompt\": \"\",
|
||||
\"git_head\": \"$escaped_git_head\",
|
||||
\"git_branch\": \"$escaped_git_branch\",
|
||||
\"virtual_env\": \"$escaped_virtual_env\",
|
||||
\"conda_env\": \"$escaped_conda_env\",
|
||||
\"node_version\": \"$escaped_node_version\",
|
||||
\"session_id\": $WARP_SESSION_ID
|
||||
}}"
|
||||
else
|
||||
# We send an lprompt to use for prompt preview purposes only (we still use prompt markers for active prompts).
|
||||
set escaped_json "{\"hook\": \"Precmd\", \"value\": {
|
||||
\"pwd\": \"$escaped_pwd\",
|
||||
\"ps1\": \"$escaped_prompt\",
|
||||
\"rprompt\": \"\",
|
||||
\"git_head\": \"$escaped_git_head\",
|
||||
\"git_branch\": \"$escaped_git_branch\",
|
||||
\"virtual_env\": \"$escaped_virtual_env\",
|
||||
\"conda_env\": \"$escaped_conda_env\",
|
||||
\"node_version\": \"$escaped_node_version\",
|
||||
\"session_id\": $WARP_SESSION_ID
|
||||
}}"
|
||||
end
|
||||
warp_send_json_message $escaped_json
|
||||
end
|
||||
|
||||
function warp_escape_prompt
|
||||
# To match the implementation of PS1 support in bash / zsh, we use the same method of encoding
|
||||
# the prompt as a hex string so that it can be interpreted on the Warp side
|
||||
# Note: before converting the prompt to a hex string, we remove any multi-line newlines and
|
||||
# replace them with a single space (to avoid prompts that span multiple empty lines)
|
||||
echo "$argv" | command tr '\n\n' ' ' | command od -An -v -tx1 | command tr -d ' \n'
|
||||
end
|
||||
|
||||
# Escapes string(s) passed as input to be JSON-serializable.
|
||||
#
|
||||
# Specifically, special characters like backspace, tab, form feed, carriage return, and newlines
|
||||
# are replaced with escaped equivalents. Double quotes and literal backslash characters are also
|
||||
# backslash-escaped.
|
||||
function warp_escape_json
|
||||
# Explanation of the sed replacements (each command is separated by a `;`):
|
||||
# s/(["\\])/\\\1/g - Replace all double-quote (") and backslash (\) characters with the escaped versions (\" and \\)
|
||||
# s/\b/\\b/g - Replace all backspace characters with \b
|
||||
# s/\t/\\t/g - Replace all tab characters with \t
|
||||
# s/\f/\\f/g - Replace all form feed characters with \f
|
||||
# s/\r/\\r/g - Replace all carriage return characters with \r
|
||||
# $!s/$/\\\\n/ - Replace any newlines (except the last trailing newline) with the literal \n character
|
||||
#
|
||||
# Additional note: In Fish, backslashes still need to be escaped in single quoted strings. So each `\\` below
|
||||
# represents a single `\` in the above regex explanation. We also close the single-quoted string in order to
|
||||
# insert literal characters (Fish supports literals with escapes when not quoting)
|
||||
#
|
||||
# We also use 'command sed' to ensure that we aren't accidentally executing a function named 'sed'
|
||||
string join \n $argv | command sed -E 's/(["\\\\])/\\\\\\1/g; s/'\b'/\\\\b/g; s/'\t'/\\\\t/g; s/'\f'/\\\\f/g; s/'\r'/\\\\r/g; $!s/$/\\\\n/' | command tr -d '\n'
|
||||
end
|
||||
|
||||
function warp_bootstrapped
|
||||
set -l histfile_directory
|
||||
set histfile_directory "$XDG_DATA_HOME"
|
||||
if test -z "$histfile_directory"
|
||||
set histfile_directory "$HOME/.local/share"
|
||||
end
|
||||
set -l escaped_histfile (warp_escape_json "$histfile_directory/fish/fish_history")
|
||||
|
||||
set -l vi_mode_enabled ""
|
||||
if [ "$fish_key_bindings" = "fish_vi_key_bindings" ]
|
||||
set vi_mode_enabled "1"
|
||||
end
|
||||
|
||||
set -l kernel_name (uname)
|
||||
if test -n "$kernel_name"
|
||||
if [ "$kernel_name" = "Darwin" ]
|
||||
set os_category "MacOS"
|
||||
else if [ "$kernel_name" = "Linux" ]
|
||||
set os_category "Linux"
|
||||
set -l default_os_release_filepath "/etc/os-release"
|
||||
set -l fallback_os_release_filepath "/usr/lib/os-release"
|
||||
# We first try /etc/os-release and then try /usr/lib/os-release as a fallback.
|
||||
if test -f "$default_os_release_filepath"
|
||||
set os_release_file "$default_os_release_filepath";
|
||||
else if test -f "$fallback_os_release_filepath"
|
||||
set os_release_file "$fallback_os_release_filepath";
|
||||
end
|
||||
if test -f "$os_release_file"
|
||||
set linux_distribution (cat $os_release_file | sed -nE 's/^NAME="(.*)"$/\1/p')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
set -l escaped_abbr (warp_escape_json (abbr --show))
|
||||
set -l escaped_aliases (warp_escape_json (alias))
|
||||
set -l env_var_names (warp_escape_json (set --names))
|
||||
set -l function_names (warp_escape_json (functions -an))
|
||||
set -l escaped_builtins (warp_escape_json (builtin -n))
|
||||
# Note "keywords" is set to an empty string since fish includes keywords as a
|
||||
# part of its builtins (e.g. "for", "while", etc.).
|
||||
set -l escaped_editor (warp_escape_json "$EDITOR")
|
||||
set -l escaped_shell_path (warp_escape_json (status fish-path))
|
||||
set -l escaped_json "{\"hook\": \"Bootstrapped\", \"value\": {\"histfile\": \"$escaped_histfile\", \"shell\": \"fish\", \"home_dir\": \"$HOME\", \"path\": \"$PATH\", \"editor\": \"$escaped_editor\", \"abbreviations\": \"$escaped_abbr\", \"aliases\": \"$escaped_aliases\", \"function_names\": \"$function_names\", \"env_var_names\": \"$env_var_names\", \"builtins\": \"$escaped_builtins\", \"keywords\": \"\", \"shell_version\": \"$FISH_VERSION\", \"vi_mode_enabled\": \"$vi_mode_enabled\", \"os_category\": \"$os_category\", \"linux_distribution\": \"$linux_distribution\", \"wsl_name\": \"$WSL_DISTRO_NAME\", \"shell_path\": \"$escaped_shell_path\"}}"
|
||||
warp_send_json_message $escaped_json
|
||||
end
|
||||
|
||||
function warp_init_shell
|
||||
set -l init_shell "{\"hook\": \"InitShell\", \"value\": {\"shell\": \"$argv\"}}"
|
||||
warp_hex_encode_string "$init_shell"
|
||||
end
|
||||
|
||||
# Add a key binding to report the current input buffer to Warp. We can override
|
||||
# any user-defined binds here because user input goes through Warp's editor, not
|
||||
# the fish line editor.
|
||||
# This is arbitrarily bound to ESC-i in all supported shells ("i" for input).
|
||||
# Binding to ESC-1 caused bootstrap failures with vi keybindings.
|
||||
function warp_report_input
|
||||
set -l escaped_input (warp_escape_json (commandline))
|
||||
warp_send_json_message "{ \"hook\": \"InputBuffer\", \"value\": { \"buffer\": \"$escaped_input\" } }"
|
||||
# This prevents fish from rendering typeahead as background output once we've collected it.
|
||||
commandline ''
|
||||
end
|
||||
|
||||
function clear
|
||||
warp_send_json_message "{\"hook\": \"Clear\", \"value\": {}}"
|
||||
end
|
||||
|
||||
function warp_finish_update
|
||||
set -l update_id "$argv[1]"
|
||||
warp_send_json_message "{\"hook\": \"FinishUpdate\", \"value\": { \"update_id\": \"$update_id\"}}"
|
||||
end
|
||||
|
||||
|
||||
# Check if the warp apt source file has been renamed to `warpdotdev.list.distUpgrade` due to an ubuntu version update.
|
||||
# If this occurred, we want to rename the source file back to `warpdotdev.list` to ensure updates can proceed.
|
||||
# We purposefully skip this if either the `warpdotdev.list` file already exists (indicating that the user has already
|
||||
# done this themselves) _or_ if a `warpdotdev.sources` file exists (which is the new Deb822 format for source files).
|
||||
# The `.sources` file could only exist if a user manually created it; Ubuntu doesn't create one automatically for the
|
||||
# warp source file due to a bug in its update flow where it considers our source file to be "invalid" because it
|
||||
# contains a `signed-by` key.
|
||||
function warp_handle_dist_upgrade
|
||||
set -l source_file_name "$argv[1]"
|
||||
|
||||
# The `apt-config shell` command outputs an environment variable assignment in POSIX-compliant syntax. Therefore,
|
||||
# we need to run this from within an sh shell to actually get the correct directory for the sources dir.
|
||||
set -l APT_SOURCESDIR (command sh -c 'eval $(apt-config shell APT_SOURCESDIR "Dir::Etc::sourceparts/d"); echo $APT_SOURCESDIR')
|
||||
|
||||
if not test -e $APT_SOURCESDIR$source_file_name.list; and not test -e $APT_SOURCESDIR$source_file_name.sources; and test -e $APT_SOURCESDIR$source_file_name.list.distUpgrade
|
||||
# DO NOT DO THIS. We should never run a command for user with `sudo`. The only reason this is safe here is because
|
||||
# we insert this function into the input for the user to determine if they want to execute (we never run it on
|
||||
# their behalf without their permission). To be transparent about what is being executed with sudo, we echo out the
|
||||
# command we're about to run.
|
||||
echo "Executing: sudo cp \"$APT_SOURCESDIR$source_file_name.list.distUpgrade\" \"$APT_SOURCESDIR$source_file_name.list\""
|
||||
sudo cp "$APT_SOURCESDIR$source_file_name.list.distUpgrade" "$APT_SOURCESDIR$source_file_name.list"
|
||||
end
|
||||
end
|
||||
|
||||
# The SSH logic only applies to local sessions, because we don't yet have support for bootstrapping
|
||||
# recursive SSH sessions.
|
||||
if test "$WARP_IS_LOCAL_SHELL_SESSION" = "1"
|
||||
function is_interactive_ssh_session
|
||||
# Parse through all ssh options, as defined in the ssh man pages. Send
|
||||
# stderr to /dev/null to silence argparse output when an option is invalid.
|
||||
argparse '1' '2' '4' '6' 'A' 'a' 'C' 'f' 'g' 'K' 'k' 'M' 'N' 'n' 'q' 's' 'T' 't' 'V' 'v' 'X' 'x' 'Y' 'y' 'b=' 'c=' 'D=' 'e=' 'F=' 'i=' 'L=' 'l=' 'm=' 'O=' 'o=' 'p=' 'R=' 'S=' 'W=' 'w=' -- $argv 2>/dev/null
|
||||
# If argparse returned a non-success value, propagate it up.
|
||||
or return
|
||||
|
||||
if [ $_flag_T ]
|
||||
# -T disables pty allocation (aka a non-interactive session)
|
||||
return 1
|
||||
end
|
||||
if [ $_flag_W ]
|
||||
# -W implies -T
|
||||
return 1
|
||||
end
|
||||
|
||||
# If there is more than one positional argument, the user is attempting to
|
||||
# run a command, not start an interactive session. If there is less than
|
||||
# one positional argument, the user should be shown the usage text.
|
||||
if [ (count $argv) -ne 1 ]
|
||||
return 1
|
||||
end
|
||||
end
|
||||
|
||||
function warp_ssh_helper
|
||||
set -l init_shell_zsh (warp_init_shell "zsh")
|
||||
set -l init_shell_bash (warp_init_shell "bash")
|
||||
# Hex-encode the ZSH environment script we use to bootstrap remote zsh b/c it contains control characters
|
||||
# We decode on the SSH server using xxd if its available, otherwise fall back to a for-loop over each byte
|
||||
# and use printf to convert back to plaintext
|
||||
set -l zsh_env_script (printf '%s' 'unsetopt ZLE; unset RCS; unset GLOBAL_RCS; WARP_SESSION_ID="$(command -p date +%s)$RANDOM"; WARP_USING_WINDOWS_CON_PTY=@@USING_CON_PTY_BOOLEAN@@; WARP_HONOR_PS1='$WARP_HONOR_PS1'; _hostname=$(command -pv hostname >/dev/null 2>&1 && command -p hostname 2>/dev/null || uname -n); _user=$(command -pv whoami >/dev/null 2>&1 && command -p whoami 2>/dev/null || echo $USER); _msg=$(printf "{\"hook\": \"InitShell\", \"value\": {\"session_id\": $WARP_SESSION_ID, \"shell\": \"zsh\", \"user\": \"%s\", \"hostname\": \"%s\"}}" "$_user" "$_hostname" | command -p od -An -v -tx1 | command -p tr -d " \n"); printf '"'"'\x1b\x50\x24\x64%s\x9c'"'"' $_msg; unset _hostname _user _msg' | command od -An -v -tx1 | command tr -d ' \n')
|
||||
|
||||
# Note that in this command, we're passing a string to the remote shell. Any variable expansions need to be
|
||||
# escaped with "''" to avoid the local shell from expanding them before they're passed to the remote shell.
|
||||
# We check the SHELL env var and use shell string manipulation to get the contents after the last slash to
|
||||
# determine what shell is the login shell on the remote machine. We perform a preliminary check to see if
|
||||
# the remote shell is the Bourne shell to avoid asking it to parse later lines that use syntax it doesn't
|
||||
# support.
|
||||
command ssh -o ControlMaster=yes -o ControlPath=$SSH_SOCKET_DIR/$WARP_SESSION_ID \
|
||||
-t $argv \
|
||||
"
|
||||
export TERM_PROGRAM='WarpTerminal'
|
||||
test -n '$WARP_CLIENT_VERSION' && export WARP_CLIENT_VERSION='$WARP_CLIENT_VERSION'
|
||||
# Only forward the protocol version if it was set locally (i.e. the HOANotifications feature flag is on).
|
||||
test -n '$WARP_CLI_AGENT_PROTOCOL_VERSION' && export WARP_CLI_AGENT_PROTOCOL_VERSION='$WARP_CLI_AGENT_PROTOCOL_VERSION'
|
||||
hook="'$(printf "{\"hook\": \"SSH\", \"value\": {\"socket_path\": \"'$SSH_SOCKET_DIR/$WARP_SESSION_ID'\", \"remote_shell\": \"%s\"}}" "${SHELL##*/}" | command od -An -v -tx1 | command tr -d " \n")'"
|
||||
printf '$DCS_START$DCS_JSON_MARKER%s$DCS_END' "'$hook'"
|
||||
|
||||
if test "'"${SHELL##*/}" != "bash" -a "${SHELL##*/}" != "zsh"'"; then
|
||||
# Emulate the SSHD logic to print the MotD. Because the Warp SSH wrapper passes
|
||||
# a command to run, SSHD does a quiet login, updating utmp and other login
|
||||
# state, but not printing the MotD. For bash and zsh, this is instead handled
|
||||
# by our bootstrap script.
|
||||
if test ! -e "'$HOME/.hushlogin'"; then
|
||||
# This uses an if-else chain instead of a for-loop to avoid expansion issues on older shells.
|
||||
if test -r /etc/motd; then
|
||||
cat /etc/motd
|
||||
elif test -r /run/motd; then
|
||||
cat /run/motd
|
||||
elif test -r /run/motd.dynamic; then
|
||||
cat /run/motd.dynamic
|
||||
elif test -r /usr/lib/motd; then
|
||||
cat /usr/lib/motd
|
||||
elif test -r /usr/lib/motd.dynamic; then
|
||||
cat /usr/lib/motd.dynamic
|
||||
fi
|
||||
fi
|
||||
# Likewise, emulate a login shell by sourcing /etc/profile
|
||||
if test -r /etc/profile; then
|
||||
. /etc/profile
|
||||
fi
|
||||
exec "'$SHELL'"
|
||||
fi
|
||||
|
||||
case "'${SHELL##*/}'" in
|
||||
bash)
|
||||
exec -a bash bash --rcfile <(echo '"'
|
||||
stty raw
|
||||
HISTCONTROL=ignorespace
|
||||
HISTIGNORE=" *"
|
||||
WARP_SESSION_ID="$(command -p date +%s)$RANDOM"
|
||||
WARP_HONOR_PS1="'$WARP_HONOR_PS1'"
|
||||
_hostname=$(command -pv hostname >/dev/null 2>&1 && command -p hostname 2>/dev/null || uname -n)
|
||||
_user=$(command -pv whoami >/dev/null 2>&1 && command -p whoami 2>/dev/null || echo $USER)
|
||||
_msg=$(printf "{\"hook\": \"InitShell\", \"value\": {\"session_id\": $WARP_SESSION_ID, \"shell\": \"bash\", \"user\": \"%s\", \"hostname\": \"%s\"}}" "$_user" "$_hostname" | command -p od -An -v -tx1 | command -p tr -d " \n")'"
|
||||
WARP_USING_WINDOWS_CON_PTY=@@USING_CON_PTY_BOOLEAN@@
|
||||
if [[ "'$OS'" == Windows_NT ]]; then WARP_IN_MSYS2=true; else WARP_IN_MSYS2=false; fi
|
||||
printf '\''"'\eP$d%s\x9c'"'\'' \""'$_msg'"\"'
|
||||
unset _hostname _user _msg
|
||||
)
|
||||
;;
|
||||
zsh) WARP_TMP_DIR="'$(mktemp -d warptmp.XXXXXX)'"
|
||||
local ZSH_ENV_SCRIPT='$zsh_env_script'
|
||||
if [[ "'$?'" == 0 ]]; then
|
||||
if command -v xxd >/dev/null 2>&1; then
|
||||
echo "'$ZSH_ENV_SCRIPT'" | command xxd -p -r > "'$WARP_TMP_DIR'"/.zshenv
|
||||
else
|
||||
for i in {0..\$((\${#ZSH_ENV_SCRIPT} - 1))..2}; do
|
||||
builtin printf "'"\x${ZSH_ENV_SCRIPT:$i:2}"'"
|
||||
done > "'$WARP_TMP_DIR'"/.zshenv
|
||||
fi
|
||||
else
|
||||
echo \"Failed to bootstrap warp. Continuing with a non-bootstrapped shell.\"
|
||||
fi
|
||||
TMPPREFIX="'$HOME/.zshtmp-'" WARP_SSH_RCFILES="'${ZDOTDIR:-$HOME}'" ZDOTDIR="'$WARP_TMP_DIR'" exec -l zsh -g $TRACE_FLAG_IF_WARP_SHELL_DEBUG_MODE
|
||||
;;
|
||||
esac
|
||||
"
|
||||
end
|
||||
|
||||
function ssh
|
||||
if is_interactive_ssh_session $argv
|
||||
warp_send_json_message '{"hook": "PreInteractiveSSHSession", "value": {}}'
|
||||
|
||||
if [ "$WARP_USE_SSH_WRAPPER" = "1" ]
|
||||
if test $WARP_SHELL_DEBUG_MODE
|
||||
set -g TRACE_FLAG_IF_WARP_SHELL_DEBUG_MODE "-x"
|
||||
else
|
||||
set -g TRACE_FLAG_IF_WARP_SHELL_DEBUG_MODE ""
|
||||
end
|
||||
warp_ssh_helper $argv
|
||||
else
|
||||
command ssh $argv
|
||||
end
|
||||
else
|
||||
command ssh $argv
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
warp_precmd
|
||||
|
||||
# Print the MotD if this is a login shell. Normally, login(1) or pam_motd(8)
|
||||
# would do this. However, Warp does not use login(1) for local sessions and for
|
||||
# remote sessions, SSHD thinks it is starting a non-interactive session, so it
|
||||
# does not print PAM messages.
|
||||
if status --is-login
|
||||
and test ! -e "$HOME/.hushlogin"
|
||||
for motd_file in /etc/motd /run/motd /run/motd.dynamic /usr/lib/motd /usr/lib/motd.dynamic;
|
||||
if test -r "$motd_file"
|
||||
command cat "$motd_file"
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
warp_bootstrapped
|
||||
|
||||
set -g WARP_BOOTSTRAPPED 1
|
||||
set -g fish_private_mode $saved_fish_private_mode
|
||||
end
|
||||
@@ -0,0 +1,9 @@
|
||||
set -g WARP_SESSION_ID (random)
|
||||
set _hostname (command -v hostname >/dev/null 2>&1 && command hostname 2>/dev/null || uname -n)
|
||||
set _user (command -v whoami >/dev/null 2>&1 && command whoami 2>/dev/null || echo $USER)
|
||||
set -g WARP_IN_MSYS2 (test "$OS" = Windows_NT; and echo true; or echo false)
|
||||
if test "$WARP_IN_MSYS2" = true; set _msg "\e]9278;k;A;InitShell\a\e]9278;k;B;session_id;$WARP_SESSION_ID\a\e]9278;k;B;shell;fish\a\e]9278;k;B;user;$_user\a\e]9278;k;B;hostname;$_hostname\a\e]9278;k;C\a"; else; set _msg (printf "{\"hook\": \"InitShell\", \"value\": {\"session_id\": $WARP_SESSION_ID, \"shell\": \"fish\", \"user\": \"%s\", \"hostname\": \"%s\"}}" "$_user" "$_hostname" | command od -An -v -tx1 | command tr -d " \n"); end
|
||||
set WARP_USING_WINDOWS_CON_PTY @@USING_CON_PTY_BOOLEAN@@
|
||||
# We send the InitShell hook via OSCs when on Windows and via DCSs otherwise.
|
||||
if test "$WARP_USING_WINDOWS_CON_PTY" = true; if test "$WARP_IN_MSYS2" = true; printf "$_msg"; else; printf '\e]9278;d;%s\x07' "$_msg"; end; else; printf '\e\x50\x24\x64%s\x9c' "$_msg"; end
|
||||
set -e _hostname _user _msg
|
||||
@@ -0,0 +1,8 @@
|
||||
set -g WARP_SESSION_ID (random)
|
||||
set _hostname (command -v hostname >/dev/null 2>&1 && command hostname 2>/dev/null || uname -n)
|
||||
set _user (command -v whoami >/dev/null 2>&1 && command whoami 2>/dev/null || echo $USER)
|
||||
set -g WARP_IN_MSYS2 (test "$OS" = Windows_NT; and echo true; or echo false)
|
||||
if test "$WARP_IN_MSYS2" = true; set _msg "\e]9278;k;A;InitShell\a\e]9278;k;B;session_id;$WARP_SESSION_ID\a\e]9278;k;B;shell;fish\a\e]9278;k;B;user;$_user\a\e]9278;k;B;hostname;$_hostname\a\e]9278;k;B;is_subshell;true\a\e]9278;k;C\a"; else; set _msg (printf "{\"hook\": \"InitShell\", \"value\": {\"session_id\": $WARP_SESSION_ID, \"user\": \"%s\", \"hostname\": \"%s\", \"shell\": \"fish\", \"is_subshell\": true, \"wsl_name\": \"$WSL_DISTRO_NAME\"}}" "$_user" "$_hostname" | command od -An -v -tx1 | command tr -d " \n"); end
|
||||
set WARP_USING_WINDOWS_CON_PTY @@USING_CON_PTY_BOOLEAN@@
|
||||
if test "$WARP_USING_WINDOWS_CON_PTY" = true; if test "$WARP_IN_MSYS2" = true; printf "$_msg"; else; printf '\e]9278;d;%s\x07' "$_msg"; end; else; printf '\e\x50\x24\x64%s\x9c' "$_msg"; end
|
||||
set -e _hostname _user _msg
|
||||
@@ -0,0 +1 @@
|
||||
echo -e '\n# Auto-Warpify\nstatus --is-interactive; and printf '\''\eP$f{"hook": "SourcedRcFileForWarp", "value": { "shell": "%", "uname": "'$(uname)'"% }}\x9c'\'' ' >> %
|
||||
@@ -0,0 +1 @@
|
||||
In remote subshells, Warp runs commands in the background to power completions, syntax highlighting, and other features.
|
||||
@@ -0,0 +1,35 @@
|
||||
# Prevent history from being written to file, among other interactive features.
|
||||
Remove-Module -Name PSReadline
|
||||
|
||||
$global:_warpOriginalPrompt = $function:global:prompt
|
||||
|
||||
if ($PSEdition -eq 'Desktop' -or $IsWindows) {
|
||||
$EP = [Microsoft.PowerShell.ExecutionPolicy]
|
||||
# MachinePolicy and UserPolicy scopes cannot be overridden. If either is Restricted, there's nothing we can do.
|
||||
if ((Get-ExecutionPolicy -Scope MachinePolicy) -eq $EP::Restricted -or (Get-ExecutionPolicy -Scope UserPolicy) -eq $EP::Restricted) {
|
||||
Write-Error 'ExecutionPolicy is Restricted. Unable to Warpify this PowerShell session.'
|
||||
} elseif ((Get-ExecutionPolicy) -eq $EP::Restricted -and (Get-ExecutionPolicy -Scope MachinePolicy) -eq $EP::Undefined -and (Get-ExecutionPolicy -Scope UserPolicy) -eq $EP::Undefined) {
|
||||
$global:_warp_PSProcessExecPolicy = $(Get-ExecutionPolicy -Scope Process)
|
||||
Set-ExecutionPolicy -Scope Process -ExecutionPolicy RemoteSigned -Force
|
||||
}
|
||||
}
|
||||
|
||||
# We must wait until pwsh attempts to show the first prompt before writing an OSC string.
|
||||
# Trying to do so beforehand will prevent the "Write-Host" command from being submitted, as pwsh
|
||||
# ignores submissions prior to the first prompt.
|
||||
function prompt {
|
||||
# Reset the prompt back to the default to avoid infinite loops if sourcing the bootstrap script has an error.
|
||||
$function:global:prompt = $global:_warpOriginalPrompt
|
||||
$username = [Environment]::UserName
|
||||
$epoch = [int](New-TimeSpan -Start ([DateTime]::new(1970, 1, 1, 0, 0, 0, 0)) -End ([DateTime]::UtcNow)).TotalSeconds
|
||||
$random = Get-Random -Maximum 32768
|
||||
$global:_warpSessionId = [int64]"$epoch$random"
|
||||
$msg = ConvertTo-Json -Compress -InputObject @{ hook = 'InitShell'; value = @{ session_id = $_warpSessionId; shell = 'pwsh'; user = $username; hostname = [System.Net.Dns]::GetHostName() } }
|
||||
$encodedMsg = [BitConverter]::ToString([System.Text.Encoding]::UTF8.GetBytes($msg)).Replace('-', '')
|
||||
$oscStart = "$([char]0x1b)]9278;"
|
||||
$oscEnd = "`a"
|
||||
$oscJsonMarker = 'd'
|
||||
$oscParameterSeparator = ';'
|
||||
Write-Host "${oscStart}${oscJsonMarker}${oscParameterSeparator}${encodedMsg}${oscEnd}"
|
||||
return $null
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
[1;32mSuccess![0m This subshell spawned by [1;34m%[0m has been Warpified.
|
||||
@@ -0,0 +1,8 @@
|
||||
# fish doesn't allow setting variables with `=`, so the easiest cross-shell compatible expression is
|
||||
# this oneliner.
|
||||
# Making this cross-shell compatible is a bit complicated: we need the surrounding curly braces to
|
||||
# fix precedence issues between `||` and `|`, but curly braces are processed differently in fish.
|
||||
# Thankfully, we don't need curly braces around the first expression, so we can put the fish check
|
||||
# first and it early exits. This runs correctly in sh, bash, zsh, and fish.
|
||||
# Replace `HOOK_NAME` with the appropriate hook name.
|
||||
[ -z $WARP_BOOTSTRAPPED ] && printf "\\e]9278;f;{\"hook\": \"HOOK_NAME\", \"value\": { \"shell\": \"%s\", \"uname\": \"%s\" }}\\a" $([ $FISH_VERSION ] && echo "fish" || { echo $0 | command -p grep -q zsh && echo "zsh"; } || { echo $0 | command -p grep -q bash && echo "bash"; } || echo "unknown") $(uname)
|
||||
@@ -0,0 +1,21 @@
|
||||
setopt interactivecomments
|
||||
# Set PS2 to an empty string to prevent zsh from printing a secondary prompt
|
||||
# (e.g.: 'heredoc> '), which would otherwise be printed repeatedly when we
|
||||
# paste the bootstrap script into the PTY.
|
||||
if (( ${+PS2} )); then
|
||||
ORIGINAL_PS2="$PS2"
|
||||
fi
|
||||
PS2=""
|
||||
# Similar to our approach in bash, we start a shell with the minimal amount of
|
||||
# startup (i.e. --no-rcs) and then take over by executing the shell startup.
|
||||
# We only support the local zsh case for now.
|
||||
#
|
||||
# Note that we indent everything in this top-level script by one space in order
|
||||
# to hide from history.
|
||||
#
|
||||
# Also, note that we put the 'eval' on the same line as the 'read' separated by a semi-colon
|
||||
# rather than on its own line after the HEREDOC. This seems to work around a bug in zsh
|
||||
# where the buffer was getting messed up after processing the heredoc about 1/50 of the time.
|
||||
read -r -d '' WARP_BOOTSTRAP_VAR << 'EOM'; eval "$WARP_BOOTSTRAP_VAR"; unset WARP_BOOTSTRAP_VAR
|
||||
#include bundled/bootstrap/zsh_body.sh
|
||||
EOM
|
||||
@@ -0,0 +1,13 @@
|
||||
# Each line starts with a leading space to leave these commands out of history.
|
||||
#
|
||||
# command -p resolves the given command with the system default PATH, ensuring the shell
|
||||
# can find them even if the user has a clobbered PATH value.
|
||||
unsetopt ZLE
|
||||
WARP_SESSION_ID="$(command -p date +%s)$RANDOM"
|
||||
_hostname=$(command -pv hostname >/dev/null 2>&1 && command -p hostname 2>/dev/null || command -p uname -n)
|
||||
_user=$(command -pv whoami >/dev/null 2>&1 && command -p whoami 2>/dev/null || echo $USER)
|
||||
_msg=$(printf "{\"hook\": \"InitShell\", \"value\": {\"session_id\": $WARP_SESSION_ID, \"shell\": \"zsh\", \"user\": \"%s\", \"hostname\": \"%s\"}}" "$_user" "$_hostname" | command -p od -An -v -tx1 | command -p tr -d " \n")
|
||||
WARP_USING_WINDOWS_CON_PTY=@@USING_CON_PTY_BOOLEAN@@
|
||||
# We send the InitShell hook via OSCs when on Windows and via DCSs otherwise.
|
||||
if [ "$WARP_USING_WINDOWS_CON_PTY" = true ]; then printf '\e]9278;d;%s\x07' "$_msg"; else printf '\e\x50\x24\x64%s\x9c' "$_msg"; fi
|
||||
unset _hostname _user _msg
|
||||
@@ -0,0 +1,16 @@
|
||||
# Ensure the histignorespace is set so all subsequent commands are omitted from history.
|
||||
# setopt hist_ignore_space will still appear, but its better than the entire bootstrap
|
||||
# script showing up in session history.
|
||||
#
|
||||
# command -p resolves the given command with the system default PATH, ensuring the shell
|
||||
# can find them even if the user has a clobbered PATH value.
|
||||
setopt hist_ignore_space
|
||||
unsetopt ZLE
|
||||
WARP_IS_SUBSHELL=1
|
||||
WARP_SESSION_ID="$(command -p date +%s)$RANDOM"
|
||||
_hostname=$(command -pv hostname >/dev/null 2>&1 && command -p hostname 2>/dev/null || command -p uname -n)
|
||||
_user=$(command -pv whoami >/dev/null 2>&1 && command -p whoami 2>/dev/null || echo $USER)
|
||||
_msg=$(printf "{\"hook\": \"InitShell\", \"value\": {\"session_id\": $WARP_SESSION_ID, \"shell\": \"zsh\", \"user\": \"%s\", \"hostname\": \"%s\", \"is_subshell\": true, \"wsl_name\": \"$WSL_DISTRO_NAME\"}}" "$_user" "$_hostname" | command -p od -An -v -tx1 | command -p tr -d " \n")
|
||||
WARP_USING_WINDOWS_CON_PTY=@@USING_CON_PTY_BOOLEAN@@
|
||||
if [ "$WARP_USING_WINDOWS_CON_PTY" = true ]; then printf '\e]9278;d;%s\x07' "$_msg"; else printf '\e\x50\x24\x64%s\x9c' "$_msg"; fi
|
||||
unset _hostname _user _msg
|
||||