Rustの勉強のためにpretty-envコマンドを作成してみる
Rustの学習ネタを探して
最近Rustを触り始めたので勉強のネタを探している。
今回、作業の合間に息抜き感覚で作れそうなネタを探していたが、ふと env
コマンドをいい感じに出力するコマンドはどうだろうかと考えた。
これを pretty-env
コマンドと名付けてみることにする。
表示内容を整形するだけのツールであれば、おそらくコードの規模感的にも気軽に作れるのではないだろうか。
いきなりRustで書くのでもよいが、まずはプログラムの全体像を把握する意味でも一度慣れている言語で試し書きをしてみることにした。
というわけで、まずはJavaScript(Node.js)で作成してみる。
envコマンドの出力結果は execSync
を利用して取得する。
env
コマンドの結果は一行に対して一つの環境変数となっているので、最初は Readline
を利用して一行ずつ処理をしていこうとしたが、これがエラーになってしまうので、ひとまず下記のように一行を一つのenvとして扱い、配列化して処理していくことにする。
(readline
を利用した際のエラーの詳細はメモするの忘れてしまっていたので割愛...ハマりそうだったので、このやり方に変えた)
envコマンドの出力結果を1行ごとに配列に格納していくサンプル(Node.js)
const { execSync } = require("child_process");
// envコマンドの出力結果が入る
const stdout = execSync("env");
// 一行に対して一つの環境変数、となっているのでこのようにして配列化してしまう
const envList = stdout.toString().trim().split("\n");
ちなみにとにかく動けりゃヨシ的な形でコードは書いています。
あとひとまずは手元のmacでのみ動かすことを目的としています。そのため各OSごとの対応などは今のところ実装しない予定です。
swc-nodeを利用してTypeScriptでNode.jsを書いていく
せっかくなのでswc-node
を利用して TypeScript
で書いていくことにした。
下記でインストールして、
yarn add -D @swc-node/register
npm scriptsに下記を追加する。
※一部抜粋
"scripts": {
"dev": "node -r @swc-node/register src/pretty-env.ts"
},
DenoのlintとfmtをNode.jsのプロジェクトで利用する
ついでに lint
と fmt
コマンドも用意する。
自分しか触らないつもりのコードだし、わざわざeslint
やprettier
を入れるのも面倒に思えたので、Denoのlint
と fmt
コマンドをプロジェクト内で利用することにする。
deno.jsonc
をプロジェクトルートに配置し、下記を記述する。
{
"lint": {
"files": {
"include": [
"src"
],
"exclude": ["node_modules"]
},
"rules": {
"tags": ["recommend"],
"exclude": []
}
},
"fmt": {
"files": {
"include": [
"src",
"deno.jsonc"
],
"exclude": ["node_modules"]
}
}
}
lint.rules.exclude
には何も入力していないがコードを書き出して入れたくなったら入れていく。
package.json
に下記を記述する。
"scripts": {
"dev": "node -r @swc-node/register src/pretty-env.ts",
"lint": "deno lint -c deno.jsonc",
"fmt": "deno fmt -c deno.jsonc"
},
これでひとまず準備はOKそうなので、コードを書いていく。
書いてみたコードがこちら。GitHubにあげている。
頑張りすぎて途中で挫折するのは一番避けたいと思い、実装する上で結構楽をしている。
例えば、
-
env
の出力結果を表示するだけのツールという限定的な機能しか持ち合わせておらず、日本語などは扱わないので、文字数の扱いは雑(foo.length
みたいな感じで文字数を扱ってしまっている) - 長いパスについてはテーブルの見た目を優先するために、途中で省略している
- テーブルの枠組みは
-
と|
だけで作った。(本当は┌
や┬
を使うような方法もあるが、実装料も増えるし、この2つだけでも最低限の見た目になるので、そうした)
というわけで、こちらの実装をベースにRustで実装していってみる。
envコマンドの出力結果を1行ごとに配列に格納していくサンプル(Rust)
Rustで早速envコマンドの出力結果を1行ごとに配列に格納していくサンプルを作ってみた。
use std::process::Command;
fn main() {
let output = Command::new("sh")
.arg("-c")
.arg("env")
.output()
.expect("failed to execute process");
let env_str = String::from_utf8(output.stdout).unwrap();
let env_list: Vec<&str> = env_str.split('\n').collect();
println!("{:?}", env_list);
}
これで
["env1行分の文字列", "env1行分の文字列", "env1行分の文字列",...]
という形で出力される。
これをベースにして実装していってみる。
書いてみたコードがこちら。GitHubにあげている。
出力結果をよくよく見ていると、項目によって1文字分ずれているような気がする...
(もしかしたらJS側の実装もそうなっている??)
テストコードなどは一切書いていないし、そこらへんも書いていきながら、今後実装は洗練させていきたいところ。
せっかく pretty-env
と名付けたので、もう少し pretty
感も加えていきたい。
ひとまず学習の記録としてはこれで一区切り。