Při programování velmi často prohledávám kód. Např. mám klávesovou zkratku na nalezení definice metody nebo naopak všech míst, ze kterých je volaná. Někdo k tomu používá IDE, řešení s vyhledáváním má výhodu, že je použitelné třeba i v případě, když jsou soubory uložené na vzdáleném serveru a IDE by se s jejich indexací po každé změně pěkně zapotilo. Kromě toho hledám i spoustu dalších věcí, kolikrát je třeba rychlejší vyhledat nějaký fragment textu ze stránky, než procházet adresáře k souboru, který ji generuje.
Ve Facebooku je repozitář tak velký, že i git grep používající index je nesnesitelně pomalý. Vznikla proto služba tbgs, která repozitář pravidelně indexuje do paměti několika serverů a hledá v nich distribuovaně.
Dobré nalezitelnosti jsem postupně začal přizpůsobovat i kód, který píšu. V první řadě je potřeba dodržovat štábní kulturu – pokud jednou napíšete funkci malými písmeny a podruhé velkými, tak musíte hledat bez rozlišování velikosti písmen a nejdete možná i to, co nechcete (třeba stejnojmennou konstantu). Pokud jednou napíšete závorku na stejný řádek a jednou na nový, tak to při hledání možná nezohledníte a najdete jen část toho, co hledáte. Stejné věci je dobré pojmenovávat stejně, různé různě. Např. pro CSS třídy používám jako oddělovač slov pomlčku, takže nekolidují s jinými identifikátory. Nalezitelnost přizpůsobuji i pojmenování metod – třeba místo obecného add
metodu raději pojmenuji addComment
, takže pak jdou snadno najít všechna místa, ze kterých je volaná.
Co ale dělat v případě, kdy hledáme něco složitějšího? Např. bychom chtěli najít všechny výskyty strncmp(A, B, strlen(B)) == 0
a změnit je na startsWith(A, B)
. Hračka, řeknete si – stačí hledat regulární výraz strncmp\(.*, strlen\(
a s tím už si nějak poradíme. Může nastat nepřeberné množství komplikací:
strlen()
může být odsazeno na další řádek.strlen()
se může nacházet až za strncmp()
.strlen()
naopak může být použito v dřívějším parametru.Pokud je v kódu jen pár výskytů, tak toho můžeme najít víc a probrat se tím ručně. Pokud ale chceme změnit stovky výskytů nebo chceme mít změnu reprodukovatelnou, tak bychom potřebovali nástroj, který kódu rozumí na vyšší úrovni.
Přesně takovým nástrojem je sgrep. Ten postaví syntaktický strom zdrojového kódu a dovoluje hledat v něm. Poradí si tím pádem se všemi nástrahami, které v kódu můžou být – nečekané bílé znaky, komentáře, vnořené výrazy, zkrátka cokoliv. Použití z příkazové řádky je velmi jednoduché:
sgrep -e 'strncmp(A, B, strlen(B)) == 0'
Pochopitelnou nevýhodou je pomalost – sgrep musí všechny soubory zparsovat. Je možné ho proto použít s normálním grepem – nejprve si nahrubo vyfiltrujeme všechny soubory, které hledaný výraz určitě obsahují (a možná i některé další) a ty potom dohledáme sgrepem.
Ještě mocnější nástroj je spatch. Ten soubory nejen prohledává, ale provádí v nich i změny. Změnu strncmp
na startsWith
lze provést tímto spatchem:
-strncmp +startsWith (A, B -, strlen(B)) == 0 +)
Sgrep a spatch nepoužívám moc často, ale když už je použiji, tak jsem za ně velmi vděčný, protože bez nich bych úkol řešil mnohem pracněji. Je proto dobré o nich minimálně vědět.
Diskuse je zrušena z důvodu spamu.