Emacs pro mírně pokročilé (2): Programování v Emacsu, módy a odsazování

18. 4. 2001
Doba čtení: 6 minut

Sdílet

Každý programátor, který někdy pracoval na libovolném týmovém projektu se musel podřídit nějakým pravidlům. Jak pojmenovávat identifikátory, jak dělit kód do částí, ale také například jak upravovat (odsazovat) samotný kód programu. Jak si s tím poradit v Emacsu se podíváme v dnešní části.

Naše povídání o Emacsu bude pokračovat sérií článků věnujících se programování. Většina částí bude obecných a snad přínosných i pro neprogramátory využívající tento editor, ovšem nutno říci, že na své si přijdou zejména programátoři. Dnešní díl, pojednávající o módech a formátování textu, snad ale najde své čtenáře i mimo tuto skupinu.

Jak bylo řečeno v úvodu, každá práce v týmu s sebou přináší jistá omezení. Pracujeme-li zároveň na několika projektech je vysoce pravděpodobné, že pravidla pro psaní kódu se budou v každém z nich lišit. Může to býti dáno zvoleným programovacím jazykem, ale také dříve zavedenými konvencemi (není snad třeba dlouze vysvětlovat, jak „čitelný“ je kód projektu, kde každý ze zúčastněných jinak formátoval své příspěvky). Jak se s tímto rozlišováním nejlépe vypořádat v prostředí Emacsu a jak si co nejvíce usnadnit život?

Pokročilejším uživatelům Emacsu netřeba představovat tzv. módy, ani to, že se v tomto editoru rozlišují jejich dva druhy: hlavní (major) a vedlejší (minor). Pro většinu rozšířených programovacích jazyků, ale i nástrojů pro formátování textu existuje pro Emacs příslušný hlavní mód, resp. lze pro zvolený jazyk použít některý z existujících módů. Výběr konkrétního módu pro daný typ souboru lze (kromě explicitního zadání pro aktuální buffer pomocí M-x) ponechat na editoru a to dvojím způsobem:

