Configure deft title stripping to hide org-roam template headers

by default (for me at least) org-roam creates lower case headers (eg. #+title:, not #+TITLE:) which i dig, but: by default deft only strips upper-case headers from its preview/summary line for each item.

perhaps sb with regex know-how can provide an edit to the deft strip title regex config so that it strips org-roam templates by default?

or is there perhaps another way ppl go abt this?

@moosehead. Adjust deft-strip-summary-regexp accordingly.

Only strip upper case (default):

"\\([\n ]\\|^#\\+[[:upper:]_]+:.*$\\)"

Strip upper/lower/mixed case, e.g #+LaTeX:

"\\([\n ]\\|^#\\+[[:upper:][:lower:]_]+:.*$\\)"


thanks very much! i wasn’t even trying change the right variable.
[hopefully helpful for other ppl too.]

1 Like


I’m having the same problem with regex in Deft for deft-strip-title-regexp and deft-strip-summary-regexp variables.

I’m trying to write the accurate regex by looking up the variable definitions into deft.el with no success so far.

I have described my file template here but I didn’t get so much help.

For title, I would like to skip the :PROPERTIES: lines and the #+title prefix.

My last try is:

  "\\(?:^%+\\|^#\\+[[:upper:]_]+:.*$\\|^#\\+TITLE: *\\|^[#* ]+\\|-\\*-[[:alpha:]]+-\\*-\\|^Title:[	 ]*\\|#+$\\)"

For summary, I would like to skip the first 10 lines to see what’s on line 11.

@mshevchuk Would you help?

1 Like

Thanks for that link! I’ve been wanting to fix the way my deft results looked for a long time, but was never quite sure how to do it. That issue thread was enough for me to figure out how to set things up to my liking – but since my requirements are different than yours, my regexps won’t do what you want (otherwise I would share them, but they’re very similar to what’s in the link you shared)

Hi @tea4or2wo I’m not very proficient with regexps to write them on the fly and currently do not have enough time to sit and figure it out.

Below is a pseudocode for how one may achieve what you want.

To match :PROPERTIES:, you’d need soomething like this:

1. Match the word :PROPERTIES: literally + end of line
2. Match any number of chars up to the end of line
3. Match expression 2 zero or more times in a non-greedy way
4. Match the word :END: literally + end of line

Also check the Org-mode source code. Look up variables starting with org and containing regexp. There are plenty of them and some of the are sure dealing with properties. Maybe you’ll find some hints.

To match titles, first of all listen to that comment by TRSx80 and simplify your regexp.

If you are using only Org-mode files with Deft then you obviously do not need ^Title:[ ]*\\|#+$ at all, since it matches Markdown-style titles Title: anything. If you don’t use file-local variables then you don’t need this part as well -\\*-[[:alpha:]]+-\\*-\\|, which matches -*- anything -*-

Skipping the first 10 lines for summary should be even easier:

1. Match anything up to the end of line
2. Match expression 1 exactly 10 times

You may also find useful the rx macro. It comes with a built-in Emacs rx package that allows for writing regular expressions in the form of Lisp s-expressions:

For example,

(rx (and (or "TITLE" "title")

produces this regular expression: \(?:TITLE\|title\)$

Since it is Elisp, you can use the macro directly in the code, e.g.
(setq deft-strip-title-regexp (rx ...))

Also, don’t forget about the excellent regexp-builder command. It allows to build regular expressions on the fly using either standard Elisp regexps or the rx s-expressions. It will highlight matches in the buffer as you type the regexp.

Hope this helps.

I’ve run into the same problem as you with deft. The main problem I’m having is that the deft readme states

The displayed title of each file is taken to be the first line of the file, with certain characters removed from the beginning. […] More generally, the title post-processing function itself can be customized by setting deft-parse-title-function , which accepts the first line of the file as an argument and returns the parsed title to display in the file browser.

So it appears like there would need to be some more significant changes to deft to make this work. A dirty workaround would be to just leave the title empty, and display it at the beginning of the summary, but I’m not sure I’d be happy with that. In it’s current form, deft and org-roam-v2 seem incompatible by design.

The corresponding function in deft seems to be

(defun deft-parse-title (file contents)
  "Parse the given FILE and CONTENTS and determine the title.
If `deft-use-filename-as-title' is nil, the title is taken to
be the first non-empty line of the FILE.  Else the base name of the FILE is
used as title."
  (if deft-use-filename-as-title
      (deft-base-filename file)
    (let ((begin (string-match "^.+$" contents)))
      (if begin
          (funcall deft-parse-title-function
                   (substring contents begin (match-end 0)))))))

It should be possible to replace that expression with ^#\\+TITLE.+" to match the title line, but I’m currently unsure where I’d have to make that change (using doom), as I’m new to lisp. I tried to just overwrite the function but that didn’t seem to work.

Edit: You may open deft.el, goto aforementioned defun deft-parse-title and replace the regex line with (let ((begin (string-match "^#\\+TITLE.+" contents))), then recompile with M-x byte-compile-file deft.el. There should be a better way to do this though, since a deft update would break this.

Did anyone did solve this issue with deft to show properly the contents of a note while searching?

I found this solution which works well for me: deft-strip-summary-regexp to exclude all properties · Issue #75 · jrblevin/deft · GitHub

@roi.holtzman Thank you. This was extremely helpful. I modified the code you linked to strip away from deft summary also links in the form of “[[][]]” which would clutter the screen since I tend to link to other notes in the first line. I find Emacs regex not so obvious. In case, this is how I modified the code:

    (use-package deft
    :after org
    :ensure t
    ("C-c n d" . deft)
    ;; (deft-recursive t)
    (deft-use-filter-string-for-filename t)
    (deft-default-extension "org")
    (deft-directory "/Users/myuser/Nextcloud/work/zettelkasten")
    (defun cf/deft-parse-title (file contents)
      "Parse the given FILE and CONTENTS and determine the title.
    If `deft-use-filename-as-title' is nil, the title is taken to
    be the first non-empty line of the FILE.  Else the base name of the FILE is
    used as title."
      (let ((begin (string-match "^#\\+[tT][iI][tT][lL][eE]: .*$" contents)))
        (if begin
            (string-trim (substring contents begin (match-end 0)) "#\\+[tT][iI][tT][lL][eE]: *" "[\n\t ]+")
          (deft-base-filename file))))
    (advice-add 'deft-parse-title :override #'cf/deft-parse-title)
    (setq deft-strip-summary-regexp
          (concat "\\("
                  "[\n\t]" ;; blank
                  "\\|^#\\+[[:alpha:]_]+:.*$" ;; org-mode metadata
                  "\\|^:PROPERTIES:\n\\(.+\n\\)+:END:\n" ;; org-roam ID
                  "\\|\\[\\[\\(.*\\]\\)" ;; any link 
1 Like