Unifikovat handling jazyka s pandocem (možná support všech pandočích variables?) #21

Closed
opened 1 year ago by jan · 13 comments
jan commented 1 year ago
https://pandoc.org/MANUAL.html#language-variables
jan changed title from Unifikovat handling jazyka s pandocem to Unifikovat handling jazyka s pandocem (možná support všech pandočích variables?) 1 year ago
jan commented 1 year ago
Poster
https://pandoc.org/MANUAL.html#variables
jan commented 1 year ago
Poster

https://pandoc.org/MANUAL.html#language-variables

Pandoc umožňuje nastavovat jazyk spanům a divům. Pro nás je to technicky trochu přes ruku, protože kontext, součástí kterýho je i jazyk, si handlujeme jinak, na úrovni dokumentů a Groups. Tohle jde vyřešit více způsoby.

  1. Handlovat attribut jazyka extra speciálně a vyrobit helper funkci get_lang, která se zeptá kontextu a ještě rekurzivně elementu a jeho rodičů.

    Tady je trochu na houby, že není jasné, jak určit, jestli má prioritu element nebo kontext, protože pokud atribut určuje nějaký hodně vzdálený rodič elementu, ale kontext je níže, nemáme to jak poznat.

  2. Proměnit všechny Spany a Divy na Groupy. Zjednoduší se tím syntaxe, nebude potřeba vlastní třída Group (prostě transform bude Spany a Divy handlovat jako by to byly Groupy), na druhou stranu nebude možný použít span na jiný účely bez zagrupování kontextu. Vadí to? Jediné co mě napadá je, že všechna metadata se pak budou předávat jen pomocí attributů, což neumožní mít víc fancy atributy, který by vyžadovaly složitější syntaxi YAMLu. (To je možná dobře? 😁)

  3. Nebýt konzistentní s pandocem.

    1. Můžeme si trvat na svém systému a být komplet oddělení od pandocu
    2. Můžeme přejmenovat náš atribut a metadatum language na lang, a všechno nechat stejné
    3. Předělat syntaxi Group tak, aby používaly Spany a Divy se třídou .group místo CodeBlocků. To má stejný problém s fancy atributy jako 2.

Thoughts @mj, @jirikalvoda ?

#19 s tímto souvisí.

> https://pandoc.org/MANUAL.html#language-variables Pandoc umožňuje nastavovat jazyk spanům a divům. Pro nás je to technicky trochu přes ruku, protože kontext, součástí kterýho je i jazyk, si handlujeme jinak, na úrovni dokumentů a `Group`s. Tohle jde vyřešit více způsoby. 1. Handlovat attribut jazyka extra speciálně a vyrobit helper funkci `get_lang`, která se zeptá kontextu a ještě rekurzivně elementu a jeho rodičů. Tady je trochu na houby, že není jasné, jak určit, jestli má prioritu element nebo kontext, protože pokud atribut určuje nějaký hodně vzdálený rodič elementu, ale kontext je níže, nemáme to jak poznat. 2. Proměnit všechny Spany a Divy na Groupy. Zjednoduší se tím syntaxe, nebude potřeba vlastní třída Group (prostě transform bude Spany a Divy handlovat jako by to byly Groupy), na druhou stranu nebude možný použít span na jiný účely bez zagrupování kontextu. Vadí to? Jediné co mě napadá je, že všechna metadata se pak budou předávat jen pomocí attributů, což neumožní mít víc fancy atributy, který by vyžadovaly složitější syntaxi YAMLu. (To je možná dobře? 😁) 3. Nebýt konzistentní s pandocem. 1. Můžeme si trvat na svém systému a být komplet oddělení od pandocu 2. Můžeme přejmenovat náš atribut a metadatum `language` na `lang`, a všechno nechat stejné 3. Předělat syntaxi Group tak, aby používaly Spany a Divy se třídou `.group` místo CodeBlocků. To má stejný problém s fancy atributy jako 2. Thoughts @mj, @jirikalvoda ? #19 s tímto souvisí.
mj commented 1 year ago
Owner

Pardon, že odpovídám až teď, ale pořád jsem v tom neměl jasno...

Vyřešil bych to drobným zobecněním kontextů. Kontext si představuji jako nějakou množinu metadat, definic příkazů a podobných věcí. Může se odkazovat na nadřazený kontext, ve kterém se hledají metadata nedefinovaná aktuálním kontextem (zatím to implementujeme kopií nadřazeného kontextu; jestli je to rozumné, teď odkládám).
Také může definovat množinu atributů, které se mají překládat na metadata.

