piątek, 27 sierpnia 2010

Kolorowanie składni Javy w systemie LaTeX

Dzisiaj opiszę trochę o środowisku lstlisting w systemie składu tekstu LaTeX. Czemu chcę o tym napisać? Ponieważ ten temat do mnie co chwile wraca. Nie wystarcza mi raz skonfigurowane i użyte środowisko, tylko co jakiś czas musze coś w nim zmodyfikować i wykorzystać gdzieś indziej. Innymi słowy chciałbym sobie zrobić małą ściągawkę na blogu, dotyczącą tego pakietu, bo ciągłe przeszukiwanie dokumentacji - co znaczą poszczególne opcje - zaczęło mnie już irytować.

Chcąc ładnie wyświetlić kod w naszym dokumencie, składanym przy użyciu systemu LaTeX, musimy dołączyć w preambule pakiet listings. Najczęściej zaraz pod nim następuje konfiguracja pakietu:



Następnie będzie można już korzystać z prostego otoczenia do wstawiania kodu:



W nawiasach kwadratowych można przedefiniować niektóre ustawienia dostępne w lstset, dodać etykietę i treść podpisu. Zmiany te będą aktywne dla danego listingu kodu.

Odmiennym sposobem wstawienia kodu może być dołączenie go bezpośrednio z pliku zewnętrznego:



I tutaj w nawiasach kwadratowych można przedefiniować odpowiednie parametry.

Poniżej najważniejsze i najciekawsze parametry lstset:

language - Wybór języka programowania z którego korzystamy. W przypadku Javy mamy dostępny dialekt AspectJ, który możemy użyć następująco: language=[AspectJ]Java.
basicstyle - Ogólny styl kodu, np. \footnotesize \small \scriptsize itp. Gdzieś wyczytałem / usłyszałem, że kod powinien być trochę mniejszą czcionką pisany od reszty tekstu.
aboveskip - Odstęp nad kodem.
belowskip - Odstęp pod kodem.
showspaces - Wyświetlanie znaku spacji (jako pokreślenie). Domyślnie wyłączone.
showstringspaces - Wyświetlanie znaku spacji (jako pokreślenie) ale w tekstach (Stringach). Domyślnie włączone, więc warto ustawić na false.
showtabs - Wyświetlanie znaku pokreślenia w miejscach występowania tabulatora.
tab - Możemy zdefiniować, co będzie wyświetlane jako znak tabulacji. Wymaga showtabs=true.
prebreak - Wyświetlanie znaku na końcu linii tekstu, która musi być złamana.
postbreak - Wyświetlanie znaku na początku linii, która została złamana.
breakindent - Wielkość wcięcia złamanej linii.
frame - Ramka dookoła listingu. Możliwe wartości: none, leftline, topline, bottomline, lines(linia na dole i górze) , single (pojedyncza ramka), shadowbox (ramka z cieniem).
identifierstyle - Styl identyfikatorów (zmiennych).
commentstyle - Styl komentarzy.
stringstyle - Styl napisów.
keywordstyle - Styl słów kluczowych.
numbers - Położenie numerów linii. Możliwe wartości: none, left, right.
stepnumber - O ile linijek ma się wyświetlać numer linii. Domyślnie 1.
numberstyle - Styl numerków.
numberblanklines - Jeśli false to puste linie nie mają numerków, domyślnie true.
numbersep - Odległość między numerem a listingiem.
captionpos - Pozycja podpisu listingu. Możliwe wartości t (top) i/lub (bottom).
gobble - Liczba początkowych znaków w kodzie, która ma być ignorowana. Tzn. jak wklejamy kod, który zawsze się zaczyna od dwóch spacji, to możemy je, za pomocą tego parametru, zignorować
escapeinside - Definiuje znaki pomiędzy którymi, można wstawić dodatkowy komentarz wewnątrz kodu. Użyte w ten sposób: escapeinside="" powodowało mi kiedyś, że nie chciał odpowiednio cudzysłowów wyświetlać.

Czasami użycie niektórych parametrów może wymagać dołączenia dodatkowych pakietów przed definicją.

Poniżej zamieszczam przykładowy kod który będę próbował ładnie wyświetlić:



Dobra teraz pokażę kilka konkretnych przykładów zastosowania tego co dotychczas opisałem. Na początek ustawienia zaproponowane przez mojego przyjaciela Tomka:



A oto efekt:

No kod został bardzo ładnie pomalowany. Wszystkie słowa kluczowe zostały ładnie wyłapane i pomalowane na niebiesko. Komentarze również zostały ładnie wyróżnione niezależnie od tego w jaki sposób zostały zadeklarowane. Podpis rysunku uzyskano przy pomocy dodatkowego parametru dla danego listingu:



Jakby się przyjrzeć bardziej temu listingowi to można jednak zobaczyć mały mankament. Otóż długa linijka tekstu została automatycznie złamana przez system składu. Spowodowało to jednak to, że obramowanie pomiędzy liniami 11 a 12 zmieniło kolor na kolor tekstu. Nie wiem czym to jest dokładniej spowodowane, ale podejrzewam komendę \raisebox użytą przy prebreak. Jak ktoś wie skąd to się bierze, to chętnie poznam rozwiązanie. Niby można wyłączyć łamanie linii za pomocą breaklines=false ale to spowoduje, że tekst wyjdzie po za obszar ramki.

