GNU Emacs - vždy je čo vylepšiť - #3 - tipy do Sunrise Commander

09.11 | 13:55 | Richard | Richard

V staršom zápise o Sunrise Commander-i sme si povedali, čo to je za dvojpanelový súborový manažér a prečo a načo ho používam. Ale s používaním som ho postupne vylepšoval a pár vylepšení by som rád uviedol, v nádeji, že niekomu budú inšpiráciou

GNU Emacs neprestáva fascinovať

Pretože tá rozšíriteľnosť je proste skvelá. Každý detail, ktorý sa nám nepáči, sa dá jednoducho zmeniť. A netreba byť ani (e)lispový guru.
Samozrejme, každý softvér s otvorenými kódmi sa dá modifikovať. Ale ak si predstavíme, že aké nástroje, knižnice a znalosti pri tom treba mať, tak nás to ľahko môže odradiť… a zmieriť sa so stavom vecí.

A pritom človek nepotrebuje zvyčajne meniť niečo fundamentálne. Zväčša sa jedná o drobnosti, alebo o pridanie malých funkcionalít, ktoré uľahčia každodenné úlohy.

Takže aj tieto moje zmeny nie sú kozmickou vedou. Možno komickou 😏.

 

Spájanie PDF

…používam pomerne často.. Napríklad exporty nákresov v CAD-e dávam do jedného súboru a posielam ich takto elektronickou poštou.
Malý kúsok kódu, v ktorom použijeme známy podftk:

(defun sr-join-pdf (&optional arg)
  "Join selected PDFs into one usind pdftk."
  (interactive)
  (let* ((fn-list (dired-get-marked-files nil arg)))
    (setq flist (format "%s" fn-list))
    (shell-command (concat "pdftk  "(dired-replace-in-string "[(|)]" " " flist)" cat output SPOJENE.pdf" )))
  (revert-buffer))

Obr. 1: Označenie PDF-iek a zavolanie sr-join-pdf

 

Zmenšovanie obrázkov

Tiež používam často - fotoaparát v mobile dnes "vypľuje" obrovské obrázky, rozlíšením i veľkosťou súboru. To je obtiažne posielať mailom, stále je veľkosť posielaných správ obmedzená (napr. na 20 MB), a nie vždy má zmysel posielať pár obrázkov cez nejaké úložisko. Často postačujú obrázky v nižšom rozlíšení. Na to použijeme zabalený imagemagick:

(defun sr-resize-images (&optional arg)
  "Resize marked images by 50% using imagemagick."
  (interactive)
  (let* ((fn-list (dired-get-marked-files nil arg)))
    (setq flist (format "%s" fn-list))
    (shell-command (concat "convert " (dired-replace-in-string "[(|)]" " " flist) " -resize 50% " (dired-replace-in-string "[(|)]" " " flist) )))
  (revert-buffer))

Aplikuje sa to na označené súbory… a ako vidieť, je to len analógia riešenia s PDF-kami.

 

Zaheslovanie a odheslovanie PDF

Napríklad bankové výpisy, alebo iné, e-mailom prijaté/odoslané dokumenty, musia byť chránené (kvôli GDPR).
Zase použijeme trik s volaním shell-command a pdftk:

