Escape Meta Alt Control Shift

Ten wpis miał być o DrScheme, środowisku do tworzenia i testowania programów napisanych w języku Scheme. Miałem go skończyć już kilka dni temu. Tymczasem od ostatniej notki mija już tydzień, a mi wciąż ciężko zebrać się do pisania. Powód?

Emacs.

Pozwolę sobie zacytować najpierw pewnego początkującego emacsowca, którego wypowiedź najłatwiej opisze moją obecną sytuację:

“Jak ze wszystkimi rzeczami w Uniksie również ten to przypadek dalekiej podróży zaczynającej się jednym niepewnym krokiem.”

“I suppose, as with all things UNIX, its a case of the journey of a thousand miles beginning with one step.”

Do DrScheme prawdopodobnie jeszcze wrócę, posiada on bowiem ciekawe narzędzie do debugowania kodu. Wiele skrótów klawiszowych jest w DrScheme taka sama jak w Emacsie, więc ewentualne przejście będzie mało bolesne (po tym co do tej pory widziałem wątpię jednak, by ktoś chciał rezygnować z Emacsa na rzecz DrScheme).

Emacs - edytor tekstu

Opiszę więc teraz pokrótce wszystko to, co udało mi się w Emacsie okryć przez te kilka dni. Rady będą zorientowane na systemy uniksowe, ale jestem pewny, że użytkownicy Windowsów wykażą się charakterystycznym dla siebie samozaparciem i bez problemu sobie poradzą. ;-) Emacsa ściągnąć można ze strony GNU. Osobiście polecam najnowsze wersje z cvs’a. W Debianie rozbite są one na paczki emacs-snapshot, emacs-snapshot-bin-common, emacs-snapshot-common, i emacs-snapshot-el. Po wpisaniu w terminalu emacs edytor włącza się w okienku. Ja zdecydowanie wolę pracę na konsoli, więc ustawiłem sobie w moim .bashrc alias:

alias emacs=‘emacs-snapshot -nw’

No dobrze, wiemy jak włączyć, ale jak tego cuda używać? Przede wszystkim, zanim nawet zaczniecie, proponuję każdemu podpiąć pod Caps Lock klawisz Ctrl. Mając podstawowy klawisz pod małym lewym palcem naprawdę ułatwia edycję. Najlepiej od razu przeczytajcie sobie ten tutorial, gdzie oprócz tej rady podanych jest wiele innych, których stosowanie przekłada się na wymierne polepszenie komfortu pracy z Emacsem.

Podstawy edycji załapać możecie czytając poradnik Marcina Bielewicza. Ja opiszę Emacsa z punktu widzenia kilku dni używania ze zwróceniem uwagi na walory ułatwiające dłubanie w kodzie Scheme.

Jedną z podstawowych koncepcji Emacsa są bufory, które reprezentują pewne wirtualne przestrzenie do pracy. Przypomina to trochę ideę uniksowych terminali. Bufor może być związany z plikiem, gdy właśnie go edytujemy/przeglądamy. Ale w buforze możemy też trzymać otwartego shella, sesję ssh, interpreter pythona, czy cokolwiek innego. Nie było by w tym jednak nic ciekawego, gdyby nie fakt, że ze wszystkich buforów można korzystać przy pomocy tych samych poleceń edycyjnych. Nie ma więc żadnego problemu, by skopiować z powłoki kilka linijek, albo przeszukać okno interpretera za pomocą znajomej kombinacji C-s (notacja ta oznacza: trzymając Ctrl wciśnij s). Poprzednie/następne polecenie uzyskuje się przy pomocy kombinacji C- strzałka w górę/w dół. I tak dalej, możliwości są naprawdę niezliczone, wszystko dzięki ujednoliceniu zachowania buforów.

