branch: externals/phps-mode commit b99da6bd92c69c622078c18a99f6b71485cecab7 Author: Christian Johansson <christ...@cvj.se> Commit: Christian Johansson <christ...@cvj.se>
Starting using new indentation calculation for indentations --- phps-mode-functions.el | 390 +++++-------------------------------------------- 1 file changed, 34 insertions(+), 356 deletions(-) diff --git a/phps-mode-functions.el b/phps-mode-functions.el index fb3f594..4d856ed 100644 --- a/phps-mode-functions.el +++ b/phps-mode-functions.el @@ -31,6 +31,9 @@ (defvar phps-mode-functions-buffer-changes-start nil "Start point of buffer changes, nil if none.") +(defvar phps-mode-functions-lines-indent nil + "The indentation of each line in buffer, nil if none.") + ;; NOTE Also format white-space inside the line, i.e. after function declarations? ;; TODO Add support for automatic parenthesis, bracket, square-bracket, single-quote and double-quote encapsulations @@ -273,146 +276,36 @@ (defun phps-mode-functions-indent-line () "Indent line." - (let ((data (phps-mode-functions-get-current-line-data)) - (line-start (line-beginning-position))) - (let* ((start (nth 0 data)) - (end (nth 1 data)) - (in-scripting (nth 0 start))) - - ;; Are we in scripting? - (when in-scripting - (let ((start-curly-bracket-level (nth 1 start)) - (start-round-bracket-level (nth 2 start)) - (start-square-bracket-level (nth 3 start)) - (start-inline-control-structure-level (nth 4 start)) - (start-alternative-control-structure-level (nth 5 start)) - (start-token-number (nth 6 start)) - (end-curly-bracket-level (nth 1 end)) - (end-round-bracket-level (nth 2 end)) - (end-square-bracket-level (nth 3 end)) - (end-inline-control-structure-level (nth 4 end)) - (end-alternative-control-structure-level (nth 5 end)) - (end-token-number (nth 6 end)) - (in-doc-comment (nth 7 start))) - (let* ((indent-start (+ start-curly-bracket-level start-round-bracket-level start-square-bracket-level start-inline-control-structure-level start-alternative-control-structure-level)) - (indent-end (+ end-curly-bracket-level end-round-bracket-level end-square-bracket-level end-inline-control-structure-level end-alternative-control-structure-level)) - (indent-level indent-start) - (indent-adjust 0)) - ;; (message "indent-start %s, indent-end %s" indent-start indent-end) - - ;; When bracket count at start is larger than bracket count at end - (when (and - (boundp 'phps-mode-lexer-tokens) - start-token-number - end-token-number) - (let ((token-number start-token-number) - (valid-tokens t) - (last-token-is-opening-curly-bracket nil) - (first-token-is-closing-curly-bracket nil) - (tokens phps-mode-lexer-tokens) - (is-first-line-token t)) - - ;; (message "token start %s, token end %s" start-token-number end-token-number) - ;; (message "First token %s, last token %s" (car (nth start-token-number tokens)) (car (nth end-token-number tokens))) - - ;; Interate tokens in line and check if all are valid - (while (and valid-tokens - (<= token-number end-token-number)) - (let ((token (car (nth token-number tokens))) - (token-start (car (cdr (nth token-number tokens)))) - (token-end (cdr (cdr (nth token-number tokens))))) - - ;; Does token start on or after current line - ;; or does it end on or after current line? - (when (or (>= token-start line-start) - (>= token-end line-start)) - - ;; Is it the last token and is it a opening brace? - (when (and (= token-number end-token-number) - (string= token "{")) - (setq last-token-is-opening-curly-bracket t)) - - ;; Is it the first line token? - (when is-first-line-token - (setq is-first-line-token nil) - - ;; Is it a closing brace? - (when (or (string= token "}") - (eq token 'T_ELSE) - (eq token 'T_ELSEIF)) - (setq first-token-is-closing-curly-bracket t))) - - (when (and valid-tokens - (not (or - (string= token "{") - (string= token "}") - (string= token "(") - (string= token ")") - (string= token "[") - (string= token "]") - (string= token ";") - (string= token ",") - (eq token 'T_CLOSE_TAG)))) - ;; (message "Token %s - %s in %s was invalid, line start %s" token token-number tokens line-start) - (setq valid-tokens nil)) - - ) - - (setq token-number (1+ token-number)))) - - (if valid-tokens - (progn - - ;; If last token is a opening brace indent line one lesser column - (when last-token-is-opening-curly-bracket - ;; (message "Last token was opening brace") - (setq indent-level (- indent-level 1))) - - ;; (message "Tokens was valid, decreasing indent %s - %s" (line-beginning-position) (line-end-position)) - (setq indent-level (- indent-level (- indent-start indent-end)))) - - - ;; If first token is a closing brace indent line one lesser column - (when first-token-is-closing-curly-bracket - ;; (message "First token was closing brace") - (setq indent-level (- indent-level 1)))) - - )) - - ;; If this line is part of a doc-comment increase indent with one unit - (when in-doc-comment - (setq indent-adjust 1)) - - (let ((indent-sum (+ (* indent-level tab-width) indent-adjust)) - (current-indentation (current-indentation))) - - (when (null current-indentation) - (setq current-indentation 0)) - - ;; Only continue if current indentation is wrong - (unless (equal indent-sum current-indentation) - (let ((indent-diff (- indent-sum current-indentation))) - ;; (message "Indenting to %s current column %s" indent-sum (current-indentation)) - ;; (message "inside scripting, start: %s, end: %s, indenting to column %s " start end indent-level) - - (indent-line-to indent-sum) - - ;; When indent is changed the trailing tokens and states just need to adjust their positions, this will improve speed of indent-region a lot - (phps-mode-lexer-move-tokens line-start indent-diff) - (phps-mode-lexer-move-states line-start indent-diff) - ;; (message "Moving tokens and states %s, %s to %s" indent-diff current-indentation indent-sum) - - ;; ;; Set point of change if it's not set or if it's larger than current point - ;; (when (or (not phps-mode-functions-buffer-changes-start) - ;; (< line-start phps-mode-functions-buffer-changes-start)) - ;; ;; (message "Setting changes start from %s to %s" phps-mode-functions-buffer-changes-start start) - ;; (setq phps-mode-functions-buffer-changes-start line-start)) - - ;; (phps-mode-lexer-run-incremental) - - ))))))))) - -;; TODO Fix flycheck error here + ;; Set lines indent if not set + (unless (and (boundp 'phps-mode-functions-lines-indent) + phps-mode-functions-lines-indent) + (setq phps-mode-functions-lines-indent (phps-mode-functions-get-lines-indent))) + + (when phps-mode-functions-lines-indent + (let ((indent (gethash (line-number-at-pos (point)) phps-mode-functions-lines-indent))) + (when indent + ;; (message "indent: %s %s %s" indent (car indent) (car (cdr indent))) + (let ((indent-sum (+ (* (car indent) tab-width) (car (cdr indent)))) + (current-indentation (current-indentation)) + (line-start (line-beginning-position))) + + (when (null current-indentation) + (setq current-indentation 0)) + + ;; Only continue if current indentation is wrong + (unless (equal indent-sum current-indentation) + (let ((indent-diff (- indent-sum current-indentation))) + ;; (message "Indenting to %s current column %s" indent-sum (current-indentation)) + ;; (message "inside scripting, start: %s, end: %s, indenting to column %s " start end indent-level) + + (indent-line-to indent-sum) + + ;; When indent is changed the trailing tokens and states just need to adjust their positions, this will improve speed of indent-region a lot + (phps-mode-lexer-move-tokens line-start indent-diff) + (phps-mode-lexer-move-states line-start indent-diff) + + ))))))) + (defun phps-mode-functions-after-change (start _stop _length) "Track buffer change from START to STOP with length LENGTH." (when (string= major-mode "phps-mode") @@ -438,222 +331,6 @@ ;; TODO Support switch case as well ;; TODO Keep track of assignments as well -(defun phps-mode-functions-get-current-line-data () - "Return information about current line in tokens. - -1. Iterate from beginning of buffer up till start of current line. -2a. If current line has no tokens, return nil -2b. If current line has tokens, return information about: -* Sum of different kinds of open brackets: curly, round and square. -* The sum of open alternative control structures -* The sum of open inline control structures -* The sum of open assignments -* The current lines tokens -* Whether current line is inside scripting or not -* Whether current line is inside a doc comment block or not -* Whether current line is inside a HEREDOC block or not -* Whether current line is inside a NOWDOC block or not." - - ;; (message "Point: %s in %s" (point) phps-mode-lexer-tokens) - (when (boundp 'phps-mode-lexer-tokens) - (save-excursion - (beginning-of-line) - (let ((line-beginning (point)) - (line-end (line-end-position)) - (start-in-scripting nil) - (start-curly-bracket-level 0) - (start-round-bracket-level 0) - (start-square-bracket-level 0) - (start-inline-control-structure-level 0) - (start-alternative-control-structure-level 0) - (start-token-number nil) - (end-in-scripting nil) - (end-curly-bracket-level 0) - (end-round-bracket-level 0) - (end-square-bracket-level 0) - (end-inline-control-structure-level 0) - (end-alternative-control-structure-level 0) - (end-token-number nil) - (line-in-doc-comment nil) - (found-line-tokens nil) - (after-special-control-structure nil) - (round-brace-level 0) - (start-expecting-semi-colon nil) - (end-expecting-semi-colon nil) - (first-token-on-line nil)) - (catch 'stop-iteration - (dolist (item phps-mode-lexer-tokens) - (let ((token (car item)) - (token-start (car (cdr item))) - (token-end (cdr (cdr item)))) - ;; (message "Token: %s Start: %s End: %s Item: %s" token start end item) - - ;; Does token start after the end of line? - break - (when (> token-start line-end) - ;; (message "Stopping iteration at: %s %s" start position) - (throw 'stop-iteration nil)) - - ;; Keep track of general round brace level - (when (string= token "(") - (setq round-brace-level (1+ round-brace-level))) - (when (string= token ")") - (setq round-brace-level (1- round-brace-level))) - - ;; Did we find any token on current line? - flag t - (when (and (not found-line-tokens) - (>= token-start line-beginning) - (<= token-end line-end)) - (setq found-line-tokens t)) - - ;; When end of token is equal or less to beginning of current line - (when (<= token-end line-beginning) - - ;; Increment start token number - (if (null start-token-number) - (setq start-token-number 0) - (setq start-token-number (1+ start-token-number))) - - (pcase token - ('T_OPEN_TAG (setq start-in-scripting t)) - ('T_OPEN_TAG_WITH_ECHO (setq start-in-scripting t)) - ('T_CLOSE_TAG (setq start-in-scripting nil)) - ('T_CURLY_OPEN (setq start-curly-bracket-level (1+ start-curly-bracket-level))) - ('T_DOLLAR_OPEN_CURLY_BRACES (setq start-curly-bracket-level (1+ start-curly-bracket-level))) - ("{" (setq start-curly-bracket-level (1+ start-curly-bracket-level))) - ("}" (setq start-curly-bracket-level (1- start-curly-bracket-level))) - ("[" (setq start-square-bracket-level (1+ start-square-bracket-level))) - ("]" (setq start-square-bracket-level (1- start-square-bracket-level))) - ("(" (setq start-round-bracket-level (1+ start-round-bracket-level))) - (")" (setq start-round-bracket-level (1- start-round-bracket-level))) - (_)) - - ;; Did we encounter end of an alternative control structure? - (when (or (equal token 'T_ENDIF) - (equal token 'T_ENDWHILE) - (equal token 'T_ENDFOR) - (equal token 'T_ENDFOREACH) - (equal token 'T_ENDSWITCH)) - (setq start-alternative-control-structure-level (1- start-alternative-control-structure-level))) - - ;; Reduce inline control structure level when we encounter a semi-colon after it's opening - (when (and start-expecting-semi-colon - (string= token ";")) - (setq start-inline-control-structure-level (1- start-inline-control-structure-level)) - (setq start-expecting-semi-colon nil))) - - ;; Are we at the final line and inside a doc-comment that ends after it? - (when (and (< token-start line-beginning) - (>= token-end line-end) - (eq token 'T_DOC_COMMENT)) - (setq line-in-doc-comment t)) - - ;; When start of token is equal or less to end of current line - (when (<= token-start line-end) - - ;; Increment end token number - (if (null end-token-number) - (setq end-token-number 0) - (setq end-token-number (1+ end-token-number))) - - (pcase token - ('T_OPEN_TAG (setq end-in-scripting t)) - ('T_OPEN_TAG_WITH_ECHO (setq end-in-scripting t)) - ('T_CLOSE_TAG (setq end-in-scripting nil)) - ('T_CURLY_OPEN (setq end-curly-bracket-level (1+ end-curly-bracket-level))) - ('T_DOLLAR_OPEN_CURLY_BRACES (setq end-curly-bracket-level (1+ end-curly-bracket-level))) - ("{" (setq end-curly-bracket-level (1+ end-curly-bracket-level))) - ("}" (setq end-curly-bracket-level (1- end-curly-bracket-level))) - ("[" (setq end-square-bracket-level (1+ end-square-bracket-level))) - ("]" (setq end-square-bracket-level (1- end-square-bracket-level))) - ("(" (setq end-round-bracket-level (1+ end-round-bracket-level))) - (")" (setq end-round-bracket-level (1- end-round-bracket-level))) - (_)) - - ;; Do we encounter first token on current line? - (when (and (not first-token-on-line) - (>= token-start line-beginning) - (<= token-start line-end)) - (setq first-token-on-line end-token-number)) - - ;; Did we encounter end of alternative control structure? - (when (or (equal token 'T_ENDIF) - (equal token 'T_ENDWHILE) - (equal token 'T_ENDFOR) - (equal token 'T_ENDFOREACH) - (equal token 'T_ENDSWITCH)) - (when (and first-token-on-line - (= first-token-on-line end-token-number)) - (setq start-alternative-control-structure-level (1- start-alternative-control-structure-level))) - (setq end-alternative-control-structure-level (1- end-alternative-control-structure-level))) - - ;; Reduce inline control structure level when we encounter a semi-colon after it's opening - (when (and end-expecting-semi-colon - (string= token ";")) - (setq end-inline-control-structure-level (- end-inline-control-structure-level 1)) - (setq end-expecting-semi-colon nil))) - - ;; Are we after a special control structure - ;; and does the round bracket level match initial round bracket level - ;; and is token not a round bracket - (when (and after-special-control-structure - (= after-special-control-structure round-brace-level) - (not (string= token ")")) - (not (string= token "("))) - - ;; Is token not a curly bracket - because that is a ordinary control structure syntax - (unless (string= token "{") - ;; (message "After special control structure %s in buffer: %s tokens: %s token-start: %s" token (buffer-substring-no-properties (point-min) (point-max)) phps-mode-lexer-tokens token-start) - (if (string= token ":") - (progn - ;; (message "Was colon") - - ;; Is token at or before line beginning? - (when (or (<= token-end line-beginning) - (and first-token-on-line - (= first-token-on-line end-token-number))) - (setq start-alternative-control-structure-level (1+ start-alternative-control-structure-level))) - - ;; Is token at or before line end? - (when (<= token-start line-end) - (setq end-alternative-control-structure-level (1+ end-alternative-control-structure-level))) - - ) - - (when (or (<= token-end line-beginning) - (and first-token-on-line - (= first-token-on-line end-token-number))) - (setq start-inline-control-structure-level (1+ start-inline-control-structure-level)) - (setq start-expecting-semi-colon t)) - - - (when (<= token-start line-end) - (setq end-inline-control-structure-level (1+ end-inline-control-structure-level)) - (setq end-expecting-semi-colon t)) - - ;; (message "Was not colon") - )) - - (setq after-special-control-structure nil)) - - ;; Does current token support inline and alternative syntax? - (when (or - (equal token 'T_IF) - (equal token 'T_WHILE) - (equal token 'T_CASE) - (equal token 'T_DEFAULT) - (equal token 'T_FOR) - (equal token 'T_FOREACH) - (equal token 'T_SWITCH) - (equal token 'T_ELSE) - (equal token 'T_ELSEIF)) - (setq after-special-control-structure round-brace-level))))) - - (unless found-line-tokens - (setq start-token-number nil) - (setq end-token-number nil)) - (let ((data (list (list start-in-scripting start-curly-bracket-level start-round-bracket-level start-square-bracket-level start-inline-control-structure-level start-alternative-control-structure-level start-token-number line-in-doc-comment) (list end-in-scripting end-curly-bracket-level end-round-bracket-level end-square-bracket-level end-inline-control-structure-level end-alternative-control-structure-level end-token-number line-in-doc-comment)))) - data))))) - (defun phps-mode-functions-init () "PHP specific init-cleanup routines." @@ -672,6 +349,7 @@ ) (set (make-local-variable 'phps-mode-functions-buffer-changes-start) nil) + (set (make-local-variable 'phps-mode-functions-lines-indent) nil) (add-hook 'after-change-functions #'phps-mode-functions-after-change)