Never been to CodeSnippets before?

Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world (or not, you can keep them private!)

2 total

Web Development Services

The beauty of these blogging engines would never notice what it is making the site tick all without limiting content and effectiveness.

Web Development Services

app2dock

An exercise in using PlistBuddy.


# first rebuild the Launch Services database
lsregister -kill -r -f -all system,local,user     # Mac OS X 10.5
lsregister -kill -r -f -domain local -domain system -domain user
lsregister -kill -r -f /

# entire system
set -xv
eval lsregister -kill -r -f $(/bin/df -l | /usr/bin/sed -E -e 1d -e 's/^([^ ]+[ ]+)[^\/]+//' -e "s/^(.+)$/'\1'/" | /usr/bin/tr '\n' ' ')
set +xv


dockplistfile="${HOME}/Library/Preferences/com.apple.dock.plist"

cp -ip "${dockplistfile}" "${dockplistfile}.orig"

plutil -convert xml1 -o /dev/fd/1 "${dockplistfile}" | /usr/bin/pl
plutil -convert xml1 -o ~/Desktop/com.apple.dock.plist "${dockplistfile}"
open -e ~/Desktop/com.apple.dock.plist


# get an example entry from $dockplistfile (last application in the Dock)
# cf. http://codesnippets.joyent.com/posts/show/1814

num_apps_dock=$(/usr/libexec/PlistBuddy -c "Print :persistent-apps" "${dockplistfile}" | awk -F '=' '/CFURLString = /{print $2}' | wc -l)
echo ${num_apps_dock}

/usr/libexec/PlistBuddy -c "Print :persistent-apps:'${num_apps_dock}'" "${dockplistfile}" 
#/usr/libexec/PlistBuddy -c "Print :persistent-apps:${num_apps_dock}" "${dockplistfile}" 

/usr/libexec/PlistBuddy -c "Print :persistent-apps:'${num_apps_dock}':tile-data:file-data:_CFURLString" "${dockplistfile}"


open /bin/bash


# we will first create an example entry step by step
# note: persistent-apps is an array that stores dictionaries

dockplistfile="${HOME}/Library/Preferences/com.apple.dock.plist"

# get a free array index number (that is, the last + 1 array index)
free_num_apps_dock=$(( 1 + $(/usr/libexec/PlistBuddy -c "Print :persistent-apps" "${dockplistfile}" | awk -F '=' '/CFURLString = /{print $2}' | wc -l) ))
echo ${free_num_apps_dock}

# add a dictionary to the persistent-apps array at array index ${free_num_apps_dock}
/usr/libexec/PlistBuddy -c "Add :persistent-apps:'${free_num_apps_dock}' dict" "${dockplistfile}" 

# print the dictionay in the persistent-apps array at array index ${free_num_apps_dock}
/usr/libexec/PlistBuddy -c "Print :persistent-apps:'${free_num_apps_dock}'" "${dockplistfile}" 

# add a dictionary named "tile-data" to the previously added dictionary 
/usr/libexec/PlistBuddy -c "Add :persistent-apps:'${free_num_apps_dock}':tile-data dict" "${dockplistfile}" 

/usr/libexec/PlistBuddy -c "Print :persistent-apps:'${free_num_apps_dock}'" "${dockplistfile}" 

# add the dictionary 'file-data' to the dictionary 'tile-data'
/usr/libexec/PlistBuddy -c "Add :persistent-apps:'${free_num_apps_dock}':tile-data:file-data dict" "${dockplistfile}" 

/usr/libexec/PlistBuddy -c "Print :persistent-apps:'${free_num_apps_dock}'" "${dockplistfile}" 

# add key - value pairs to the file-data dictionary
/usr/libexec/PlistBuddy -c "Add :persistent-apps:'${free_num_apps_dock}':tile-data:file-data:thisIsAKey string 'this is a string value'" "${dockplistfile}" 
/usr/libexec/PlistBuddy -c "Add :persistent-apps:'${free_num_apps_dock}':tile-data:file-data:_CFURLString string '/path/to/app'" "${dockplistfile}" 
/usr/libexec/PlistBuddy -c "Add :persistent-apps:'${free_num_apps_dock}':tile-data:file-data:_CFURLStringType integer 0" "${dockplistfile}" 

/usr/libexec/PlistBuddy -c "Print :persistent-apps:'${free_num_apps_dock}'" "${dockplistfile}" 

