hgiesel / closet

The Web Framework for Flashcards
https://closetengine.com
GNU General Public License v3.0
65 stars 6 forks source link

[usability] Simplify/declutter syntax for lists #56

Open kleinerpirat opened 3 years ago

kleinerpirat commented 3 years ago

Do you intend to implement the same sort of syntax highlighting you're using on your website for the add-on?

Without visual cues, Closet cards can get confusing rather quickly. For image occlusions with clozes and picking I'm currently wrapping text with <span> elements of two different classes in the editor, which are translated to commands in the template. Without this, it would be unfeasible to create big notes:

image Humans are good at pattern recognition, but we're not robots.

I would prefer to keep things as vanilla as possible, but without syntax highlighting (or even better, a way of using Closet via interactive HTML-elements *), I can't see myself (and much less my friends) using standard Closet commands for this type of notes.


* This is something I have experimented on during the christmas holidays, but university caught up to me and I had to drop this endeavour. Probably for the best, because Closet is still undergoing a lot of changes.

hgiesel commented 3 years ago

I had this concern myself for some time already.

  1. One method for decreasing declutter was implemented in the last update, and that's block tags + optics. This would let you skip those individual setl commands, like so:

[[#forli::setl]]
1. First item
2. Second item
[[/]]

which is then translated to:

1. [[setl1::First item]]
2. [[setl2::Second item]]

That's not exactly the same that you have, but functionally. I could also implement one version, that consumes the list, while it is replacing.

2. The second method, using colored spans for indicating Closet elements, can work as well, the question is just what the implementation should look like. A few ideas I had:

  1. Use Syntax Highlighting, like on the website. Right now I don't know how exactly it will work out in practice. Hopefully without any blinking between renders. I'm also not sure how helpful it would be, because different elements would still look alike (e.g. your iocm and ioce elements).
  2. I could implement a "pre-template step", that scans the template text for specific HTML elements. For example for elements using data-closet as an attribute:
    <span data-closet="iocm0">Cholin<span> wird über <span data-closet="iocm0">Cholin-Transporter (CHT1)</span> in die Nervenzelle aufgenommen.
    // and transforms them to:
    [[iocm0::Cholin]] wird über [[iocm0::Cholin-Transporter (CHT1)]] in die Nervenzelle aufgenommen. 
    // you could style them like so:
    [data-closet="iocm0"] {
    /* ... */
    }

    The issue with those would be, they might also be confusing, if they end up empty, and they're not visible in the fields anymore.

Do you have any other suggestion / or what did you envision?

kleinerpirat commented 3 years ago

One method for decreasing declutter was implemented in the last update, and that's block tags + optics.

This is beautiful. Thanks for that!

I could implement a "pre-template step", that scans the template text for specific HTML elements.

So this would basically the same thing I am doing with my template script. So far, it worked surprisingly well for my specific use case.

Naive babble I share your concern about empty spans. Perhaps there is a way to prevent such elements from becoming invisible zero-width remnants... - Maybe requiring them to be deleted a specific way, like via a clickable "X"-tooltip... - Shift+click deletes image occlusion rectangles. Maybe the same could be used to delete these span elements in a controlled manner. - Or you could scan for empty Closet elements and clean them up via JS. Deleting an element would remove the span and leave only the text. Another issue is that with the current Anki editor, classes cannot be deleted via Ctrl+Z. And if you select the end of such a ``, there is no easy way to jump out of one, as far as I know. ---- ### What I tried: When I played around with a visual approach around Christmas, I translated specific ``'s to plain Closet commands when notes were saved (add/switch/close browser), so the database entries would always contain pure Closet content. On load, a note's plain commands would be translated to the visual, HTML style again. The thought behind this was to keep the standard syntax available for mobile editing, but show it in a more friendly way on desktop. --- **Disclaimer:** The following vision ~~may sound~~ *is* bonkers and I don't expect any form of approval for it 😄 ### A vision for Closet elements I envisioned these HTML elements to be _more than just a replacement for the standard tags_, but a significant enhancement. With a little group of tooltips/menus expanding on click, you would modify their respective commands, their index, their tag-type, delete them etc. Here's a little mockup of what I'm thinking of: ![mockup](https://user-images.githubusercontent.com/62722460/111051924-0c668a80-8457-11eb-9d56-fee72b45aac9.png) - Different tag-types could have distinct colors/styles. The little notification-circles could indicate the card index via numbers + different colors. - That link symbol to the left could represent [selective activation](https://closetengine.com/flashcard/activating-selectively#selectively-activating-tags) via.. well, selecting elements (like "show c:1 on c4's card"). - You could show a menu (within the tooltip, see the [Dropdown example of Tippy.js](https://atomiks.github.io/tippyjs/#html-content)) where you select the cards an element will be active/shown/hidden on via checkboxes. - You could visualize complex intertwined commands (multiple tags with different indices activated on one card due to commands): e.g. Hovering/clicking an element highlights all other elements that belong to the same card ("linked elements", so to speak) and grays out the others. **I think this vision would need its own add-on to keep visual programming _optional_ OR a switching functionality between fancy and raw editing within the Closet add-on.** _Side note: If you know the PlayStation game series Little Big Planet: I think that's where my love for visually pleasing ways of creating stuff stems from._ ---

Enough dreaming for today. Simple syntax highlighting would be a great improvement already 👍🏻

kleinerpirat commented 3 years ago

Now that you'll soon be working on Closet again, I wanted to give you a brief update on how I tackle this issue nowadays.

I have fully committed to a visual pre-template syntax that is heavily focused on lists and implicit logic.

Some examples

Clozes or hints are marked with HTML tags like <u>, <i>, and <strike> (all execCommands that can be toggled) instead of <span>'s because they are handled better by the webkit and they all have individual closing tags, which makes batch changes much easier. Their appearance is modified with shadow-root stylesheets.

I won't bother you with more details. Just rest assured that I am happy with the way Closet tags work right now, that my vision in the comment above was a bit narrow-minded and that there are plenty of ways to use Closet the way you want.

kleinerpirat commented 2 years ago

Hey Henrik, Things have changed in my workflow once again and I'd like to get back to you on this example for block tags + optics:

[[#forli::setl]]
1. First item
2. Second item
[[/]]

I got this generic function to translate list items into closet commands, where the switch block will be expanded for a number of tags:

filterManager.registrar.register(
   "forli",
   e => {
      const { hasBlock, hasInline, inlineValues, blockValues } = e;

      if (hasInline) {
         const [tag, ...args] = inlineValues;

         switch (tag) {
            case "setl": {
               return setl(args, blockValues); /* <- What to do with this output? */
            }
         }
      } else return null;
   },
   {
      inlineOptics: [
         closet.template.optics.separated({ sep: "::", trim: true }),
      ],
      blockOptics: [
         closet.template.optics.templated({
            before: "<li>",
            after: "</li>",
         }),
      ],
   }
);

Instead of reimplementing the standard effects within the user setup, I'd like to convert block values into existing tags (mc, setl, etc.) and rely mostly on Closet's predefined recipes.

Say my function setl() returns

[[setl1::First item]][[setl2::Second item]][[sel]]

How would I proceed? Should I reiterate over that output with Closet? Or is there an easy way to invoke the respective functions directly within setl() without another parsing round?

kleinerpirat commented 2 years ago

You mentioned on the add-on download page that Closet can detect meaningful content (such as list items). The only example for lists I could find is this one: https://github.com/hgiesel/closet/blob/766b4233f641725ff018cba72aba1ed736451fd7/docs/_data/setups/templated_shuffle.yml#L14-L21

But that wouldn't work for nested lists. "Meaningful" makes me think of DOM traversal :thinking: But I haven't found anything like that yet, so for now, I'm reopening the issue :)