|
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 |
@@ -67,6 +69,10 @@ def add_arguments(self, parser, cli_name): |
67 | 69 | parser.add_argument( |
68 | 70 | '-r', '--rate', metavar='N', type=float, |
69 | 71 | help='Repeat the call at a specific rate in Hz') |
| 72 | + |
| 73 | + # Prevent argcomplete from escaping special characters in the YAML string |
| 74 | + argcomplete.autocomplete = UnescapedCompletionFinder(parser) |
| 75 | + |
70 | 76 | add_qos_arguments(parser, 'service client', 'services_default') |
71 | 77 |
|
72 | 78 | def main(self, *, args): |
@@ -117,7 +123,16 @@ def requester(service_type: str, service_name: str, values, period: Optional[flo |
117 | 123 | except (AttributeError, ModuleNotFoundError): |
118 | 124 | raise RuntimeError('The passed service type is invalid') |
119 | 125 |
|
120 | | - values_dictionary = yaml.safe_load(values) |
| 126 | + try: |
| 127 | + # Handle cases where the user pastes the autocompleted bash safe string |
| 128 | + if '^J' in values: |
| 129 | + values = values.replace("'", '') |
| 130 | + values = values.replace('^J', '\n') |
| 131 | + |
| 132 | + values_dictionary = yaml.safe_load(values) |
| 133 | + |
| 134 | + except (yaml.parser.ParserError, yaml.scanner.ScannerError): |
| 135 | + return 'The passed value needs to be in YAML string or a dictionary' |
121 | 136 |
|
122 | 137 | with rclpy.init(): |
123 | 138 | node = rclpy.create_node(NODE_NAME_PREFIX + '_requester_%s_%s' % (package_name, srv_name)) |
|
0 commit comments