Objekt Group se chová jako lokální výměna kontextu pro všechno, co je ve stromu pod ním. Mimo to generuje (volitelně?) TeXovou skupinu.

Když je ve zdrojáku group nebo partial, vznikne objekt Group s novým kontextem.

Když je ve zdrojáku div nebo span, podíváme se, jestli má nějaké atributy prohlášené aktuálním kontextem za metadatové. Pokud ano, vložíme nad něj do stromu Group s novým kontextem, ve kterém podle atributů nastavíme příslušná metadata.

Při procházení stromu si vždy udržujeme, který kontext je aktuální. Transform to už dělá, generátor ještě ne – tam to asi můžeme udržovat v atributu generátorového objektu.

Bylo by hezké, kdyby kontext mohly ovlivňovat i uživatelské pythoní funkce. Minimálně se ptát na metadata a přenastavovat je. Případně vracejí-li podstrom, mohou si v něm samy založit Group s novým kontextem.

(Vlastně je to skoro Tvé řešení č. 2, ale příjde mi hezčí oddělit sémantiku přepínání kontextů od Divů a Spanů.)

Pardon, že odpovídám až teď, ale pořád jsem v tom neměl jasno... Vyřešil bych to drobným zobecněním kontextů. Kontext si představuji jako nějakou množinu metadat, definic příkazů a podobných věcí. Může se odkazovat na nadřazený kontext, ve kterém se hledají metadata nedefinovaná aktuálním kontextem (zatím to implementujeme kopií nadřazeného kontextu; jestli je to rozumné, teď odkládám). *Také může definovat množinu atributů, které se mají překládat na metadata.* Objekt Group se chová jako lokální výměna kontextu pro všechno, co je ve stromu pod ním. Mimo to generuje (volitelně?) TeXovou skupinu. Když je ve zdrojáku group nebo partial, vznikne objekt Group s novým kontextem. Když je ve zdrojáku div nebo span, podíváme se, jestli má nějaké atributy prohlášené aktuálním kontextem za metadatové. Pokud ano, vložíme nad něj do stromu Group s novým kontextem, ve kterém podle atributů nastavíme příslušná metadata. Při procházení stromu si vždy udržujeme, který kontext je aktuální. Transform to už dělá, generátor ještě ne – tam to asi můžeme udržovat v atributu generátorového objektu. Bylo by hezké, kdyby kontext mohly ovlivňovat i uživatelské pythoní funkce. Minimálně se ptát na metadata a přenastavovat je. Případně vracejí-li podstrom, mohou si v něm samy založit Group s novým kontextem. (Vlastně je to skoro Tvé řešení č. 2, ale příjde mi hezčí oddělit sémantiku přepínání kontextů od Divů a Spanů.)
jan commented 1 year ago
Poster

(zatím to implementujeme kopií nadřazeného kontextu; jestli je to rozumné, teď odkládám).

Aha? To, že se děje? To rozhodně nebyl plán, kouknu na to, měl jsem pocit, že instance tříd se by default předávají přes referenci a ne hodnotu a že naopak předat kopii něčeho tak složitého jako instance třídy je něco, co high-level jazyky neumí vůbec nebo na to mají specifické funkce (obvykle deep_copy, v JavaScriptu JSON.parse(JSON.stringify(abžikt))), každopádně se to obvykle dělá velmi explicitně.

Také může definovat množinu atributů, které se mají překládat na metadata.
...
Když je ve zdrojáku div nebo span, podíváme se, jestli má nějaké atributy prohlášené aktuálním kontextem za metadatové. Pokud ano, vložíme nad něj do stromu Group s novým kontextem, ve kterém podle atributů nastavíme příslušná metadata.

Jo, to zní docela dobře. Mám obavu, že to může být trochu neintuitivní, pokud spany poměrně magicky mohou ale nemusí vytvářet groupy. Navíc zjist, jestli se to stane bude nejspíš vyžadovat netriviální znalost kontextu celého aktuálně zpracovávaného zdrojáku.

Bylo by hezké, kdyby kontext mohly ovlivňovat i uživatelské pythoní funkce. Minimálně se ptát na metadata a přenastavovat je. Případně vracejí-li podstrom, mohou si v něm samy založit Group s novým kontextem.

Tohle umíme. Uživatelské pythoní funkce vždy měly a mají vždy ke kontextu přístup a mohou na něm volat funkce na jeho úpravu. Aktuálně se kontext předává jako jeden z parametrů funkce.

