diff options
author | Stefan Monnier <monnier@iro.umontreal.ca> | 2010-06-02 16:13:11 -0400 |
---|---|---|
committer | Stefan Monnier <monnier@iro.umontreal.ca> | 2010-06-02 16:13:11 -0400 |
commit | 927c346bd66a7048e83d4f3275342a3d86a50f39 (patch) | |
tree | bacd1e7b45c245cc21df9af2af08df5dd4c03569 /lisp/emacs-lisp/smie.el | |
parent | 1efeec868dec5b42ed3b8cade883066e178a6e2a (diff) | |
download | emacs-927c346bd66a7048e83d4f3275342a3d86a50f39.tar.gz emacs-927c346bd66a7048e83d4f3275342a3d86a50f39.tar.bz2 emacs-927c346bd66a7048e83d4f3275342a3d86a50f39.zip |
* lisp/emacs-lisp/smie.el (smie-indent-calculate): Simplify and cleanup.
(smie-indent-hanging-p): Use smie-bolp.
* test/indent: New dir.
Diffstat (limited to 'lisp/emacs-lisp/smie.el')
-rw-r--r-- | lisp/emacs-lisp/smie.el | 144 |
1 files changed, 68 insertions, 76 deletions
diff --git a/lisp/emacs-lisp/smie.el b/lisp/emacs-lisp/smie.el index 1952b43452d..5f181036d81 100644 --- a/lisp/emacs-lisp/smie.el +++ b/lisp/emacs-lisp/smie.el @@ -484,6 +484,14 @@ Possible return values: :type 'integer) (defvar smie-indent-rules 'unset + ;; TODO: For SML, we need more rule formats, so as to handle + ;; structure Foo = + ;; Bar (toto) + ;; and + ;; structure Foo = + ;; struct ... end + ;; I.e. the indentation after "=" depends on the parent ("structure") + ;; as well as on the following token ("struct"). "Rules of the following form. \(TOK OFFSET) how to indent right after TOK. \(TOK O1 O2) how to indent right after TOK: @@ -506,7 +514,7 @@ A nil offset defaults to `smie-indent-basic'.") (forward-char 1)) (skip-chars-forward " \t") (eolp)) - (save-excursion (skip-chars-backward " \t") (not (bolp))))) + (not (smie-bolp)))) (defun smie-bolp () (save-excursion (skip-chars-backward " \t") (bolp))) @@ -526,9 +534,6 @@ VIRTUAL can take two different non-nil values: to be good only if it follows a line break. - :hanging: means that the current indentation of point can be trusted to be good except if the following token is hanging." - ;; FIXME: This has accumulated a lot of rules, some of which aren't - ;; clearly orthogonal any more, so we should probably try and - ;; restructure it somewhat. (or ;; Trust pre-existing indentation on other lines. (and virtual @@ -598,41 +603,73 @@ VIRTUAL can take two different non-nil values: (forward-comment (point-max)) (skip-chars-forward " \t\r\n") (smie-indent-calculate nil))) - ;; indentation inside a comment. - ;; FIXME: Hey, this is not generic!! - (and (looking-at "\\*") (nth 4 (syntax-ppss)) + ;; indentation of comment-continue lines. + (and (< 0 (length comment-continue)) + (looking-at (regexp-quote comment-continue)) (nth 4 (syntax-ppss)) (let ((ppss (syntax-ppss))) (save-excursion (forward-line -1) (if (<= (point) (nth 8 ppss)) (progn (goto-char (1+ (nth 8 ppss))) (current-column)) (skip-chars-forward " \t") - (if (looking-at "\\*") + (if (looking-at (regexp-quote comment-continue)) (current-column)))))) ;; Indentation right after a special keyword. (save-excursion (let* ((tok (funcall smie-backward-token-function)) (tokinfo (assoc tok smie-indent-rules)) - (toklevel (assoc tok smie-op-levels))) - (when (or tokinfo (and toklevel (null (cadr toklevel)))) - (if (or (smie-indent-hanging-p) - ;; If calculating the virtual indentation point, prefer - ;; looking up the virtual indentation of the alignment - ;; point as well. This is used for indentation after - ;; "fn x => fn y =>". - virtual) + (toklevel (if (and (zerop (length tok)) + ;; 4 == Open paren syntax. + (eq (syntax-class (syntax-after (1- (point)))) + 4)) + (progn (forward-char -1) + (setq tok (buffer-substring + (point) (1+ (point)))) + (setq tokinfo (assoc tok smie-indent-rules)) + (list tok nil 0)) + (assoc tok smie-op-levels)))) + (if (and toklevel (null (cadr toklevel)) (null tokinfo)) + (setq tokinfo (list (car toklevel) nil nil))) + (if (and tokinfo (null toklevel)) + (error "Token %S has indent rule but has no parsing info" tok)) + (when toklevel + (let ((default-offset + ;; The default indentation after a keyword/operator + ;; is 0 for infix and t for prefix. + ;; Using the BNF syntax, we could come up with + ;; better defaults, but we only have the + ;; precedence levels here. + (if (or tokinfo (null (cadr toklevel))) + (smie-indent-offset t) 0))) + ;; For indentation after "(let", we end up accumulating the + ;; offset of "(" and the offset of "let", so we use `min' + ;; to try and get it right either way. + (min (+ (smie-indent-calculate :bolp) - (or (caddr tokinfo) (cadr tokinfo) (smie-indent-offset t))) + (or (caddr tokinfo) (cadr tokinfo) default-offset)) (+ (current-column) - (or (cadr tokinfo) (smie-indent-offset t))))))) - ;; Main loop (FIXME: whatever that means!?). + (or (cadr tokinfo) default-offset))))))) + ;; Indentation of sequences of simple expressions without + ;; intervening keywords or operators. E.g. "a b c" or "g (balbla) f". + ;; Can be a list of expressions or a function call. + ;; If it's a function call, the first element is special (it's the + ;; function). We distinguish function calls from mere lists of + ;; expressions based on whether the preceding token is listed in + ;; the `list-intro' entry of smie-indent-rules. + ;; + ;; TODO: to indent Lisp code, we should add a way to specify + ;; particular indentation for particular args depending on the + ;; function (which would require always skipping back until the + ;; function). + ;; TODO: to indent C code, such as "if (...) {...}" we might need + ;; to add similar indentation hooks for particular positions, but + ;; based on the preceding token rather than based on the first exp. (save-excursion (let ((positions nil) - (begline nil) arg) (while (and (null (car (smie-backward-sexp))) (push (point) positions) - (not (setq begline (smie-bolp))))) + (not (smie-bolp)))) (save-excursion ;; Figure out if the atom we just skipped is an argument rather ;; than a function. @@ -640,73 +677,28 @@ VIRTUAL can take two different non-nil values: (member (funcall smie-backward-token-function) (cdr (assoc 'list-intro smie-indent-rules)))))) (cond - ((and arg positions) + ((null positions) + ;; We're the first expression of the list. In that case, the + ;; indentation should be (have been) determined by its context. + nil) + (arg + ;; There's a previous element, and it's not special (it's not + ;; the function), so let's just align with that one. (goto-char (car positions)) (current-column)) - ((and (null begline) (cdr positions)) + ((cdr positions) ;; We skipped some args plus the function and bumped into something. ;; Align with the first arg. (goto-char (cadr positions)) (current-column)) - ((and (null begline) positions) + (positions ;; We're the first arg. - ;; FIXME: it might not be a funcall, in which case we might be the - ;; second element. (goto-char (car positions)) (+ (smie-indent-offset 'args) ;; We used to use (smie-indent-calculate :bolp), but that ;; doesn't seem right since it might then indent args less than ;; the function itself. - (current-column))) - ((and (null arg) (null positions)) - ;; We're the function itself. Not sure what to do here yet. - ;; FIXME: This should not be possible, because it should mean - ;; we're right after some special token. - (if virtual (current-column) - (save-excursion - (let* ((pos (point)) - (tok (funcall smie-backward-token-function)) - (toklevels (cdr (assoc tok smie-op-levels)))) - (cond - ((numberp (car toklevels)) - ;; We're right after an infix token. Let's skip over the - ;; lefthand side. - (goto-char pos) - (let (res) - (while (progn (setq res (smie-backward-sexp 'halfsexp)) - (and (not (smie-bolp)) - (equal (car res) (car toklevels))))) - ;; We should be right after a token of equal or - ;; higher precedence. - (cond - ((and (consp res) (memq (car res) '(t nil))) - ;; The token of higher-precedence is like an open-paren. - ;; Sample case for t: foo { bar, \n[TAB] baz }. - ;; Sample case for nil: match ... with \n[TAB] | toto ... - ;; (goto-char (cadr res)) - (smie-indent-calculate :hanging)) - ((and (consp res) (<= (car res) (car toklevels))) - ;; We stopped at a token of equal or higher precedence - ;; because we found a place with which to align. - (current-column)) - ))) - ;; For other cases.... hmm... we'll see when we get there. - ))))) - ((null positions) - (funcall smie-backward-token-function) - (+ (smie-indent-offset 'args) (smie-indent-calculate :bolp))) - ((car (smie-backward-sexp)) - ;; No arg stands on its own line, but the function does: - (if (cdr positions) - (progn - (goto-char (cadr positions)) - (current-column)) - (goto-char (car positions)) - (+ (current-column) (smie-indent-offset 'args)))) - (t - ;; We've skipped to a previous arg on its own line: align. - (goto-char (car positions)) - (current-column))))))) + (current-column)))))))) (defun smie-indent-line () "Indent current line using the SMIE indentation engine." |