VSCode 拡張作ってみる
眺める
型
TextEditor 1つのファイルを開いているエディタ
TextDocument
? Resource もこれになる? たとえは Markdown Preview
Selection カーソル位置、選択範囲
https://gyazo.com/abfb1dbc1d12216a4a01b5764b8ed5aa
はい
Activating extension 'undefined_publisher.pokutuna-test' failed: Cannot find module '/Users/pokutuna/tmp/20200624.vscode-extension.ZzklL4/pokutuna-test/out/extension.js'
ビルドできてないのかな
yarn compile したら動く
デバッガ起動する前のタスクに問題がありそう
The terminal process terminated with exit code: 127
出てるな
なんもしらんが .vscode/{tasks.json, launch.json} あたりだろう
yeoman で yarn 選んだのに npm になってるところあるな → "type": "npm" なだけでよさそう
Task の起動にコケてる
yo したときのログでなんか出てはいた
code:error
✖ NODE_PATH matches the npm root
Unable to find the npm root, something went wrong.
Try to execute npm -g root --silent on your command-line
ndenv 使っているからいかにもありそう
vscode の shell が bash になってて .zshenv の内容が反映されていなかった
あとそもそも NODE_PATH も設定してなかった(別に他では要らんと思うが...)
export NODE_PATH="$(npm root -g)" して
settings.json に "terminal.integrated.shell.osx": "/usr/local/bin/zsh", 追加する
ついでに ndenv 古いから nodenv にした
まあ個別にちまちま設定したくないのでやらないけど、他で使うことはあるかも
デバッガの使い方もわかった、偉い
やってみてる
console.log の出力は親の Debug Console に出てる
editor の ID はこういう文字列
"vs.editor.ICodeEditor:4,$model10"
標準の動作のイベントリスナがいろいろある
vscode.workspace.*
https://gyazo.com/357b4b48a5d8459f929ada2ec154dcbf
まとめて見たいな
! イベントリスナも context.subscriptions.push してから登録される 標準の動作から探したいときは VSCode 本体のコード見るのがよさそう
workbench.action.navigateBack なら
単に historyService 呼ぶだけなのか〜 とか
メニューにアクションを登録しているな〜 とか
HistoryService の実装を見に行くと、どういうイベントリスナから履歴書いてるのかとかはすぐ分かる
マウスボタンのサポートとか色々やっている
自分で Eidtor 内での進む戻るを作りたかったらこのへんかな?
onDidActiveEditorChange 常にカレントエディタごとの履歴を記録してればいらないかも
onDidFilesCahnge なんか色々開きそうで気になる
onExpressionChange Expression どういう単位だろ? エディタテキスト中の式のことなんだろうか
onDidCloseEditor 閉じたら履歴消したいよね
あるいは HistoryService を舐めれる?
そういうのは Extension API に提供されてないと思う
↑ 大体internal やんけ
vscode.window.* だな
なんかどういう値が来るのかとか頻度とかチマチマ log 仕込んで認識合わせる必要がありそう
ある程度は internal のやつとのマッピングがあるんじゃないか
カーソル位置へのアクセス
editor.selection.active とか?
editor は各種コールバックや vscode.window.activeTextEditor とかで取れる
履歴操作のインタフェース
どこで push してるのか?
これ? なんか違う気が
雰囲気はいいけど
アクション登録する雰囲気はこういう感じか
workbench.action.navigateForward/Back からたどりたい
これが HistoryService の実体かな?
IHistoryService を実装していてイベントハンドラがもろもろ設定されてある
なんかこの規模のエディタを自分で作れる気がしないな
TextEditorState が履歴エントリだろう
forward/back とかでどうしてるか
setIndex & navigate
setIndex は履歴エントリをたどる
naigate は排他制御しつつ editroService.openEditor
revealIfOpened: true, // support to navigate across editor groups,
サポートしてほしくないんだが
code:registerListeners.ts
this._register(this.editorService.onDidActiveEditorChange(() => this.onActiveEditorChanged()));
this._register(this.editorService.onDidOpenEditorFail(event => this.remove(event.editor)));
this._register(this.editorService.onDidCloseEditor(event => this.onEditorClosed(event)));
this._register(this.storageService.onWillSaveState(() => this.saveState()));
this._register(this.fileService.onDidFilesChange(event => this.onDidFilesChange(event)));
this._register(this.editorService.onDidMostRecentlyActiveEditorsChange(() => this.handleEditorEventInRecentEditorsStack()));
onActiveEditorChanged
同じエディタなら何もしない
古いリスナを消す(Active なやつだけにセットする)
DisporsableStore に入れてる、イベントリスナを入れてるユーティリティか
拡張でもいい感じに消す必要あるかどうか、subscription がなんかいい感じにしてくれるのか
カーソルポジションが動くイベントを debounce 0ms してる
navigatingInStack これ排他制御と思ってるフラグが有効かどうかでやっている
TextEditor or NonTextEditor
add or replace
onDidChangeModelContext で編集、これも debounce
this.lastEditLocation.selection を更新
remove
ファイルが削除されたら & 開けなかったら履歴エントリから消しまくる
History, NavigationStack, RecentlyClosedEditors, RecentlyOpened
今気にするのは History 系だけだな
onEditorClosed
History に関係ないかな? というかそこに絞ってみるべきだな...
push してるところをみる
navigationStackIndex を更新するところ
addToNavigationStack & replaceInNavigationStack を呼ぶところをみていく
handle(Non)TextEditorEventInNavigationStack の2つだけ
handleTextEditorEventInNavigationStack
navigatingInStack これ排他制御かと思ったけど、履歴から履歴への移動も含むのか
add も replace も navigatingInStack ならなにもしない
currentTextEditorState に状態を保存している
どういったタイミングで更新されるか見る
navigate → = true → doNavigate → = false
handleEditorSelectionChangeEvent
onActiveEditorChanged から debounce しつつ呼ばれる
handleActiveEditorChange
onActiveEditorChanged の最初に呼ばれる
doAddOrReplaceInNavigationStack
連続的な更新、同じエントリは replace する
matches が複数のオブジェクトの種類を考慮した比較ロジックを持ってる
sameSelection は startLineNumber が同じなら同じとみなす
途中に挿入したら、そこ以降を消す、最大を超えたら最初から消す