Při procházení stromu si vždy udržujeme, který kontext je aktuální. Transform to už dělá, generátor ještě ne – tam to asi můžeme udržovat v atributu generátorového objektu.

Aktuálně pracuji s myšlenkou, že generátor už ke kontextu vůbec nemá přístup a pokud nějaký element chce něco z kontextu pro svoje generování, musí si o to explicitně říct v transformu. Primárně třeba kvůli tomu, že úpravy kontextu ho nekopírují (nebo alespoň nemají kopírovat 😅), takže v době generování už kontext tak, jak ho znala většina elementů v transformu neexistuje.

(Vlastně je to skoro Tvé řešení č. 2, ale příjde mi hezčí oddělit sémantiku přepínání kontextů od Divů a Spanů.)

To je více méně status quo (až na metadatové atributy), ten původní způsob, jak vytvářet skupiny s odděleným kontextem je:

```md {.group}
Jsem ve skupině
```
> (zatím to implementujeme kopií nadřazeného kontextu; jestli je to rozumné, teď odkládám). Aha? To, že se děje? To rozhodně nebyl plán, kouknu na to, měl jsem pocit, že instance tříd se by default předávají přes referenci a ne hodnotu a že naopak předat kopii něčeho tak složitého jako instance třídy je něco, co high-level jazyky neumí vůbec nebo na to mají specifické funkce (obvykle deep_copy, v JavaScriptu `JSON.parse(JSON.stringify(abžikt))`), každopádně se to obvykle dělá velmi explicitně. > Také může definovat množinu atributů, které se mají překládat na metadata. > ... > Když je ve zdrojáku div nebo span, podíváme se, jestli má nějaké atributy prohlášené aktuálním kontextem za metadatové. Pokud ano, vložíme nad něj do stromu Group s novým kontextem, ve kterém podle atributů nastavíme příslušná metadata. Jo, to zní docela dobře. Mám obavu, že to může být trochu neintuitivní, pokud spany poměrně magicky mohou ale nemusí vytvářet groupy. Navíc zjist, jestli se to stane bude nejspíš vyžadovat netriviální znalost kontextu celého aktuálně zpracovávaného zdrojáku. > Bylo by hezké, kdyby kontext mohly ovlivňovat i uživatelské pythoní funkce. Minimálně se ptát na metadata a přenastavovat je. Případně vracejí-li podstrom, mohou si v něm samy založit Group s novým kontextem. Tohle umíme. Uživatelské pythoní funkce vždy měly a mají vždy ke kontextu přístup a mohou na něm volat funkce na jeho úpravu. Aktuálně se kontext předává jako jeden z parametrů funkce. > Při procházení stromu si vždy udržujeme, který kontext je aktuální. Transform to už dělá, generátor ještě ne – tam to asi můžeme udržovat v atributu generátorového objektu. Aktuálně pracuji s myšlenkou, že generátor už ke kontextu vůbec nemá přístup a pokud nějaký element chce něco z kontextu pro svoje generování, musí si o to explicitně říct v transformu. Primárně třeba kvůli tomu, že úpravy kontextu ho nekopírují (nebo alespoň nemají kopírovat 😅), takže v době generování už kontext tak, jak ho znala většina elementů v transformu neexistuje. > (Vlastně je to skoro Tvé řešení č. 2, ale příjde mi hezčí oddělit sémantiku přepínání kontextů od Divů a Spanů.) To je více méně status quo (až na metadatové atributy), ten původní způsob, jak vytvářet skupiny s odděleným kontextem je: ```` ```md {.group} Jsem ve skupině ``` ````
mj commented 1 year ago
Owner

Aha? To, že se děje?

Pardon, chyba mezi židlí a monitorem. Čtu znovu, neděje. Odkládám :)

Mám obavu, že to může být trochu neintuitivní, pokud spany poměrně magicky mohou ale nemusí vytvářet groupy. Navíc zjist, jestli se to stane bude nejspíš vyžadovat netriviální znalost kontextu celého aktuálně zpracovávaného zdrojáku.

Hmm, to máš pravdu ... tak že by přeci jenom divy a spany vždycky kontext zakládaly?

Aktuálně pracuji s myšlenkou, že generátor už ke kontextu vůbec nemá přístup a pokud nějaký element chce něco z kontextu pro svoje generování, musí si o to explicitně říct v transformu.

Myslíš, že je to rozumné? Mně přijde docela přirozené, aby generátor koukal na metadata. Třeba může chtít uložit název dokumentu do PDFkových metadat, nebo do HTML propagovat změny jazyka. Asi už bych mu kontext zakázal měnit, ale čtení mi zní OK.

