aboutsummaryrefslogtreecommitdiffstats
path: root/Library/Homebrew/utils
diff options
context:
space:
mode:
authorMike McQuaid2016-09-04 21:23:33 +0100
committerGitHub2016-09-04 21:23:33 +0100
commitdfcbefff73e90eda5801d9892303e10fc31831b6 (patch)
treee20a7c5a5a28458d7729155c2b537ac63bc0aadd /Library/Homebrew/utils
parent8e98a0a198551f19696b3c09469fcbb1e1223f73 (diff)
parentdcc3377aa30b34dfcced0df77696674f91a5a9f3 (diff)
downloadbrew-dfcbefff73e90eda5801d9892303e10fc31831b6.tar.bz2
Merge pull request #201 from gregory-nisbet/feature-env-shells
--env: support more shells, allow explicit shell selection
Diffstat (limited to 'Library/Homebrew/utils')
-rw-r--r--Library/Homebrew/utils/shell.rb87
1 files changed, 87 insertions, 0 deletions
diff --git a/Library/Homebrew/utils/shell.rb b/Library/Homebrew/utils/shell.rb
new file mode 100644
index 000000000..c0d6b90ae
--- /dev/null
+++ b/Library/Homebrew/utils/shell.rb
@@ -0,0 +1,87 @@
+module Utils
+ SHELL_PROFILE_MAP = {
+ :bash => "~/.bash_profile",
+ :csh => "~/.cshrc",
+ :fish => "~/.config/fish/config.fish",
+ :ksh => "~/.kshrc",
+ :sh => "~/.bash_profile",
+ :tcsh => "~/.tcshrc",
+ :zsh => "~/.zshrc",
+ }.freeze
+
+ module Shell
+ UNSAFE_SHELL_CHAR = /([^A-Za-z0-9_\-.,:\/@\n])/
+
+ # take a path and heuristically convert it
+ # to a shell name, return nil if there's no match
+ def self.path_to_shell(path)
+ # we only care about the basename
+ shell_name = File.basename(path)
+ # handle possible version suffix like `zsh-5.2`
+ shell_name.sub!(/-.*\z/m, "")
+ shell_name.to_sym if %w[bash csh fish ksh sh tcsh zsh].include?(shell_name)
+ end
+
+ def self.preferred_shell
+ path_to_shell(ENV.fetch("SHELL", ""))
+ end
+
+ def self.parent_shell
+ path_to_shell(`ps -p #{Process.ppid} -o ucomm=`.strip)
+ end
+
+ def self.csh_quote(str)
+ # ruby's implementation of shell_escape
+ str = str.to_s
+ return "''" if str.empty?
+ str = str.dup
+ # anything that isn't a known safe character is padded
+ str.gsub!(UNSAFE_SHELL_CHAR, "\\\\" + "\\1")
+ # newlines have to be specially quoted in csh
+ str.gsub!(/\n/, "'\\\n'")
+ str
+ end
+
+ def self.sh_quote(str)
+ # ruby's implementation of shell_escape
+ str = str.to_s
+ return "''" if str.empty?
+ str = str.dup
+ # anything that isn't a known safe character is padded
+ str.gsub!(UNSAFE_SHELL_CHAR, "\\\\" + "\\1")
+ str.gsub!(/\n/, "'\n'")
+ str
+ end
+
+ # quote values. quoting keys is overkill
+ def self.export_value(shell, key, value)
+ case shell
+ when :bash, :ksh, :sh, :zsh
+ "export #{key}=\"#{sh_quote(value)}\""
+ when :fish
+ # fish quoting is mostly Bourne compatible except that
+ # a single quote can be included in a single-quoted string via \'
+ # and a literal \ can be included via \\
+ "set -gx #{key} \"#{sh_quote(value)}\""
+ when :csh, :tcsh
+ "setenv #{key} #{csh_quote(value)};"
+ end
+ end
+
+ # return the shell profile file based on users' preferred shell
+ def self.shell_profile
+ SHELL_PROFILE_MAP.fetch(preferred_shell, "~/.bash_profile")
+ end
+
+ def self.prepend_path_in_shell_profile(path)
+ case preferred_shell
+ when :bash, :ksh, :sh, :zsh, nil
+ "echo 'export PATH=\"#{sh_quote(path)}:$PATH\"' >> #{shell_profile}"
+ when :csh, :tcsh
+ "echo 'setenv PATH #{csh_quote(path)}:$PATH' >> #{shell_profile}"
+ when :fish
+ "echo 'set -g fish_user_paths \"#{sh_quote(path)}\" $fish_user_paths' >> #{shell_profile}"
+ end
+ end
+ end
+end