Gerencie seu PATH com um script Ruby, usando uma única linha de Bash

Sou um grande fã da interface POSIX, mas realmente acho o Bash nojento. Eu prefiro muito mais Ruby! Já que preciso modificar meus arquivos de configuração do shell de vez em quando mexendo com eles de PATHmaneiras desagradáveis, prefiro cuidar disso com uma linguagem elegante e divertida de programar.

Como a propagação de ambiente entre ambientes shell é unilateral, pensei em uma boa solução na qual poderia usar Ruby para realizar toda a lógica de modificação da PATHvariável, enquanto ainda captura os resultados em meu .bashrcscript de configuração. Ao definir a função setpath() { $(ruby ~/.pathconfig.rb SET); }no meu .bashrc, posso configurar PATHexatamente como preciso em qualquer ponto. Ao armazenar o original PATHem um ambiente var ao mesmo tempo, posso facilmente retornar o PATHestado original com um único comando. Brilhante!

Ruby é realmente conveniente para isso porque você pode organizar bem as entradas de caminho na ordem que desejar e, em seguida, usar truques legais como o |operador de união para fundir perfeitamente com o existente PATH. Além disso, coisas como classificar e executar operações complexas em coleções não são complicadas com Ruby; você pode implementar facilmente diretivas funcionais ou baseadas em regras para decidir o seu PATH.

Ah, e a única razão pela qual uso o nome engraçado VANILLA_PATHé porque simplesmente pensei que reduziria a probabilidade de conflito com outros nomes de variáveis; você nunca sabe quem está modificando o ambiente junto com seu script bacana.

#!/usr/bin/env ruby
#
# PATH management via Ruby
#
# The following two functions accompany this script and
# shoudl be defined in ~/.bashrc, ~/.profile, or ~/.bash_profile:
#
# setpath() { $(ruby ~/.pathconfig.rb SET); }
# resetpath() { $(ruby ~/.pathconfig.rb UNSET); }
#
abort
unless ARGV.first
if ARGV.first == 'SET'
HOME
= ENV['HOME']

additions
= [
# Ensure binstubs have priority within a local Bundler project, and reduce use of `bundle exec`
'./.bundle/bin',

# NPM - Node.js package manager
'/usr/local/share/npm/bin',
"#{HOME}/usr/local/share/npm/bin"
]

# Sort the path entries using Ruby's comparison operator, to achieve ideal precedence
newpath
= ENV['PATH'].split(':').uniq.sort! {|a, b| b.length <=> a.length }

# Prepend additions to PATH, and remove duplicates with Set#union
newpath
= (additions | newpath).join ':'

oldpath
= ENV['PATH']
else
newpath
= ENV['VANILLA_PATH']
oldpath
= nil
end

puts
"export PATH=#{newpath};"
puts
"export VANILLA_PATH=#{oldpath}"

PS Aqui está a essência