[...] takže v době generování už kontext tak, jak ho znala většina elementů v transformu neexistuje.

Co se tam s kontextem děje tak drastického? Jde o to, že transformace do kontextu přidává definice funkcí a spouští funkce, které mohou kontext libovolně měnit? Tím pádem generátor vidí kontext až po provedení všech změn, zatímco transformace je ty změny, které zatím proběhly?

To je více méně status quo (až na metadatové atributy), ten původní způsob, jak vytvářet skupiny s odděleným kontextem je: [...]

Já vím, ale budu radši, když půjde skupiny zakládat, aniž by bylo potřeba na vnitřek skupiny znovu volat parser.

> Aha? To, že se děje? Pardon, chyba mezi židlí a monitorem. Čtu znovu, neděje. Odkládám :) > Mám obavu, že to může být trochu neintuitivní, pokud spany poměrně magicky mohou ale nemusí vytvářet groupy. Navíc zjist, jestli se to stane bude nejspíš vyžadovat netriviální znalost kontextu celého aktuálně zpracovávaného zdrojáku. Hmm, to máš pravdu ... tak že by přeci jenom divy a spany vždycky kontext zakládaly? > Aktuálně pracuji s myšlenkou, že generátor už ke kontextu vůbec nemá přístup a pokud nějaký element chce něco z kontextu pro svoje generování, musí si o to explicitně říct v transformu. Myslíš, že je to rozumné? Mně přijde docela přirozené, aby generátor koukal na metadata. Třeba může chtít uložit název dokumentu do PDFkových metadat, nebo do HTML propagovat změny jazyka. Asi už bych mu kontext zakázal měnit, ale čtení mi zní OK. > [...] takže v době generování už kontext tak, jak ho znala většina elementů v transformu neexistuje. Co se tam s kontextem děje tak drastického? Jde o to, že transformace do kontextu přidává definice funkcí a spouští funkce, které mohou kontext libovolně měnit? Tím pádem generátor vidí kontext až po provedení všech změn, zatímco transformace je ty změny, které zatím proběhly? > To je více méně status quo (až na metadatové atributy), ten původní způsob, jak vytvářet skupiny s odděleným kontextem je: [...] Já vím, ale budu radši, když půjde skupiny zakládat, aniž by bylo potřeba na vnitřek skupiny znovu volat parser.
jan commented 1 year ago
Poster

Já vím, ale budu radši, když půjde skupiny zakládat, aniž by bylo potřeba na vnitřek skupiny znovu volat parser.

Ano, pak je to ta druhá varianta, co jsem navrhoval.

Co se tam s kontextem děje tak drastického? Jde o to, že transformace do kontextu přidává definice funkcí a spouští funkce, které mohou kontext libovolně měnit? Tím pádem generátor vidí kontext až po provedení všech změn, zatímco transformace je ty změny, které zatím proběhly?

Ano, přesně tak.

Myslíš, že je to rozumné? Mně přijde docela přirozené, aby generátor koukal na metadata. Třeba může chtít uložit název dokumentu do PDFkových metadat, nebo do HTML propagovat změny jazyka. Asi už bych mu kontext zakázal měnit, ale čtení mi zní OK.

Aktuálně to dělám tak, že vše, co potřebuju manuálně v transformu přilepím do atributů elementu, pro který je dané metadatum relevantní. Například můžeš název dokumentu pak předat do atributů elementu Doc, který tuto informaci předá dál TeXu. (Mimochodem ten si metadata odnese tak jako tak, protože jsou jeho) Důvod není opinion-based, ale spíš technický (důvod, na který ti přitakávám výše). Aby mohl mít generátor přístup ke kontextu, budeme si asi muset pořídit nějakou speciální datovou strukturu s historií nebo kontexty při změně kopírovat, což je asi hodně suboptimální. Přišlo mi to jako nejlepší řešení.

