Rubyの新しいデバッガを試してみる

# はじめに

Ruby 3.1.0 の目玉機能の１つに新しいデバッガがあります。
私は、このデバッガの２つの特徴に注目しました。
１つは、リモートデバッガ。もう１つは、DAPに対応していることです。

# 新しいデバッガのインストール

デバッガ自体は、Ruby 3.0 でも使うことができます。

```shell
$ ruby -v
ruby 3.0.2p107 (2021-07-07 revision 0db68f0233) [x86_64-linux]
```

デバッガをインストールしてみましょう。

```
$ gem install debug
```

デバッガのバージョンは、1.3.4です。

```
$ rdbg -v
rdbg 1.3.4
```

# リモートデバッガ

リモートデバッガは、別のサーバーで動いているデバッガに接続してデバッグできる機能です。
以下のような簡単なプログラムで少し試してみましょう。

```ruby:target.rb
a = 1
b = 2
c = 3
d = 4
p [a, b, c, d]
```

## リモートデバッガを試してみる

コンソールからデバッガを起動し、別のコンソールからTCP/IPで接続してデバッグの操作をしてみます。

まずは、コンソールからデバッガを起動します。デバッガのコマンドは、 `rdbg` です。デバッガを実行するときに、リモートでデバッグできるように `-O` オプションを指定します。また、 `--port` でポート番号を指定します。

```shell:コンソール1
$ rdbg -O --port 12345 target.rb
DEBUGGER: Debugger can attach via TCP/IP (127.0.0.1:12345)
DEBUGGER: wait for debugger connection...
```

メッセージから、デバッガの接続を待ち受けていることがわかります。

では、別のコンソールからTCP/IPで接続してみましょう。
接続する場合も `rdbg` コマンドを使います。 `-A` オプションを指定し、`--port` オプションで接続先ポートを指定します。

```shell:コンソール2
$ rdbg -A --port 12345
[1, 5] in target.rb
=>   1| a = 1
     2| b = 2
     3| c = 3
     4| d = 4
     5| p [a, b, c, d]
=>#0    <main> at target.rb:1
(rdbg:remote)
```

`(rdbg:remote)` とプロンプトが表示され、リモートでデバッガが動作されたのがわかります。

また、１つ目のコンソールには、リモートから接続があったメッセージが出力されます。

```shell:コンソール1
DEBUGGER: Connected.
```

いくつか、2つ目のコンソールからdebugの操作をしてみます。

`n` で１行だけ実行します。

```shell:コンソール2
(rdbg:remote) n    # next command
[1, 5] in target.rb
     1| a = 1
=>   2| b = 2
     3| c = 3
     4| d = 4
     5| p [a, b, c, d]
=>#0    <main> at target.rb:2
(rdbg:remote)
```

変数 `a` の値を参照してみます。

```shell:コンソール2
(rdbg:remote) a
1
(rdbg:remote)
```

`info` コマンドを実行してみましょう

```shell:コンソール2
(rdbg:remote) info    # command
%self = main
a = 1
b = nil
c = nil
d = nil
(rdbg:remote)
```

`c` コマンドで最後まで実行します。

```shell:コンソール2
(rdbg:remote) c    # continue command
$
```

最初のコンソールに接続が切れたことが出力され、デバッガが終了します。
```shell:コンソール1
[1, 2, 3, 4]
DEBUGGER: Disconnected.
```

## 何が嬉しいのか

例えば、別のサーバーでデバッガを起動して、自分の端末からリモートで接続してデバッグするとか、docker のコンテナでデバッガを起動しておいて、別コンソールから接続するとか、そういったことに利用できそうです。

# DAP と NeoVim

DAP は、Debug Adapter Protocol の略です。DAPに対応したエディタ(DAPに対応したクライアントなら何でも良い)であれば、エディタ経由でRubyのデバッガを操作できます。

Visual Studio Code には、[VSCode rdbg Ruby Debugger](https://marketplace.visualstudio.com/items?itemName=KoichiSasada.vscode-rdbg) があります。 このプラグインをインストールすれば、 Visual Studio Code で、Rubyのデバッグできるようになるようです。

が、私は NeoVim を使っています。NeoVim から使えないかと思って調べました。 [nvim-dap](https://github.com/mfussenegger/nvim-dap) を見つけました。

このプラグイン単体だと使いづらいので、自分でRubyのデバッガ用の設定を追加するプラグイン [nvim-dap-ruby](https://github.com/suketa/nvim-dap-ruby) を作って公開しました。

[nvim-dap](https://github.com/mfussenegger/nvim-dap) と [nvim-dap-ruby](https://github.com/suketa/nvim-dap-ruby) の2つのプラグインを NeoVim に追加すれば、NeoVim が Ruby のデバッガと連携して動作します。

2つのプラグインを追加したあとで、 `target.rb` を NeoVim で開きます。

```shell
nvim target.rb
```

では、Rubyのデバッガを起動してみましょう。

```
:lua require('dap').continue()
```

と入力します。
![nvim01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209941/77985185-4cdf-af70-c184-d0da5d50c914.png)


続けて Enter キーを押します。選択肢が表示されるので、ここでは、　`1` と入力してEnterキーを押します。

![nvim02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209941/a4e5f3bb-3772-f64d-57de-c8cf823f9ca3.png)

1行目がハイライトされます。
続けて、

```
:lua require('dap').repl.open()
```

と入力して、 Enter キーを押します。

![nvim03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209941/16d17279-6600-e734-6cf5-5f9aba0c9ad4.png)


エディタのカーソルを下のバッファに移動してから `i` キーを押して入力モードにすると `dap >` というプロンプトが表示されます。
このプロンプトでデバッガを操作することができるようになります。

以下の画像は、 `.n` と入力して次の行まで処理を進めてから、 `a` と入力して、変数 a の値を参照しているところです。
![nvim04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209941/74112ead-d32f-e3fa-df78-178274cfba59.png)

# まとめ

Rubyの新しいデバッガの機能のうち、リモートデバッガとDAPを試してみました。
あなたも新しいRubyのデバッガを試してみてはいかがでしょうか？