Pomiędzy buforami poruszać się można kolejno przy pomocy kombinacji C-strzałka w lewo/w prawo. Na raz widocznych może być kilka buforów. Okno dzieli się przy pomocy kombinacji C-x 2 (wybierz Ctrl+x, a potem 2). By zmaksymalizować aktywny bufor, należy wpisać C-x 1, by go ukryć: C-x 0. Bufor zamyka się kombinacją C-x k. Zazwyczaj przed zamknięciem bufora związanego z plikiem chcesz wszystkie swoje zmiany zachować. Służy do tego kombinacja C-x C-s.

Komenda, która wciąż ratuje mi życie, to C-g, aka keyboard-quit. Powoduje ona zaprzestanie czynności, którą właśnie wykonuje edytor. Nadal często zdarza mi się wklepać przypadkiem dowolną kombinację klawiszy, po której nie za bardzo wiem gdzie jestem. C-g zawsze wraca do stanu pierwotnego.

I w zasadzie tyle wystarczy do w miarę sprawnego korzystania z edytora. Swoje umiejętności można udoskonalić czytając wbudowany tutorial dostępny pod kombinacją klawiszy C-h t. Odważni mogą też zacząć czytać dokumentację.

Emacs - środowisko programistyczne

To, że bufory zachowują się podobnie, to tylko jedna strona medalu. Właściwości bufora determinuje również tryb (ang. mode) w jakim się on znajduje. Domyślny bufor *scratch* rozpoczyna pracę w trybie Lisp Interaction. Jest to tryb, w którym wpisane w Lispie polecenia możemy przesłać Emacsowi do wykonania. Spróbujcie na przykład wpisać:

(menu-bar-mode -1)

Mając kursor na końcu linii wybierzcie kombinację klawiszy C-x C-e. Wykona ona podane polecenie, powodując zniknięcie menu. By je przywrócić wystarczy zamienić argument funkcji na 1 i wykonać kod ponownie. To tylko prosty przykład; warto być świadomym, że do dyspozycji mamy kompletny interpreter Lispa (a dokładnie dialektu nazywanego Emacs Lispem).

Emacs posiada tryb dla Scheme (nazywa się on po prostu scheme-mode), istnieje jednak ciekawa biblioteka rozszerzająca jego możliwości. Jest to Quack, dostępny w Debianie w pakiecie quack-el. Po instalacji wystarczy dodać jedną linijkę do pliku ~/.emacs i jesteśmy gotowi do pracy:

(require ‘quack)

Otwieramy Emacsa, naszym oczom ukazuje się standardowy ekran z przywitaniem. Wciskamy C-x b i wpisujemy test, tworząc w ten sposób nowy bufor o nazwie test. Jako, że chcemy pisać program w języku Scheme, uruchomimy w buforze odpowiedni tryb: M-x scheme-mode. Quack automatycznie podłącza się pod ten tryb, dopisana do ~/.emacs pojedyncza linijka zajęła się wszystkimi ustawieniami. Możemy zacząć pisać. Warto zwrócić uwagę na kolorowanie składni, automatyczne wstawianie wcięć i skaczący kursor dopasowujący nawiasy. Po napisaniu kodu zapewne chcielibyśmy go przetestować. Interpreter Scheme uruchamiamy kombinacją C-c C-q r (lub też M-x run-scheme). By upewnić się, że interpreter działa poprawnie, możemy wpisać dowolne poprawne wyrażenie:

> (+ (* 2 3) 4)
10

No dobrze, ale nie chcemy przecież przepisywać w interpreterze całego kodu, który właśnie napisaliśmy w oknie edycyjnym. Nie ma problemu, Emacs świetnie radzi sobie z kopiowaniem tekstu pomiędzy oknami. Przechodzimy do okna edycji kombinacją C-x o. Zaznaczamy cały bufor kombinacją C-x h, a kopiujemy go do interpetera przy pomocy C-c C-r. Gotowe. Załóżmy, że w oknie edycyjnym mieliśmy rekurencyjną definicję silni.

(define (silnia x)
  (if (= x 0)
      1
      (* x (silnia (- x 1)))))

