Flat Leon Works

アプリやゲームを作ってます。

【Nim】VSCodeで始めるNimプログラミング

この記事は「Nim Advent Calendar 2021」の9日目の記事として登録させてもらっています。

はじめに

この記事ではVSCodeでNimプログラミングを行う方法を紹介したいと思います。 単純にNimの実行方法を紹介するだけでなく、実際にNimのプログラミングをするにあたって必要そうなものも一通り紹介します。

注意点:

  • 環境構築やワークフローの紹介がメインなのでNimの文法などについては触れません
  • インストール手順や各種サンプルコードはあまり動作確認できていません(手元の環境がすでに構築済みなので…)
  • もっと良い方法や改善点があるかもしれません

Nimとは

NimはPython風の文法に静的型付けと強力なマクロ、便利なメソッドコール記法といった特徴を持つプログラミング言語です。 C/C++コードを生成することで動作するので、非常に高速かつ、さまざまな環境用のプログラムを作成することができます。 私はNimでモバイルやPCで動くツールやゲームを作る予定です。

Nimのインストール

Nimをインストールするには、複数のバージョンのNimをインストールした上で使うバージョンを選択できるChoosenim経由でインストールするのがおすすめです。

choosenimのインストール(Macの場合)

choosenimはターミナルで以下のコマンドを実行することでインストールできます(参考:Nim公式サイト内のドキュメント)

curl https://nim-lang.org/choosenim/init.sh -sSf | sh

choosenimをインストールすると一緒に最新のnimもインストールされます。 choosenimをインストールしたときのターミナルの表示にあるように、インストール後はPATHを通しておく必要があります。 PATHの通し方も一緒に表示されるのでそれに従ってPATHを通しましょう。

xzコマンドのインストール(必要な場合)

上記方法によるchoosenimのインストールを手元の古めのMacで試してみたところ、xzコマンドがないというエラーになりました。 homebrew経由でインストールできるようだったので以下のようにしてインストールしました。(参考:Mac で xz を使用する方法 - Qiita)

brew install xz

homebrewのインストール(必要な場合)

homebrew自体が未インストールの場合は、以下のコマンドでhomebrewをインストールできます。(HomeBrew公式サイト)

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

choosenimのインストール(Windowsの場合)

公式サイトインストーラーがあります。choosenim-0.8.2_windows_amd64.zipのようなzipファイルをダウンロードして展開し、中のrunme.batを実行するとインストールが行われます。PATH通しも任意でやってくれます(やるかどうか聞かれる)。PATHを通した場合はWindowsを再起動しないと反映されないことに注意。

インストールされたかどうか確認する

ターミナル(Mac)あるいはコマンドプロンプト(Windows)でnim --versionと打ってNimのバージョン情報が表示されたらインストールに成功しています。

VSCode(Visual Studio Code)とは

プログラミングに適した使いやすいマルチプラットフォームテキストエディタです。すごい勢いで機能の追加や改善が行われており、バージョンアップのリリースノートが毎度すごいことになっています。 ユーザーによる拡張機能も豊富でNimの拡張機能もあります。

ちなみにVisual Studioとは別物です。

VSCode(Visual Studio Code)のインストール

公式サイトからダウンロードして適当にインストールしてください。

Nimの拡張機能のインストール

VSCodeにNimの拡張機能を入れることで構文カラーが付いたりいろいろいいことがあります。 Nimの拡張機能はいくつかあるのですが、↓のやつが一番アクティブなようなのでおすすめです。

Nim - Visual Studio Marketplace

とりあえず実行してみる

実行のための設定を行う

実行するには、VSCodeの設定ファイルtask.jsonにNim実行用のタスクを登録します。 task.jsonは個別プロジェクト用(.vscodeフォルダ内に配置)と全体用(ユーザー設定フォルダ内に配置)の2種類があります。

ここではとりあえず、全体用のtask.jsonに登録します。

Cmd + Shift + pVSCodeのコマンドパレットを表示し、Tasks: Open User Tasksと入力しエンターで実行すると全体用のtask.jsonが表示されます。 初回の場合はtask.jsonが生成されます。そして以下のように記述します。

{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "2.0.0",
    "tasks": [
        {
            "label": "Nim Run",
            "type": "shell",
            "command": "nim r ${file}",
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "problemMatcher": []
        },
    ]
}

Nimコードを書く

VSCodeで新規ファイルを作成し、以下のようなコードを記述します。

echo "hello world"

そして、helloworld.nimとか適当な名前で保存します。Nimのソースコードの拡張子は.nimです。

実行する

Cmd + Shift + Bを入力するとタスク選択ポップアップが表示されるので、先程task.jsonに追加した「Nim Run」のタスクを選択すると、現在開いているファイルがNimソースコードとして実行されます。

実行すると、VSCodeのターミナルにビルドログなどと一緒に「hello world」と出力されると思います。

Nimbleパッケージを作る

