Emacs的Deft插件
Deft是一个Emacs模式,用于快速浏览、过滤和编辑纯文本笔记目录,灵感来自Notational Velocity。它的设计目的是通过快速简单地在正确的时间找到正确的文件,并自动化许多常见任务(如创建新文件和保存文件),从而提高写作和记笔记时的生产力。
获取Deft
Deft是开源软件,可以在BSD许可下自由分发和修改。最新的稳定版本是0.8版,发布于2018年1月12日。
通过MELPA Stable安装
推荐的安装Deft方法是使用package.el
从MELPA Stable获取稳定版本。首先,通过在您的.emacs
、init.el
或等效启动文件中添加以下内容来配置package.el
和MELPA Stable仓库:
(require 'package)
(add-to-list 'package-archives
'("melpa-stable" . "https://stable.melpa.org/packages/"))
(package-initialize)
然后,重启Emacs或评估上述语句后,执行以下命令:M-x package-install RET deft RET。
直接下载
或者,您可以手动下载并安装Deft。首先,下载最新的稳定版本并将文件保存在Emacs可以找到的位置——load-path
中的一个目录:
然后,在您的启动文件中添加以下行:
(require 'deft)
开发版本
要关注或贡献Deft的开发,您可以在GitHub上浏览或克隆Git仓库:
git clone https://github.com/jrblevin/deft.git
如果您更喜欢安装和使用开发版本(可能在某些时候变得不稳定),您可以克隆Git仓库或从MELPA安装Deft。
如果您直接克隆仓库,请确保Emacs可以找到它,方法是在启动文件中添加以下行:
(add-to-list 'load-path "/path/to/deft/repository")
概述
Deft缓冲区只是一个文件浏览器,列出Deft目录中所有文本文件的标题,后面跟着简短摘要和最后修改时间。标题被视为文件的第一行,摘要从后面的文本中提取。默认情况下,文件按最后修改日期排序,从最新到最旧。
所有Deft文件或笔记都是简单的纯文本文件,其中第一行包含标题。例如,以下目录结构生成了上面的截图。
% ls ~/.deft
about.txt browser.txt directory.txt operations.txt
ack.txt completion.txt extensions.org
binding.txt creation.txt filtering.txt
% cat ~/.deft/about.txt
# About
An Emacs mode for slicing and dicing plain text files.
Deft的主要操作是搜索和过滤。可以使用搜索字符串限制或过滤文件列表,该字符串将匹配标题和正文文本。要开始过滤,只需开始输入。过滤是实时进行的。当您输入时,文件浏览器会更新,只包括匹配当前字符串的文件。
要打开第一个匹配的文件,只需按RET。如果没有文件匹配您的搜索字符串,按RET将使用该字符串作为标题创建一个新文件。这是开始写新笔记的一种非常快速的方法。文件名将自动生成。如果您更喜欢提供特定的文件名,请使用C-RET。
要打开第一个匹配之外的文件,使用C-p和C-n上下导航,然后在要打开的文件上按RET。打开文件时,Deft会向前搜索并将光标留在过滤字符串的第一个匹配项的末尾。
您还可以按C-o在另一个窗口中打开文件,而不切换到该窗口。使用前缀参数C-u C-o执行相同的命令,可以在另一个窗口中打开文件并切换到该窗口。
要编辑过滤字符串,按DEL
(退格键)删除最后一个字符,或按M-DEL删除最后一个"单词"。要将最近剪切(剪切或复制)的文本粘贴到过滤字符串中,请按C-y。按C-c C-c清除过滤字符串并显示所有文件,按C-c C-g使用当前过滤字符串刷新文件浏览器。
对于更高级的编辑操作,您还可以通过按C-c C-l在迷你缓冲区中编辑过滤字符串。在迷你缓冲区中,可以通过按M-p和M-n循环浏览之前的编辑历史。这种静态、一次性过滤(相对于增量、实时过滤)在某些情况下可能更可取,例如在连接速度慢或交互式过滤性能较差的系统上。
默认情况下,Deft以增量字符串搜索模式过滤文件,其中"search string"将匹配所有包含"search"和"string"的文件,顺序不限。另外,Deft支持直接正则表达式过滤,其中过滤字符串被解释为正式的正则表达式。例如,^\(foo\|bar\)
匹配行首的foo或bar。按C-c C-t可以在增量搜索和正则表达式搜索模式之间切换。正则表达式搜索模式在模式行中用"R"表示。
Deft还可以执行常见的文件操作。
可以使用C-c C-r重命名文件或使用C-c C-d删除文件。
还可以使用C-c C-n快速创建新文件,或使用C-c C-m提示输入文件名;加上前缀参数时,这些操作会询问文件扩展名。随时可以使用C-c C-q退出Deft。
可以按C-c C-a归档未使用的文件。文件将被移动到deft-archive-directory
,默认为deft-directory
中名为archive
的目录。
通过Deft打开的文件会在Emacs空闲一段时间后自动保存。这个时间间隔是一个可自定义的浮点数,由deft-auto-save-interval
指定(默认值:1.0)。
入门
按照上述方法之一安装Deft后,只需运行M-x deft即可启动Deft。为了快速启动,最好为deft
函数创建一个全局键绑定(如功能键)(详见下文)。
首次运行Deft时,它会提示找不到~/.deft
目录。你可以创建一个指向保存笔记的其他目录的符号链接,或运行M-x deft-setup自动创建~/.deft
目录。
Deft的一个实用方法是将笔记目录保存在Dropbox文件夹中。这样可以与其他应用程序和移动设备配合使用,例如OS X上的nvALT、Notational Velocity或Simplenote,或iOS上的Editorial、Byword或1Writer。
基本自定义
你可以自定义deft
组中的项目来更改默认功能。
默认情况下,Deft在~/.deft
目录中搜索扩展名为.txt
、.text
、.md
、.markdown
或.org
的文件作为笔记。你可以运行M-x customize-group并输入deft
来自定义文件扩展名和Deft目录。或者,你可以在.emacs
文件中进行配置:
(setq deft-extensions '("txt" "tex" "org"))
(setq deft-directory "~/Dropbox/notes")
deft-extensions
的第一个元素(在Lisp术语中称为car)是用于创建新文件的默认扩展名。
默认情况下,Deft只在deft-directory
中搜索文件,不搜索任何子目录。deft-directory
中所有具有指定扩展名的文件都将被包含,除了那些匹配deft-ignore-file-regexp
的文件。将deft-recursive
设置为非nil值以启用子目录搜索(不匹配deft-recursive-ignore-dir-regexp
的子目录):
(setq deft-recursive t)
你可以轻松设置Deft的全局键盘绑定。例如,要将其绑定到F8,请将以下代码添加到.emacs
文件中:
(global-set-key [f8] 'deft)
如果你使用use-package管理加载包,则可以通过在初始化文件中添加如下声明来进行配置:
(use-package deft
:bind ("<f8>" . deft)
:commands (deft)
:config (setq deft-directory "~/Dropbox/notes"
deft-extensions '("md" "org")))
读取文件
每个文件显示的标题取自文件的第一行,并删除开头的某些字符。会删除Markdown标题中使用的井号字符和Org Mode标题中使用的星号。此外,还会从显示的标题中删除Org mode的#+TITLE:
标签、MultiMarkdown的Title:
标签、LaTeX注释标记和Emacs模式行声明(例如-*-mode-*-
)。可以通过更改deft-strip-title-regexp
来自定义这一行为。
更一般地,可以通过设置deft-parse-title-function
来自定义标题后处理函数,该函数接受文件的第一行作为参数,并返回要在文件浏览器中显示的解析后的标题。默认函数是deft-strip-title
,它会删除上述所有deft-strip-title-regexp
的匹配项。
为了与使用文件名作为笔记标题的其他应用程序兼容(而不是文件的第一行),请将deft-use-filename-as-title
标志设置为非nil
值。然后Deft将使用笔记文件名生成在Deft文件浏览器中显示的标题。要启用此功能,请将以下内容添加到.emacs
文件中:
(setq deft-use-filename-as-title t)
最后,可以通过更改deft-strip-summary-regexp
来自定义文件标题后显示的简短摘要。默认情况下,它被设置为删除某些org-mode元数据语句,如#+OPTIONS:
和#+AUTHOR:
。
创建文件
Deft会自动生成新创建文件的文件名。
生成过程由变量deft-use-filename-as-title
和deft-use-filter-string-for-filename
以及deft-file-naming-rules
关联列表中的规则决定。
可能的情况如下:
-
默认(
deft-use-filename-as-title
和deft-use-filter-string-for-filename
都为nil
):文件名将使用类似ISO的短时间戳自动生成,如
2016-05-12T09:00.txt
。可以通过设置变量deft-new-file-format
来自定义格式。过滤字符串将被插入文件的第一行(也用作显示标题)。如果文件名冲突,将在扩展名之前添加下划线和数字后缀(例如_2
)。 -
文件名作为标题(
deft-use-filename-as-title
为非nil
): 当deft-use-filename-as-title
不为nil
时,过滤字符串将被用作新文件的文件名(适当的文件扩展名会被附加到末尾)。在这种情况下,新文件创建的示例如下:
- 过滤字符串: "My New Project"
- 文件名: "My New Project.txt"
- 文件内容: [空]
- 可读的文件名(
deft-use-filename-as-title
为nil
但deft-use-filter-string-for-filename
不为nil
):
在这种情况下,你可以选择显示从文件第一行解析的标题,同时也为新文件生成基于过滤字符串的可读文件名。变量 deft-use-filter-string-for-filename
控制这种行为,并将标题显示(deft-use-filename-as-title
)与实际文件名分离。新文件名将根据过滤字符串生成,并按照 deft-file-naming-rules
列表中定义的规则进行处理。默认情况下,斜杠会被删除并替换为连字符,但还有许多其他选项(驼峰命名法、用连字符替换空格等)。有关更多详细信息,请参阅 deft-file-naming-rules
的文档。
例如,使用以下 deft-file-naming-rules
值,Deft 将把所有斜杠和空格替换为连字符,并将文件名转换为小写:
(setq deft-file-naming-rules
'((noslash . "-")
(nospace . "-")
(case-fn . downcase)))
以下是这种情况下的示例,使用上述文件命名规则。注意,过滤字符串被插入为文件的第一行,但也用于生成"可读"的文件名。
- 过滤字符串: "My New Project"
- 文件名: "my-new-project.txt"
- 文件内容: "My New Project"
从过滤字符串插入文件的标题也可以针对两种常见模式进行自定义,即 markdown-mode
和 org-mode
,通过设置以下变量:
-
deft-markdown-mode-title-level
- 当设置为正整数时,决定在新的 Markdown 文件中标题前添加多少个井号。换句话说,将deft-markdown-mode-title-level
设置为 2 将导致新文件创建时使用## Title
形式的二级标题。 -
deft-org-mode-title-prefix
- 当不为 nil 时,新org-mode
文件中自动生成的标题将以#+TITLE:
为前缀。
其他自定义设置
Deft 默认按最新到最旧的顺序列出文件。你可以将 deft-current-sort-method
设置为 'title 以按文件标题排序(忽略大小写)。或者,你可以使用 deft-toggle-sort-method
切换排序方法。
增量字符串搜索是启动时的默认过滤方法,但你可以将 deft-incremental-search
设置为 nil,使正则表达式搜索成为默认方法。
Deft 还提供了一个不直接使用 Deft 缓冲区打开文件的函数。调用 deft-find-file
将提示打开一个文件,类似于 find-file
,但仅限于 deft-directory
中 Deft 已知的文件(即那些匹配 deft-extensions
的文件)。与 find-file
不同,会提供所有这些文件的列表,并且可以使用 completing-read
完成所需的文件名(因此,当启用时,deft-find-file
将使用 ido、helm 等读取/完成文件名)。如果选定的文件在 deft-directory
中,它将以常用的 Deft 功能打开(自动保存、自动更新 Deft 缓冲区等)。否则,该文件将像往常一样由 find-file
打开。因此,你可以为这个函数设置一个全局快捷键,以在任何地方打开 Deft 文件。例如,要使用 C-x C-g(C-x C-f 的邻居),可以使用以下设置:
(global-set-key (kbd "C-x C-g") 'deft-find-file)
用于高亮显示屏幕各个部分的面也可以自定义。默认情况下,这些面继承自当前颜色主题定义的标准 font-lock 面的属性。
Deft 还提供了几个钩子:deft-mode-hook
、deft-filter-hook
和 deft-open-file-hook
。有关更多详细信息,请参阅这些变量的文档。
致谢
感谢 Konstantinos Efstathiou 编写 simplenote.el,我从中借鉴了很多,也感谢 Zachary Schneirov 编写 Notational Velocity,我希望将其功能和精神带到 Emacs 中。
历史
版本 0.8 (2018-01-12):
- 将
deft-find-file
限制为 Deft 已知的文件,并支持 completing-read。 - 显示文件名时保留子目录部分。
- 新变量
deft-width-offset
用于自定义摘要行宽度偏移。 - 尝试在刷新浏览器后恢复光标位置,并在过滤时保持位置。
- 添加钩子:
deft-filter-hook
用于过滤字符串变化,deft-open-file-hook
在打开文件后运行。 - 防止 Deft 浏览器的虚假刷新,解决了与
sublimity-mode
的问题。 - 窗口大小变化时更可靠地更新浏览器。
- 仅在缓冲区可见时更新宽度。
- 保存文件后延迟更新 Deft 缓冲区。
- 删除文件时关闭打开的缓冲区。
- 即使在后台启动时也初始化宽度。
- 忽略从 org 或 markdown 生成的文件。
- 自定义格式字符串
deft-new-file-format
用于新文件名。 - 当没有边缘时减少摘要行宽度。
- 支持 Org 链接。
- 选项
deft-filter-only-filenames
仅对文件名进行过滤。
版本 0.7 (2015-12-21):
- 添加自定义正则表达式
deft-strip-summary-regexp
用于删除生成摘要行时的多余文本。默认情况下删除所有org-mode
元数据。 - 新的可自定义正则表达式用于忽略文件和目录。参见
deft-recursive-ignore-dir-regexp
和deft-ignore-file-regexp
。 - 错误修复:防止控制台模式下行换行。
- 错误修复:在加载时设置
deft-extensions
和deft-default-extension
。 - 错误修复:尝试防止在 org-mode 笔记中出现误匹配标题,其中
#+TITLE:
字符串可能也出现在正文中。 - 错误修复:在自动保存文件时使用
with-current-buffer
而不是save-excursion
,因为我们不想保存光标位置。 - 错误修复:在
deft-file-naming-rules
中不转义引号。
版本 0.6 (2015-06-26):
- 子目录递归搜索(可选)。将
deft-recursive
设置为非空值以启用。 - 通过
deft-extensions
列表支持多个扩展名。因此,deft-extension
现已弃用。 - 新变量
deft-create-file-from-filter-string
可以启用基于过滤字符串生成新文件名的功能。这将标题显示(deft-use-filename-as-title
)与实际文件名生成分离。 - 新变量
deft-file-naming-rules
允许自定义文件名生成,包括字母大小写和空格处理。 - 新变量
deft-markdown-mode-title-level
和deft-org-mode-title-prefix
用于自动插入标题标记。 - 在
deft-archive-directory
中归档文件。 - 通过
deft-current-sort-method
可以按标题或修改时间排序。 - 更新默认的
deft-strip-title-regexp
以移除以下内容:- org-mode 的
#+TITLE:
标签 - MultiMarkdown 的
Title:
标签 - LaTeX 注释标记
- Emacs 模式行声明(如
-*-mode-*-
)
- org-mode 的
- 移除标题首尾的空白字符。
- 禁用可视行模式以防止换行。
- 启用行截断以避免显示截断字符。
- 重命名文件时,将旧文件名显示为默认提示。
- 打开文件时调用
hack-local-variables
以读取文件局部变量。 - 修复了几个字节编译警告。
- 错误修复:更健壮地处理相对和绝对文件名。
- 错误修复:使用字符串宽度而非长度进行计算。
- 错误修复:修复空文件时的
string-width
错误。
版本 0.5.1 (2013-01-28):
- 错误修复:当过滤字符串和
deft-use-filename-as-title
都非空时,使用 C-c C-n 创建文件会导致无效路径。 - 错误修复:已关闭的缓冲区会在
deft-auto-save-buffers
中持续存在。
版本 0.5 (2013-01-25):
- 实现增量字符串搜索(默认)和正则表达式搜索。可以通过按 C-c C-t 切换这些搜索模式。
- 可以通过设置
deft-incremental-search
更改默认搜索方法。 - 支持自定义
deft-parse-title-function
进行标题后处理。 - 默认的
deft-parse-title-function
只是去除deft-strip-title-regexp
的匹配项,用于移除 Markdown 和 Org 标题。 - 使用 C-o 在另一个窗口打开文件。用 C-u 前缀可切换到另一个窗口。
- 对于符号链接,使用目标文件的修改时间进行排序。
- 打开文件时,将光标移动到过滤字符串第一个匹配项的末尾。
- 改进了过滤编辑:删除(
DEL
)、删除词(M-DEL)和粘贴(C-y)。 - 在小缓冲区中进行高级过滤编辑(C-c C-l)。
版本 0.4 (2011-12-11):
- 提高过滤性能。
- 可选择从文件名而非内容第一行获取标题(参见
deft-use-filename-as-title
)。 - 动态调整宽度以适应整个窗口。
- 可自定义时间格式(参见
deft-time-format
)。 - 正确处理带或不带尾斜杠的
deft-directory
。
版本 0.3 (2011-09-11):
- 国际化:支持使用多字节字符进行过滤。
版本 0.2 (2011-08-22):
- 过滤时匹配文件名。
- 自动保存打开的文件(可选)。
- 解决一些字节编译警告。
Deft 最初由 Jason Blevins 编写。 初始版本 0.1 于 2011 年 8 月 6 日发布。