ObsidianMobileが「Obsidianの手入れ」を後押ししてくれる

Obsidianに毎日お世話になっています。
モバイルアプリの開発が進行中で、開発を金銭面においてもサポートするユーザーを対象としてβverが公開となリマした。サポートの金額によってランクがわかれているのですが、一番リーズナブルなサポーターに対しても公開になったタイミングでライセンスを購入。今週のはじめくらいからObsidianのiOSアプリβverを利用中です。
このモバイルアプリがかなりすごくて。
今まではDropboxにデータを入れることでデバイス間での同期をしていましたが、モバイルアプリではiCloudを使う必要があったので、そちらに全て移行し、使っています。

モバイル版のすごいのが、プラグインが動くところ。
Obsidianでは、機能を拡張するために、コアプラグインとサードパーティプラグインをインストールすることができます。
コアプラグインは、公式に提供されているプラグイン。
サードパーティープラグインは、有志で作成されたプラグインで、様々な機能を提供してくれており、いくつかのプラグインをインストールして使っています。
Obsidian上のページを公開する「Obsidian publish」はコアプラグインの中の1つで、publishの契約するとそのプラグインが使えるようになる仕組みになっています。

モバイルアプリでは、全てではないものの、多くのプラグインが、デスクトップアプリと同じように動いてくれるんです。そして、Obsidian publishも動いてくれます。
ということは、publishしているページの修正や、新たなページの公開が、iOSアプリからもできる、ということ。iPhoneでpublishページに編集を加えることができるわけです。素晴らしい。

以前はScrapboxにて公開していたメモたち全てObsidianに移行しているので、それらのメモをpublishの機能を利用して公開していってます。
その際、そのまま公開するのではなく、不要なリンクは削除しつつ、お互いがよりリンクするよう修正を加えながらpublishしていっています。
修正を加えて公開するくらいなら、iPhoneからでもなんとかできるので、というか、ちょっとした時間を利用してちまちまと修正を進めることができるので、モバイルアプリを使いはじめてからpublish作業がかなりはかどっております。
Obsidianには、ブログの下書きもけっこうな数保存されていて、それらに関しては、1つの記事から複数のObsidianのページが生まれたり。
ObsidianPublishとブログには明確な境界線があり、ブログは、他の人にもわかりやすい形で、できるだけ1つの記事で完結することを意識して書いています。なので、1つの記事でいくつかのテーマに触れいることが多い。一方でObsidian publishでは1ページ1テーマを貫こうと意識しているので、ブログをObsidian publishにて公開する場合は、1つの記事を1テーマずつに分割する必要があり、1記事からいくつかのページが生まれることがよく起きる、というわけです。
そういったことを、気軽にiPhoneでできる、というのは、すごく楽しい。
そう、過去のメモやブログの記事を見返して、Obsidian publishにて公開する用に修正していくのは、楽しい作業なんです。それをいつでもiPhoneでできる、というのが、素晴らしい。
楽しいとはいえ、修正を加えるのは簡単なことではなく、それなりにあれこれ考えることになるので、頭はけっこう使います。なんぼでもできる、というわけではありません。ちまちまと進める必要があり、それにはiPhoneがピッタリだなと感じます。

モバイルアプリも使いつつ、どんどんObsidianの手入れをしていければな、と思っております。
よろしければ、本と思考のカードボックスをのぞいてください。

では、お読みいただきありがとうございました。

ObsidianPublishとブログの明確な境界線

これまでいろいろと書いたり試したりしてきました。
ブログから始めて、動画を載せる別ブログを立ち上げたり、Scrapboxに書いたり。
今は、やろうと思えばYouTubeで動画の公開ができたり、ポッドキャストで音声の配信ができたり、Substackでニュースレターを書けたり。
選択肢は色々とありますが、そんなに試してはおらず、ぼくの場合は2つの媒体に絞っています。

どちらも「文章を書いてそれを公開する」場なのですが、この2つには明確な違いがありまして。
「これについてはどっちに書こうかなぁ」と迷うことはありませんし、書き方・記述の仕方も違います。

