Skip to content

Commit

Permalink
fix: ssh management nushell
Browse files Browse the repository at this point in the history
  • Loading branch information
AlanBuscagliaGFT committed Nov 4, 2024
1 parent 99d7d9b commit 4968884
Show file tree
Hide file tree
Showing 6 changed files with 332 additions and 8 deletions.
1 change: 1 addition & 0 deletions Gentleman.Dots
Submodule Gentleman.Dots added at 99d7d9
1 change: 1 addition & 0 deletions GentlemanNushell/config.nu
Original file line number Diff line number Diff line change
Expand Up @@ -898,6 +898,7 @@ $env.config = {
source ~/.cache/carapace/init.nu
source ~/.local/share/atuin/init.nu
use ~/.cache/starship/init.nu
use ~/.config/bash-env.nu

let MULTIPLEXER = "tmux"
let MULTIPLEXER_ENV_PREFIX = "TMUX"
Expand Down
11 changes: 6 additions & 5 deletions GentlemanNushell/env.nu
Original file line number Diff line number Diff line change
Expand Up @@ -106,11 +106,12 @@ let brew_path = if $nu.os-info.name == 'macOS' {
}

$env.PATH = (
$env.PATH
| split row (char esep)
| prepend '/opt/homebrew/bin'
| append /usr/local/bin
| append ($env.HOME | path join ".cargo/bin")
$env.PATH
| split row (char esep)
| prepend brew_path
| append '/usr/local/bin'
| append ($env.HOME | path join ".config")
| append ($env.HOME | path join ".cargo/bin")
)

mkdir ~/.cache/starship
Expand Down
276 changes: 276 additions & 0 deletions bash-env-json
Original file line number Diff line number Diff line change
@@ -0,0 +1,276 @@
#!/usr/bin/env bash
#
# Copyright 2024 Simon Guest
#
# 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, subl# icense, 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.

VERSION="0.9.1"
USAGE="bash-env-json [--help] [--shellfns <comma-separated-function-names>] [path]"

shopt -s extglob

function capture() {
local -n _capture_env="$1"
local -n _capture_shellvars="$2"
local _name _value
# some shell variables leak into our environment, so inhibit that:
local -A _inhibit_shellvars=([_value]=X [BASH_LINENO]=X [COLUMNS]=X [LINES]=X)

# environment variables
while IFS='=' read -r -d '' _name _value; do
_capture_env["$_name"]="${_value}"
done < <(env -0)

# shellvars
for _name in $(
set -o posix
set | sed -n -e '/^[a-zA-Z_][a-zA-Z_0-9]*=/s/=.*$//p'
set +o posix
); do
if test -v "$_name" -a ! "${_capture_env[$_name]+EXISTS}" -a ! "${_inhibit_shellvars[$_name]+EXISTS}"; then
_capture_shellvars["$_name"]="${!_name}"
fi
done
}

function emit_value() {
# jq -R produces nothing on empty input, but we want ""
if test -n "$1"; then
echo -n "$1" | jq -R
else
echo -n '""'
fi
}

function emit_meta() {
local _prefix="$1"
local _suffix="$2"
local _usage="$3"
echo -n "$_prefix\"meta\":{\"version\":"
emit_value "$VERSION"
test -n "$_usage" && {
echo -n ',"usage":'
emit_value "$USAGE"
}
echo "}$_suffix"
}

function emit_error() {
local _msg="$1"
local _usage="$2"
echo -n '{"error":'
emit_value "$_msg"
emit_meta , '}' "$_usage"
}

function emit_error_exit() {
emit_error "$@" | jq
exit 1
}

function emit_help_exit() {
emit_meta '{' '}' usage | jq
exit 0
}

function emit_version_exit() {
emit_meta '{' '}' | jq
exit 0
}

function emit() {
local _name
local -a _names
local _comma=""
local _sep="$1"
local _tag="$2"
local -n _emit_previous="$3"
local -n _emit_current="$4"

echo -n "$_sep\"$_tag\":{"

# changes
_names=("${!_emit_current[@]}")
for _name in "${_names[@]}"; do
if test "${_emit_current[$_name]}" != "${_emit_previous[$_name]}" -o "${_emit_previous[$_name]+EXISTS}" != EXISTS; then
if [[ "$_name" != BASH_FUNC_* ]]; then
echo -n "${_comma}\"$_name\":"
emit_value "${_emit_current[$_name]}"
_comma=","
fi
fi
done

# unset
for _name in "${!_emit_previous[@]}"; do
if test ! -v "$_name"; then
if [[ "$_name" != BASH_FUNC_* ]]; then
echo -n "${_comma}\"$_name\":null"
_comma=","
fi
fi
done

echo -n "}"
}

function eval_or_source() {
local _source _path _error_file
_path="$1"

_error_file=$(mktemp -u)
touch "$_error_file"
# shellcheck disable=SC2094
exec 3<"$_error_file" 4>"$_error_file"
rm -f "$_error_file"

if test -n "$_path"; then
# source from file if specified

if test ! -r "$_path"; then
emit_error_exit "no such file '$_path'"
fi

# ShellCheck can't cope with sourcing from an unknown path
# shellcheck disable=SC1090
if ! source "$_path" >/dev/null 2>&4; then
exec 4>&-
emit_error_exit "$(head -1 <&3)"
fi
else
# otherwise eval from stdin
_source=$(</dev/stdin)
if ! eval "$_source" >/dev/null 2>&4; then
exec 4>&-
# discard error location, because it is this file not the one sourced
emit_error_exit "$(sed -e 's/^.*line\s*[0-9]*:\s*//' <&3)"
fi
fi
}

function invoke_safely() {
local _fn="$1"

_error_file=$(mktemp -u)
touch "$_error_file"
# shellcheck disable=SC2094
exec 3<"$_error_file" 4>"$_error_file"
rm -f "$_error_file"

"$_fn" >/dev/null 2>&4 || {
exec 4>&-
emit_error_exit "$(head -1 <&3)"
}
}

function get_args() {
local -n _opt_path="$1"
local -n _opt_shellfn_names="$2"
shift 2

# process args
while test -n "$1"; do
case "$1" in
--help)
emit_help_exit
;;
--version)
emit_version_exit
;;
--shellfns)
test -z "$2" && {
bad_usage "--shellfns requires comma-separated list of function names"
}
mapfile -td, _opt_shellfn_names <<<"$2,"
unset '_opt_shellfn_names[-1]'
shift
;;
-*)
bad_usage "unexpected option: $1"
;;
*)
test -n "$_opt_path" && {
bad_usage "repeated path '$_opt_path'"
}
_opt_path="$1"
;;
esac
shift
done
}

