【TP脚本】在OB里搜索文件夹的方法

有的时候只想按关键字检索文件夹(而非笔记),并快速跳转过去——遂写了这个脚本:

效果演示:
10d7110c-1a2f-4c2f-8526-873b5eb7de13

方法:安装 Templater 插件,然后使用这个 Templater 脚本:

<%*
// 获取所有文件夹路径
let folders = app.vault.getAllFolders();
// 过滤掉根目录
folders = folders.filter(folder => folder.path !== "/");

const autoCollapse = true;

// 准备用于显示的文件夹名称和对应的路径
const folderPaths = folders.map(f => f.path);
const folderNames = folders.map(f => {
    // 获取文件夹深度,用于显示缩进
    const depth = f.path.split('/').length - 1;
    const indent = '  '.repeat(depth);
    // 使用 📁 emoji 来表示文件夹
    return `${indent}📁 ${f.name} (${f.path})`;
});

// 使用 Templater 的 suggester 来创建选择器
// tp.system.suggester 的第一个参数是显示的文本数组或函数,第二个参数是实际值的数组
let selectedFolderPath = await tp.system.suggester(folderNames, folderPaths);

// 如果用户取消了选择,则退出
if (selectedFolderPath === null) return;

// 获取选中的文件夹对象
const selectedFolder = app.vault.getAbstractFileByPath(selectedFolderPath);

// 如果找到了文件夹,则在 File Explorer 中聚焦它
if (selectedFolder) {
    if (autoCollapse) {
        app.workspace.getLeavesOfType('file-explorer')[0].view.tree.setCollapseAll(true)
    }
    
    try {
        // 尝试使用内部 API 聚焦文件夹
        const fileExplorerLeaves = app.workspace.getLeavesOfType('file-explorer');
        // 检查是否存在可用叶子节点
        if (fileExplorerLeaves.length === 0) {
            // 若不存在,创建新的文件浏览器标签(参考源码逻辑)
            const leaf = app.workspace.getLeaf('tab');
            await leaf.setViewState({ type: 'file-explorer' });
            fileExplorerLeaves.push(leaf);
        }
        // 获取首个文件浏览器视图实例
        const fileExplorerView = fileExplorerLeaves[0].view;

        // 强制激活文件浏览器标签(确保视图可见)
        app.workspace.revealLeaf(fileExplorerLeaves[0]);

        const targetFile = app.vault.getAbstractFileByPath(selectedFolderPath);
        fileExplorerView.revealInFolder(targetFile);
    } catch (error) {
        // 如果上述方法都失败,显示一个通知
        new Notice( `无法在文件浏览器中聚焦文件夹:${selectedFolderPath},请手动查找` );
    }

    // 显示一个通知,表明操作成功
    new Notice(`已选择文件夹: ${selectedFolderPath}`);
} else {
    new Notice(`未找到文件夹: ${selectedFolderPath}`);
}
%>

也可以给它注册个快捷键,用起来方便点。

脚本下载:TP脚本:搜索文件夹

相关帖子:
如何搜索文件夹的名称 - 疑问解答 - Obsidian 中文论坛

注:
这个脚本的想法和实现基于 @熊猫别熬夜 熊猫佬的 FolderNotes 定位脚本:
如何搜索文件夹的名称 - #6,来自 熊猫别熬夜

2 个赞

如何使用?放进Templater之后 下一步 :pray:

官方文档:Introduction - Templater
中文文档: Templater插件简介和基础语法 | obsidian文档咖啡豆版

简而言之,用你的 Templater 输入框运行这个模板:

也可以在 TP 插件的设置里,给这个模板注册成快捷键。

谢谢 之前不能行是因为我没在笔记里面。 好像必须是在笔记中才能生效 。随便选其中一个都可以生效。
image

嗯,Templater 插件只能在笔记里使用。

想要全局用的话可以改用 QuickAdd 插件,让 AI 改一下 JS 脚本内容……不过那个插件弄起来会稍微麻烦点x

1 个赞

搞定了,我把改成了 Quickadd 脚本,使用方法如下:

  1. 将脚本保存为 .js 文件,放入 Obsidian 库文件夹中。
  2. 进入 Quickadd 设置。
  3. 点击右侧的 Template 按钮,改成 Macro。
  4. 在该按钮左侧的输入框中填上你喜欢的命令名字。
  5. 点击右侧 Add Choice 按钮,新增命令。
  6. 点击新增命令上的小闪电,方便后继加快捷键。
  7. 点击新增命令上的小齿轮,设置该命令。
  8. 随后点击右侧加号,然后再点小齿轮。
  9. 在 User Scripts 里面选择一开始保存好的脚本文件。
  10. 点击右侧 Add,添加至上方操作列表。
  11. 回到 Obsidian 设置界面,进入快捷键设置里。
  12. 搜索刚刚给命令设置的名字,并设置上喜欢的快捷键。

