Skip to content

Commit

Permalink
Enable titles to have commas, support multiline properties generally
Browse files Browse the repository at this point in the history
Now properties can have multiple lines in the metadata section. The new const
ekg-property-multivalue-type controls how multivalued properties act. This fixes
#110.
  • Loading branch information
ahyatt committed Oct 29, 2023
1 parent cb42e4c commit cc20f36
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 18 deletions.
1 change: 1 addition & 0 deletions doc/ekg.org
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ Clone the ekg library, from whatever branch you would like to use (=main= corres
- Fix inclusion of title-based transclusion ">t", which included the "t" as part of the completion.
- Fix tag renaming possibly causing duplication.
- Ensure renamed tags are normalized.
- Support metadata where fields are specified via multiple property lines and make "title" such a field, so now titles can have commas.
** Version 0.4.1
- Fix issues using default emacs in-buffer completion, and allowing completion in places we shouldn't.
- Add =ekg-embedding-generate-on-save= and =ekg-embedding-disable-generate-on-save= to turn off generating embeddings for notes.
Expand Down
2 changes: 2 additions & 0 deletions doc/ekg.texi
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,8 @@ Fix inclusion of title-based transclusion ">t", which included the "t" as part o
Fix tag renaming possibly causing duplication.
@item
Ensure renamed tags are normalized.
@item
Support metadata where fields are specified via multiple property lines and make "title" such a field, so now titles can have commas.
@end itemize

@node Version 041
Expand Down
64 changes: 46 additions & 18 deletions ekg.el
Original file line number Diff line number Diff line change
Expand Up @@ -180,9 +180,18 @@ backups in your database after it has been created, run
(defvar ekg-metadata-parsers '(("Tags" . ekg--metadata-update-tag)
("Resource" . ekg--metadata-update-resource)
("Title" . ekg--metadata-update-title))
"Metadata fields to functions for updating data based on buffer test.
Each function updates the buffer's `ekg-note' with the results of the field.
The function takes one argument, the field metadata property value.")
"Metadata fields to functions for updating data based on buffer text.
Each function updates the buffer's `ekg-note' with the results of
the field. The function takes one argument, a list of the field
metadata property values for multivalue types, or a single one
for single value types. If `ekg-property-multivalue-type' has an
entry, it is a multivalue type.")

(defconst ekg-property-multivalue-type '(("Tags" . comma)
("Title" . line))
"Defines per typehow multiple values are separated.
The values are symbols, COMMA means a comma-separated value. LINE
means each value gets its own property line.")

(defvar ekg-metadata-labels '((:titled/title . "Title"))
"Alist of properties that can be on the note and their labels.
Expand Down Expand Up @@ -892,13 +901,18 @@ The ID represents meaningful resource to the user, other than auto-generated id.
(mapconcat (lambda (tag) (format "%s" tag))
(ekg-note-tags note) ", ")))
(map-apply (lambda (k v)
(when-let (label (cdr (assoc k ekg-metadata-labels)))
(insert (ekg--metadata-string
label
(if (listp v)
(mapconcat (lambda (v) (format "%s" v))
v ", ")
(format "%s" v))))))
(when-let ((label (assoc-default k ekg-metadata-labels)))
(if (listp v)
(pcase (assoc-default label ekg-property-multivalue-type)
('line (cl-loop for val in v do
(insert (ekg--metadata-string label val))))
('comma (insert (ekg--metadata-string
label
(if (listp v)

(mapconcat (lambda (v) (format "%s" v))
v ", ")
(format "%s" v)))))))))
(ekg-note-properties note))
(buffer-string))))

Expand Down Expand Up @@ -1177,8 +1191,13 @@ attempt the completion."
(save-excursion (skip-chars-forward "^:\s\t\n") (point))
(completion-table-dynamic
(lambda (_)
;; Complete all fields, except single-value fields (which have no
;; entry in ekg-property-multivalue-type) with an existing field
;; already in existence.
(seq-difference (mapcar #'car ekg-metadata-parsers)
(mapcar #'car (ekg--metadata-fields nil)))))))
(seq-difference
(mapcar #'car (ekg--metadata-fields nil))
(mapcar #'car ekg-property-multivalue-type)))))))

(defun ekg--tags-cap-exit (completion finished)
"Cleanup after completion at point happened in a tag.
Expand Down Expand Up @@ -1243,13 +1262,12 @@ The metadata fields are comma separated."

(defun ekg--metadata-update-tag (val)
"Update the tag field from the metadata VAL."
(setf (ekg-note-tags ekg-note) (ekg--split-metadata-string val)))
(setf (ekg-note-tags ekg-note) val))

(defun ekg--metadata-update-title (val)
"Update the title field from the metadata VAL."
(setf (ekg-note-properties ekg-note)
(plist-put (ekg-note-properties ekg-note) :titled/title
(ekg--split-metadata-string val))))
(plist-put (ekg-note-properties ekg-note) :titled/title val)))

(defun ekg--metadata-update-resource (val)
"Update the resource to the metadata VAL."
Expand All @@ -1272,11 +1290,21 @@ If EXPECT-VALID is true, warn when we encounter an unparseable field."

(defun ekg--update-from-metadata ()
"Update the `ekg-note' object from the metadata."
(cl-loop for field in (ekg--metadata-fields t)
(cl-loop with values = (make-hash-table :test 'equal)
for (field . value) in (ekg--metadata-fields t)
do
(if-let (func (assoc (car field) ekg-metadata-parsers))
(funcall (cdr func) (cdr field))
(warn "EKG: No function found for field %s" (car field)))))
(pcase (assoc-default field ekg-property-multivalue-type)
('line (push value (gethash field values)))

This comment has been minimized.

Copy link
@qingshuizheng

qingshuizheng Dec 20, 2023

Contributor

Empty string should be excluded when being parsed? So change this line to:

('line (unless (string-empty-p value) (push value (gethash field values))))

Before:

#s(ekg-note 33521945315 "abcdefg" org-mode ("date/2023-12-19") 1702973577 1702978094 (:titled/title ("" "b")) nil)

After:

#s(ekg-note 33521945315 "abcdefg" org-mode ("date/2023-12-19" "test") 1702973577 1703069394 (:titled/title ("b")) nil)

This comment has been minimized.

Copy link
@qingshuizheng

qingshuizheng Dec 20, 2023

Contributor

The tags line is dealt correctly, no need to change.

This comment has been minimized.

Copy link
@qingshuizheng

qingshuizheng Dec 20, 2023

Contributor

Wait, there's another issue here.

Deleting title string to empty doesn't seem to remove the title slot in ekg-note by running ekg--update-from-metadata. Let me check it and come back later.

This comment has been minimized.

Copy link
@qingshuizheng

qingshuizheng Dec 21, 2023

Contributor

Actually there's two title-related issues:

  1. ekg--update-from-metadata is collecting empty titles
  2. delete title to empty doesn't really delete title in db.

Since this is only part of it, I created a new issue here: #126

Apologize for the distraction :-(

This comment has been minimized.

Copy link
@ahyatt

ahyatt Dec 23, 2023

Author Owner

Thanks for noticing this, I checked in the fix you suggested.

This comment has been minimized.

Copy link
@qingshuizheng

qingshuizheng Dec 23, 2023

Contributor

Thanks! 😄

('comma (push (ekg--split-metadata-string value) (gethash field values)))
(_ (setf (gethash field values) value)))
finally return
(maphash (lambda (key val)
(if-let (func (assoc key ekg-metadata-parsers))
(funcall (cdr func) (if (listp val)
(nreverse (flatten-list val))
val))
(warn "EKG: No function found for field %s" key)))
values)))

(defun ekg-capture-finalize ()
"Save the current note."
Expand Down

0 comments on commit cc20f36

Please sign in to comment.