branch: elpa/haskell-tng-mode commit 96609e4b9a4b8572c0527dde20657434dbabd4ac Author: Tseen She <ts33n....@gmail.com> Commit: Tseen She <ts33n....@gmail.com>
thoughts on layout inference --- haskell-tng-smie.el | 41 +++++++++++++++++++++++++++++------------ test/lexer/layout.hs.lexer | 4 ++-- 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/haskell-tng-smie.el b/haskell-tng-smie.el index 576a783..67ac14d 100644 --- a/haskell-tng-smie.el +++ b/haskell-tng-smie.el @@ -46,17 +46,27 @@ (case-fold-search nil) (syntax (char-syntax (char-after)))) (cond - ;; TODO brace inference - ((and - (not (eq start-line this-line)) - (<= - (haskell-tng-smie:indentation-level (point)) - (haskell-tng-smie:indentation-level start)) - ";")) + ;; layout: semicolon inference + ((not (eq start-line this-line)) + (let ((start-layout (haskell-tng-smie:layout-level start-line)) + (this-layout (current-indentation))) + (cond + ((null start-layout) "" + (eq start-layout this-layout) ";" + t "")))) ;; parens ((member syntax '(?\( ?\) ?\" ?$)) nil) + ;; TODO brace inference ("offside" rule). + ;; + ;; Starting braces are trivial, there is a known list of keywords, so + ;; we just need to do a lookback when we hit a non-{ lexeme. Ending + ;; braces are a lot harder, as we need to calculate "do we need to + ;; close a brace here" every time the indentation level decreases. A + ;; possible solution is to calculate and cache the closing brace when + ;; discovering an open brace, but that just introduces more problems. + ;; regexps ((or ;; known identifiers @@ -68,12 +78,19 @@ (goto-char (match-end 0)) (match-string-no-properties 0))))))) -(defun haskell-tng-smie:indentation-level (p) - "Calculates the indentation level of the most inner part of the given point's line." - ;; FIXME this is a hack for now, look for `let', `do' and friends according to - ;; the Haskell2010 report. +(defun haskell-tng-smie:layout-level (line) + "Calculates the layout indentation of the most inner part of +the given point's line." + ;; FIXME should the input be the line numbers? + ;; + ;; TODO starting at the end of the line, look backwards for wldo (where, let, do, of). + ;; If the wldo is the last lexeme, then the layout level is set by the next line (return nil). + ;; If the wldo is followed by a non-brace lexeme, set the layout level. + ;; + ;; If there is no wldo, the layout level is set by the indentation level + ;; (think about this some more) (save-excursion - (goto-char p) + (goto-line line) (current-indentation))) ;; TODO a haskell grammar diff --git a/test/lexer/layout.hs.lexer b/test/lexer/layout.hs.lexer index d048eb2..f76687b 100644 --- a/test/lexer/layout.hs.lexer +++ b/test/lexer/layout.hs.lexer @@ -64,8 +64,8 @@ where stkToLst Empty = -[ -] +SYNTAX_[ +SYNTAX_] ; stkToLst SYNTAX_(