1Writer 過去タスク検索・追加 v2
作成日: 2025/08/26
このスクリプトは、日付ごとに保存されたノートを検索し、
「時間範囲付きタスク」または「開始時刻付きメモ」 を抽出して、現在のノートに挿入するツールです。
対象:1Writer
入力:選択文字列 or ユーザー入力キーワード
出力:検索結果をリスト表示し、選択した項目を 逆順 で挿入
code:js
const dayDifference = Math.floor((new Date() - new Date('2025-02-01')) / (1000 * 60 * 60 * 24));
const maxDaysToSearch = dayDifference;
const maxTasksToFind = 30;
var cursorPosition = editor.getSelectedRange();
let originalFilePath;
// ユーザーに検索キーワードを入力させる
async function promptUserForKeywords() {
const selectedText = editor.getSelectedText();
if (selectedText) {
return selectedText.split(/\s+/);
} else {
return new Promise((resolve) => {
ui.input("タスク検索", "", "検索キーワードを入力してください(スペースで区切るとAND検索)", "default", (input) => {
resolve(input ? input.split(/\s+/) : null);
});
});
}
}
// 指定された日付のノートを取得
function getNoteForDate(folderPath, dateString) {
return new Promise((resolve) => {
const filePath = ${folderPath}/${dateString}.md;
editor.openFile(filePath, "edit", (success) => {
resolve(success ? editor.getText() : null);
});
});
}
// 曜日の取得(リスト表示用)
function getJapaneseWeekday(dateString) {
const date = new Date(dateString);
if (isNaN(date.getTime())) {
throw new Error("無効な日付形式です。yyyy-MM-dd 形式で入力してください。");
}
}
const timeTaskRegex = /^\s*(?:-\s*\[ xX?\]\s*|-)?\s*(\d{2}:\d{2})-(\d{2}:\d{2}) (.+)$/; const memoRegex = /^\s*(?:-\s*\[ xX?\]\s*|-)?\s*(\d{2}:\d{2}) (.+)$/; // タスクやメモの判定
function isTaskOrMemo(line) {
return timeTaskRegex.test(line) || memoRegex.test(line);
}
// 行の解析(タスクかメモか判別)
function parseLine(line) {
match = line.match(timeTaskRegex);
if (match) {
return { type: "task", startTime: match1, endTime: match2, content: match3.trim(), completed: false }; }
match = line.match(memoRegex);
if (match) {
return { type: "memo", time: match1, content: match2.trim() }; }
return { type: "unknown", content: line.trim() };
}
// キーワードを含むかチェック
function containsKeywords(line, keywords) {
return keywords.every(keyword => line.toLowerCase().includes(keyword.toLowerCase()));
}
// タスク・メモの検索
async function searchTasksAndMemos(keywords, folderPath) {
let foundItems = [];
let currentDate = new Date();
let daysChecked = 0;
while (foundItems.length < maxTasksToFind && daysChecked < maxDaysToSearch) {
const dateString = currentDate.toISOString().split('T')0; const weekdayString = getJapaneseWeekday(dateString);
const note = await getNoteForDate(folderPath, dateString);
if (note) {
const lines = note.split('\n');
for (const line of lines) {
if (isTaskOrMemo(line) && containsKeywords(line, keywords)) {
foundItems.push({ date: dateString, lineContent: line });
if (foundItems.length === maxTasksToFind) break;
}
}
}
currentDate.setDate(currentDate.getDate() - 1);
daysChecked++;
}
// 日付と時刻の降順でソート
foundItems.sort((a, b) => {
const parsedA = parseLine(a.lineContent);
const parsedB = parseLine(b.lineContent);
const dateA = new Date(${a.date} ${parsedA?.time || parsedA?.startTime});
const dateB = new Date(${b.date} ${parsedB?.time || parsedB?.startTime});
return dateB - dateA;
});
return foundItems;
}
// 検索結果をリスト表示
function displayTasksAndMemos(items) {
if (items.length === 0) {
ui.hudError("該当するタスクやメモが見つかりませんでした。");
} else {
const itemList = items.map(item => {
const parsedItem = parseLine(item.lineContent);
let title, subtitle, value;
if (parsedItem) {
if (parsedItem.type === "task") {
title = parsedItem.content;
value = ${parsedItem.content};
subtitle = ${item.date} ${parsedItem.startTime}-${parsedItem.endTime};
} else if (parsedItem.type === "memo") {
title = parsedItem.content;
value = ${parsedItem.content};
subtitle = ${item.date} ${parsedItem.time};
} else {
title = parsedItem.content;
subtitle = ${item.date};
value = ${parsedItem.content};
}
} else {
title = parsedItem.content;
subtitle = ${item.date};
value = line.trim();
}
return { title, subtitle, value };
});
ui.list("検索結果", itemList.map(t => ${t.title}|${t.value}|${t.subtitle}), true, (selectedItems) => {
if (selectedItems) {
// 選択した項目を逆順に並べ替え
const itemsToInsert = selectedItems.reverse().join('\n');
// displayTasksAndMemos関数内の挿入処理を以下に置き換え
editor.openFile(originalFilePath, 'edit', function () {
const insertText = itemsToInsert;
if (selStart !== selEnd) {
// 選択範囲がある場合はその範囲を置き換える
editor.setSelectedRange(selStart, selEnd);
editor.replaceSelection(insertText);
editor.setSelectedRange(selStart + insertText.length);
} else {
// カーソルのみの場合はカーソル位置に挿入
editor.setSelectedRange(selStart);
editor.replaceSelection(insertText);
editor.setSelectedRange(selStart + insertText.length);
}
});
ui.hudSuccess("選択されたアイテムが逆順で挿入されました。");
}
});
}
}
// 元のファイルを再度開く
function reopenOriginalFile() {
if (originalFilePath) {
editor.openFile(originalFilePath, "edit", (success) => {
if (!success) {
ui.hudError("元のファイルを開けませんでした。");
}
});
}
}
// メイン処理
async function main() {
const folderPath = editor.getFolderPath();
const filePath = editor.getFileName();
originalFilePath = folderPath + "/" + filePath;
const keywords = await promptUserForKeywords();
if (!keywords) {
ui.hudError("検索キーワードが入力されませんでした。");
return;
}
const items = await searchTasksAndMemos(keywords, folderPath);
displayTasksAndMemos(items);
reopenOriginalFile();
}
main();