add tutorial packages for the ros1-bridge examples

Signed-off-by: Mikael Arguedas <a16f295d1139a1392bb19262902c32cf3e999ce4@gmail.com>

%YAML 1.1
# ROS2 Dockerfile database
---
images:
    ros-core:
        base_image: @(os_name):@(os_code_name)
        maintainer_name: @(maintainer_name)
        template_name: docker_images_ros2/create_ros_core_image.Dockerfile.em
        entrypoint_name: docker_images_ros2/ros_entrypoint.sh
        pip3_install:
            - argcomplete
        template_packages:
            - docker_templates
        ros2_packages:
            - ros-core
    ros-base:
        base_image: @(user_name):@(ros2distro_name)-ros-core-@(os_code_name)
        maintainer_name: @(maintainer_name)
        template_name: docker_images_ros2/create_ros_image.Dockerfile.em
        template_packages:
            - docker_templates
        ros2_packages:
            - ros-base
    desktop:
        base_image: @(user_name):@(ros2distro_name)-ros-base-@(os_code_name)
        maintainer_name: @(maintainer_name)
        template_name: docker_images_ros2/create_ros_image.Dockerfile.em
        template_packages:
            - docker_templates
        ros2_packages:
            - desktop
    ros1-bridge:
        base_image: @(user_name):@(ros2distro_name)-ros-base-@(os_code_name)
        maintainer_name: @(maintainer_name)
        template_name: docker_images_ros2/ros1_bridge/create_ros_ros1_bridge_image.Dockerfile.em
        entrypoint_name: docker_images_ros2/ros1_bridge/ros_entrypoint.sh
        template_packages:
            - docker_templates
        ros2_packages:
            - ros1-bridge
            - demo-nodes-cpp
            - demo-nodes-py
        ros_packages:
            - ros-comm
            - roscpp-tutorials
            - rospy-tutorials

%YAML 1.1
# ROS2 Dockerfile database
---
images:
    ros-core:
        base_image: @(os_name):@(os_code_name)
        maintainer_name: @(maintainer_name)
        template_name: docker_images_ros2/create_ros_core_image.Dockerfile.em
        entrypoint_name: docker_images_ros2/ros_entrypoint.sh
        pip3_install:
            - argcomplete
        template_packages:
            - docker_templates
        ros2_packages:
            - ros-core
    ros-base:
        base_image: @(user_name):@(ros2distro_name)-ros-core-@(os_code_name)
        maintainer_name: @(maintainer_name)
        template_name: docker_images_ros2/create_ros_image.Dockerfile.em
        template_packages:
            - docker_templates
        ros2_packages:
            - ros-base
    desktop:
        base_image: @(user_name):@(ros2distro_name)-ros-base-@(os_code_name)
        maintainer_name: @(maintainer_name)
        template_name: docker_images_ros2/create_ros_image.Dockerfile.em
        template_packages:
            - docker_templates
        ros2_packages:
            - desktop
    ros1-bridge:
        base_image: @(user_name):@(ros2distro_name)-ros-base-@(os_code_name)
        maintainer_name: @(maintainer_name)
        template_name: docker_images_ros2/ros1_bridge/create_ros_ros1_bridge_image.Dockerfile.em
        entrypoint_name: docker_images_ros2/ros1_bridge/ros_entrypoint.sh
        template_packages:
            - docker_templates
        ros2_packages:
            - ros1-bridge
        ros_packages:
            - ros-comm


Disable __debugPrints in animationInfo class.

/*  Sirikata
 *  animationInfo.em
 *
 *  Copyright (c) 2011, Tahir Azim.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are
 *  met:
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *  * Neither the name of Sirikata nor the names of its contributors may
 *    be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

system.require("std/library.em");

/** The AnimationInfo class enables the graphics system to send out
    notifications when an object starts or stops animating.
 */
std.graphics.AnimationInfo = system.Class.extend(
    {
        init: function(pres, sim) {
            this._pres = pres;

            this._subscription_group = [];

            this._simulator = sim;

            var p  = new util.Pattern("name", "support_animation");
            std.core.bind(this.onTestMessage, this) << p;
           this._pres.onProxAdded(std.core.bind(this.proxAddedCallback, this), true);
        },

        // Send a message to all current members of the chat group
        sendAll: function(msg) {
            for(var i = 0; i < this._subscription_group.length; i++) {
                //system.__debugPrint("Sending anim msg to " + this._subscription_group[i] + " \n");
                msg >> this._subscription_group[i] >> [];
            }
        },

        // Handles requests from the UI to send a chat messages.
        sendAnimationInfo: function(cmd, vis_addr, anim_name) {
            if (cmd == 'AnimationInfo' && vis_addr && anim_name)
                this.sendAll( { 'animation_info' : '1', 'vis_addr' : vis_addr, 'anim_name' : anim_name } );
        },

        // Handler for animation msgs from others.
        onAnimationMessage: function(msg, sender) {
            //system.__debugPrint("Received anim msg: " + msg.vis_addr + " : " + msg.anim_name + "\n");

            var visibleMap = system.getProxSet(system.self);
            for (var key in visibleMap) {
              //system.__debugPrint(key + " compared to "  + msg.vis_addr + "\n");
              if (msg.vis_addr == key) {
                this._simulator.startAnimation(visibleMap[key], msg.anim_name, true);
              }
           }
        },

        // Handle an initial message from a new neighbor, adding them and listening for messages from them.
        handleNewAnimationSubscriber: function(msg, sender) {
            if (msg.support_animation != 'yes') return;

            for(var i = 0; i < this._subscription_group.length; i++) {
                if(this._subscription_group[i].toString() == sender.toString())
                    return;
            }

            //system.__debugPrint("Adding "  + sender + " to subscription group\n");

            this._subscription_group.push(sender);
            var p = new util.Pattern("animation_info");
            std.core.bind(this.onAnimationMessage, this) << p << sender;
        },

        proxAddedCallback: function(new_addr_obj) {
            if(system.self.toString() == new_addr_obj.toString())
                return;

            this.sendIntro(new_addr_obj, 5);
        },

        sendIntro: function(new_addr_obj, retries) {
            if (retries == 0) return;

            var test_msg = { "name" : "support_animation" };
            //also register a callback
            test_msg >> new_addr_obj >> [std.core.bind(this.handleNewAnimationSubscriber, this), 2, std.core.bind(this.sendIntro, this, new_addr_obj, retries-1)];
        },

        // Reply to probes for what protocols we support.
        onTestMessage: function(msg, sender) {
            //system.__debugPrint("Replying to intro msg\n");
            msg.makeReply( { "support_animation": "yes" } ) >> [];
        }
    }
);

/*  Sirikata
 *  animationInfo.em
 *
 *  Copyright (c) 2011, Tahir Azim.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are
 *  met:
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *  * Neither the name of Sirikata nor the names of its contributors may
 *    be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

system.require("std/library.em");

/** The AnimationInfo class enables the graphics system to send out
    notifications when an object starts or stops animating.
 */
std.graphics.AnimationInfo = system.Class.extend(
    {
        init: function(pres, sim) {
            this._pres = pres;

            this._subscription_group = [];

            this._simulator = sim;

            var p  = new util.Pattern("name", "support_animation");
            std.core.bind(this.onTestMessage, this) << p;
           this._pres.onProxAdded(std.core.bind(this.proxAddedCallback, this), true);
        },

        // Send a message to all current members of the chat group
        sendAll: function(msg) {
            for(var i = 0; i < this._subscription_group.length; i++) {
                system.__debugPrint("Sending anim msg to " + this._subscription_group[i] + " \n");
                msg >> this._subscription_group[i] >> [];
            }
        },

        // Handles requests from the UI to send a chat messages.
        sendAnimationInfo: function(cmd, vis_addr, anim_name) {
            if (cmd == 'AnimationInfo' && vis_addr && anim_name)
                this.sendAll( { 'animation_info' : '1', 'vis_addr' : vis_addr, 'anim_name' : anim_name } );
        },

        // Handler for animation msgs from others.
        onAnimationMessage: function(msg, sender) {
            system.__debugPrint("Received anim msg: " + msg.vis_addr + " : " + msg.anim_name + "\n");

            var visibleMap = system.getProxSet(system.self);
            for (var key in visibleMap) {
              system.__debugPrint(key + " compared to "  + msg.vis_addr + "\n");
              if (msg.vis_addr == key) {
                this._simulator.startAnimation(visibleMap[key], msg.anim_name, true);
              }
           }
        },

        // Handle an initial message from a new neighbor, adding them and listening for messages from them.
        handleNewAnimationSubscriber: function(msg, sender) {
            if (msg.support_animation != 'yes') return;

            for(var i = 0; i < this._subscription_group.length; i++) {
                if(this._subscription_group[i].toString() == sender.toString())
                    return;
            }

            system.__debugPrint("Adding "  + sender + " to subscription group\n");

            this._subscription_group.push(sender);
            var p = new util.Pattern("animation_info");
            std.core.bind(this.onAnimationMessage, this) << p << sender;
        },

        proxAddedCallback: function(new_addr_obj) {
            if(system.self.toString() == new_addr_obj.toString())
                return;

            this.sendIntro(new_addr_obj, 5);
        },

        sendIntro: function(new_addr_obj, retries) {
            if (retries == 0) return;

            var test_msg = { "name" : "support_animation" };
            //also register a callback
            test_msg >> new_addr_obj >> [std.core.bind(this.handleNewAnimationSubscriber, this), 2, std.core.bind(this.sendIntro, this, new_addr_obj, retries-1)];
        },

        // Reply to probes for what protocols we support.
        onTestMessage: function(msg, sender) {
            system.__debugPrint("Replying to intro msg\n");
            msg.makeReply( { "support_animation": "yes" } ) >> [];
        }
    }
);


Relocate ROS2_WS to /opt

Relocate ROS2_WS to /opt

%YAML 1.1
# ROS2 Dockerfile database
---
images:
    source:
        base_image: @(os_name):@(os_code_name)
        maintainer_name: @(maintainer_name)
        template_name: docker_images_ros2/source/create_ros_image.Dockerfile.em
        entrypoint_name: docker_images_ros2/source/ros_entrypoint.sh
        template_packages:
            - docker_templates
        upstream_packages:
            - bash-completion
            - git
            - libasio-dev
            - libtinyxml2-dev
            - wget
        ros2_repo_packages:
            - python3-catkin-pkg-modules
            - python3-rosdep
            - python3-vcstool
        pip3_install:
            - argcomplete
            - flake8
            - flake8-blind-except
            - flake8-builtins
            - flake8-class-newline
            - flake8-comprehensions
            - flake8-deprecated
            - flake8-docstrings
            - flake8-import-order
            - flake8-quotes
            - pytest-repeat
            - pytest-rerunfailures
        ws: /opt/ros2_ws
        colcon_args:
            - build
            - --cmake-args
                -DSECURITY=ON --no-warn-unused-cli
            - --symlink-install
        rosdep:
            install:
                - --from-paths src
                - --ignore-src
                - --rosdistro bouncy
                - --skip-keys "console_bridge fastcdr fastrtps libopensplice67 libopensplice69 rti-connext-dds-5.3.1 urdfdom_headers"
        vcs:
            ros2:
                repos: https://raw.githubusercontent.com/ros2/ros2/release-latest/ros2.repos

