カーソル行から特定の文字列を抽出するテスト
カーソルがある行から、
外部リンクに相当する文字列を抽出して表示するテスト
仕様
[/
と ]
で囲まれた部分を括弧付きで表示する
抽出する文字列の性質
最初 [/
で始まる
最後が ]
で終わる
カーソルを含むもののみ抽出
抽出方法
正規表現だけだと無理そう
カーソルと比べて、どの位置にあるのかがわからない
こういうalgorithmだとどうだ?
1. 前から順番に [
/
と並んでいるspanを探す
この値とcursorのleftとが一致する
3. カーソルのleftに一番近いものを探す
この時点でどれもカーソルのleftより大きかったら補完しない
先に正規表現で大雑把に探したほうが良さそう
/\[\/[^\s!"#%&'()\*\+,\-\.\/\{\|\}<>_~]+[^\]]*\]/
で探せる?
探したら、その文字列に一致する文字列の先頭文字のclassを取得する
正規表現がマッチした位置を取得できれば、そこからclass名を逆算できる
あとは、カーソルのleftと比較し、判定が通れば補完を開始する
条件
[
の内側でいいや。
インデントも入れる(正規表現を使うのでどうせ引っかからない)
必要な関数
正規表現がマッチした文字の先頭からの位置を取得する関数
対象行の c-x
の番号
インデント込みの文字の位置を取得できるので、この位置を c-x
にそのまま当てはめられる
script.jsclass suggestWindow{
constructor() {
this.box = document.createElement('div');
this.box.classList.add('form-group');
this.box.style.position = 'absolute';
this.container = document.createElement('div');
this.container.classList.add('dropdown');
this.box.appendChild(this.container);
this.items = document.createElement('ul');
this.items.classList.add('dropdown-menu');
this.items.style.whiteSpace='nowrap'; // 文字列を折り返さない
this.container.appendChild(this.items);
this.editor = document.getElementById('editor');
this.editor.appendChild(this.box);
}
// 入力補完window を開く
open() {
this.container.classList.add('open');
}
close() {
this.container.classList.remove('open');
}
// 入力候補に表示するアイテムを更新する
updateItems(items) {
const newList = document.createElement('ul');
newList.classList.add('dropdown-menu');
newList.style.whiteSpace='nowrap';
for(const item of items) {
let listItem = document.createElement('li');
listItem.classList.add('dropdown-item');
listItem.innerHTML = item;
newList.appendChild(listItem)
}
this.items.replaceWith(newList);
this.items = newList; // これを書かないと置き換えが完了しない
}
}
const suggestion=new suggestWindow();
suggestion.editor.addEventListener('keyup',() => {
let text= 'No line is focused.'
if(suggestion.editor.getElementsByClassName('cursor-line').length!=0){
let line = suggestion.editor.getElementsByClassName('cursor-line')[0];
text = line.textContent;
}
//if(!/\[\//.test(text)) {
// suggestion.close();
// return;
//}
suggestion.open();
let list = [text,
...[...text.matchAll(/\[\/[^\s!"#%&'()\*\+,\-\.\/\{\|\}<>_~\]]+[^\]]*\]/g)]
.map(match => `Found ${match[0]} start=${match.index} end=${match.index + match[0].length -1}.`)];
正規表現テスト
ちゃんと別々にマッチする
斜体はマッチしない
script.js
suggestion.updateItems(list);
const cursor = document.getElementById('text-input');
// 入力補完windowの位置を更新する
suggestion.box.style.top = `${parseInt(cursor.style.top) + parseInt(cursor.style.height) + 3}px`;
suggestion.box.style.left = `${parseInt(cursor.style.left)}px`;
});