pondělí 7. května 2012

Rozšíření Nautila vlastními skripty

Nautilus umožňuje velmi jednoduše rozšířit svou kontextovou nabídku (to menu, co se zobrazí po kliknutí pravým myšítkem). Úplně nejjednodušší je použití skriptů, které jen umístíte do patřičného adresáře a Nautilus přidá do své kontextové nabídky submenu Skripty, kde je pak najdete. Pokud by se měla vaše rozšíření objevit v první úrovni kontextového menu, je to možné zařídit třeba za pomoci modulu python-nautilus a napsat tedy rozšíření v Pythonu.
V aktuálním Ubuntu chybí nějaké ty balíky s rozšířeními pro Nautila, jako například nautilus-gksu, který umožňoval spouštět vybrané položky s právy roota. Je to proto, že je autoři zatím nepřepsali do podoby vhodné pro aktuální GNOME 3. Tak si můžeme jednoduše pomoct sami a vystačíme si prozatím s BASHem.

Uživatelské skripty se strkají do adresáře
~/.gnome2/nautilus-scripts
(funguje stále i v GNOME 3)
UPDATE: přinejmenším od Ubuntu 13.04 je třeba použít nové umístění:
~/.local/share/nautilus/scripts/
Nautilus skripty spouští s parametrem v podobě seznamu jmen vybraných souborů a adresářů. Zároveň přidá Nautilus pár proměnných, ze kterých mohou vaše skripty čerpat další informace.
Proměnné Nautilus dodá tyto:

$NAUTILUS_SCRIPT_SELECTED_FILE_PATHS - seznam cest k vybraným souborům, ale pouze lokálním
$NAUTILUS_SCRIPT_SELECTED_URIS - seznam URI k vybraným souborům
$NAUTILUS_SCRIPT_CURRENT_URI - URI aktuálního adresáře
$NAUTILUS_SCRIPT_WINDOW_GEOMETRY - velikost a umístění aktuálního okna: šířka, výška, x, y

Položky v seznamech jsou oddělené znaky nového řádku (\n).

Vzhledem k tomu, že Nautilus zařídí, aby pracovním adresářem vašeho skriptu byl aktuální adresář otevřený okně ze kterého skript voláte, dá se říct, že:

[ $NAUTILUS_SCRIPT_CURRENT_URI == `pwd` ]

pwd je příkaz, který vypíše aktuální pracovní adresář.

Také se dá říci, že pokud nezměníte pracovní adresář, jsou následující proměnné stejně použitelné:

[[ $NAUTILUS_SCRIPT_SELECTED_FILE_PATHS =~ $@ ]]

Jde o to, že $@ obsahuje jména všech vybraných souborů/adresářů, kdežto zmíněná proměnná Nautila obsahuje celé cesty k nim. Pokud chcete vybrané položky otevírat nějakým dalším programem, je v této situaci jedno, jestli dostane jen jméno souboru (bude ho hledat v aktuálním adresáři), nebo celou cestu k němu. Zmíněný test v syntaxi BASHe testuje, zda první prměnná obsahuje druhou proměnnou. Pokud bude vybranách souborů více, tato podmínka samozřejmě nebude splněna, ale bude splněna pro každou jednotlivou položku obou proměnných. To si jen trochu prosvišťuju BASH :)

Otevřít jako root

Faktem je, že se mi nepodařilo otevřít více Nautilem vybraných položek pod rootem, na druhou stranu jsem to osobně nikdy nepotřeboval a tak mi to nevadí.
Skript na otevírání souborů by mohl vypadat takto:

#!/bin/bash

[ -z $NAUTILUS_SCRIPT_SELECTED_URIS ] && gksu nautilus "$NAUTILUS_SCRIPT_CURRENT_URI"
IFS=$'\n'
for p in $NAUTILUS_SCRIPT_SELECTED_URIS; do
  gksu gnome-open "$p" &
done

Pokud z toho vyhodíte gksu, bude to fungovat pro všechny vybrané soubory, ale s gksu se ve skutečnosti otevře pouze první v seznamu. Alespoň v aktálním Ubuntu. Takže by se dal skript přepsat tak, aby prostě bral jen první adresu a zbavit se zbytečné smyčky. Musíte také počítat i s tím, že asociace souborů, které jste si nastavili sami pro vašeho uživatele, nebudou pod rootem k dispozici.