NimbleはNimのパッケージ管理ツールです。Nimに付属されています。 Nimbleを使うことで、ユーザーが作ったNim製のツールやライブラリ(Nimbleパッケージ)を簡単にインストールしたり、自分が作ったNimbleパッケージを簡単に公開することができます。

Nimbleパッケージを公開するつもりがなかったとしても、最初からNimbleパッケージとして作っておくと何かと便利です。 例えば以下のようなメリットがあります。

  • 作ったプログラムが再利用しやすくなる(ローカルでインストールすることで、どこからでもimportできるようになる)
  • 単体テストが簡単に実行できる

Nimbleパッケージのフォルダを作成する

Nimbleパッケージのフォルダ構成

Nimbleパッケージは以下のようなフォルダ構成が推奨されています。

nim-lang/nimble: Package manager for the Nim programming language.から引用

.                   # The root directory of the project
├── LICENSE
├── README.md
├── foobar.nimble   # The project .nimble file
└── src
    └── foobar.nim  # Imported via `import foobar`
└── tests           # Contains the tests
    ├── config.nims
    ├── tfoo1.nim   # First test
    └── tfoo2.nim   # Second test

この中の.nimbleファイルがNimbleパッケージのプロジェクト設定ファイルになります。

nimble init でNimbleパッケージフォルダを作成する

自分でこのフォルダ構成を用意してもいいのですが、nimble initコマンドを使うと、適切な設定がされた.nimbleファイルと一緒にフォルダを作成してくれます。

nimble init

実行するといくつか質問が出されて、それらを元に.nimbleファイルとフォルダが生成されます。

ただ、毎回新しいNimbleパッケージを作るごとに質問に答えるのは面倒なので、私は2個目以降のパッケージを作るときは作成済みのパッケージをコピペしています。

開発で使うNimbleコマンド

Nimbleコマンドを使うことで以下のような作業を行うことができます。

  • ビルド
  • 実行
  • 単体テストの実行
  • パッケージのインストール
  • ドキュメントの生成

ひとまずは、ターミナル上で使用する方法を紹介しますが、後でVSCode上から実行する方法も紹介します。

ビルド/実行

パッケージのビルドを行うにはパッケージフォルダをカレントディレクトリにして以下のコマンドを使います。

nimble build

このときパラメータを与えるとnimコマンドへそのまま渡されます。(後述するrunコマンドやtestコマンドも同様です)

nimble build -d:debug --verbose

実行するにはrunを使います。

nimble run

※ビルドや実行は、ライブラリとしてNimbleパッケージを作っている場合はあまり使う機会はないです。

単体テストの作成

単体テストファイルの配置

単体テストを作成するにはNimbleのパッケージフォルダ内にtestsフォルダを用意し、そのなかにtから始まるnimファイルを置きます。

(ファイルの配置例)

tests/
    testMyFunc.nim

testsフォルダからsrcフォルダが見えるようにする

テストファイルはtestsフォルダ内に配置しますが、テスト対象のファイルはsrcフォルダ内に存在するので、 テストコード内からimportするにはimport ../src/my_moduleみたいに記述する必要があり不便です。 それを回避するにはnim.cfgファイルをtestsフォルダ内に置き、中に以下のように記述します。

switch("path", "$projectDir/../src")

こうすることで、srcフォルダ内のファイルをそのままimportできるようになります。

単体テストを記述する

単体テストを記述するには、標準で用意されているstd/unittestモジュールを使います。

import unittest
import mymodule

test "test_1":
  check myfunc_add( 10, 20 ) == 30 
  check myfunc_add( -10, 20 ) == 10 

testブロックを作って、その中でcheckを使って動作を確認します。(他にも機能はあるので詳しくはstd/unittestのドキュメントを見てください)

単体テストの実行

# nimbleパッケージをカレントディレクトリにした上で
nimble test

testコマンドを実行すると、nimbleのパッケージフォルダ内のtests内のtで始めるNimファイルすべてを順番に実行してくれます。

パッケージのインストール

作成したNimbleパッケージをインストールすることで、どのフォルダからでもimport文を使ってそのパッケージを利用することができるようになります。

インストールするにはinstallコマンドを使います。

# nimbleパッケージをカレントディレクトリにした上で
nimble install

すでにインストール済みの場合は、.nimbleに記述するバージョンを上げないと警告がでますが、邪魔な場合は-yオプションで警告を無視することができます。

nimble install -y

-yオプションを使用すると、上書き警告だけでなく、他の質問事項にも強制的にyesと答えてしまうので注意してください。

ドキュメントの生成

Nimにはドキュメント生成機能があります。またNimbleもそれに対応したdocコマンドがあります。 生成されるドキュメントは、公式ドキュメントと同じフォーマットのものです。

(使用例)

nimble doc --project --index:on --outdir:doc main.nim

Nimbleパッケージの作業をVSCodeで行う

Nimbleパッケージ内にVSCodeワークスペースファイル(.code-workspace)を用意する

Nimbleのパッケージフォルダを作ったら、その中にVSCodeワークスペースファイルを作成しておきましょう。 ワークスペースファイルがあればダブルクリックするだけでNimbleのパッケージフォルダをVSCodeで開くことができて便利です。