> Já vím, ale budu radši, když půjde skupiny zakládat, aniž by bylo potřeba na vnitřek skupiny znovu volat parser. Ano, pak je to ta druhá varianta, co jsem navrhoval. > Co se tam s kontextem děje tak drastického? Jde o to, že transformace do kontextu přidává definice funkcí a spouští funkce, které mohou kontext libovolně měnit? Tím pádem generátor vidí kontext až po provedení všech změn, zatímco transformace je ty změny, které zatím proběhly? Ano, přesně tak. > Myslíš, že je to rozumné? Mně přijde docela přirozené, aby generátor koukal na metadata. Třeba může chtít uložit název dokumentu do PDFkových metadat, nebo do HTML propagovat změny jazyka. Asi už bych mu kontext zakázal měnit, ale čtení mi zní OK. Aktuálně to dělám tak, že vše, co potřebuju manuálně v transformu přilepím do atributů elementu, pro který je dané metadatum relevantní. Například můžeš název dokumentu pak předat do atributů elementu `Doc`, který tuto informaci předá dál TeXu. (Mimochodem ten si metadata odnese tak jako tak, protože jsou jeho) Důvod není opinion-based, ale spíš technický (důvod, na který ti přitakávám výše). Aby mohl mít generátor přístup ke kontextu, budeme si asi muset pořídit nějakou speciální datovou strukturu s historií nebo kontexty při změně kopírovat, což je asi hodně suboptimální. Přišlo mi to jako nejlepší řešení.
mj commented 1 year ago
Owner

Ano, pak je to ta druhá varianta, co jsem navrhoval.

Ne úplně – pořád půjde založit Group i vložením pod-dokumentu včetně metadat. Jen to asi nebude typický způsob.

Aktuálně to dělám tak, že vše, co potřebuju manuálně v transformu přilepím do atributů elementu, pro který je dané metadatum relevantní.

Přijde mi, že tím zbytečně prolézají soukromé záležitosti generátoru do zbytku kódu.

Aby mohl mít generátor přístup ke kontextu, budeme si asi muset pořídit nějakou speciální datovou strukturu s historií nebo kontexty při změně kopírovat, což je asi hodně suboptimální.

Šla by navrhnout jednoduchá persistentní struktura. Už mám nějaké nápady, ale než je sepíši, zkusím se zamyslet, zda je to potřeba.

Definice funkcí persistenci nepotřebují, protože na ty se generátor nedívá.

Takže jde jenom o meta-data. Ta se uvnitř skupiny mohou změnit jenom tehdy, když to provede nějaká zavolaná funkce. Chceme to ale někdy dovolit? Neměly by se takové funkce volat vždy jen na začátku skupiny a jakmile se objeví první "obsahový" element, už budou meta-data zmražená? Nemusíme to nutně kontrolovat, zatím stačí dokumentovat, že to nemá definované chování :)

Nebo jsem něco přehlédl?

> Ano, pak je to ta druhá varianta, co jsem navrhoval. Ne úplně – pořád půjde založit Group i vložením pod-dokumentu včetně metadat. Jen to asi nebude typický způsob. > Aktuálně to dělám tak, že vše, co potřebuju manuálně v transformu přilepím do atributů elementu, pro který je dané metadatum relevantní. Přijde mi, že tím zbytečně prolézají soukromé záležitosti generátoru do zbytku kódu. > Aby mohl mít generátor přístup ke kontextu, budeme si asi muset pořídit nějakou speciální datovou strukturu s historií nebo kontexty při změně kopírovat, což je asi hodně suboptimální. Šla by navrhnout jednoduchá persistentní struktura. Už mám nějaké nápady, ale než je sepíši, zkusím se zamyslet, zda je to potřeba. Definice funkcí persistenci nepotřebují, protože na ty se generátor nedívá. Takže jde jenom o meta-data. Ta se uvnitř skupiny mohou změnit jenom tehdy, když to provede nějaká zavolaná funkce. Chceme to ale někdy dovolit? Neměly by se takové funkce volat vždy jen na začátku skupiny a jakmile se objeví první "obsahový" element, už budou meta-data zmražená? Nemusíme to nutně kontrolovat, zatím stačí dokumentovat, že to nemá definované chování :) Nebo jsem něco přehlédl?
jan commented 1 year ago
Poster

Ne úplně – pořád půjde založit Group i vložením pod-dokumentu včetně metadat. Jen to asi nebude typický způsob.

Fair point, ok.

Přijde mi, že tím zbytečně prolézají soukromé záležitosti generátoru do zbytku kódu.

To, co navrhuješ ty mi přijde, že je jedna velká soukromá záležitost generátoru. 😁 Moje původní představa byla, že output generátor už nedělá nic chytrého, jen se má postarat o to, aby se z AST stal nějaký kýžený výstup. Co se s dokumentem dělo předtím, už by ho nemělo mět zajímat. Tuhle představu bych demonstroval tím, že třeba FQuoted během transformu dostane podle metadat o jazyce informaci o tom, jaké má vysázet uvozovky. OG už neví, v jakém jazyce text byl, jen jaké dostal uvozovky.

