ros2 topic pub でタブ補完がうまくいかない場合の解決策

# 結論
メッセージ内容を補完する前にダブルクォーテーション（"）を入力して補完しよう!

# 検証環境
- OS: Ubuntu 20.04 LTS
- ROS 2バージョン: Humble

# 背景
作成したノードの動作確認をする際に、"ros2 topic pub"を使うと楽なのですが、タブ補完を使ってメッセージ内容を補完すると表示がおかしい。
```bash
ros2 topic pub /cmd_vel geometry_msgs/msg/Twist linear:\
\ \ x:\ 0.0\
\ \ y:\ 0.0\
\ \ z:\ 0.0\
angular:\
\ \ x:\ 0.0\
\ \ y:\ 0.0\
\ \ z:\ 0.0\ 
```
さらに、実行してみると以下のようなよくわからないエラーが発生する。
```bash
Traceback (most recent call last):
  File "/root/ros2_humble/install/ros2cli/bin/ros2", line 11, in <module>
    load_entry_point('ros2cli', 'console_scripts', 'ros2')()
  File "/root/ros2_humble/build/ros2cli/ros2cli/cli.py", line 89, in main
    rc = extension.main(parser=parser, args=args)
  File "/root/ros2_humble/build/ros2topic/ros2topic/command/topic.py", line 41, in main
    return extension.main(args=args)
  File "/root/ros2_humble/build/ros2topic/ros2topic/verb/pub.py", line 222, in main
    return main(args)
  File "/root/ros2_humble/build/ros2topic/ros2topic/verb/pub.py", line 240, in main
    return publisher(
  File "/root/ros2_humble/build/ros2topic/ros2topic/verb/pub.py", line 271, in publisher
    values_dictionary = yaml.safe_load(values)
  File "/usr/lib/python3/dist-packages/yaml/__init__.py", line 162, in safe_load
    return load(stream, SafeLoader)
  File "/usr/lib/python3/dist-packages/yaml/__init__.py", line 114, in load
    return loader.get_single_data()
  File "/usr/lib/python3/dist-packages/yaml/constructor.py", line 49, in get_single_data
    node = self.get_single_node()
  File "/usr/lib/python3/dist-packages/yaml/composer.py", line 36, in get_single_node
    document = self.compose_document()
  File "/usr/lib/python3/dist-packages/yaml/composer.py", line 55, in compose_document
    node = self.compose_node(None, None)
  File "/usr/lib/python3/dist-packages/yaml/composer.py", line 84, in compose_node
    node = self.compose_mapping_node(anchor)
  File "/usr/lib/python3/dist-packages/yaml/composer.py", line 127, in compose_mapping_node
    while not self.check_event(MappingEndEvent):
  File "/usr/lib/python3/dist-packages/yaml/parser.py", line 98, in check_event
    self.current_event = self.state()
  File "/usr/lib/python3/dist-packages/yaml/parser.py", line 428, in parse_block_mapping_key
    if self.check_token(KeyToken):
  File "/usr/lib/python3/dist-packages/yaml/scanner.py", line 116, in check_token
    self.fetch_more_tokens()
  File "/usr/lib/python3/dist-packages/yaml/scanner.py", line 223, in fetch_more_tokens
    return self.fetch_value()
  File "/usr/lib/python3/dist-packages/yaml/scanner.py", line 577, in fetch_value
    raise ScannerError(None, None,
yaml.scanner.ScannerError: mapping values are not allowed here
  in "<unicode string>", line 1, column 11:
    linear:  x: 0.0  y: 0.0  z: 0.0angular:  x ... 
```
上記のような経験をされた方は私だけではないと思います。結果として、メッセージの中身を手打ちする必要に迫られて"ros2 topic pub"を使わなくなる人もいるんじゃないでしょうか。この記事を作成するまで私もそうでした。
CrystalやDashingの頃ならまだしもHumbleまでバージョンが進んでいたら、何かしら解決策があるはずだということで調査してみました。

# 解決策
"ros2 topic pub"は、ros2cliパッケージに格納されています。そこで、ros2cliのGitHubページのissueを確認すると、以下のように未だに問題として取り上げられていることがわかります（2023/07/20時点）。
https://github.com/ros2/ros2cli/issues/793
しかし、このissueの元を辿ると、とりあえずこれで動くという解決策がありました。
https://github.com/ros2/ros2cli/issues/563#issuecomment-782135494
この投稿曰く、メッセージ内容を補完する前にダブルクォーテーションを入力すると良いらしいです。
実際に入力した結果は以下のとおりです。
```bash
ros2 topic pub /float geometry_msgs/msg/Twist "l
```
上記の時点でタブキーを押下して補完
```bash
ros2 topic pub /float geometry_msgs/msg/Twist "linear:
  x: 0.0
  y: 0.0
  z: 0.0
angular:
  x: 0.0
  y: 0.0
  z: 0.0" 
```
綺麗な形のメッセージ内容を見ることが出来ました。

実行結果も以下のように問題ありませんでした。
```bash
publisher: beginning loop
publishing #1: geometry_msgs.msg.Twist(linear=geometry_msgs.msg.Vector3(x=0.0, y=0.0, z=0.0), angular=geometry_msgs.msg.Vector3(x=0.0, y=0.0, z=0.0))

publishing #2: geometry_msgs.msg.Twist(linear=geometry_msgs.msg.Vector3(x=0.0, y=0.0, z=0.0), angular=geometry_msgs.msg.Vector3(x=0.0, y=0.0, z=0.0))

publishing #3: geometry_msgs.msg.Twist(linear=geometry_msgs.msg.Vector3(x=0.0, y=0.0, z=0.0), angular=geometry_msgs.msg.Vector3(x=0.0, y=0.0, z=0.0))
```

# 最後に
上記の解決策は初心者にとって直感的ではなく分かりにくいので、ソースコードを眺めて問題になりそうな箇所に手を加えたりして試行してみましたが、根本的な解決策は見つかりませんでした。我こそはというエンジニアの方は、ぜひ根本的な解決を模索していただけると助かります。