%YAML 1.1
# ROS2 Dockerfile database
---
images:
    source:
        base_image: @(os_name):@(os_code_name)
        maintainer_name: @(maintainer_name)
        template_name: docker_images_ros2/source/create_ros_image.Dockerfile.em
        entrypoint_name: docker_images_ros2/source/ros_entrypoint.sh
        template_packages:
            - docker_templates
        upstream_packages:
            - bash-completion
            - git
            - libasio-dev
            - libtinyxml2-dev
            - wget
        ros2_repo_packages:
            - python3-catkin-pkg-modules
            - python3-rosdep
            - python3-vcstool
        pip3_install:
            - argcomplete
            - flake8
            - flake8-blind-except
            - flake8-builtins
            - flake8-class-newline
            - flake8-comprehensions
            - flake8-deprecated
            - flake8-docstrings
            - flake8-import-order
            - flake8-quotes
            - pytest-repeat
            - pytest-rerunfailures
        ws: /root/ros2_ws
        colcon_args:
            - build
            - --cmake-args
                -DSECURITY=ON --no-warn-unused-cli
            - --symlink-install
        rosdep:
            install:
                - --from-paths src
                - --ignore-src
                - --rosdistro bouncy
                - --skip-keys "console_bridge fastcdr fastrtps libopensplice67 libopensplice69 rti-connext-dds-5.3.1 urdfdom_headers"
        vcs:
            ros2:
                repos: https://raw.githubusercontent.com/ros2/ros2/release-latest/ros2.repos


Allow expected ROS_DISTRO value to be overridden at compile time.

# generated from ros/env-hooks/10.ros.sh.em

# scrub old ROS bin dirs, to avoid accidentally finding the wrong executables
export PATH="`@(PYTHON_EXECUTABLE) -c \"import os; print(os.pathsep.join([x for x in \\\"$PATH\\\".split(os.pathsep) if not any([d for d in ['cturtle', 'diamondback', 'electric', 'fuerte'] if d in x])]))\"`"

@{
# This is a build-time environment variable which allows a build engineer to override the expected
# ROS_DISTRO value for a workspace, for example to deliberately use a newer version of roslib with
# an older release or vice-versa, or to define a custom distro (eg, "ROS Banana").
from os import environ
ROS_DISTRO = environ.get("ROS_DISTRO_OVERRIDE", "kinetic")
}@
if [ -n "$ROS_DISTRO" -a "$ROS_DISTRO" != "@(ROS_DISTRO)" ]; then
  echo "ROS_DISTRO was set to '$ROS_DISTRO' before. Please make sure that the environment does not mix paths from different distributions."
fi
export ROS_DISTRO=@(ROS_DISTRO)

# python function to generate ROS package path based on all workspaces
PYTHON_CODE_BUILD_ROS_PACKAGE_PATH=$(cat <<EOF
from __future__ import print_function
import os
env_name = 'CMAKE_PREFIX_PATH'
paths = [path for path in os.environ[env_name].split(os.pathsep)] if env_name in os.environ and os.environ[env_name] != '' else []
workspaces = [path for path in paths if os.path.exists(os.path.join(path, '.catkin'))]
paths = []
for workspace in workspaces:
    filename = os.path.join(workspace, '.catkin')
    data = ''
    with open(filename) as f:
        data = f.read()
    if data == '':
        paths.append(os.path.join(workspace, 'share'))
        if os.path.isdir(os.path.join(workspace, 'stacks')):
            paths.append(os.path.join(workspace, 'stacks'))
    else:
        for source_path in data.split(';'):
            paths.append(source_path)
print(os.pathsep.join(paths))
EOF
)
export ROS_PACKAGE_PATH="`@(PYTHON_EXECUTABLE) -c \"$PYTHON_CODE_BUILD_ROS_PACKAGE_PATH\"`"

@[if DEVELSPACE]@
# env variables in develspace
export ROS_ETC_DIR="@(CATKIN_DEVEL_PREFIX)/@(CATKIN_GLOBAL_ETC_DESTINATION)/ros"
@[else]@
# env variables in installspace
if [ -z "$CATKIN_ENV_HOOK_WORKSPACE" ]; then
  CATKIN_ENV_HOOK_WORKSPACE="@(CMAKE_INSTALL_PREFIX)"
fi
export ROS_ETC_DIR="$CATKIN_ENV_HOOK_WORKSPACE/@(CATKIN_GLOBAL_ETC_DESTINATION)/ros"
@[end if]@

# unset ROS workspace
unset ROS_WORKSPACE

# generated from ros/env-hooks/10.ros.sh.em

# scrub old ROS bin dirs, to avoid accidentally finding the wrong executables
export PATH="`@(PYTHON_EXECUTABLE) -c \"import os; print(os.pathsep.join([x for x in \\\"$PATH\\\".split(os.pathsep) if not any([d for d in ['cturtle', 'diamondback', 'electric', 'fuerte'] if d in x])]))\"`"

if [ -n "$ROS_DISTRO" -a "$ROS_DISTRO" != "kinetic" ]; then
  echo "ROS_DISTRO was set to '$ROS_DISTRO' before. Please make sure that the environment does not mix paths from different distributions."
fi
export ROS_DISTRO=kinetic

# python function to generate ROS package path based on all workspaces
PYTHON_CODE_BUILD_ROS_PACKAGE_PATH=$(cat <<EOF
from __future__ import print_function
import os
env_name = 'CMAKE_PREFIX_PATH'
paths = [path for path in os.environ[env_name].split(os.pathsep)] if env_name in os.environ and os.environ[env_name] != '' else []
workspaces = [path for path in paths if os.path.exists(os.path.join(path, '.catkin'))]
paths = []
for workspace in workspaces:
    filename = os.path.join(workspace, '.catkin')
    data = ''
    with open(filename) as f:
        data = f.read()
    if data == '':
        paths.append(os.path.join(workspace, 'share'))
        if os.path.isdir(os.path.join(workspace, 'stacks')):
            paths.append(os.path.join(workspace, 'stacks'))
    else:
        for source_path in data.split(';'):
            paths.append(source_path)
print(os.pathsep.join(paths))
EOF
)
export ROS_PACKAGE_PATH="`@(PYTHON_EXECUTABLE) -c \"$PYTHON_CODE_BUILD_ROS_PACKAGE_PATH\"`"

@[if DEVELSPACE]@
# env variables in develspace
export ROS_ETC_DIR="@(CATKIN_DEVEL_PREFIX)/@(CATKIN_GLOBAL_ETC_DESTINATION)/ros"
@[else]@
# env variables in installspace
if [ -z "$CATKIN_ENV_HOOK_WORKSPACE" ]; then
  CATKIN_ENV_HOOK_WORKSPACE="@(CMAKE_INSTALL_PREFIX)"
fi
export ROS_ETC_DIR="$CATKIN_ENV_HOOK_WORKSPACE/@(CATKIN_GLOBAL_ETC_DESTINATION)/ros"
@[end if]@

# unset ROS workspace
unset ROS_WORKSPACE


Removed genmsg-in-package, changed force-genmsg to genmsg, fixed bugs

# vim: set ft=cmake :
@[if DEVELSPACE]@
# location of scripts in develspace
set(GENGO_BIN_DIR "@(CMAKE_CURRENT_SOURCE_DIR)/scripts" CACHE INTERNAL "gengo binary directory")
@[else]@
# location of scripts in installspace
set(GENGO_BIN_DIR "${gengo_DIR}/../../../@(CATKIN_PACKAGE_BIN_DESTINATION)" CACHE INTERNAL "gengo binary directory")
@[end if]@

set(GENMSG_GO_BIN ${GENGO_BIN_DIR}/gen_go.py CACHE INTERNAL "genmsg for go")
set(GENSRV_GO_BIN ${GENGO_BIN_DIR}/gen_go.py CACHE INTERNAL "genmsg for go")

