EFLS / zetteldeft

A Zettelkasten system! Or rather, some functions on top of the emacs deft package.
https://efls.github.io/zetteldeft
GNU General Public License v3.0
394 stars 42 forks source link

Proposal for custom ID generation #68

Closed jeffvalk closed 4 years ago

jeffvalk commented 4 years ago

Overview

Allow a user to specify a custom function for ID generation. The current ID generation function would be the default implementation and the only one provided by zetteldeft itself.

This is a pretty "light touch" proposal, intended to add flexibility without complexity.

Background

I like timestamp-based IDs; they make good sense for notes. My use case for this proposal comes from "upgrading" existing notes to be zetteldeft notes (having IDs). When assigning an ID to an existing note, I'd prefer the timestamp be based on the file's create date/time, rather than the current time.

My use case is half addressed by the patch I posted here for #63, which has Zetteldeft's rename function automatically generate an ID if one isn't present. Simple enough. What remains is to allow a user-specified ID generation function to be used.

Proposed Approach

  1. Make zetteldeft-generate-id a custom variable that points to a function. Document that the function must accept optional arguments for title and (existing) file path; this enables an implementing function to consider all available note attributes when generating the ID.
  2. Rename the current ID generation function to zetteldeft-generate-id-from-current-time (or similar), and update its argument signature. The function body would stay the same.
  3. Make zetteldeft-generate-id-from-current-time (or whatever we name this) the default value for zetteldeft-generate-id.
  4. When creating a new note, pass title as an argument to zetteldeft-generate-id.
  5. When renaming an existing note, pass title and file path as arguments to zetteldeft-generate-id.

The default implementation will ignore the additional arguments. Custom implementations may use these however they like (including examining file system metadata, or reading the file and parsing its contents).

Additional Thoughts

The output of a custom ID generation function could be anything. It would be up to the user to ensure the ID regex is compatible, just as it is currently.

This may be sufficient to address #66 as well...or at least allow someone to have a go at this.

EFLS commented 4 years ago

Thanks for your detailed explanation. The patch you linked to is great because of its reversal of approach.

Changing the zetteldeft-generate-id behaviour shouldn't be too complex, as the function is only called upon twice.

There are still some questions, though

Perhaps this discussion is also of interest to @gklimowicz and his experiments with different types of IDs (as in #66)? Or rather, are there things we need to take into account?

jeffvalk commented 4 years ago

How many (and which) arguments would the custom function need to be able to process? Only title and path?

Yes. Those two things enable access to everything that can be known about the note. In the case of a new note, only the title would be known at the time of ID generation. For a note being renamed, the existing file would also be available.

The argument list would be (&optional title filename) or (title &optional filename). The function could simply ignore the extra information, as with the default:

;; Default implementatioon in zetteldeft.el
(defun zetteldeft-generate-id-from-current-time (&optional title filename)
  "Generate an ID in the format of `zetteldeft-id-format'."
  (format-time-string zetteldeft-id-format))

...or use the available information however it likes in a custom function:

;; Hypothetical custom function in user's init.el
(defun zetteldeft-generate-id-custom-example (&optional title filename)
  "Generate an ID exactly the way I like it"
  (if (and title filename)
      (concat
       (random-anagram title)
       (cryptographic-hash filename))
    (zetteldeft-generate-id-from-current-time)))

(setq zetteldeft-generate-id 'zetteldeft-generate-id-custom-example)

That's the general idea, anyway. If there are other thoughts or use cases that might shape this, I'd be interested to hear them.

jeffvalk commented 4 years ago

Is the use case not too specific? I mean, is it useful for things other than renaming existing notes? (I don't mean this to be negative, just asking before considering increased complexity)

It's a valid question. I initially considered my use case to be a one-off that didn't merit any changes to zetteldeft. When I saw there were other issues (such as #66) around ID generation, I reconsidered. I figured it was a worth a discussion.

My thinking is this:

I'd also be interested in @gklimowicz's thoughts based on #66.

I'm happy to put together a patch for discussion purposes, if this seems worth considering.

jeffvalk commented 4 years ago

For consideration, here is a patch with commentary that enables the custom ID generation. It's minimal, and leaves default behavior untouched.

EFLS commented 4 years ago

Looks great. I'll try to take a closer look when I have more time. Feel free to submit this as a PR! And thanks for using Org-mode blocks.

jeffvalk commented 4 years ago

That commit is based on my patch for #42, so I think it would be most efficient to resolve #42 first. Once that's done, I'll submit a PR.

EFLS commented 4 years ago

Really happy with these changes, thanks again @jeffvalk!