Jak dla mnie ustawienia te nie są idealne. W swojej pracy magisterskiej zrezygnuję z ramki i kolorów. Dlaczego? Gdyż będę musiał wtedy część stron wydrukować na kolorowej drukarce a takiej nie posiadam. Może to spowodować, że marginesy stron pochodzących z różnych źródeł, nie będą dokładnie do siebie pasowały (z powodu innych obszarów drukowania w różnych drukarkach). Dlatego wolę uniknąć kolorowych stron w swojej pracy.

Poniżej zamieszczam mój zestaw ustawień:



Dają one następujący efekt:


Już nie wygląda tak ładnie, ale nie jest też tragicznie. Można się dziwić czemu nie wyrzuciłem z kodu definicji keywordstyle, commentstyle i stringstyle tylko ustawiłem w nich kolor na czarny? A no po to, aby krój czcionki mi się nie zmienił :)

Dobra teraz chciałbym pokazać takie ustawienia, aby składnia kodu wyglądała tak jak w NetBeans’ie:



Efekt poniżej:

Nie jest to do końca tak jak bym sobie tego życzył. NetBeans dodatkowo nazwę klasy i metody testSetId wyświetla czcionką pogrubioną. A metoda assertEquals jest czcionką pochyloną pisana, ze względu że jest to metoda statyczna. Szukałem sposobu w jaki to zrobić, ale lstlisting po za słowami kluczowymi, komentarzami i string’ami nic więcej nie rozróżnia…

Ale można, jakby dodefiniować nowe słowa kluczowe i zastosować dla nich oddzielny styl. Z tym że jeśli chodzi o nazwy klas i metod, to warto te ustawienia jednorazowo dla konkretnego listingu stosować. Przykład poniżej:



Efekt poniżej:


Uff udało się. Nazwa klasy i metody są już pisane pogrubioną czcionką. Również metoda assertEquals zaczęła być wyświetlana kursywą. A co ja takiego zrobiłem? Najpierw zdefiniowałem nowy classoffset o numerze 1. Następnie zdecydowałem jakie słowa kluczowe należą do tego zestawu (morekeywords) i jak mają wyglądać (keywordstyle). Następnie czynność powtórzyłem dla assertEquals nadając jej inny styl. Może da się to jakoś bardziej uniwersalnie zrobić, ale tego już nie wiem.

Na koniec podam jeszcze kilka ciekawych sztuczek. Gdybyśmy chcieli zmienić numerowanie linii musimy przedefiniować polecenie \thelstnumber. Np. chcąc wyświetlać dwukropek po numerze linii musimy po definicji \lstset dodać poniższą linijkę:



Chcąc zrobić np. na końcu dokumentu spis wszystkich listingów użytych w dokumencie wystarczy wydać komendę:



Aby zmienić nagłówek dodawany przez to polecenie piszemy w preambule:



Chcąc zmienić nazwę Listing dokładaną do każdego listingu możemy zastosować nastepującą instrukcję w preambule:



I jeszcze numerowanie listingów. Chcąc je numerować według numeru rozdziału i numeru który to rysunek w danym rozdziale piszemy (najlepiej w jednej linijce):



Definicję tę umieszczamy za \begin{document}! Dodatkowo trzeba przedefiniować section (w premabule):



Co ciekawsze jak kilka razy w ramach \lstset zdefiniujemy pewne wartości to zostaną wybrane te położone dalej. Dlatego czasem jak nam nie chcą działać pewne zmiany to sprawdźmy czy nie mamy duplikatów. Ja trochę czasu w ten sposób straciłem.

Ponadto trzeba kolejne ustawienia wartości rozdzielać przecinkiem (nie stawiamy go po ostatnim parametrze). Inaczej nie wszystkie parametry zostaną dobrze skwalifikowane. Podobnie możemy mieć ustawione parametry które nie istnieją, a kod i tak się będzie kompilował :)

I jeszcze uwaga jeśli chodzi o umieszczanie listingów kodu na prezentacjach z użyciem pakietu beamer. Musimy zezwolić na „złamanie” slajdu, gdyby kod się nie zmieścił na jednym. Inaczej dostaniemy błąd: Paragraph ended before \lst@next was complete. Pozbywamy się tego za pomocą:



Powinniśmy jednak unikać kilkustronicowych listingów kodu na slajdach prezentacji, gdyż nie należy to do sztuki tworzenia dobrych prezentacji. Zmniejszenie czcionki kodu może zwiększyć liczbę kodu jaki możemy przedstawić, ale stanie się on mniej czytelny. Zresztą komu chce się analizować kilkustronicowy kod na prezentacjach?

Użycie allowframebreaks powoduje jednak, że w górnej części slajdu w tytule będzie na końcu wyświetlana cyfra rzymska mówiąca który to slajd z kodem. Nawet jak będziemy tworzyć jednoslajdowe listingi to i tak otrzymamy brzydką jedynkę rzymską w tytule. Aby się tego pozbyć należy w preambule dokumentu dodać linijkę:



Od teraz już nasze listingi kodu, czy to w dokumentach, czy w prezentacjach będą wyglądać profesjonalnie:)

2 komentarze: