org-noter / org-noter

Emacs document annotator, using Org-mode
GNU General Public License v3.0
148 stars 18 forks source link

Standardisation of the file creation process #16

Closed chatziiola closed 1 month ago

chatziiola commented 1 year ago

I was searching through the issues to see if there was a flag allowing for the completely opposite functionality (of the one described at #15) so I suppose that maybe writing here may let us (me?) get a better understanding.

The problem I have is that I want separate org files for each entry. I also want them to be automatically created using the documents filename, in the specified directory (org-noter-notes-search-path). Instead of that, I find myself in the cumbersome process of manually selecting between the default file name and the suggested one, as well as between the different path options.

That selection occurs at this point in org-noter and seems to me like what @dmitrym0 suggests, though I most probably am wrong.

            (let* ((notes-file-name (completing-read "What name do you want the notes to have? "
                                                     search-names nil t))
                   list-of-possible-targets
                   target)

I hope that this is not something silly that I simply have missed. I read what was available and played around with my configuration before posting here.

dmitrym0 commented 1 year ago

👍

I think we're talking about similar functionality as far as I can tell. I'd like the flexibility of keeping my book notes in the default file, but most other PDFs in their own individual notes files. Thanks for the snippet, that's where I'll start looking.

dmitrym0 commented 1 year ago

So this is the behaviour that I'm seeing:

org-noter asks me what notes file I want:

image

then it asks me where I want the file to be saved:

image

This is already pretty dang close to what I want. org-noter is opinionated and only wants me to select from the lists provided. I want to be able to name my own notes files though, and integrate the whole flow with org-roam.

I don't see how to do what you, @chatziiola, want without code change.

chatziiola commented 1 year ago

I see, I had not thought of that so much. This reminds of when I tried to use a function like the following one by jethrokuan , creator of org roam, (the function is slightly modified by me), to eliminate any spaces in the notes' filename (and got nowhere).

Maybe designing it so that the filename generating function can be overwritten by the user is a good next step here. Any thoughts on this one?

(defun klp/sluggify (inputString)
  "Given a string return it's /sluggified/ version.
It has only one argument, INPUTSTRING, which is self-described"
  (let ((slug-trim-chars '(
               ;; Combining Diacritical Marks https://www.unicode.org/charts/PDF/U0300.pdf
                           768 ; U+0300 COMBINING GRAVE ACCENT
                           769 ; U+0301 COMBINING ACUTE ACCENT
                           770 ; U+0302 COMBINING CIRCUMFLEX ACCENT
                           771 ; U+0303 COMBINING TILDE
                           772 ; U+0304 COMBINING MACRON
                           774 ; U+0306 COMBINING BREVE
                           775 ; U+0307 COMBINING DOT ABOVE
                           776 ; U+0308 COMBINING DIAERESIS
                           777 ; U+0309 COMBINING HOOK ABOVE
                           778 ; U+030A COMBINING RING ABOVE
                           779 ; U+030B COMBINING DOUBLE ACUTE ACCENT
                           780 ; U+030C COMBINING CARON
                           795 ; U+031B COMBINING HORN
                           803 ; U+0323 COMBINING DOT BELOW
                           804 ; U+0324 COMBINING DIAERESIS BELOW
                           805 ; U+0325 COMBINING RING BELOW
                           807 ; U+0327 COMBINING CEDILLA
                           813 ; U+032D COMBINING CIRCUMFLEX ACCENT BELOW
                           814 ; U+032E COMBINING BREVE BELOW
                           816 ; U+0330 COMBINING TILDE BELOW
                           817 ; U+0331 COMBINING MACRON BELOW
                           )))
    (cl-flet* ((nonspacing-mark-p (char) (memq char slug-trim-chars))
               (strip-nonspacing-marks (s) (ucs-normalize-NFC-string
                                            (apply #'string
                                                   (seq-remove #'nonspacing-mark-p (ucs-normalize-NFD-string s)))))
               (cl-replace (inputString pair) (replace-regexp-in-string (car pair) (cdr pair) inputString)))
      (let* ((pairs `(("[^[:alnum:][:digit:]]" . "_") ;; convert anything not alphanumeric
                      ("__*" . "_")                   ;; remove sequential underscores
                      ("^_" . "")                     ;; remove starting underscore
                      ("_$" . "")))                   ;; remove ending underscore
             (slug (-reduce-from #'cl-replace (strip-nonspacing-marks inputString) pairs)))
        (downcase slug)))))

All in all, thanks a lot for your time. I'd like to ask to keep the issue open so that I work on it (obviously on #15 too since they are so closely related) in the coming week.

dmitrym0 commented 1 year ago

Maybe designing it so that the filename generating function can be overwritten by the user is a good next step here. Any thoughts on this one?

I like this idea. Currently the process for selecting notes is very rigid. I will try to refactor it such that if a hook is defined it runs the hook instead.

This is what I've come up with so far:

  (defun get-filename-for-org-roam-node ()
  "Use the standard org-roam interface to select an existing node or create a new one and return a path to it"
    (let* (
           (templates (list (append (car org-roam-capture-templates) '(:immediate-finish t))))
           (node (org-roam-node-read))
           (_ (org-roam-capture-
               :node node
               :info nil
               :templates templates
               :props nil))
           (node-id (org-roam-node-id node))
           (file-path-for-new-entry (org-roam-node-file (org-roam-node-from-id node-id))))
      (message "%s" file-path-for-new-entry)
      file-path-for-new-entry))

Re: slugify, the MELPA version of org-roam already removes spaces for me (and replaces them with _). What's missing for your use case?

chatziiola commented 1 year ago

In my use case, I take advantage of that function in other areas too. It allows for an easy to manage file naming convention:

For example I have an ebook with the filename of: "Unix Power Tools - Shelley Powers, Jerry Peek, Tim O'Reilly.pdf". Since calibre manages my ebook library for me, and I have not really dived into its configuration, that is the actual pdf filename, and should I use org-noter on it I would get "Unix Power Tools - Shelley Powers, Jerry Peek, Tim O'Reilly.org" this filename.

It certainly is not much of a problem, which I'm describing, but if I were to use ~slugify~ on that I would get "unix_power_tools_shelley_powers_jerry_peek_tim_o_reilly.org", which is more suitable to my workflow and the way I organize my files.

It is not actually something to be implemented into org-noter, and it obviously is not something to bore you with. I just mentioned it as an example of how I would take advantage of a more fluid alternative to naming the noter file.

EDIT: Your function is more elegant than my working implementation: I would create a file X.org with org-noter (like "Unix Power Tools - Shelley Powers, Jerry Peek, Tim O'Reilly.org") and then create an org-roam note manually (or in the beginnings, I would just generate a unique ID through sluggification and put that up top). Certainly not a beautiful sight.

dmitrym0 commented 1 year ago

Here's my current progress. The most important aspect of it, is that when you M-x org-noter you get a completing read with all my org-roam nodes. It's currently a hook and therefore can be anything.

Demo video: https://www.youtube.com/watch?v=54YFv-b6grQ Code: https://github.com/org-noter/org-noter/blob/feature%2Forg-roam-integration-issue-15-16/org-noter.el#L159

chatziiola commented 1 year ago

I have been using that for the past couple days (without getting too much in depth with it ) and it works pretty smoothly. At this point the only thing I would suggest is moving on from the (org-noter--get-files-containing-notes) command to the stock one: (org-roam-list-files). It is not much but there are two main points in its favor:

  1. It does not need ag, nor the declaration of another function
  2. It allows for already existing notes to be updated-linked to the document much more easily.

(I'm thinking that we could potentially auto-tag the newly created and/or visited nodes with a noter-document tag for future uses, since it would allow for a simpler get-files-containing-notes command, should that be necessary, but on the other hand, the existing solution works smoothly, too. I'll play around and post here if I have something I consider of value).

Wonderful work!

dmitrym0 commented 1 year ago

Hey @chatziiola thanks for testing it, I'm glad it's relatively stable.

(org-noter--get-files-containing-notes) was an experiment. I thought, if you have to select the notes file every single time you open a publication, what if you forget you started in notes file 1 and open up notes file 2? This was a way to perhaps avoid this problem.

I'll rip this out for now, but in the future I might look into using org-roam itself. I wonder if there's an official way to sore extra metadata, so there's a way to surface existing notes for a publication.

I'll clean this up in the next little while and make it official.

Primarily extract the roam-specific work into it's own .el.

dmitrym0 commented 1 month ago

Closing this, support has been implemented in #39.

The documentation for this can be found in #89.