Myslím, že to, co se ty aktuálně snažíš vymyslet je způsob, jak dát větší rozhodovací práva OG, protože je uživatelsky rozšiřitelný, na úkor transformu, který není. A v takovém případě se ptám, jestli by nebylo na místě, učinit podobný refaktor celého transformu jako dostal OutputGenerator, místo něčeho, co mi přijde, že je, minimálně z hlediska původní architektury programu docela "vohekule"*. Mohla by existovat jedna třída, ze které by dědil i OG, i TransformProcessor, s jediným rozdílem, že TP by jen modifikoval AST a OG by ho vypisoval do nějakého souboru. Jinak by to bylo postavené na podobné logice nahraditelných jednotlivých metod na velké třídě (které by navíc u transformu byly z většiny jenom přímý return vstupu, protože většinu elementů neteransformujeme). Ve finálním formátítku, které už by si každý uživatel poskládal podle sebe, by pak mohlo být klidně i víc různých dědiců TP, kteří by se mohli různě větvit, atd. (Lehce OT: V takovém případě by také nemuselo být od věci přesunout třeba image processing do TP a OG by si jen vyžádaly konkrétní už vygenerované formáty, ale vzhledem k tomu, že o to už se stejně celé stará úplně separátní ImageProcessor, tak na to asi není nutné sahat...)

Ano, uvědomuji si, že se tu chystám řešit jeden kapající kohoutek tím, že přestavím půlku budovy, ale když už mě to napadlo, zkouším to rozvést, protože by to vůbec nemuselo být od věci a dlouhodobě užitečnější, protože bude pak formátítko víc customizable než průměrná LEGO sada.

*Jinak vyrobit "vokehukli", kterou navrhuješ ty, je samozřejmě také možnost, rozhodně to není myšleno nijak negativně (pardon nenašel jsem lepší slovo), spíš bych tím chtěl vyjádřit, že se tím krokem za mě odkloníme od jedné z původních idejí programu a chceme si takový krok explicitně acknout.

> Ne úplně – pořád půjde založit Group i vložením pod-dokumentu včetně metadat. Jen to asi nebude typický způsob. Fair point, ok. > Přijde mi, že tím zbytečně prolézají soukromé záležitosti generátoru do zbytku kódu. To, co navrhuješ ty mi přijde, že je jedna velká soukromá záležitost generátoru. 😁 Moje původní představa byla, že output generátor už nedělá nic chytrého, jen se má postarat o to, aby se z AST stal nějaký kýžený výstup. Co se s dokumentem dělo předtím, už by ho nemělo mět zajímat. Tuhle představu bych demonstroval tím, že třeba FQuoted během transformu dostane podle metadat o jazyce informaci o tom, jaké má vysázet uvozovky. OG už neví, v jakém jazyce text byl, jen jaké dostal uvozovky. Myslím, že to, co se ty aktuálně snažíš vymyslet je způsob, jak dát větší rozhodovací práva OG, protože je uživatelsky rozšiřitelný, na úkor transformu, který není. A v takovém případě se ptám, jestli by nebylo na místě, učinit podobný refaktor celého transformu jako dostal OutputGenerator, místo něčeho, co mi přijde, že je, minimálně z hlediska původní architektury programu docela "vohekule"\*. Mohla by existovat jedna třída, ze které by dědil i OG, i TransformProcessor, s jediným rozdílem, že TP by jen modifikoval AST a OG by ho vypisoval do nějakého souboru. Jinak by to bylo postavené na podobné logice nahraditelných jednotlivých metod na velké třídě (které by navíc u transformu byly z většiny jenom přímý return vstupu, protože většinu elementů neteransformujeme). Ve finálním formátítku, které už by si každý uživatel poskládal podle sebe, by pak mohlo být klidně i víc různých dědiců TP, kteří by se mohli různě větvit, atd. (Lehce OT: *V takovém případě by také nemuselo být od věci přesunout třeba image processing do TP a OG by si jen vyžádaly konkrétní už vygenerované formáty, ale vzhledem k tomu, že o to už se stejně celé stará úplně separátní ImageProcessor, tak na to asi není nutné sahat...*) Ano, uvědomuji si, že se tu chystám řešit jeden kapající kohoutek tím, že přestavím půlku budovy, ale když už mě to napadlo, zkouším to rozvést, protože by to vůbec nemuselo být od věci a dlouhodobě užitečnější, protože bude pak formátítko víc customizable než průměrná LEGO sada. \*Jinak vyrobit "vokehukli", kterou navrhuješ ty, je samozřejmě také možnost, rozhodně to není myšleno nijak negativně (pardon nenašel jsem lepší slovo), spíš bych tím chtěl vyjádřit, že se tím krokem za mě odkloníme od jedné z původních idejí programu a chceme si takový krok explicitně acknout.
mj commented 1 year ago
Owner

