Einführung in Emacs Lisp

Vorbemerkungen

Lisp ("List Processing") ist eine der ältesten heute noch verbreiteten Programmiersprachen. Konzipiert wurde die Sprache in den späten Fünfziger Jahren von John McCarthy. Die einzige heute noch ernsthaft genutzte Programmiersprache, die älter ist, ist FORTRAN. Über die Jahrzehnte entstanden viele Lisp-Dialekte. Am erfolgreichsten war das am MIT Anfang der Sechziger Jahre entwickelte MacLisp, von dem sich wiederum verschiedene Dialekte entspannen. Schließlich wurde von den Programmierern der verschiedenen MacLisp-Abarten zu Beginn der Achtziger Jahre ein Kommittee ins Leben gerufen, das die Standardisierung der Sprache zum Ziel hatte. Das Ergebnis bekam den Namen Common Lisp. 1994 wurde Common Lisp zur ersten ANSI-zertifizierten objektorientierten Sprache (durch CLOS, das Common Lisp Object System).

Neben Common Lisp, das in verschiedenen kommerziellen und freien Implementierungen zur Verfügung steht, gibt es weiterhin verschiedene Dialekte wie zum Beispiel Scheme, eine hauptsächlich in der akademischen Ausbildung genutzte Sprache, und nicht zuletzt Lisp als Skriptsprache für Applikationen wie AutoCAD oder Emacs.

Wer Lisp sagt, meint heute in der Regel ANSI Common Lisp. Common Lisp hat einen riesigen Sprachumfang und bietet dem Programmierer die größtmöglichen Freiheiten. Vielfach wird Lisp als die Lösung für das rapid prototyping, also das schnelle Entwerfen von Lösungen gepriesen, auch deshalb, weil in der Sprache viele Konstrukte bereits eingebaut sind, die man in anderen Sprachen erst mühsam selbst implementieren muß. Lisp eignet sich aber nicht nur dafür. Clisp, eine unter der GPL stehende Implementierung, kann sogar als Login-Shell benutzt werden und erzeugt Bytecode ähnlich wie Java, cmucl (Public Domain) kompiliert zu Maschinencode, der von der Geschwindigkeit her mit C mithalten kann. Einige kommerzielle Anbieter offerieren kostenlose Testversionen ihrer Entwicklungsumgebungen: Für Windows gibt es Corman Lisp, für Windows und Linux Xanalys Lispworks und Allegro Common Lisp. Die am besten unterstützte Plattform ist inzwischen Mac OS X, für das u. a. die kommerziellen Implementationen Lispworks und MCL und die freien OpenMCL, SBCL, CMUCL und CLISP erhältlich sind.

Wenn Lisp so toll ist, warum benutzt es dann heute keiner?

Also, zunächst mal stimmt das so gar nicht. Common Lisp wird auch heute durchaus ernsthaft benutzt, nicht zuletzt für Anwendungen, die in anderen Sprachen gar nicht machbar sind, ohne Lisp darin neu zu erfinden. Schön zusammengefaßt hat dies Philip Greenspun in seinem "10th Rule of Programming":

Any sufficiently-complicated C or Fortran program contains an ad-hoc, informally-specified bug-ridden slow implementation of half of Common Lisp.

Hinter Lisp steht kein großes Unternehmen wie Microsoft oder Sun mit seinen Marketingbrigaden, außerdem gibt es die Sprache schon ziemlich lang. Sie ist nicht neu, und was nicht neu ist, ist nicht cool. Um die Sprache zu lernen, muß man sich Zeit nehmen. Die Sprachspezifikation umfaßt gedruckt etwa 1000 Seiten.

Was Lisp darüberhinaus geschadet hat, war der sogenannte AI Winter gegen Ende der Achtziger Jahre. Lisp war eine der bevorzugten Sprachen für Anwendungen im Bereich der Künstlichen Intelligenz, von der man sich in den Achtzigern zu viel versprach. Als nach einigen Jahren die große Ernüchterung kam, wurde Lisp vielfach zusammen mit den Ideen der KI in den Eimer geworfen, obwohl die Sprache, in der das Unmögliche möglich gemacht werden sollte, am wenigsten dafür kann.

Lisp ist modern! Die gerade in den letzten Monaten wieder deutlich wachsende Community zeigt, daß immer mehr Leute Lisp für sich unvoreingenommen neu entdecken.

Konzepte

Grundlegende Konzepte in Common Lisp sind

Lisp ermöglicht es dem Programmierer, die Sprache zu erweitern und an seine Bedürfnisse anzupassen. Man kann in sehr kurzer Zeit eigene Sprachen in Lisp entwerfen, die für die anstehende Problemlösung maßgeschneidert sind, oder Programme schnell konzipieren, auf Praktikabilität prüfen und später auf Geschwindigkeit optimieren. Der dynamische Charakter von Lisp macht es zudem ideal als Erweiterungssprache für anspruchsvolle Anwendungen.

