Better SSH completion.
[profile.git] / .profile.d / PATH.bashrc
index ab57aaa..38bb825 100644 (file)
@@ -6,7 +6,7 @@
 #
 
 # Location of the XXXdirs files.
-DIR="$HOME/.PATH"
+DIR=${PROFILE_HOME:-~}/.PATH
 
 # Paths to set and the file to get them from @variable to copy from.
 PATHS="
@@ -14,7 +14,6 @@ PATH:bindirs
 C_INCLUDE_PATH:incdirs
 CPLUS_INCLUDE_PATH:@C_INCLUDE_PATH
 LD_LIBRARY_PATH:libdirs
-LD_RUN_PATH:@PATH
 MANPATH:mandirs
 PKG_CONFIG_PATH:pkgdirs
 "
@@ -49,6 +48,38 @@ function copypath() {
   [ -z "$path" ] || eval "export $newpath='$path'"
 }
 
+# Try to expand variables in a path definition, discarding it if expansion fails.
+function expandpath() {
+  local path="$1"; shift
+
+  while [ -n "$path" ]; do
+    [ "${path/\$/}" = "$path" ] && return 0
+    path="${path#*\$}"
+
+    local var="${path%%/*}"
+    eval "[ -n \"\$$var\" ] || return 1"
+  done
+
+  return 0
+}
+
+# Helper.
+function addpath() {
+  local path="$1"; shift
+  local dir="$1"; shift
+
+  if ! expandpath "$dir"; then
+    echo "$path"
+  else
+    dir=$(eval echo "$dir")
+    if [ -d "$dir" ]; then
+      echo "$path:$dir"
+    else
+      echo "$path"
+    fi
+  fi
+}
+
 # Set a path from directories.
 function makepath() {
   local newpath="$1"; shift
@@ -61,10 +92,11 @@ function makepath() {
   # Read them.
   local path=
   while read dir; do
-    local dir=$(eval echo "$dir")
-    [ -d "$dir" ] || continue
-
-    path="$path:$dir"
+    path=$(addpath "$path" "$dir")
+    if [ -n "$PROFILE_HOME" -a ! "${dir#\$HOME}" = "$dir" ]; then
+      dir="$PROFILE_HOME${dir#\$HOME}"
+      path=$(addpath "$path" "$dir")
+    fi
   done < "$dirs"
 
   # Restore IFS.
@@ -89,6 +121,35 @@ function makepath() {
   eval "export $newpath='$path'"
 }
 
+# Remove entries which are symlinks to other existing entries.
+function canonicalisepath() {
+  local path="$1"; shift
+  local newpath=
+
+  local JGD=$IFS
+  IFS='
+'
+
+  local dirs=$(eval echo "\$$path")
+  local check=":$dirs:"
+  for dir in ${dirs//:/
+}; do
+    if [ -L "$dir" ]; then
+      # Is this a symlink to another entry?
+      local canon=$(readlink -f "$dir" 2>/dev/null)
+      if [ -n "$canon" ]; then
+        [ "${check/:$canon:/}" = "$check" ] || continue
+      fi
+    fi
+
+    newpath="$newpath:$dir"
+  done
+
+  IFS=$JGD
+
+  eval "export $path='${newpath##:}'"
+}
+
 # Construct directory list, omitting nonexistent and undefined ones.
 dirs=
 for dir in "${SYSTEM:-@}/${ARCHITECTURE:-@}" "${SYSTEM:-@}" ""; do
@@ -109,10 +170,10 @@ for path in $PATHS; do
       [ -e "$dir" ] || continue
       makepath "$var" "$dir"
     done
+    canonicalisepath "$var"
   else
     copypath "$var" "${source#@}"
   fi
 done
 
-
-unset DIR PATHS dir dirs path var source sanitisepath copypath makepath newpath setpaths
+unset DIR PATHS dir dirs path var source expandpath sanitisepath copypath makepath newpath addpath canonicalisepath