deft
deft copied to clipboard
deft-strip-summary-regexp to exclude all properties
I'm trying to set a custom deft-strip-summary-regexp
value as follows:
(setq deft-strip-summary-regexp
(concat "\\("
"[\n\t]" ;; blank
"\\([\n ]\\|[[:upper:]_]+:.*$\\)"
"\\)"))
It's not perfect, but I'm hoping this will strip down from the summary all org mode properties. For example, in a file with the following:
#+TITLE: My Title
#+LINK: https://my-url.com/
#+ADDED: [2020-04-15]
* Summary
:PROPERTIES:
:URL: https://my-url.com/
:ID: 832E9339-542C-4A8E-BEE8-672C546EF36A
:ARCHIVED_AT: [[file:/]]
:END:
This is the summary for this file and so it goes.
I would love for deft to exclude all org mode properties, including everything between :PROPERTIES:
and :END:
. Is that possible? Currently my setting of deft-strip-summary-regexp
does not seem to take any effect.
Following should remove everything between :PROPERTIES:
and :END:
, inclusive:
":PROPERTIES:\n\\(.+\n\\)+:END:\n"
Just remove the last \n
if you don't want to remove the blank line after :END:
.
Explanation: Literal ":PROPERTIES:", then newline, then a group (parenthesis) of one or more of any character (".+"), followed by a newline; then that (group) repeats one or more times ("+"), and finally literal ":END:" and a final newline. N.B. the double escaping on the group parens, but not on the newlines.
I came across this while searching for answers to a very similar problem. Then I solved my own problem. Then after that, since I was already brushing up on my regex, I decided to solve your problem. :smile:
Now, my deft / Org files have slightly different structure, I don't use any of the "#+TITLE: " style metadata (I use a simple Org heading instead, which I get the title from), but I do use PROPERTIES and LOGBOOK, like so:
* Some Org heading
:PROPERTIES:
:VISIT_COUNT: 1
:END:
:LOGBOOK:
- State "UPDATED" from "CREATED" [2020-08-11 Tue 00:24] \\
- Another status update.
- State "CREATED" from [2020-07-15 Tue 00:24] \\
- Status update.
:END:
Body starts here....
So, in my case I wanted to remove "everything through the first blank line" which I accomplished with the following regex:
(setq deft-strip-summary-regexp "\\`\\(.+\n\\)+\n")
Not sure if you can squish things together a little more or not, nor whether or not that sort of solution would work for you.
Thanks! How are you setting deft-strip-summary-regexp
? I suppose in your init.el file.
I'm trying that (and all kinds of different regexp settings) but none seem to be taking any effect. I tried manually updating the variable and refreshing the list with C-c C-g and also restarting emacs to refresh. The summary never gets stripped.
Not sure what I'm doing wrong. Any ideas?
How are you setting
deft-strip-summary-regexp
? I suppose in your init.el file.
Yes, via setq
in my init file. Although the concat
method you do is also perfectly valid, in fact the more complicated the regex the more likely I am to employ something like that, along with lots of notes, for the benefit of my future self. :wink:
You also need to make sure Deft is really closed, it seems to like hanging around. From Deft buffer, kill that buffer. Then I look and make sure it's gone (I like kpm-list
, but there are other ways I'm sure).
Are you also doing eval-last-sexp
on your changed setq
? You shouldn't need to restart Emacs. Just put point after parenthesis of your setq
expression, and do "C-x C-e" which will evaluate it and return the value in the minibuffer.
After you have done both those things, then, when you start Deft again, it should take up the new settings.
This is assuming you copied the regex I posted verbatim. If you are still trying to learn Emacs regex, well, that is a whole another beast... Xah has some pretty good pages about it, and there are others on the web. Just keep practicing. But go into an actual buffer and do regex commands to test your stuff, that is probably the best way. Start small and build them up. I only very recently got to the point of being able to rip off more complicated ones on the first try. But it took me a while, so stick with it; you'll get it eventually.
I have a similar problem here.
The header I use for my files is either like this:
:PROPERTIES:
:ID: 675a4db1-bb4a-4940-b6b5-9c1d2d86ae7a
:END:
#+title: Title
#+ROAM_ALIAS:
#+ROAM_TAGS: tag
#+CREATED: [YYYY-MM-DD day 17:57]
#+EDITED: [YYYY-MM-DD day 17:57]
This is content.
for regular files, or like that:
:PROPERTIES:
:ID: 546bf7c4-aab0-4532-8203-51f6bcc1a55d
:END:
#+title: ref1
#+ROAM_ALIAS:
#+ROAM_KEY: cite:ref1
#+ROAM_TAGS: tag
#+CREATED: [2020-08-22 sam. 11:13]
#+EDITED: [2020-08-22 sam. 11:13]
This is content.
for references.
I would like deft-strip-title-regexp
to show Title
(i.e. #+title:
value, preferably without the prefix). Original value hides the title prefix but not the :PROPERTIES:
drawer.
(setq deft-strip-title-regexp
(concat
"\\(?:^%+\\|^#\\+TITLE: *\\|^[#* ]+\\|-\\*-[[:alpha:]]+-\\*-\\|^Title:[ ]*\\|#+$\\)"
))
Following suggestion above, I tried to implement regex for skipping :PROPERTIES:
with no success:
(setq deft-strip-title-regexp
(concat
"\\(?:^%+\\|^#\\+TITLE: *\\|^[#* ]+\\|-\\*-[[:alpha:]]+-\\*-\\|^Title:[ ]*\\|#+$\\)"
":PROPERTIES:\n\\(.+\n\\)+:END:"
))
Maybe @TRSx80 could tell me what is wrong in my implementation?
Concerning deft-strip-summary-regexp
, I would like to skip the whole header and get to content:
— I think @riclage solution doesn't fit to my context
— @TRSx80 idea looks great, but it only gets me to #+ROAM_TAGS:
for regular files and to #+CREATED:
for reference files.
Would you have an idea how to formulate the regex?
@tea4or2wo,
If I were you, and you are sure your files will always look like this (as you have shown here), I would get rid of the complicated default altogether (you can save it in a comment if you like) and build a new one up from scratch. There are some hints (and examples) above how to do that.
For your deft-strip-title-regexp
, you need to essentially remove everything from :PROPERTIES:
thru #+title:
.
For deft-strip-summary-regexp
, the same, but you need to also include newlines, and go all the way through the entire line that starts with #+EDITED: [...]
.
In the meantime, I actually moved away from deft, for lots of reasons, but something like this sort of complexity just being one of the small ones. In fact I ended up implementing my own solution which is much simpler and more in line with Emacs native way of doing things, including leveraging Orgmode a lot more. I haven't published it anywhere yet, but I plan to at some point.
In case other people will run into the issue with the title not being shown in deft (which presumably will, as org-roam v2 will put those :PROPERTY:
drawers at the top of each file by default), it should be pointed out that a little change to deft.el might be necessary.
The function deft-parse-title
will currently return the first line through the regex expression "^.+$"
: https://github.com/jrblevin/deft/blob/c4af44827f4257e7619e63abfd22094a29a9ab52/deft.el#L1082
So it isn't possible to use deft-strip-title-regexp
in this scenario. To get the line that contains the title instead, this could be replaced by "^#\\+TITLE.+"
.
Would it perhaps be possible to carve this expression out as defcustom
so that it can be easily customized?
Not s full solution, but there is the deft-use-filename-as-title
option, which (partially) solved the org-roam-v2 issue for me (I still have the big number at the start of the filename, but this is an improvement on just PROPERTIES being shown.)
So in the end my config is
(after! deft
(setq deft-recursive t)
(setq deft-directory "~/Documents/org/roam/")
(setq deft-strip-summary-regexp ":PROPERTIES:\n\\(.+\n\\)+:END:\n")
(setq deft-use-filename-as-title 't)
)
Wouldn’t it be a better solution to consider first paragraph instead of first line to be parsed for title ?
Same idea for second paragraph to search for a summary.
This would be a simple extension to what exists now, including current behavior as a particular case of single line paragraphs.
Why can't you not simple set the value of #+TITLE as the title in deft :sweat_smile:
This is what I did to get deft working with org-roam v2. I think someone who's better familiar with how deft would like these settings to work would know best how to turn it into a usable patch (notably, I disagree some with the styling of using regexes for "stripping" things, rather than settings to say "use TITLE" or "use filename" or "use title" etc).
Instead of reading in each line, and "stripping" out whatever, I just overrode everything since I knew I wanted the first #+title:
in each file:
(defun cm/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 #'cm/deft-parse-title)
(setq deft-strip-summary-regexp
(concat "\\("
"[\n\t]" ;; blank
"\\|^#\\+[[:alpha:]_]+:.*$" ;; org-mode metadata
"\\|^:PROPERTIES:\n\\(.+\n\\)+:END:\n"
"\\)"))
This will find the first instance of #+title:
or #+TITLE:
in your file, and use it as the title. I don't use filenames as titles, but if there is no #+title:
, I use the filename as fallback.
My deft-strip-summary-regexp
does well enough to skip all property drawers, along with org-mode metadata and blanks.
I had the same problem with my deft buffer not displaying as I wanted after the upgrade to org-roam v2. I don't think there is anything new here, but maybe it is consolidated in a way to help others. I used an advice-add
to override the deft-parse-title
function. That seemed to give me an easier way to adapt to my use case. Maybe others will find it useful.
In my init.el I have a declaration for the summary that strips many of the lines I don't want.
(use-package deft
:commands (deft)
:config
(setq deft-directory "~/org/deft/")
(setq deft-recursive t)
(setq deft-strip-summary-regexp
(concat "\\("
"^:.+:.*\n" ; any line with a :SOMETHING:
"\\|^#\\+.*\n" ; anyline starting with a #+
"\\|^\\*.+.*\n" ; anyline where an asterisk starts the line
"\\)"))
)
This is followed by an override of the deft-parse-title
function like this.
(advice-add 'deft-parse-title :override
(lambda (file contents)
(if deft-use-filename-as-title
(deft-base-filename file)
(let* ((case-fold-search 't)
(begin (string-match "title: " contents))
(end-of-begin (match-end 0))
(end (string-match "\n" contents begin)))
(if begin
(substring contents end-of-begin end)
(format "%s" file))))))
Note this depends on the fact that I want the "title" line and all my files have them, but others might be able to adapt the code to their own use.