generated at
external-completion-3
外部プロジェクトのリンクアイコン記法をはじめとしたいくつかの拡張Scrapbox入力補完を導入するUserScriptです。

特徴
予め指定した外部プロジェクトのリンクを入力補完する
補完候補をdrag & dropでscrapbox内に挿入したり、 Ctrl + i でアイコン記法として入力する事もできる
予め指定した外部プロジェクトのアイコンページを入力補完する
mobile端末でも動く
読み込みが高速
local storageに予めリンク情報をcacheしておくため、毎回fetchする必要がなくなる
その他、/takker/external-completion-2のバグを潰してあります
入力確定時に文字がバグる問題
まだ微妙におかしい
非常に長い検索語句を入れるとCPU使用率が100%のまま下がらなくなる問題
操作説明

known issues
Searching... が2つ出てくる時がある
done候補をクリックできない
原因
候補をクリックする
行が編集モードでなくなる
.cursor の位置と行の位置とがずれる
scrapbox-cursor-position-2で文字を検出できなくなる
補完が終了したとexternal-completion-3/completionObserver-2が誤認識する
onend が実行され、windowが閉じられる
対策
#text-input にfocusが残っている状態の場合はwindowを閉じないようにする
body にfocusが移ってしまうのでアウト
windowを閉じる条件を限定する
external-completion-3/completionObserver-2の終了条件を、実際に文字列が変更されたときだけに限定する
これにしてみた
うまくいったみたい?
done高速に編集しているとwindowが残るバグが発生する
多分windowを表示する座標を計算するためのDOMが消えた場合に発生するんだと思う
座標計算を検索の前にやれば解決する?
表示位置は正しくなったが、windowが消えなくなってしまった
external-completion-3#606e25111280f00000de7ee9に終了処理を挟んで解決させた
isRunning: true のまま、何も計算されないときがある
原因も再現方法も不明
検索出来ているのにUIに反映されないことがある
リロードされるまで一切反映されない
おそらくフラグ処理をミスっている
[] の中を抜けて補完が終了しているにも関わらず、windowが表示されたままになる
コードが汚い
ごめんなさいtakker
ファイル数が多すぎ
ごめんなさいtakker
今自分でも/takkerに書き写しているけど、とても面倒だな

interfaceについて、2つ方針がある
補完の種類ごとにinstanceを分ける
一つのinstanceで複数の補完を扱う

code

test code
js
import('/api/code/programming-notes/external-completion-3/sample.js') .then(({execute}) => execute());

dependencies
sample.js
import {ExternalCompletion} from '../external-completion-3%2Fcore/script.js'; import {setting} from '../external-completion-3%2Fsource/script.js'; import {projects} from './project-list.js'; import {scrapboxDOM} from '../scrapbox-dom-accessor/script.js'; import {js2vim} from '../JSのkeyをVim_key_codeに変換するscript/script.js'; export function execute() { const completion = new ExternalCompletion(); // 好きなショートカットキー登録方法を使う const config = [ {key: '<S-Tab>', command: () => completion.selectPrev()}, {key: '<Tab>', command: () => completion.selectNext(),}, {key: '<C-Space>', command: () => completion.start(), oncompleting: false}, {key: '<CR>', command: () => completion.confirm(),}, {key: '<C-i>', command: () => completion.confirm({mode: 'icon'}),}, ]; scrapboxDOM.editor.addEventListener('keydown', e => { if (!e.isTrusted) return; // programで生成したkeyboard eventは無視する if (e.isComposing) return; const key = js2vim(e); const pair = config.find(pair => pair.key === key); if (!pair) return; if (!completion.completing) { completion.end(); return; } e.preventDefault(); e.stopPropagation(); pair.command(); }); // 補完ソースを選ぶ completion.push( setting(projects), setting(['icons', 'icons2', 'emoji'], { trigger: /^\[:/, icon: true, limit: 10, verbose: true, }) ); }

project-list.js
export const projects = [ 'hub', 'shokai', 'nishio', 'masui', 'rakusai', 'yuiseki', 'june29', 'villagepump', 'rashitamemo', 'thinkandcreateteck', 'customize', 'scrapboxlab', 'scrasobox', 'foldrr', 'scrapbox-drinkup', 'motoso', 'public-mrsekut', 'mrsekut-p', 'marshmallow-rm', 'wkpmm', 'sushitecture', 'nwtgck', 'dojineko', 'kadoyau', 'inteltank', 'sta', 'kn1cht', 'miyamonz', 'rmaruon', 'MISONLN41', 'yuta0801', 'choiyakiBox', 'choiyaki-hondana', 'spud-oimo', 'keroxp', 'aioilight', 'programming-notes', ];