Accueil > Informatique > Emacs > org-protocol : partie 1

org-protocol : partie 1

dimanche 7 février 2021, par Vincent

Cet article est le premier d’une série de trois autour d’org-protocol et org-roam

 partie 1 : marque-page et capture
 partie 2 : marque-page et notes roam
 partie 3 : gestion de documents pdf avec org-roam

Pré-requis et contexte

- Debian buster sid
- emacs 26+ (testé avec emacs 27 et emacs 28) en mode client/server
- straight pour la gestion de paquets d’emacs
- un bureau compatible avec freedesktop (gnome/xfce/ etc.)
- firefox (ou chromium avec quelques adaptations)
- pandoc pour la conversion html—>org-mode
- wget pour capturer les pages

Présentation

org-mode
org-mode est un mode majeur pour emacs. C’est au départ un langage de balisage comme markdown mais c’est également un outil pour prendre des notes, gérer ses agendas, faire de la programmation lettrée un peu comme les notebook (IPython, Jupyter, etc.) ou gérer un blog.

Les fichiers org ont une syntaxe simple et peuvent-être vus comme des notes (post-it) structurées et augmentées.

L’écosystème autour d’org-mode et la communauté afférente est très dynamique ; dans cet article je présente la mise en œuvre de deux extensions org-protocol-capture-html et org-web-tools du même auteur, merci à lui pour ces deux très bonnes extensions !

org-capture

Org-mode permet de « capturer » rapidement une idée ou une nouvelle tâche. Il s’agit de notes pré-remplies à l’aide de modèles que l’on peut saisir rapidement en utilisant une liste de choix. Ce système de capture est décrit ici par exemple ou dans le manuel d’org-mode.

org-protocol

Org-protocol est un outil qui permet de déclencher des actions dans emacs à partir d’autres applications. Il existe des « protocols » prédéfinis, org-protocol-capture-html et un « protocol » supplémentaire qui permet de gérer la conversion d’une page web en note org à l’aide de pandoc.

objectif de ce tutoriel

Il s’agit de gérer ses signets dans un document org. Ainsi les signets ne dépendent plus d’un navigateur particulier, ni d’un système d’exploitation particulier en mettant en place une synchronisation de fichiers avec syncthing par exemple. De plus chaque signet peut être accompagné de commentaires, de liens etc.

Avantages :
 indépendance du navigateur
 utilisable sur plusieurs postes (ordinateurs, téléphones, etc.)
 ne nécessite pas de recourir à un tiers de confiance pour la synchronisation (les signets restent privés)
 très bonne intégration à l’eco-système emacs/org-mode (tableau/latex/etc.)
 possibilité de capturer les pages pour une lecture hors connexion avec org-web-tools
 le stockage et la sauvegarde sont facilités : tout est dans un fichier texte.

Inconvénient :
 Long à mettre en œuvre, nécessite une bonne connaissance d’emacs et d’org-mode d’où ce tutoriel ;-)

Mise en œuvre

Les signets seront stockés dans le fichier ~/Documents/Memo/note.org qui contient une ligne

* Marque-pages

L’astérisque est importante car elle marque le début d’un titre (headline)

Configuration d’emacs

Voici un exemple de configuration qui utilise le gestionnaire de paquetage straight.

Commençons par charger org-protocol et créer deux modèles de capture.

Un premier repéré par la lettre b pour un signet simple. Le curseur sera placé entre l’entête et la citation issue du site web ; et un second repéré par la lettre c qui ajoute au premier la capture de la page pour une lecture hors-ligne. Au passage l’url est placée dans le tampon circulaire (kill-ring).

Pour adapter les modèles à vos beoins, rendez-vous sur la page du manuel d’org-mode : template-expansion.

