選択範囲の行の空白を整えるUserScript
個人的には並び替えとかを先に作りたいけどtakker.icon
要件
選択範囲が存在する状態で特定のkeyを押すと、以下の作業をおこなう
インデント部分の空白をすべて半角スペースにする
末尾の空白をすべて消す
コードブロックやテーブルにかかわらず、任意の場所で実行できるようにする
考えないといけなさそうなやつ
問題のようであれば修正する
2021-01-01 14:35:26 できた
テストしてみる
14:45:55 謎の挙動しかしない……
goLineが正常に動いていない?
このコードを試してみよう
code:test1.js
import {goLine, enterEdit} from '/api/code/takker/scrapbox-edit-emulation/script.js';
window.goLine =(index) =>{enterEdit();goLine({index});};
14:50:28 正常に動いた……
もしかしてenterEdit()を挟んでいないのが問題?
14:52:37 全然違った
14:52:45 選択範囲を解除すればいいのか?
14:54:28 選択範囲ありで↑を実行したらうまく動いた……
コマンド実行後に少し待って、描画状況を確認してみよう。
15:03:26 待機ありとなしとで全然結果が違うのだが……
https://gyazo.com/e7ef9bc4133deea7e35d35407046a212
もしかして、発行したeventの完了を待っていないのが原因か?
event完了を待つ方法ってあるのかな?
やっぱり完了を待たずに次々とコマンドを出していることが原因だ
イベントハンドラは入れ子のコールスタック上で実行され、実行が完了するまで呼び出し元をブロックしますが、例外は呼び出し元まで伝播しません。
15:15:44 行末からShift+Home x2で選択するようにしてみた
15:18:58 だめでした
15:19:04 keyupを同時に発行するようにしてみた
15:21:37 だめでした
15:21:57 待たないとこういう挙動になる
2. 行末をクリックしてマウスを移動する
2. 行末をクリックしてマウスを移動する
3. ↑を待たずにHomeを二回押す
何故かShiftで選択ができていないみたい
4. カーソル位置に挿入する
6. 他にも編集対象となる行があった場合は、2.を待たずに1.から実行しだす。
6. 他にも編集対象となる行があった場合は、2.を待たずに1.から実行しだす。
1msくらいまつ
どう対処するか
1msくらいまつ
こうなる
https://gyazo.com/9bb5cd89b4231ac80a1afaa52e0524a0
すんごいdirtyな感じがする……
ただこれ以外に方法がなさそう……
おそらくKeyboard入力のみなら、待つ必要がない
テキスト入力やマウスクリックを組み合わせると、待たないとおかしなことになる
16:17:07 この仮説は多分あってる
addEventListenerでeventを補足する
イメージ
code:js
element.dispatchEvent(...);
return new Promise(resolve => {
element.addEventListener('event', () => resolve(), {once: true});
};
本当にこんなことで捕捉できるのか?
そもそも、callback関数に非同期関数が渡されていたら元も子もない
編集コマンドを減らす
今回はテロメアの更新をなるべく減らすために何度もinsertTextを実行している
これを一度にすべて書き換えるようにすれば待たなくて済む?
いや、キー入力を組み合わせている以上、待つ必要が出てくる
code:script.js
import {selection} from '/api/code/takker/scrapbox-selection-2/script.js';
import {scrapboxDOM} from '/api/code/takker/scrapbox-dom-accessor/script.js';
import {goLine, goHead, enterEdit} from '/api/code/takker/scrapbox-edit-emulation/script.js';
import {press} from '/api/code/takker/scrapbox-keyboard-emulation-2/script.js';
import {insertText} from '/api/code/takker/scrapbox-insert-text/script.js';
export async function tidySpaces() {
const {start: {lineNo: startNo}, end: {lineNo: endNo}} = selection.range;
for (let i = startNo; i <= endNo; i++) {
const orgText = scrapbox.Page.linesi.text; // 処理する必要がなければ何もしない
if (!/\s+$/.test(orgText) && !/^ /.test(orgText.replace(/^(\s*).*/, '$1'))) continue; const indent = scrapbox.Page.linesi.nodes.unit.tag.length; const body = orgText.trim();
const text = ${' '.repeat(indent)}${body};
scrapboxDOM.lines.childreni); before: orgText,
after: text
});
// 指定の行に飛んで編集する
enterEdit();
goLine({index: i});
await sleep(10);
press('Home', {shiftKey: true});
press('Home', {shiftKey: true});
//await sleep(1);
insertText({text});
await sleep(1);
}
}
const sleep = milliseconds => new Promise(resolve => setTimeout(resolve, milliseconds));