Já si také představuji, že generátoru je jedno, co se s dokumentem dělo předtím. Takže ho zajímá jaká metadata v daném místě dokumentu existují, nikoliv odkud se tam vzala :)

FQuoted mi dává lepší smysl ve společném transformátoru, protože je to transformace nezávislá na výstupním formátu. Naopak třeba propagování změn jazyka do HTML nebo generování PDFkových metadat nemá s obecnými transformacemi nic společného, týká se to jednoho konkrétního generátoru.

Založit transformaci a generování na nějaké společné abstraktní knihovně by mohlo být zajímavé, ale přijde mi, že je to zcela nezávislé na tom, co řešíme zde.

Zatím mi každopádně přijde nejpřímočařejší, aby metadata byla dostupná v každém okamžiku zpracovávání.

Já si také představuji, že generátoru je jedno, co se s dokumentem dělo předtím. Takže ho zajímá *jaká* metadata v daném místě dokumentu existují, nikoliv *odkud* se tam vzala :) FQuoted mi dává lepší smysl ve společném transformátoru, protože je to transformace nezávislá na výstupním formátu. Naopak třeba propagování změn jazyka do HTML nebo generování PDFkových metadat nemá s obecnými transformacemi nic společného, týká se to jednoho konkrétního generátoru. Založit transformaci a generování na nějaké společné abstraktní knihovně by mohlo být zajímavé, ale přijde mi, že je to zcela nezávislé na tom, co řešíme zde. Zatím mi každopádně přijde nejpřímočařejší, aby metadata byla dostupná v každém okamžiku zpracovávání.
jan commented 1 year ago
Poster

Naopak třeba propagování změn jazyka do HTML nebo generování PDFkových metadat nemá s obecnými transformacemi nic společného, týká se to jednoho konkrétního generátoru.

To mi nepřijde pravda, minimálně ne u těchto dvou příkladů, které zmiňuješ. Propagování změn jazyka na výstup rozhodně nezajímá jen HTML, ale je to hodně věc, která si zaslouží výjimku a aby se o ní dozvěděly všechny výstupnítka (což se aktuálně děje). Metadata, která chceš propagovat do PDF také můžou být obecně zajímavá ostatním formátům a mám pocit, že jsou extrémně lokální, při outputu budou zajímavá max pro Doc, který se tam vyskytne právě jednou a pro nic jiného, není tedy důvod tahle metadata natvrdo předávat všem Elementům.

Druhý problém je spíše technický a to, že tak, jak je aktuálně AST, který držíme v paměti, postavený, není možné na libovolný element navázat libovolný kousek dat. attributes má ve skutečnosti jen omezená podmnožina Elementů, konkrétně Doc (ten nemá attributes, ale metadata), Code, CodeBlock, Div, Span, Figure, Header, Image, Link a Table{,Body,Cell,Foot,Head,Row}. U ostatních, pokud to nechceme držet úplně externě, stejně data do OG nedostaneme.

> Naopak třeba propagování změn jazyka do HTML nebo generování PDFkových metadat nemá s obecnými transformacemi nic společného, týká se to jednoho konkrétního generátoru. To mi nepřijde pravda, minimálně ne u těchto dvou příkladů, které zmiňuješ. Propagování změn jazyka na výstup rozhodně nezajímá jen HTML, ale je to hodně věc, která si zaslouží výjimku a aby se o ní dozvěděly všechny výstupnítka (což se aktuálně děje). Metadata, která chceš propagovat do PDF také můžou být obecně zajímavá ostatním formátům a mám pocit, že jsou extrémně lokální, při outputu budou zajímavá max pro Doc, který se tam vyskytne právě jednou a pro nic jiného, není tedy důvod tahle metadata natvrdo předávat všem Elementům. Druhý problém je spíše technický a to, že tak, jak je aktuálně AST, který držíme v paměti, postavený, není možné na libovolný element navázat libovolný kousek dat. `attributes` má ve skutečnosti jen omezená podmnožina Elementů, konkrétně Doc (ten nemá attributes, ale metadata), Code, CodeBlock, Div, Span, Figure, Header, Image, Link a Table{,Body,Cell,Foot,Head,Row}. U ostatních, pokud to nechceme držet úplně externě, stejně data do OG nedostaneme.
mj commented 1 year ago
Owner