execute_process(COMMAND go env GOARCH OUTPUT_VARIABLE ROSGO_ARCH OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(COMMAND go env GOOS OUTPUT_VARIABLE ROSGO_OS OUTPUT_STRIP_TRAILING_WHITESPACE)

set(gengo_INSTALL_DIR ${CATKIN_GLOBAL_LIB_DESTINATION}/go/src)

# Generate .msg -> .go
# The generated .go files should be added ALL_GEN_OUTPUT_FILES_go
macro(_generate_msg_go ARG_PKG ARG_MSG ARG_IFLAGS ARG_MSG_DEPS ARG_GEN_OUTPUT_DIR)
  #Create input and output filenames
  get_filename_component(MSG_SHORT_NAME ${ARG_MSG} NAME_WE)

  #Append msg to output dir
  set(GEN_OUTPUT_DIR "${ARG_GEN_OUTPUT_DIR}")
  file(MAKE_DIRECTORY ${GEN_OUTPUT_DIR})

  set(MSG_GENERATED_NAME ${MSG_SHORT_NAME}.go)
  set(GEN_OUTPUT_FILE ${GEN_OUTPUT_DIR}/${MSG_GENERATED_NAME})

  add_custom_command(OUTPUT ${GEN_OUTPUT_FILE}
    DEPENDS ${GENMSG_GO_BIN} ${ARG_MSG} ${ARG_MSG_DEPS}
    COMMAND ${CATKIN_ENV} ${GENMSG_GO_BIN} ${ARG_MSG}
    ${ARG_IFLAGS}
    -p ${ARG_PKG}
    -o ${GEN_OUTPUT_DIR}
    COMMENT "Generating Go code from MSG ${ARG_PKG}/${MSG_SHORT_NAME}"
    )

  list(APPEND ALL_GEN_OUTPUT_FILES_go ${GEN_OUTPUT_FILE})

endmacro()

#todo, these macros are practically equal. Check for input file extension instead
macro(_generate_srv_go ARG_PKG ARG_SRV ARG_IFLAGS ARG_MSG_DEPS ARG_GEN_OUTPUT_DIR)
  #Create input and output filenames
  get_filename_component(SRV_SHORT_NAME ${ARG_SRV} NAME_WE)

  #Append msg to output dir
  set(GEN_OUTPUT_DIR "${ARG_GEN_OUTPUT_DIR}")
  file(MAKE_DIRECTORY ${GEN_OUTPUT_DIR})

  set(SRV_GENERATED_NAME ${SRV_SHORT_NAME}.go)
  set(GEN_OUTPUT_FILE ${GEN_OUTPUT_DIR}/${SRV_GENERATED_NAME})

  add_custom_command(OUTPUT ${GEN_OUTPUT_FILE}
    DEPENDS ${GENSRV_GO_BIN} ${ARG_SRV} ${ARG_MSG_DEPS}
    COMMAND ${CATKIN_ENV} ${PYTHON_EXECUTABLE} ${GENSRV_GO_BIN} ${ARG_SRV}
    ${ARG_IFLAGS}
    -p ${ARG_PKG}
    -o ${GEN_OUTPUT_DIR}
    COMMENT "Generating Go code from SRV ${ARG_PKG}/${SRV_SHORT_NAME}"
    )

  list(APPEND ALL_GEN_OUTPUT_FILES_go ${GEN_OUTPUT_FILE})
endmacro()

macro(_generate_module_go ARG_PKG ARG_GEN_OUTPUT_DIR ARG_GENERATED_FILES)
  # Nothing to do
endmacro()

# Generate messages from specified packages.  As a result the macro
# defines a custom target `${pkg}_gengo` for each package.  Can be
# repeated and will only generate messages for each package once.
macro(rosgo_generate_messages)
    set(ROSGO_SRC_DIR ${CATKIN_DEVEL_PREFIX}/lib/go/src)
    execute_process(COMMAND ${CATKIN_ENV} rosmsg packages -s
                    OUTPUT_VARIABLE rosmsg_output
                    OUTPUT_STRIP_TRAILING_WHITESPACE)
    string(REPLACE " " ";" msg_pkg_list ${rosmsg_output})
    set(iflags "")
    foreach(msg_pkg ${msg_pkg_list})
        execute_process(COMMAND ${CATKIN_ENV} rospack find ${msg_pkg}
                        OUTPUT_VARIABLE msg_pkg_path
                        OUTPUT_STRIP_TRAILING_WHITESPACE)
        list(APPEND iflags "-I${msg_pkg}:${msg_pkg_path}/msg")
    endforeach()
    set(all_gen_output_files "")
    foreach(pkg ${ARGV})
        if(NOT TARGET ${pkg}_gengo)
            # Find msg directory
            execute_process(COMMAND ${CATKIN_ENV} rospack find ${pkg}
                            OUTPUT_VARIABLE pkg_path
                            OUTPUT_STRIP_TRAILING_WHITESPACE)
            set(gen_output_files "")

            #message(STATUS pkg_path=${pkg_path})
            set(msg_dir ${pkg_path}/msg)
            #message(STATUS msg_dir=${msg_dir})
            file(GLOB msg_files "${msg_dir}/*.msg")
            #message(STATUS msg_files=${msg_files})

            foreach(msg ${msg_files})
                file(MAKE_DIRECTORY ${ROSGO_SRC_DIR}/${pkg})
                get_filename_component(msg_name ${msg} NAME_WE)
                set(output_file ${ROSGO_SRC_DIR}/${pkg}/${msg_name}.go)
                add_custom_command(OUTPUT ${output_file}
                    COMMAND ${CATKIN_ENV} ${PYTHON_EXECUTABLE} ${GENMSG_GO_BIN}
                    ${msg} ${iflags} -p ${pkg} -o ${ROSGO_SRC_DIR}/${pkg}
                    )
                list(APPEND gen_output_files ${output_file})
            endforeach()

            set(srv_dir ${pkg_path}/srv)
            #message(STATUS srv_dir=${srv_dir})
            file(GLOB srv_files "${srv_dir}/*.srv")
            #message(STATUS srv_files=${srv_files})
            foreach(srv ${srv_files})
                file(MAKE_DIRECTORY ${ROSGO_SRC_DIR}/${pkg})
                get_filename_component(srv_name ${srv} NAME_WE)
                set(output_files "")
                list(APPEND output_files ${ROSGO_SRC_DIR}/${pkg}/${srv_name}.go)
                list(APPEND output_files ${ROSGO_SRC_DIR}/${pkg}/${srv_name}Request.go)
                list(APPEND output_files ${ROSGO_SRC_DIR}/${pkg}/${srv_name}Response.go)
                add_custom_command(OUTPUT ${output_files}
                    COMMAND ${CATKIN_ENV} ${PYTHON_EXECUTABLE} ${GENMSG_GO_BIN}
                    ${srv} ${iflags} -p ${pkg} -o ${ROSGO_SRC_DIR}/${pkg}
                    )
                list(APPEND gen_output_files ${output_files})
            endforeach()

            #install(DIRECTORY ${CATKIN_DEVEL_PREFIX}/lib/go/src/${pkg}/gen
            #        DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/go/src/gen
            #        PATTERN "*.go")

            #list(APPEND all_gen_output_files ${gen_output_files})
            add_custom_target(${pkg}_gengo ALL DEPENDS ${gen_output_files})
        endif()
    endforeach()
    #foreach(pkg ${ARGV})
    #    set(msg_lib ${CATKIN_DEVEL_PREFIX}/lib/go/pkg/${ROSGO_OS}_${ROSGO_ARCH}/${pkg}/gen.a)
    #    add_custom_command(OUTPUT ${msg_lib}
    #        COMMAND env GOPATH=${CATKIN_DEVEL_PREFIX}/lib/go go install ${pkg}/gen
    #        DEPENDS ${all_gen_output_files}
    #        )
    #    add_custom_target(rosgo_genmsg_for_${pkg} ALL DEPENDS ${msg_lib})

    #    install(FILES ${msg_lib}
    #        DESTINATION ${CMAKE_INSTALL_PREFIX}/go/pkg/${ROSGO_OS}_${ROSGO_ARCH}/)
    #endforeach()
endmacro()

# vim: set ft=cmake :
@[if DEVELSPACE]@
# location of scripts in develspace
set(GENGO_BIN_DIR "@(CMAKE_CURRENT_SOURCE_DIR)/scripts")
@[else]@
# location of scripts in installspace
set(GENGO_BIN_DIR "${gengo_DIR}/../../../@(CATKIN_PACKAGE_BIN_DESTINATION)")
@[end if]@

set(GENMSG_GO_BIN ${GENGO_BIN_DIR}/gen_go.py)
set(GENSRV_GO_BIN ${GENGO_BIN_DIR}/gen_go.py)

execute_process(COMMAND go env GOARCH OUTPUT_VARIABLE ROSGO_ARCH OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(COMMAND go env GOOS OUTPUT_VARIABLE ROSGO_OS OUTPUT_STRIP_TRAILING_WHITESPACE)

set(gengo_INSTALL_DIR ${CATKIN_GLOBAL_LIB_DESTINATION}/go/src)

# Generate .msg -> .go
# The generated .go files should be added ALL_GEN_OUTPUT_FILES_go
macro(_generate_msg_go ARG_PKG ARG_MSG ARG_IFLAGS ARG_MSG_DEPS ARG_GEN_OUTPUT_DIR)
  #Create input and output filenames
  get_filename_component(MSG_SHORT_NAME ${ARG_MSG} NAME_WE)

  #Append msg to output dir
  set(GEN_OUTPUT_DIR "${ARG_GEN_OUTPUT_DIR}")
  file(MAKE_DIRECTORY ${GEN_OUTPUT_DIR})

  set(MSG_GENERATED_NAME ${MSG_SHORT_NAME}.go)
  set(GEN_OUTPUT_FILE ${GEN_OUTPUT_DIR}/${MSG_GENERATED_NAME})

  add_custom_command(OUTPUT ${GEN_OUTPUT_FILE}
    DEPENDS ${GENMSG_GO_BIN} ${ARG_MSG} ${ARG_MSG_DEPS}
    COMMAND ${CATKIN_ENV} ${GENMSG_GO_BIN} ${ARG_MSG}
    ${ARG_IFLAGS}
    -p ${ARG_PKG}
    -o ${GEN_OUTPUT_DIR}
    COMMENT "Generating Go code from MSG ${ARG_PKG}/${MSG_SHORT_NAME}"
    )

  list(APPEND ALL_GEN_OUTPUT_FILES_go ${GEN_OUTPUT_FILE})

endmacro()

#todo, these macros are practically equal. Check for input file extension instead
macro(_generate_srv_go ARG_PKG ARG_SRV ARG_IFLAGS ARG_MSG_DEPS ARG_GEN_OUTPUT_DIR)
  #Create input and output filenames
  get_filename_component(SRV_SHORT_NAME ${ARG_SRV} NAME_WE)

  #Append msg to output dir
  set(GEN_OUTPUT_DIR "${ARG_GEN_OUTPUT_DIR}")
  file(MAKE_DIRECTORY ${GEN_OUTPUT_DIR})

  set(SRV_GENERATED_NAME ${SRV_SHORT_NAME}.go)
  set(GEN_OUTPUT_FILE ${GEN_OUTPUT_DIR}/${SRV_GENERATED_NAME})

  add_custom_command(OUTPUT ${GEN_OUTPUT_FILE}
    DEPENDS ${GENSRV_GO_BIN} ${ARG_SRV} ${ARG_MSG_DEPS}
    COMMAND ${CATKIN_ENV} ${PYTHON_EXECUTABLE} ${GENSRV_GO_BIN} ${ARG_SRV}
    ${ARG_IFLAGS}
    -p ${ARG_PKG}
    -o ${GEN_OUTPUT_DIR}
    COMMENT "Generating Go code from SRV ${ARG_PKG}/${SRV_SHORT_NAME}"
    )

  list(APPEND ALL_GEN_OUTPUT_FILES_go ${GEN_OUTPUT_FILE})
endmacro()

macro(_generate_module_go ARG_PKG ARG_GEN_OUTPUT_DIR ARG_GENERATED_FILES)
  # Nothing to do
endmacro()

macro(rosgo_generate_message_in_package _package)
    set(pkg ${_package})
    execute_process(COMMAND ${CATKIN_ENV} rosmsg packages -s
                    OUTPUT_VARIABLE rosmsg_output
                    OUTPUT_STRIP_TRAILING_WHITESPACE)
    string(REPLACE " " ";" msg_pkg_list ${rosmsg_output})
    set(iflags "")
    foreach(msg_pkg ${msg_pkg_list})
        execute_process(COMMAND ${CATKIN_ENV} rospack find ${msg_pkg}
                        OUTPUT_VARIABLE msg_pkg_path
                        OUTPUT_STRIP_TRAILING_WHITESPACE)
        list(APPEND iflags "-I${msg_pkg}:${msg_pkg_path}/msg")
    endforeach()

    # Find msg directory
    execute_process(COMMAND ${CATKIN_ENV} rospack find ${pkg}
                    OUTPUT_VARIABLE pkg_path
                    OUTPUT_STRIP_TRAILING_WHITESPACE)
    set(gen_output_files "")

    #message(STATUS pkg_path=${pkg_path})
    set(msg_dir ${pkg_path}/msg)
    #message(STATUS msg_dir=${msg_dir})
    file(GLOB msg_files "${msg_dir}/*.msg")
    #message(STATUS msg_files=${msg_files})

    foreach(msg ${msg_files})
        file(MAKE_DIRECTORY ${PROJECT_SOURCE_DIR}/src/${pkg})
        get_filename_component(msg_name ${msg} NAME_WE)
        set(output_file ${PROJECT_SOURCE_DIR}/src/${pkg}/gen/${msg_name}.go)
        add_custom_command(OUTPUT ${output_file}
            COMMAND ${CATKIN_ENV} ${PYTHON_EXECUTABLE} ${GENMSG_GO_BIN}
            ${msg} ${iflags} -p ${pkg} -o ${PROJECT_SOURCE_DIR}/src/${pkg}/gen
            )
        list(APPEND gen_output_files ${output_file})
    endforeach()

    set(srv_dir ${pkg_path}/srv)
    #message(STATUS srv_dir=${srv_dir})
    file(GLOB srv_files "${srv_dir}/*.srv")
    #message(STATUS srv_files=${srv_files})
    foreach(srv ${srv_files})
        file(MAKE_DIRECTORY ${PROJECT_SOURCE_DIR}/src/${pkg})
        get_filename_component(srv_name ${srv} NAME_WE)
        set(output_files "")
        list(APPEND output_files ${PROJECT_SOURCE_DIR}/src/${pkg}/gen/${srv_name}.go)
        list(APPEND output_files ${PROJECT_SOURCE_DIR}/src/${pkg}/gen/${srv_name}Request.go)
        list(APPEND output_files ${PROJECT_SOURCE_DIR}/src/${pkg}/gen/${srv_name}Response.go)
        add_custom_command(OUTPUT ${output_files}
            COMMAND ${CATKIN_ENV} ${PYTHON_EXECUTABLE} ${GENMSG_GO_BIN}
            ${srv} ${iflags} -p ${pkg} -o ${PROJECT_SOURCE_DIR}/src/${pkg}/gen
            )
        list(APPEND gen_output_files ${output_files})
    endforeach()
    add_custom_target(rosgo_generate_${pkg}_in_${PROJECT_NAME} ALL DEPENDS ${gen_output_files})
endmacro()

# Force generate specified messages.
# As a result the macro defines a custom target `${pkg}_gengo`.
macro(rosgo_force_generate_messages)
    set(ROSGO_SRC_DIR ${CATKIN_DEVEL_PREFIX}/lib/go/src)
    execute_process(COMMAND ${CATKIN_ENV} rosmsg packages -s
                    OUTPUT_VARIABLE rosmsg_output
                    OUTPUT_STRIP_TRAILING_WHITESPACE)
    string(REPLACE " " ";" msg_pkg_list ${rosmsg_output})
    set(iflags "")
    foreach(msg_pkg ${msg_pkg_list})
        execute_process(COMMAND ${CATKIN_ENV} rospack find ${msg_pkg}
                        OUTPUT_VARIABLE msg_pkg_path
                        OUTPUT_STRIP_TRAILING_WHITESPACE)
        list(APPEND iflags "-I${msg_pkg}:${msg_pkg_path}/msg")
    endforeach()
    set(all_gen_output_files "")
    foreach(pkg ${ARGV})
        # Find msg directory
        execute_process(COMMAND ${CATKIN_ENV} rospack find ${pkg}
                        OUTPUT_VARIABLE pkg_path
                        OUTPUT_STRIP_TRAILING_WHITESPACE)
        set(gen_output_files "")

        #message(STATUS pkg_path=${pkg_path})
        set(msg_dir ${pkg_path}/msg)
        #message(STATUS msg_dir=${msg_dir})
        file(GLOB msg_files "${msg_dir}/*.msg")
        #message(STATUS msg_files=${msg_files})

        foreach(msg ${msg_files})
            file(MAKE_DIRECTORY ${ROSGO_SRC_DIR}/${pkg})
            get_filename_component(msg_name ${msg} NAME_WE)
            set(output_file ${ROSGO_SRC_DIR}/${pkg}/${msg_name}.go)
            add_custom_command(OUTPUT ${output_file}
                COMMAND ${CATKIN_ENV} ${PYTHON_EXECUTABLE} ${GENMSG_GO_BIN}
                ${msg} ${iflags} -p ${pkg} -o ${ROSGO_SRC_DIR}/${pkg}
                )
            list(APPEND gen_output_files ${output_file})
        endforeach()

        set(srv_dir ${pkg_path}/srv)
        #message(STATUS srv_dir=${srv_dir})
        file(GLOB srv_files "${srv_dir}/*.srv")
        #message(STATUS srv_files=${srv_files})
        foreach(srv ${srv_files})
            file(MAKE_DIRECTORY ${ROSGO_SRC_DIR}/${pkg})
            get_filename_component(srv_name ${srv} NAME_WE)
            set(output_files "")
            list(APPEND output_files ${ROSGO_SRC_DIR}/${pkg}/${srv_name}.go)
            list(APPEND output_files ${ROSGO_SRC_DIR}/${pkg}/${srv_name}Request.go)
            list(APPEND output_files ${ROSGO_SRC_DIR}/${pkg}/${srv_name}Response.go)
            add_custom_command(OUTPUT ${output_files}
                COMMAND ${CATKIN_ENV} ${PYTHON_EXECUTABLE} ${GENMSG_GO_BIN}
                ${srv} ${iflags} -p ${pkg} -o ${ROSGO_SRC_DIR}/${pkg}
                )
            list(APPEND gen_output_files ${output_files})
        endforeach()

        #install(DIRECTORY ${CATKIN_DEVEL_PREFIX}/lib/go/src/${pkg}/gen
        #        DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/go/src/gen
        #        PATTERN "*.go")

        #list(APPEND all_gen_output_files ${gen_output_files})
        add_custom_target(${pkg}_gengo ALL DEPENDS ${gen_output_files})
    endforeach()
    #foreach(pkg ${ARGV})
    #    set(msg_lib ${CATKIN_DEVEL_PREFIX}/lib/go/pkg/${ROSGO_OS}_${ROSGO_ARCH}/${pkg}/gen.a)
    #    add_custom_command(OUTPUT ${msg_lib}
    #        COMMAND env GOPATH=${CATKIN_DEVEL_PREFIX}/lib/go go install ${pkg}/gen
    #        DEPENDS ${all_gen_output_files}
    #        )
    #    add_custom_target(rosgo_genmsg_for_${pkg} ALL DEPENDS ${msg_lib})

    #    install(FILES ${msg_lib}
    #        DESTINATION ${CMAKE_INSTALL_PREFIX}/go/pkg/${ROSGO_OS}_${ROSGO_ARCH}/)
    #endforeach()
endmacro()


Through gui, can now remove files from visibles.

system.require('std/core/simpleInput.em');

(function()
 {

     /**
      @param {std.ScriptingGui.Controller}

      @param {object: <String(visibleId):visible object>} nearbyVisMap
      -- all the visible objects that satisfy scripter's proximity
      query.

      @param {object: <String(visibleId):
      std.FileManager.FileManagerElement> scriptedVisMap -- A record
      of all visibles that we have scripted at some point.

      @param {object: <int:std.ScriptingGui.Action> actionMap -- Which
      actions are selectable by scripter.

      @param {std.ScriptingGui.Console} console -- has several
      scripting events.
      */
     std.ScriptingGui =
         function(controller,nearbyVisMap,scriptedVisMap,actionMap,console)
     {
         if (typeof(simulator) == 'undefined')
         {
             throw new Error('Cannot initialize scripting gui without ' +
                             'simulator graphics.');
         }

         this.controller       = controller;
         this.nearbyVisMap     = nearbyVisMap;
         this.scriptedVisMap   = scriptedVisMap;
         this.actionMap        = actionMap;
         this.console          = console;

         this.guiMod = simulator._simulator.addGUITextModule(
             guiName(),
             getGuiText(),
             std.core.bind(guiInitFunc,undefined,this));
         this.hasInited = false;
     };

     system.require('scriptingGuiUtil.em');

     std.ScriptingGui.prototype.redraw = function()
     {
         if (!this.hasInited)
             return;

         //trigger redraw call
         this.guiMod.call(
             'ishmaelRedraw',toHtmlNearbyMap(this),toHtmlScriptedMap(this),
             toHtmlActionMap(this),toHtmlFileMap(this));
     };

     /**
      @param {String} visId -- Id of visible.
      */
     //called by html to add the visible with id
     std.ScriptingGui.prototype.hAddVisible = function(visId)
     {
         //already can script the visible.
         if (visId in this.scriptedVisMap)
         {
             this.console.guiEvent();
             this.redraw();
             return;
         }

         if (!(visId in this.nearbyVisMap))
         {
             //visible is no longer available.
             this.console.guiEvent();
             this.redraw();
             return;
         }

         //redraw called from inside of addVisible.
         this.controller.addVisible(this.nearbyVisMap[visId]);
     };

     std.ScriptingGui.prototype.hRemoveVisible = function(visId)
     {
         //FIXME: should finish this call
         throw new Error('FIXME: must finish hRemoveVisible call ' +
                         'in scriptingGui');
     };

     /**
      @param {String?} actId -- Should be parsedInt to get an index
      into actionMap
      @param {String} newText -- What action with actId should set as
      its text.
      */
     std.ScriptingGui.prototype.hSaveAction = function(actId,newText)
     {
         this.controller.editAction(parseInt(actId),newText);
     };

     /**
      @param {String?} actId -- Should be parsedInt to get an index
      into actionMap
      @param {String} newText -- What action with actId should set as
      its text.
      @param {String} visId   -- Id of visible to execute action on.
      */
     std.ScriptingGui.prototype.hSaveAndExecuteAction =
         function(actId,newText, visId)
     {
         this.hSaveAction(actId,newText);
         this.controller.execAction(actId,visId);
     };

     /**
      Prompt user for the name of the new action using
      std.core.SimpleInput.
      */
     std.ScriptingGui.prototype.hNewAction =
         function()
     {
         var newInput = std.core.SimpleInput(
             std.core.SimpleInput.ENTER_TEXT,
             'Enter new action\'s name',
             std.core.bind(addActionInputCB,undefined,this));
     };

     /**
      @param {std.ScriptingGui} scriptingGui
      @param {String} userResp_actionName - The name of the new action
      that the user wants.
      */
     function addActionInputCB(scriptingGui,userResp_actionName)
     {
         //new action won't have any text in it.
         scriptingGui.controller.addAction(userResp_actionName,'');
         scriptingGui.redraw();
     }

     /**
      @param {String?} actId -- Should be parsedInt to get an index
      into actionMap
      */
     std.ScriptingGui.prototype.hRemoveAction =
         function(actId)
     {
         this.controller.removeAction(parseInt(actId));
         this.redraw();
     };

     std.ScriptingGui.prototype.hAddFile =
         function(visId)
     {
         var newInput = std.core.SimpleInput(
             std.core.SimpleInput.ENTER_TEXT,
             'Enter new file\'s name',
             std.core.bind(addFileInputCB,undefined,this,visId));
     };

     function addFileInputCB(scriptingGui,visId,userResp_filename)
     {
         scriptingGui.controller.addExistingFileIfCan(
             visId,userResp_filename);
         scriptingGui.redraw();
     }

     //reread file first, then send it to visible.
     std.ScriptingGui.prototype.hUpdateAndSendFile =
         function(visId,filename)
     {
         this.controller.rereadFile(visId,filename);
         this.controller.updateFile(visId,filename);
     };

     std.ScriptingGui.prototype.hUpdateAndSendAllFiles =
         function(visId)
     {
         this.controller.rereadAllFiles(visId);
         this.controller.updateAll(visId);
     };

     std.ScriptingGui.prototype.hRemoveFile =
         function(visId,filename)
     {
         this.controller.removeFile(visId,filename);
         this.redraw();
     };

     /**
      @param {std.ScriptingGui}
      */
     function guiInitFunc(scriptingGui)
     {
         scriptingGui.hasInited = true;

         //when a user clicks on any of the nearby visibles to script
         //them, want that object to move into scripted objects.
         scriptingGui.guiMod.bind(
             'addVisible',
             std.core.bind(scriptingGui.hAddVisible,scriptingGui));

         //when a user clicks to remove any of the scripted visibles
         //from scripted map, then destroy it.
         scriptingGui.guiMod.bind(
             'removeVisible',
             std.core.bind(scriptingGui.hRemoveVisible,scriptingGui));

         //when a user updates a particular action, and clicks to save
         //the new action text.
         scriptingGui.guiMod.bind(
             'saveAction',
             std.core.bind(scriptingGui.hSaveAction,scriptingGui));

         //saves and executes action to visible.
         scriptingGui.guiMod.bind(
             'saveAndExecuteAction',
             std.core.bind(scriptingGui.hSaveAndExecuteAction,scriptingGui));

         scriptingGui.guiMod.bind(
             'newAction',
             std.core.bind(scriptingGui.hNewAction,scriptingGui));

         scriptingGui.guiMod.bind(
             'removeAction',
             std.core.bind(scriptingGui.hRemoveAction,scriptingGui));

         scriptingGui.guiMod.bind(
             'addFile',
             std.core.bind(scriptingGui.hAddFile,scriptingGui));

         scriptingGui.guiMod.bind(
             'updateAndSendFile',
             std.core.bind(scriptingGui.hUpdateAndSendFile,scriptingGui));

         scriptingGui.guiMod.bind(
             'updateAndSendAllFiles',
             std.core.bind(scriptingGui.hUpdateAndSendAllFiles,scriptingGui));

         scriptingGui.guiMod.bind(
             'removeFile',
             std.core.bind(scriptingGui.hRemoveFile,scriptingGui));

         scriptingGui.redraw();
     }

     /**
      @returns {object: <string (visibleId): string (visibleId)>}
      scriptingGui -- Takes the list of nearby objects and turns it
      into an object that (for now) maps visibleIds to visibleIds.

      @see ishmaelRedraw
      */
     function toHtmlNearbyMap(scriptingGui)
     {
         var returner = { };
         for (var s in scriptingGui.nearbyVisMap)
             returner[s] = s;
         return returner;
     }

     /**
      @returns {object: <string (visibleId): string (visibleId)>}
      scriptingGui -- Takes the list of nearby objects and turns it
      into an object that (for now) maps visibleIds to visibleIds.

      @see ishmaelRedraw
      */
     function toHtmlScriptedMap(scriptingGui)
     {
         var returner = { };
         for (var s in scriptingGui.scriptedVisMap)
             returner[s] = s;
         return returner;
     }

     function toHtmlActionMap(scriptingGui)
     {
         return scriptingGui.actionMap;
     }

     function toHtmlFileMap(scriptingGui)
     {
         return scriptingGui.controller.htmlFileMap();
     }

     function guiName()
     {
         return 'ishmaelEditor';
     }

     function getGuiText()
     {

         var returner = "sirikata.ui('" + guiName() + "',";
         returner += 'function(){ ';

         returner += @

         function ishmaelWindowId()
         {
             return 'ishmael__windowID_';
         }

         //the div that surrounds all the nearby objects.
         function nearbyListId()
         {
             return 'ishmael__nearbyListID__';
         }

         //the div that surrounds all the scripted objects.
         function scriptedListId()
         {
             return 'ishmael__scriptedListID__';
         }

         function actionListId()
         {
             return 'ishmael__actionListID__';
         }

         function actionTareaId()
         {
             return 'ishmael__actionEditor__';
         }

         function saveActionButtonId()
         {
             return 'ishmael__saveActionButton__';
         }

         function execActionButtonId()
         {
             return 'ishmael__execActionButton__';
         }

         function newActionButtonId()
         {
             return 'ishmael__newActionButton__';
         }

         function removeActionButtonId()
         {
             return 'ishmael__removeActionButton__';
         }

         function fileSelectId()
         {
             return 'ishmael__fileSelectId__';
         }

         function addFileButtonId()
         {
             return 'ishmael__addFileButtonId__';
         }

         function updateAndSendFileButtonId()
         {
             return 'ishmael__updateAndSendFileButtonId__';
         }

         function updateAndSendAllFilesButtonId()
         {
             return 'ishmael__updateAndSendAllFilesButtonId__';
         }

         function removeFileButtonId()
         {
             return 'ishmael__removeFileButtonId__';
         }

         /**
          \param {String} nearbyObj (id of visible that we are
          communicating with).
          gives the div for each nearby object.
          */
         function generateNearbyDivId(nearbyObj)
         {
             var visIdDivable = divizeVisibleId(nearbyObj);
             return 'ishmael__nearbyDivID___' + visIdDivable;
         }

         /**
          \param {String} scriptedObj (id of visible that we are
          communicating with).
          gives the div for each scripted object.
          */
         function generateScriptedDivId(scriptedObj)
         {
             var visIdDivable = divizeVisibleId(scriptedObj);
             return 'ishmael__scriptedDivID___' + visIdDivable;
         }

         function divizeVisibleId(visId)
         {
             return visId.replace(':','');
         }

         $('
'   +

           //which presences are available
           'Scripted presences
' +
           '<select id="'     + scriptedListId() + '" size=5>' +
           '</select>
'   +

           'Nearby presences
'      +
           '<select id="'     + nearbyListId() + '" size=5>'   +
           '</select>
'   +

           '
'            +

           //action gui
           '<select id="'     + actionListId() + '" size=5>'   +
           '</select>'        +

           '<textarea id="'   + actionTareaId()         + '">' +
           '</textarea>'      +

           '<button id="'     + saveActionButtonId()    + '">' +
           'save action'      +
           '</button>'        +

           '<button id="'     + execActionButtonId()    + '">' +
           'exec&save action' +
           '</button>'        +

           '<button id="'     + newActionButtonId()     + '">' +
           'new action'       +
           '</button>'        +

           '<button id="'     + removeActionButtonId()  + '">' +
           'remove action'    +
           '</button>'        +

           '
'            +

           //file gui
           'Files
'  +
           '<select id="'     + fileSelectId() + '" size=5>'   +
           '</select>'        +

           '<button id="'+ addFileButtonId() + '">' +
           'add file' +
           '</button>'+

           '<button id="'+ updateAndSendFileButtonId() + '">' +
           'update and send file' +
           '</button>'+

           '<button id="'+ updateAndSendAllFilesButtonId() + '">' +
           'update and send all files' +
           '</button>'+

           '<button id="' + removeFileButtonId() + '">' +
           'remove file' +
           '</button>'   +

           '
' //end div at top.
          ).attr({id:ishmaelWindowId(),title:'ishmael'}).appendTo('body');

         //The id of the visible that the scripter has selected to
         //program.
         var currentlySelectedVisible = undefined;

         //int id of the currently selected action.
         var currentlySelectedAction = undefined;
         //map from int to std.ScriptingGui.Action objects.  It gets
         //updated whenever we received an ishmaelRedraw call.  Note
         //that the redraw call will not write over the text of
         //currentlySelectedAction.  This ensures that scripter
         //edits will not be lost while they are being written if some
         //other action triggers a call to ishmaelRedraw (for
         //instance, a new nearbyObject gets added).
         var allActions = undefined;

         var currentlySelectedFile = undefined;
         var allFiles = undefined;

         $('#' + scriptedListId()).change(
             function()
             {
                 //loads the visible id
                 var val = $('#' + scriptedListId()).val();

                 //updates currentlySelectedVisible and the display of
                 //the files that should be associated with it.
                 changeCurrentlySelectedVisible(val);

                 //if we change which visible we're scripting from the
                 //scripting selection menu, we want that change to be
                 //reflected in the nearby selection list.
                 updateNearbySelection(val.toString());
             });

         //set a listener for action list.  whenever select an option,
         //should communicate that to emerson gui, so that can keep
         //track of selected action.
         $('#' + actionListId()).change(
             function()
             {
                 var val =
                     $('#' + actionListId()).val();
                 changeActionText(parseInt(val));
                 sirikata.log('error', 'Selected action: '  + val.toString());
             });

         $('#' + nearbyListId()).change(
             function()
             {
                 var val = $('#'+nearbyListId()).val();
                 //updates currentlySelectedVisible and the display of
                 //the files that should be associated with it.
                 changeCurrentlySelectedVisible(val);
                 sirikata.event('addVisible',val);
             });

         /**
          \param {String} newVisible -- id of the new visible to set
          currentlySelectedVisible to.

          This function changes currentlySelectedVisible as well as
          updating the file fields that should be associated with that
          visible.
          */
         function changeCurrentlySelectedVisible(newVisible)
         {
             currentlySelectedVisible = newVisible;
             //ensures that file list gets updated as well.
             redrawFileSelect(allFiles);
         }

         //when hit save, sends the action text through to controller
         //to save it.
         $('#' + saveActionButtonId()).click(
             function()
             {
                 //no action is selected
                 if ((typeof(currentlySelectedAction) == 'undefined') ||
                     (currentlySelectedAction === null))
                     return;

                 var toSaveText = $('#' + actionTareaId()).val();

                 //saving action does not force a redraw.  must
                 //preserve new text in allActions on our end. (takes
                 //care of failure case where save an action, then
                 //click on another action, then return to current
                 //action).
                 allActions[currentlySelectedAction].text = toSaveText;

                 sirikata.event(
                     'saveAction',currentlySelectedAction,toSaveText);
             });

         //saves and executes current action
         $('#' + execActionButtonId()).click(
             function()
             {
                 if ((typeof(currentlySelectedAction)  == 'undefined') ||
                     (typeof(currentlySelectedVisible) == 'undefined'))
                 {
                     sirikata.log(
                         'error','Cannot execute action.  ' +
                             'No vis or action selected.');
                     return;
                 }

                 //see comments in click handler for saveActionButton.
                 var toSaveText = $('#' + actionTareaId()).val();
                 allActions[currentlySelectedAction].text = toSaveText;
                 sirikata.event(
                     'saveAndExecuteAction',currentlySelectedAction,
                     toSaveText,currentlySelectedVisible);
             });

         //user asks for new action: we pass event down to
         //scriptingGui, which creates a simpleInput asking for new
         //action name.
         $('#' + newActionButtonId()).click(
             function()
             {
                 sirikata.event('newAction');
             });

         $('#' + removeActionButtonId()).click(
             function()
             {
                 if (typeof(currentlySelectedAction) == 'undefined')
                     return;

                 sirikata.event('removeAction',currentlySelectedAction);
                 currentlySelectedAction = undefined;
             });

         $('#' + fileSelectId()).change(
             function()
             {
                 currentlySelectedFile = $('#' + fileSelectId()).val();
             });

         $('#' + addFileButtonId()).click(
             function()
             {
                 if (typeof(currentlySelectedVisible)=='undefined')
                     return;

                 sirikata.event('addFile',currentlySelectedVisible);
             });

         $('#' + updateAndSendFileButtonId()).click(
             function()
             {
                 if ((typeof(currentlySelectedVisible) == 'undefined') ||
                     (typeof(currentlySelectedFile) == 'undefined'))
                 {
                     return;
                 }
                 sirikata.event(
                     'updateAndSendFile',currentlySelectedVisible,
                     currentlySelectedFile);
             });

         $('#' + updateAndSendAllFilesButtonId()).click(
             function()
             {
                 if (typeof(currentlySelectedVisible) == 'undefined')
                     return;

                 sirikata.event(
                     'updateAndSendAllFiles',currentlySelectedVisible);
             });

         $('#' + removeFileButtonId()).click(
             function()
             {
                 if ((typeof(currentlySelectedVisible) == 'undefined') ||
                     (typeof(currentlySelectedFile) == 'undefined'))
                 {
                     return;
                 }

                 sirikata.event(
                     'removeFile',currentlySelectedVisible,currentlySelectedFile);

             });

         var inputWindow = new sirikata.ui.window(
             '#' + ishmaelWindowId(),
                 {
	             autoOpen: true,
	             height: 'auto',
	             width: 600,
                     height: 600,
                     position: 'right'
                 }
             );
         inputWindow.show();

         /**
          changes selection in updateNearby to the one associated with
          visibleId (if it's available).  If it's not, then we just
          unselect.

          Right now, we take a performance hit, because the selection
          change that we do here will trigger the .change handler
          associated with nearbyList.  Should still maintain semantics
          though.
          */
         function updateNearbySelection(visibleId)
         {
             var nearbyOption = $('#' + generateNearbyDivId(visibleId));
             if (nearbyOption.size())
             {
                 //means that the element did exist.  now want it to
                 //appear selected in nearbyList.
                 var nearbyVal = nearbyOption.val();
                 $('#' + nearbyListId()).val(nearbyVal);
             }
             else
             {
                 var errMsg =
                     'In updatenearbyselection attempting '+
                     'to set selector to none.';

                 sirikatal.log('error',errMsg);
                 $('#' + nearbyListId()).val(null);
             }
         }

         /**
          \param {int or undefined} idActSelected.  If an int, then
          looks through record of allActions, and sets action text
          area to that.  If undefined, then clears action text area.
          */
         function changeActionText(idActSelected)
         {
             currentlySelectedAction = idActSelected;
             var textToSetTo = '';

             if (typeof(idActSelected) !='undefined')
             {
                 if (! idActSelected in allActions)
                 {
                     sirikata.log('error','action ids out of ' +
                                  'sync with actions in scripting gui.');
                     return;
                 }
                 textToSetTo = allActions[idActSelected].text;
             }

             //actually update textarea with correct text
             $('#' + actionTareaId()).val(textToSetTo);
         }

         /**
          \param {object: <int:std.ScriptingGui.Action>} actionMap

          \param {object: <string (visibleId):
              object: <string(filename):string(filename)>>} fileMap --
          keyed by visible id, elements are maps of files that each
          remote visible has on it.
          */
         ishmaelRedraw = function(
             nearbyObjs,scriptedObjs,actionMap,fileMap)
         {
             redrawNearby(nearbyObjs);
             redrawScriptedObjs(scriptedObjs);
             redrawActionList(actionMap);
             redrawFileSelect(fileMap);
         };

         /**
          \param {object: <string (visibleId): string (visibleId)>}
          nearbyObjs -- all objects that are in vicinity.
          */
         function redrawNearby(nearbyObjs)
         {
             var newHtml = '';
             for (var s in nearbyObjs)
             {
                 if (s===currentlySelectedVisible)
                     newHtml += '<option selected ';
                 else
                     newHtml += '<option ';

                 newHtml += 'value="' + s + '" ';
                 newHtml += 'id="' + generateNearbyDivId(s) + '">';
                 newHtml += s;
                 newHtml += '</option>';
             }
             $('#' + nearbyListId()).html(newHtml);
         }

         /**
          \param {object: <string (visibleId): string(visibleId)>}
          scriptedObjs -- all objects that we have a scripting
          relationship with.
          */
         function redrawScriptedObjs(scriptedObjs)
         {
             var newHtml = '';
             for (var s in scriptedObjs)
             {
                 if (s === currentlySelectedVisible)
                     newHtml += '<option selected ';
                 else
                     newHtml += '<option ';

                 newHtml += 'value="' +s +  '">';
                 newHtml += s;
                 newHtml += '</option>';
             }
             $('#' + scriptedListId()).html(newHtml);
         }

         function redrawActionList(actionMap)
         {
             var prevCurAct = null;
             if (typeof(currentlySelectedAction) != 'undefined')
             {
                 prevCurAct = allActions[currentlySelectedAction];
                 //update with text that had entered in tarea.
                 prevCurAct.text = $('#' + actionTareaId()).val();
             }

             allActions = actionMap;
             //preserves edits that scripter was potentially making
             //when other action triggered redraw (eg. a new nearby
             //object).
             if (prevCurAct !== null)
                 allActions[prevCurAct.id] = prevCurAct;

             var newHtml = '';
             for (var s in actionMap)
             {
                 if (parseInt(s) === parseInt(currentlySelectedAction))
                     newHtml += '<option selected ';
                 else
                     newHtml += '<option ';

                 newHtml += 'value="' + s + '">';
                 newHtml += actionMap[s].name ;
                 newHtml += '</option>';
             }

             $('#' + actionListId()).html(newHtml);
         }

         /**
          \param {object: <string (visibleId):
              object: <string(filename):string(filename)>>} fileMap --
          keyed by visible id, elements are maps of files that each
          remote visible has on it.

          (fileMap can also be undefined if called from
          changeCurrentlySelectedVisible.)

          Sets currentlySelectedFile to undefined if have no
          currentlySelectedFile that exists in list of files under
          currentlySelectedVisible.  This ensures that
          changeCurrentlySelectedVisible can call this function
          whenever want to update files after having updated
          currentlySelectedVisible.
          */
         function redrawFileSelect(fileMap)
         {
             if (typeof(allFiles) == 'undefined')
                 allFiles = fileMap;

             //no work to do.
             if(typeof(allFiles) == 'undefined')
                 return;

             //no visible selected, and hence no list of files to
             //show.
             if (typeof(currentlySelectedVisible) == 'undefined')
             {
                 currentlySelectedFile = undefined;
                 return;
             }

             var visFiles = fileMap[currentlySelectedVisible];
             var newHtml = '';
             var haveSelectedFile = false;
             for (var s in visFiles)
             {
                 if (s === currentlySelectedFile)
                 {
                     newHtml += '<option selected ';
                     haveSelectedFile = true;
                 }
                 else
                     newHtml += '<option ';

                 newHtml += 'value="' + s + '">';
                 newHtml += visFiles[s];
                 newHtml += '</option>';
             }

             if (!haveSelectedFile)
                 currentlySelectedFile = undefined;

             $('#' + fileSelectId()).html(newHtml);
         }

         @;

         returner += '});';
         return returner;
     }
 })();

//do all further imports for file and gui control.
system.require('controller.em');
system.require('action.em');
system.require('console.em');
system.require('fileManagerElement.em');

system.require('std/core/simpleInput.em');

(function()
 {

     /**
      @param {std.ScriptingGui.Controller}

      @param {object: <String(visibleId):visible object>} nearbyVisMap
      -- all the visible objects that satisfy scripter's proximity
      query.

      @param {object: <String(visibleId):
      std.FileManager.FileManagerElement> scriptedVisMap -- A record
      of all visibles that we have scripted at some point.

      @param {object: <int:std.ScriptingGui.Action> actionMap -- Which
      actions are selectable by scripter.

      @param {std.ScriptingGui.Console} console -- has several
      scripting events.
      */
     std.ScriptingGui =
         function(controller,nearbyVisMap,scriptedVisMap,actionMap,console)
     {
         if (typeof(simulator) == 'undefined')
         {
             throw new Error('Cannot initialize scripting gui without ' +
                             'simulator graphics.');
         }

         this.controller       = controller;
         this.nearbyVisMap     = nearbyVisMap;
         this.scriptedVisMap   = scriptedVisMap;
         this.actionMap        = actionMap;
         this.console          = console;

         this.guiMod = simulator._simulator.addGUITextModule(
             guiName(),
             getGuiText(),
             std.core.bind(guiInitFunc,undefined,this));
         this.hasInited = false;
     };

     system.require('scriptingGuiUtil.em');

     std.ScriptingGui.prototype.redraw = function()
     {
         if (!this.hasInited)
             return;

         //trigger redraw call
         this.guiMod.call(
             'ishmaelRedraw',toHtmlNearbyMap(this),toHtmlScriptedMap(this),
             toHtmlActionMap(this),toHtmlFileMap(this));
     };

     /**
      @param {String} visId -- Id of visible.
      */
     //called by html to add the visible with id
     std.ScriptingGui.prototype.hAddVisible = function(visId)
     {
         //already can script the visible.
         if (visId in this.scriptedVisMap)
         {
             this.console.guiEvent();
             this.redraw();
             return;
         }

         if (!(visId in this.nearbyVisMap))
         {
             //visible is no longer available.
             this.console.guiEvent();
             this.redraw();
             return;
         }

         //redraw called from inside of addVisible.
         this.controller.addVisible(this.nearbyVisMap[visId]);
     };

     std.ScriptingGui.prototype.hRemoveVisible = function(visId)
     {
         //FIXME: should finish this call
         throw new Error('FIXME: must finish hRemoveVisible call ' +
                         'in scriptingGui');
     };

     /**
      @param {String?} actId -- Should be parsedInt to get an index
      into actionMap
      @param {String} newText -- What action with actId should set as
      its text.
      */
     std.ScriptingGui.prototype.hSaveAction = function(actId,newText)
     {
         this.controller.editAction(parseInt(actId),newText);
     };

     /**
      @param {String?} actId -- Should be parsedInt to get an index
      into actionMap
      @param {String} newText -- What action with actId should set as
      its text.
      @param {String} visId   -- Id of visible to execute action on.
      */
     std.ScriptingGui.prototype.hSaveAndExecuteAction =
         function(actId,newText, visId)
     {
         this.hSaveAction(actId,newText);
         this.controller.execAction(actId,visId);
     };

     /**
      Prompt user for the name of the new action using
      std.core.SimpleInput.
      */
     std.ScriptingGui.prototype.hNewAction =
         function()
     {
         var newInput = std.core.SimpleInput(
             std.core.SimpleInput.ENTER_TEXT,
             'Enter new action\'s name',
             std.core.bind(addActionInputCB,undefined,this));
     };

     /**
      @param {std.ScriptingGui} scriptingGui
      @param {String} userResp_actionName - The name of the new action
      that the user wants.
      */
     function addActionInputCB(scriptingGui,userResp_actionName)
     {
         //new action won't have any text in it.
         scriptingGui.controller.addAction(userResp_actionName,'');
         scriptingGui.redraw();
     }

     /**
      @param {String?} actId -- Should be parsedInt to get an index
      into actionMap
      */
     std.ScriptingGui.prototype.hRemoveAction =
         function(actId)
     {
         this.controller.removeAction(parseInt(actId));
         this.redraw();
     };

     std.ScriptingGui.prototype.hAddFile =
         function(visId)
     {
         var newInput = std.core.SimpleInput(
             std.core.SimpleInput.ENTER_TEXT,
             'Enter new file\'s name',
             std.core.bind(addFileInputCB,undefined,this,visId));
     };

     function addFileInputCB(scriptingGui,visId,userResp_filename)
     {
         scriptingGui.controller.addExistingFileIfCan(
             visId,userResp_filename);
         scriptingGui.redraw();
     }

     //reread file first, then send it to visible.
     std.ScriptingGui.prototype.hUpdateAndSendFile =
         function(filename,visId)
     {
         this.controller.rereadFile(visId,filename);
         this.controller.updateFile(visId,filename);
     };

     std.ScriptingGui.prototype.hUpdateAndSendAllFiles =
         function(visId)
     {
         this.controller.rereadAllFiles(visId);
         this.controller.updateAll(visId);
     };

     /**
      @param {std.ScriptingGui}
      */
     function guiInitFunc(scriptingGui)
     {
         scriptingGui.hasInited = true;

         //when a user clicks on any of the nearby visibles to script
         //them, want that object to move into scripted objects.
         scriptingGui.guiMod.bind(
             'addVisible',
             std.core.bind(scriptingGui.hAddVisible,scriptingGui));

         //when a user clicks to remove any of the scripted visibles
         //from scripted map, then destroy it.
         scriptingGui.guiMod.bind(
             'removeVisible',
             std.core.bind(scriptingGui.hRemoveVisible,scriptingGui));

         //when a user updates a particular action, and clicks to save
         //the new action text.
         scriptingGui.guiMod.bind(
             'saveAction',
             std.core.bind(scriptingGui.hSaveAction,scriptingGui));

         //saves and executes action to visible.
         scriptingGui.guiMod.bind(
             'saveAndExecuteAction',
             std.core.bind(scriptingGui.hSaveAndExecuteAction,scriptingGui));

         scriptingGui.guiMod.bind(
             'newAction',
             std.core.bind(scriptingGui.hNewAction,scriptingGui));

         scriptingGui.guiMod.bind(
             'removeAction',
             std.core.bind(scriptingGui.hRemoveAction,scriptingGui));

         scriptingGui.guiMod.bind(
             'addFile',
             std.core.bind(scriptingGui.hAddFile,scriptingGui));

         scriptingGui.guiMod.bind(
             'updateAndSendFile',
             std.core.bind(scriptingGui.hUpdateAndSendFile,scriptingGui));

         scriptingGui.guiMod.bind(
             'updateAndSendAllFiles',
             std.core.bind(scriptingGui.hUpdateAndSendAllFiles,scriptingGui));

         scriptingGui.redraw();
     }

     /**
      @returns {object: <string (visibleId): string (visibleId)>}
      scriptingGui -- Takes the list of nearby objects and turns it
      into an object that (for now) maps visibleIds to visibleIds.

      @see ishmaelRedraw
      */
     function toHtmlNearbyMap(scriptingGui)
     {
         var returner = { };
         for (var s in scriptingGui.nearbyVisMap)
             returner[s] = s;
         return returner;
     }

     /**
      @returns {object: <string (visibleId): string (visibleId)>}
      scriptingGui -- Takes the list of nearby objects and turns it
      into an object that (for now) maps visibleIds to visibleIds.

      @see ishmaelRedraw
      */
     function toHtmlScriptedMap(scriptingGui)
     {
         var returner = { };
         for (var s in scriptingGui.scriptedVisMap)
             returner[s] = s;
         return returner;
     }

     function toHtmlActionMap(scriptingGui)
     {
         return scriptingGui.actionMap;
     }

     function toHtmlFileMap(scriptingGui)
     {
         return scriptingGui.controller.htmlFileMap();
     }

     function guiName()
     {
         return 'ishmaelEditor';
     }

     function getGuiText()
     {

         var returner = "sirikata.ui('" + guiName() + "',";
         returner += 'function(){ ';

         returner += @

         function ishmaelWindowId()
         {
             return 'ishmael__windowID_';
         }

         //the div that surrounds all the nearby objects.
         function nearbyListId()
         {
             return 'ishmael__nearbyListID__';
         }

         //the div that surrounds all the scripted objects.
         function scriptedListId()
         {
             return 'ishmael__scriptedListID__';
         }

         function actionListId()
         {
             return 'ishmael__actionListID__';
         }

         function actionTareaId()
         {
             return 'ishmael__actionEditor__';
         }

         function saveActionButtonId()
         {
             return 'ishmael__saveActionButton__';
         }

         function execActionButtonId()
         {
             return 'ishmael__execActionButton__';
         }

         function newActionButtonId()
         {
             return 'ishmael__newActionButton__';
         }

         function removeActionButtonId()
         {
             return 'ishmael__removeActionButton__';
         }

         function fileSelectId()
         {
             return 'ishmael__fileSelectId__';
         }

         function addFileButtonId()
         {
             return 'ishmael__addFileButtonId__';
         }

         function updateAndSendFileButtonId()
         {
             return 'ishmael__updateAndSendFileButtonId__';
         }

         function updateAndSendAllFilesButtonId()
         {
             return 'ishmael__updateAndSendAllFilesButtonId__';
         }

         /**
          \param {String} nearbyObj (id of visible that we are
          communicating with).
          gives the div for each nearby object.
          */
         function generateNearbyDivId(nearbyObj)
         {
             var visIdDivable = divizeVisibleId(nearbyObj);
             return 'ishmael__nearbyDivID___' + visIdDivable;
         }

         /**
          \param {String} scriptedObj (id of visible that we are
          communicating with).
          gives the div for each scripted object.
          */
         function generateScriptedDivId(scriptedObj)
         {
             var visIdDivable = divizeVisibleId(scriptedObj);
             return 'ishmael__scriptedDivID___' + visIdDivable;
         }

         function divizeVisibleId(visId)
         {
             return visId.replace(':','');
         }

         $('
'   +

           //which presences are available
           'Scripted presences
' +
           '<select id="'     + scriptedListId() + '" size=5>' +
           '</select>
'   +

           'Nearby presences
'      +
           '<select id="'     + nearbyListId() + '" size=5>'   +
           '</select>
'   +

           '
'            +

           //action gui
           '<select id="'     + actionListId() + '" size=5>'   +
           '</select>'        +

           '<textarea id="'   + actionTareaId()         + '">' +
           '</textarea>'      +

           '<button id="'     + saveActionButtonId()    + '">' +
           'save action'      +
           '</button>'        +

           '<button id="'     + execActionButtonId()    + '">' +
           'exec&save action' +
           '</button>'        +

           '<button id="'     + newActionButtonId()     + '">' +
           'new action'       +
           '</button>'        +

           '<button id="'     + removeActionButtonId()  + '">' +
           'remove action'    +
           '</button>'        +

           '
'            +

           //file gui
           'Files
'  +
           '<select id="'     + fileSelectId() + '" size=5>'   +
           '</select>'        +

           '<button id="'+ addFileButtonId() + '">' +
           'add file' +
           '</button>'+

           '<button id="'+ updateAndSendFileButtonId() + '">' +
           'update and send file' +
           '</button>'+

           '<button id="'+ updateAndSendAllFilesButtonId() + '">' +
           'update and send all files' +
           '</button>'+

           '
' //end div at top.
          ).attr({id:ishmaelWindowId(),title:'ishmael'}).appendTo('body');

         //The id of the visible that the scripter has selected to
         //program.
         var currentlySelectedVisible = undefined;

         //int id of the currently selected action.
         var currentlySelectedAction = undefined;
         //map from int to std.ScriptingGui.Action objects.  It gets
         //updated whenever we received an ishmaelRedraw call.  Note
         //that the redraw call will not write over the text of
         //currentlySelectedAction.  This ensures that scripter
         //edits will not be lost while they are being written if some
         //other action triggers a call to ishmaelRedraw (for
         //instance, a new nearbyObject gets added).
         var allActions = undefined;

         var currentlySelectedFile = undefined;
         var allFiles = undefined;

         $('#' + scriptedListId()).change(
             function()
             {
                 //loads the visible id
                 var val = $('#' + scriptedListId()).val();

                 //updates currentlySelectedVisible and the display of
                 //the files that should be associated with it.
                 changeCurrentlySelectedVisible(val);

                 //if we change which visible we're scripting from the
                 //scripting selection menu, we want that change to be
                 //reflected in the nearby selection list.
                 updateNearbySelection(val.toString());
             });

         //set a listener for action list.  whenever select an option,
         //should communicate that to emerson gui, so that can keep
         //track of selected action.
         $('#' + actionListId()).change(
             function()
             {
                 var val =
                     $('#' + actionListId()).val();
                 changeActionText(parseInt(val));
                 sirikata.log('error', 'Selected action: '  + val.toString());
             });

         $('#' + nearbyListId()).change(
             function()
             {
                 var val = $('#'+nearbyListId()).val();
                 //updates currentlySelectedVisible and the display of
                 //the files that should be associated with it.
                 changeCurrentlySelectedVisible(val);
                 sirikata.event('addVisible',val);
             });

         /**
          \param {String} newVisible -- id of the new visible to set
          currentlySelectedVisible to.

          This function changes currentlySelectedVisible as well as
          updating the file fields that should be associated with that
          visible.
          */
         function changeCurrentlySelectedVisible(newVisible)
         {
             currentlySelectedVisible = newVisible;
             //ensures that file list gets updated as well.
             redrawFileSelect(allFiles);
         }

         //when hit save, sends the action text through to controller
         //to save it.
         $('#' + saveActionButtonId()).click(
             function()
             {
                 //no action is selected
                 if ((typeof(currentlySelectedAction) == 'undefined') ||
                     (currentlySelectedAction === null))
                     return;

                 var toSaveText = $('#' + actionTareaId()).val();

                 //saving action does not force a redraw.  must
                 //preserve new text in allActions on our end. (takes
                 //care of failure case where save an action, then
                 //click on another action, then return to current
                 //action).
                 allActions[currentlySelectedAction].text = toSaveText;

                 sirikata.event(
                     'saveAction',currentlySelectedAction,toSaveText);
             });

         //saves and executes current action
         $('#' + execActionButtonId()).click(
             function()
             {
                 if ((typeof(currentlySelectedAction)  == 'undefined') ||
                     (typeof(currentlySelectedVisible) == 'undefined'))
                 {
                     sirikata.log(
                         'error','Cannot execute action.  ' +
                             'No vis or action selected.');
                     return;
                 }

                 //see comments in click handler for saveActionButton.
                 var toSaveText = $('#' + actionTareaId()).val();
                 allActions[currentlySelectedAction].text = toSaveText;
                 sirikata.event(
                     'saveAndExecuteAction',currentlySelectedAction,
                     toSaveText,currentlySelectedVisible);
             });

         //user asks for new action: we pass event down to
         //scriptingGui, which creates a simpleInput asking for new
         //action name.
         $('#' + newActionButtonId()).click(
             function()
             {
                 sirikata.event('newAction');
             });

         $('#' + removeActionButtonId()).click(
             function()
             {
                 if (typeof(currentlySelectedAction) == 'undefined')
                     return;

                 sirikata.event('removeAction',currentlySelectedAction);
                 currentlySelectedAction = undefined;
             });

         $('#' + fileSelectId()).change(
             function()
             {
                 currentlySelectedFile = $('#' + fileSelectId()).val();
             });

         $('#' + addFileButtonId()).click(
             function()
             {
                 if (typeof(currentlySelectedVisible)=='undefined')
                     return;

                 sirikata.event('addFile',currentlySelectedVisible);
             });

         $('#' + updateAndSendFileButtonId()).click(
             function()
             {
                 if ((typeof(currentlySelectedVisible) == 'undefined') ||
                     (typeof(currentlySelectedFile) == 'undefined'))
                 {
                     return;
                 }
                 sirikata.event(
                     'updateAndSendFile',currentlySelectedFile,currentlySelectedVisible);
             });

         $('#' + updateAndSendAllFilesButtonId()).click(
             function()
             {
                 if (typeof(currentlySelectedVisible) == 'undefined')
                     return;

                 sirikata.event(
                     'updateAndSendAllFiles',currentlySelectedVisible);
             });

         var inputWindow = new sirikata.ui.window(
             '#' + ishmaelWindowId(),
                 {
	             autoOpen: true,
	             height: 'auto',
	             width: 600,
                     height: 600,
                     position: 'right'
                 }
             );
         inputWindow.show();

         /**
          changes selection in updateNearby to the one associated with
          visibleId (if it's available).  If it's not, then we just
          unselect.

          Right now, we take a performance hit, because the selection
          change that we do here will trigger the .change handler
          associated with nearbyList.  Should still maintain semantics
          though.
          */
         function updateNearbySelection(visibleId)
         {
             var nearbyOption = $('#' + generateNearbyDivId(visibleId));
             if (nearbyOption.size())
             {
                 //means that the element did exist.  now want it to
                 //appear selected in nearbyList.
                 var nearbyVal = nearbyOption.val();
                 $('#' + nearbyListId()).val(nearbyVal);
             }
             else
             {
                 var errMsg =
                     'In updatenearbyselection attempting '+
                     'to set selector to none.';

                 sirikatal.log('error',errMsg);
                 $('#' + nearbyListId()).val(null);
             }
         }

         /**
          \param {int or undefined} idActSelected.  If an int, then
          looks through record of allActions, and sets action text
          area to that.  If undefined, then clears action text area.
          */
         function changeActionText(idActSelected)
         {
             currentlySelectedAction = idActSelected;
             var textToSetTo = '';

             if (typeof(idActSelected) !='undefined')
             {
                 if (! idActSelected in allActions)
                 {
                     sirikata.log('error','action ids out of ' +
                                  'sync with actions in scripting gui.');
                     return;
                 }
                 textToSetTo = allActions[idActSelected].text;
             }

             //actually update textarea with correct text
             $('#' + actionTareaId()).val(textToSetTo);
         }

         /**
          \param {object: <int:std.ScriptingGui.Action>} actionMap

          \param {object: <string (visibleId):
              object: <string(filename):string(filename)>>} fileMap --
          keyed by visible id, elements are maps of files that each
          remote visible has on it.
          */
         ishmaelRedraw = function(
             nearbyObjs,scriptedObjs,actionMap,fileMap)
         {
             redrawNearby(nearbyObjs);
             redrawScriptedObjs(scriptedObjs);
             redrawActionList(actionMap);
             redrawFileSelect(fileMap);
         };

         /**
          \param {object: <string (visibleId): string (visibleId)>}
          nearbyObjs -- all objects that are in vicinity.
          */
         function redrawNearby(nearbyObjs)
         {
             var newHtml = '';
             for (var s in nearbyObjs)
             {
                 if (s===currentlySelectedVisible)
                     newHtml += '<option selected ';
                 else
                     newHtml += '<option ';

                 newHtml += 'value="' + s + '" ';
                 newHtml += 'id="' + generateNearbyDivId(s) + '">';
                 newHtml += s;
                 newHtml += '</option>';
             }
             $('#' + nearbyListId()).html(newHtml);
         }

         /**
          \param {object: <string (visibleId): string(visibleId)>}
          scriptedObjs -- all objects that we have a scripting
          relationship with.
          */
         function redrawScriptedObjs(scriptedObjs)
         {
             var newHtml = '';
             for (var s in scriptedObjs)
             {
                 if (s === currentlySelectedVisible)
                     newHtml += '<option selected ';
                 else
                     newHtml += '<option ';

                 newHtml += 'value="' +s +  '">';
                 newHtml += s;
                 newHtml += '</option>';
             }
             $('#' + scriptedListId()).html(newHtml);
         }

         function redrawActionList(actionMap)
         {
             var prevCurAct = null;
             if (typeof(currentlySelectedAction) != 'undefined')
             {
                 prevCurAct = allActions[currentlySelectedAction];
                 //update with text that had entered in tarea.
                 prevCurAct.text = $('#' + actionTareaId()).val();
             }

             allActions = actionMap;
             //preserves edits that scripter was potentially making
             //when other action triggered redraw (eg. a new nearby
             //object).
             if (prevCurAct !== null)
                 allActions[prevCurAct.id] = prevCurAct;

             var newHtml = '';
             for (var s in actionMap)
             {
                 if (parseInt(s) === parseInt(currentlySelectedAction))
                     newHtml += '<option selected ';
                 else
                     newHtml += '<option ';

                 newHtml += 'value="' + s + '">';
                 newHtml += actionMap[s].name ;
                 newHtml += '</option>';
             }

             $('#' + actionListId()).html(newHtml);
         }

         /**
          \param {object: <string (visibleId):
              object: <string(filename):string(filename)>>} fileMap --
          keyed by visible id, elements are maps of files that each
          remote visible has on it.

          (fileMap can also be undefined if called from
          changeCurrentlySelectedVisible.)

          Sets currentlySelectedFile to undefined if have no
          currentlySelectedFile that exists in list of files under
          currentlySelectedVisible.  This ensures that
          changeCurrentlySelectedVisible can call this function
          whenever want to update files after having updated
          currentlySelectedVisible.
          */
         function redrawFileSelect(fileMap)
         {
             if (typeof(allFiles) == 'undefined')
                 allFiles = fileMap;

             //no work to do.
             if(typeof(allFiles) == 'undefined')
                 return;

             //no visible selected, and hence no list of files to
             //show.
             if (typeof(currentlySelectedVisible) == 'undefined')
             {
                 currentlySelectedFile = undefined;
                 return;
             }

             var visFiles = fileMap[currentlySelectedVisible];
             var newHtml = '';
             var haveSelectedFile = false;
             for (var s in visFiles)
             {
                 if (s === currentlySelectedFile)
                 {
                     newHtml += '<option selected ';
                     haveSelectedFile = true;
                 }
                 else
                     newHtml += '<option ';

                 newHtml += 'value="' + s + '">';
                 newHtml += visFiles[s];
                 newHtml += '</option>';
             }

             if (!haveSelectedFile)
                 currentlySelectedFile = undefined;

             $('#' + fileSelectId()).html(newHtml);
         }

         @;

         returner += '});';
         return returner;
     }
 })();

//do all further imports for file and gui control.
system.require('controller.em');
system.require('action.em');
system.require('console.em');
system.require('fileManagerElement.em');