Emacs Lisp

Grundsätzliches

Emacs Lisp ist die Erweiterungssprache des Texteditors Emacs. Die Sprache orientiert sich an MacLisp und Common Lisp, wobei viele Features von Common Lisp fehlen, um Emacs Lisp einfacher und kleiner machen zu können. Die grundsätzliche Syntax ist die gleiche, aber beispielsweise der Geltungsbereich von Variablen unterscheidet sich deutlich.

Common-Lisp-Systeme verfügen über einen Top-Level, in dem ein REPL (read-eval-print-loop) auf Eingaben des Benutzers wartet. Dieser sieht in der Regel aus wie eine Shell und verhält sich oft auch ähnlich. Beim Emacs gibt es eine solche Shell auch; man erreicht sie über M-x ielm RET (der sogenannte Inferior Emacs Lisp Mode — Dank an Christoph für den Hinweis!). In der IELM-Shell kann man per (set-buffer "offene-datei.txt") auch noch einen Buffer wählen, auf dem sämtliche Editier-Kommandos ausgeführt werden. Oder man evaluiert Ausdrücke ohne Shell, einfach durch das Kommando C-x C-e hinter dem jeweiligen Ausdruck. Man muß dazu erwähnen, daß man sich im Emacs eigentlich ständig in einem REPL befindet, denn jeder Tastendruck wird evaluiert, und es ist möglich, jedem Tastendruck ein Ereignis zuzuweisen. Normalerweise führt ein Druck auf die Taste "d" dazu, daß ein "d" in den jeweiligen Buffer am Point (der Stelle, an der der Cursor steht) eingefügt wird. Im dired-Mode aber, mit dem man Verzeichnisse bearbeiten kann, führt ein Druck auf "d" dazu, daß die Datei an der Cursorposition als "löschbar" markiert wird. Ein anschließendes "x" im Buffer löscht die markierten Dateien nach Nachfrage.

Der *scratch*-Buffer eignet sich als Lisp-Lern-Buffer, weil er im Lisp-Interaction-Mode läuft. Man kann in ihm Lisp-Code schreiben und anschließend mit C-x C-e evaluieren. Das Ergebnis der Evaluierung wird im Minibuffer angezeigt.

Die einfachsten Lisp-Ausdrücke sind Zahlen. Zahlen evaluieren zu sich selbst.
Evaluierung der Zahl 1

Bekanntlich kann man Zahlen zusammenzählen und erhält damit eine neue Zahl. Dies geht auch in Lisp. Allerdings schreibt man in Lisp nicht 1 + 3 (sog. Infix-Notation), sondern man benutzt S-Expressions (das "S" steht dabei für "Symbolic" -- siehe unten -- oder auch für "Simple"). Eine S-Expression ist ein Ausdruck in runden Klammern. Der Operator kommt als erstes (Präfix-Notation), danach folgen die Argumente. Die Lisp-Version von 1 + 3 lautet also (+ 1 3).
Evaluierung von (+ 1 3)

Der Vorteil dieser Notation ist vielleicht bis jetzt noch nicht offensichtlich, aber gleich kommt's: Manchmal möchte man mehr als zwei Zahlen zusammenzählen, zum Beispiel gleich vier Stück auf einmal. In Infix-Notation bedeutet das, man müßte schreiben: 1 + 3 + 5 + 1022. In Präfix-Notation spart man sich eine Menge Tipparbeit, denn der Operator gilt für alle nachfolgenden Elemente: (+ 1 3 5 1022).
Evaluierung von (+ 1 3 5 1022)

Nun erschließt sich auch der Sinn der runden Klammern: Da jeder Operator beliebig viele Argumente haben kann, muß eindeutig abgegrenzt sein, welches Argument zu welchem Operator gehört. Nun, da wir das wissen, können wir Lisp-Ausdrücke ineinander verschachteln, denn jedes Argument kann seinerseits wieder ein Lisp-Ausdruck sein. Ein guter Editor hilft einem dabei, die Klammerebenen auseinanderzuhalten und blökt oder blinkt, wenn man zu viele, zu wenige oder falsche Klammern verwendet:
verschachtelter arithmetischer Ausdruck
das gleiche mit Klammerfehler

Der Lisp-Interpreter paßt dabei auch auf, daß die Ausdrücke gültig sind, und das gilt nicht nur für Klammerfehler:
Backtrace

Datentypen

Strings und Symbole