# delete the dictionay in the persistent-apps array at array index ${free_num_apps_dock}
/usr/libexec/PlistBuddy -c "Delete :persistent-apps:'${free_num_apps_dock}'" "${dockplistfile}" 

# print all dictionaries of the persistent-apps array
/usr/libexec/PlistBuddy -c "Print :persistent-apps" "${dockplistfile}" 


# short version
dockplistfile="${HOME}/Library/Preferences/com.apple.dock.plist"
free_num_apps_dock=$(( 1 + $(/usr/libexec/PlistBuddy -c "Print :persistent-apps" "${dockplistfile}" | awk -F '=' '/CFURLString = /{print $2}' | wc -l) ))
echo ${free_num_apps_dock}
/usr/libexec/PlistBuddy -c "Add :persistent-apps:'${free_num_apps_dock}':tile-data:file-data:thisIsAKey string 'this is a string value'" "${dockplistfile}" 
/usr/libexec/PlistBuddy -c "Add :persistent-apps:'${free_num_apps_dock}':tile-data:file-data:_CFURLString string '/path/to/app'" "${dockplistfile}" 
/usr/libexec/PlistBuddy -c "Add :persistent-apps:'${free_num_apps_dock}':tile-data:file-data:_CFURLStringType integer 0" "${dockplistfile}" 
/usr/libexec/PlistBuddy -c "Print :persistent-apps:'${free_num_apps_dock}'" "${dockplistfile}" 
/usr/libexec/PlistBuddy -c "Delete :persistent-apps:'${free_num_apps_dock}'" "${dockplistfile}" 
/usr/libexec/PlistBuddy -c "Print :persistent-apps" "${dockplistfile}" 


:<<-'COMMENT'
# example entry
Dict {
    tile-data = Dict {
        file-data = Dict {
            thisIsAKey = this is a string value
            _CFURLString = /path/to/app
            _CFURLStringType = 0
        }
    }
}

COMMENT



#-----------------------------------------------------------------------------



# first rebuild the Launch Services database
lsregister -kill -r -f -all system,local,user     # Mac OS X 10.5
lsregister -kill -r -f -domain local -domain system -domain user
lsregister -kill -r -f /

# entire system
set -xv
eval lsregister -kill -r -f $(/bin/df -l | /usr/bin/sed -E -e 1d -e 's/^([^ ]+[ ]+)[^\/]+//' -e "s/^(.+)$/'\1'/" | /usr/bin/tr '\n' ' ')
set +xv


# app2dock
# allows case insensitive name of application as input
# uses lsregister & egrep -i

# lsregister
/usr/bin/sudo /bin/ln -is $(/usr/bin/locate *lsregister | /usr/bin/head -n 1) /bin/lsregister 


