1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
|
package cmd
import (
"fmt"
"strings"
)
type fish struct{}
// Fish adds support for the fish shell as a host
var Fish Shell = fish{}
const fishHook = `
function __direnv_export_eval --on-event fish_prompt;
"{{.SelfPath}}" export fish | source;
if test "$direnv_fish_mode" != "disable_arrow";
function __direnv_cd_hook --on-variable PWD;
if test "$direnv_fish_mode" = "eval_after_arrow";
set -g __direnv_export_again 0;
else;
"{{.SelfPath}}" export fish | source;
end;
end;
end;
end;
function __direnv_export_eval_2 --on-event fish_preexec;
if set -q __direnv_export_again;
set -e __direnv_export_again;
"{{.SelfPath}}" export fish | source;
echo;
end;
functions --erase __direnv_cd_hook;
end;
`
func (sh fish) Hook() (string, error) {
return fishHook, nil
}
func (sh fish) Export(e ShellExport) (string, error) {
var out string
for key, value := range e {
if value == nil {
out += sh.unset(key)
} else {
out += sh.export(key, *value)
}
}
return out, nil
}
func (sh fish) Dump(env Env) (string, error) {
var out string
for key, value := range env {
out += sh.export(key, value)
}
return out, nil
}
func (sh fish) export(key, value string) string {
if key == "PATH" {
command := "set -x -g PATH"
for _, path := range strings.Split(value, ":") {
command += " " + sh.escape(path)
}
return command + ";"
}
return "set -x -g " + sh.escape(key) + " " + sh.escape(value) + ";"
}
func (sh fish) unset(key string) string {
return "set -e -g " + sh.escape(key) + ";"
}
func (sh fish) escape(str string) string {
in := []byte(str)
out := "'"
i := 0
l := len(in)
hex := func(char byte) {
out += fmt.Sprintf("'\\X%02x'", char)
}
backslash := func(char byte) {
out += string([]byte{BACKSLASH, char})
}
escaped := func(str string) {
out += "'" + str + "'"
}
literal := func(char byte) {
out += string([]byte{char})
}
for i < l {
char := in[i]
switch {
case char == TAB:
escaped(`\t`)
case char == LF:
escaped(`\n`)
case char == CR:
escaped(`\r`)
case char <= US:
hex(char)
case char == SINGLE_QUOTE:
backslash(char)
case char == BACKSLASH:
backslash(char)
case char <= TILDE:
literal(char)
case char == DEL:
hex(char)
default:
hex(char)
}
i++
}
out += "'"
return out
}
|