sympodius / org-novelist

Org Novelist is a system for writing novel-length fiction using Emacs Org mode.
GNU General Public License v3.0
183 stars 14 forks source link

Make content of note templates customizable? #9

Closed sthesing closed 8 months ago

sthesing commented 1 year ago

Hi @sympodius , thanks for this wonderful package!

Would you be open to make the templates of notes customizable by the user? Currently, they are hard-coded into the following constants:

Your method of structuring character notes etc. should stay the default, I think. But if a user has their own method, they could define their own content, e.g. like:

(customize-set-variable 'org-novelist-user-character-notes 
  (concat
 "** Physical Description\n"
 "** Personality\n"
 "** Background\n"
 "** Notes\n"))

One idea to do this that I could make work was to put the respective variable directly into the template if non-nil:

(defcustom orgn-user-character-notes nil
  "User defined content of character notes."
  :group 'org-novelist
  :type 'string)

(defconst orgn--character-notes-template
  (concat
   "<<mode>>\n"
   "\#\+TITLE\: <<title>>\n"
   "* <<notes-for>> /<<character-name>>/, <<indefinite-article>> "
   "\[\[file:<<character-index-file>>\]\[<<character>>\]\] <<from>> "
   "\[\[file:<<main-file>>\]\[<<story-name>>\]\].\n"
   (if orgn-user-character-notes
       orgn-user-character-notes
     "<<character-notes-content>>"))
  "The template for the story's character notes files.")

But that probably isn't a good solution, because it assumes that a single user doesn't want language-specific settings. Also the variable needs to be set before the package is loaded, because the constant won't update retroactively. Other approaches come to mind, but the complexity of your infrastructure for localization is beyond my elisp literacy.

But maybe you have a better idea how to do this... if you approve of the general idea, at all. What do you think?

sympodius commented 1 year ago

Hey @sthesing ,

Thanks for taking an interest in Org Novelist šŸ™‚

User customizable templates definitely feel like something that should be supported, and they've been on my to-do list since I first planned a public release.

The language packs themselves should provide a kludgey way to add in support for overriding the templates (just create your own language pack, and make the strings whatever you want), but I've yet to actually add other languages or fully test that idea.

I think I'd worried that making customize variables for the templates might make it too easy for people to break things. I sort of suspected people wouldn't try to make their own language pack without really knowing what they were doing šŸ¤”

Out of interest, have you tried the language pack approach? Does it work? šŸ˜‚

sthesing commented 1 year ago

Thanks for the quick reply!

Out of interest, have you tried the language pack approach? Does it work? šŸ˜‚

No, I haven't. In fact, it didn't even occur to me that creating my own language definition would be the way to go - just to get a few note skeletons :wink:. Since I don't need note templates in different languages, I followed the approach in my example, defining custom variables that effectively enable me to override the constants orgn--*-notes-content-en-GB. So I'm running a fork of your package, at the moment.

The language packs themselves should provide a kludgey way to add in support for overriding the templates (just create your own language pack, and make the strings whatever you want), but I've yet to actually add other languages or fully test that idea.

I think I'd worried that making customize variables for the templates might make it too easy for people to break things. I sort of suspected people wouldn't try to make their own language pack without really knowing what they were doing šŸ¤”

Maybe that's why no one hasn't tried it yet... :grin:.

Seriously though, I'm not sure if it's a good idea to mingle two very separate topics like support for different languages and categories of note contents. And I agree that the template system is complex enough that people could break things, just as easily as by wrongly defining their own language packs.

Maybe a simpler approach would be to turn the content of constants like orgn--chapter-notes-content-en-GB into default values of customizations that the user can override by setting them herself? That wouldn't touch the template or language system at all. And I don't think there's much danger of breaking things, either. The worst that can happen is that the notes are created with nonsense content...

sympodius commented 1 year ago

It's a tricky one. One of the main reasons I sought to create multi-language support was to have the templates available in different languages, so I wouldn't say they are disparate things. However, that's not to say that people wouldn't also want to create templates separate from their chosen language pack's default.

As you say, some sort of override system would probably make this easier than creating entire custom language packs, but I'd need to investigate the ramifications a bit more and do some testing to see what the dangers are. The cross references generator, for example, might make assumptions about note templates, and I'd need to see how bad that could be.

It might also be possible to have a language pack inheritance system where you can designate a base language pack and just override the bits you want to, but that seems like overkill when the language packs aren't (currently) very large.

In an ideal world, you'd just select your language and then override any strings you want with customize variables, but that could get messy in the customize interface. Restricting it to just templates might not be too bad, as long as it was safe enough.

sthesing commented 1 year ago

In an ideal world, you'd just select your language and then override any strings you want with customize variables, but that could get messy in the customize interface. Restricting it to just templates might not be too bad, as long as it was safe enough.

I don't really work with the customization UI (because it usually is too messy for me). But I looked up my custom setting there, and it's not so bad. After all, in the end, the note content skeleton is just a string.

screenshot_2023-09-12T18:08:09

At the end of the day, preventing errors is probably just a question of providing documentation and examples. Using use-package as you did in the installation instructions, this doesn't look like lisp-witchcraft, either.

(use-package org-novelist
    :ensure nil
    :load-path "~/path/to/org-novelist/"
    :custom
    (org-novelist-user-character-notes
     (concat
      "** Role in Story\n"
      "** Physical Description\n"
      "** Background\n"
      "** Occupation\n"
      "** Personality\n"
      "** Habits/Mannerisms\n"
      "** What Does This Character Want?\n"
      "** What Transformation Does This Character Experience?\n"
      "** Notes\n")))

But you know your code best.

The cross references generator, for example, might make assumptions about note templates, and I'd need to see how bad that could be.

I didn't think of that, for example.

Anyway, my fork is a solution that works for me, so no pressure from my side. If you need an opinion or someone to test something, just say the word.

sympodius commented 1 year ago

I've had a quick look at the code that touches the notes files and I think it should be fine. The only potential problem I can see is if someone added in their own "Appearances in Chapters" heading somewhere in their templates, as it would likely end up getting deleted and replaced (along with all its contents) whenever the references were updated. However... this is also true of any current notes files, so it's not really adding any additional risk šŸ˜‚

I'll code up a solution and let you know when it's in the development branch if you still fancy giving it a whirl, @sthesing ?

sthesing commented 1 year ago

I'll code up a solution and let you know when it's in the development branch if you still fancy giving it a whirl, @sthesing ?

Sure, I'm game. :+1:

sympodius commented 8 months ago

This is in the development branch now. Thanks for the suggestion!