Obsidianは、1ページ1テーマをつらぬく

Obsidianでは、1ページ1テーマをつらぬく気持ちで書きます。とにかく、1つのことについて書く。
未来の自分は他人という気持ちできちんとした文章で書きつつも、必要以上に説明しすぎることをせず、そこはリンクで別ページとのつながりを作りながら。
いわゆる豆論文を書く気持ちで。
ObsidianのPublishの一つひとつのページは、1ページ1テーマであるが故に、ブログなど他の文章を書く際に、言及・引用がしやすい状態である、と言えます。それらを組み合わせさえすれば文章が書ける、とまでは行かないまでも、1つのテーマについて書かれたものは、取り回しが良く、使いやすいのは間違いありません。
『知的生産の技術 (岩波新書)』(梅棹忠夫)を読んで何年も経ちますが、ようやく1枚1テーマで書く、ということに対する理解が追いついた気持ちです。
また、Obsidianのリンクする機能を使うことで、ページ同士がつながってくれており、それもまた言及・引用のしやすさに一役を買っています。Obsidian上のページをひらけば、それに関連するページが必ず表示されるので、思い起こすことができるから。

ブログは、1つの完成したものを

一方でブログは、はじめから読んでいけば内容を理解でき、それだけで完結することを意識して書いています。
そのためには、文中に出てくる語句の解説を入れる必要があったり、前提となる条件を書いたり、最後にまとめ的なことを書いたりすることが必要になります。
となると、1つの記事にはいくつものテーマが混在することになり、それでようやくはじめから読んでいけば内容を理解できる、読めるものが出来上がる、と思います。
ブログの記事は、それ一つで完結したものになるように心がける、ということです。

以下は、同じ「明日をInboxにする」ということについて書いた、Obsidianとブログの記事。かなり違いが表れていると思います。

おわりに

ブログに投稿するもの、Obsidianでpublishするもの、ブログに投稿してObsidianでもpublishするもの〜その1〜ブログに投稿するもの、Obsidianでpublishするもの、ブログに投稿してObsidianでもpublishするもの〜その2〜にて、その当時のObsidianPublishとブログの分け方を書いていました。
その時にも今回と同じような結論が出ていたのですが(書いたこと完全に忘れてた)、特に今後意識していきたいのは、「Obsidianは、1ページ1テーマをつらぬく」こと。で、ページ同士をリンクさせておくこと。
その気になれば、ブログには基本的には何を書いてもいいと考えているので、完成したものをと思いつつも、そこにはあまり縛られず、気軽に書いていきたい。
なので、ある意味Obsidianにてpublishする方が、そっちにちゃんと書いていく方が、結構難しかったりするかもしれません。
ただ、あまり書く前からハードルをあげすぎるのもよくないので、とりあえず書いて、後からどんどん手入れしていくという方針で、1ページ1テーマをつらぬいていこうと考えています。

では、お読みいただきありがとうございました。

ファイルからリストを作成して、リピートタスクを呼び出す〜1Writerカスタマイズ④〜

「1Writerカスタマイズ」の①〜③にて書いたアクションを作成した段階で、たすくまを使うのをやめ、1Writer(Obsidian)に完全移行しました。

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

Taskuma —TaskChute for iPhone
カテゴリ: 仕事効率化, ライフスタイル

デイリーのテンプレートと、行ごとの削除と移動があれば、一つ一つの行動を記録しながら過ごすことは、けっこう簡単になります。
あとは、予定になかった、つまり、デイリーページ上に書き込まれていないリピートタスクを呼び出すことができれば、終了予定の算出だけがないタスクシュートと呼べるようになるでしょう。
ということで、「リピートタスクの呼び出しできるようにならないか」と考えました。

1Writerのjavascriptアクションの数々には例が載っています。試しに「ui.list()」の例を実行してみると、項目がリスト表示され、そのリストから好きなものをタップすると、そのリストの内容が文中に挿入されるものでした。
これは、使えそうです。
そのコードを書き換え、

  • リピートタスクの一覧が記述されたファイルを開く
  • それをリスト形式に表示する
  • 選択された項目をクリップボードにコピーする

