選択範囲の行の空白を整えるUserScript
個人的には並び替えとかを先に作りたいけど

要件
選択範囲が存在する状態で特定のkeyを押すと、以下の作業をおこなう
インデント部分の空白をすべて半角スペースにする
末尾の空白をすべて消す
コードブロックやテーブルにかかわらず、任意の場所で実行できるようにする
考えないといけなさそうなやつ
問題のようであれば修正する
2021-01-01 14:35:26 できた
テストしてみる
14:45:55 謎の挙動しかしない……
goLine
が正常に動いていない?
このコードを試してみよう
test1.jsimport {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 待機ありとなしとで全然結果が違うのだが……
もしかして、発行した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くらいまつ
こうなる
すんごいdirtyな感じがする……
ただこれ以外に方法がなさそう……
おそらくKeyboard入力のみなら、待つ必要がない
テキスト入力やマウスクリックを組み合わせると、待たないとおかしなことになる
16:17:07 この仮説は多分あってる
addEventListener
でeventを補足する
イメージ
jselement.dispatchEvent(...);
return new Promise(resolve => {
element.addEventListener('event', () => resolve(), {once: true});
};
本当にこんなことで捕捉できるのか?
そもそも、callback関数に非同期関数が渡されていたら元も子もない
編集コマンドを減らす
今回はテロメアの更新をなるべく減らすために何度も insertText
を実行している
これを一度にすべて書き換えるようにすれば待たなくて済む?
いや、キー入力を組み合わせている以上、待つ必要が出てくる
script.jsimport {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.lines[i].text;
// 処理する必要がなければ何もしない
if (!/\s+$/.test(orgText) && !/[^ ]/.test(orgText.replace(/^(\s*).*/, '$1'))) continue;
const indent = scrapbox.Page.lines[i].nodes.unit.tag.length;
const body = orgText.trim();
const text = `${' '.repeat(indent)}${body}`;
console.log('[(WIP)選択範囲の行の空白を整えるUserScript]Tidy the line: %o',
scrapboxDOM.lines.children[i]);
console.log('[(WIP)選択範囲の行の空白を整えるUserScript]%o', {
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));