unset -f app2dock
function app2dock() {

   declare appname dockplistfile free_num_apps_dock path num index

   declare -a fullpaths

   dockplistfile="${HOME}/Library/Preferences/com.apple.dock.plist"

   for appname in "${@}"; do

      appname="${appname%/}"

      declare IFS=$'\n'     # bug: does not work for file paths with embedded newlines \n

      fullpaths=( $(/bin/lsregister -dump | /usr/bin/egrep -i "path: +.*\/[^\/]*${appname}[^\/]*\.app$" | \
                       /usr/bin/sed -E 's/^[[:space:]]+path:[[:space:]]+//') )


      if [[ ${#fullpaths[@]} -eq 0 ]]; then

         echo "No such application: ${appname}"
         continue

      elif [[ ${#fullpaths[@]} -eq 1 ]]; then

         path="${fullpaths[0]}"

      else

         echo
         for ((i=0; i < ${#fullpaths[@]}; i++)); do 
            printf "\e[1m%+8s\e[m    %s\n" "$[ ${i} +1 ]:" "${fullpaths[${i}]##*/}"   # print basename only
         done

         echo
         read -e -p $'\e[1mChoose one of the numbers above\e[m:  '  num
         echo


         # check if $num is a positive integer
         # do not allow leading zeros
         if [[ "${num//[[:digit:]]/}" != "" ]] || [[ "${num#"${num%%[!0]*}"}" != "${num}" ]]; then
            echo 'Wrong input!'
            continue
         fi

         index=$[ $num - 1 ]

         [[ ${index} -ge ${#fullpaths[@]} ]] && echo 'Number too high!' && continue

         path="${fullpaths[${index}]}"


      fi


      path="${path%/}"   # cut off trailing slash if any

      [[ ! -d "${path}" ]] && echo "No such directory: ${path}" && continue

      # if $path does not end with .app ...
      [[ "${path}" == "${path%.app}" ]] && echo "Argument error: ${path}" && continue


      # escape single & double quotes in $path
      path="${path//\'/\'}"
      path="${path//\"/\\\"}"

      printf "%s\n" "$path"
      
      free_num_apps_dock=$(( 1 + $(/usr/libexec/PlistBuddy -c "Print :persistent-apps" "${dockplistfile}" | \
             /usr/bin/awk -F '=' '/CFURLString = /{print $2}' | /usr/bin/wc -l) ))
      #echo ${free_num_apps_dock}
      /usr/libexec/PlistBuddy -c "Add :persistent-apps:'${free_num_apps_dock}':tile-data:file-data:_CFURLString string '${path}'" "${dockplistfile}" 
      /usr/libexec/PlistBuddy -c "Add :persistent-apps:'${free_num_apps_dock}':tile-data:file-data:_CFURLStringType integer 0" "${dockplistfile}" 
      #/usr/libexec/PlistBuddy -c "Print :persistent-apps:'${free_num_apps_dock}'" "${dockplistfile}" 
      /usr/libexec/PlistBuddy -c save "${dockplistfile}" &>/dev/null

   done  # for

   /usr/bin/killall -HUP Dock

   return 0

}



# app2dock_fp
# only allows full file path to application as input

function app2dock_fp() {
   declare dockplistfile free_num_apps_dock path
   dockplistfile="${HOME}/Library/Preferences/com.apple.dock.plist"

   for path in "${@}"; do
      path="${path%/}"
      if [[ ! -d "${path}" ]] || [[ "${path}" == "${path%.app}" ]]; then echo "Argument error: ${path}"; continue; fi
      free_num_apps_dock=$(( 1 + $(/usr/libexec/PlistBuddy -c "Print :persistent-apps" "${dockplistfile}" | \
             /usr/bin/awk -F '=' '/CFURLString = /{print $2}' | /usr/bin/wc -l) ))
      #echo ${free_num_apps_dock}

      # escape single & double quotes in $path
      path="${path//\'/\'}"
      path="${path//\"/\\\"}"

      /usr/libexec/PlistBuddy -c "Add :persistent-apps:'${free_num_apps_dock}':tile-data:file-data:_CFURLString string '${path}'" "${dockplistfile}" 
      /usr/libexec/PlistBuddy -c "Add :persistent-apps:'${free_num_apps_dock}':tile-data:file-data:_CFURLStringType integer 0" "${dockplistfile}" 
      #/usr/libexec/PlistBuddy -c "Print :persistent-apps:'${free_num_apps_dock}'" "${dockplistfile}" 
      /usr/libexec/PlistBuddy -c save "${dockplistfile}" &>/dev/null

   done

   /usr/bin/killall -HUP Dock
   return 0
}



# remove_app_from_dock
# allows case insensitive name of application as input

function remove_app_from_dock() {

   declare appname dockplistfile nums=""

   dockplistfile="${HOME}/Library/Preferences/com.apple.dock.plist"

   for appname in "${@}"; do

      appname="${appname%/}"

      nums=""
      nums=$(/usr/libexec/PlistBuddy -c "Print :persistent-apps" "${dockplistfile}" | /usr/bin/awk -F '=' '/CFURLString = /{print $2}' | \
            /usr/bin/nl | /usr/bin/egrep -i "${appname}" | /usr/bin/awk '{print $1}' | /usr/bin/sort -rn)

      if [[ -z "${nums}" ]]; then echo "No application: ${appname} found in the Dock."; continue; fi

      for num in ${nums}; do
         /usr/libexec/PlistBuddy -c "Delete :persistent-apps:'${num}'" "${dockplistfile}" 
      done

      # test
      #for num in ${nums}; do
      #   /usr/libexec/PlistBuddy -c "Print :persistent-apps:'${num}'" "${dockplistfile}" 
      #done

      /usr/libexec/PlistBuddy -c save "${dockplistfile}" &>/dev/null

   done

   /usr/bin/killall -HUP Dock

   return 0

}


app2dock_fp /Applications/Chess.app /Applications/Chess.app

app2dock chess grapher

remove_app_from_dock chess grapher
2 total