MicroでJavaScriptのコードフォーマッターを使えるようにする

MicroでJavaScriptで書かれたコードを保存する時に、自動でコードフォーマッターのPrettierとリンターのESLintが実行するようにしてみます。

※コードフォーマッターがコードを整形し、リンターがコードの書き方の問題点を調べます

Prettier · Opinionated Code Formatter · Prettier

Find and fix problems in your JavaScript code - ESLint - Pluggable JavaScript Linter


最初に上記のライブラリをインストールするためのnpmをインストールします。

npm | Home


最初に最新版のNode.jsを簡単にインストールできるnvm(Node Version Manager)を入れます。

当記事執筆時のnvmの最新版のバージョンは0.40.1でして、下記のコマンドでnwmをインストールします。

$ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
$ source .bashrc
$ nvm -v
0.40.1

nvmのインストールが終了しましたら、最新版のNode.jsをインストールします。

$ nvm install node
$ node -v
v23.6.0

Node.jsのインストールに合わせて、npm(Node Package Manager)も同時にインストールされますので、

$ npm -v

でnpmがインストールされているか?を確認します。

11.0.0

最後にnpmを最新版にしておきます。

$ npm update -g npm



下記コマンドを実行して、Prettierのインストールを行います。

$ npm install --global prettier
$ prettier -v
3.5.1

Microでコードを保存した時にPrettierが自動で実行するようにします。

$ ~/.config/micro/init.lua
local micro = import("micro")
local shell = import("micro/shell")

function onSave(bp)
	if bp.Buf:FileType() == "html" or bp.Buf:FileType() == "javascript" then
		bp:Save()
		local _, err = shell.RunCommand("prettier " .. bp.Buf.Path .. " --write")
		if err ~= nil then
			micro.InfoBar():Error(err)
			return
		end

		bp.Buf:ReOpen()
	end
end

動作確認の為に、Microを起動して下記のHTMLのコードを用意します。

$ micro ~/hoge.html
<!doctype html>
<html>
<head>
<meta charset="UTF-8" />
<title>hoge</title>
</head>
<body>
<p>hello world</p>
</body>
<script>
console.log(x);
</script>
</html>

Micro上で上記のコードを保存したら、

<!doctype html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>hoge</title>
  </head>
  <body>
    <p>hello world</p>
  </body>
  <script>
    console.log(x);
  </script>
</html>

のようにコードが自動で整形されます。


コードの自動整形の設定を変更したい場合は、

$ micro ~/.prettierrc.json
{
	"tabWidth": 4,
	"useTabs": true
}

のようにPrettier用の設定ファイルを用意しましょう。

※設定項目はOptions · Prettier(英語)をご確認ください。




下記コマンドを実行して、ESLintのインストールを行います。

$ npm install -g eslint
$ eslist -v
v9.20.1
$ npm install globals
$ npm install @eslint/js
$ micro ~/eslint.config.mjs
import globals from "globals"
import pluginJs from "@eslint/js"

/** @type {import('eslint').Linter.Config[]} */
export default [
	{
		files: ["**/*.js"],
		languageOptions: { sourceType: "script" },
	},
	{ languageOptions: { globals: globals.browser } },
	pluginJs.configs.recommended,
]

以上の手続きでESLintのインストールは終了です。


Microでコードを保存した時にESLintが自動で実行するようにします。

$ ~/.config/micro/init.lua
local micro = import("micro")
local shell = import("micro/shell")

function onSave(bp)
	if bp.Buf:FileType() == "html" or bp.Buf:FileType() == "javascript" then
		bp:Save()
		local _, err = shell.RunCommand("prettier " .. bp.Buf.Path .. " --write")
		if err ~= nil then
			micro.InfoBar():Error(err)
			return
		end

		local output, _ = shell.RunCommand("eslint " .. bp.Buf.Path)
		local strings = import("strings")
		output = strings.TrimSpace(output)
		if output ~= "" then
			micro.TermMessage(output)
			return
		end

		bp.Buf:ReOpen()
	end
end



動作確認の為に、Microを起動して下記のJavaScriptのコードを用意します。

$ micro ~/hoge.js
console.log(x);

Micro上で上記のコードを保存したら、

/home/pi/hoge.js
  1:13  error  'x' is not defined  no-undef

✖ 1 problem (1 error, 0 warnings)

のような内容が出力されました。


続いて、先程作成しましたhoge.htmlの方でESLintを試してみます。

$ micro ~/hoge.html

Microでコードを保存してみます。

/home/pi/hoge.html
  0:0  warning  File ignored because no matching configuration was supplied

✖ 1 problem (0 errors, 1 warning)

ESLintの現在の設定では、HTMLファイルに記述されたJavaScriptの構文チェックができないそうです。

HTMLファイルの方でも使用できるように下記の手続きを行います。

