MicroでJavaScriptで書かれたコードを保存する時に、自動でコードフォーマッターのPrettierとリンターのESLintが実行するようにしてみます。
※コードフォーマッターがコードを整形し、リンターがコードの書き方の問題点を調べます
Prettier · Opinionated Code Formatter · Prettier
Find and fix problems in your JavaScript code - ESLint - Pluggable JavaScript Linter
最初に上記のライブラリをインストールするためのnpmをインストールします。
最初に最新版の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