【脚本】更聪明地打开今日笔记

题外话:这篇帖子也可以用来学习:
如何查询当前开启的笔记、如何在新标签页中打开指定笔记、如何切换标签页

正文

我使用 DailyNote 的频率很高——今天的任务啊、时间记录啊……都在上面——所以需要频繁地打开「今天的 DailyNote」。

虽然 Obsidian 原生提供了这个命令,PeriodicNote 也提供了 Open daily note:

但都不太智能。

为什么这么说呢?

我想要实现的需求是:

  1. 用快捷键在新标签页中打开今日笔记
  2. 如果当前已经开着了,就直接切换到对应的标签页

所以只能自己实现了。

最后做出来的脚本:

```js
<%*
// 获取当前所有的标签页(范围未知)
const tabs = app.workspace.activeTabGroup;
// 定义今日笔记的格式
const DailyNoteName = tp.date.now('YYYY-MM-DD');
let dailyNoteTab = null;

for (const tab of tabs.children) {
    if (tab.view.file.basename && tab.view.file.basename === DailyNoteName) {
        dailyNoteTab = tab;
        break;
    }
}

if (dailyNoteTab) {
    // 如果已经打开了,切换到对应页面
    app.workspace.setActiveLeaf(dailyNoteTab, { focus: true });
} else {
    // 如果没有打开,就打开(或新建)
    const file = tp.file.find_tfile(DailyNoteName);
    if (file) {
        app.workspace.getLeaf("tab").openFile(file);
    } else {
        new Notice(`未找到 ${DailyNoteName}`);
    }
}
%>
```

运行这个脚本就可以实现更聪明地打开今日笔记。

通用说明:关于 TP 脚本的用法

TP 脚本其实就是一个单独的 markdown 笔记文件,配合 Templater 插件可以进行调用。

首先安装 Templater 插件:

image

然后在 Templater 插件的设置里选择一个文件夹,作为模板文件夹
image

再在这个文件夹里新建一个笔记,粘贴主贴里的 TP 脚本内容。
(从 <% 开始到 %> 结束的部分)

创建完成后,在插件设置里点击这个按钮:

image

选择刚才新建的笔记,就能把它注册成命令。

然后打开你的命令面板(默认是 Ctrl+P )就能看到 Templater: Insert 你新建的笔记.md ,运行这个命令就是执行脚本。


也可以注册一个快捷键方便调用:

自动创建

如果你还想更强一点,实现真正的「随时调用」——
也就是说,如果今天的 DailyNote 还没创建过,就调用模板自动创建。

那么就用下面这个版本:

```js
<%*
// 获取当前所有的标签页
const tabs = app.workspace.activeTabGroup;
// 定义今日笔记的格式
const DailyNoteName = tp.date.now('YYYY-MM-DD');
let dailyNoteTab = null;

// 今日笔记的文件夹,文件还不存在的话,创建一个
const DailyNoteFolder = "PeriodicNote/Daily/"+tp.date.now("YYYY-MM");
// 今日笔记的模板文件名称
const DailyNoteTemplate = "DailyNote模板";

for (const tab of tabs.children) {
    if (tab.view.file.basename && tab.view.file.basename === DailyNoteName) {
        dailyNoteTab = tab;
        break;
    }
}

if (dailyNoteTab) {
    // 如果已经打开了,切换到对应页面
    app.workspace.setActiveLeaf(dailyNoteTab, { focus: true });
} else {
    // 如果没有打开,就打开(或新建)
    const file = tp.file.find_tfile(DailyNoteName);
    if (file) {
        app.workspace.getLeaf("tab").openFile(file);
    } else {
        const tpFolder = app.vault.getAbstractFileByPath(DailyNoteFolder);

        const tpFile = tp.file.find_tfile(DailyNoteTemplate);

        console.log(`创建了新的 DailyNote ${DailyNoteName}`);
        await tp.file.create_new(tpFile, DailyNoteName, true, tpFolder);
    }
}
%>
```

其他的方法

还可以用 Mononote 之类的「避免打开重复标签页」的插件,但是它们解决不了「在新标签页打开」的需求。
我曾经试过用 Commander 插件组合两个动作:新建标签页+打开今日笔记
但是这样配合的结果就是会留下一个空的新标签页。

