Range
これは、以下のような場合に特に便利です。
- IDEやエディタとの連携
一部のIDEやエディタのPrettierプラグインでは、選択範囲のみをフォーマットする機能があり、その内部で「Range」の概念が使われていることがあります。 - 既存のコードベースにPrettierを導入する際
一度に全てのファイルをフォーマットするのが難しい場合、段階的に導入するために特定の範囲から始めることができます。 - 大規模なファイルの一部分だけをフォーマットしたい場合
ファイル全体をフォーマットすると時間がかかったり、意図しない変更が入る可能性がある場合に、必要な部分だけをフォーマットできます。
具体的には、Prettier CLI(コマンドラインインターフェース)で--range-start
と--range-end
オプションを使って指定します。
Rangeオプションが期待通りに機能しない
よくある問題
- 範囲外のコードが意図せず変更される
指定した範囲外のコードもフォーマットの影響を受けてしまうことがあります。 - ファイル全体がフォーマットされてしまう
--range-start
と--range-end
を指定したにもかかわらず、ファイル全体がフォーマットされてしまうことがあります。
原因とトラブルシューティング
- IDE/エディタの統合の問題
VS CodeなどのIDEやエディタのPrettier拡張機能を使用している場合、拡張機能が内部的に--range
を正しく渡していない可能性があります。- 解決策
- まず、Prettier CLIで直接
--range
オプションを試して、CLIでは正しく動作するか確認します。 - IDE/エディタのPrettier拡張機能の設定を確認し、"Format Selection"などの機能がPrettierの
--range
オプションをサポートしているか、その設定が正しく行われているかを確認します。 - 拡張機能のキャッシュをクリアしたり、IDEを再起動したりするのも有効な場合があります。
- 関連するGitHub Issuesを確認し、既知のバグがないか調べてみてください。
- まず、Prettier CLIで直接
- 解決策
- Rangeの境界が不適切
指定した行番号がファイルの実際の行数を超えている、または負の数を指定しているなど、不適切な範囲を指定している場合があります。- 解決策
開始行と終了行がファイルの有効な範囲内にあることを確認してください。行番号は0から始まることに注意してください(--range-start 0
はファイルの最初から)。
- 解決策
- パーサーの問題
Prettierは、指定されたファイルの言語に応じて適切なパーサーを使用します。稀に、パーサーが範囲指定を正しく解釈できない場合があります。- 解決策
--parser
オプションを明示的に指定してみてください。例えば、JavaScriptファイルなら--parser babel
または--parser typescript
。
- 解決策
- Prettierのバージョンが古い
非常に古いバージョンのPrettierでは、--range
オプションの挙動にバグがあったり、適切にサポートされていなかったりする可能性があります。- 解決策
Prettierを最新バージョンにアップデートしてください。npm install -g prettier@latest
またはyarn add prettier@latest
- 解決策
フォーマットされたコードが構文エラーを引き起こす
よくある問題
Range
で一部だけフォーマットした結果、その範囲のコードが構文的に壊れてしまう。
原因とトラブルシューティング
- 部分的なフォーマットの限界
Prettierは、コード全体の整合性を保ちつつフォーマットを行うように設計されています。そのため、コードの一部だけをフォーマットすると、その部分が文脈から切り離され、構文的に不完全になることがあります。- 解決策
Range
オプションは、ある程度独立したブロック(例:特定の関数、クラス定義全体など)に対して使用するのが最も安全です。非常に細かな部分をフォーマットしようとすると、問題が発生しやすくなります。 - 根本的な解決策
可能であれば、ファイル全体をPrettierでフォーマットし、Gitの差分ツールで変更内容を確認する方が安全です。
- 解決策
パフォーマンスの問題
よくある問題
- 大規模なファイルに対して
--range
オプションを使用しても、フォーマットに時間がかかる。
原因とトラブルシューティング
- ファイル全体のパース
Prettierは、たとえ--range
オプションが指定されていても、多くの場合、ファイルを完全にパース(解析)する必要があります。これは、指定された範囲のコードがファイル全体の構文ツリーの一部であり、正確なフォーマットにはその文脈が必要だからです。- 解決策
残念ながら、これはPrettierの設計上の特性であり、根本的に解決することは難しい場合があります。パフォーマンスが非常に重要な場合は、以下の点を検討してください。- 部分的なフォーマットの頻度を減らす
開発フローにおいて、--range
の使用頻度を減らすことを検討します。 - Prettierの実行を最適化
Git Hooks (Husky + lint-stagedなど) を使用して、コミット前に変更されたファイルのみをフォーマットするように設定することで、CI/CDパイプラインや手動での実行時間を短縮できます。
- 部分的なフォーマットの頻度を減らす
- 解決策
よくある問題
- Prettierの
Range
フォーマット後に、ESLintが予期しないエラーを報告する。
- フォーマットルールの競合
PrettierとESLint(または他のリンター)が、同じ種類のフォーマットルールを持っている場合、それぞれのツールが異なるスタイルを強制しようとすることがあります。- 解決策
- eslint-config-prettierの使用
これが最も一般的な解決策です。eslint-config-prettier
を導入し、ESLintの設定ファイルでPrettierと競合するESLintのフォーマットルールを無効にします。 - リンターの実行順序
IDEやCI/CDパイプラインで、Prettierを先に実行し、その後にESLintを実行するように設定することで、競合を最小限に抑えることができます。
- eslint-config-prettierの使用
- 解決策
Prettierの--range-start
と--range-end
オプションを使ったプログラミング関連のコード例をいくつか紹介します。これらは主にコマンドラインからの実行例になります。
基本的な使い方 (JavaScriptファイルの例)
まず、フォーマット対象となるJavaScriptファイル example.js
を用意します。
example.js
// This is a comment at the very beginning of the file.
const myVariable = 123;
function longFunctionName(
param1,
param2,
param3
) {
console.log("Hello from a long function!");
const result = param1 + param2 + param3;
return result;
}
class MyClass {
constructor(name) {
this.name = name;
}
greet() {
console.log(`Hello, ${this.name}!`);
}
}
例1: ファイルの先頭から特定の行までをフォーマット
ファイルの0行目から10行目までをフォーマットします。
prettier --write --range-start 0 --range-end 10 example.js
実行後のexample.js (部分的な変更)
// This is a comment at the very beginning of the file.
const myVariable = 123;
function longFunctionName(
param1,
param2,
param3 // Prettierのデフォルト設定では、行末カンマはつかない
) { // ここまでがフォーマット対象の範囲
console.log("Hello from a long function!");
const result = param1 + param2 + param3;
return result;
}
class MyClass {
constructor(name) {
this.name = name;
}
greet() {
console.log(`Hello, ${this.name}!`);
}
}
解説
longFunctionName
の定義が少し変更されました。特にparam3
の後のカンマが、Prettierのデフォルト設定(trailingComma: "none"
または"es5"
でない場合)に従って削除されます。10行目以降のコードは変更されません。
例2: ファイルの中間部分の関数定義だけをフォーマット
longFunctionName
の定義部分(例として7行目から14行目)だけをフォーマットします。
prettier --write --range-start 7 --range-end 14 example.js
実行後のexample.js (部分的な変更)
// This is a comment at the very beginning of the file.
const myVariable = 123;
function longFunctionName(
param1,
param2,
param3 // フォーマットされる
) {
console.log("Hello from a long function!"); // フォーマットされる
const result = param1 + param2 + param3; // フォーマットされる
return result; // フォーマットされる
} // ここまでが範囲
class MyClass {
constructor(name) {
this.name = name;
}
greet() {
console.log(`Hello, ${this.name}!`);
}
}
解説
longFunctionName
の定義とその内部の行がフォーマットされ、インデントやスペースがPrettierのルールに従って調整されます。他の部分は untouched です。
例3: --range-end
を省略して、開始行からファイルの最後までをフォーマット
prettier --write --range-start 17 example.js
実行後のexample.js (部分的な変更)
// This is a comment at the very beginning of the file.
const myVariable = 123;
function longFunctionName(
param1,
param2,
param3
) {
console.log("Hello from a long function!");
const result = param1 + param2 + param3;
return result;
}
class MyClass { // ここからファイルの最後までが対象
constructor(name) {
this.name = name;
}
greet() {
console.log(`Hello, ${this.name}!`);
}
}
解説
MyClass
の定義以降がフォーマットされます。--range-end
を省略すると、指定された--range-start
からファイルの最後までが対象となります。
--range-start
と--range-end
の注意点
- 部分的なフォーマットの限界
前述の通り、コードの途中で範囲を区切ると、構文的な整合性が保てなくなり、エラーが発生する可能性があります。完全に独立した関数やクラスのブロックなど、自然な単位で範囲指定することをお勧めします。 - パーサーの指定
ファイルの種類によっては、--parser
オプションを明示的に指定する必要がある場合があります。例えば、TypeScriptファイルなら--parser typescript
。 - 行番号は0から始まる
コマンドラインで指定する行番号は、ファイルの内容の最初の行が0
になります。
応用例: GitフックやIDE/エディタとの連携
--range
オプションは、Gitフック(例:lint-staged
)やIDE/エディタの「選択範囲をフォーマット」機能の内部で利用されることがあります。
lint-staged
と--range
(Gitフックの例)
これは直接--range
オプションを使うわけではありませんが、lint-staged
のようなツールがコミットされる変更ファイルの一部(ステージングされた変更)のみをPrettierでフォーマットする際に、類似のコンセプトで動くことがあります。ただし、lint-staged
は通常、ファイル全体を対象としますが、変更された行のみをフォーマットするような、より高度な機能を持つツールと組み合わせる場合に--range
が関連してきます。
.lintstagedrc.js の例 (直接--rangeを使うわけではないが、概念的に関連)
module.exports = {
'*.js': 'prettier --write', // コミットされるJavaScriptファイル全体をフォーマット
// 'prettier --write --range-start ... --range-end ...' は通常lint-stagedでは使わない
// なぜなら、lint-stagedは「変更されたファイル全体」を対象とするため
};
IDEやエディタの「選択範囲のフォーマット」機能は、ユーザーが選択した範囲の開始行と終了行を取得し、Prettierに--range-start
と--range-end
を渡して実行していると理解できます。
これらの例を通して、Prettierの--range
オプションがコードベースの特定のエリアに焦点を当ててフォーマットを実行するのにどのように役立つか理解できたかと思います。
Prettierの「Range」機能は、CLI(コマンドラインインターフェース)を使って、特定のファイルの指定された行範囲のみをフォーマットするために使用されます。
ここでは、JavaScriptファイルを例にとって、具体的なコード例と動作を説明します。
準備: サンプルファイル example.js
まず、フォーマットするJavaScriptファイルを作成します。
example.js
const myLongVariableOne = 10;
const myLongVariableTwo = 20;
const myLongVariableThree = 30;
function calculateSum(a, b, c) {
const sum = a + b + c;
return sum;
}
const data = {
name: "John Doe",
age: 30,
city: "New York",
};
console.log(calculateSum(myLongVariableOne, myLongVariableTwo, myLongVariableThree));
console.log(data.name);
Prettier CLI で Range
を使用する例
コマンドラインでPrettierを実行し、--range-start
と --range-end
オプションを使用します。行番号は 0 から始まります。
例 1: 特定の関数のみをフォーマットする
calculateSum
関数(5行目から8行目)のみをフォーマットしたい場合を考えます。
return sum;
は8行目です。function calculateSum(a, b, c) {
は5行目です。
prettier --write example.js --range-start 4 --range-end 8
コマンド実行後 (example.js の変化)
このコマンドは、指定された範囲のコードブロックのフォーマットに影響を与えます。Prettierは構文ツリーに基づいてフォーマットするため、指定した行範囲が完全な構文要素(関数、ステートメントなど)を含んでいる場合に最も効果的です。
例では、calculateSum
関数の部分だけが、Prettierのルールに基づいて整形されます。もしcalculateSum
関数がPrettierによって推奨されるフォーマットから逸脱していた場合、このコマンドで修正されます。
例えば、もし関数が以下のように意図的に崩されていたとします。
example.js (フォーマット前)
const myLongVariableOne = 10;
const myLongVariableTwo = 20;
const myLongVariableThree = 30;
function calculateSum(a, b, c){
const sum = a + b + c;
return sum;
}
const data = {
name: "John Doe",
age: 30,
city: "New York",
};
console.log(calculateSum(myLongVariableOne, myLongVariableTwo, myLongVariableThree));
console.log(data.name);
上記のコマンドを実行すると、calculateSum
関数のみがPrettierのデフォルトルール(インデント、スペースなど)に従って整形されます。
example.js (フォーマット後、--range-start 4 --range-end 8 の場合)
const myLongVariableOne = 10;
const myLongVariableTwo = 20;
const myLongVariableThree = 30;
function calculateSum(a, b, c) { // ここから
const sum = a + b + c;
return sum; // ここまで
}
const data = {
name: "John Doe",
age: 30,
city: "New York",
};
console.log(calculateSum(myLongVariableOne, myLongVariableTwo, myLongVariableThree));
console.log(data.name);
(注意: Prettierは構文ツリーに基づいて範囲を拡張する場合があります。そのため、指定した開始・終了行が厳密にその通りに解釈されるとは限りません。関連する構文要素全体をフォーマットしようとします。)
例 2: 特定のオブジェクト定義のみをフォーマットする
data
オブジェクト(10行目から14行目)をフォーマットしたい場合。
};
は14行目です。const data = {
は10行目です。
prettier --write example.js --range-start 9 --range-end 13
const myLongVariableOne = 10;
const myLongVariableTwo = 20;
const myLongVariableThree = 30;
function calculateSum(a, b, c) {
const sum = a + b + c;
return sum;
}
const data = { // ここから
name: "John Doe",
age: 30,
city: "New York",
}; // ここまで
console.log(calculateSum(myLongVariableOne, myLongVariableTwo, myLongVariableThree));
console.log(data.name);
- IDE/エディタの統合
多くのIDEやエディタのPrettier拡張機能は、「選択範囲をフォーマット」する機能を提供しており、内部的にこの--range-start
と--range-end
オプションが使われていることが多いです。ユーザーが直接コマンドを入力する必要はありません。 - 部分フォーマットの限界
Range
オプションは、ファイル全体をフォーマットするのが難しい場合に役立ちますが、コードの整合性を完全に保証するものではありません。複雑なコードや、依存関係のある部分を個別にフォーマットすると、全体としてコードの可読性や整合性が損なわれる可能性もあります。可能であればファイル全体をフォーマットするのが最も推奨される方法です。 - 構文ツリーに基づいたフォーマット
Prettierは行単位ではなく、コードの抽象構文ツリー(AST)を解析してフォーマットを行います。そのため、指定した行範囲が、構文的に完全なブロック(例: 関数全体、オブジェクト全体、ステートメント全体)を含んでいない場合、予期しない結果になったり、エラーになったりする可能性があります。 - 行番号は0から始まる
--range-start 0
はファイルの最初の行を意味します。
ファイル全体をフォーマットする
最も一般的で推奨される方法です。 Prettierの設計思想は、ファイル全体をフォーマットして一貫したコードスタイルを強制することにあります。Range機能はあくまで例外的なケースで用いられることが多いです。
利点
- IDE/エディタとの親和性
ほとんどのPrettier統合は、デフォルトでファイル全体のフォーマットをサポートしています。 - シンプルさ
コマンドが簡単で、オプションを気にする必要がありません。 - 一貫性
コードベース全体で統一されたスタイルを維持できます。
コマンド例
prettier --write example.js
または、プロジェクト全体を対象とする場合:
prettier --write .
Git staged changes のみをフォーマットする (lint-staged の活用)
これは、チーム開発において非常に強力な代替手段です。コミットされる予定の変更(Gitのステージングエリアにあるファイル)のみをPrettierでフォーマットします。これにより、大規模なコードベースにPrettierを導入する際、過去のコードを一度にすべて変更するリスクを避けつつ、新しいコードや変更されたコードだけをクリーンに保つことができます。
必要なツール
- husky
Gitフックを簡単に設定するためのライブラリ(pre-commit
フックでlint-staged
を実行するため)。 - lint-staged
Gitのステージングエリアにあるファイルに対してコマンドを実行するためのライブラリ。
設定例 (package.json)
{
"name": "my-project",
"version": "1.0.0",
"scripts": {
"format": "prettier --write ."
},
"devDependencies": {
"prettier": "^3.0.0",
"lint-staged": "^15.0.0",
"husky": "^9.0.0"
},
"lint-staged": {
"*.{js,jsx,ts,tsx,json,css,md}": "prettier --write"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
}
}
ワークフロー
- ファイルに変更を加える。
git add <file>
で変更をステージする。git commit -m "feat: my new feature"
でコミットしようとすると、pre-commit
フックがトリガーされ、lint-staged
がステージされたファイルに対してprettier --write
を実行する。- フォーマットされた変更が自動的にステージされ、コミットされる。
利点
- Range機能の代替
特定の「変更された範囲」をフォーマットするという意味で、Range機能のユースケースの多くをカバーできます。 - チーム開発での一貫性
チームメンバー全員が、コミット時に自動的にフォーマットされたコードを共有できます。 - 効率的
変更されたファイルのみが処理されるため、大規模プロジェクトでも高速です。 - 段階的な導入
既存の大量のコードを変更せずに、新しいコードからPrettierを適用できます。
IDE/エディタの「選択範囲をフォーマット」機能
多くのモダンなIDEやコードエディタ(VS Code, WebStormなど)は、Prettierプラグインを通じて「選択範囲をフォーマット」する機能を提供しています。これは、Range機能が裏側で使われている場合もありますが、ユーザーはCLIコマンドを意識せずにGUI操作で行えます。
利点
- リアルタイム性
コードを記述しながら、その都度必要な部分だけを整形できます。 - 直感的
マウスやキーボードショートカットで簡単に特定のコードブロックをフォーマットできます。
VS Codeでの例
- フォーマットしたいコードを選択する。
- 右クリックして「選択範囲のフォーマット」を選択するか、
Shift + Alt + F
(Windows/Linux) またはShift + Option + F
(macOS) を押す。 - Prettierがその選択範囲をフォーマットします。
Range機能とは少し異なりますが、特定のファイルやディレクトリをPrettierのフォーマット対象から完全に除外したい場合に有効です。
.prettierignore ファイルの例
# build output
/dist
/build
# dependencies
/node_modules
# specific files
src/legacy-code.js
利点
- 一度設定すれば、それらのファイルが誤ってフォーマットされるのを防げる。
- フォーマットしたくないコードを明確に区別できる。
PrettierのRange機能は、特定の行範囲をピンポイントでフォーマットしたい場合に有効なツールですが、より広範な開発ワークフローにおいては、以下の代替方法が推奨されます。
- ファイル全体をフォーマットする
最もシンプルで一貫性を保つ方法。 - lint-stagedとhuskyでGit staged changesのみをフォーマットする
チーム開発や大規模プロジェクトで最も実用的で、Range機能の多くのユースケースをカバーできる。 - IDE/エディタの「選択範囲をフォーマット」機能
開発中のリアルタイムなフォーマットに便利。 - .prettierignore で対象外を指定する
特定のファイルやディレクトリをフォーマット対象から完全に除外する。