Emacs/Unicode symbols

From HaskellWiki
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.
Emacs for Haskell

Inferior Haskell processes
Automatic unit testing
Automatic building
API searching
Project navigation
Snippets
Literate programming

In Haskell code, you can end up using a lot of mathematical symbols. It is possible to hack the fontifying features of Emacs to change the ASCII textual representations of arrows and operators into the nice-looking real symbols, much like you could with TeX. The following code is a compilation of Emacs lisp code found on the Emacs wiki on the Pretty Lambda page (that page also has examples of how to apply the general Unicode defuns to other languages):

HOWEVER: due to the symbols taking up less space, this has the unfortunate side effect of changing the indentation stops that the indent key offers. This will mean that your code may not look properly aligned to those who do not have this feature in their editor, or could even mean that your code means something different to how it looks. (It is possible to contrive an example that looks correct in emacs, but actually fails to compile). The following is left for interest, but probably should NOT be used.

Haskell-mode has included this feature for a long time now, so you probably just need to (setq haskell-font-lock-symbols t) in your .emacs to use this feature.

(defun unicode-symbol (name)
   "Translate a symbolic name for a Unicode character -- e.g., LEFT-ARROW                                      
 or GREATER-THAN into an actual Unicode character code. "
   (decode-char 'ucs (case name                                             
			(left-arrow 8592)
                       (up-arrow 8593)
                       (right-arrow 8594)
                       (down-arrow 8595)                                                
			(double-vertical-bar #X2551)                  
                       (equal #X003d)
                       (not-equal #X2260)
                       (identical #X2261)
                       (not-identical #X2262)
                       (less-than #X003c)
                       (greater-than #X003e)
   		        (less-than-or-equal-to #X2264)
            		(greater-than-or-equal-to #X2265)                        
                       (logical-and #X2227)
                       (logical-or #X2228)
                       (logical-neg #X00AC)                                                  
                       ('nil #X2205)
                       (horizontal-ellipsis #X2026)
                       (double-exclamation #X203C)
                       (prime #X2032)
                       (double-prime #X2033)
                       (for-all #X2200)
                       (there-exists #X2203)
                       (element-of #X2208)              
                       (square-root #X221A)
                       (squared #X00B2)
                       (cubed #X00B3)                                            
                       (lambda #X03BB)
                       (alpha #X03B1)
                       (beta #X03B2)
                       (gamma #X03B3)
                       (delta #X03B4))))
(defun substitute-pattern-with-unicode (pattern symbol)
    "Add a font lock hook to replace the matched part of PATTERN with the                                       
     Unicode symbol SYMBOL looked up with UNICODE-SYMBOL."
    (font-lock-add-keywords
    nil `((,pattern 
           (0 (progn (compose-region (match-beginning 1) (match-end 1)
                                     ,(unicode-symbol symbol)
                                     'decompose-region)
                             nil))))))
(defun substitute-patterns-with-unicode (patterns)
   "Call SUBSTITUTE-PATTERN-WITH-UNICODE repeatedly."
   (mapcar #'(lambda (x)
               (substitute-pattern-with-unicode (car x)
                                                (cdr x)))
           patterns))
(defun haskell-unicode ()
 (substitute-patterns-with-unicode
  (list (cons "\\(<-\\)" 'left-arrow)
        (cons "\\(->\\)" 'right-arrow)
        (cons "\\(==\\)" 'identical)
        (cons "\\(/=\\)" 'not-identical)
        (cons "\\(()\\)" 'nil)
        (cons "\\<\\(sqrt\\)\\>" 'square-root)
        (cons "\\(&&\\)" 'logical-and)
        (cons "\\(||\\)" 'logical-or)
        (cons "\\<\\(not\\)\\>" 'logical-neg)
        (cons "\\(>\\)\\[^=\\]" 'greater-than)
        (cons "\\(<\\)\\[^=\\]" 'less-than)
        (cons "\\(>=\\)" 'greater-than-or-equal-to)
        (cons "\\(<=\\)" 'less-than-or-equal-to)
        (cons "\\<\\(alpha\\)\\>" 'alpha)
        (cons "\\<\\(beta\\)\\>" 'beta)
        (cons "\\<\\(gamma\\)\\>" 'gamma)
        (cons "\\<\\(delta\\)\\>" 'delta)
        (cons "\\(''\\)" 'double-prime)
        (cons "\\('\\)" 'prime)
        (cons "\\(!!\\)" 'double-exclamation)
        (cons "\\(\\.\\.\\)" 'horizontal-ellipsis))))
(add-hook 'haskell-mode-hook 'haskell-unicode)