Ability to generate nested cloze

It would be great if it was possible to create nested clozes. For example if I wanted to learn “The first three letters of the alphabet are abc”

I would create a nested cloze for {{c4:: {{c1::a}}{{c2::b}}{{c3::c}} }} . Which would generate four, three where only one letter is hidden, and one where all are hidden

3 Likes

I just wanted to bump this thread and also ask the devs if a PR to this end would be welcome? From glancing at the code it seems it would only require some changes in clozes.rs?

2 Likes

While this feels like a bit of a niche feature to me, if the PR is clean and does not introduce regressions, I can’t see a strong reason for rejecting it.

3 Likes

Ok, I have started to sketch on one, will make a PR once I’ve had the time to finish it.

2 Likes

@TRIAEIOU you are evil I wanted to contribute to anki :frowning: /s

let string1 =
   "The war was {{c3::{{c2::19::it was the last century}}{{c1::42}}}}";
let string2 = "The war was {{c2::{{c3::19}}{{c1::42}}}}";
let string3 = "The war was {{c1::{{c2::19}}{{c3::42}}}}";
let string4 =
   "The first world war begon {{c1::{{c2::19}}{{c3::36}}}} and ended {{c4::{{c5::19}}{{c6::42}}}}";
let string5 = "This is a {{c2::cloze}} not a {{c1::question}}";
let string6 = "This is a {{c1::cloze}} not a {{c2::question}}";

let is_nested_cloze = /{{c\d+::.*?}}}}/g;
let remove_cloze = /{{c\d+::|((::.*?)?}})/g;
let get_cloze_answer = /(?<={{c\d+::).*?((?=::)|(?=}}))/g;

function generate_cloze(string) {
   let nested_cloze = string.match(is_nested_cloze);
   if (nested_cloze) {
      for (let i = 0; i < nested_cloze.length; i++) {
         let clozes = nested_cloze[i].slice(6);
         clozes = clozes.match(get_cloze_answer);
         console.log({ clozes });
         clozes.forEach((answer) => {
            let get_cloze = new RegExp(`({{c\\d+::)${answer}.*?(}})`, "g");
            let match = string.match(get_cloze);
            let question = string.replaceAll(get_cloze, "[...]");
            question = question.replaceAll(remove_cloze, "");
            console.log({ question, answer, match, get_cloze });
         });
         let answer = clozes.reduce((result, element) => result + element, "");
         let question = string.replace(nested_cloze, "[...]");
         question = question.replaceAll(remove_cloze, "");
         console.log({ nested_cloze, answer, question });
      }
   }
}

generate_cloze(string1);
generate_cloze(string2);
generate_cloze(string3);
generate_cloze(string4);
generate_cloze(string5);
generate_cloze(string6);

here is someone who has already done it if you insist on writing it

2 Likes

Unless I am mistaken that is JavaScript, so for “client side” parsing of the note {{Text}}?

I was looking at doing it in the rust backend, through a simplistic state machine to parse the clozes in cloze.rs.

Cheers

1 Like

I also planned of doing it in rust. But I used javascript to prototype the algorithm. Since programming with rust takes more time.

1 Like

If you want to do it you are more than welcome to run with the ball :slight_smile: I simply wanted the functionality! FWIW I am not sure regex is the way to go, as far as I understand the rust implementation lacks recursive patterns which I think would be needed to make it clean. Let me know if you decide to run with it - then I wont.

Cheers

1 Like

I am struggling a lot. It would be better if you implemented it.

1 Like

Love this, I’ve been waiting for this for years :slight_smile:

1 Like