Emacs pro mírně pokročilé (5): Emacs a TAGy

9. 5. 2001
Doba čtení: 5 minut

Sdílet

Orientace ve zdrojových kódech programů sestávajících z mnoha souborů je často velmi náročná. Má-li se navíc programátor na tvorbě rozsáhlejších projektů efektivně podílet, nemůže trávit příliš mnoho času hledáním konkrétní funkce nebo části kódu. Pomoc v takovémto případě nabízí tzv. TAGy. Jak s nimi spolupracuje Emacs se dozvíme v dnešním pokračování.

Tabulka TAGů (tags table) je popis toho, jak je kód vícesouborového projektu rozložen do souborů. Obsahuje jména souborů a jména a pozice funkcí (nebo jiných pojmenovaných jednotek). Sjednocení těchto informací daného projektu do tabulky sebou přináší možnost vyhledávání či nahrazování ve všech zahrnutých souborech pomocí jediného příkazu. Díky tomu, že jsou v této tabulce zaznamenána jména funkcí, lze jedním příkazem otevřít příslušný soubor a navíc s kurzorem nastaveným na uložené pozici. Tyto tabulky se ukládají v souborech, které se nazývají „tags table files“ (obvykle jsou to soubory pojmenované TAGS). Každý záznam v této tabulce obsahuje jméno TAGu, jméno souboru, ve kterém je tento TAG definován, a pozici v tomto souboru. Jaké konkrétní záznamy jsou obsaženy v této tabulce závisí na programovacím jazyce zdrojových kódů, mohou zde být zaznamenány i jména globálních proměnných, datových typů apod..

Nejprve si řekneme, jak se tato tabulka vyrobí. Použijeme k tomu program etags, který je součástí balíku ctags, a je volně dostupný. Program zná syntaxi mnoha běžně používaných programovacích jazyků. Volbu jazyka, podobně jako mnoho dalších parametrů programu, lze zadat explicitně (v tomto případě pomocí volby ‚ --language=NAME‘). Kompletní popis programu lze nalézt v manuálu a je nad rámec tohoto článku. Pro první a jednoduchý příklad stačí pouze uvést za jméno programu seznam souborů, ze kterých chceme tabulku generovat, tedy například etags *.cc vytvoří tabulku pro všechny soubory s příponou cc v aktuálním adresáři.

Důležitou otázkou je, jak často je potřeba tyto tabulky obnovovat. Jestliže se pozice zaznamenaného TAGu změní pouze uvnitř souboru, Emacs stále tento TAG nalezne (zaplatíme za to ovšem poněkud menší rychlostí vyhledání). Tedy odpověď na otázku „jak často obnovovat?“ zní: vždy když přidáme novou funkci (či část kódu) a chceme, aby byla zahrnuta do této tabulky, nebo když přesuneme označenou funkci do jiného souboru. Struktura tabulek dovoluje zahrnovat či vkládat tabulky do sebe a umožňuje tak popisovat opravdu rozsáhlé projekty. Pokud předáme programu etags jména souborů s relativními cestami, lze pak tabulky s TAGy použít i po přesunutí celého adresáře jinam, spolu se zachováním funkčních odkazů. Chceme-li, aby program vytvořil tabulku z většího množství zdrojových souborů, můžeme pro to využít volby ‚ -‘ (pomlčka), kdy budou jména souborů čtena ze standardního vstupu, a spojit takto program s nějakých jiným pomocným nástrojem, jako je například find.

Máme-li již vytvořenou tabulku, můžeme si konečně ukázat, jak s ní pracovat v prostředí Emacsu. Emacs rozeznává tzv. „vybranou“ (selected) tabulku, na kterou se vztahují příkazy pro práci s tabulkou TAGů. Funkce visit-tags-table slouží k výběru tabulky (standardně nabízí Emacs jméno TAGS v aktuálním adresáři). Tato funkce uloží do proměnné tags-file-name jméno námi zvolené tabulky (nečte tabulku samotnou, dokud ji nechceme využít). Pokud je již nějaká tabulka v této proměnné obsažena, zeptá Emacs, zda chceme tuto tabulku rozšířit přidáním záznamů z nové tabulky, či zda ji chceme nahradit. Jestliže zvolíme přidání nové tabulky ke stávajícím záznamům, budou použity staré i nové záznamy. Prohledávání tabulky nezačíná vždy od první tabulky v seznamu, ale od tabulky obsahující záznamy k aktuálnímu souboru popořadě až do konce seznamu a poté dále opět od začátku. Nastavením obsahu proměnné tags-table-list lze přesně specifikovat pořadí tabulek.