Über die oben bereits verwendeten Integer hinaus bietet Lisp eine Vielzahl anderer Datentypen. Neben den von anderen Sprachen bekannten wie "Strings" (stehen in Anführungszeichen) gibt es auch noch welche, die Lisp ziemlich für sich alleine hat, nämlich 'Symbole und '(Listen). Die Hochkommata im vorigen Satz stehen nicht ohne Grund da: Sie verhindern eine Evaluierung. Ein Symbol evaluiert normalerweise nicht zu sich selbst. Wird es nicht gequotet, gibt es entweder den Inhalt der Variablen zurück, die den Namen des Symbols trägt, oder, falls keine Variable mit diesem Namen existiert, gibt es eine Fehlermeldung. Gequotet:
gequotetes Symbol
Nicht gequotet und nicht definiert:
quoten vergessen

Diesem Fehler kann man abhelfen, indem man die Variable definiert. Zum Setzen und Ändern von Variablen gibt es den Befehl setq:
Variable mederle wird auf String "Wolfgang Mederle" gesetzt
Ein Evaluieren des ungequoteten Symbols bringt nun keine Fehlermeldung mehr, sondern liefert den Inhalt der Variablen zurück:
Symbol wird erfolgreich evaluiert

Zwei Symbole evaluieren immer zu sich selbst: t und nil, die in Lisp wahr und falsch repräsentieren. Diese Werte spielen vor allem bei Prädikaten eine Rolle, also bei Funktionen, die wahr oder falsch zurückgeben. Lisp verfügt über eine Menge eingebauter Prädikate, deren Namen in der Regel auf p oder -p enden. stringp ist ein solches Prädikat, es prüft, ob der folgende Ausdruck ein String ist:
(stringp mederle) --> t
(stringp 'mederle) --> nil

Listen

Listen sind ein ganz elementarer Datentyp in Lisp. S-Expressions sind Listen, die evaluiert werden. Damit eine Liste nicht evaluiert wird, muß sie auch mittels "'" gequotet werden. Listen sind Datenstrukturen, deren Bestandteile zweiteilig sind. Der erste Teil heißt car (das hat historische Gründe) und beinhaltet die Daten. Der zweite Teil, das cdr, enthält einen Verweis auf den Nachfolger in der Liste oder nil, wenn es das letzte Element ist:
Struktur eine Liste

Das car einer Liste ist deren erstes Element, das cdr ist die Liste ohne ihr erstes Element. Bei wem es nun bimmelt und das Wort "Rekursion!" erschallt, tut es dies zu Recht.

Listen kann man einfach selberbauen -- der Befehl dazu lautet list. (list 'langweiliger "Kurs" 'baeh) erzeugt eine Liste, die einen String und zwei Symbole als Element enthält. Auch hier ist der Unterschied zwischen Symbolen und deren Inhalt zu beachten:
(list 'langweiliger "Kurs" mederle) --> (langweiliger "Kurs" "Wolfgang Mederle"

Abgesehen von list gibt es noch den eine Ebene darunter operierenden Befehl cons, mit dem man sich Listen zusammenbauen kann -- das erste Argument ist das car eines Listenbestandteils (die man deshalb auch "Cons" nennt), das zweite das cdr. Eine Liste, die nur aus einem Element besteht, enthaelt man durch (cons mederle nil) -- nicht vergessen: Das letzte cdr einer regulären Liste ist nil! Eine Liste aus drei Elementen würde man so zusammenbauen: (cons "Hoer" (cons "auf" (cons mederle nil))). Man beachte die Ambiguität der eben erzeugten Liste.

Funktionen

Nicht immer möchte man im *scratch*-buffer herumwühlen, wenn etwas zu ändern oder neue Funktionalität hinzuzufügen ist. Um es etwas einfacher zu haben, gibt es den Befehl defun, mit dem man neue Funktionen definieren kann. defun bekommt als Argumente eine Liste der Argumente, mit der die Funktion aufzurufen ist, sowie einen Body, in dem steht, was mit diesen Argumenten zu tun ist. Wenn man eine Funktion definiert, gibt sie beim Evaluieren ihren Namen zurück. Wenn man sie aufruft, gibt sie das zurück, was bei ihrem Body als letztes herauskommt. Funktionen in Lisp brauchen normalerweise kein "return $wert", wie man es von anderen Sprachen her kennt, da sie immer einen Wert zurückliefern. Diesen kann man entweder weiterverwenden oder ignorieren.

Eine einfache Funktion, die nichts weiter tut, als ihre ersten beiden Argumente zu addieren und davon das dritte abzuziehen, sieht so aus:

(defun add-sub (a b c)
    (- (+ a b) c))
(defun add-sub (a b c) (- (+ a b) c)) --> add-sub

Die Datei .emacs

Der Emacs ist, oberflächlich betrachtet, ein Texteditor. Das ist nichts besonderes, denn Texteditoren gibt es viele. Was den Emacs von anderen Texteditoren unterscheidet, ist, daß er eine Lisp-Laufzeitumgebung mitbringt. Interessant wird die Arbeit mit dem Emacs dann, wenn man ihn an die persönlichen Bedürfnisse anpaßt. Es gibt kaum ein zweites Programm, das so weitgehend konfigurierbar und damit in der Lage ist, mit den Bedürfnissen des Benutzers mitzuwachsen. Die Datei .emacs (oder .emacs.el, was ihren Inhalt, Emacs-Lisp-Code, besser beschreibt) enthält das, was den Emacs auszeichnet: Die persönlichen Anpassungen des Benutzers. Im Folgenden werde ich anhand eines Ausschnittes aus meiner .emacs.el einige Erläuterungen geben. Für alles Weitere empfehle ich die Hinweisliste am Ende dieses Textes.

;;;; .emacs.el
;;;; Kommentare werden mit einem Semikolon eingeleitet
;;;; Alles mit vier Strichpunkten eingeleitete sind Zusatzkommentare,
;;;; um weitergehende Informationen zu geben. Die anderen Kommentare
;;;; stehen so in der Originaldatei.
;; <<<<<<<<<<<<<<<<<<<< load-path >>>>>>>>>>>>>>>>>>>>>>>>
;;;; Hier wird eine Variable gesetzt, naemlich die Variable
;;;; `load-path', die dem Emacs mitteilt, wo er nach Elisp-
;;;; Dateien suchen soll. `append' ist eine Funktion, die
;;;; eine Liste an eine andere Liste anhaengt.
;;;;  Die Prosaform der unten
;;;; stehenden Anweisung lautet:
;;;; "Schreibe in die Variable load-path eine Liste mit Pfadnamen,
;;;; an die du den bisherigen Inhalt der Variablen load-path anhaengst!"
(setq load-path
      (append '(
                "~/emacs"
                "~/emacs/ecb"
                "/usr/local/share/cis/emacs"
                "/usr/share/emacs/site-lisp/elib"
                "/usr/share/emacs/site-lisp/eieio"
                "/usr/share/emacs/site-lisp/semantic"
                "/usr/share/emacs/site-lisp/speedbar"
                "/usr/share/emacs/site-lisp/bbdb"
                "/usr/share/emacs/site-lisp/w3m"
                "/usr/share/emacs/site-lisp/mailcrypt"
                "/usr/share/emacs/site-lisp/psgml"
                "/usr/share/emacs/site-lisp/misc"
                )
              load-path))

;;;; Hier werden einige Dateien geladen, das heisst, ihr Inhalt wird
;;;; evaluiert. An dieser Stelle der Hinweis, dass alles in dieser
;;;; Datei auf mein System angepasst ist. Vieles davon wird auf
;;;; anderen Systemen nicht vorhanden sein. Die Dateien, die unten
;;;; geladen werden, existieren nur auf CIS-Rechnern.
(load "cis-tramp.el")
(load "cis-ilisp.el")
(load "cis-ede.el")
(load "cis-html-helper-mode.el")
(load "cis-preview-latex.el")
(load "cis-tex.el")
(load "cis-w3m.el")
(load "cis-jde.el")

;;;; Hier stelle ich den Standard-Browser auf Opera. Die Loesung ist
;;nicht gerade schoen, weil ich eigentlich die falsche Variable dafuer
;;verwende, aber sie funktioniert. :-)
;; Browser
(setq browse-url-netscape-program "/usr/bin/opera")
;;;; Mit dieser Variablen gibt man der URL, die man im Opera
;;;; darstellen lassen will, die Information mit, dass das in einem
;;;; neuen Browser-Fenster geschehen soll.
(setq browse-url-new-window-flag t)


