JSON Par modeは、EmacsでJSONを構造的に編集をするためのマイナーモードであり、lispyに影響を受けています。
(非視覚的UAをお使いの方へ: 以降の例で‘|’はポイントであり、‘*’はマークです。)
ポイントが文字列の外にある場合、各キーはコマンドとして解釈されます。一方ポイントが文字列の上にある場合、キーはそのまま入力されます:
リージョンがアクティブな場合、各キーはコマンドとして解釈されます。
前後のメンバー(キーと値のペア)や、親などへ移動できます:
キー | コマンド | 説明 |
---|---|---|
j | json-par-backward-member |
次のメンバー(キーと値のペア) |
k | json-par-forward-member |
前のメンバー |
h | json-par-up-backward |
囲んでいるオブジェクトや配列の先頭 |
l, }, あるいは] | json-par-up-forward |
囲んでいるオブジェクトや配列の末尾 |
a | json-par-beginning-of-member |
メンバーの先頭 |
e | json-par-end-of-member |
メンバーの末尾 |
v | json-par-beginning-of-object-value |
値の先頭 |
J | json-par-backward-record |
前のオブジェクトの同じキー |
K | json-par-forward-record |
次のオブジェクトの同じキー |
A | json-par-beginning-of-list |
最初のメンバーの先頭 |
E | json-par-end-of-list |
最後のメンバーの末尾 |
その他のコマンド:
|[ 1, 2, 3 ]
↓ i (‘json-par-down’)
[ |1, 2, 3 ]
[ 1, 2, 3 ]|
↓ i (‘json-par-down’)
[ 1, 2, 3| ]
{
"key|": 123
}
↓ TAB (‘json-par-tab’)
{
"key": |123
}
↓ S-TAB (‘json-par-mark-head-of-member’)
{
"*key|": 123
}
[
"The quick brown |fox jumps over the lazy dog."
]
↓ TAB (‘json-par-tab’)
[
"The quick brown fox jumps over the lazy dog."|
]
{
|"name": "Emacs",
"website": "https://www.gnu.org/software/emacs/",
"written_in": [ "C", "Emacs Lisp" ]
}
↓ g (‘json-par-goto-key’) website RET
{
"name": "Emacs",
|"website": "https://www.gnu.org/software/emacs/",
"written_in": [ "C", "Emacs Lisp" ]
}
[
"a",
|"b",
"c"
]
↓ M-x json-par-goto-index 0 RET
[
|"a",
"b",
"c"
]
小技: j、k、J、K以外のコマンドは移動前にマークリングにマークをプッシュします。またbはpop-to-mark-command
にバインドされています。そのためbを押すと移動前の位置に戻れます。
qを押すと次のコマンドだけJSON Par modeを無効にできます。Qを押すと明示的に再有効化するまで無効になります。
1キーで値を入力できます:
キー | 説明 |
---|---|
t | true を挿入する |
f | false を挿入する |
n | null を挿入する |
[ | [] を挿入する |
{ | {} を挿入する |
" | "" を挿入する |
, | , を挿入する |
: | : を挿入する |
+, -, 0-9 | 数値を挿入する |
カンマや改行は適宜挿入されます:
[
[
1, 2, 3
]|
]
↓ [
[
[
1, 2, 3
],
[
|
]
]
[
[ 1, 2, 3 ]|
]
↓ [
[
[ 1, 2, 3 ],
[|]
]
↓ 1
[
[ 1, 2, 3 ],
[ 1| ]
]
リージョンがアクティブな場合[、{、"でリージョンを囲めます。C-uプレフィックスを付けた場合、"は文字列を展開します。
リージョンがアクティブな場合、dや<backspace>でリージョンを削除できます。
リージョンがアクティブでない場合、d+移動キーでメンバーや値をマークできます:
[
1|,
2,
3,
4
]
↓ d2j (「後続のメンバーを2つマークする」)
[
1|,
2,
3*,
4
]
↓ d
[
1|,
4
]
キー | 説明 |
---|---|
dd | 現在のメンバー(キーと値のペア)をマークする。 |
d. | 現在の値やキーをマークする。 |
dj | ポイントの後にあるメンバーをマークする。 |
dk | ポイントの前にあるメンバーをマークする。 |
dh | 囲んでいるオブジェクトや配列をマークする(ポイントは親の前に移動する)。 |
dl | 囲んでいるオブジェクトや配列をマークする(ポイントは親の後に移動する)。 |
da | 現在のキーと値のペアのうち、キーをマークする。 |
deあるいはdv | 現在のキーと値のペアのうち、値をマークする。 |
dA | 囲んでいるオブジェクトや配列の全てのメンバーをマークする(ポイントは最初のメンバーの前に移動する)。 |
dE | 囲んでいるオブジェクトや配列の全てのメンバーをマークする(ポイントは最後のメンバーの後に移動する)。 |
di | ポイントの前か後にあるオブジェクトや配列や文字列の中身を全てマークする。 |
小技: json-par-action-when-deleting-value-or-memberをdelete
にするとマークせずに削除できます。
<backspace>やC-dを使うと構造を保ったまま様々な物を削除あるいはマークできます:
[ 1, 2, 3 ]|
↓ <backspace>
[ *1, 2, 3| ]
[]|
↓ <backspace>
*[]|
[| 1, 2, 3 ]
↓ <backspace>
[ |1, 2, 3* ]
[|]
↓ <backspace>
|[]*
"Emacs"|
↓ <backspace>
"*Emacs|"
"|Emacs"
↓ <backspace>
"|Emacs*"
[ 1,| 2 ]
↓ <backspace>
[ *1,| 2 ]
{
"name":| "Emacs",
"website": "https://www.gnu.org/sotware/emacs/"
}
↓ <backspace>
{
*"name": "Emacs",
|"website": "https://www.gnu.org/sotware/emacs/"
}
delete-outer
: オブジェクトや値全体を削除する。delete-inner
: オブジェクトや値が空でなければ中身を削除する。そうでなければオブジェクトや配列全体を削除する。mark-outer
: オブジェクトや配列全体をマークする。mark-or-delete-outer
: オブジェクトや配列全体をマークする。既にマークされていれば削除する。mark-inner
: オブジェクトや配列が空でなければ中身をマークする。そうでなければオブジェクトや配列全体をマークする。enter
: オブジェクトや配列の内側にポイントを移動する。delete-outer
: オブジェクトや配列全体を削除する。delete-inner
: オブジェクトや配列が空でなければ中身を削除する。そうでなければオブジェクトや配列全体を削除する。mark-outer
: オブジェクトや配列全体をマークする。mark-inner
: オブジェクトや配列が空でなければ中身をマークする。そうでなければオブジェクトや配列全体をマークする。mark-or-delete-inner
: オブジェクトや配列が空でなければ中身をマークする。そうでなければオブジェクトや配列全体をマークする。既にマークされていれば削除する。exit
: オブジェクトや配列の外にポイントを移動する。none
: 何もしない。delete
: カンマの向こうにあるメンバー(キーと値のペア)全体を無条件に削除する。mark-or-delete
: カンマの向こうにあるメンバー(キーと値のペア)全体がマークされていれば削除する。mark
: カンマの向こうにあるメンバー全体を無条件にマークする。skip
: カンマの向こう側にポイントを移動する。delete
: メンバー(キーと値のペア)全体を無条件に削除する。mark-or-delete
: メンバー(キーと値のペア)全体がマークされていれば削除する。mark
: メンバー全体を無条件にマークする。skip
: コロンの向こう側にポイントを移動する。v (json-par-delete-object-values
)は現在のオブジェクトや配列の値を全て削除します。
{
"group": "group1",
"key": "foo",
"value": |[ 1, 2, 3 ]
}
↓ V
{
"group": ,
"key": ,
"value": |
}
例:
|[
[
1,
2
],
[
3,
4
]
]
↓ O (‘json-par-oneline’) ↑ M (‘json-par-multiline’)
|[ [ 1, 2 ], [ 3, 4 ] ]
↓ O
|[[1,2],[3,4]]
{
"lyrics": |"Twinkle, twinkle, little star,
How I wonder what you are!
Up above the world so high,
Like a diamond in the sky."
}
↓ O (‘json-par-oneline’) ↑ M (‘json-par-multiline’)
{
"lyrics": |"Twinkle, twinkle, little star,\nHow I wonder what you are!\nUp above the world so high,\nLike a diamond in the sky."
}
プレフィックス引数を付けると、影響する範囲を限定できます:
|[
[
1,
2
],
[
3,
4
]
]
↓ C-1 O (レベルが1より大きいメンバーを1行に変換する)
|[
[ 1, 2 ],
[ 3, 4 ]
]
↑ C-1 M (レベルが1以下のカンマの後に改行を入れる)
|[ [ 1, 2 ], [ 3, 4 ] ]
括弧のすぐ内側に改行が挿入された場合、各メンバーの後にも改行が挿入されます。括弧のすぐ内側の改行が削除された場合、オブジェクトや配列全体が1行に変換されます:
[| [ 1, 2 ], [ 3, 4 ] ]
↓ RET ↑ <backspace>
[
|[ 1, 2 ],
[ 3, 4 ]
]
括弧のすぐ内側に改行を入れた場合の動作。
break-inside-brackets
: 括弧のすぐ内側のみに改行を入れる。
例 (‘|’はポイント):
[ |1, 2, 3 ] ↓ RET [ |1, 2, 3 ]
break-each-member
: 各メンバーの後にも改行を入れる。
例 (‘|’はポイント):
[ |1, 2, 3 ] ↓ RET [ |1, 2, 3 ]
デフォルト値はbreak-each-member
です。
最初のメンバーの後に改行を入れた場合の動作。
just-break
: その行のみに改行を入れる。
例 (‘|’はポイント):
[ 1, |2, 3 ] ↓ RET [ 1, |2, 3 ]
break-each-member
: 各メンバーの後にも改行を入れる。
例 (‘|’はポイント):
[ 1, |2, 3 ] ↓ RET [ 1, |2, 3 ]
デフォルト値はjust-break
です。
空行以外の改行を削除した場合の動作。
just-delete
: その改行のみを削除する。
例 (‘|’はポイント):
[ 1, | 2, 3 ] ↓ <backspace> [ 1,| 2, 3 ]
delete-line-breaks-between-members
: 1メンバー1行になっている場合、各メンバー間の改行(最初のメンバーの前や最後のメンバーの後の改行は含まない)を全て削除する。
例 (‘|’はポイント):
[ 1, | 2, 3 ] ↓ <backspace> [ 1,| 2, 3 ]
[ 1, | 2, 3, 4 ] ↓ <backspace> [ 1,| 2, 3, 4 ]
delete-line-breaks-inside-brackets
: 1メンバー1行になっている場合、現在の配列やオブジェクト内の改行を全て削除する。
例 (‘|’はポイント):
[ 1, | 2, 3 ] ↓ <backspace> [ 1,| 2, 3 ]
[ 1, | 2, 3, 4 ] ↓ <backspace> [ 1,| 2, 3, 4 ]
デフォルト値はjust-delete
です。
例:
{
"properties": {
"tags": |{
"type": "array",
"items": {
"type": "string"
}
}
}
}
↓ cj (‘json-par-clone-member-forward’: 現在のメンバーをその後に複製する)
{
"properties": {
"tags": {
"type": "array",
"items": {
"type": "string"
}
},
"|tags*": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
[
{
"group": |"group1",
"key": "foo",
"value": [ 1, 2, 3 ]
}
]
↓ CJ (‘json-par-clone-parent-forward-without-value’: 親であるメンバーをその後に値を除いて複製する)
[
{
"group": "group1",
"key": "foo",
"value": [ 1, 2, 3 ]
},
{
"group": |,
"key": ,
"value":
}
]
キー | 説明 |
---|---|
cj, cc | 現在のメンバーをその後に複製する。 |
ck | 現在のメンバーをその前に複製する。 |
cJ | 親であるメンバーをその後に複製する。 |
cK | 親であるメンバーをその前に複製する。 |
Cj, CC, cvj, cvc | 現在のメンバーをその後に値を除いて複製する。 |
Ck, cvk | 現在のメンバーをその前に値を除いて複製する。 |
CJ, cvJ | 親であるメンバーをその後に値を除いて複製する。 |
CK, cvK | 親であるメンバーをその前に値を除いて複製する。 |
発展: cの後にhやiを押すと複製する祖先を選択できます。
? (json-par-insert-guessed
)はJSONの値やキーに対するdabbrev-expand
です。つまり文脈から推測した値やキーを挿入します:
{
"properties": {
"id": {
"type": "string",
"minLength": 1
},
"name": {
"type": "string"
},
"email": |
}
}
↓ ?
{
"properties": {
"id": {
"type": "string",
"minLength": 1
},
"name": {
"type": "string"
},
"email": {
"type": "string"
}|
}
}
↓ ?
{
"properties": {
"id": {
"type": "string",
"minLength": 1
},
"name": {
"type": "string"
},
"email": {
"type": "string",
"minLength": 1
}|
}
}
前述の例では、まず現在のバッファや他のJSONのバッファから"email"
キーを探します。その後、"properties"
を探してその孫を抽出します。json-par-guess-max-ancestorsは検索に使う祖先をどれだけ辿るのか制御します。
ポイントがオブジェクトの内部にあり、キーの後にない場合は、キーを補完します:
{
"properties": {
"id": {
"type": "string",
"minLength": 1
},
"name": {
"type": "string"
},
"email": {
"type": "string"|
}
}
}
↓ ?
{
"properties": {
"id": {
"type": "string",
"minLength": 1
},
"name": {
"type": "string"
},
"email": {
"type": "string",
"minLength": |
}
}
}
キーを推測する場合、祖先のキー("email"
や"properties"
)と兄弟のキー("type"
)を使います。
{
"key": |"key1",
"value": "value1"
}
↓ s (‘json-par-transpose-member-forward’) ↑ w (‘json-par-transpose-member-backward’)
{
"value": "value1",
"key": |"key1"
}
{
"items" {
"oneOf": [
|{ "$ref": "#/definitions/Foo" },
{ "$ref": "#/definitions/Bar" }
]
}
}
↓ r (‘json-par-raise-member’)
{
"items" {
|{ "$ref": "#/definitions/Foo" }
}
}
m (json-par-mark-more
)やC-M-SPCを繰り返し押すと、リージョンを拡張できます。C-uプレフィックスを付けると拡張を取り消せます。
同様に、N (json-par-narrow
)で現在の値やキーにナロー(表示範囲の限定)でき、繰り返すと拡張できます。
S (json-par-split
)でポイントがある文字列やオブジェクトや配列を分割できます。F (json-par-join
)で2つの文字列や配列やオブジェクトを結合できます。
カスタム変数を設定すると、ウィンドウ外の祖先を表示できます::
祖先は次のフェイスで表示されます:
また、祖先や現在のメンバーの前に文字を表示できます: