Journal classeur, un script python quick&dirty pour avoir tout son texte dans un seul fichier

Posté par  (site web personnel, Mastodon) . Licence CC By‑SA.
Étiquettes :
23
11
jan.
2024

Cher journal,

Il y a quelques semaines je demandais sur le forum linuxfr comment utiliser vim pour avoir tous les fichiers textes d'un document dans un même buffer.

S'en est suivi une réponse fleuve de Gil Cot transformée elle même en journal.

Pour résumer, mon problème était le suivant : J'aime bien rédiger ma documentation en markdown: ça fait de beaux diff, c'est lisible en texte brut et c'est convertible en tout un tas de format avec pandoc (à condition de passer un peu de temps à tout configurer quand même).

Mais pour la doc de projet informatique, j’essaie de mettre les fichiers au plus près du code, avec des fichier de documentation dans chaque répertoire. Comme pour le projet fpgamacro qui a un README.md par module. Textes que je rassemble ensuite pour créer un seul document grâce à de la cuisine Makefile/Pandoc.

Sauf que quand on multiplie les petits fichiers ça devient compliqué de switcher avec vim (mais c'est le même problème avec tous les éditeurs en fait) et j'aimerais bien les rassembler dans un même «buffer» pour avoir une vue sur tout le texte.

Un ami m'a ensuite fait remarquer que mon problème ne se cantonne pas à vim, quelques soit l'éditeur, il est pénible d'avoir à switcher entre des onglets ou autres fenêtres. Donc autant faire un petit script qui colle (merge) tous ces fichiers dans un seul pour l'éditer. Et avoir un deuxième script (ou une option) pour les redécouper et mettre à jour les fichiers texte à leurs place.

C'est donc l'objet de Classeur. Un logiciel écrit en python qui permet de «coller» tous les fichiers textes donnés en argument avec des séparateurs donnant le chemin du fichier collé :

$ classeur -m intro.md chapitre1.md pouet.md annexes.md -o my_merged_doc.md
Merging intro.md
Merging chapitre1.md
Merging pouet.md
Merging annexes.md
Merged 4 files in my_merged_doc.md

On peut éditer le fichier my_merged_doc.md pour écrire sa doc. Chaque fichier est chapeauté du chemin/nom du fichier édité entouré de caractères ciseaux «✂✂✂»:

$ cat my_merged_doc.md 
✂✂✂ intro.md ✂✂✂
= Introduction =

J'adore LinuxFR, c'est un super rocher.
✂✂✂ chapitre1.md ✂✂✂
= Comment s'accrocher à un rocher =

Dans ce chapitre nous parlerons de l'art de s'accrocher aux rocher malgré les
marées.
✂✂✂ pouet.md ✂✂✂
prout
✂✂✂ annexes.md ✂✂✂
= Annexes =

Toutes les références marine.

Une fois que l'on est content de son texte et que l'on souhaite mettre à jours les fichiers correspondants on utilise la commande «split» pour redécouper en suivant bien les ciseaux et remettre les textes dans leurs fichiers respectifs.

$ classeur -s my_merged_doc.md 
Splitting my_merged_doc.md with scissors «✂✂✂»
Found file intro.md
Found file chapitre1.md
Found file pouet.md
Found file annexes.md

Il ne reste plus qu'à faire un diff avec git et/ou commiter pour avoir sa doc à jour.

Bien placé dans son Makefile, classeur simplifie la vie de celles et ceux qui écrivent de la doc et qui doivent jongler avec tous ces feuillets qui traînent à droite et à gauche.

J'ai même fait un petit dessin/logo parce que j'avais envie de jouer avec ma tablette :

Logo de classeur, dessiné à la main avec une tablette numérique

Voila, c'est tout. Je ne suis pas sûr que ça méritait une dépêche à la vue de la quantité de code pondu. Et je suis sûr qu'on peut faire ça avec les commandes Shell/Bash classiques, mais j'avais pas envie de me souvenir des commandes à chaque fois.

Je rêve de pouvoir ajouter une option permettant de mettre les pages du pdf généré dans le texte à l'image des bandeaux de découpe des fichiers (✂✂✂), mais c'est une autre histoire.

  • # Remerciements et suggestion

    Posté par  . Évalué à 4.

    Bonjour et merci pour cette appli. J'aime beaucoup pandoc moi aussi (qui m'a souvent sauvé la vie) et je pensais justement faire un script shell pour un usage similaire, mais j'ai chopé une forme grave de flemmite dans l'enfance et je ne me suis jamais remis.

    Bref, j'aurais une toute petite suggestion : quand on veut fusionner les .md et ensuite les exporter en odt, on va retrouver les petits ciseaux dans le fichier markdown global. On pourra bien-sûr les enlever très rapidement à l'aide d'une expression régulière dans un éditeur de texte (où même modifier soi-même le code source d'à peine 73 lignes en Python que l'auteur a aimablement mis à disposition, au lieu de lui casser les pieds !) mais c'est une action supplémentaire, action qui va vite se transformer pour les procrastinateurs en remontée de l'Everest.

    Est-ce qu'il ne serait pas plus judicieux de mettre les ciseaux en commentaire ? Comme ça si on veut générer le document au complet à l'aide de Pandoc à partir du markdown global, on n'aura pas le ✂✂✂ dans l'export final.

    Nec spe, nec metu

    • [^] # Re: Remerciements et suggestion

      Posté par  (site web personnel, Mastodon) . Évalué à 6.

      Bref, j'aurais une toute petite suggestion : quand on veut fusionner les .md et ensuite les exporter en odt, on va retrouver les petits ciseaux dans le fichier markdown global. On pourra bien-sûr les enlever très rapidement à l'aide d'une expression régulière dans un éditeur de texte (où même modifier soi-même le code source d'à peine 73 lignes en Python que l'auteur a aimablement mis à disposition, au lieu de lui casser les pieds !) mais c'est une action supplémentaire, action qui va vite se transformer pour les procrastinateurs en remontée de l'Everest.

      Demandez, c'est codé !

      J'ai plus qu'une balle

  • # Shell/Bash

    Posté par  (site web personnel, Mastodon) . Évalué à 8. Dernière modification le 13 janvier 2024 à 17:24.

    On parle de moi ? Me voici…1 :D

    S'en est suivi une réponse fleuve de Gil Cot transformée elle même en journal.

    En journaux en fait, mais seul le premier a été accouché ; la suite est restée en gestation (j’étais en recherche de réponses par rapport aux markdown de malheur…)

    Bon, revenons au classeur ;) Comme le shell est mon dada, je vais fournir les équivalences (ce qui ne remet pas en cause le travail.)2

    Et je suis sûr qu'on peut faire ça avec les commandes Shell/Bash classiques,

    Habituellement, le merge est le travail de cat

    $ # classeur -m intro.md chapitre1.md pouet.md annexes.md -o my_merged_doc.md
    $ cat intro.md chapitre1.md pouet.md annexes.md > my_merged_doc.md

    Mais ici il y a l’ajout des chapeaux… que je traduirai par quelque chose comme :

    >"$outputfilename"
    for filename in "${markdownfiles[@]}"; do
        echo "$scissors $filename $scissors" >>"$outputfilename"
        cat $filename >>"$outputfilename"
    done
    echo "Merged ${#markdownfiles[@]} in ${outputfilename}

    Habituellement, le split est le boulot de split tout simplement.

    $ # classeur -s my_merged_doc.md
    $ split -p '^✂✂✂ [[:alnum:]]+\.md ✂✂✂$' my_merged_doc.md temporaire-

    On peut utiliser sed ou awk ou un oneliner d’un autre langage, mais split, qui est dédié à cette tâche, est plus performant.
    Quelque soit l’outil, il y a un « mais » ici aussi : cette commande va créer une série de fichiers dont la base est dans mon exemple temporaire-

    $ ls temporaire-*
    temporaire-aa
    temporaire-ab
    temporaire-ac
    temporaire-ad

    Noter que split seul est bien comme miroir de cat ici…

    $ # classeur -s my_merged_doc.md
    $ split -p '^= .* =$' my_merged_doc.md classeur-

    On a la première ligne qui contient le motif, donc le chapeau… On peut rajouter une commande pour faire fi de cette ligne dans le cas présent, mais je ne sais pas si c’est le comportement de Classeur.
    De plus, si je comprends bien, il faut remettre dans les chemins indiqués. Du coup, je traduirai par quelque chose comme

    tmp=$(mktemp -t $(basename $0))-
    echo "Splitting ${markdownfile} with scissors «${scissors}»"
    split -p "^$scissors [[:alnum:]]+\.md $scissors$' "$markdownfile" $tmp
    for openfile in $(ls $tmp??); do
        filename=$(expr "$(head -n 1 "$openfile")" : "$scissors (.*) $scissors")
        if [ -e "$filename" ]; then
            echo "Found file $filename"
        else
            echo "Add file $filename"
        fi
        mv "$openfile" "$filename" && rm "$openfile"
    done

    Ça commence à devenir sioux et je ressors un vieil ami souvent oublié : expr au lieu de juste quelque chose comme filename=$(head -n 1 "$openfile" | sed "s/$scissors//g") car je ne sais pas aprioris le délimiteur qui sera disponible… Il est aussi possible d’utiliser grep -Po au lieu de sed mais ce n’est pas portable…

    Anyway, la bonne approche est bien d’écrire un script (que tu maîtrises et peux maintenir) …pour la bonne raison que ce n’est pas de l’utilisation directe des commandes et que ces opérations ne sont pas ponctuelles.

    j'avais pas envie de me souvenir des commandes à chaque fois.

    Sur ce, bonne fin de semaine à tout le monde.


    1. Tiens, s’il y en a qui ont l’idée de comment réaliser l’équivalent des capteurs d’attention comme sur IRC ça m’intéresse : en gros, que les journaux et commentaires me mentionnant m’interpellent. 

    2. Autant il est facile de faire un prototype ou de résoudre un problème interactivement en shell, écrire un script solide n’est pas forcément trivial et peu connaissent bien le shell en tant que langage de programmation (il y a pas mal de subtilités qui prennent du temps à être maitrisé.) Dans tous les cas prenez un langage dans lequel vous ferez quelque chose de robuste et performant dans un temps raisonnable : le commentaire présent est plus pour faire découvrir/rappeler des commandes qui pourront être utiles à d’autres occasions. 

    “It is seldom that liberty of any kind is lost all at once.” ― David Hume

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.