;;;; Tastaturbelegungen kann man sich nach Lust und Laune
;;;; umdefinieren. `global-set-key' definiert sie global um, das
;;;; heisst, sie gelten in jedem Mode. Deshalb sollte man dabei ein
;;;; bisschen vorsichtig sein. `global-set-key' nimmt als erstes
;;;; Argument ein Tastenkuerzel und als zweites die Funktion, die
;;;; dabei ausgefuehrt werden soll. Bei der Taste F1 steht ein
;;;; Lambda-Ausdruck. Lambda-Ausdruecke sind vollwertige Funktionen
;;;; wie defuns, nur dass sie keinen Namen haben, etwa, weil man sie
;;;; nur einmal benutzt. Der Lambda-Asudruck bei F1 stellt mir die
;;;; Eingabemethode auf Korean-Hangul um, und da ich das oft brauche,
;;;; liegt es auf einer eigenen Funktionstaste. F12 tut etwas
;;;; aehnliches, es schaltet auf German-Postfix um, das aus "ae"
;;;; automatisch ein a-Umlaut macht usw. Dies brauche ich auch
;;;; haeufig, da ich mit einer US-Tastatur arbeite. F11 schliesslich
;;;; schaltet die Eingabemethoden aus bzw. wieder ein.
;; Tastenbelegung
(global-set-key [f1] '(lambda () (interactive) (set-input-method 'korean-hangul)))
(global-set-key [pause] 'toggle-read-only) ; HoldScreen
(global-set-key [f2]  'split-window)
(global-set-key [f3] 'other-window)
(global-set-key [S-f3] 'speedbar-get-focus)
(global-set-key [f4]  'query-replace-regexp)
(global-set-key [f5]  'revert-buffer)
(global-set-key [f6]  'gnus)
(global-set-key [f7]  'buffer-menu)
(global-set-key [f8] 'kill-buffer-other-window) ;; selbsterklaerend
(global-set-key [f9] 'create-tex-letter)
;; f10 for accessing menu in console mode
(global-set-key [S-f10] 'increase-quote-level)
(global-set-key [f11] 'toggle-input-method)
(global-set-key [f12] '(lambda () (interactive) (set-input-method 'german-postfix)))
(global-set-key [S-f12] 'my-uncomment-region)

;;;; Nun folgen einige Funktionsdefinitionen, die ich selbst
;;;; geschrieben oder von anderen uebernommen habe.
;;
;; Eigendefinierte Funktionen
;;
;; gut, wenn man einen Hinweis-buffer weghaben oder in Gnus das Artikel-Fenster
;; schliessen moechte
;;;; diese Funktion liegt, wie man oben sehen kann, bei mir auf F8
;;;; Der String in zweiter und dritter Zeile der Funktion ist ein
;;;; Doc-String. Er wird angezeigt, wenn man das System nach
;;;; Informationen ueber die Funktion fragt (siehe Emacs-Tutorial).
(defun kill-buffer-other-window (arg)
  "Kill the buffer in the other window, and make the current buffer full size. 
If no other window, kills current buffer."
  (interactive "p")
  (let ((buf (save-window-excursion (other-window arg) (current-buffer))))
    (delete-windows-on buf)
    (kill-buffer buf)))



;;;; Diese Funktion ruft ein externes Programm auf, um den aktuellen
;;;; Buffer darauf zu ueberpruefen, ob er valides HTML enthaelt und
;;;; Fehler gegebenenfalls zu korrigieren. 
;; Funktion fuer HTML-tidy innerhalb Emacs
(global-set-key "\C-xt" 'tidy-region)
(setq shell-command-default-error-buffer "tidy-errors") ; define an error buffer
(defun tidy-region ()
  "Run Tidy HTML parser on current region."
  (interactive)
  (let ((start (point-min))
        (end (point-max))
        (command "tidy -config /home/reboot/.tidy"))
        (shell-command-on-region start end command t t  shell-command-default-error-buffer))
  (font-lock-fontify-buffer))

;; Euro
(defun insert-euro ()
  "insert the euro sign"
  (interactive "*")
  (insert (string (make-char 'latin-iso8859-15 164))))

;; uncomment-region
(defun my-uncomment-region (point-min point-max)
  (interactive "r")
  (comment-region point-min point-max -1))

;;;; Das folgende ist ein Beispiel fuer ein Tastaturmakro. So etwas
;;;; schreibt man normalerweise nicht selbst, sondern man zeichnet es
;;;; mit dem Emacs-Makrorecorder auf und kopiert es dann hier rein.
;; fuegt > ein (liegt auf F10)
(fset 'increase-quote-level
      [?\C-a ?> ?  down ?\C-a])

;;*
;;* diverse Einstellungen
;;* =====================

;;;; Evaluieren von Emacs-Code in allen Buffern ermoeglichen (Cave!)
(put 'eval-expression 'disabled nil)

;;;; Dies startet den Emacs im Server-Mode. Anstatt 'emacs datei'
;;;; kann man nun 'emacsclient datei' sagen, und die Datei wird im
;;;; laufenden Emacs geladen. Sehr praktisch und unbedingt zu
;;;; empfehlen, weil man so die lange Ladezeit des Emacs nur einmal am
;;;; Tag hat. Emacsclient-Buffer schliesst man nicht mit C-x k,
;;;; sondern mit C-x #.
(server-start)

;; Schriftart
;;;; Die hier eingestellte Standardschrift hat keinen kursiven
;;;; Schnitt, ich mag sie aber viel lieber als die voreingestellte.
(set-default-font "-b&h-lucidatypewriter-medium-r-normal-sans-17-120-100-100-m-80-iso8859-1")

;;;; Die folgenden Einstellungen sind auskommentiert. Die hatte ich
;;;; frueher mal.
;; (set-default-font "-Adobe-Courier-Medium-R-Normal--14-140-75-75-M-90-ISO8859-1")
;; (set-default-font "-Adobe-Courier-Medium-R-Normal--20-140-100-100-M-110-ISO8859-1")
;; (set-default-font "-monotype-andale mono-medium-r-normal--0-0-0-0-m-0-iso8859-1")
;  (set-default-font "-adobe-courier-medium-r-normal--18-180-75-75-m-110-iso8859-1")
;; (add-to-list 'default-frame-alist '(background-mode . dark))
;; (set-background-color "DarkSlateGray")
;; (set-foreground-color "Wheat")
;; (set-face-background 'default "DarkSlateGray")
;; (set-face-foreground 'default "Wheat")
; (unless window-system
;       (set-face-background 'default "snow1"))

;;;; Uhrzeit in der Statuszeile anzeigen
(display-time)
;;;; nicht beim Runterscrollen staendig den Cursor in Bildmitte setzen
(setq scroll-conservatively 1)
;;;; Markierte Textbereiche farbig anzeigen.
(setq transient-mark-mode t)
;;;; Toolbar brauche ich nicht, nimmt nur Platz weg.
(tool-bar-mode -1)
;;;; Mach Leerzeichen anstatt Tabulatorzeichen. In der Regel
;;;; empfehlenswert, vor allem wenn man programmiert und Code
;;;; mit anderen austauscht.
(setq-default indent-tabs-mode nil)


;;*
;;* verschiedene Modi
;;* =================

;;;; Die folgenden Einstellungen sind teilweise fuer Modes, die nicht
;;;; unbedingt auf jedem System vorhanden sind. Was auskommentiert
;;;; ist, benutze ich entweder selbst nicht mehr, oder es wird am CIS
;;;; aus anderen Dateien konfiguriert.

;;;; Im Text-Modus automatisch umbrechen, sobald 78 Zeichen erreicht sind
;; Text-Modus
(add-hook 'text-mode-hook 'turn-on-auto-fill)
(setq fill-column 78)

;;;; C-Mode-Einstellungen
;; C
(add-hook 'c-mode-common-hook
   '(lambda () (c-set-style "stroustrup") (c-set-offset 'case-label 4)))


;;;; Alles, was mit TeX zu tun hat, wird am CIS aus einer anderen
;;;; Datei vorkonfiguriert. AucTeX und preview-LaTeX sind sehr
;;;; praktische Modes fuer LaTeX-Nutzer. AucTeX stellt viele
;;;; komfortable Funktionen zur Verfuegung, und preview-LaTeX dient
;;;; dazu, bereits im LaTeX-Sourcecode innerhalb des Emacs Formeln und
;;;; anderes so darzustellen, wie es spaeter im Dokument erscheint.
;; AUC-TeX
;; (require 'tex-site)
;; (setq-default TeX-master nil)
;; (setq TeX-parse-self t)
;; (add-hook 'TeX-mode-hook '(lambda () (setq fill-column 78)))

;; RefTeX für LaTeX-Files starten
;(add-hook 'LaTeX-mode-hook 'turn-on-reftex)

;; Preview-LaTeX
;(autoload 'LaTeX-preview-setup "preview")
;(add-hook 'LaTeX-mode-hook #'LaTeX-preview-setup)

;;;; Ein sehr praktischer Mode zum Briefeschreiben mit LaTeX. Nicht
;;;; standardmaessig vorhanden.
;; letter-template
(autoload 'create-tex-letter "letter-template" "Schnell einen Brief schreiben" t)
(setq *letter-default-dir* "~/brief/")
(setq *letter-template-file* (list "~/brief/template/brief.tex" "~/brief/template/cis-lettr.tex"))

;;;; Dieser Mode erzeugt Tabellen fuer LaTeX und HTML. Nicht
;;;; Standard. 
;; Table-Mode
;; (require 'table)
;; (add-hook 'text-mode-hook 'table-recognize)

;; Speedbar
(autoload 'speedbar-frame-mode "speedbar" "Popup a speedbar frame" t)
(autoload 'speedbar-get-focus "speedbar" "Jump to speedbar frame" t)
(define-key-after (lookup-key global-map [menu-bar tools])
  [speedbar] '("Speedbar" . speedbar-frame-mode) [calendar])

;;;; `require'-Anweisungen bedeuten "Lade diesen Mode, damit er bei
;;;; Bedarf verfuegbar ist". Die folgenden sind Nicht-Standard, aber
;;;; hilfreich fuer verschiedene andere Modes.
;; eieio
(require 'cl)
(require 'eieio-speedbar)
(require 'tree)
(require 'chart)

; ;; JDE
; (require 'jde)

;;;; Einstellungen fuer den HTML-Helper-Mode, mit dem auch diese Seite
;;;; erzeugt wurde. Wird am CIS teilweise von anderer Stelle
;;;; konfiguriert. 
;; HTML-Helper-Mode
;(autoload 'html-helper-mode "html-helper-mode" "Yay HTML" t)              
;(setq auto-mode-alist (cons '("\\.html$" . html-helper-mode) auto-mode-alist))
;;;; Den Rest musste ich rausschnippeln, damit das HTML hier nicht
;;;; kaputtgeht ...
    
; (add-hook 'html-helper-load-hook '(lambda () (require 'html-font)))   
; (add-hook 'html-helper-mode-hook '(lambda () (font-lock-mode 1)))
; (add-hook 'html-helper-mode-hook '(lambda () (auto-fill-mode -1)))

;;;; Crypt++ dient zum Ver- und Entschluesseln von Dateien, bei mir
;;;; mit gpg, dem GNU Privacy Guard. N-S.
; ;; Crypt++
(require 'crypt++)
(setq crypt-encryption-type 'gpg)
(modify-coding-system-alist 'file "\\.bz\\'" 'no-conversion)
(modify-coding-system-alist 'file "\\.bz2\\'" 'no-conversion)
(modify-coding-system-alist 'file "\\.gpg\\'" 'no-conversion)
(modify-coding-system-alist 'file "\\.gz\\'" 'no-conversion)
(modify-coding-system-alist 'file "\\.Z\\'" 'no-conversion)

;;;; Boxquote macht nette ASCII-Boxen um Textbestandteile. N-S.
;; boxquote
(require 'boxquote)

; ;; PSGML-Mode
; (autoload 'sgml-mode "psgml" "Major mode to edit SGML files." t)

;; Prolog-Mode
;; (setq load-path (cons "/usr/local/lib/sicstus3" load-path))
;; (autoload 'run-prolog "prolog" "Start a Prolog sub-process." t)
;; (autoload 'prolog-mode "prolog" "Major mode for editing Prolog programs." t)
;; (autoload 'mercury-mode "prolog" "Major mode for editing Mercury programs." t)
;; (setq prolog-system 'sicstus)
;; (setq auto-mode-alist (append '(("\\.pro$" . prolog-mode))
;;                                auto-mode-alist))

;; PHP-Mode
;; (require 'php-mode)

;;;; Einstellungen fuer Allegro Lisp, das ich momentan nicht benutze.
;; Franz Lisp
;;
; (defvar *eli-directory*)
; (setq *eli-directory* (expand-file-name "/opt/acl60/eli/"))
; (setq load-path (cons *eli-directory* load-path))
; (load (format "%sfi-site-init" *eli-directory*))
; (setq fi:common-lisp-image-name "/opt/acl60/mlisp")
; (setq fi:common-lisp-host "sudo.cis.uni-muenchen.de")
; ;; This function starts up lisp with your defaults.
; (defun run-common-lisp ()
;   (interactive)
;   (fi:common-lisp fi:common-lisp-buffer-name
;                 fi:common-lisp-directory
;                 fi:common-lisp-image-name
;                 fi:common-lisp-image-arguments
;                 fi:common-lisp-host))
;; Set up a keybinding for `run-common-lisp', two possible ways:
; (progn
;   (setq ctlx-3-map (make-keymap))
;   (define-key ctl-x-map "3" ctlx-3-map)
;   (define-key ctlx-3-map "l" 'run-common-lisp))
; ;; or this:
; (define-key global-map "\C-xl" 'run-common-lisp)
;; Run cl each time emacs is run:
; (run-common-lisp)

;;;; ILISP benutze ich hingegen haeufig, es ist *der* Mode, um Common
;;;; Lisp zu programmieren. N-S, wird am CIS teilweise vorgeladen.
;;; ILISP
;(require 'completer)
;; (autoload 'clisp-hs "ilisp"
;;   "Inferior generic Common Lisp." t)
;; (autoload 'cmulisp "ilisp"
;;   "Inferior CMU Common Lisp." t)

;; (setq cmulisp-program "lisp")
;; (setq clisp-hs-program "clisp -I")

(setq ilisp-site-hook
          '(lambda ()
                 (setq ilisp-motd "CLISP ISLISP V%s")
                 (setq expand-symlinks-rfs-exists t)
                 (setq lisp-indent-function #'common-lisp-indent-function)))

(setq common-lisp-hyperspec-symbol-table "file:/usr/local/doc/lisp/HyperSpec/Data/Map_Sym.txt")

;; (setq auto-mode-alist
;;       (append '(("\\.lisp$" . lisp-mode)
;;                 ("\\.lsp$" . lisp-mode)
;;                 ("\\.cl$" . lisp-mode))
;;               auto-mode-alist))
;; (setq lisp-mode-hook '(lambda () (require 'ilisp)))
;; (require 'hyperspec)

;;;; VM ist ein Mail-Mode, den ich nicht benutze. Gnus, das ich
;;;; zum E-Mail- und Newslesen benutze, hat eine eigene
;;;; Konfigurationsdatei, .gnus.el.
;; vm
;; (autoload 'vm "vm" "Start VM on your primary inbox." t)
;; (autoload 'vm-other-frame "vm" "Like `vm' but starts in another frame." t)
;; (autoload 'vm-visit-folder "vm" "Start VM on an arbitrary folder." t)
;; (autoload 'vm-visit-virtual-folder "vm" "Visit a VM virtual folder." t)
;; (autoload 'vm-mode "vm" "Run VM major mode on a buffer" t)
;; (autoload 'vm-mail "vm" "Send a mail message using VM." t)
;; (autoload 'vm-submit-bug-report "vm" "Send a bug report about VM." t)

;;;; Noch besser als der eingebaute show-paren-mode. N-S.
;; mic-paren
(require 'mic-paren)
(paren-activate)

;;;; Die folgenden werden am CIS vorgeladen.
;; semantic
; (setq semantic-load-turn-everything-on t)
; (require 'semantic-load)

;; Emacs Code Browser ECB
; (require 'ecb)

;; Emacs Development Environment
; (require 'ede)

;;;; Tramp ist mittlerweile Standard. Damit kann man remote (auf
;;;; anderen Rechnern) ueber ssh oder andere Protokolle Dateien
;;;; bearbeiten, als wuerde man an dem anderen Rechner sitzen. 
;; Tramp
; (require 'tramp)

;;;; BBDB, die Big Brother Database, speichert Namen, Adressen,
;;;; E-Mail, Telefonnummern und beliebige weitere Informationen ueber
;;;; Leute und ist perfekt in Gnus integriert.
;;;;
;; *** BBDB ***
;; die Adressdatenbank
(require 'bbdb)
(bbdb-initialize)
(add-hook 'gnus-startup-hook 'bbdb-insinuate-gnus)
;; Message-Mode für Mails verwenden
(setq bbdb-send-mail-style 'message)
;; BBDB-Einträge als normale Aliase im Message-Mode
(autoload 'bbdb-define-all-aliases
  "bbdb-com" "Hook mail alias feature of BBDB into message-mode." t)
(add-hook 'message-setup-hook 'bbdb-define-all-aliases)
;; kein Syntax-Check für Telefonnummern
(setq bbdb-north-american-phone-numbers-p nil)
;; immer zu vollem Namen expandieren
(setq bbdb-dwim-net-address-allow-redundancy t)
;; eigene Adresse
(setq bbdb-user-mail-names (concat user-login-name "@.*"))
;; automatisch abspeichern
(setq bbdb-offer-save 'auto)
;; 4 Zeilen-Layout
(setq window-min-height 4)
(setq bbdb-pop-up-target-lines 4)
;; Kurzform
;(setq bbdb-elided-display t)
;; Kurzform
;(setq bbdb-pop-up-elided-display t)
;; Informationen sammeln
(setq  bbdb-notice-hook 'bbdb-auto-notes-hook)
(setq bbdb-auto-notes-alist
          (list
           '("Organization"  (".*" company 0))
           '("Newsgroups"    ("[^,]+" newsgroups 0))
           '("Subject"       (".*" last-subj 0 t))
           '("User-Agent"    (".*" mailer 0))
           '("X-URL"         (".*" www 0))
           '("X-Mailer"      (".*" mailer 0))
           '("X-Newsreader"  (".*" mailer 0))))
;; Trennen der Infos mit Newlines
(setq bbdb-notes-default-separator "\n") 
(add-hook 'bbdb-change-hook 'bbdb-timestamp-hook) 
(add-hook 'bbdb-create-hook 'bbdb-creation-date-hook) 
;; So geben wir der BBDB einen Datumsstempel mit auf den Weg
(add-hook 'bbdb-change-hook 'bbdb-creation-date-hook)
(add-hook 'bbdb-change-hook 'bbdb-timestamp-hook)
;; und das ist fuer bbdb-frame, das ein neues Fenster mit Kontaktinfos öffnet
;; (load "bbdb-frame")

;; BBDB-envelope
;(load "bbdb-envelope")
;(setq bbdb-envelope-rtn-address "{\\\\Street\\\\City, State
;  or Province, Postal Code}\n")
;(define-key bbdb-mode-map [(E)]          'bbdb-envelope-print)
;(define-key bbdb-mode-map [(L)]   'bbdb-envelope-letter-print)

;;;; Ende der Datei. 

Die Datei kann hier heruntergeladen werden.

Weiterführende Informationen

Informationen über Common Lisp

WWW

Usenet

Bücher

Für Einsteiger:

Für Fortgeschrittene:

Emacs und seine Modes

Emacs lernen

Emacs erweitern

Die größte Sammlung an Emacs-Modes, die nicht standardmäßig mit dem Emacs ausgeliefert werden, ist die Emacs Lisp List.

Beispiele für Emacs-Konfigurationsdateien finden sich auf dotemacs.de.

Alles zum Thema Gnus, dem Mail- und Newsreader für den Emacs (mitgeliefert!) gibt es auf gnus.org.

Emacs im Usenet

Viele Newsgroups widmen sich ausschließlich dem Emacs oder gar nur dem Newsreader Gnus:

Home

Last modified: Wed Oct 31 12:08:04 CET 2012