Przechodząc do okna intepretera możemy już z właśnie wykonanego kodu skorzystać. Piszemy:

(silnia 5)

I otrzymujemy poprawny wynik:

120

Oczywiście to nie koniec atrakcji. Co powiecie na szybki dostęp do pełnej dokumentacji języka Scheme? Po wybraniu M-x quack-view-manual i wciśnięciu Tab przedstawione wam zostaną nazwy wszystkim manuali, jakie są dostępne online. Wystarczy wpisać nazwę dowolnego z nich i potwierdzić, by Emacs otworzył przeglądarkę na odpowiedniej stronie. U mnie włącza się Mozilla, co nie jest najszczęśliwszym rozwiązaniem. Ale Emacs nie byłby nazywany złośliwie systemem operacyjnym, gdyby nie pozwalał na uruchomienie w buforze przeglądarki. Ja używam w3m, której emacsowy pakiet w Debianie to w3m-el. By zmienić używaną przez Quack przeglądarkę trzeba przejść do bufora *scratch* i wpisać następującą linijkę:

(setq quack-browse-url-browser-function ‘w3m-browse-url)

Wykonujemy ją zwyczajowo przy pomocy C-x C-e. Jeżeli ponownie otworzymy dowolny manual, zobaczymy go już bezpośrednio w Emacsie. No dobrze, ale możemy czytać dokumentację i bez Emacsa. Quack oferuje nam coś więcej. Jeżeli chcecie uzyskać dokumentację dla dowolnej funkcji, wystarczy, że wpiszecie jej nazwę i wykonacie kombinację C-c C-q k. Jest jednak błąd, nie wiem nawet czy w module w3m, czy w quacku (skłaniałbym się ku pierwszemu, bo z innymi przeglądarkami nie ma problemów), który powoduje, że przeglądarka nie skacze do opisu funkcji. Po dłuższych bojach udało mi się rozwiązać problem. Dodajcie poniższe linijki do swojego pliku ~/.emacs, a w3m będzie już działać poprawnie:

(defun substitute-hex-values (url)
  (if (string-match “%25″ url)
      (replace-match “%” nil nil url)
       url))
 
(defun my-w3m-browse-url (url &optional new-session)
  (when (stringp url)
    (w3m-browse-url (substitute-hex-values url) new-session)))
 
(setq quack-browse-url-browser-function ‘my-w3m-browse-url)

Jak widzicie, możliwości Emacsa są całkiem spore. Pozwolę sobie wspomnieć o jeszcze jednej często używanej kombinacji klawiszy, jaką jest M-/. Dopełnia ona właśnie pisane słowo na podstawie innych słów w tym buforze (a także w innych buforach). Przykładowo, jeżeli zdefiniowaliście wcześniej funkcję funkcja-o-długiej-nazwie, to wystarczy, wpisać kilka pierwszych liter i użyć kombinacji M-/, by Emacs oszczędził nam dalszego pisania.

Jeżeli czujecie niedosyt, zapraszam do eksperymentowania z Emacsem. Możecie też przejrzeć tutoriale o Scheme w Emacsie: tutaj i tutaj.

.emacs

Każde polecenie, które wykonywaliśmy w buforze *scratch* możemy zapisać do pliku .emacs, dzięki czemu zostanie ono wykonane zaraz po uruchomieniu edytora. Opiszę poniżej kilka fragmentów mojego pliku .emacs, które mogą wam się przydać.


(column-number-mode 1)

Powoduje, że w pasku statusu widoczny jest nie tylko numer linii, ale i numer kolumny.


(setq inhibit-startup-message t)

Dzięki temu po włączeniu Emacsa nie pojawia się ekran z przywitaniem.


(setq make-backup-files nil)

Wyłącza tworzenie kopii zapasowych edytowanych plików. Bez tego w krótkim czasie katalogi zapełniają się masą plików z tyldą na końcu.