完成。

脚本代码如下:

module.exports = async () => {
    const quickAddApi = app.plugins.plugins.quickadd.api;

    // 获取所有文件夹路径
    let folders = app.vault.getAllFolders();
    // 过滤掉根目录
    folders = folders.filter(folder => folder.path !== "/");

    const autoCollapse = true;

    // 准备用于显示的文件夹名称和对应的路径
    const folderPaths = folders.map(f => f.path);
    const folderNames = folders.map(f => {
        // 获取文件夹深度,用于显示缩进
        const depth = f.path.split('/').length - 1;
        const indent = '  '.repeat(depth);
        // 使用 📁 emoji 来表示文件夹
        return `${indent}📁 ${f.name} (${f.path})`;
    });

    // 使用 Quickadd 的 suggester 来创建选择器
    // quickAddApi.suggester 的第一个参数是显示的文本数组或函数,第二个参数是实际值的数组
    let selectedFolderPath = await quickAddApi.suggester(folderNames, folderPaths);

    // 如果用户取消了选择,则退出
    if (selectedFolderPath === null) return;

    // 获取选中的文件夹对象
    const selectedFolder = app.vault.getAbstractFileByPath(selectedFolderPath);

    // 如果找到了文件夹,则在 File Explorer 中聚焦它
    if (selectedFolder) {
        if (autoCollapse) {
            app.workspace.getLeavesOfType('file-explorer')[0].view.tree.setCollapseAll(true)
        }

        try {
            // 尝试使用内部 API 聚焦文件夹
            const fileExplorerLeaves = app.workspace.getLeavesOfType('file-explorer');
            // 检查是否存在可用叶子节点
            if (fileExplorerLeaves.length === 0) {
                // 若不存在,创建新的文件浏览器标签(参考源码逻辑)
                const leaf = app.workspace.getLeaf('tab');
                await leaf.setViewState({ type: 'file-explorer' });
                fileExplorerLeaves.push(leaf);
            }
            // 获取首个文件浏览器视图实例
            const fileExplorerView = fileExplorerLeaves[0].view;

            // 强制激活文件浏览器标签(确保视图可见)
            app.workspace.revealLeaf(fileExplorerLeaves[0]);

            const targetFile = app.vault.getAbstractFileByPath(selectedFolderPath);
            fileExplorerView.revealInFolder(targetFile);
        } catch (error) {
            // 如果上述方法都失败,显示一个通知
            new Notice( `无法在文件浏览器中聚焦文件夹:${selectedFolderPath},请手动查找` );
        }

        // 显示一个通知,表明操作成功
        new Notice(`已选择文件夹: ${selectedFolderPath}`);
    } else {
        new Notice(`未找到文件夹: ${selectedFolderPath}`);
    }
};

也没有啦,我一般习惯保存为 js 文件并用 Macro 调用,但其实可以直接用 Capture,然后插入内容写:

```quickadd
// 脚本内容
```

都不需要另存为文件的。

保存为文件的好处是可以加设置,比如 CSS 片段开关脚本,我只要写一个脚本文件,加个文件名设置,就能复用,而 Templater 就不行,要么得保存多个文件,要么命令运行后还要再选一次。

嗯,我也喜欢保存成单独的文件,用 VSC 编辑也方便~

然后现在的话,我会更推荐用 NoteToolbar 来作为脚本发射器。

以你上面回复的流程作为例子,如果使用 NTB 插件的话,大概是:

  1. 将脚本保存为 .js 文件,放入 Obsidian 库文件夹中。
  2. 进入 NTB 的工具栏设置
  3. 新建工具,输入名称,修改类型为“JavaScript”,并选择对应的脚本文件
  4. 点击下方三个点按钮,选择 将该项目注册为命令
  5. 回到 Obsidian 设置界面,进入快捷键设置里。
  6. 搜索刚刚的工具名称,并设置上喜欢的快捷键。

QA 的嵌套配置结构就是我嫌它麻烦的原因 :joy:

1 个赞

雀食,我也不是很能理解,为什么 qa 要把 macro 拆得那么细,平白增加步骤。

不过 capture 还是蛮好的,少有的不需要保存文件的操作。

(再次安利)
NTB 也可以直接执行指定的 JS 脚本:
image

不过我现在也还留着不少 QuickAdd 的脚本,用习惯了也懒得换hhh

1 个赞