Category Archives: newLISP

Il linguaggio di programmazione NewLISP, e i suoi parenti (fratelli, cugini, etc.)

Unicode – il carattere e il codice – 3

Continuo –e forse oggi finisco– la storia dei caratteri Unicode,  isole  emoji compresi. Ne ho scritto qui e qui.

Ogni tanto mi capita di dover fare qualche elaborazione veloce e –secondo me– un tool unico è newLISP, anche qualcuno poi mi guarda male. Sperando che non mi legga ecco cosa mi è serendipicamente venuto in mente:

Visto? la procedura (ma il manuale le chiama funzioni) char funziona nei due sensi: se gli passi un codice restituisce il carattere, se gli passi un carattere restituisce il codice: due piccioni con una fava 💥

La prima versione, da lanciare come script (sapete, ha i suoi quirks, come si vedrà a breve), ecco il file u0.nl, scrive info provvisorie:

;; u0.nl

(println (main-args))
(set 'dato (main-args 2))
(println 1 " " dato)
(set 'isnum (not (= (int dato) nil))) 
(println 2 " " isnum)
(println 3 " " (char (int dato)))
(println 4 " " (char (main-args 2)))

(exit)

OK, la variabile isnum discrimina i casi codice / carattere; posso quindi passare a u1.nl, prototipo funzionante:

;; u.nl

(set 'dato (main-args 2))
(println 1 " " dato)
(set 'isnum (not (= (int dato) nil))) 
(println 2 " " isnum)
(if isnum 
    (println 3 " " (char (int dato)))
    (println 4 " " (char (main-args 2))))

(exit)

OK, da pulire, eliminare le variabili inutili e, se deve restituire il codice visualizzarlo anche in esadecimale (u2.nl):

;; u2.nl

(if (not (= (int (main-args 2)) nil)) 
    (println (char (int (main-args 2))))
    (println (char (main-args 2)) (format " 0x%x" (char (main-args 2)))))

(exit)

OK, ma adesso il motivo vero per cui questa versione. L’output viene visualizzato nel terminale ma collegandola (via pipe) a xclip posso caricarla nella clipboard, così:

Con newLISP posso eseguire un comando esterno via exec:

E, come previsto ho il dato nella clipboard. Applicato al compito corrente diventa (u3.nl):

;; u3.nl

(if (not (= (int (main-args 2)) nil))
    (set 'ans (char (int (main-args 2))))
    (set 'ans (string (char (main-args 2))
              (format " 0x%x" (char (main-args 2))))))
(println ans)
(exec (string "echo " ans " | xclip -f -selection clipboard"))
    
(exit)

OK, funziona come previsto. L’ultimo passo è quello di rendere eseguibile lo script cosa che si potrebbe fare aggiungendo la shebang e abilitandolo con chmod. Ma esiste un alternativa assai più sexy, compilarlo. c’è però un quirk come annunciat all’inizio del post.

Consideriamo lo script di test t.nl:

#!/usr/bin/newlisp

(set 'largs (main-args))
(set 'len (length largs)) 
(println len)
(println largs)
(for (n 0 (- len 1))
    (println n " " (largs n)))
    
(exit)

Compilo lo script:

e lo eseguo

OOPS! 😯 il primo argomento adesso è il numero 1 😯
Per cui lo script per la gestione dell’Unicode va modificato (nelle righe indicate con * come commento) sostitunedo il parametro 2 con 1 per main-args; inoltre gestisco la mancanza del parametro, file uc.nl:

;; uc.nl viene compilato con il nome _u

(when (= (length (main-args)) 1)                        ;; * 
        (println "manca il codice o il carattere")
        (exit 2))

(if (not (= (int (main-args 1)) nil))                   ;; *
    (set 'ans (char (int (main-args 1))))               ;; *
    (set 'ans (string (char (main-args 1))              ;; *
              (format " 0x%x" (char (main-args 1))))))  ;; *
(println ans)
(exec (string "echo " ans " | xclip -f -selection clipboard"))
    
(exit)

Ed ecco

Anche se non posso farlo vedere il contnuto della clipboard è quello previsto. Comando _u adottato –per me. Da trasferire in ~/bin.

E –sempre secondo me– newLISP rockz! 👽

:mrgreen:

newLISP – nuova versione – 10.7

Uh! installo subito, da così

1
via download dal sito di newLISP e con l’aiuto (dubbio) del Software Center

2
Ecco, quasi 🙄

Intanto manca il certificato e salta fuori il solito warning 🙄 ma OK, vado e

3
Sì, quasi panico 👿 Il link (symbolico) non è dove dovrebbe essere, poco male, dista solo un cp 😀

OK, adesso prima di subito devo vedere quali sono le novità. Appena don Lucio aggiorna le News. Tanto io sono in ritardo anche su tutto il resto.

:mrgreen:

Installare newLISP

newlisp-rockets-pictureCome installare newLISP su Ubuntu 64 bits. Forse lo sanno tutti, o forse no –io per esempio.

newLISP rockz! è risaputo.
Ma a volte, come ho verificato in questi giorni, l’installazione normale non funziona, da errore “file o directory non esistente“. Panico?
No, niente panico, proprio come c’è scritto sulla copertina della Guida (grande libro, fondamentale, l’unico che serve davvero).

Nel caso specifico dopo aver fatto qualche tentativo per capire cos’era che mancava e aver mandato una richiesta d’aiuto a Lutz sono ricorso a G+. Trovato quasi subito. Qui: How to compile newLISP from source on 64-bit Ubuntu.

Funziona. Notare che:

  • il post è vecchio di 18 mesi;
  • il blog è operato da newLISP;
  • la versione corrente è la 10-6.0 e non quella indicata nel post.

eniac4

OK, caso risolto. Se avete un momento libero date una scorsa qui: Why newLISP on Rockets?

Ve l’ho già detto che newLISP rockz? Rocket Man too, nèh!

GEB.G ovvero come ho scoperto la ricorsività nella programmazione

gebIo sono in ferie. Nel senso che sto tentando di tenermi lontano dal ‘puter per qualche giorno, disintossicarmi. E cosa si fa in questi casi? Altro, per esempio rileggere i classici. Io sono alle prese con Gödel, Escher, Bach di Douglas Hofstadter (1979, versione italiana 1984).

Ogni volta che lo rileggo salta fuori qualcosa di nuovo. O, come nei giorni scorsi un ricordo (attenzione: nostalgia qui) di cose successe all’inizio degli anni ’80, peccato non aver tenuto appunti e sorgente dei programmi! (ma sono passati più di trent’anni).
Allora il mio ‘puter, il Pr1me 550, un mini voleva che si usasse principalmente il Fortran. Vero che c’erano linguaggi di scipting come il CPL, Cobol e RPG per i gestionali, Basic per Giorgio ma erano complementari. E i capi insistevano per usare il IV (1964) meno esoso di risorse del 77 (1978).
DRH invece parla di ricorsività, vietata nel Fortran, prendi questo pezzo copiato da p.146-148 (sperando che l’autore e il sgnor Adelphi non si arrabbino):

Possiamo definire strutture geometriche infinite usando lo stesso metodo, cioè quello di espandere un nodo dopo l’altro. Per esempio, definiamo un diagramma infinito chiamato “Diagramma G”. Useremo a questo scopo una rappresentazione implicita. In due nodi scriveremo semplicemente la lettera ‘G’, che starà per una copia del Diagramma G. Nella Figura 31a abbiamo disegnato il Diagramma G implicitamente.

g1

Ora, se vogliamo vedere il Diagramma G più esplicitamente, possiamo espandere ognuna delle due G, cioè, sostituirle con lo stesso diagramma, ma in dimensioni ridotte (vedi Fig. 31b). Questa versione “di secondo ordine” del diagramma G ci dà una vaga idea dell’aspetto che avrebbe il Diagramma G se fosse completato, cosa che è impossibile.

g2

Nella Figura 32 si vede una parte ancora più grande del Diagramma G, in cui i nodi sono stati numerati, cominciando dal basso e da sinistra a destra. In basso sono stati inseriti due nodi supplementari che portano i numeri 1 e 2.
[…]
Ma il Diagramma G possiede proprietà ancora più sorprendenti. Tutta la sua struttura può essere racchiusa in un’unica definizione ricorsiva che è la seguente:

g3Come fa questa funzione G(n) a racchiudere la struttura ad albero di G? È molto semplice: se si costruisce un albero nel quale si colloca G(n) al di sotto di n per tutti i valori di n, si ritrova il Diagramma G. È proprio così che ho scoperto il Diagramma G la prima volta. Stavo indagando la funzione G e, mentre cercavo un metodo rapido per calcolarne i valori, mi venne l’idea di disporre i valori già noti in un albero. Con mia grande sorpresa, trovai che questo albero ammetteva quella descrizione geometrica ricorsiva estremamente ordinata.

Etc.
Uh! mi ero detto, chissà se… A quei tempi era normale avere un contratto di assistenza, tipo che l’hard disk andava in crash un paio di volte all’anno (fare spesso il back-up!) e conoscevi bene i tecnici. Io mi ero fatto dare un nastro con una versione non proprio ufficiale del Lisp e me ne sono innamorato, e perdura ancora. Tanto che l’altra sera arrivato a p.148 del GEB mi sono detto: ma la G cos’è già che fa, e se…
Ecco (g.nl):

#!/usr/bin/newlisp

(define (g n)
	(if (= 0 n) 
		0
		(- n (g (g (- n 1))))))

;; main
(set 'n (int (main-args 2)))
(print n " -> " (g n) "\n")
(exit)

gnl

Sì, lo so che il Lisp non è che piaccia proprio a tutti e allora ecco Python, il Basic di adesso, ormai la ricorsività non è più un taboo (g.py):

#!/usr/bin/env python3

from sys import argv

def g(n):
	if n == 0:
		return 0
	else:
		return n - g(g(n - 1))

#main
n = int(argv[1])
print(n, '->', g(n))

gpy
OK?
Ma però –ricordo perfettamente– mi disse teh Boss: la ricorsività costa!
Vero. Riscriviamo lo script Python à la Fortran –potrei installarlo ma sapete che sono in ferie :wink:– (g-nonric.py):

#!/usr/bin/env python3

from sys import argv

n = int(argv[1])
g = [0]
for c in range(1, n + 1):
	g.append(c - g[g[c - 1]])
print(n, '->', g[n])

Adesso g non è più una funzione ma una lista, in Fortran sarebbe un array. A proposito allora gli array si chiamavano vettori se monodimensionali e matrici se con due o più dimensioni, oggi i giovani mi hanno cambiato anche il vocabolario 😯

Non cambia niente ma i pythonisti per bene userebbero la list comprehension, lo script precedente sarebbe così:

#!/usr/bin/env python3

from sys import argv

n = int(argv[1])
g = [0]
[g.append(c - g[g[c - 1]]) 
	for c in range(1, n + 1)]
print(n, '->', g[n])

Quindi torniamo all’osservazione del capo di allora (se vi dicessi che il suo nome inizia per G ci credereste?), ecco:

cpy

Quasi 17 secondi contro meno di 3 centesimi! G, teh Boss ha ragione, ancora adesso. Lo so che non interessa ma newLISP ha la possibilità di creare l’eseguibile, vediamo:

cnl

Nessun vantaggio. Però basta nostalgia e basta ‘puter, sono in ferie 😉

Modificare il testo (IV) con newLISP

nl-logo

Nell’ultimo post sull’argomento dicevo cose brutte sul migliore dei linguaggi di scripting disponibile nell’Universo Mondo.
Sbagliavo. Era tutta colpa mia! “E leggersi quel *bip* di manuale!” come si diceva una volta (frase che ho usato anch’io con chi potevo, ma solo quando non riuscivo a controllarmi). OK, era semplice, ecco qui la versione per i file provenienti da Excel (o equivalenti).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
#!/usr/bin/newlisp

(set 'fname (main-args 2))
(if (= fname nil) (begin (println "errore") (exit 2)))
(if (not (file? fname)) (begin 
                (println "file non trovato") (exit 2)))
(set 'txt (read-file fname))

(replace {(\d)(,)(\d)} txt (string $1 "." $3)  0)
(replace {[;\t]} txt " "  0)
(println txt)
(exit)

L’errore che facevo era nella definizione della RE che  dev’essere delimitata con le parentesi graffe e non con le virgolette. Capita la stessa cosa di virgolette semplici e doppie per la shell.

E si può fare anche il test con tanti dati, come con Python?
Certo, ecco:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
#!/usr/bin/newlisp

(set 'fname (main-args 2))
(if (= fname nil) (begin (println "errore") (exit 2)))
(if (not (file? fname)) (begin 
                (println "file non trovato") (exit 2)))
(set 'txt (read-file fname))

(replace {(\S)(u)(\S)} txt (string $1 "*" $3)  0)
(replace {[vw]} txt "#"  0)
(println txt)
(exit)

nl1nl2e
time
OK, ri-fatto 🙄

Modificare il testo

b

Le espressioni regolari (re, regexp o altre sigle) sono una cosa bellissima o difficilissima. Io ci arriverò, ma non subito. Anche perché non è detto che serva tutta la loro potenzialità. Come nei post precedenti qui (e commenti) e qui ci sono casi più semplici.

Per esempio se avete dati in un foglio i calcolo (come Excel, non necessariamente quello di M$, sono ottimi quelli FOSS) potete salvarli separando i contenuti delle celle con tab o il carattere predefinito per il CSV, il punto-virgola per la versione italiana.

Con Linux la cosa è immediata:

dtab

e

dpv

Il carattere “è” è fuori dal set ASCII ma se reindirizzate l’output in un file vedrete che c’è.
Ecco se vivessimo in un universo leibniziano (il migliore dei mondi possibili) si userebbe solo Linux e il mio post finirebbe qui. Invece no: entri Windows 🙄

Qui sed non c’è. Vero che potrei anche installarlo, lui e altro, p.es. vedi qui o qui.
Ma ci sono soluzioni più semplici. Il mio amico Beppe ha risolto tutto con un programmino (non tanto -ino in realtà) in Visual Basic ma se volessimo che lo stesso programma (probabilmente uno script) sia disponibile per entrambi gli OS dovremmo ricorrere a altri linguaggi, possibilmente freeware.

Io una soluzione semplice e elegante ce l’ho, da sempre, ecco lo script nella versione più semplice (e comprensibile):

1
2
3
4
5
6
7
8
#!/usr/bin/newlisp

(set 'fname (main-args 2))
(set 'txt (read-file fname))
(if (= txt nil) (begin (println "errore") (exit 2)))
(set 'stxt (replace ";" txt " "))
(println stxt) 
(exit 0)

Naturalmente qualsiasi lispista oltre quota 101 avrebbe a che ridire, sapete la moda (non solo moda) della programmazione funzionale e allora, senza esagerare, ecco:

1
2
3
4
5
6
#!/usr/bin/newlisp

(set 'txt (read-file (main-args 2)))
(if (= txt nil) (begin (println "errore") (exit 2)))
(println (replace ";" txt " "))
(exit 0)

nl

Un lispista finito sposterebbe certamente la parentesi che chiude l’if al findo e unificherebbe le righe restanti (sì, lambda) ma si era detto di fare un passo per volta, no?

Questo script è quasi buono. Notare che basterebbe cambiare il carattere “;” con “\t” o quel che si vuole nella replace per adattarlo agli altri casi. È inotre immediato creare l’eseguibile .exe soluzione normale (quasi d’obbligo) per Windows, in questo caso non hai bisogno di installare newLisp, basta l’eseguibile stand-alone.
Ma –c’è sempre un ma– si era detto (nei post precedenti) che stiamo tentando di ridurre il numero di linguaggi di programmazione usati (cosa che mi sento dire da 30 anni in verità e il loro numero è sempre cresciuto) e allora niente, da rifare con Python, o altro, idee? suggerimenti?.
Prossimamente… forse… :mrgreen:

L’errore misterioso (ci casco ogni volta)

nl-logo
Questa è solo una storiella. Ma devo raccontarla anche perché dimostra come siano cambiando le cose e noi vecchi alle volte, anzi troppo spesso, fatichiamo a tenere il passo.

C’è un’aggravante (grave): lo script incriminato è 1) mio; e 2) (più grave) scritto in newLISP. Come vedremo alla fine del post non è un problema di newLISP (che è un linguaggio di scripting molto simile a Python, Ruby, Lua o quello che usate di solito, solo con la sintassi del Lisp).

Ricevo una telefonata disperata (perché non ho risposto subito a tre email spempre più disperate) sul fatto che lo script non funziona più. “Ma come”, dico io, “è vecchio e supercollaudato!”, in relatà è dell’inizio del 2009, ha quasi 5 anni. Risulta che doveva essere usato lanciandolo da Python, riscriverlo non è impossibile ma if it’s work…

Naturalmente non riesco a riprodurre l’errore, da me funziona, come sempre.
Per vedere di cosa sto parlando ho estratto il pezzo incriminato, in realtà era una funzione ma così dovrebbe essere più chiaro.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
#!/usr/bin/newlisp

(println "argomenti: " (main-args))
(set 'n (if (find "newlisp" (main-args 0)) 2 1))
(set 'fdat (main-args n))
(println n " " fdat)
(if (nil? fdat) 
    (begin
        (println "specificare il file dei dati")
        (exit)))
(if (file? fdat)
    (println "il file dei dati è " fdat)
    (println "manca il file dei dati"))
(exit)

tok

Con Linux è normale attivare lo script:

r

OK, continua a funzionare. Anche se non è il nostro caso, ma non si sa mai e l’if della riga 4 era proprio per quell’evenienza, è possibile creare un eseguibile (la procedura è cambiata recentemente):

xt

Funziona anche in questo caso. Qui si vede una particolarità (unica probabilmente) di newLISP: la lista dei parametri non è quella che normalmente si ottiene con gli altri linguaggi e poi varia se interpretato o eseguito.

Insomma: panico! Come ultima risorsa non resta che un’ispezione sul luogo del misfatto. Caso risolto. Per noi vecchi:

spazi

Ah! Ormai è normale, siamo nel 2013 😳
Ricordarselo (nota per me) 🙄

Uh! ‘na cosa, visto che siamo nel 2013 e va di moda la programmazione funzionale possiamo fare a meno della variabile n, così:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
#!/usr/bin/newlisp

(println "argomenti: " (main-args))
(set 'fdat (if (find "newlisp" (main-args 0)) 
    (main-args 2) 
    (main-args 1)))
(println fdat)
(if (nil? fdat) 
    (begin
        (println "specificare il file dei dati")
        (exit)))
(if (file? fdat)
    (println "il file dei dati è " fdat)
    (println "manca il file dei dati"))
(exit)

E se questo codice finisce in una funzione eliminiamo anche fdat. Resta sempre il fatto che scrive, non è ancora pura 😯

10.5.6

Link simbolici

linkUn post didascalico con uno spiegone per un mio amcico che viene da Windows. E un’ottima occasione per provare Lubit.

Per evitare un’inutile accumulo di tensione spasmodica con conseguenze imprevedibili vi dico subito che il test è stato superato brillantemente. Ho tenuto d’occhio Conky e l’uso della RAM non ho mai superato 145MB. Adesso, su Ubuntu RR con 4 schede di Firefox, Gedit, Nautilus, Eog (visualizzatore di immagini) e qualche altra utility sono a 620MB.
Devo anche confessarvi un’altra cosa: ho installato Gedit su Lubit e Conky ha fatto un salto da 145 a 198MB. Era una prova, non so nemmeno se serve, Leafpad è OK.

Linux ha ereditato da Unix una cosa meravigliosa (una delle tante): i link. Adesso non è che vi racconto tutto quello che ci sarebbe da dire sui link, hard e simbolici. Semplicemente vediamo un paio di cose di quest’ultimo tipo, il più giovane, quello che ottenete facendo click con il tasto destro sull’icona di un file e scegliendo Crea collegamento. Questo nell’ambiente grafico, io che sono vecchio… OK, uso il terminale.

Sono partito da uno script semplicissimo in Python, ds.py:

#!/usr/bin/python
# -*- coding: utf-8 -*-

import os, os.path, sys

print "La directory corrente è:\n", os.path.abspath(os.curdir)
scrdir = os.path.dirname(os.path.realpath(sys.argv[0]))
print "\nLa directory dello script è\n", scrdir

e questo è lo screenshot del terminale. Sì, ho fatto un pasticcio: manca la riga del primo comando, che sarebbe python ds.py.

p0

Le prime righe sono come ce le aspettiamo, anche per chi viene da Windows. Poi le cose cambiano: chmod +x ds.py rende lo script eseguibile, cosa che si potrebbe fare anche con click con tasto destro / Proprietà / Permessi / Consentire l’esecuzione….
Questo in virtù della shebang, la prima riga dello script.
Segue la prova di esecuzione ./ds.py, tutto OK.
A questo punto mi sono trasferito nella directory ~/bin. Altra particolarità di Linux (e prima di Unix): se c’è bin nella tua home viene automaticamente inserita nella PATH (all’avvio, quindi non potete pretendere di averla subito disponibile appena creata (ci sarebbe un discorso lungo da fare, diciamo che dovete ri-logarvi)).
Lì ho creato il link DS e l’ho testato. OK, come pure quando mi sono spostato nella home e in altre directories (non presenti nell’immagine ma provate e vedrete che funziona tutto).

A questo punto lo spiegone dei link sarebbe finito. Da studiare bene che la prossima volta interrogo, nèh! Anzi compito in classe.

Però visto che ci sono continuo, faccio un altro test. Questa volta voglio creare un eseguibile. Un compilatore leggero ce l’ho, newLISP che ultimamente è cambiato parecchio, vediamo (s-d.nl):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
#!/usr/bin/newlisp

(println "La directory corrente è:\n" (real-path "."))
(set 'nf (main-args 0))
(set 'rnf (real-path nf true))
(set 'tree (parse rnf "/"))
(pop tree -1)
(set 'dir (join tree "/"))
(println "\nLa directory del programma è:\n" dir)
(exit)

che produce questi risultati:

nl

Notare l’errore che ottengo lanciando l’eseguibile dalla directory in cui si trova; non sono riuscito a capirne la ragione. Poi tutto come per Python.

OK, questo è tutto. Solo più due comunicazioni per la regia:

Bit3Lux potrebbe pensare che sto barando; in effetti gli avevo comunicato che facevo altro, solo rimandato, prossimamente…
A me sembra che il post sia venuto bene, lo riciclo anche sull’altro blog, sperando che nessuno se ne accorga 😉

Note:

  • questo post è stato pubblicato sul blog dell’amico Bit3Lux, qui: Link simbolici;
  • ho provato anche la versione interpretata, problemi diversi ma anche lì risposta diversamente corretta.

Maiuscolo|minuscolo – ultima puntata

tmm-finOggi concludo la telenovela serie sulla conversione maiuscolo|minuscolo all’interno della clipboard. Le puntate precedenti sono qui e qui.
Avevo pensato di poter utilizzare il comando echo con l’opzione dell’here document ma non ci sono riuscito. Non so se è una mia carenza o il metodo non è praticabile. Sono ricorso a cat, soluzione meno bella perché ho dovuto creare un file temporaneo in /tmp.

Il codice è commentato e semplicissimo (non cambia granché dalla puntata precedente) per cui eccolo, senza preamboli:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/usr/bin/newlisp

;; get state of CapsLock
(set 'clON (% (int (slice (string 
        (exec "xset q | grep LED")) -4 2)) 2))

;; get clipboard content
(set 'txt (join (exec "xsel -ob") "\n"))
;;  case translate
(if (= clON 1) 
    (set 'txt (upper-case txt))
    (set 'txt (lower-case txt)))

;; park in a temp file
(set 'tmpf "/tmp/Mm")
(write-file tmpf txt)

;; put the temp file it in the clipboard
(set 'cmd (join (list "cat " tmpf " | xsel -ib")))
(exec cmd)
(delete-file tmpf)

(exit)

Si potrebbe ancora modificarlo rendendolo più lispico ma poi si perderebbe la possibilità di confronto con la versione del passo successivo, questo che segue immediatamente.

Se a questo punto qualcuno ponesse la domanda “ma si deve fare con newLISP?” risponderei “certo che no! ecco la versione con Python”.

#!/usr/bin/python
# -*- coding: utf-8 -*-

import subprocess, os

# stato di capslock
cmd = "xset q | grep LED"
ps = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,
                      stderr=subprocess.STDOUT)
output = (ps.communicate()[0]).strip()
clON = int(output[-2:]) % 2

# contenuto della clipboard
cmd = "xsel -ob"
ps = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
txt = (ps.communicate()[0])

# converto
if clON:
    txt = txt.upper()
else:
    txt = txt.lower()

# lo parcheggio in un file temporaneo
tmpf = "/tmp/Mm"
f = open(tmpf, 'w')
f.write(txt)
f.close()

# copio il file nella clipboard
#cmd = "cat"
cmd = "cat {0} | xsel -ib".format(tmpf)
os.system(cmd) #, "", shell = True)
os.remove(tmpf)

Sono quasi equivalenti. Ecco un dump del test effettuato.

MMSì newLISP converte anche le lettere non ASCII 😀
Ma siccome è un’inutility il discorso, per me, si chiude qua 😉

Ancora su maiuscolo|minuscolo

tmm2OK, lo so che non serve a niente ma voglio relazionarvi. Si continua dal post precedente: Convertire testo in maiuscolo|minuscolo.
Mentre preparavo quel post mi era venuto in mente che…
Non avevo considerato la Legge di Hofstadter. Cosa imperdonabile per chiunque abbia avuto accesso a uno o più ‘puters per più di qualche anno. Ma tant’è, sembrava facile. E poi la soluzione precedente non funziona con i caratteri con numero ASCII/ANSI maggiore a 127.
Eppure guarda qua:

nl-ulahemmm, sì, ma posso smettere quando voglio, dai 😉

Allora sono riuscito a fare questo:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
#!/usr/bin/newlisp

;; get state of CapsLock
(set 'clON (% (int (slice (string 
        (exec "xset q | grep LED")) -4 2)) 2))

;; get clipboard content
(set 'txt (join (exec "xsel -ob") "§"))

;;  case translate
(if (= clON 1) 
    (set 'txt (upper-case txt))
    (set 'txt (lower-case txt)))

;; set it in the clipboard
(set 'cmd (join (list "echo " txt " | xsel -ib")))
(exec cmd)

(exit)

Che non è ancora perfetto, non gestisce correttamente la selezione multilinea. Il workaround attuale è di sostituire l’a-capo con il carattere § (galassia a spirale?). E c’è ancora da vedere quelli che la shell considera caratteri speciali, che pal 😦

Insomma ci sarebbe ancora da fare, chissà forse, anche perché sembra semplice. Per esempio per la selezione multilinea c’è l’here document.

E anche i caratteri speciali possono essere escapati. Noioso ma fattibile. E per questo lo script usa parecchie variabili, ridondanti ma utili per il debug. Poi quando sarà a posto sarà molto più elegante, forse.

Chissà… Comunque posso smettere quando voglio. E c’è Ruby che aspetta. Anche se sembra tutto davvero semplice.
Anche tenendo conto della Legge di Hofstadter 😉