Skip to content

Commit c7bfb8a

Browse files
mabelzhangahcordechapulina
authored
Bash completion for flags (#392)
Signed-off-by: Mabel Zhang <mabel@openrobotics.org> Signed-off-by: Louise Poubel <louise@openrobotics.org> Co-authored-by: Alejandro Hernández Cordero <ahcorde@gmail.com> Co-authored-by: Louise Poubel <louise@openrobotics.org>
1 parent e3cf225 commit c7bfb8a

File tree

5 files changed

+131
-2
lines changed

5 files changed

+131
-2
lines changed

CMakeLists.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,11 @@ ign_find_package(ignition-msgs5 REQUIRED)
6868
set(IGN_MSGS_VER ${ignition-msgs5_VERSION_MAJOR})
6969

7070
#--------------------------------------
71-
# Find if ign command is available
71+
# Find if command is available. This is used to enable tests.
72+
# Note that CLI files are installed regardless of whether the dependency is
73+
# available during build time
7274
find_program(HAVE_IGN_TOOLS ign)
75+
set (IGN_TOOLS_VER 1)
7376

7477
#--------------------------------------
7578
# Find QT

src/CMakeLists.txt

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,35 @@ ign_build_tests(TYPE UNIT
4646
LIB_DEPS
4747
${IGNITION-MATH_LIBRARIES}
4848
TINYXML2::TINYXML2
49+
TEST_LIST
50+
gtest_targets
4951
)
5052

53+
foreach(test ${gtest_targets})
54+
target_compile_definitions(${test} PRIVATE
55+
"PROJECT_SOURCE_DIR=\"${PROJECT_SOURCE_DIR}\"")
56+
endforeach()
57+
58+
if(TARGET UNIT_ign_TEST)
59+
# Running `ign gazebo` on macOS has problems when run with /usr/bin/ruby
60+
# due to System Integrity Protection (SIP). Try to find ruby from
61+
# homebrew as a workaround.
62+
if (APPLE)
63+
find_program(BREW_RUBY ruby HINTS /usr/local/opt/ruby/bin)
64+
endif()
65+
66+
target_compile_definitions(UNIT_ign_TEST PRIVATE
67+
"BREW_RUBY=\"${BREW_RUBY} \"")
68+
69+
target_compile_definitions(UNIT_ign_TEST PRIVATE
70+
"IGN_PATH=\"${HAVE_IGN_TOOLS}\"")
71+
72+
set(_env_vars)
73+
list(APPEND _env_vars "IGN_CONFIG_PATH=${CMAKE_BINARY_DIR}/test/conf")
74+
75+
set_tests_properties(UNIT_ign_TEST PROPERTIES
76+
ENVIRONMENT "${_env_vars}")
77+
endif()
78+
5179
add_subdirectory(cmd)
5280
add_subdirectory(plugins)

src/cmd/CMakeLists.txt

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Generate a the ruby script.
1+
# Generate the ruby script.
22
# Note that the major version of the library is included in the name.
33
if (APPLE)
44
set(IGN_LIBRARY_NAME lib${PROJECT_NAME_LOWER}.dylib)
@@ -11,3 +11,13 @@ configure_file(
1111

1212
# Install the ruby command line library in an unversioned location.
1313
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/cmdgui${PROJECT_VERSION_MAJOR}.rb DESTINATION lib/ruby/ignition)
14+
15+
# Tack version onto and install the bash completion script
16+
configure_file(
17+
"gui.bash_completion.sh"
18+
"${CMAKE_CURRENT_BINARY_DIR}/gui${PROJECT_VERSION_MAJOR}.bash_completion.sh" @ONLY)
19+
install(
20+
FILES
21+
${CMAKE_CURRENT_BINARY_DIR}/gui${PROJECT_VERSION_MAJOR}.bash_completion.sh
22+
DESTINATION
23+
${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATAROOTDIR}/gz/gz${IGN_TOOLS_VER}.completion.d)

src/cmd/gui.bash_completion.sh

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#!/usr/bin/env bash
2+
#
3+
# Copyright (C) 2022 Open Source Robotics Foundation
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
#
17+
18+
# bash tab-completion
19+
20+
# This is a per-library function definition, used in conjunction with the
21+
# top-level entry point in ign-tools.
22+
23+
GZ_GUI_COMPLETION_LIST="
24+
-l --list
25+
-s --standalone
26+
-c --config
27+
-v --verbose
28+
-h --help
29+
--force-version
30+
--versions
31+
"
32+
33+
function _gz_gui
34+
{
35+
if [[ ${COMP_WORDS[COMP_CWORD]} == -* ]]; then
36+
# Specify options (-*) word list for this subcommand
37+
COMPREPLY=($(compgen -W "$GZ_GUI_COMPLETION_LIST" \
38+
-- "${COMP_WORDS[COMP_CWORD]}" ))
39+
return
40+
else
41+
# Just use bash default auto-complete, because we never have two
42+
# subcommands in the same line. If that is ever needed, change here to
43+
# detect subsequent subcommands
44+
COMPREPLY=($(compgen -o default -- "${COMP_WORDS[COMP_CWORD]}"))
45+
return
46+
fi
47+
}
48+
49+
function _gz_gui_flags
50+
{
51+
for word in $GZ_GUI_COMPLETION_LIST; do
52+
echo "$word"
53+
done
54+
}

src/ign_TEST.cc

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <stdio.h>
2020
#include <stdlib.h>
2121

22+
#include <fstream>
2223
#include <string>
2324

2425
#include <ignition/common/Filesystem.hh>
@@ -32,6 +33,9 @@
3233
# define pclose _pclose
3334
#endif
3435

36+
static const std::string kIgnCommand(
37+
std::string(BREW_RUBY) + std::string(IGN_PATH));
38+
3539
/////////////////////////////////////////////////
3640
std::string custom_exec_str(std::string _cmd)
3741
{
@@ -97,3 +101,33 @@ TEST_F(CmdLine, DETAIL_IGN_UTILS_ADD_DISABLED_PREFIX(list))
97101
EXPECT_TRUE(common::exists(common::joinPaths(this->kFakeHome, ".ignition",
98102
"gui")));
99103
}
104+
105+
//////////////////////////////////////////////////
106+
/// \brief Check --help message and bash completion script for consistent flags
107+
TEST(ignTest, GuiHelpVsCompletionFlags)
108+
{
109+
// Flags in help message
110+
std::string helpOutput = custom_exec_str(kIgnCommand + " gui --help");
111+
112+
// Call the output function in the bash completion script
113+
std::string scriptPath = common::joinPaths(std::string(PROJECT_SOURCE_DIR),
114+
"src", "cmd", "gui.bash_completion.sh");
115+
116+
// Equivalent to:
117+
// sh -c "bash -c \". /path/to/gui.bash_completion.sh; _gz_gui_flags\""
118+
std::string cmd = "bash -c \". " + scriptPath + "; _gz_gui_flags\"";
119+
std::string scriptOutput = custom_exec_str(cmd);
120+
121+
// Tokenize script output
122+
std::istringstream iss(scriptOutput);
123+
std::vector<std::string> flags((std::istream_iterator<std::string>(iss)),
124+
std::istream_iterator<std::string>());
125+
126+
EXPECT_GT(flags.size(), 0u);
127+
128+
// Match each flag in script output with help message
129+
for (std::string flag : flags)
130+
{
131+
EXPECT_NE(std::string::npos, helpOutput.find(flag)) << helpOutput;
132+
}
133+
}

0 commit comments

Comments
 (0)