$ npm install --save-dev @html-eslint/parser @html-eslint/eslint-plugin

ESLintの設定ファイルが、~/eslint.config.mjs になりますので、

$ micro ~/eslint.config.mjs

で設定ファイルを開き、

import globals from "globals";
import pluginJs from "@eslint/js";
import html from "eslint-plugin-html"

/** @type {import('eslint').Linter.Config[]} */
export default [
	{
		files: ["**/*.js", "**/*.html"],
		plugins: { html },
		languageOptions: { sourceType: "script" },
	},
	{ languageOptions: { globals: globals.browser } },
	pluginJs.configs.recommended,
];

太字で示した箇所の内容を追加します。


改めて、hoge.htmlを開き、Micro上でコードの保存を行ってみます。

/home/pi/hoge.html
  11:15  error  'x' is not defined  no-undef

✖ 1 problem (1 error, 0 warnings)

のような内容が出力されました。


追記

Microで保存の度にESLintを実行すると実行時間が長いので、都度実行ではなく、lintコマンドを設けて実行するようにします。

※Microで新規に追加するコマンドに関してはMicroのプラグイン開発、文字列を出力するをご確認ください。

$ ~/.config/micro/init.lua
local micro = import("micro")
local config = import("micro/config")
local shell = import("micro/shell")

function init()
	config.MakeCommand("lint", lint, config.NoComplete)
end

function onSave(bp)
	if bp.Buf:FileType() == "html" or bp.Buf:FileType() == "javascript" then
		bp:Save()
		local _, err = shell.RunCommand("prettier " .. bp.Buf.Path .. " --write")
		if err ~= nil then
			micro.InfoBar():Error(err)
			return
		end

		bp.Buf:ReOpen()
	end
end

function lint(bp)
	if bp.Buf:FileType() == "html" or bp.Buf:FileType() == "javascript" then
		local output, _ = shell.RunCommand("npx eslint " .. bp.Buf.Path)
		local strings = import("strings")
		output = strings.TrimSpace(output)
		if output ~= "" then
			micro.TermMessage(output)
			return
		end
	end
end



補足1

typescript-language-serverの設定

typescript-language-server - npm

$ npm install -g typescript-language-server typescript
$ micro -plugin install lsp
$ micro ~/.config/micro/settings.json
{
	...
	"lsp.autocompleteDetails": true,
	"lsp.server": "javascript=typescript-language-server --stdio",
	...
}

※ ...はsettings.jsonで他に追加している設定

※ lsp.autocompleteDetailsをtrueにしておくと、後ほど触れますCtrtl + Space(スペース)の際に表示が見やすくなります。


settings.jsonの編集の後にMicroを起動してみると、~/.config/micro/bindings.jsonに今回のプラグイン用のキーバインドが追加されています。

{
	"Alt-d": "command:definition",
	"Alt-f": "command:format",
	"Alt-k": "command:hover",
	"Alt-r": "command:references",
	"CtrlSpace": "command:lspcompletion",
}

Microで.jsの拡張子のファイルを開き、コードの作成途中で、Ctrl + Space(スペース)を押すと、



のような入力補完の機能が使えるようになります。

Ctrl + Spaceで候補を選択肢、Spaceを押すことで決定できます。



関数やメソッドを追加した後にAlt + kを押すと、選択したコードの説明文が出力されるようになります。


補足2

Ctrl + rでJavaScriptのコードを実行できるようにinit.luaを改修します。

$ ~/.config/micro/init.lua
local micro = import("micro")
local config = import("micro/config")
local shell = import("micro/shell")

function init()
	config.TryBindKey("Ctrl-r", "lua:initlua.run", true)
	config.MakeCommand("lint", lint, config.NoComplete)
end

function run(bp)
	if bp.Buf:FileType() == "javascript" then
		shell.RunInteractiveShell("node " .. bp.Buf.Path, true, false)
	elseif bp.Buf:FileType() == "html" then
		shell.RunCommand("chromium " .. buf.Path)
	end
end

function onSave(bp)
	if bp.Buf:FileType() == "html" or bp.Buf:FileType() == "javascript" then
		bp:Save()
		local _, err = shell.RunCommand("prettier " .. bp.Buf.Path .. " --write")
		if err ~= nil then
			micro.InfoBar():Error(err)
			return
		end

		bp.Buf:ReOpen()
	end
end

function lint(bp)
	if bp.Buf:FileType() == "html" or bp.Buf:FileType() == "javascript" then
		local output, _ = shell.RunCommand("npx eslint " .. bp.Buf.Path)
		local strings = import("strings")
		output = strings.TrimSpace(output)
		if output ~= "" then
			micro.TermMessage(output)
			return
		end
	end
end
同じカテゴリーの記事
マインクラフト用ビジュアルエディタを開発しています。
詳しくはinunosinsi/mcws_blockly - githubをご覧ください。