[lisppaste-requests] syntax coloring support for haskell
Kristof Bastiaensen
kristof at vleeuwen.org
Tue Aug 29 12:42:18 UTC 2006
Hi,
the code that I send earlier contains a bug that eats spaces from the
beginning of the line. Here is the new code (hopefully without bugs
this time):
(defvar *haskell-open-parens* "([{")
(defvar *haskell-close-parens* ")]}")
(defvar *haskell-in-word* "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789")
(defvar *haskell-begin-id* "abcdefghijklmnopqrstuvwxyz")
(defvar *haskell-begin-cons* "ABCDEFGHIJKLMNOPQRSTUVWXYZ")
(defvar *haskell-in-symbol* "!#$%&*+./<=>?@\\^|-~:")
(defvar *haskell-reserved-symbols*
'(".." "::" "@" "~" "=" "->" "<-" "|" "\\"))
(defvar *haskell-reserved-words*
'("case" "class" "data" "default" "deriving" "do" "else" "if"
"import" "in" "infix" "infixl" "infixr" "instance" "let" "module"
"newtype" "of" "then" "type" "where"))
(defvar *haskell-non-constituent*
'(#\space #\return #\tab #\newline #\{ #\} #\( #\) #\" #\[ #\]))
(define-coloring-type :haskell "Haskell"
:modes (:normal :comment :multi-comment :string :char :identifier :backquote
:newline :symbol :parenlike :single-escape)
:default-mode :normal
:transitions
(((:normal)
((scan-any *haskell-in-word*)
(set-mode :identifier
:until (or (scan-any *haskell-non-constituent*)
(scan-any *haskell-in-symbol*))
:advancing nil))
((scan "--")
(set-mode :comment
:until (scan-any '(#\return #\newline))
:advancing nil))
((scan "{-")
(set-mode :multi-comment
:until (scan "-}")))
((scan #\")
(set-mode :string
:until (scan #\")))
((scan #\`)
(set-mode :backquote
:until (scan #\`)))
((scan "'")
(set-mode :char
:until (scan #\')))
((scan-any *haskell-in-symbol*)
(set-mode :symbol
:until (or (scan-any *haskell-non-constituent*)
(scan-any *haskell-in-word*)
(scan #\'))
:advancing nil))
((or (scan-any *haskell-open-parens*)
(scan-any *haskell-close-parens*))
(set-mode :parenlike
:until (advance 1)
:advancing nil))
((scan-any '(#\newline #\return))
(set-mode :newline
:until (advance 1)
:advancing nil)))
((:string)
((scan #\\)
(set-mode :single-escape
:until (advance 1))))
((:char)
((scan #\\)
(set-mode :single-escape
:until (advance 1)))))
:formatter-variables
((paren-counter 0)
(beginning-of-line t))
:formatter-after-hook (lambda nil
(format nil "~{~A~}"
(loop for i from paren-counter downto 1
collect "</span></span>")))
:formatters
(((:normal)
(lambda (type s)
(declare (ignore type))
(cond (beginning-of-line
(setq beginning-of-line nil)
(if (char= (elt s 0) #\space)
(concatenate 'string " " (subseq s 1))
s))
(t s))))
((:newline)
(lambda (type s)
(declare (ignore type))
(setq beginning-of-line t)
s))
((:backquote)
(lambda (type s)
(declare (ignore type))
(setq beginning-of-line nil)
(if (find (elt s 1) *haskell-begin-cons*)
(format nil "<span class=\"variable\">~A</span>"
s)
(format nil "<span class=\"atom\">~A</span>"
s))))
((:comment :multi-comment)
(lambda (type s)
(declare (ignore type))
(setq beginning-of-line nil)
(format nil "<span class=\"comment\">~A</span>"
s)))
((:string)
(lambda (type s)
(declare (ignore type))
(setq beginning-of-line nil)
(format nil "<span class=\"string\">~A</span>"
s)))
((:char)
(lambda (type s)
(declare (ignore type))
(setq beginning-of-line nil)
(format nil "<span class=\"character\">~A</span>"
s)))
((:identifier)
(lambda (type s)
(declare (ignore type))
(prog1
(cond ((find (elt s 0) *haskell-begin-cons*)
(format nil "<span class=\"variable\">~A</span>" s))
((member s *haskell-reserved-words* :test #'string=)
(format nil "<span class=\"keyword\">~A</span>" s))
(beginning-of-line
(format nil "<span class=\"function\">~A</span>" s))
(t s))
(setq beginning-of-line nil))))
((:symbol)
(lambda (type s)
(declare (ignore type))
(setq beginning-of-line nil)
(cond ((member s *haskell-reserved-symbols* :test #'string=)
(format nil "<span class=\"keyword\">~A</span>" s))
((char= (elt s 0) #\:)
(format nil "<span class=\"variable\">~A</span>" s))
(t (format nil "<span class=\"atom\">~A</span>" s)))))
((:single-escape)
(lambda (type s)
(call-formatter (cdr type) s)))
((:parenlike)
(lambda (type s)
(declare (ignore type))
(setq beginning-of-line nil)
(let ((open nil)
(count 0))
(if (eql (length s) 1)
(progn
(when (find (elt s 0) *haskell-open-parens*)
(setf open t)
(setf count (mod paren-counter 6))
(incf paren-counter))
(when (find (elt s 0) *haskell-close-parens*)
(setf open nil)
(decf paren-counter)
(setf count (mod paren-counter 6)))
(if open
(format nil "<span class=\"paren~A\">~A<span class=\"~A\">"
(1+ count) s *css-background-class*)
(format nil "</span>~A</span>"
s)))
s))))))
thanks,
Kristof
More information about the lisppaste-requests
mailing list