function main() {
local _path _fn
declare -a _shellfn_names

get_args _path _shellfn_names "$@"

declare -A _env_previous
declare -A _env_current
declare -A _shellvars_previous
declare -A _shellvars_current

capture _env_previous _shellvars_previous
eval_or_source "$_path"
capture _env_current _shellvars_current

# accumulate result in a file until we know we are error-free
_result_file=$(mktemp -u)
touch "$_result_file"
# shellcheck disable=SC2094
exec 5<"$_result_file" 6>"$_result_file"
rm -f "$_result_file"

emit "{" env _env_previous _env_current >&6
emit "," shellvars _shellvars_previous _shellvars_current >&6

test "${#_shellfn_names[@]}" -gt 0 && {
echo ",\"fn\":{" >&6
}

local _fn_comma=""
for _fn in "${_shellfn_names[@]}"; do
capture _env_previous _shellvars_previous
invoke_safely "$_fn"
capture _env_current _shellvars_current

echo "$_fn_comma\"$_fn\":" >&6
emit "{" env _env_previous _env_current >&6
emit "," shellvars _shellvars_previous _shellvars_current >&6
echo "}" >&6
_fn_comma=","
done

test "${#_shellfn_names[@]}" -gt 0 && {
echo "}" >&6
}

emit_meta ',' '}' >&6
exec 6>&-

jq <&5
}

function bad_usage() {
emit_error_exit "$1" usage
}

main "$@"
38 changes: 38 additions & 0 deletions bash-env.nu
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
export def main [
path?: string
--export: list
--shellvars (-s)
--fn (-f): list
] {
let fn_args = if ($fn | is-not-empty) {
['--shellfns' ($fn | str join ',')]
} else {
[]
}

let path_args = if $path != null {
[($path | path expand)]
} else {
[]
}

let raw = ($in | str join "\n") | bash-env-json ...($fn_args ++ $path_args) | complete
let raw_json = $raw.stdout | from json

let error = $raw_json | get -i error
if $error != null {
error make { msg: $error }
} else if $raw.exit_code != 0 {
error make { msg: $"unexpected failure from bash-env-json ($raw.stderr)" }
}

if ($export | is-not-empty) {
print "warning: --export is deprecated, use --shellvars(-s) instead"
let exported_shellvars = ($raw_json.shellvars | select -i ...$export)
$raw_json.env | merge ($exported_shellvars)
} else if $shellvars or ($fn | is-not-empty) {
$raw_json
} else {
$raw_json.env
}
}
13 changes: 10 additions & 3 deletions install-linux-mac.sh
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,11 @@ if [ "$os_choice" != "mac" ]; then
install_dependencies
fi
else
run_command "xcode-select --install"
if xcode-select -p &>/dev/null; then
echo -e "${GREEN}Xcode is already installed.${NC}"
else
run_command "xcode-select --install"
fi
run_command "curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh"
fi

Expand Down Expand Up @@ -342,7 +346,6 @@ else
unzip ~/.local/share/fonts/Iosevka.zip -d ~/.local/share/fonts/
fc-cache -fv
elif [ "$os_choice" = "mac" ]; then
brew tap homebrew/cask-fonts
brew install --cask font-iosevka-term-nerd-font
fi
echo -e "${GREEN}Iosevka Term Nerd Font installed.${NC}"
Expand Down Expand Up @@ -397,8 +400,11 @@ shell_choice=$(select_option "Which shell do you want to install? " "fish" "zsh"
# Case for shell choice
case "$shell_choice" in
"nushell")
run_command "cp -rf bash-env-json ~/.config/"
run_command "cp -rf bash-env.nu ~/.config/"

if ! command -v nu &>/dev/null; then
install_shell_with_progress "nushell" "brew install nushell carapace zoxide atuin"
install_shell_with_progress "nushell" "brew install nushell carapace zoxide atuin jq bash"
else
echo -e "${GREEN}Nushell shell is already installed.${NC}"
fi
Expand All @@ -421,6 +427,7 @@ case "$shell_choice" in
mkdir -p ~/.config/nushell
run_command "cp -rf GentlemanNushell/* ~/.config/nushell/"
fi

;;
"fish")
if ! command -v fish &>/dev/null; then
Expand Down

0 comments on commit 4968884

Please sign in to comment.