カット・ペーストを可能にして、ダイナミックな移動を可能に〜1Writerカスタマイズ②〜

Obsidianが日々の相棒となってくれており、iPhoneでは「1Writer」というアプリを使ってObsidianで扱っているファイルと同じファイルを編集できるようにしています。

1Writer – Markdown Text Editor
カテゴリ: 仕事効率化, ユーティリティ

そして、リストアプリのようにテキストを扱えるようにするにはなにが必要かを考え、

  • 行ごとの削除
  • 行ごとの移動

の2つが欠かせないということで、

にて、削除と上下の移動は可能にすることができました。が、もっとダイナミックに移動させたいという願望が出てきました。


リストアプリでは、長押しや「編集」ボタンを押すことで、項目のドラッグ&ドロップが可能になるものが多いと思います。で、これが結構大事でして。
タスクを、実行しようと思っている順に並べているのですが、実際はそれ通りにいくことはあんまりありません。時にはリストの項目を大きく移動させたい時が出てきます。そんな時に重宝するのがドラッグ&ドロップの機能なわけです。
でもこれをテキストエディタに求めるのは、つまり1行ごとにドラッグ&ドロップによる移動ができるようにするのは、なかなかに難しい。
でもやっぱり、大きく移動させる機能は欲しい。

ということで、「カット」と「ペースト」を気軽にできるようにすることで、ドラッグ&ドロップのような動きを可能にしよう、と考えました。

  • カーソル(選択)行をカット
  • クリップボードの内容をペースト

という2つの機能があれば、リストの項目を大きく動かしたい時は、動かしたい項目をカットして動かしてきたかった場所でペーストすることができるので、ドラッグ&ドロップ機能の代わりができるだろう、と。
実際に動きを見てみましょう。

移動させたい行にカーソルを持っていく。あるいは、複数行に渡る場合は範囲選択をしておき、カット。するとその行がカットされる。移動したい先にカーソルを持っていって、ペーストボタンを押せばそこに移動完了です。
この機能で、さらにテキストエディタの内容を1行ごとに操作することが、以前よりやりやすくなりました。

カーソル(選択)行をカット

var text = editor.getText();
var linetexts = text.split('\n');
const range = editor.getSelectedRange();
var s = range[0];
var e = range[1];
var selects;
var selecte;
var linecount = 0;
var selectrange;
for (let i = 0; i < linetexts.length; i++){
    if ( s <
        linecount + linetexts[i].length +1){
        selects = i;
        selectrange = linecount - 1;
        break;
    }else{
        linecount += linetexts[i].length + 1;
    }
}
linecount = 0;
for (let i = 0; i < linetexts.length; i++){
if ( e <
    linecount + linetexts[i].length +1){
        selecte = i;
        break;
    }else{
        linecount += linetexts[i].length + 1;
    }
}

var before = -1;
for(let i=0; i < selects;i++){
    before = before + linetexts[i].length + 1;
}
var after = before;
if(before < 0){
    before = 0;
}
for(let i=selects; i < selecte+1;i++){
    after = after + linetexts[i].length + 1;
}
editor.replaceTextInRange(before, after, "")
var cutlines = [];
for(let i = 0; i < selecte-selects+1; i++){
    cutlines.push(linetexts[selects + i])
}
var cuttext = cutlines.join('\n');
app.setClipboard('\n' + cuttext);

クリップボードの内容をペースト

“`
var text = editor.getText();
var linetexts = text.split('\n');
const range = editor.getSelectedRange();
var s = range[0];
var e = range1;

var cuttext = app.getClipboard();

editor.replaceTextInRange(s,e,cuttext);
“`

テキストエディタ上のテキストを1行ごとに扱うことができるようになることが、iPhone上ではこんなに快適になるものなんだな、と驚いています。
ついでに、カーソル行をコピーするアクションも作りました。

カーソル(選択)行をコピー

var text = editor.getText();<br /> var linetexts = text.split('\n');<br /> const range = editor.getSelectedRange();<br /> var s = range[0];<br /> var e = range[1];<br /> var selects;<br /> var selecte;<br /> var linecount = 0;<br /> var selectrange;<br /> for (let i = 0; i < linetexts.length; i++){<br /> if ( s <<br /> linecount + linetexts[i].length +1){<br /> selects = i;<br /> selectrange = linecount - 1;<br /> break;<br /> }else{<br /> linecount += linetexts[i].length + 1;<br /> }<br /> }<br /> linecount = 0;<br /> for (let i = 0; i < linetexts.length; i++){<br /> if ( e <<br /> linecount + linetexts[i].length +1){<br /> selecte = i;<br /> break;<br /> }else{<br /> linecount += linetexts[i].length + 1;<br /> }<br /> }<br /> var cutlines = [];<br /> for(let i = 0; i < selecte-selects+1; i++){<br /> cutlines.push(linetexts[selects + i])<br /> }<br /> var cuttext = cutlines.join('\n');<br /> app.setClipboard('\n' + cuttext);

  • カーソル(選択)行を削除
  • カーソル(選択)行を上へ移動
  • カーソル(選択)行を下へ移動
  • カーソル(選択)行をカット
  • カーソル(選択)行をコピー
  • クリップボードの内容をペースト

以上のアクションをカスタムキーボードに設定し、毎日使っています。

とても快適になったわけですが、1Writerで、たすくまのように「全ての行動を記録する」となると、行ごとの操作に加え、リピートタスクを設定し、それを簡単に呼び出せる仕組みが必要になってきます。全ての行動を記録する際、毎日やっていることに関しては、。毎日入力するよりもテンプレートで引っ張って来る方が明らかに手間が省けます。ましてや、たすくまのタスク数は大体40程度。それらを毎日入力するのは現実的ではありません。

そこで、1Writerにも、テンプレートを引っ張ってきてエディタ部分に入力し、たくさんのタスク名をいちいち入力しなくて住むようになりました。が、これはまた別の機会に。

See Also