(defun sr-decrypt-pdf (&optional arg)
  "Decrypt PDF using pdftk."
  (interactive "p")
  (let ((pass-query (read-from-minibuffer "Enter PDF password to decrypt: " ())))
    (shell-command (concat "pdftk " (thing-at-point 'filename) " input_pw " (format " %s " pass-query) "output "
                           (substring (thing-at-point 'filename) 0 -4) "-decrypted.pdf"))))

(defun sr-encrypt-pdf (&optional arg)
  "Encrypt PDF using pdftk."
  (interactive "p")
  (let ((pass-query (read-from-minibuffer "Enter PDF password to encrypt: " ())))
    (shell-command (concat "pdftk " (thing-at-point 'filename) " output "
                           (substring (thing-at-point 'filename) 0 -4) "-encrypted.pdf user_pw " (format " %s " pass-query)))))

No, ako som spomínal, nie je to nič, z čoho by sme padli na zadok, ale má to mieru užitočnosti.

 

Šifrovanie a dešifrovanie súborov pomocou ccrypt

Wikipedia o ccrypt píše: "Ccrypt je nástroj na bezpečné šifrovanie a dešifrovanie súborov a tokov. Bol navrhnutý ako náhrada za štandardný nástroj crypt systému UNIX, ktorý je známy tým, že používa veľmi slabý šifrovací algoritmus.

Program ccrypt je založený na šifre Rijndael, rovnakej šifre, ktorá sa používa v štandarde AES. V štandarde AES sa však používa 128-bitová veľkosť bloku, zatiaľ čo ccrypt používa 256-bitovú veľkosť bloku. ccrypt bežne používa pre šifrované súbory príponu .cpt.

No a naša implementácia:

(defun sr-encrypt-ccrypt (&optional arg)
  "Encrypt any file using ccrypt."
  (interactive "p")
  (let ((pass-query (read-from-minibuffer "Enter password to encrypt: " ())))
    (shell-command (concat "export heslo=\"" (format "%s" pass-query) "\" && ccrypt -e -E heslo " (thing-at-point 'filename)))))

(defun sr-decrypt-ccrypt (&optional arg)
  "Decrypt any file using ccrypt."
  (interactive "p")
  (let ((pass-query (read-from-minibuffer "Enter password to decrypt: " ())))
    (shell-command (concat "export heslo=\"" (format "%s" pass-query) "\" && ccrypt -d -E heslo " (thing-at-point 'filename)))))

 

Upload na 0x0.st

Poznáte službu 0x0.st? Je to dobrovoľnícky projekt zdieľania súborov, ktorý je rozdiel od iných služieb fantastický v tom, že upload sa dá spraviť pomocou cURL. Súbor je uschovávaný na ich serveri od 30 dní po jeden rok, čím menší, tým dlhšie. Pre Emacs na prácu s touto službou existuje rozšírenie 0x0. Použitie je priamočiare, a výsledný link na súbor je automaticky vložený do schránky.
Proste perfektné!

Obr. 2: Výber požadovaného príkazu

Obr. 3: …a adresa so súborom je vložená do kill-ringu

 

Výber súborov z definovaného zoznamu

Samozrejme, Emacs má viac nástrojov na prácu so zoznamom posledne otvorených súborov.
Ja mám však pár súborov, napríklad archív hesiel, poznámok a pod., ktoré chcem otvárať z osobitne vytvoreneného zoznamu.

Obr. 4: Výber súborov z elegantného menu

 

Na toto menu v rozšírení helm si pripravíme jednu funkciu a pár definícií (ktoré môžu byť aj zahrnuté do funkcie, ale neviem to teraz rýchlo nájsť… Edit: našiel som, uvediem v blogu o audiu v Emacse.).

V prvej definícii si vytvoríme pár, v ktorom je názov/popis a cestu k súboru (v príklade uvádzam len niekoľko položiek). V druhej zohrazujeme prvú (car) položku v zozname kandidátov a poslednú (cdr) zobrazujeme v správe a celú zvolenú dvojicu posielame cez helm do príkazu na otvorenie súboru - v interaktívnej funkcii.

(setq my-config-data '((".emacs" . "~/.emacs")
                       ("hesla" . "~/.hesla.org.gpg")
                       ("pal" . "~/.pal/richard.pal")))
(setq my-config-helm-source
      `((name . "Moje konfiguračné súbory a iné časté")
        (candidates . ,(mapcar 'car my-config-data))
        (action . (lambda (candidate)
                    (message "%s" (cdr (assoc candidate my-config-data)))))))
(defun open-my-config-data ()
  "Open my config files and others"
  (interactive)
  (find-file (helm :sources '(my-config-helm-source))))

 

Menu na uspanie/reštart/vypnutie počítača

A analogicky si môžeme spraviť pekné menu na uspanie, reštart, vypnutie počítača či vypnutie len obrazovky.

(setq poweroff-data '(("Suspend" . "sudo pm-suspend")
                      ("Reboot" . "sudo /sbin/reboot")
                      ("Power Off" . "sudo /sbin/halt")
                      ("Switch Off the screen" . "/home/richard/bin/screenoff")))
(setq poweroff-helm-source
      `((name . "Vypnutie počítača")
        (candidates . ,(mapcar 'car poweroff-data))
        (action . (lambda (candidate)
                    (message "%s" (cdr (assoc candidate poweroff-data)))))))
(defun poweroff-computer ()
  "Switch off or hibernate computer"
  (interactive)
  (shell-command (helm :sources '(poweroff-helm-source))))

 

Otváranie súborov ako root

V e-shelli, ako východzom shelli pre Sunrise Commander nie je možné otvoriť súbor jednoducho ako root. Nejaký trik ako sudo vi <súbor> nejde už len z toho princípu, že už sa nachádzame v samotnom textovom editore.

Preto používam tento spôsob:

(defun sudo-find-file (path)
  (let ((qualified-path (if (string-match "^/" path)
                            path
                          (concat (expand-file-name (eshell/pwd)) "/" path))))
    (find-file (concat "/sudo::" qualified-path))))

Defacto sa jedná o vloženie /sudo:: do cesty súboru.
Pretože, ak by sme otvárali súbor pomocou klávesovej skratky, vyzeralo by to takto: C-x C-f /sudo::<súbor>

 

Detox

Tentokrát sa nejedná o pitie cviklovej a zemiakovej šťavy počas určitého obdobia. Je to známy program, ktorý z názvov súborov odstraňuje diakritiku, medzery a kdejaké protivenstvá.

Mám to ale hodne zjednodušené, funkcia

(defun sr-detox ()
  "Clean file names from non ASCII chars."
  (interactive)
  (progn
    (shell-command (concat "~/bin/space-detox.sh"))
    (revert-buffer)))

len volá bash skript, ktorý je ešte jednoduchší:

#!/bin/bash
for file in *; do detox "$file" ; done

Takže tu je priestor, bash skript prepísať do (e)lispu (teda v princípe prepísať for cyklus). No, nabudúce.

 

Záver

Ako som uviedol, tá rozšíriteľnosť Emacsu (ale dá sa to aplikovať na slobodný svet vo všeobecnosti) je limitovaná len našou fantáziou (dalo by sa povedať, že aj zručnosťou, ale v konečnom dôsledku možno na nakódovanie niekoho osloviť - napr. známy Protesilaos 'Prot' Stavrou je tam horšie s financiami a verím, že jeho lispový potenciál je obrovský (https://protesilaos.com/news/2022-11-05-help-me-find-job-move-country/)).

A každý jeho (= slobodného softvéru) zástanca má určite sústavu nástrojov a trikov, ako si používanie vylepšiť, spríjemniť, priohnúť podľa svojich predstáv. Pritom sa uspokojí aj prirodzená ľudská hravosť a zvedavosť.