|
15 | 15 | import time |
16 | 16 | from typing import Optional |
17 | 17 |
|
| 18 | +import argcomplete |
| 19 | + |
18 | 20 | import rclpy |
19 | 21 | from rclpy.qos import QoSPresetProfiles |
20 | 22 | from rclpy.qos import QoSProfile |
21 | 23 |
|
22 | | -from ros2cli.helpers import collect_stdin |
| 24 | +from ros2cli.helpers import collect_stdin, UnescapedCompletionFinder |
23 | 25 | from ros2cli.helpers import interactive_select |
24 | 26 | from ros2cli.node import NODE_NAME_PREFIX |
25 | 27 | from ros2cli.node.strategy import NodeStrategy |
@@ -71,6 +73,10 @@ def add_arguments(self, parser, cli_name): |
71 | 73 | '--timeout', metavar='N', type=float, |
72 | 74 | help='Maximum time to wait for service response in seconds. ' |
73 | 75 | 'If not specified, waits indefinitely.') |
| 76 | + |
| 77 | + # Prevent argcomplete from escaping special characters in the YAML string |
| 78 | + argcomplete.autocomplete = UnescapedCompletionFinder(parser) |
| 79 | + |
74 | 80 | add_qos_arguments(parser, 'service client', 'services_default') |
75 | 81 |
|
76 | 82 | def main(self, *, args): |
@@ -122,7 +128,16 @@ def requester(service_type: str, service_name: str, values, period: Optional[flo |
122 | 128 | except (AttributeError, ModuleNotFoundError): |
123 | 129 | raise RuntimeError('The passed service type is invalid') |
124 | 130 |
|
125 | | - values_dictionary = yaml.safe_load(values) |
| 131 | + try: |
| 132 | + # Handle cases where the user pastes the autocompleted bash safe string |
| 133 | + if '^J' in values: |
| 134 | + values = values.replace("'", '') |
| 135 | + values = values.replace('^J', '\n') |
| 136 | + |
| 137 | + values_dictionary = yaml.safe_load(values) |
| 138 | + |
| 139 | + except (yaml.parser.ParserError, yaml.scanner.ScannerError): |
| 140 | + return 'The passed value needs to be in YAML string or a dictionary' |
126 | 141 |
|
127 | 142 | with rclpy.init(): |
128 | 143 | node = rclpy.create_node(NODE_NAME_PREFIX + '_requester_%s_%s' % (package_name, srv_name)) |
|
0 commit comments