另外也可以用 AdvancedURI 插件,它是可以自己配置打开方式的。
不过 OB 内没法直接注册成一个快捷键。

另外…… QuickAdd 理论上也可以?
甚至是专门用来做这个的?
研究太少了可能忽略了哈哈哈……

尝试了一下,QA 可以实现需求1和3,但是2(直接切换到打开的现有标签页)还是实现不了:

特殊情况下的处理

当前的标签页如果是「非笔记」内容——如插件页面——Templater 的脚本是无法应用的。

这种情况下,反而可以借助 QuickAdd 来运行:

==直接把 TP 脚本粘贴进 Capture format 就能运行==

来自:QuickAdd JS & Templater JS 简介及相互修改

但是这样的话 编辑不太方便……
对于直接使用脚本的人来说应该问题不大,自己要写脚本加调试的话……

这里就得用上 QuickAdd 插件的 MACRO 以及用户脚本功能了。
总之也写了一份,in case 谁用得上的。

/*
 * @Author: Moy
 * @Date: 2024-08-06 12:44:36 
 * @Last Modified by: Moy
 * @Last Modified time: 2024-04-01 19:11:23
 * @URL: 
*/

// 导入所需模块
const path = require('path');
const fs = require('fs');
const quickAddApi = app.plugins.plugins.quickadd.api;

// 导出异步函数
module.exports = async (params) => {

    // 获取当前所有的标签页(范围未知)
    const tabs = app.workspace.activeTabGroup;
    // 定义今日笔记的格式
    const DailyNoteName = moment().format('YYYY-MM-DD');
    let dailyNoteTab = null;

    // 今日笔记的文件夹,文件还不存在的话,创建一个
    const DailyNoteFolder = "PeriodicNote/Daily/"+moment().format('YYYY-MM-DD');
    // 今日笔记的模板文件名称
    const DailyNoteTemplate = "DailyNote模板";

    for (const tab of tabs.children) {
        if (tab.view.file && tab.view.file.basename && tab.view.file.basename === DailyNoteName) {
            dailyNoteTab = tab;
            break;
        }
    }

    if (dailyNoteTab) {
        // 如果已经打开了,切换到对应页面
        app.workspace.setActiveLeaf(dailyNoteTab, { focus: true });
        new Notice("切换到今日笔记");
    } else {
        // 如果没有打开,就打开(或新建)
        // 获取所有文件
        const allFiles = app.vault.getMarkdownFiles();

        // 查找特定文件
        const file = allFiles.find(file => file.name === DailyNoteName+".md");
        // const file = tp.file.find_tfile(DailyNoteName);
        if (file) {
            app.workspace.getLeaf("tab").openFile(file);
            new Notice("打开今日笔记");
        } else {
            new Notice("今日笔记不存在!");

            const tp = app.plugins.plugins["templater-obsidian"].templater.current_functions_object;
            
            const tpFolder = app.vault.getAbstractFileByPath(DailyNoteFolder);
            const tpFile = allFiles.find(file => file.name === DailyNoteTemplate);

            await tp.file.create_new(tpFile, DailyNoteName, true, tpFolder);
            new Notice(`创建了新的 DailyNote ${DailyNoteName}`);
            
        }
    }
};

3 个赞

真是好相似的需求,我之前也写过

算是普遍痛点了,哈哈 【摊手】

楼主这个沙土色的主题是什么 :joy:

好眼光,是 NieR 的主题:
exloseur3d/nier-theme: Obsidian theme inspired by the UI of the video game “NieR: Automata” (github.com)

这明明应该是一个更泛用的特性,居然还没有被插件实现吗

其实有至少3个插件(Mononote、No Dupe Leaves、Opener)是做类似的优化的。

但是它们基本上都基于「点击链接打开笔记」的操作:
你开着「A」页面的情况下,点击了一个指向「A」的笔记链接,会直接切换到「A」标签页。
(或者是先打开新的 A 然后发现有开着的,关闭新标签页,跳转到A)

感谢,原本是觉的配色不错,对眼睛友好,没想到这主题制作如此精良,神了 :+1: