random_done e Obsidian: o come crearsi uno script in Python da eseguire da riga di comando e aggiungerlo al proprio sistema operativo.

Obisidan è bello, ma vuoi mettere prendere e usarlo anche come modo per tracciare cosa fare? Ultimamente sto usando il terminale e ci è voluto poco a pensare:

Mi risolvo un problema da terminale

Aprire un terminale su Mac è abbastanza comodo. Uno si cerca Terminale dalle applicazioni o magari ha una scorciatoia dedicata. (Sì, lo so, vorrei vedere che ha fatto Wes con Ghosthub , non tanto per gli agenti quanto per le sessioni ssh. Ho aggiunto un task con l'applicazione che andremo a sviluppare per venirne a capo: rdone --add "test_ghosthub_and_post".)

Lavorando, facendo cose, etc capita di aver voglia di segnarsi qualcosa da fare. Magari anche piccola. Cerca questo libro, prova a fare questo, vedi com'è questo servizio. Cose che magari si fanno in un quarto d'ora, però poi spesso uno le perde per strada.

Fare un tool da riga di comando in Python è abbastanza semplice, anche se non l'ho mai fatto sul serio.

Quindi, a parte trovare qualcosa che ci fa interagire con il nostro programma usando la tastiera o il terminale, il resto del codice è abbastanza semplice. Abbiamo dei task con un titolo e quando vengono completate. E sappiamo che dobbiamo pescare dei task a caso e proporli all'utente. Sta a noi poi accettarli, rifiutarli o completarli.

Ecco randomdone o, per gli amici, rdone. Perché, ecco, da un lato ci risparmiamo di qualche carattere per invocarlo e, dall'altro, qualcosa che ti spara addosso task a caso è un po' un (me)rdone.

Cosa si impara

Visto che è un post un po' tecnico, vediamo che cosa bolle in pentola per noi. L'idea è di vedere come:

Python e riga di comando

Ci sono sostanzialmente due modi per scrivere cose in Python da usare da terminale: – usi argparse per definire i comandi che vuoi mandare e gli dici cosa fare. A me serve aggiungere task (--add) e poi completarle (--done). E poi mi serve gestire l'elenco delle task quando sono dentro il programma: accettare un task, skipparlo, completarlo e chiudere il programma. – in alternativa si può usare qualcosa di più moderno tipo typer, dal creatore di FastAPI. Sostanzialmente facciamo le stesse codice, però usando meno codice.

Visto che vogliamo usare la cosa da terminale senza troppe seccature, andiamo sul semplice. Per eseguire il nostro programma ci bastano Python e la libreria standard. Ci accolliamo un po' di codice in più da scrivere, però evitiamo di dover gestire l'aggiunta di pacchetti extra.

I task sono file che gestiamo in Obsidian

Le task da fare sono in realtà dei file. In particolare file da gestire in Obsidian. Magari dentro al file mi segno l'url del servizio da testare o un po' di note sulle cose da fare.

Quello che mi aspetto è questo: – dico a Rdone di aggiungere un task. Mi crea il file in markdown (il formato di Obsidian) e me lo mette in una cartella dedicata – accetto di fare un task del (me)Rdone. Mi apre il file in questione in Obsidian. Questo è comodissimo se uno deve prendere e si becca un task che riguarda lo scrivere qualcosa.

Lato applicativo, il fatto che i task siano file ci semplifica parecchio le cose: non ci sono grandi query da fare, si tratta di prendere e contare i file che sono in una determinata cartella – quello delle task da fare. Quando un task è completato, lo spostiamo in un'altra cartella. Questo si porta dietro due cose di cui essere consapevoli: da una parte ci toccherà interagire con Obsidian per aprire i file; dall'altra se vogliamo associate dei metadati alle task tipo quando sono state create o completate dobbiamo scendere a compromessi col fatto che le task non sono nostri oggetti sul database, ma – appunto – file.

Obsidian delle mie brame

Capire come usare Obsidian per aprire un file è stata la parte più complicate. Ho creato una funzione di Python che aprisse un file test.md usando Obsidian. Qui ci sono un po' di considerazioni da fare.

Partiamo da una cosa più facile. Apriamo e basta un file di testo. Ovviamente ogni sistema operativo fa come gli pare: macOS ha un comando, Windows un altro, Linux ancora un altro. E, sviluppando dentro un devcontainer da macOS, ci si ritrova in una situazione in cui sviluppi in un mondo (Linux) ma userai il programma in un altro.

In fondo metto uno schema per queste differenze, soprattutto per me che presto mi dimenticherò di averlo fatto.

Obsidian aggiunge un livello di complessità. Al netto del fatto che ogni sistema operativo apre i file a modo suo, adesso tocca aprire usando Obsidian.

A quanto pare dobbiamo risolvere questo

subprocess.run([opener, uri],

L'apertura di Obsidian è un sottoprocesso rispetto alla nostra app che gira da linea di comando. Per eseguirlo ci serve un comando di apertura – e qui ci risolviamo la questione del sistema operativo – e una risorsa da aprire. Questa risorsa è obsidian. Qui la documentazione di Obsidian ci dice come usare open. E, volendo, qui c'è un plugin per fare ancora più cose con l'apertura dei file in obsdian.

Qui si apre un problemino extra. Obsidian si apre alle sue condizioni. Obisdian ragiona in Vault, la cassaforte dove tenere i file. In pratica: Obsidian apre solo una cassaforte, non possiamo aprire obsidian “into the wild” se vogliamo aprire dei file. Quindi

Da scriptino in Python a “hey, vive nel mio sistema”

Abbiamo uno script, lo abbiamo messo nella cartella giusta di Obsidian. Praticamente funziona e ci siamo. Però come facciamo ad eseguire tutto da terminale? Questo è l'ultimo passo che ci tocca fare.

In pratica dobbiamo fare due cose: 1. assicurarci che lo script sia eseguibile 2. fare in modo che il terminale sappia che quando scriviamo qualcosa (nel mio caso rdone) vogliamo utilizzare quello script, e renderlo disponibile ovunque.

Si fa abbastanza presto. Lato Mac con questa riga all'inizio del file

#!/usr/bin/env python3 Lo rendiamo eseguibile. Poi dobbiamo assicurarci che chi interagisce col file abbia i permessi per farlo, quindi chmod +x script.py (script.py è il nostro file, la x sono i permessi di esecuzione) per poter eseguire direttamente ./script.py

Per renderlo eseguibile, dobbiamo aggiungere qualcosa nel nostro terminale. Un'operazione simile a quando definite una scorciatoia – tipo up per aprire tutto quello che vi serve per lavorare. O magari tipo alcune personalizzazioni in git.

In pratica creiamo una cartella dove mettere il nostro programma (bin, un altro modo convenzionale per parlare di scatoloni). Colleghiamo il nostro file dentro obsidian con questo scatolone con un link simbolico (symlink) Il link simbolico è quello con cui evocheremo il comando. Aggiungiamo il nome fittizio del link simbolico al terminale.

Tutto insieme è questo (macOS / Linux):

mkdir -p ~/bin # creiamo una cartella di comodo
chmod +x ~/Documents/vault_obsidian/randomdone_tasks/random_done.py # diamo i permessi per eseguire il file
ln -sf ~/Documents/vault_obsidian/randomdone_tasks/random_done.py ~/bin/rdone # link simbolico. Se non vi piace 'rdone aggiustatelo
echo 'export PATH="$HOME/bin:$PATH"' >> ~/.zshrc # il terminale sa che il nostro file è disponibile, aggiungiamo il nostro ~/bin al PATH del terminale
source ~/.zshrc # refresh del terminale

E su Windows?

C'è da passare dai bat, ma ancora non ho provato. Qualcosa del tipo

A proposito di differenze

Recap e schemini

#obsidian #taskmanager #randomdone #python #coding

Ci si vede nel Fediverso?

In attesa di capire come funzionano i commenti in Writefreely, e se val la pena aggiungerli, mi trovate qui nel fediverso.