Obsahem proměnné auto-mode-alist
Tato proměnná obsahuje seznam dvojic, kde na prvním místě je maska jména souboru a na druhém příslušný hlavní mód. Tedy například konstrukcí (setq auto-mode-alist (cons '("\\.ll$" . c++-mode) auto-mode-alist)), kterou lze přidat do konfiguračního souboru, rozšíříme tuto proměnnou o dvojici masky souborů končících příponou ‚.ll‘ (což může být například zdrojový soubor pro flex), a módem pro c++. Tento mód se nyní tedy zapne pokaždé, když otevřeme soubor s vybranou příponou.
Zapsáním přímo do zdrojového kódu
Pokud na první neprázdný řádek kódu (pro úplnost poznamenejme, že pro zdrojové kódy skriptovacích jazyků začínajících sekvencí #! na druhý řádek) zapíšeme -*- MODENAME;-*-, kde MODENAME je zvolený hlavní mód, zapne Emacs tento mód i bez ohledu na obsah proměnné auto-mode-alist. Tato konstrukce je dokonce mnohem silnější a přináší s sebou možnost měnit přímo i chování vybraného módu. Pokud bychom nechtěli v předchozím příkladě měnit chování Emacsu pro všechny zdrojové soubory flexu, ale pouze pro jeden konkrétní přidali bychom na první řádek například  /* -*- c++ -*- */.

Zapnutím zvoleného módu uvádíme zároveň v činnost tzv. mode hook, což není nic jiného než lispovká proměnná, obsahující seznam funkcí, které se mají volat v předem definovaném případě. Příslušný hook je pojmenován podle hlavního módu (přidáním jména módu, jako předpony ke koncovce -hook). Většina módů pro programovací jazyky nemá standardně v této proměnné „nahozené“ žádné funkce. Zde se otevírá první možnost, jak ovlivňovat chování vybraného módu – stačí rozšířit tuto proměnnou o požadovaná volání. Přidávat volání funkcí lze nejlépe pomocí funkce add-hook. V podstatě lze přidat libovolnou lispovskou funkci, ovšem ne každá funkce je k tomuto účelu vhodná. Hovořit obecně o tom, jak je možné rozšířit tuto proměnnou by bylo nad rámec tohoto seriálu, podívejme se proto alespoň na ilustrační příklad, který ukazuje jeden ze způsobů, jak změnit odsazování kódu v módu jazyka C.


(setq my-c-style
        '((c-comment-only-line-offset . 4)
         (c-cleanup-list . (scope-operator
                   empty-defun-braces
                   defun-close-semi))
         (c-offsets-alist . ((arglist-close . c-lineup-arglist)
                (substatement-open . 0)))
         (c-toggle-auto-state t)))

     (add-hook 'c-mode-common-hook
       '(lambda ()
          (c-add-style "my-style" my-c-style t)))

V příkladu se nejprve do proměnné my-c-style přiřadí seznam proměnných ovlivňujících chování tohoto módu (jejichž přesný popis lze nalézt v manuálu). Pomocí add-hook poté přidáme jako funkci anonymní výraz lambda, a předefinujeme tak tyto proměnné v tomto módu. Stručně poznamenejme, že v uvedeném příkladu nastavujeme odsazení pro řádky obsahující pouze komentář na čtyři mezery; seznam konstrukcí, které se mají při použití auto-new-line „čistit“, tedy jistým způsobem upravovat; list obsahující odsazování pro pro konkrétní syntaktické konstrukce (viz níže); a konečně poslední konstrukce obsahující zapnutí tzv. automatického odsazování.

Odsazování

Každý mód pro programovací jazyk definuje celou řadu funkcí a proměnných ovlivňujících chování editoru. Nebudeme tedy popisovat nějaký konkrétní mód příliš dopodrobna, to by bylo skutečně příliš mnoho informací. Podívejme se ale trochu blíže na část, která ovlivňuje odsazování kódu, a která je navenek nejvíce viditelná. Nejvhodnější způsob, jak odsazovat zdrojový kód, je přenechat tuto činnost editoru přímo při vytváření kódu. V Emacsu existují příkazy k odsazování konkrétního řádku, celé skupiny řádků, či například bloku.

Odsazení aktuální řádky provedeme v Emacsu klávesou <TAB> (aktivujeme funkci MODE-indent-command, kde MODE je aktuální hlavní mód), kombinací C-j kromě odsazení aktuální řádky přejdeme na nový řádek (funkce newline-and-indent). Funkce k odsazování, která vkládá či maže tzv. bílé znaky na začátek řádky odsazuje na základě předchozích řádků (kontextu). Pokud se kurzor nachází někde uvnitř těchto bílých znaků na počátku řádku klávesa <TAB> ho posouvá na konec této „mezery“, v opačném případě s kurzorem nehýbe. Pokud chceme vložit znak tabelátoru, provedeme to např. pomocí kláves M-i. Jak odsazovat více řádek, region a podobně se lze dočíst v manuálu.

Ve stručnosti se podívejme, ještě na způsob, jak samotné odsazování funguje a jak jeho chování změnit. Omezíme se v tomto případě na mód pro jazyk C. Tento mód a stejně tak módy odvozené, používá k odsazování jednoduchý mechanismus: nejprve řádku syntakticky klasifikuje (podle obsahu a kontextu) a na základě této klasifikace určí odsazení, které lze měnit. Nebudeme rozebírat celý mechanismus příliš do hloubky (pokud to někoho zajímá, najde patřičné údaje v dokumentaci).

Rozlišíme však dvě zásadní možnosti, jak ovlivnit odsazení: s využitím tzv. odsazovacího stylu anebo změnu odsazování přímo jednotlivých syntaktických konstrukcí módu. Odsazovací styl lze zvolit jeden z předem definovaných nebo si napsat vlastní (jak jsme viděli v příkladu s hooky). Odsazovací styl pro aktuální buffer změníme pomocí funkce c-set-style, které jako argument předáme vybraný styl. Z předem definovaných máme k dispozici například styl k&r, gnu, linux a další. Pomocí kláves C-c C-o lze interaktivně měnit odsazování pro danou syntaktickou konstrukci (funkce c-set-offset, jíž lze pro změnu přidat do konfiguračního souboru). Odsazení jednotlivých konstrukcí se zadává pomocí tzv. offsetu, což může být celé číslo, funkce, jméno proměnné či jeden z následujících symbolů: +, -, ++, --, * nebo /, pracujících s proměnnou c-basic-offset. Tato proměnná charakterizuje základní odsazení, od kterého pak lze pomocí těchto symbolů přičítat, násobit, zkrátka aritmeticky měnit odsazení jednotlivých konstrukcí. Již jsme hovořili o prvním neprázdném řádku v souvislosti s výběrem módu. Na tomto místě lze také ovlivnit odsazování, neboť tato řádka dovoluje konstrukce typu: -*- mode: MODENAME; VAR: VALUE; ... -*-, kde lze přímo nastavovat obsah proměnných. Tedy například řádek -*- mode: c++; c-basic-offset: 2; -*- donutí Emacs nejen k výběru c++ módu pro daný buffer, ale zároveň nastaví základní osazení na dvě mezery. Tento typ předefinováni odsazení je nejsilnější a lze tak nejlépe zajistit zachování odsazování.

bitcoin školení listopad 24

Odsazování ovšem není jedinou funkcí hlavních módů pro programovací jazyky. Dalšími užitečnými vlastnostmi jsou snazší pohyb po bufferu apod.. Spousta zajímavých, užitečných a práci usnadňujících funkcí lze nalézt také v nepřeberném množství vedlejších módů. Módy, které skrývají a zase odkrývají těla funkcí a umožňují tak přehlednější pohled na kód ( outline-minor-mode), módy pro zvýrazňování syntaxe (tzv. syntax highlight, font-lock-mode) a další, mnohdy již ne zcela související s programováním. Na některé zajímavé se snad dostane v závěru tohoto seriálu.

Příště si povíme něco o kompilování, spouštění a ladění programů v prostředí editoru Emacs. Na své si tedy přijdou opět zejména programátoři. Ostatní se tím snad nenechají odradit.