というものにしました。

リピートタスクの呼び出し

//アクションを実行したあと、元のファイルに戻るため、今編集中ファイルのフォルダとファイル名を取得
var folder = editor.getFolderPath();
var editingfile = editor.getFileName();

//リピートタスクを記述しているファイルのファイル名
var openfilename = 'ここに一覧を取得したいファイル名を記述.md'

//リピートタスクの一覧が記述されているファイルを開く。フォルダは、そのファイルが保存されているものを指定してください。
editor.openFile('Dropbox/'+openfilename,'edit',call);

function call(){
    //開いたファイルに記述されているテキストを取得
    var text = editor.getText();
    //改行ごとに配列に格納
    const listData = text.split('\n');
    ui.hudDismiss();
    //配列をリストに
    ui.list('Repeat', listData, false, selectedValues => {
        if (!selectedValues) {
            return;
        }
        const text = selectedValues.join('\n');
        if (editor.isClosed()) {
            editor.newFile(text);
        }else {
            //選択した項目をクリップボードにコピー
            app.setClipboard('\n' + text);
            //はじめに編集中だったファイルを開く
            editor.openFile(folder + '/' + editingfile);
        }
    });
}

アクションを起動した時の動き

アクションを起動するとリストが表示され、そのうち一つを選択すると選択した項目のがクリップボードにコピーされ、元のファイルに戻ってくるので、好きな場所に貼り付けることができます。
リストは、複数選択を可能にもできるので、その場合は
ui.list('Repeat', listData, false, selectedValues
のfalseの部分をtrueに書き換えてください。

まずは、リスト表示したいファイルを作成して、そのファイル名をコード内の「ここに一覧を取得したいファイル名を記述」の部分に書くことでアクションが使えるようになします。
改行を目じるしに、1行1項目でリストに表示するので、リスト表示したいファイルは、そのことを念頭に置いた上で作成していただければと思います。


これまで4回にわたり1Writerの自作アクションについて書いてきました。これにて、「やったことの記録がすこぶる取りやすいリストアプリ」のように、テキストを扱えるようになり、日々、デイリーリストを作成し、1WriterとObsidianで同一のファイルを扱いながら、やったことの記録をとりつつ過ごしています。
まずまず気に入っているので、しばらくはこのまま使い続けようかな、と思います。

では、お読みいただきありがとうございました。

別ファイルに記述されたデイリーテンプレートを呼び出す〜1Writerカスタマイズ③〜

テキストを1行ごとに削除したり移動したりできるようにすることで、「1行ごとのリスト」として扱えるようにしたのが前回までの話。

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

これでかなり便利になり、1行単位での操作ができるようになったので、箇条書きやチェックリストがすごく扱いやすくなりました。
こうなると本格的に「テキストエディタでタスク管理」がしたくなってきます。
しかもぼくは普段から「たすくま」を利用しているので、テキストエディタである1Writerでも、たすくまのように「すべての行動を記録してはいけないものか」、と考えました。

Taskuma —TaskChute for iPhone
カテゴリ: 仕事効率化, ライフスタイル

となると不可欠になってくるのが、リピートタスクを呼び出すこと。
毎日やっていることに関しては、リピートタスクとして登録しておき、日々それを呼び出してタスクリストを作ることで、たすくまのような「やったことの記録がすこぶる取りやすい」テキストエディタが実現します。

1Writerには、「指定したファイルを開く」アクションがあり、それを使うことでテンプレートを呼び出すアクションを作ることができます。
アクションを起動すると、

  • あらかじめ作成したテンプレートファイルを開く
  • 内容をコピーする
  • 元のファイルに戻ってくる

ところまでやってくれるので、あとは任意の場所にペーストするだけ。
準備は、テンプレート用のファイルを作成しておくことと、以下のコードの「ここにテンプレートファイル名を記述」の場所を自分で書き換えること。

テンプレートファイルを開き、コピーし、戻るアクション

d=new Date();
today=d.getFullYear()+zero(d.getMonth()+1)+zero(d.getDate());
yesterday = d.getFullYear()+zero(d.getMonth()+1)+zero(d.getDate()-1);
tomorrow = d.getFullYear()+zero(d.getMonth()+1)+zero(d.getDate()+1);
oneyearsago = (d.getFullYear()-1)+zero(d.getMonth()+1)+zero(d.getDate());
twoyearsago = (d.getFullYear()-2)+zero(d.getMonth()+1)+zero(d.getDate());
threeyearsago = (d.getFullYear()-3)+zero(d.getMonth()+1)+zero(d.getDate());
var dayOfWeek = d.getDay(); // 曜日(数値)
var weekday = [ "(Sun)", "(Mon)", "(Tue)", "(Wed)", "(Thu)", "(Fri)", "(Sat)" ][dayOfWeek]; // 曜日(日本語表記)

var folder = editor.getFolderPath();
var editingfile = editor.getFileName();

var openfilename = "ここにテンプレートファイル名を記述.md";

editor.openFile('Dropbox/Days/'+openfilename,'edit',call); //ファイル名の前には、フォルダを指定。ここでは、「Dropbox」フォルダ内の、「Days」フォルダを指定している。

function call(){
    var text = editor.getText();
    var text = text.replace(/{{today}}/g,today).replace(/{{tomorrow}}/g,tomorrow).replace(/{{yesterday}}/g,yesterday).replace(/{{oneyearsago}}/g,oneyearsago).replace(/{{twoyearsago}}/g,twoyearsago).replace(/{{threeyearsago}}/g,threeyearsago).replace(/{{weekday}}/g,weekday);
    app.setClipboard(text);
    editor.openFile(folder + '/' + editingfile);
}

function zero(s){return ("0"+s).substr(-2)}

コード内に、{{today}}や{{yesterday}}という記述があることにお気づきでしょうか。
これは、テンプレートのテキスト内の{{today}}と書かれている部分を、今日の日付に変換するための記述です。

このように書かれている場合、アクションを起動してテンプレートの内容を取得し、ペーストすると

こうなります(スクショは4月15日に撮影)。

{{oneyearsago}}や{{twoyearsago}}は、1年前、2年前の同じ月日。Obsidianにて連用手帳を実践していて、その際1年前や2年前のページを見返したいので、テンプレートに組み込んでいます。

テンプレートは1つのmdファイルなので、編集が簡単。
ただ、たすくまのような複雑なリピート設定はできないので、そこは今後工夫する必要がありそうです。


これで、日々のリピートは簡単に呼び出し可能になり、かなり詳細な記録を取ることができるようになりました。
こうなってくると、1日の計画を立てるときには書いていなかったタスクも、リピートに登録されているのであれば、リピート一覧から選択し、挿入できるようにしたくなってきます。
1Writerには、配列のデータから「リスト」を作成するアクションもありまして。次はそのあたりについて書いていきます。

カット・ペーストを可能にして、ダイナミックな移動を可能に〜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 = range[1];

var cuttext = app.getClipboard();

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

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

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

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 cutlines = [];
for(let i = 0; i < selecte-selects+1; i++){
cutlines.push(linetexts[selects + i])
}
var cuttext = cutlines.join('\n');
app.setClipboard('\n' + cuttext);

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

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

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

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

テキストを「1行ごとのリスト」ととらえ、削除と移動を可能に〜1Writerカスタマイズ①〜

タスク管理アプリの多くは、長年使っている「たすくま」もそうですが「リスト」の形式をとっています。

1タスク1リスト(1タスク1行)の表示で、タスクがダァーッと並んでいる形式。
確かにこの形式は、タスク管理をする上で扱いやすいなぁと感じます。
リスト形式であれば、

  • 行の削除ができる
  • 行の順番の入れ替えができる

という機能を備えており、それがタスクを扱いやすくしてくれている要因ではないか、ということで、「やったことの記録がすこぶる取りやすいリストアプリ」のように、テキストを扱えるようにしたいな、という思いがわいたわけでした。
「アウトライナー」をタスク管理に利用している方も多くいられると思うのですが、それは、アウトライナーは行の削除と順番の入れ替えが容易であるというのも大いに関係していると感じます。

ぼくは、タスク管理に今はObsidianを使っているのですが、iPhoneでは、「1Writer」というアプリを使っています。

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

1Writerはjavascriptを扱えますので、テキストを加工することができます。そこで、1Writerのjavascript機能を使って、

  • 行の削除ができる
  • 行の順番の入れ替えができる

という機能を実装しようと考えました。
そうして作成したのが、以下の3つのアクション。

  • カーソル(選択)行を削除
  • カーソル(選択)行を上へ移動
  • カーソル(選択)行を下へ移動

カーソル(選択)行を削除

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 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 = 0;
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');

if ( selects == 0 ){
    editor.replaceTextInRange(0, 0, cuttext + '\n');
    editor.setSelectedRange(cuttext.length,cuttext.length);
}else if( selects == 1 ){
    editor.replaceTextInRange(0, 0, cuttext + '\n');
    editor.setSelectedRange(s - linetexts[0].length-1,e-linetexts[0].length-1);
}else{
    var before = 0;
    for(let i=0; i < selects-1;i++){
        before = before + linetexts[i].length + 1;
    }
    editor.replaceTextInRange(before-1, before-1, '\n'+cuttext)
    editor.setSelectedRange(s - linetexts[selects-1].length-1,e-linetexts[selects-1].length-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 = 0;
for(let i=0; i < selects;i++){
    before = before + linetexts[i].length + 1;
}

if ( selecte == linetexts.length-1 ){

}else{

    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');
    var before = 0;
    for(let i=0; i < selecte+1;i++){
        before = before + linetexts[i].length + 1;
    }
    editor.replaceTextInRange(before-1+linetexts[selecte+1].length-cuttext.length, before-1+linetexts[selecte+1].length-cuttext.length, '\n'+cuttext);
    editor.setSelectedRange(s + linetexts[selecte+1].length+1,e+linetexts[selecte+1].length+1);
}

おそらくあんまりキレイなコードではないと思うのですが、、、便利なのでよかったら使ってみてください。

で、これらによって、テキストを行ごとに削除したり移動したりが簡単になったわけです。でも、だいぶと便利になったのに、さらに欲が出てきまして。
もっとダイナミックに移動させたいようになってきました。

つづく

ObsidianPublishは、今のページを起点としてつながりのある他のページへ

2回の記事を通して、ObsidianのPublish機能をどう使うのか、ブログとどう使い分けていくのかについて書きました。
今回は、Obsidianでpublishしたものについて。


上のリンク先は「choiyakiノート」のトップページにあたるもので、そこにはズラズラとタグが並んでいます。
これは、各ページにつけているタグの一覧。興味があるものをポチッと押していただければ、Obsidianにてpublishしているページの中で、押したタグがつけられているページが一覧で表示されるようになっています。
Obsidianでは、ページ同士をリンクさせることと、それぞれのページにタグをつけることができます。
Scrapboxでは、リンクとタグは表記上の違いだけで、役割としては同じなのですが、Obsidianは違う役割を果たします。

  • タグを押すと、そのタグがつけられているページを一覧できる
  • リンクを押すと、リンク先のページに移動できる

なので、Obsidianでは、リンクとタグを使い分けることができる、ということになります。

Obsidianを使い始めた当初は、というか、publishの機能を使い始める前までは、タグの使い道がわからず、Scrapboxみたいにリンクだけでいいじゃないかということでリンクしか使っていませんでした。けど、publishによって、既存のページを修正して公開していくようになり、タグの必要性を感じるようになりました。

Obsidianのpublishでは、今開いているページに言及しているページ一覧の「Backlink」と、リンクしているページをグラフ化した「Graph」が表示されます。
どちらにおいても、今表示しているページと、リンクでつながっている「一つ先」のページしか表示されません。
例えば、表示ページの文章内に「Obsidian」というリンクがあったとします。
今表示しているページと「Obsidian」とはつながっており、「Obsidian」ページはBacklinkあるいはGraphに表示されます。けれども、Obsidianとつながっている他のページは、どこにも表示されることはありません。
なので、Obsidianとリンクされている他のページがみたければ、Obsidianページへのリンクを踏む必要があります。
ここで問題になるのが、Obsidianというページが存在するか否か。
存在しなければObsidianページには移動することができず、移動できないのでObsidianページとつながっている他のページを見ることができないことになります。
これでは、タグとしてリンクを機能させることができません。タグというのは、同じタグがついているページが一覧で表示される必要があるから。
というわけで、Obsidianのpublish機能においては、タグが必要になるわけです。

(Scrapboxにおいてはリンクとタグが表記の違いだけであるのは、つながっているページの「二つ先」まで一覧できるからであり、そういうところまで考え尽くされているScrapboxはすごいなぁ、と感じます)

  1. 今開いているページに言及しているページは、「Backlink」として下に一覧表示される
  2. 今開いているページが言及している他のページは、文中でリンクになっていて飛ぶことができる
  3. 今開いているページに言及しているページと、今開いているページが言及しているページの両方が、Graphには表示される
  4. 同一テーマについて書かれているページにはそのタグがつけられているので、一覧表示させることができる

他の人が読むことを考えると、上記4つの機能によって、テーマを絞って一覧表示したり、文中のリンクをたどってもらったり、Graphの中の気になるページを訪れてもらったりしてもらえればな、と思います。

Obsidian publishによって公開されるWebページは、ブログのように最新記事が上に並ぶのではなく、記事名による五十音順で並びます。
なので、更新順に次々見ていくということはおそらく想定されておらず、リンクやタグをたどって他のページを見ていくことを基本としているように感じます。
そのページの移動の仕方は、まさに実際にObsidianを使っている人のような移動の仕方を基本としているということだと思います。
publishしているものは、ぼくの個人的な着想メモの数々、読んだ本に対する感想の数々。ただのメモと感想なので、publishする効果はどれくらいあるのかわかりませんが、書かれれていることがちょっとでも思考の刺激になってくれればいいな、と思います。
少なからず、ぼくにとっては興味深い事柄を集めているので。

では、お読みいただきありがとうございました。

ブログに投稿するもの、Obsidianでpublishするもの、ブログに投稿してObsidianでもpublishするもの〜その2〜

にて、今課題としていることとして、

  • ブログとObsidian publishをどう使い分けるのか
  • 過去のブログの下書きがObsidianにはあるけれども、それをpublishするか否か

を挙げました。そのうち、「ブログとObsidian publishをどう使い分けるのか」については、

  • Scrapbox「book scrapbook」で公開していたようなものをpublishしていく
  • 1ページ1テーマで書き、関連するページ同士を直接つなげていく
  • 1ページ1テーマを保つために、ブログ記事の下書きをそのままObsidianでpublishはしない
    • 1ページ1テーマに加工してからpublishする

という方針でいこう、ということになりました。
今回は、過去のブログ記事の下書きはどうするかについて。


「その1」でも述べたように、ブログ記事は、1記事1テーマになっていないか、あるいはテーマそのものを持っていないかのどちらかであるものがほとんどです。ブログの下書きも同じ。
であれば、下書きをそのままpublishするのは、Obsidianのpublishは1ページ1テーマでいく、という方針にはそぐわないことになります。
ただ、いくつかの内容を含むページがあってもいいかも、と考えたり。各メモの、「ハブ」の役割をするようなページになってくれることを期待して。
とはいえ全ての過去記事の下書きがそんな役割を担えるか、というとそうではないので、テーマを持たない雑記のような記事についてはpublishをせず、publishするものに関しては、基本的には1ページ1テーマにバラす。いろいろなものに言及しているようなものに関しては、ハブの役割となることを期待して1ページ複数テーマを持つものもpublishする、という方針でいこうかな、と思います。
とにかく、Obsidianのpublishにおいては、各ページがリンクでつながっており、(基本的には)1ページ1テーマであるが故に、そのページを読むだけでは全容を把握できないとしても、リンクを辿っていくつかのページを読めばだいたいのことはわかる、みたいな状態にしたいな、と考えています。

また、Obsidianでは、リンクとタグの使い分ける方がいいだろう、とも考えています。
リンクは「このページと関連するページはどれか?」を記述するものであり、ページ同士の結びつきを表すので、書き手が、今開いているページと関連する他のページを提案することになります。
タグは「このページは何に関することが書かれているか?」を表すものであり、そのタグに関することが書かれているページを串刺しする役割を担います。
明確に役割が違うのですから、ちゃんと使い分けていく、というのも、Obsidian publishを利用して公開していく上での基本方針となります。


Obsidian上には、ちょっとずつページが増えていってます。その中のプライベートなものを除いた全ては、公開してしまおうと考えています。
各ページが他のページとのいくつものつながりを持ち、書き直したり書き加えたりすることで日々刻々と変化していく。
そういったものにしていければなーと考えています。

では、お読みいただきありがとうございました。

ブログに投稿するもの、Obsidianでpublishするもの、ブログに投稿してObsidianでもpublishするもの〜その1〜

Obsidianのpublishを利用して、これまでのメモをObsidianでどんどん公開していってる。

で、最近考えているのが、ブログとObsidian publishをどう使い分けるのか、というところ。
また、過去のブログの下書きがObsidianにはあるけれども、それをpublishするか否か、というところ。


まず、「ブログとObsidian publishをどう使い分けるのか」について考えたこと。
Obsidianのpubloshで何を公開していくかというと、Scrapbox「book scrapbook」で公開していたようなものをpublishしていこうかな、と考えてる。
Scrapboxでは、

  • 読んだ本について
  • 考えたことをまとめたことについて
  • ブログ記事の下書き

を公開していた。自分が読んだこと、考えたことについて書いたことのほぼ全て。
そのうちのブログの下書き以外はObsidian publishでも同じように公開しようかな、と決めたけど、ブログの下書きについてはどうするか。とりあえず、Scrapboxの時のように下書きをそのまま公開するのはやめようと思った。
じゃあどうするか。
考えたのは、Obsidian publishでObsidianの中のどのページを公開していこうと思っているか、ということ。
デイリーページなどタスク管理に使っている個人的なページは公開する気はないけれども、それ以外の、考えたことややってみたことなんかは積極的に公開していくのがいいのでは、と思っている。
で、それらのページの作成の方法を、Scrapboxで公開してた時とはちょっと変えていこうと思っていて。

Scrapboxでは、単語のリンクを介して繋げていくのが多かった。
例えば、「Obsidian」や「アウトライナー」などをブラケット「[]」で囲んでリンクにし、単語をリンクすることでページ同士をその単語を介してつなげていた。単語のリンクは、タグ的な役割を果たし、同じタグがついているページ一覧が下に表示されるイメージ。
Image

Obsidianではその方法ではなく、ページ同士をつなげていこうかな、と。
1ページ1テーマで書き、関連するものを直接つなげる。しばらくはこれまでのメモを見返し、書き換えつつ、書き足しつつ、関連するページ同士をつなげつつ。
で、これまでScrapboxでタグ的につけていたリンクに関しては、Obsidian上ではリンクという形ではなく、タグをつけよう、と。
Scrapboxではタグとリンクの表記以外の区別はなかったけど、Obdisianでは二つは役割が違う。タグをクリックすればそのタグがつけられているページ一覧を見れるという機能になっているので。Obsidianでは、リンクとタグの使い分ける方針を取り、リンクはページ同士を直接つなぐ。
で、1ページ1テーマを保つために、ブログ記事の下書きをそのままObsidianでpublishはしないでおこうと思う。
ブログの記事は、1記事で完結したものにするために、色々と説明を加えたり、Obsidian publishよりも他の人が読むことをより意識したものになり、1ページ1テーマではなく、いくつも盛り込むことが多い。
また、雑記的なものはテーマを持たないことがほとんど。
なので、ブログ記事は1ページ1テーマではないことか多いので、Obsidianでpublishするときには書き換えたりページを分けたりして、1ページ1テーマに加工してからpublishしようと考え中。ブログとObsidian publishは、全然違ったものにしていく予定。


「過去のブログの下書きがObsidianにはあるけれども、それをpublishするか否か」については、、、長くなってきたのでまた次回ということで。

2021年現在の、日々の記録あれこれの利用の仕方

2021年現在の、日々の記録あれこれにて、現在どういったものを日々の記録として残していっているのかについて述べました。今回は、その残しているものをどうしているのか、についてです。


デイリーページ

日々「デイリーページ」をObsidian上に作成し、そのページを開きっぱなしにして日中過ごして何かあれば書き込んだり、タスクを書き出してそれに倣って行動しているのですが、そのデイリーページのログは、来年の同じ日付の日に見返されることになります。
「連用手帳」という形式をとっており、日々のデイリーページには1年前・2年前の同じ日付の日を埋め込んでおり、プレビューによって毎日見返しているからです(Obsidianにて連用手帳)。
1年や2年前はまだObsidianを使っていませんでしたが、Scrapboxにてデイリーページを作成して過ごしていた時期があるので、それをObsidianにインポートし、毎日見返しています。
なので、今日かいたページは、確実に1年後、見返すこととなります。
去年や一昨年の1日を見返し、今日を過ごす参考にする、という感じです。あるいは、そこに書かれているメモを読み返し、何かしら書き加えたくなることもあったり、です。

たすくまの記録

Obsidian以外に、「たすくま」にて行動を記録していますが、こちらはほぼ見返されません。
ごくごくたまーに、「あの日は何をしていたのだ?」ということを知りたくなることがあるので、そういう時には過去の記録を振り返りますが、その程度。
デイリーページのように確実に見返されることが決まっている、というわけではなく、ごくごくたまーに特定の日の記録を見返すだけです。

日記

日記はEvernoteに連用日記を書いていっており、デイリーページと同様、今日かいた日記は来年の同じ日に見返されることになります。
2015年から書き加え続けているので、今は毎日過去5年分の日記を見返しています。
日記は読み返すだけで楽しいですし、結構「あぁこの時期にこれをやってるんか」と、今年を過ごす上で参考になることも多い。
それもあって、手帳も連用形式にしよう、となったわけですが。
まぁでも、日記は読み返すだけで面白いので、書くのは多少面倒に思いつつも、毎日欠かさず書き続けています。

個別にページを与えてログを取っているものたち

自分の好きなものに関しては個別にページを与え、記録をとっていってるわけですが、これらはあまり見返しません。
お酒の記録であれば、時々「これって飲んだことあるっけ?」と検索をかけてみたり、映画の記録は友達と面白かった映画を共有するときに振り返ってみるくらい。
コーヒー豆焙煎の記録は、同じ豆を焙煎するときに少し振り返り、次の焙煎はどうするか考えるときに。
読んだ本や読書メモも、とってはいるもののさほど見返すことはありません。以前は読んだ本についてブログで書いたりするときに読み返していましたが、今はそれがやりたいのになかなかできていないという現状です。


デイリーページと日記は、1年をサイクルとして必ず見返します。
そのほかはたまに検索をかけて見返したり、といったところでしょうか。

ぼくというものはどうやら「定期的に見返すぞ」と思っても確実にちゃんと見返してはくれないようなので、連用形式で1年後勝手に目に入るようにしています。
意図的に見返して使っていきたいものに関しては、勝手に目に入るような状況を作り出し、活用している、という感じです。

では、お読みいただきありがとうございました。