Uvedený skript testuje, zda vůbec nějaké položky vybrané jsou a pokud ne, otevře pod rootem v Nautilovi aktuální adresář. V tomto případě se následující smyčka přeskočí pro nedostatek vstupních dat. Proměnná $IFS určuje oddělovač, standardně je to mezera, ale naše položky jsou oddělené novým řádkem - \n.

V případě, že nějaké položky vybrané jsou, projdou se jejich URI jedna po druhé a předhodí se aplikaci gnome-open, která je otevře jednu po druhé v aplikacích, které jsou jednotlivým položkám (soubory/adresáře) přiřazené (nastavit/modifikovat se dají v ve vlastnostech souboru přímo v Nautilu), stejně, jako byste na každou poklepali myší v okně Nautila. & na konci zajistí, že se proces spustí na pozadí a rovnou se přejde na další položku v seznamu, jinak by se čekalo na ukončení spuštěného procesu.
Jenže, jak jsem zmínil, pod rootem to takhle nefunguje, cykus proběhne ale otevře se pouze první položka.

Pokud byste místo proměnné $NAUTILUS_SCRIPT_SELECTED_URIS, použili $@, nebo $NAUTILUS_SCRIPT_SELECTED_FILE_PATHS, fungovalo by to pro lokální soubory stejně, ale pokud se vybrané položky nacházejí třeba na síti, kam jste vlezli přes sambu, nebo jinou službu, budou tyto proměnné prázdné. URI obsahuje kromě cesty i prefix obsahující identifikátor zdroje, kde se data náchází. Například následující cesty vedou v mém systému ke stejnému souboru:

smb://gdh-ep45-ud3p/home/gdh/.gnome2/nautilus-scripts/Open%20as%20root
file:///home/gdh/.gnome2/nautilus-scripts/Open%20as%20root
/home/gdh/.gnome2/nautilus-scripts/Open as root

URI adresy se také liší v tom, že některé speciální znaky jsou vyjádřeny kódem znaku - např. mezery jsou zapsány jako %20, obrácené apostrofy jako %60.

Otevřít v Guake

Jelikož používám jako terminál aplikaci Guake, hodí se mi možnost předat cestu k vybranému objektu právě jemu:

#!/bin/bash

if [ -n "$NAUTILUS_SCRIPT_SELECTED_FILE_PATHS" ]; then
   p="$NAUTILUS_SCRIPT_SELECTED_FILE_PATHS"
   IFS=$'\n'
   (for i in $p; do
      if [ -f "$i" ]; then
         i=`dirname $i`
      fi
      tabName=`basename $i`
      guake -n NEW_TAB
      guake -r "$tabName"
      i=`sed -e 's/\([ ()]\)/\\\\\1/g' <<< $i`
      guake -e cd\ "$i"
   done)
else
   p=`(cut -d'/' -f3-|sed 's/\([()]\)/\\\\\1/g; s/\%20/\\\\ /g')<<< "$NAUTILUS_SCRIPT_CURRENT_URI"`
   tabName=`basename "$(sed 's/\%20/ /g' <<< $NAUTILUS_SCRIPT_CURRENT_URI)"`
   guake -n NEW_TAB
   guake -r "$tabName"
   guake -e cd\ "$p"
fi

guake -t

V tomto skriptu je vidět práce s přeměnou URI zápisu na standardní aby mu rozuměl i Guake. Jednak je potřeba připravit cestu, na kterou přejde příkazem cd a pak i jméno tabu (tedy samostatného terminálu v rámci Guake), které bude obsahovat jméno adresáře, bez celé cesty. Příkazy shellu dirname (odstraní z cesty jméno souboru) a basename (naopak odstraní cestu a nechá jen jméno souboru) se občas hodí, i když sedem to zapíšete taky.

No tak zhruba takto, už mě to psaní zase vyčerpalo, tak si jdu odpočinout :)
Časem třeba přidám nějaké ty užitečné odkazy k tématu a příště napíšu, jak na to v Pythonu, v první úrovni menu s možností rozhodování, zda se položka v menu objeví, či ne, na základě vlastností vybraných souborů.

Související:
Nautilus Extension API z Pythonu
Jak obcházím nedostatky Rhythmboxu

Žádné komentáře:

Okomentovat

Zkuste prosím při komentováni používat místo volby Anonymní volbu Název/adresa URL, kde vyplníte nějakou přezdívku, adresu zadávat nemusíte. Vědět, které příspěvky jsou od jednoho člověka, je fajn. Díky.

Pokud by se vám náhodou odeslaný komentář na stránce nezobrazil, vytáhnu ho z koše hned jak si toho všimnu. I Google spam filter se občas sekne.