VSCodeワークスペースファイルを作るには、ワークスペースにしたいフォルダをVSCodeドラッグ&ドロップし、ファイルメニューの「Save Workspace As...」で保存します。

NimbleコマンドをVSCodeから利用できるようにする

先程紹介した、NimbleのbuildruntestinstalldocといったコマンドはVSCodeから実行できるようにしておくと便利です。 やり方は「実行のための設定を行う」でやったのと同じようにtask.jsonに登録することで実行可能になります。

(登録例)

        {
            "label": "Nimble Build",
            "type": "shell",
            "command": "nimble build",
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "problemMatcher": []
        },
        {
            "label": "Nimble Install",
            "type": "shell",
            "command": "nimble install -y",
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "problemMatcher": []
        },
        {
            "label": "Nimble Doc",
            "type": "shell",
            "command": "nimble doc --project --index:on --outdir:${workspaceFolder}/doc ${workspaceFolder}/src/${workspaceFolderBasename}.nim",
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "problemMatcher": []
        },
        {
            "label": "Nimble Test",
            "type": "shell",
            "command": "nimble test",
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "problemMatcher": []
        },
        {
            "label": "Nimble Test(Debug)",
            "type": "shell",
            "command": "nimble test -d:debug --debugger:native",
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "problemMatcher": []
        },

実行するときはCmd + Shift + pでコマンドパレットを表示し、そこでlebelで設定した名前を入力します。入力補完や実行履歴も出るので、すべての名前の入力する必要はありません。

VSCodeでNimのステップ実行(デバッガ実行)を行う

Nim自体がLLDBやGDBなどの一般的なデバッガーサポートに対応しており、またVSCode拡張機能によってLLDBやGDBとの連携が可能になっているので、それらを使って VSCodeでNimのステップ実行が可能になっています。

事前にLLDBのインストールが必要かもしれません。ターミナルでlldb -vと打ってインストールされているか確認してください。

Nimのステップ実行(デバッガ実行)については、Nim拡張機能のドキュメントを参考にしました。

CodeLLDBのVSCode拡張をインストールする

VSCodeをLLDBと連携させるための拡張機能をインストールします

ビルド時にデバッグ情報を付加するようにする

ステップ実行を行うには、ビルドオプションに--debugger:nativeをつけて、ビルド時にデバッグ情報を付加するようにします。 --debugger:nativeをつけたビルド方法をtask.jsonに追加しておきましょう。

        {
            // testのデバッグビルド用
            "label": "Nimble Test(Debug)",
            "type": "shell",
            "command": "nimble test -d:debug --debugger:native",
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "problemMatcher": []
        },

VSCodeデバッグ実行設定(launch)に追加する

VSCodeデバッグ実行を行うための設定を追加する必要があります。 以下のコードを、setting.json(コマンドパレットのOpen Settingsから開ける)に追加します。

    "launch": {
        "configurations": [
            {
                "type": "lldb",
                "request": "launch",
                "name": "Nim Test Run With Debugger",
                "preLaunchTask": "Nimble Test(Debug)",
                "program": "${workspaceFolder}/tests/test",
                "args": [],
                "cwd": "${workspaceFolder}"
            }
        ],
        "compounds": []
    }

"preLaunchTask"でデバッグビルド用のタスクを指定しているので、デバッグ実行する前に自動でデバッグビルドも走ります。

VSCodeデバッグ実行を行う

F5あるいは、コマンドパレットからStart Debuggingデバッグ実行を開始します。 VSCode上でブレークポイントを貼っておけば、そこで停止し、ステップ実行を行うことができます。 コールスタックや変数も見れますが、生成されたC言語を元にしたものなのであまり参考にはならないかもしれません。(無いよりかはマシですが)

その他設定など

nimsuggestの無効化

VSCodeのNimの拡張機能にはコード補完や定義ジャンプ機能があるのですが、この機能に使われるnimsuggestというプログラムがCPU使用率100%でハングアップすることがよくあるので、 私は無効にしています。無効にするにはVSCodeの設定(Nim拡張機能の設定)の中のEnable Nimsuggestのチェックマークを外します。当然、コード補完や定義ジャンプは使えなくなりますが、構文カラーは使えます。

まとめ

今回紹介したVSCodeを使ったNimプログラミングは、まとめると以下のような感じです。

  • とりあえず、Nimbleパッケージを作成する
  • VSCodeでNimbleパッケージを開く
  • Nimコードを書く
  • testsでテストコードを書いて動作確認
  • 他のプロジェクトで使う場合はNimbleインストールしておく
  • 必要に応じてドキュメント生成

また、今回は全く触れませんでしたが、作成したNimbleパッケージはgitで管理しておくと作業ログとして便利です。VSCodeもgitに対応しています。

この記事でNimを始める人が増えてくれると嬉しいです。

Nimリンク集

最後にNimプログラミングでよく利用するリソースへのリンクを置いておきます。

以下当サイトの記事