From 14946ca96c655319ab6d0319c9edeae044beedca Mon Sep 17 00:00:00 2001 From: Thibault Kruse Date: Sun, 4 Mar 2012 06:45:25 +0000 Subject: [PATCH] cleanedup completion function local vars, aligned zsh with bash, more unit tests --- tools/rosbash/rosbash | 37 +++++++++--- tools/rosbash/roszsh | 87 ++++++++++++++++++++++++---- tools/rosbash/test/test_rosbash.bash | 18 +++++- tools/rosbash/test/test_roszsh.zsh | 21 +++++++ tools/rosbash/test/test_scripts.py | 13 +++-- 5 files changed, 151 insertions(+), 25 deletions(-) create mode 100755 tools/rosbash/test/test_roszsh.zsh diff --git a/tools/rosbash/rosbash b/tools/rosbash/rosbash index f4c6c178..05130603 100644 --- a/tools/rosbash/rosbash +++ b/tools/rosbash/rosbash @@ -1,3 +1,7 @@ +# rosbash - functions to support ROS users +# Useful things to know: +# 'local' variables get unset after function, all others stay forever +# COMPREPLY is the var used by bash complete builtin function _rossed { if [[ `uname` == Darwin || `uname` == FreeBSD ]]; then @@ -7,9 +11,13 @@ function _rossed { fi } - - +# _ros_location_find +# based on $ROS_LOCATIONS, which the user can set to any colon +# separated of key=folder pairs also resolves keys 'log' and +# 'test_results' to ROS defaults finally resolves to package, then +# stack echoes its result function _ros_location_find { + local homedir ROS_LOCATION_KEYS_ARR ROS_LOCATIONS_ARR loc homedir=`echo $HOME | sed -e "s/\//\t\//g" -e "s/\t/\\\\\/g"` ROS_LOCATION_KEYS_ARR=(`echo $ROS_LOCATIONS | _rossed -e 's/([^:=]*)=([^:=]*)(:*[^=])*(:|$)/\1 /g'`) ROS_LOCATIONS_ARR=(`echo $ROS_LOCATIONS | _rossed -e 's/([^:=]*)=([^:=]*)(:*[^=])*(:|$)/\2 /g' -e "s/~/${homedir}/g"`) @@ -43,6 +51,7 @@ function _ros_location_find { } function _ros_list_locations { + local ROS_LOCATION_KEYS packages stacks ROS_LOCATION_KEYS=`echo $ROS_LOCATIONS | _rossed -e 's/([^:=]*)=([^:=]*)(:*[^=])*(:|$)/\1 /g'` packages=`export ROS_CACHE_TIMEOUT=-1.0 && rospack list-names` stacks=`export ROS_CACHE_TIMEOUT=-1.0 && rosstack list-names` @@ -51,6 +60,7 @@ function _ros_list_locations { } function _ros_package_find { + local loc loc=`export ROS_CACHE_TIMEOUT=-1.0 && rospack find $1 2> /dev/null` if [[ $? != 0 ]]; then return 1 @@ -60,20 +70,25 @@ function _ros_package_find { } function _ros_list_packages { + local packages packages=`export ROS_CACHE_TIMEOUT=-1.0 && rospack list-names` echo $packages | tr ' ' '\n' return 0 } function _ros_list_stacks { + local stacks stacks=`export ROS_CACHE_TIMEOUT=-1.0 && rosstack list-names` echo $stacks | tr ' ' '\n' return 0 } +# takes as argument either just a package-path or just a pkgname +# returns 0 for no argument or if package (+ path) exist, 1 else +# on success with arguments returns [pkgname, abspath, relpath basename] function _ros_decode_path { local rosname rosdir reldir last - + rosvals=() if [[ -z $1 ]]; then return 0 fi @@ -101,6 +116,7 @@ function _ros_decode_path { } function rospython { + local pkgname if [[ $1 = "--help" ]]; then echo -e "usage: rospython [package] \n\nRun python loading package manifest first." return 0 @@ -193,7 +209,7 @@ function rosls { } function _roscmd { - local pkgdir exepath opt catkin_source_dir catkin_binary_dir + local pkgdir exepath opt catkin_source_dir catkin_binary_dir opts arg if [[ -n $CATKIN_SOURCE_DIR ]]; then catkin_source_dir=`ROS_ROOT=$CATKIN_SOURCE_DIR ROS_PACKAGE_PATH= _ros_package_find $1` fi @@ -309,9 +325,6 @@ function _msg_opts { pkgname=${1} fi - echo Pkg: $pkgname - echo Msg: $msgname - if [[ -z ${searchmsg} ]]; then pkgs=(`rospack list`) @@ -482,6 +495,7 @@ function _roscomplete_test { } function _roscomplete_rosbag { + local opts COMPREPLY=() arg="${COMP_WORDS[COMP_CWORD]}" @@ -523,6 +537,7 @@ function _roscomplete_rosbag { } function _roscomplete_rospack { + local arg opts COMPREPLY=() arg="${COMP_WORDS[COMP_CWORD]}" @@ -537,6 +552,7 @@ function _roscomplete_rospack { } function _roscomplete_rosnode { + local arg opts COMPREPLY=() arg="${COMP_WORDS[COMP_CWORD]}" @@ -573,6 +589,7 @@ function _roscomplete_rosnode { } function _roscomplete_rosparam { + local arg opts COMPREPLY=() arg="${COMP_WORDS[COMP_CWORD]}" @@ -602,6 +619,7 @@ function _roscomplete_rosparam { } function _roscomplete_rostopic { + local arg opts COMPREPLY=() arg="${COMP_WORDS[COMP_CWORD]}" @@ -661,6 +679,7 @@ function _roscomplete_rostopic { } function _roscomplete_rosservice { + local arg opts COMPREPLY=() arg="${COMP_WORDS[COMP_CWORD]}" @@ -732,6 +751,7 @@ function _msg_opts { } function _roscomplete_rosmsg { + local arg opts COMPREPLY=() arg="${COMP_WORDS[COMP_CWORD]}" @@ -757,6 +777,7 @@ function _roscomplete_rosmsg { } function _roscomplete_roscreate_pkg { + local arg opts COMPREPLY=() arg="${COMP_WORDS[COMP_CWORD]}" @@ -780,7 +801,7 @@ function _roscomplete_roswtf { } function _roscomplete_rosclean { - local arg + local arg opts COMPREPLY=() arg="${COMP_WORDS[COMP_CWORD]}" if [[ $COMP_CWORD == 1 ]]; then diff --git a/tools/rosbash/roszsh b/tools/rosbash/roszsh index 1ccd1f29..bec7cb86 100644 --- a/tools/rosbash/roszsh +++ b/tools/rosbash/roszsh @@ -1,6 +1,67 @@ +# roszsh - functions to support ROS users +# Useful things to know: +# 'local' variables get unset after function, all others stay forever +# 'reply' is the var used by zsh compctl builtin + +function _rossed { + if [[ `uname` == Darwin || `uname` == FreeBSD ]]; then + sed -E "$@" + else + sed -r "$@" + fi +} + +# _ros_location_find +# based on $ROS_LOCATIONS, which the user can set to any colon +# separated of key=folder pairs also resolves keys 'log' and +# 'test_results' to ROS defaults finally resolves to package, then +# stack echoes its result +function _ros_location_find { + local homedir ROS_LOCATION_KEYS_ARR ROS_LOCATIONS_ARR loc + homedir=`echo $HOME | sed -e "s/\//\t\//g" -e "s/\t/\\\\\/g"` + ROS_LOCATION_KEYS_ARR=(`echo $ROS_LOCATIONS | _rossed -e 's/([^:=]*)=([^:=]*)(:*[^=])*(:|$)/\1 /g'`) + ROS_LOCATIONS_ARR=(`echo $ROS_LOCATIONS | _rossed -e 's/([^:=]*)=([^:=]*)(:*[^=])*(:|$)/\2 /g' -e "s/~/${homedir}/g"`) + + for (( i = 1 ; i <= ${#ROS_LOCATION_KEYS_ARR[@]} ; i++ )); do + if [[ $1 == ${ROS_LOCATION_KEYS_ARR[$i]} ]]; then + echo ${ROS_LOCATIONS_ARR[i]} + return 0 + fi + done + + if [[ $1 == log ]]; then + echo `roslaunch-logs` + return 0 + elif [[ $1 == test_results ]]; then + echo `rosrun rosunit test_results_dir.py` + return 0 + fi + + loc=`export ROS_CACHE_TIMEOUT=-1.0 && rospack find $1 2> /dev/null` + if [[ $? != 0 ]]; then + loc=`export ROS_CACHE_TIMEOUT=-1.0 && rosstack find $1 2> /dev/null` + if [[ $? != 0 ]]; then + return 1 + fi + echo $loc + return 0 + fi + echo $loc + return 0 +} + +function _ros_list_locations { + local ROS_LOCATION_KEYS packages stacks + ROS_LOCATION_KEYS=`echo $ROS_LOCATIONS | _rossed -e 's/([^:=]*)=([^:=]*)(:*[^=])*(:|$)/\1 /g'` + packages=`export ROS_CACHE_TIMEOUT=-1.0 && rospack list-names` + stacks=`export ROS_CACHE_TIMEOUT=-1.0 && rosstack list-names` + echo $packages $stacks log test_results $ROS_LOCATION_KEYS | tr ' ' '\n' + return 0 +} + function _ros_decode_path { local rosname rosdir reldir last rospackdir rosstack_result rosstackdir - + rosvals=() if [[ -z $1 ]]; then return 0 fi @@ -138,7 +199,7 @@ function rosls { } function _roscmd { - local pkgdir exepath opt + local pkgdir exepath opt arg pkgdir=`export ROS_CACHE_TIMEOUT=-1.0 && rospack find $1 2> /dev/null` if [[ $? != 0 ]] ; then echo "Couldn't find package [$1]" @@ -232,7 +293,7 @@ function _roscomplete_sub_dir { } function _roscomplete_search_dir { - local words arg opts pkgdir + local words arg opts pkgdir pkgdir_result stack_result reply=() words=(${=BUFFER}) pkgdir=`export ROS_CACHE_TIMEOUT=-1.0 && rospack find ${words[2]} 2> /dev/null` @@ -264,6 +325,7 @@ function _roscomplete_launchfile { } function _roscomplete_rosbag { + local opts reply=() if [[ ${CURRENT} == 2 ]]; then @@ -305,6 +367,7 @@ function _roscomplete_rosbag { } function _roscomplete_rospack { + local opts reply=() if [[ ${CURRENT} == 2 ]]; then opts="help find list list-names list-duplicates langs depends depends-manifests depends1 depends-indent depends-msgsrv depends-why rosdep rosdep0 vcs vcs0 depends-on depends-on1 export plugins cflags-only-I cflags-only-other libs-only-L libs-only-l libs-only-other profile" @@ -316,6 +379,7 @@ function _roscomplete_rospack { } function _roscomplete_rosnode { + local opts reply=() if [[ ${CURRENT} == 2 ]]; then @@ -348,11 +412,11 @@ function _roscomplete_rosnode { ;; esac fi - } -function _roscomplete_rosparam { - reply=() +function _roscomplete_rosparam { + local opts + reply=() if [[ ${CURRENT} == 2 ]]; then opts="set get load dump delete list" @@ -446,6 +510,7 @@ function _roscomplete_rostopic { } function _roscomplete_rosservice { + local opts reply=() @@ -478,6 +543,7 @@ function _roscomplete_rosservice { } function _msg_opts { + local pkgname msgname searchmsg pkgs count pkgname2 opts result unset searchmsg if [[ $1 =~ .+/.* ]]; then @@ -517,6 +583,7 @@ function _msg_opts { } function _roscomplete_rosmsg { + local opts reply=() @@ -541,6 +608,7 @@ function _roscomplete_rosmsg { } function _srv_opts { + local pkgname srvname searchsrv pkgs count opts pkgpath result unset searchsrv if [[ $1 =~ .+/.* ]]; then @@ -580,9 +648,9 @@ function _srv_opts { } function _roscomplete_rossrv { + local opts reply=() - if [[ ${CURRENT} == 2 ]]; then opts="show list md5 package packages" reply=(${=opts}) @@ -603,17 +671,16 @@ function _roscomplete_rossrv { fi } - - function _roscomplete_roscreate_pkg { + local opts reply=() - if [[ ${CURRENT} > 2 ]]; then opts=`rospack list-names` reply=(${=opts}) fi } + compctl -K "_roscomplete_sub_dir" -S / "roscd" "rospd" "rosls" compctl -K "_roscomplete_rosmake" "rosmake" diff --git a/tools/rosbash/test/test_rosbash.bash b/tools/rosbash/test/test_rosbash.bash index a7dbe10e..8169e28c 100755 --- a/tools/rosbash/test/test_rosbash.bash +++ b/tools/rosbash/test/test_rosbash.bash @@ -7,12 +7,18 @@ . ../rosbash +echo Testing BASH + +. test_zshbash.sh + +# roslaunch completion + export COMP_CWORD=1 _roscomplete_launch roslaunch if [[ ! ${COMPREPLY[@]} =~ rosbash ]]; then echo "rosbash package missing from" ${COMPREPLY[@]} ; exit 1 fi -echo success 1 +echo success roslaunch pkg export COMP_WORDS=("roslaunch" "--") export COMP_CWORD=1 @@ -20,7 +26,7 @@ _roscomplete_launch roslaunch "--" roslaunch if [[ ! ${COMPREPLY[@]} == "--files --args --nodes --find-node --child --local --screen --server_uri --run_id --wait --port --core --pid --dump-params" ]]; then echo "roslaunch --options missing" from ${COMPREPLY[@]} ; exit 1 fi -echo success 2 +echo success roslaunch --option export COMP_WORDS=("roslaunch" "roslaunch") export COMP_CWORD=2 @@ -28,4 +34,10 @@ _roscomplete_launch roslaunch roslaunch if [[ ! ${COMPREPLY[@]} =~ "example.launch" ]]; then echo "example.launch missing from " ${COMPREPLY[@]} ; exit 1 fi -echo success 3 +echo success roslaunch launchfiles + + +# if [[ ! ${COMPREPLY[@]} =~ "example.launch" ]]; then +# echo "example.launch missing from " ${COMPREPLY[@]} ; exit 1 +# fi +# echo success 4 \ No newline at end of file diff --git a/tools/rosbash/test/test_roszsh.zsh b/tools/rosbash/test/test_roszsh.zsh new file mode 100755 index 00000000..6ed6e2dc --- /dev/null +++ b/tools/rosbash/test/test_roszsh.zsh @@ -0,0 +1,21 @@ +#! /usr/bin/env zsh + +# This script is supposed to be a unit test for rosbash, also used for manual checks against other operating systems. + +# TODO extend this script + + +. ../roszsh + +echo "Testing ZSH" + +. ./test_zshbash.sh + +# roslaunch completion + +BUFFER=("foo roslaunch") +_roscomplete_search_dir +if [[ ! ${reply[@]} =~ "example.launch" ]]; then + echo "rosbash package missing from" ${reply[@]} ; exit 1 +fi +echo success roslaunch launchfiles diff --git a/tools/rosbash/test/test_scripts.py b/tools/rosbash/test/test_scripts.py index d054290f..55cd14ea 100644 --- a/tools/rosbash/test/test_scripts.py +++ b/tools/rosbash/test/test_scripts.py @@ -10,9 +10,14 @@ TEST_PATH = os.path.join(PKG_PATH, 'test') class TestRosBash(unittest.TestCase): def setUp(self): - self.cmd = os.path.join(TEST_PATH, 'test_rosbash.bash') - self.assertTrue(os.path.exists(self.cmd)) - + self.cmdbash = os.path.join(TEST_PATH, 'test_rosbash.bash') + self.assertTrue(os.path.exists(self.cmdbash)) + + self.cmdzsh = os.path.join(TEST_PATH, 'test_roszsh.zsh') + self.assertTrue(os.path.exists(self.cmdzsh)) + def test_rosbash_completion(self): - subprocess.check_call([self.cmd], cwd = TEST_PATH) + subprocess.check_call([self.cmdbash], cwd = TEST_PATH) + def test_roszsh_completion(self): + subprocess.check_call([self.cmdzsh], cwd = TEST_PATH)