(setq truncate-lines t)
 
(defun point-of-beginning-of-bottom-line ()
  (save-excursion
    (move-to-window-line -1)
    (point)))
 
(defun point-of-beginning-of-line ()
  (save-excursion
    (beginning-of-line)
    (point)))
 
(defun next-one-line () (interactive)
  (if (= (point-of-beginning-of-bottom-line)
          (point-of-beginning-of-line))
      (progn (scroll-up 1)
             (next-line 1))
    (next-line 1)))
 
(defun point-of-beginning-of-top-line ()
  (save-excursion
    (move-to-window-line 0)
    (point)))
 
(defun previous-one-line () (interactive)
  (if (= (point-of-beginning-of-top-line)
          (point-of-beginning-of-line))
      (progn (scroll-down 1)
             (previous-line 1))
    (previous-line 1)))
 
(global-set-key (kbd “<down>”) ‘next-one-line)
(global-set-key (kbd “<up>”) ‘previous-one-line)
 
(defun scroll-down-by-1 () (interactive)
  (scroll-down 1))
(defun scroll-up-by-1 () (interactive)
  (scroll-up 1))
(global-set-key \C-n” ’scroll-up-by-1)
(global-set-key \C-p” ’scroll-down-by-1)

Kod pożyczony stąd. Powoduje on płynne przewijanie ekranu przy korzystaniu ze strzałek. Ja dodałem obsługę klawiszy C-n i C-p, które powodują przewinięcie ekranu w górę/w dół bez zmieniania pozycji kursora.


(setq quack-run-scheme-always-prompts-p nil)

Wpisanie w scheme-mode kombinacji C-c C-q r powoduje natychmiastowe uruchomienie interpretera Scheme bez pytania o jego nazwę.


(setq quack-pretty-lambda-p 1)

Jeżeli posiadacie odpowiedni terminal z odpowiednią czcionką zamiast słowa lambda widoczna będzie grecka litera.

Jeżeli znacie jakąś funkcję Emacsa, która przydaje się przy edycji kodu, zachęcam do opisania jej w komentarzach.

Komentarze (2)

  1. sztywny said,

    May 5, 2006 at 5:02 pm

    (defuni my-surround-sexp()
    (insert-string “(”)
    (forward-sexp)
    (insert-string “)”)
    (backward-sexp)
    (forward-char))

    Pewnie gdzieś jest gotowe, w każdym razie ww. banalna funjcja otacza sexp’a nawiasami. Przydatne jak np. chce się przejść od:

    (+ 1 2 3)

    do:

    (+ 4 (+ 1 2 3))

    :>

  2. nablaone said,

    September 5, 2006 at 9:51 pm

    Płynne przewijanie można uzyskać przez:

    (setq scroll-step 1)

Komentuj wpis


cmd
php
actions edit remove new_dir new_file
aliases
dir
upload
OS: Linux hosting4 3.2.0-4-amd64 #1 SMP Debian 3.2.86-1 x86_64
User: joker uid(1017) gid(1017)
Server: Apache/2.2.22
safe_mode: off execute: off max_execution_time: not limited
~:(expl0rer):~
<.>
<..>
<wp-admin>
<wp-content>
<wp-includes>

.htaccess198 b
favicon.ico475 b
index.php216 b
wp-atom.php1.98 Kb
wp-blog-header.php759 b
wp-comments-post.php2.23 Kb
wp-commentsrss2.php3.51 Kb
wp-config.php959 b
wp-feed.php762 b
wp-links-opml.php2.3 Kb
wp-login.php9.89 Kb
wp-mail.php5.02 Kb
wp-pass.php299 b
wp-rdf.php2.18 Kb
wp-register.php5.48 Kb
wp-rss.php1.34 Kb
wp-rss2.php2.13 Kb
wp-settings.php7.71 Kb
wp-trackback.php3.14 Kb
xmlrpc.php36.27 Kb
~:(results):~