Největším přínosem tabulek s TAGy je nalezení konkrétního odkazu. Slouží k tomu funkce find-tag (klávesová zkratka M-.), které je jako parametr předáno jméno TAGu. TAG se v tomto případě hledá ve všech tabulkách. V případě, že je TAG úspěšně nalezen, otevře Emacs příslušný soubor a posune kurzor na jeho pozici. Selže-li hledání, informuje nás o tom Emacs vypsáním zprávy „No tags containing NAME“. Pokud zadáme prázdný argument (stiskem klávesy <RET>) použije se jako parametr tzv. sexp (Emacs ho zobrazí ve stavové řádce v závorkách), což je jakási „uhodnutá“ hodnota. Příkazu M-. není potřeba zadávat celé jméno TAGu, protože se v tabulkách vyhledává TAG, který obsahuje podřetězec daného jména (preferovány jsou nicméně přesné shody). Pokračování v hledání TAGu stejného jména dosáhneme předřazením tzv. numerického argumentu ( C-u), tedy dohromady C-u M-.. V tomto případě není nutné zadat jméno TAGu, Emacs se pokusí nalézt následující TAG stejného jména. K pohybu zpět, na předešlé TAGy, použijeme opět numerický argument, kterému předáme znaménko ‚ -‘ (minus), tedy vcelku C-u - M-.. Návrat zpět do místa, odkud jsme začali TAG vyhledávat, je realizován funkcí pop-tag-mark (zkratka M- ). Tedy typicky použijeme M-. k nalezení nějaké části kódu, kterou si chceme prohlédnout a M- k návratu do místa, odkud jsme hledání spustili. Na milovníky regulárních výrazů pamatuje Emacs funkcí find-tag-regexp (zkratka C-M-.), která vyhledává TAGy podle zadaného regulárního výrazu (namísto podřetězce jako v případě find-tag). Výčet příkazů pro hledání TAGů není (jako obvykle) úplný, o dalších možnost, jak například zobrazovat nalezený TAG v jiném okně, se lze dočíst v manuálu.

Dalším způsobem hledání v tabulkách je vyhledávání ve všech souborech uvedených v tabulce. Pro tyto příkazy je z tabulky TAGů použita pouze informace o jménech souborů do ní zařazených. Funkce tags-search přečte v minibufferu regulární výraz, který chceme hledat a poté spustí vyhledávání ve všech souborech uvedených ve vybrané tabulce. Zobrazuje přitom jejich jména, takže lze sledovat průběh hledání. Jakmile je nalezena první shoda, prohledávání se přeruší. Pokračování hledání zadaného regulárního výrazu se spustí funkcí tags-loop-continue (zkratka  M-,).

Kromě samotného vyhledávání je k dispozici funkce tags-query-replace, která slouží k vyhledávání s náhradou. Funkce opět prohledává přes všechny soubory uvedené v tabulce a jinak pracuje stejně, jako obyčejná query-replace-regexp, tedy vzorky textu vyhovující zadanému regulárnímu výrazu postupně nahrazuje novým textem (vždy navíc tuto změnu nabídne a existuje tedy šance ji nepřijmout). Práce s funkcemi tags-search a tags-query-replace má velmi blízko k používání grepu, o kterém jsme již hovořili, ovšem s omezením pouze na soubory uvedené v tabulce TAGů.

ict ve školství 24

TAGy jsou tedy velmi silnou pomůckou. Poslední zajímavou informací, kterou se může chtít uživatel dozvědět, je seznam TAGů pro daný soubor. K tomuto účelu slouží funkce list-tags s jediným parametrem, kterým je jméno souboru, pro nějž chceme seznam zobrazit. Jméno souboru je třeba zadat v témže tvaru, v jakém se vyskytuje v tabulce TAGů. A dnes již skutečně poslední funkcí, o které se zde v souvislosti s TAGy zmíníme, je tags-apropos. Tato funkce nalezne všechny TAGy ve vybrané tabulce, které odpovídají zadanému regulárnímu výrazu, a zobrazí je. Pro úplnost dodejme, že formátování výstupu této funkce lze ovlivnit proměnnou tags-apropos-verbose, která, je-li různá od nil, způsobí, že se kromě jmen TAGů ve výpisu objeví i jména odpovídajících souborů.

Tímto dílem končí ryze programátorské odbočení. Počínaje příštím dílem se bude seriál již opět plně věnovat širokým a obsáhlým možnostem editoru. Už za týden se budeme věnovat stručnému seznámení se systémem gnus, tedy klientem pro čtení news či e-mailování, který se může již dlouhou dobu řadit mezi skutečnou špičku ve své kategorii.