(use-package org
      :hook
((org-mode  . auto-fill-mode))
     :init

     (require 'org-protocol)
	     :custom
	     (org-directory "~/Documents/Memo")
	     (org-capture-templates
	      '(
		("b" "Signet" entry
		 (file+headline "~/Documents/Memo/note.org" "Marque-pages")
		 "** %c :website:
:PROPERTIES:
:URL: %(kill-new \"%:link\")
:TIMESTAMP: %t
:CAPTURE: 0
:CUSTOM_ID: signet:%(org-id-new)
:END:
%?
%:initial
" :empty-lines 1 :prepend t)
		("c" "Signet et archive" entry
		 (file+headline "~/Documents/Memo/note.org" "Marque-pages")
		 "** %c :website:
:PROPERTIES:
:URL: %(kill-new \"%:link\")
:TIMESTAMP: %t
:CAPTURE: 1
:CUSTOM_ID: signet:%(org-id-new)
:END:
%?
%:initial
" :empty-lines 1 :prepend t)))
	     
	     )

Ensuite, on charge l’extension d’org-protocol qui gérera les pages web.

	     

(use-package  org-protocol-capture-html
 :straight  (org-protocol-capture-html :type git :host github :repo "alphapapa/org-protocol-capture-html")
 :after (org)
 :init
 (require 'org-protocol-capture-html)
 )

Enfin, on charge une extension qui permet la capture de la page web. On remarquera
le crochet (add-hook 'org-capture-prepare-finalize-hook  'webarchivecustom)

qui déclenche (ou pas) l’archivage de la page grâce au mécanisme d’attachement d’org-mode.

(use-package org-web-tools
  :straight t
  :after (org)
  :custom
  (org-web-tools-archive-fn 'org-web-tools-archive--wget-tar)
  (org-web-tools-archive-wget-html-only-options
   '("-e robots=off" "--adjust-extension" "--timestamping" "--no-directories"))
  (org-web-tools-archive-wget-options
   '("--ignore-tags=script,iframe" "--reject=eot,ttf,svg,otf,*.woff*" "-e robots=off" "--adjust-extension" "--span-hosts" "--convert-links" "--page-requisites" "--timestamping" "--no-directories"))
  (org-web-tools-attach-archive-max-attempts 3)
  
  :config
 (defun webarchivecustom ()
    "Utilisation de org-web-tools pour sauvegarder la page dans une archive"
    (if  (cdr (assoc "CAPTURE" (org-entry-properties nil "CAPTURE")))
        (let (
              (mycap (cdr (assoc "CAPTURE" (org-entry-properties nil "CAPTURE"))))
              (myurl (car (last (org-property-values "URL"))))
              )

          (if (equal mycap "1")
	      (progn
                (org-web-tools-archive-attach myurl)
	        (message (concat "Création de l'archive de la page: " myurl))
	        )
            (progn
              (message (concat "Création du signet de la page: " myurl)))
            )
          )
      )

    )
  :init
   (add-hook 'org-capture-prepare-finalize-hook  'webarchivecustom)
   (bind-key "C-c r a"  'org-web-tools-archive-attach)
   (bind-key "C-c r v"  'org-web-tools-archive-view)
   (bind-key "C-c r o"  'org-attach-open-in-emacs)
   
   )

Enregistrement d’org-protocol dans le bureau

Commençons par créer un fichier .desktop dans le répertoire  /.local/share/applications/ qui utilisera emacsclient pour le type mime x-scheme-handler/org-protocol. Pour utiliser emacs en mode client/server voir par exemple cet article

mkdir -p ~/.local/share/applications/
<< FDF > ~/.local/share/applications/org-protocol.desktop
[Desktop Entry]
Name=org-protocol
Exec=emacsclient %u
Type=Application
Terminal=false
Categories=System;
MimeType=x-scheme-handler/org-protocol;
FDF
update-desktop-database ~/.local/share/applications/

Enregistrement d’org-protocol dans le firefox

Il est possible de réaliser cette étape à l’aide d’extensions. Par exemple Org-capture. Détaillons ici la procédure.

Commençons par enregistrer la prise en charge de org-protocol

Saisir about:config dans la barre d’adresse et accepter de faire attention.

About:config

Puis créer une nouvelle clef network.protocol-handler.expose.org-protocol de type boolean et assigner lui la valeur True.

org-protocol 1
org-protocol 2

créons des bookmarklets pour activer les captures
Si la barre personnelle n’est pas apparente, l’afficher par un clic droit à côté de la barre de recherche.

Barre de recherche

Puis créer un bookmarklets en suivant la documentation de org-protocol-capture-html.

Créer un bookmarklet

Dans le champ Adresse il suffit de saisir :

javascript:location.href = 'org-protocol://capture-html?template=b&url=' + encodeURIComponent(location.href) + '&title=' + encodeURIComponent(document.title || "[untitled page]") + '&body=' + encodeURIComponent(function () {var html = ""; if (typeof document.getSelection != "undefined") {var sel = document.getSelection(); if (sel.rangeCount) {var container = document.createElement("div"); for (var i = 0, len = sel.rangeCount; i < len; ++i) {container.appendChild(sel.getRangeAt(i).cloneContents());} html = container.innerHTML;}} else if (typeof document.selection != "undefined") {if (document.selection.type == "Text") {html = document.selection.createRange().htmlText;}} var relToAbs = function (href) {var a = document.createElement("a"); a.href = href; var abs = a.protocol + "//" + a.host + a.pathname + a.search + a.hash; a.remove(); return abs;}; var elementTypes = [['a', 'href'], ['img', 'src']]; var div = document.createElement('div'); div.innerHTML = html; elementTypes.map(function(elementType) {var elements = div.getElementsByTagName(elementType[0]); for (var i = 0; i < elements.length; i++) {elements[i].setAttribute(elementType[1], relToAbs(elements[i].getAttribute(elementType[1])));}}); return div.innerHTML;}());

Lors de la première capture, il faut lier les deux : les liens org-protocol sont à ouvrir avec org-protocol.desktop.

Premier lancement

Utilisation

Lorsqu’une page est digne d’intérêt, il suffit de sélectionner un morceau de texte et de cliquer sur Signet dans la barre personnelle ; pour qu’un tampon s’ouvre dans une fenêtre emacsclient préalablement ouverte.
Dans ce tampon, apparaît le titre de la page, un lien vers cette page ainsi que la sélection formatée en org-mode. Ce tampon est modifiable, en utilisant uniquement des titres de niveau 3 (*** sous - titre) pour être cohérent avec la structure du fichier note.org. Une fois l’édition terminée, il suffit de saisir C-c C-c et le contenu tampon est ajouté au début du fichier note.org (prepend : 1)

Création d’un signet sous forme de note org

Le principe est le même lors d’un clic sur Capture, à la différence qu’à l’enregistrement de la note une capture de la page est réalisée sous la forme d’une archive tar.gz et attachée à la note. Lorsque l’on visite le fichier note.org, les titres où apparaissent le mot clef ATTACH sont des sites où une capture est disponible. Pour voir le site hors-ligne il suffit de saisir C-c r v

Capture d’une page et création d’un signet.

Conclusion

De nombreuses améliorations sont possibles, (les paquetages org-protocol-capture-html et org-web-tools possèdent une multitude d’options et de fonctionnalités). Par exemple :
 améliorer la capture car wget ne donne pas toujours le résultat escompté...
 permettre la capture de pages, nécessitant des identifiants ;
 interagir avec l’extension de firefox tabfs
 assigner des raccourcis aux captures
 

Bonus

Un fichier note.org avec de nombreux liens sur le thème “org-capture”

note.org

le fichier init.el qui a servi à réaliser ce tutoriel.

La config d’emacs