]> code.delx.au - gnu-emacs/blobdiff - lisp/emacs-lisp/smie.el
* lisp/emacs-lisp/smie.el: Provide smarter auto-filling.
[gnu-emacs] / lisp / emacs-lisp / smie.el
index 17cc5668b5f9716ef040dc4babc4322eb97dd562..49ee051e62db2e21d70489ad3548618e62cc4e24 100644 (file)
@@ -229,14 +229,18 @@ one of those elements share the same precedence level and associativity."
               ;; the trouble, and it lets the writer of the BNF
               ;; be a bit more sloppy by skipping uninteresting base
               ;; cases which are terminals but not OPs.
-              (assert (not (member (cadr rhs) nts)))
+              (when (member (cadr rhs) nts)
+                (error "Adjacent non-terminals: %s %s"
+                       (car rhs) (cadr rhs)))
               (pushnew (cadr rhs) first-ops)))
           (let ((shr (reverse rhs)))
             (if (not (member (car shr) nts))
                 (pushnew (car shr) last-ops)
               (pushnew (car shr) last-nts)
               (when (consp (cdr shr))
-                (assert (not (member (cadr shr) nts)))
+                (when (member (cadr shr) nts)
+                  (error "Adjacent non-terminals: %s %s"
+                         (cadr shr) (car shr)))
                 (pushnew (cadr shr) last-ops)))))
         (push (cons nt first-ops) first-ops-table)
         (push (cons nt last-ops) last-ops-table)
@@ -1535,6 +1539,38 @@ to which that point should be aligned, if we were to reindent it.")
           (save-excursion (indent-line-to indent))
         (indent-line-to indent)))))
 
+(defun smie-auto-fill ()
+  (let ((fc (current-fill-column))
+        (try-again nil))
+    (while (and fc (> (current-column) fc))
+      (cond
+       ((not (or (nth 8 (save-excursion
+                          (syntax-ppss (line-beginning-position))))
+                 (nth 8 (syntax-ppss))))
+        (save-excursion
+          (beginning-of-line)
+          (smie-indent-forward-token)
+          (let ((bsf (point))
+                (gain 0)
+                curcol)
+            (while (<= (setq curcol (current-column)) fc)
+              ;; FIXME?  `smie-indent-calculate' can (and often will)
+              ;; return a result that actually depends on the presence/absence
+              ;; of a newline, so the gain computed here may not be accurate,
+              ;; but in practice it seems to works well enough.
+              (let* ((newcol (smie-indent-calculate))
+                     (newgain (- curcol newcol)))
+                (when (> newgain gain)
+                  (setq gain newgain)
+                  (setq bsf (point))))
+              (smie-indent-forward-token))
+            (when (> gain 0)
+              (setq try-again)
+              (goto-char bsf)
+              (newline-and-indent)))))
+       (t (do-auto-fill))))))
+
+
 (defun smie-setup (grammar rules-function &rest keywords)
   "Setup SMIE navigation and indentation.
 GRAMMAR is a grammar table generated by `smie-prec2->grammar'.
@@ -1545,6 +1581,7 @@ KEYWORDS are additional arguments, which can use the following keywords:
   (set (make-local-variable 'smie-rules-function) rules-function)
   (set (make-local-variable 'smie-grammar) grammar)
   (set (make-local-variable 'indent-line-function) 'smie-indent-line)
+  (set (make-local-variable 'normal-auto-fill-function) 'smie-auto-fill)
   (set (make-local-variable 'forward-sexp-function)
        'smie-forward-sexp-command)
   (while keywords