Plány na nový File Finder
- David Grudl
- Nette Core | 8227
Jedna z knihoven, které už moře let plánuju předělat, je Finder. Narazil jsem totiž časem na různé situace, kdy mi nevyhovoval.
V současnosti funguje takto:
Finder::findFiles('*.php', '*.inc')->in('/foo'); // hledá /foo/*.php a /foo/*.inc
Finder::findFiles('*.php', '*.inc')->from('/foo'); // hledá navíc v podadresářích
// nebo Finder::find() a Finder::findDirectories()
plus vyloučení:
Finder::findFiles('*.php', '*.inc')
->exclude('temp.php') // vyloučení názvu souboru
->from('/foo')
->exclude('vendor') // vyloučení cesty, nebude prohledávat např. v /foo/sub/vendor
V metodě in()
a from()
musí být platný
adresář, ve find*()
a exclude()
mohou být
souborové/adresářové masky.
Masky a cesty všude
Líbilo by se mi, kdyby šel konfigurovat podobně jako gitignore. Včetně podpory pro wildcard **
,
který představuje libovolně mnoho adresářů. Pokud zapíšu třeba
foo/**/file.php
, znamená to jak foo/sub/file.php
, tak
i foo/file.php
nebo foo/sub1/sub2/file.php
.
Plán je, že by ve všech zmíněných metodách mohla být maska
i adresář. Třeba ve findFiles()
:
Finder::findFiles('tests/*.inc')->from('/foo'); // *.inc kdekoliv ve /foo/**/tests
Finder::findFiles('**/tests/*.inc')->from('/foo'); // ekvivalent předchozího
Finder::findFiles('./tests/*.inc')->from('/foo'); // *.inc jen ve /foo/tests
Maska v in()
a from()
:
Finder::findFiles('*.php')->in('/foo/*/vendor');
Finder::findFiles('*.php')->in('/foo/*/vendor/**'); // totéž jako from('/foo/*/vendor')
Finder::findFiles('*.php')->from('/foo/**/vendor'); // najde i /foo/sub1/sub2/vendor/sub3/file.php
Vlastně by klidně mohlo jít zapsat i stručné:
Finder::findFiles('/foo/**/*.php');
A nakonec masky a adresáře ve vyloučení:
Finder::findFiles('*.php')->from('/foo')->exclude('tests/*.inc'); // vynechá *.inc v tests/
Finder::findFiles('*.php')->from('/foo')->exclude('**/tests/*.inc'); // ekvivalent předchozího
Finder::findFiles('*.php')->from('/foo')->exclude('./tests/*.inc'); // vynechá *.inc jen ve /foo/tests/
Finder::findFiles('*.php')->from('/foo')->exclude('bar/'); // vynechá jen adresáře bar/ při procházení
FileInfo
Vrácené soubory budou objekty Nette\Utils\FileInfo
, což je
potomek původního SplFileInfo
, ale přidává důležité metody
getRelativePath()
a getRelativePathname()
, které mi
vždycky chyběly. Přidám asi i read
a write
pro
přečtení/zápis obsahu souboru.
Další věci
Metody pro přidání cest a masek půjde volat vícekrát. Protože nejde
volat vícekrát statickou metodu jako např. findFiles()
, přidám
metody files()
a directories()
:
(new Finder)->files('*.php')->files('*.inc')->in('/foo')->from('/bar');
Také by bylo možné říct, že chci hledat soubory dle určité masky v jednom adresáři a dle jiné masky v jiném adresáři. Mohlo by to vypadat nějak takto:
($finder = new Finder)
->files('*.php')->in('/foo')
->append()
->files('*.inc')->from('/bar');
Do výsledku je tak možné přidat třeba jeden soubor navíc:
$finder = Finder::findFiles('*.php')->from('/foo')
->append(__FILE__);
Dále lze přeskakovat adresáře, které nelze číst pomocí
$finder->ignoreUnreadableDirs()
(uvažuju, že by to mohlo být
default) a třídit adresáře a v nich soubory pomocí
$finder->sortByName()
.
Máte k tomu nějaké nápady nebo něco dalšího vám u Finderu chybí?
- paranoiq
- Člen | 392
ahoj.
na co jsem narazil já – když jsem nedávno psal jeden nástroj a
potřeboval použít nějaký finder, sáhl jsem napřed po Nette Finderu a pak
po Symfomy Finderu. ani jeden neměl všechny fičůry, které jsem potřeboval,
takže jsem nakonec napsal obálku nad SF (https://github.com/…leFinder.php)
za mě nejdůležitější fičůra by byla přidat samostatně konfigurovatelný baseDir, abych mohl adresáře i soubory zadávat relativně k němu
pak prohledávání adresáře bez rekurze (což možná řeší ty hvězdičky?)
pak filtrování podle hashbangu nebo mime-magic u souborů bez přípon
- Felix
- Nette Core | 1245
Osobne by se mi hodilo napriklad mazani podle nejakych pravidel. Nebo obecne volani nejakeho callbacku.
Finder::findFiles('*.log')
->from('/srv/logs')
->exclude('.gitignore')
->delete()
Finder::findFiles('*.log')
->from('/srv/logs')
->exclude('.gitignore')
->callback(Finder::delete)
- David Grudl
- Nette Core | 8227
za mě nejdůležitější fičůra by byla přidat samostatně konfigurovatelný baseDir, abych mohl adresáře i soubory zadávat relativně k němu
Tohle mělo fungovat už dříve, tj
Finder::findFiles('relative/path/*.php')->in($baseDir)
. Nebo jsi
to myslel jinak?
pak prohledávání adresáře bez rekurze (což možná řeší ty hvězdičky?)
Tohle taky mělo fungovat už dříve, tj
Finder::findFiles('*.php')->in($dir)
. Rekurze
je from($dir)
pak filtrování podle hashbangu nebo mime-magic u souborů bez přípon
Tohle taky mělo fungovat už dříve :-), tj
Finder::findFiles('*.php')->filter($mimeFilter)->in($dir)
.
Teda s tím, že ten filter si napíšeš.
- David Grudl
- Nette Core | 8227
Felix napsal(a):
Osobne by se mi hodilo napriklad mazani podle nejakych pravidel. Nebo obecne volani nejakeho callbacku.
V podstatě na to lze taky použít filter(), asi něco jako
filter('unlink')
.
U filtrů mi vadí, že se chová jinak za findFiles() a jinak za in()/from(), což je záměr, ale ne úplně šťastnej.
- paranoiq
- Člen | 392
ad „Tohle mělo fungovat už dříve“ – když o tom tak přemýšlím znovu a lépe, asi byl problém spíš v tom, že jsem potřeboval prohledávat několik adresářů najednou (což teď řešíš :) krát mnoho přípon, takže tak jak to píšeš v té ukázce jsem to stejně bez nějaké obálky použít nemohl a bylo jednodušší to postavit nad SF finderem, než dělat několik dotazů Nette finderem a slučovat výsledky
ad „Tohle taky“ – asi platí to co výše. spíš jsem už zapomněl, že to jde : ]
ad „Tohle taky 2“ – jj. o obecném filtru vím
- Tomáš Jacík
- Člen | 147
Za mě super nápad, jen aby to bylo kompatibilní třeba s tím .gitignore, ať pak člověk netápe, proč mu něco nefunguje :)
- David Grudl
- Nette Core | 8227
Prosím o otestování nového Finderu (jak na to).
Migrační příručka
V předchozí verzi platilo, že metody exclude
a
filter()
fungovaly jinak, když byly zavolány
před from()
resp. in()
a
po ní. Tohle už neplatí, exclude()
a
filter()
fungují vždy stejně. Dřívější
filter()
volaný až po nahradila nová metoda
descentFilter()
.
Finder již neimplementuje rozhraní Countable.
Na Linuxu se nově chová v režimu case-sensitive.
Finder::findFiles()
(nebo find()
a
findDirectories()
) volaný bez argumentů dříve vrátil všechny
soubory, teď vyhodí chybu Too few arguments.
Řetězec začínající lomítkem ve Finder::findFiles('/f*')
se nově považuje za absolutní cestu, je potřeba ho nahradit např. za
Finder::findFiles('./f*')
.