cmdr 插件教程
Commander 插件使用指南
Commander 是 Obsidian 中用于自定义命令入口的插件,可以将任意 Obsidian 命令、代码片段和脚本添加到 Ribbon 栏、侧边栏、右键菜单和文件标题栏。
插件特点
| 特性 | 说明 |
|---|---|
| 🎛️ 多位置绑定 | Ribbon、侧边栏、右键菜单、标题栏均可添加 |
| ⌨️ 快捷方式 | 为任意命令创建快捷键 |
| 📝 代码片段 | 运行自定义 JavaScript 代码 |
| 🔧 自定义命令 | 创建组合命令序列 |
| 🖼️ 图标系统 | 支持 Lucide 和自定义图标 |
安装插件
- 打开「设置」→「第三方插件」→ 关闭「安全模式」
- 点击「浏览」→ 搜索「Commander」→ 安装并启用
基础配置
打开配置面板
- 命令:
Commander: Open settings - 在「Settings」选项卡中管理所有命令
添加命令到 Ribbon 栏
Ribbon 栏是 Obsidian 左侧的图标区域:
- 在 Commander 设置中点击「Add」→ 选择「Ribbon」
- 选择要添加的命令
- 选择图标(如
📝、🔍、📅) - 设置提示文字
常用 Ribbon 命令:
| 命令 | 图标 | 说明 |
|---|---|---|
| 打开日记 | 📅 | 打开今日日记 |
| 搜索 | 🔍 | 全局搜索 |
| 新建笔记 | ✏️ | 创建新笔记 |
| 命令面板 | ⌨️ | 打开命令面板 |
添加命令到右键菜单
- 点击「Add」→ 选择「Context Menu」
- 选择命令
- 设置菜单位置(文件菜单 / 编辑菜单 / 文件夹菜单)
代码片段
Commander 支持运行自定义 JavaScript 代码片段。
创建代码片段
- 在设置中选择「Snippets」选项卡
- 点击「Add snippet」
- 编写 JavaScript 代码
常用片段
一键创建带日期的笔记
javascript
// 创建以当前日期命名的笔记
const today = new Date().toISOString().slice(0, 10);
const fileName = `Journal/Daily/${today}.md`;
const template = `---
date: ${today}
tags: [日记]
---
# ${today}
## 今日记录
`;
await app.vault.create(fileName, template);
new Notice(`已创建 ${today} 日记`);快速添加任务
javascript
// 在当前笔记末尾添加新任务
const file = app.workspace.getActiveFile();
if (file) {
const task = `\n- [ ] 新任务 📅 ${new Date().toISOString().slice(0, 10)}`;
await app.vault.append(file, task);
new Notice('已添加任务');
}切换主题
javascript
// 在亮色/暗色主题间切换
const theme = document.body.classList.contains('theme-dark')
? 'light' : 'dark';
app.changeTheme(theme);
new Notice(`已切换到${theme === 'dark' ? '暗色' : '亮色'}主题`);自定义命令序列
将多个命令组合成一个序列,一次执行。
创建命令序列
- 在设置中选择「Commands」选项卡
- 点击「Add command」
- 选择多个命令并设置执行顺序
示例:晨间工作流
序列:晨间规划
├─ 1. 打开今日日记
├─ 2. 打开本周周记
└─ 3. 聚焦日记编辑器示例:日终回顾
序列:日终回顾
├─ 1. 显示今日日记
├─ 2. 标记已完成任务
└─ 3. 创建明日待办图标系统
Commander 使用 Lucide 图标库。
选择图标
- 在添加命令时点击图标选择器
- 输入图标名称搜索(如
calendar、search) - 点击选择
常用图标对照
| 操作 | 图标名称 |
|---|---|
| 日历 | calendar |
| 搜索 | search |
| 新建 | plus |
| 标签 | tag |
| 文件夹 | folder |
| 链接 | link |
| 设置 | settings |
| 保存 | save |
高级配置
条件显示
设置命令在特定条件下才显示:
javascript
// 仅当笔记为日记时显示
module.exports = {
condition: (app) => {
const file = app.workspace.getActiveFile();
return file && file.path.includes('Journal/Daily');
}
};文件类型过滤
javascript
// 仅在 Markdown 文件中显示
module.exports = {
filter: (file) => file.extension === 'md'
};快捷键管理
在「Shortcuts」选项卡中管理所有命令的快捷键:
| 操作 | 说明 |
|---|---|
| 查看快捷键 | 列出所有已设置的快捷键 |
| 搜索 | 按命令名搜索快捷键 |
| 导出 | 导出快捷键配置 |
| 导入 | 导入快捷键配置 |
常用命令配置
Ribbon 栏配置
| 图标 | 命令 | 说明 |
|---|---|---|
| 📅 | Daily notes: Open today's daily note | 打开日记 |
| 📁 | New file | 新建笔记 |
| 🔍 | Search: Open search pane | 打开搜索 |
| 📋 | Commander: Open settings | 打开设置 |
| 🏷️ | Editor: Toggle tags view | 标签视图 |
右键菜单配置
| 菜单位置 | 命令 | 说明 |
|---|---|---|
| 文件菜单 | Daily notes: Open today's daily note | 用日记打开 |
| 编辑菜单 | Editor: Toggle strikethrough | 添加删除线 |
| 文件夹菜单 | New note here | 在此处新建 |
常见问题
Q: Ribbon 图标不显示?
- 确认插件已启用
- 检查图标名称是否正确
- 重启 Obsidian
Q: 代码片段运行报错?
检查 JavaScript 语法是否正确,Commander 的代码片段在 sandbox 环境中运行,部分 API 可能受限。
Q: 如何备份配置?
在 Commander 设置中有「Export」选项,可以导出所有命令和片段配置为 JSON 文件。
Q: 如何隐藏默认 Ribbon 图标?
在 Commander 设置中启用「Hide default ribbon icons」,然后选择性显示需要的图标。
Commander 高级使用案例
本文介绍 Commander 插件的进阶配置,包括复杂脚本、命令序列、API 集成和自动化工作流。
复杂代码片段
批量文件操作
javascript
const folder = app.workspace.getActiveFolder();
if (folder) {
const children = folder.children;
for (const child of children) {
if (child instanceof TFile && child.extension === 'md') {
const oldName = child.basename;
const newName = oldName.replace(/\s+/g, '-');
if (oldName !== newName) {
await app.fileManager.renameFile(child, `${folder.path}/${newName}.md`);
}
}
}
new Notice(`已处理 ${children.length} 个文件`);
}智能模板插入
javascript
const file = app.workspace.getActiveFile();
const fileName = file?.basename || 'untitled';
const templates = {
'日记': `---
date: {{date:YYYY-MM-DD}}
tags: [日记]
---
# {{date:YYYY-MM-DD}}`,
'会议': `---
date: {{date:YYYY-MM-DD}}
participants: []
---
# 会议记录 | {{date:YYYY-MM-DD}}
## 参会人员
## 议程
1.
## 决策
## 待办
- [ ] `,
'项目': `---
project:
status: 🟡 进行中
tags: [项目]
---
# 项目名称
## 目标
## 里程碑
- [ ]
`
};
const template = templates[fileName] || templates['日记'];
const editor = app.workspace.getActiveEditor();
if (editor) {
editor.replaceSelection(template);
new Notice(`已插入 ${fileName} 模板`);
}命令序列
每周回顾序列
序列:每周回顾
├─ 1. 打开本周周记
├─ 2. 收集过去 7 天日记中的任务完成情况
├─ 3. 统计完成率
└─ 4. 在周记中生成周报项目启动序列
序列:启动新项目
├─ 1. 提示输入项目名称
├─ 2. 创建项目文件夹
├─ 3. 生成项目笔记(使用模板)
└─ 4. 创建项目日记分区API 集成
调用外部 API
javascript
const response = await fetch('https://api.example.com/data');
const data = await response.json();
const file = app.workspace.getActiveFile();
if (file) {
const content = await app.vault.read(file);
const updatedContent = content + `\n\n## API 数据\n\n\`\`\`json\n${JSON.stringify(data, null, 2)}\n\`\`\``;
await app.vault.modify(file, updatedContent);
new Notice('已同步数据');
}Obsidian API 高级用法
javascript
app.metadataCache.on('changed', (file, data) => {
if (file.path.includes('Journal/Daily')) {
const hasTodos = data.includes('- [ ]');
if (hasTodos) {
console.log(`日记 ${file.basename} 有待办`);
}
}
});自动化脚本
每日自动归档
javascript
const moment = window.moment || require('moment');
const threshold = moment().subtract(30, 'days');
const journalFolder = 'Journal/Daily';
const files = app.vault.getFiles()
.filter(f => f.path.startsWith(journalFolder))
.filter(f => {
const date = moment(f.basename, 'YYYY-MM-DD');
return date.isBefore(threshold);
});
if (files.length > 0) {
for (const file of files) {
const newPath = `Archives/Journal/${file.name}`;
await app.fileManager.renameFile(file, newPath);
}
new Notice(`已归档 ${files.length} 个旧日记`);
} else {
new Notice('没有需要归档的日记');
}任务统计生成
javascript
const file = app.workspace.getActiveFile();
if (file) {
const content = await app.vault.read(file);
const total = (content.match(/- \[ \]/g) || []).length;
const completed = (content.match(/- \[x\]/g) || []).length;
const percentage = total > 0 ? Math.round(completed / total * 100) : 0;
const stats = `\n\n---\n\n**任务统计**: ${completed}/${total} (${percentage}%)\n\n${'█'.repeat(percentage / 5)}${'░'.repeat(20 - percentage / 5)}`;
await app.vault.append(file, stats);
new Notice(`已生成任务统计: ${percentage}%`);
}调试技巧
javascript
// 使用 console 输出到控制台
console.log('=== Commander Debug ===');
console.log('Active file:', app.workspace.getActiveFile()?.path);
// 错误处理
try {
await app.vault.create('test.md', 'content');
} catch (error) {
console.error('Error:', error);
new Notice(`执行失败: ${error.message}`);
}常见问题
Q: 片段执行后无响应?
- 检查 JavaScript 代码是否有语法错误
- 在开发者工具中查看控制台错误
- 尝试简化代码逐步排查
Q: 如何调试复杂脚本?
使用 console.log 输出中间变量值,在 Obsidian 的「开发者工具」→「控制台」中查看。