Mně právě přijde, že ten technický problém má jednoduché řešení, aspoň pokud se shodneme, že volání externích funkcí měnících stav kontextu má definováné chování jen před všemi obsahovými elementy.

Stačí, aby transformace nechávala ve stromu elementy Group a procházení stromu v generátoru udržovalo uvnitř objektu generátoru odkaz na aktuální kontext.

Mně právě přijde, že ten technický problém má jednoduché řešení, aspoň pokud se shodneme, že volání externích funkcí měnících stav kontextu má definováné chování jen před všemi obsahovými elementy. Stačí, aby transformace nechávala ve stromu elementy Group a procházení stromu v generátoru udržovalo uvnitř objektu generátoru odkaz na aktuální kontext.
jan commented 1 year ago
Poster

Naimplementoval jsem více méně všechy nápady, které tu padly.

Pro předávání metadat přes atributy jsem se nakonec rozhodl pro upravenou variantu 3.3, tedy všechny Divy se třídou .group se promění v Groups a všechny jejich atributy se stanou metadaty. Atributy mohou obsahovat tečky, ty se pak zpropagují do struktury metadat. Zatím mi to přijde, že to může fungovat docela použitelně. Pro Spany to bude vyžadovat trochu složitější úpravy, neboť si potřebujeme založit InlineGroup a BlockGroup podobně, jako je to u Commandů, aby se daly Groups umísťovat i dovnitř Inline prvků.

Taky jsem zkusil naimplementovat ten TransformProcessor, který jsem si tu vybásnil a nepřijde mi to úplně špatné, ta overridovatelnost může být dost fajn, nehledě na nezávislost na panflutím walku a nějakém minimálním zrychlení, protože je tam míň ifů a víc se spoléhá na třídy, ale kód je téměř přesně na 3x tolik řádcích a asi to není tak přehledné. Upřímně zatím nemám preferenci ani na jednu stranu a rád uslyším nějaké další argumenty pro obě varianty.

Kontext jsem také přivázal ke Groupám a naučil OG, aby si v self.context udržoval ten aktuální. Nový TP si ho udržuje stejným způsobem, místo toho, aby se podával jako argument. Tohle teoreticky může být náchylnější k chybám, ale tak jak to je by to snad mělo fungovat.

Naimplementoval jsem více méně všechy nápady, které tu padly. Pro předávání metadat přes atributy jsem se nakonec rozhodl pro upravenou variantu 3.3, tedy všechny Divy se třídou `.group` se promění v Groups a všechny jejich atributy se stanou metadaty. Atributy mohou obsahovat tečky, ty se pak zpropagují do struktury metadat. Zatím mi to přijde, že to může fungovat docela použitelně. Pro Spany to bude vyžadovat trochu složitější úpravy, neboť si potřebujeme založit InlineGroup a BlockGroup podobně, jako je to u Commandů, aby se daly Groups umísťovat i dovnitř Inline prvků. Taky jsem zkusil naimplementovat ten TransformProcessor, který jsem si tu vybásnil a nepřijde mi to úplně špatné, ta overridovatelnost může být dost fajn, nehledě na nezávislost na panflutím `walk`u a nějakém minimálním zrychlení, protože je tam míň ifů a víc se spoléhá na třídy, ale kód je téměř přesně na 3x tolik řádcích a asi to není tak přehledné. Upřímně zatím nemám preferenci ani na jednu stranu a rád uslyším nějaké další argumenty pro obě varianty. Kontext jsem také přivázal ke Groupám a naučil OG, aby si v self.context udržoval ten aktuální. Nový TP si ho udržuje stejným způsobem, místo toho, aby se podával jako argument. Tohle teoreticky může být náchylnější k chybám, ale tak jak to je by to snad mělo fungovat.
jan commented 1 year ago
Poster

Vzhledem k 0c2ce7d56c mi tohle přijde hotové, v případě jakékoliv nesrovnalosti znovu otevřete.

Vzhledem k 0c2ce7d56c8936c9eb933f256e27befcda2de167 mi tohle přijde hotové, v případě jakékoliv nesrovnalosti znovu otevřete.
jan closed this issue 1 year ago
Sign in to join this conversation.
No Milestone
No project
No Assignees
2 Participants
Notifications
Due Date

No due date set.

Dependencies

This issue currently doesn't have any dependencies.

Loading…
There is no content yet.