aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJackson Ray Hamilton2019-03-26 20:14:46 -0700
committerJackson Ray Hamilton2019-04-08 22:48:23 -0700
commitafec4511cf5c336eaf9f8bb1425bf2dd1fc12740 (patch)
tree35b760f6eb48099f7f982b65cb733b8a9dabaa92
parent55c80d43a972d3e126c173745c57a0a383bd3ad4 (diff)
downloademacs-afec4511cf5c336eaf9f8bb1425bf2dd1fc12740.tar.gz
emacs-afec4511cf5c336eaf9f8bb1425bf2dd1fc12740.zip
Split JSX indentation calculation into several functions
* lisp/progmodes/js.el (js-jsx--contextual-indentation) (js-jsx--expr-attribute-pos, js-jsx--expr-indentation): Extract logic from js-jsx--indentation, and improve the logic’s documentation. (js-jsx--indentation): Simplify by splitting into several functions (see above) and improve the logic’s documentation.
-rw-r--r--lisp/progmodes/js.el146
1 files changed, 81 insertions, 65 deletions
diff --git a/lisp/progmodes/js.el b/lisp/progmodes/js.el
index 679633fc836..2d29d4e443a 100644
--- a/lisp/progmodes/js.el
+++ b/lisp/progmodes/js.el
@@ -2575,12 +2575,86 @@ current line is the \"=>\" token (of an arrow function)."
2575 (list 'tag (nth 0 enclosing-tag-pos) (nth 1 enclosing-tag-pos))) 2575 (list 'tag (nth 0 enclosing-tag-pos) (nth 1 enclosing-tag-pos)))
2576 (list 'text (nth 0 enclosing-tag-pos) (nth 2 enclosing-tag-pos)))))) 2576 (list 'text (nth 0 enclosing-tag-pos) (nth 2 enclosing-tag-pos))))))
2577 2577
2578(defun js-jsx--contextual-indentation (line context)
2579 "Calculate indentation column for LINE from CONTEXT.
2580The column calculation is based off of `sgml-calculate-indent'."
2581 (pcase (nth 0 context)
2582
2583 ('string
2584 ;; Go back to previous non-empty line.
2585 (while (and (> (point) (nth 1 context))
2586 (zerop (forward-line -1))
2587 (looking-at "[ \t]*$")))
2588 (if (> (point) (nth 1 context))
2589 ;; Previous line is inside the string.
2590 (current-indentation)
2591 (goto-char (nth 1 context))
2592 (1+ (current-column))))
2593
2594 ('tag
2595 ;; Special JSX indentation rule: a “dangling” closing angle
2596 ;; bracket on its own line is indented at the same level as the
2597 ;; opening angle bracket of the JSXElement. Otherwise, indent
2598 ;; JSXAttribute space like SGML.
2599 (if (progn
2600 (goto-char (nth 2 context))
2601 (and (= line (line-number-at-pos))
2602 (looking-back "^\\s-*/?>" (line-beginning-position))))
2603 (progn
2604 (goto-char (nth 1 context))
2605 (current-column))
2606 ;; Indent JSXAttribute space like SGML.
2607 (goto-char (nth 1 context))
2608 ;; Skip tag name:
2609 (skip-chars-forward " \t")
2610 (skip-chars-forward "^ \t\n")
2611 (skip-chars-forward " \t")
2612 (if (not (eolp))
2613 (current-column)
2614 ;; This is the first attribute: indent.
2615 (goto-char (+ (nth 1 context) js-jsx-attribute-offset))
2616 (+ (current-column) js-indent-level))))
2617
2618 ('text
2619 ;; Indent to reflect nesting.
2620 (goto-char (nth 1 context))
2621 (+ (current-column)
2622 ;; The last line isn’t nested, but the rest are.
2623 (if (or (not (nth 2 context)) ; Unclosed.
2624 (< line (line-number-at-pos (nth 2 context))))
2625 js-indent-level
2626 0)))
2627
2628 ))
2629
2630(defun js-jsx--expr-attribute-pos (start limit)
2631 "Look back from START to LIMIT for a JSXAttribute."
2632 (save-excursion
2633 (goto-char start) ; Skip the first curly.
2634 ;; Skip any remaining enclosing curlies until the JSXElement’s
2635 ;; beginning position; the last curly ought to be one of a
2636 ;; JSXExpressionContainer, which may refer to its JSXAttribute’s
2637 ;; beginning position (if it has one).
2638 (js-jsx--goto-outermost-enclosing-curly limit)
2639 (get-text-property (point) 'js-jsx-expr-attribute)))
2640
2578(defvar js-jsx--indent-col nil 2641(defvar js-jsx--indent-col nil
2579 "Baseline column for JS indentation within JSX.") 2642 "Baseline column for JS indentation within JSX.")
2580 2643
2581(defvar js-jsx--indent-attribute-line nil 2644(defvar js-jsx--indent-attribute-line nil
2582 "Line relative to which indentation uses JSX as a baseline.") 2645 "Line relative to which indentation uses JSX as a baseline.")
2583 2646
2647(defun js-jsx--expr-indentation (parse-status pos col)
2648 "Indent using PARSE-STATUS; relative to POS, use base COL.
2649To indent a JSXExpressionContainer’s expression, calculate the JS
2650indentation, using JSX indentation as the base column when
2651indenting relative to the beginning line of the
2652JSXExpressionContainer’s JSXAttribute (if any)."
2653 (let* ((js-jsx--indent-col col)
2654 (js-jsx--indent-attribute-line
2655 (if pos (line-number-at-pos pos))))
2656 (js--proper-indentation parse-status)))
2657
2584(defun js-jsx--indentation (parse-status) 2658(defun js-jsx--indentation (parse-status)
2585 "Helper function for `js--proper-indentation'. 2659 "Helper function for `js--proper-indentation'.
2586Return the proper indentation of the current line if it is part 2660Return the proper indentation of the current line if it is part
@@ -2605,74 +2679,16 @@ return nil."
2605 (and 2679 (and
2606 (= beg-line current-line) 2680 (= beg-line current-line)
2607 (or (not curly-pos) (> (point) curly-pos))))))) 2681 (or (not curly-pos) (> (point) curly-pos)))))))
2682 ;; When on the second or later line of JSX, indent as JSX,
2683 ;; possibly switching back to JS indentation within
2684 ;; JSXExpressionContainers, possibly using the JSX as a base
2685 ;; column while switching back to JS indentation.
2608 (when (and context (> current-line beg-line)) 2686 (when (and context (> current-line beg-line))
2609 (save-excursion 2687 (save-excursion
2610 ;; The column calculation is based on `sgml-calculate-indent'. 2688 (setq col (js-jsx--contextual-indentation current-line context)))
2611 (setq col (pcase (nth 0 context)
2612
2613 ('string
2614 ;; Go back to previous non-empty line.
2615 (while (and (> (point) (nth 1 context))
2616 (zerop (forward-line -1))
2617 (looking-at "[ \t]*$")))
2618 (if (> (point) (nth 1 context))
2619 ;; Previous line is inside the string.
2620 (current-indentation)
2621 (goto-char (nth 1 context))
2622 (1+ (current-column))))
2623
2624 ('tag
2625 ;; Special JSX indentation rule: a “dangling”
2626 ;; closing angle bracket on its own line is
2627 ;; indented at the same level as the opening
2628 ;; angle bracket of the JSXElement. Otherwise,
2629 ;; indent JSXAttribute space like SGML.
2630 (if (progn
2631 (goto-char (nth 2 context))
2632 (and (= current-line (line-number-at-pos))
2633 (looking-back "^\\s-*/?>" (line-beginning-position))))
2634 (progn
2635 (goto-char (nth 1 context))
2636 (current-column))
2637 ;; Indent JSXAttribute space like SGML.
2638 (goto-char (nth 1 context))
2639 ;; Skip tag name:
2640 (skip-chars-forward " \t")
2641 (skip-chars-forward "^ \t\n")
2642 (skip-chars-forward " \t")
2643 (if (not (eolp))
2644 (current-column)
2645 ;; This is the first attribute: indent.
2646 (goto-char (+ (nth 1 context) js-jsx-attribute-offset))
2647 (+ (current-column) js-indent-level))))
2648
2649 ('text
2650 ;; Indent to reflect nesting.
2651 (goto-char (nth 1 context))
2652 (+ (current-column)
2653 ;; The last line isn’t nested, but the rest are.
2654 (if (or (not (nth 2 context)) ; Unclosed.
2655 (< current-line (line-number-at-pos (nth 2 context))))
2656 js-indent-level
2657 0)))
2658
2659 )))
2660 ;; To indent a JSXExpressionContainer’s expression, calculate
2661 ;; the JS indentation, possibly using JSX indentation as the
2662 ;; base column.
2663 (if expr-p 2689 (if expr-p
2664 (let* ((js-jsx--indent-col col) 2690 (js-jsx--expr-indentation
2665 (expr-attribute-pos 2691 parse-status (js-jsx--expr-attribute-pos curly-pos (nth 1 context)) col)
2666 (save-excursion
2667 (goto-char curly-pos) ; Skip first curly.
2668 ;; Skip any remaining enclosing curlies up until
2669 ;; the contextual JSXElement’s beginning position.
2670 (js-jsx--goto-outermost-enclosing-curly (nth 1 context))
2671 (get-text-property (point) 'js-jsx-expr-attribute)))
2672 (js-jsx--indent-attribute-line
2673 (when expr-attribute-pos
2674 (line-number-at-pos expr-attribute-pos))))
2675 (js--proper-indentation parse-status))
2676 col)))) 2692 col))))
2677 2693
2678(defun js--proper-indentation (parse-status) 2694(defun js--proper-indentation (parse-status)