branch: externals/phps-mode commit 0ca0e447b8a0be631fa6556c0ce2ad5fd763b7cd Author: Christian Johansson <christ...@cvj.se> Commit: Christian Johansson <christ...@cvj.se>
Improved indentation on lines starting with a closing bracket --- phps-mode-indent.el | 1664 +++++++++++++++++++++++++-------------------------- 1 file changed, 832 insertions(+), 832 deletions(-) diff --git a/phps-mode-indent.el b/phps-mode-indent.el index 457c4693be..d2d57c52e8 100644 --- a/phps-mode-indent.el +++ b/phps-mode-indent.el @@ -631,34 +631,154 @@ new-indentation (+ new-indentation tab-width))) - ;; LINE AFTER LINE THAT ENDS WITH CLOSING BRACKET - ;; function myFunction($key, - ;; $value) - ;; { + ;; LINE THAT ENDS BRACKET + ;; switch ($condition) { + ;; case true: + ;; echo 'here'; + ;; } + (current-line-starts-with-closing-bracket + (setq + match-type + 'line-that-ends-bracket) + (let ((old-point (point)) + (still-looking t) + (bracket-start-line) + (bracket-level -1)) + + ;; Should keep track of brackets + ;; and stop when we reach the correct bracket + (while (and + still-looking + (search-backward-regexp "[][{}()]" nil t)) + (let ((match (match-string-no-properties 0))) + (cond + ((or + (string= "{" match) + (string= "(" match) + (string= "[" match)) + (setq + bracket-level + (1+ bracket-level))) + (t + (setq + bracket-level + (1- bracket-level)))) + + (when (= bracket-level 0) + (setq + still-looking + nil) + (setq + bracket-start-line + (buffer-substring-no-properties + (line-beginning-position) + (line-end-position)))))) + + (goto-char old-point) + + (unless still-looking + (setq + new-indentation + (phps-mode-indent--string-indentation + bracket-start-line))))) + + ;; LINE THAT ENDS ALTERNATIVE SWITCH BLOCK + ;; switch (blala): + ;; case bla: + ;; echo 'bla'; + ;; endswitch; + ((and + (string-match-p + "^[\t ]*endswitch[\t ]*;[\t ]*$" + current-line-string) + (not + (string-match-p + "^[\t ]*switch" + previous-line-string))) + (setq + match-type + 'line-that-ends-alternative-switch-block) + (setq + new-indentation + (- new-indentation tab-width tab-width))) + + ;; NEW CASE AFTER CASE DEFINITION + ;; case true: + ;; echo 'here'; + ;; case false: ;; or - ;; (is_array($data) - ;; && !empty($data['index']) - ;; && (is_a($data['index'], 'Index') - ;; || is_a($data['Index'], 'Index2'))) - ;; || is_a($data, 'WC_Index') - (previous-line-ends-with-closing-bracket + ;; case true: + ;; echo 'here'; + ;; default: + ((and + (not previous-line-ends-with-opening-bracket) + (not (string-match-p ":[\t ]*$" previous-line-string)) + (or + (string-match-p + "^[\t ]*case[\t ]+.*\\(;\\|:\\)[\t ]*$" + current-line-string) + (string-match-p + "^[\t ]*default.*\\(;\\|:\\)[\t ]*$" + current-line-string))) (setq match-type - 'line-after-line-that-ends-with-closing-bracket) - ;; Backtrack to line were bracket started - ;; and use indentation from that line for this line + 'line-after-case-definition) + (setq + new-indentation + (- new-indentation tab-width))) + + ;; LINE AFTER ENDING OF BRACKET AND COMMA + ;; return array( + ;; '' => __( + ;; 'None', + ;; 'domain' + ;; ), + ;; '-' => + ;; or + ;; return [ + ;; [ + ;; '25' + ;; ], + ;; 25 + ;; or + ;; if (myFunction( + ;; random(), + ;; heredom(), + ;; or + ;; 'name' => + ;; $myObject->getName(), + ;; 'age' => + ;; or + ;; myFunction( + ;; 'my Argument', + ;; 'my second argument' + ;; or + ;; myFunction( + ;; [ + ;; 2, + ;; 3, + ((string-match-p + ",[\t ]*\\(\\?>[\t\n ]*\\)?$" + previous-line-string) + (setq + match-type + 'line-after-ending-of-bracket-and-comma) + + ;; Backtrack first to line were bracket started + ;; and use indentation from that line from that line (forward-line (* -1 move-length1)) (end-of-line) - (let ((not-found t) + (search-backward-regexp "," nil t) ;; Skip trailing comma + (let ((not-found-bracket-start t) (reference-line) - (reference-line2) - (reference-indentation) + (found-colon) + (reference-line-started-bracket) (parenthesis-level 0)) (while (and - not-found + not-found-bracket-start (search-backward-regexp - "[][(){}]" + "\\([][(),]\\|=>\\)" nil t)) (let ((match (match-string-no-properties 0))) @@ -666,356 +786,405 @@ ((or (string= "(" match) - (string= "[" match) - (string= "{" match)) + (string= "[" match)) (setq parenthesis-level (1+ parenthesis-level)) - (when (= parenthesis-level 0) + (when (= parenthesis-level 1) + (unless found-colon + (setq + reference-line-started-bracket + t) + (setq + reference-line + (buffer-substring-no-properties + (line-beginning-position) + (line-end-position)))) (setq - not-found + not-found-bracket-start nil))) ((or (string= ")" match) - (string= "]" match) - (string= "}" match)) + (string= "]" match)) (setq parenthesis-level - (1- parenthesis-level)) + (1- parenthesis-level))) + + ;; The second occurence of a colon + ;; is a significant marker of + ;; a starting bracket row + ((string= "," match) + (when (= parenthesis-level 0) + (if found-colon + (setq + not-found-bracket-start + nil) + (setq + found-colon + t) + (setq + reference-line + (buffer-substring-no-properties + (line-beginning-position) + (line-end-position)))))) + + ;; The first occurrence of a => + ;; is a significant marker of + ;; a starting bracket row + ((string= "=>" match) (when (= parenthesis-level 0) (setq - not-found + reference-line + (buffer-substring-no-properties + (line-beginning-position) + (line-end-position))) + (setq + not-found-bracket-start nil))) ))) - (unless not-found - (setq - reference-line - (buffer-substring-no-properties - (line-beginning-position) - (line-end-position))) - (setq - reference-line2 - (buffer-substring-no-properties - (point) - (line-end-position))) + + (when reference-line + ;; (message "reference-line-2: %S" reference-line) (setq - reference-indentation + new-indentation (phps-mode-indent--string-indentation reference-line)) + (when reference-line-started-bracket + (let ((reference-bracket-level + (phps-mode-indent--get-string-brackets-count + reference-line))) + ;; (message "reference-bracket-level: %S" reference-bracket-level) + ;; define('_PRIVATE_ROOT', + ;; 'here'); + ;; or + ;; ['abc', + ;; 'def']; + (when (> reference-bracket-level 0) + (setq + new-indentation + (+ new-indentation tab-width))))) + ) + + (when current-line-starts-with-closing-bracket (setq new-indentation - reference-indentation) - (let ((reference-bracket-level - (phps-mode-indent--get-string-brackets-count - reference-line)) - (reference-bracket-level2 - (phps-mode-indent--get-string-brackets-count - reference-line2)) - (reference-contains-assignment - (string-match-p - "^[\t ]*$[a-zA-Z0-9_]+[\t ]*[^=!]*=\\($\\|[\t ]+.*[^,;]$\\)" - reference-line))) - ;; if ( - ;; (is_array($data) - ;; && !empty($data['index']) - ;; && (is_a($data['index'], 'Index') - ;; || is_a($data['Index'], 'Index2'))) - ;; || is_a($data, 'WC_Index') - ;; or - ;; $copies = method_exists($object, 'get_copies') - ;; ? true - ;; (message "reference-bracket-level: %S" reference-bracket-level) - ;; (message "reference-bracket-level2: %S" reference-bracket-level2) - - (when (or - reference-contains-assignment - (and - (> reference-bracket-level 0) - (> reference-bracket-level reference-bracket-level2))) - (setq - new-indentation - (+ new-indentation tab-width)))) + (- new-indentation tab-width)))) - (when current-line-starts-with-closing-bracket - (setq - new-indentation - (- new-indentation tab-width))) - - ) - - (goto-char point)) - - ) + (goto-char point)) - ;; LINE AFTER OPENING MULTI-LINE ASSIGNMENT - ;; $var = 'A line' . - ;; 'something'; + ;; LINE AFTER ENDING OF COMMAND + ;; $var .= + ;; 'hello'; + ;; echo 'here'; ;; or - ;; $var .= 'A line' . - ;; 'something' + ;; $var = + ;; 25; + ;; echo 'here'; ;; or - ;; $var += 35 + - ;; 77 - ;; but ignore - ;; $var === true + ;; $var = array( + ;; 'here' + ;; ); + ;; echo 'here'; ;; or - ;; $var == 3 + ;; $var = <<<EOD + ;; OKASDOKASD + ;; EOD; + ;; echo 'here'; ;; or - ;; $argument1 = 3, - ;; $argument2 = 4 + ;; $var = myFunction( + ;; 'expression'); + ;; echo 'here'; ;; or - ;; function myFunction( - ;; $abc = 3 - ;; ) { + ;; return myFunction( + ;; 'expression'); + ;; echo 'here'; ;; or - ;; $abc != 3 + ;; define('_PRIVATE_ROOT_', + ;; 'here'); + ;; echo 'here'; ((and - (string-match-p - "^[\t ]*$[a-zA-Z0-9_]+[\t ]*[^=!]*=\\($\\|[\t ]+.*[^,;]$\\)" - previous-line-string) + previous-line-ends-with-terminus + (string= previous-line-ends-with-terminus ";") (not - current-line-starts-with-closing-bracket)) + (string-match-p + "^[\t ]*\\(echo[\t ]+\\|print[\t ]+\\)" + previous-line-string))) (setq match-type - 'line-after-opening-multiline-assignment) - (setq - new-indentation - (+ new-indentation tab-width))) + 'line-after-ending-of-command) - ;; LINE THAT ENDS BRACKET AND COMMAND - ;; $variable = array( - ;; 'random' => - ;; 'hello' - ;; ); - ;; or - ;; $variable = [ - ;; 'random' => - ;; 'hello' - ;; ]; - ((string-match-p - "^[\t ]*\\()\\|]\\);[\t ]*$" - current-line-string) - (setq - match-type - 'line-that-ends-bracket-and-command) - (let ((old-point (point)) - (still-looking t) - (bracket-count -1)) + ;; Back-trace buffer from previous line + ;; Determine if semi-colon ended an multi-line assignment or bracket-less command or not + ;; If it's on the same line we ignore it + (forward-line (* -1 move-length1)) + (end-of-line) + (search-backward-regexp ";" nil t) ;; Skip the semi-colon - ;; Try to backtrack buffer until we reach start of bracket + (let ((not-found t) + (is-assignment nil) + (is-string-doc) + (is-function-call) + (parenthesis-level 0) + (is-bracket-less-command nil) + (is-same-line-p t) + (bracket-opened-on-first-line)) (while (and - still-looking + not-found (search-backward-regexp - "\\((\\|]\\|\\[\\|)\\)" nil t)) - (let ((match-string (match-string-no-properties 0))) + "\\(;\\|{\\|[a-zA-Z_]+[a-zA-Z0-9_]*[\t ]*(\\|)\\|=$\\|=[^>]\\|return\\|echo[\t ]+\\|print[\t ]+\\|\n\\|<<<'?\"?[a-zA-Z0-9_]+'?\"?\\)" + nil + t)) + (let ((match (match-string-no-properties 0))) (cond - ((or - (string= match-string "(") - (string= match-string "[")) - (setq bracket-count (1+ bracket-count))) - ((or - (string= match-string ")") - (string= match-string "]")) - (setq bracket-count (1- bracket-count))))) - (when (= bracket-count 0) - (setq still-looking nil))) - - ;; Did we find bracket start line? - (unless still-looking - (let ((bracket-start-indentation - (phps-mode-indent--string-indentation - (buffer-substring-no-properties - (line-beginning-position) - (line-end-position))))) - ;; Use its indentation for this line as well - (setq - new-indentation - bracket-start-indentation))) - ;; Reset point - (goto-char old-point))) + ((string= match "\n") + (setq is-same-line-p nil)) - ;; LINE THAT CONTINUES MULTI-LINE CONCATENATION - ;; echo 'Something' - ;; . 'more'; - ;; or - ;; echo - ;; 'Something' - ;; . 'more'; - ;; or - ;; echo 'Something' . - ;; 'more'; - ;; or - ;; echo - ;; 'Something' . - ;; 'more'; - ((or - (string-match-p - "^[\t ]*\\." - current-line-string) - (string-match-p - "\\.[\t ]*$" - previous-line-string)) - (setq - match-type - 'line-that-continues-multi-line-concatenation) + ((string-match-p + "<<<'?\"?[a-zA-Z0-9_]+'?\"?" + match) + (setq + is-string-doc + t) + (setq + not-found + nil)) - ;; If previous line matched ending . - ;; we must backtrack at least two lines - ;; to find a good reference indentation - (let ((old-point (point)) - (match-string) - (previous-concatenation) - (keep-searching 1) - (concat-was-trailing-p - (string-match-p - "\\.[\t ]*$" - previous-line-string)) - (previous-concatenation2)) - (when concat-was-trailing-p - (setq - keep-searching - 2)) - (while keep-searching - (let ((previous-expression - (search-backward-regexp - "\\(^[\t ]*\\.\\|\\.[\t ]*$\\|[{}=;]\\)" nil t))) - (if previous-expression - (progn - (setq - match-string - (match-string-no-properties 0)) - (if (string-match-p - "[{}=;]" - match-string) - (setq - keep-searching - nil) - (setq - keep-searching - (1- keep-searching)) - (when (= keep-searching 0) - (setq - keep-searching - nil) - (when concat-was-trailing-p - (goto-char previous-concatenation2)) - (setq - previous-concatenation - match-string)) - (setq - previous-concatenation2 - (point)))) + ((string-match-p + "[a-zA-Z_]+[a-zA-Z0-9_]*[\t ]*(" + match) (setq - keep-searching - nil)))) + parenthesis-level + (1+ parenthesis-level)) + (when (= parenthesis-level 0) + (setq + is-function-call + t) + (setq + not-found + nil))) - (if previous-concatenation - (let ((first-concatenated-line-indent - (phps-mode-indent--string-indentation - (buffer-substring-no-properties - (line-beginning-position) - (line-end-position))))) - ;; We use previous concatenated lines indent + ((string= match ")") (setq - new-indentation - first-concatenated-line-indent))) + parenthesis-level + (1- parenthesis-level))) - ;; Reset point - (goto-char old-point))) + ((= parenthesis-level 0) + (setq is-assignment (string-match-p "=" match)) + (setq is-bracket-less-command + (string-match-p + "\\(echo[\t ]+\\|print[\t ]+\\|return[\t ]+\\)" + match)) + (setq not-found nil))))) - ;; LINE AFTER CASE DEFINITION - ;; case true: - ;; echo 'here'; - ;; or - ;; case true; - ;; echo 'here'; - ;; or - ;; default: - ;; echo 'here'; - ;; or - ;; default; - ;; echo 'here'; + ;; $var = <<<EOD + ;; OKASDOKASD + ;; EOD; + ;; echo 'here'; + (when is-string-doc + (setq + new-indentation + (phps-mode-indent--string-indentation + (buffer-substring-no-properties + (line-beginning-position) + (line-end-position))))) + + ;; When we have an assignment + ;; keep track if bracket was opened on first + ;; line + (when is-assignment + (let ((start-bracket-count + (phps-mode-indent--get-string-brackets-count + (buffer-substring-no-properties + (line-beginning-position) + (line-end-position))))) + ;; (message "start-bracket-count: %S from %S" start-bracket-count (buffer-substring-no-properties + ;; (line-beginning-position) + ;; (line-end-position))) + (setq + bracket-opened-on-first-line + (> start-bracket-count 0)))) + + ;; (message "is-assignment: %S" is-assignment) + ;; (message "bracket-opened-on-first-line: %S" bracket-opened-on-first-line) + + ;; echo 'there' . + ;; 'here'; + ;; echo 'here'; + ;; or + ;; print 'there' . + ;; 'here'; + ;; echo 'here'; + ;; or + ;; $var = + ;; 'opkeokoek'; + ;; echo 'here' + + ;; ignore cases like + ;; $var = array( + ;; 'here' + ;; ); + ;; echo 'here'; + ;; but not cases like + ;; $var = 'abc' + ;; . 'def' . __( + ;; 'okeoke' + ;; ) . 'ere'; + ;; echo 'here'; + ;; NOTE stuff like $var = array(\n 4\n);\n + ;; will end assignment but also decrease previous-bracket-level + ;; NOTE but cases like $var = array(\n 4);\n should pass + (when (and + (not is-same-line-p) + (or + (and + is-assignment + (or + (not bracket-opened-on-first-line) + (not previous-line-starts-with-closing-bracket))) + is-bracket-less-command)) + (setq + new-indentation + (- new-indentation tab-width))) + + ;; define('_PRIVATE_ROOT', + ;; 'here'); + ;; echo 'here'; + ;; but ignore + ;; if (true) { + ;; define('_PRIVATE_ROOT', 'here'); + ;; echo 'here'; + (when (and + is-function-call + (not is-same-line-p)) + (setq + new-indentation + (- new-indentation tab-width))) + + ) + + (goto-char point)) + + ;; LINE AFTER ALTERNATIVE CASE DEFINITION + ;; switch ($array): + ;; case 'Something'; ((and - (not - (string-match-p - "^[\t ]*\\(case[\t ]+\\|default\\)" - current-line-string)) - (or - (string-match-p - "^[\t ]*case[\t ]+.*\\(;\\|:\\)[\t ]*$" - previous-line-string) - (string-match-p - "^[\t ]*default.*\\(;\\|:\\)[\t ]*$" - previous-line-string))) + (string-match-p + "^[\t ]*\\(case.+\\|default\\)\\(;\\|:\\)[\t ]*$" + current-line-string) + (string-match-p + "^[\t ]*\\(switch\\)[\t ]*(.+):$" + previous-line-string)) (setq match-type - 'line-after-case-definition) + 'line-after-alternative-case-definition) (setq new-indentation (+ new-indentation tab-width))) - ;; NEW CASE AFTER CASE DEFINITION - ;; case true: - ;; echo 'here'; - ;; case false: + ;; LINE AFTER ENDING OF DOC-COMMENT + ;; /** + ;; * + ;; */ + ;; echo 'here'; + ((= previous-bracket-level -1) + (setq + match-type + 'line-after-ending-of-doc-comment) + (setq + new-indentation + (1- new-indentation))) + + ;; LINE AFTER STARTING DOC-COMMENT + ;; /** + ;; * + ((= previous-bracket-level 1) + (setq + match-type + 'line-after-opening-doc-comment) + (setq + new-indentation + (+ new-indentation 1))) + + ;; LINE AFTER INCREASE IN BRACKETS + ;; array( + ;; 'here' ;; or - ;; case true: + ;; [[ + ;; 'here' + ;; or + ;; if (something) { ;; echo 'here'; - ;; default: - ((and - (not previous-line-ends-with-opening-bracket) - (not (string-match-p ":[\t ]*$" previous-line-string)) - (or - (string-match-p - "^[\t ]*case[\t ]+.*\\(;\\|:\\)[\t ]*$" - current-line-string) - (string-match-p - "^[\t ]*default.*\\(;\\|:\\)[\t ]*$" - current-line-string))) + ((>= previous-bracket-level tab-width) (setq match-type - 'line-after-case-definition) + 'line-after-increase-in-brackets) (setq new-indentation - (- new-indentation tab-width))) + (+ new-indentation tab-width))) - ;; LINE AFTER ENDING OF BRACKET AND COMMAND - ;; if (true) { - ;; $cacheKey = sprintf( - ;; 'key_%s', - ;; md5(json_encode($key)) - ;; ); - ;; $cache = + ;; LINE AFTER LINE THAT ENDS AND STARTS A BRACKET BLOCK + ;; ) { + ;; echo 'here' ;; or - ;; if (true) { - ;; $cache = - ;; Cache::getInstance(); - ;; echo 'here'; - ((string-match-p - "[])][\t ]*;[\t ]*\\(\\?>[\t\n ]*\\)?$" - previous-line-string) + ;; ][ + ;; 25 + ((and (= previous-bracket-level 0) + previous-line-starts-with-closing-bracket) (setq match-type - 'line-after-ending-of-bracket-and-command) + 'line-after-line-that-ends-and-starts-a-bracket-block) + (setq + new-indentation + (+ new-indentation tab-width))) - ;; Backtrack first to line were bracket started - ;; and then backwards until the line were statement / expression - ;; started and use indentation from that line from that line + ;; LINE THAT STARTS WITH CLOSING BRACKET + ;; [ + ;; 'hello' + ;; ] + ;; or + ;; array( + ;; 'hello' + ;; ) + ;; but ignore + ;; [ + ;; ] + ;; or + ;; array( + ;; ) + ;; or + ;; if ( + ;; myFunction( + ;; 'random') + ;; ) { + ;; but ignore + ;; var_dump(array(<<<EOD + ;; ölöas + ;; EOD + ;; )); + ((and + current-line-starts-with-closing-bracket + (not previous-line-ends-with-opening-bracket)) + (setq + match-type + 'line-that-starts-with-closing-bracket) + + ;; Backtrack to line were bracket started + ;; and use indentation from that line for this line (forward-line (* -1 move-length1)) (end-of-line) - (search-backward-regexp ";" nil t) ;; Skip trailing comma - (let ((not-found-bracket-start t) + (let ((not-found t) (reference-line) - (parenthesis-level 0)) + (reference-indentation) + (parenthesis-level -1)) (while (and - not-found-bracket-start + not-found (search-backward-regexp - "[][()]" + "[][(){}]" nil t)) (let ((match (match-string-no-properties 0))) @@ -1023,209 +1192,119 @@ ((or (string= "(" match) - (string= "[" match)) + (string= "[" match) + (string= "{" match)) (setq parenthesis-level (1+ parenthesis-level)) (when (= parenthesis-level 0) (setq - not-found-bracket-start + not-found nil))) ((or (string= ")" match) - (string= "]" match)) + (string= "]" match) + (string= "}" match)) (setq parenthesis-level (1- parenthesis-level)) (when (= parenthesis-level 0) (setq - not-found-bracket-start + not-found nil))) ))) - - ;; Found line were bracket started? - (unless not-found-bracket-start + (unless not-found (setq reference-line (buffer-substring-no-properties (line-beginning-position) (line-end-position))) - ;; (message "reference-line-1: %S" reference-line) + (setq + reference-indentation + (phps-mode-indent--string-indentation + reference-line))) - ;; Search for first line of statement / expression here - (let ((not-found-command-start t)) - (while - (and - not-found-command-start - (search-backward-regexp - "\\(;\\|}\\|{\\|^[\t ]*[^\t\n ]+.*$\\)" - nil - t)) - (let ((match (match-string-no-properties 1))) - ;; (message "match: %S" match) - (cond - - ;; End of expression / statement - ((or - (string= ";" match) - (string= "}" match) - (string= "{" match)) - (setq - not-found-command-start - nil)) - - ;; Non-empty line - (t - (setq - reference-line - (buffer-substring-no-properties - (line-beginning-position) - (line-end-position)))) - - ))))) - - (when reference-line - ;; (message "reference-line-2: %S" reference-line) - (setq - new-indentation - (phps-mode-indent--string-indentation - reference-line))) + (goto-char point) - (when - (and - current-line-starts-with-closing-bracket - (string= current-line-starts-with-closing-bracket "}")) + (when reference-indentation (setq new-indentation - (- new-indentation tab-width)))) - - (goto-char point)) + reference-indentation)))) - ;; LINE THAT ENDS CURLY BRACKET - ;; switch ($condition) { - ;; case true: - ;; echo 'here'; - ;; } + ;; LINE AFTER LINE INSIDE DOC-COMMENT + ;; /** + ;; * here + ;; but ignore + ;; /** */ + ;; here ((and - current-line-starts-with-closing-bracket - (string= current-line-starts-with-closing-bracket "}")) + previous-line-starts-with-opening-doc-comment + (not previous-line-ends-with-closing-doc-comment)) (setq match-type - 'line-that-ends-curly-bracket) - (let ((old-point (point)) - (still-looking t) - (bracket-start-line) - (curly-bracket-balance -1)) - - ;; Should keep track of brackets - ;; and stop when we reach the correct bracket - (while (and - still-looking - (search-backward-regexp "[{}]" nil t)) - (cond - ((looking-at-p "{") - (setq - curly-bracket-balance - (1+ curly-bracket-balance))) - ((looking-at-p "}") - (setq - curly-bracket-balance - (1- curly-bracket-balance)))) - - (when (= curly-bracket-balance 0) - (setq - still-looking - nil) - (setq - bracket-start-line - (buffer-substring-no-properties - (line-beginning-position) - (line-end-position))))) - - (goto-char old-point) - - (unless still-looking - (let ((reference-indentation - (phps-mode-indent--string-indentation - bracket-start-line))) - (setq - new-indentation - reference-indentation))))) + 'line-after-line-inside-doc-comment) + (setq + new-indentation + (+ new-indentation 1))) - ;; LINE THAT ENDS ALTERNATIVE SWITCH BLOCK - ;; switch (blala): - ;; case bla: - ;; echo 'bla'; - ;; endswitch; + ;; LINE AFTER LINE THAT ENDS WITH ASSIGNMENT + ;; $var = ((and - (string-match-p - "^[\t ]*endswitch[\t ]*;[\t ]*$" - current-line-string) - (not - (string-match-p - "^[\t ]*switch" - previous-line-string))) + previous-line-ends-with-assignment + (<= previous-bracket-level 0)) (setq match-type - 'line-that-ends-alternative-switch-block) + 'line-after-line-that-ends-with-assignment) (setq new-indentation - (- new-indentation tab-width tab-width))) + (+ new-indentation tab-width))) - ;; LINE AFTER ENDING OF BRACKET AND COMMA - ;; return array( - ;; '' => __( - ;; 'None', - ;; 'domain' - ;; ), - ;; '-' => + ;; LINE AFTER LINE THAT ENDS WITH OPENING BRACKET + ;; )) { + ;; echo 'here'; ;; or - ;; return [ - ;; [ - ;; '25' - ;; ], + ;; ]][ ;; 25 - ;; or - ;; if (myFunction( - ;; random(), - ;; heredom(), - ;; or - ;; 'name' => - ;; $myObject->getName(), - ;; 'age' => - ;; or - ;; myFunction( - ;; 'my Argument', - ;; 'my second argument' - ;; or - ;; myFunction( - ;; [ - ;; 2, - ;; 3, - ((string-match-p - ",[\t ]*\\(\\?>[\t\n ]*\\)?$" - previous-line-string) + ((and + previous-line-ends-with-opening-bracket + (< previous-bracket-level 0)) (setq match-type - 'line-after-ending-of-bracket-and-comma) + 'line-after-line-that-ends-with-opening-bracket) + (setq + new-indentation + (+ new-indentation tab-width))) - ;; Backtrack first to line were bracket started - ;; and use indentation from that line from that line + ;; LINE AFTER LINE THAT ENDS WITH CLOSING BRACKET + ;; function myFunction($key, + ;; $value) + ;; { + ;; or + ;; (is_array($data) + ;; && !empty($data['index']) + ;; && (is_a($data['index'], 'Index') + ;; || is_a($data['Index'], 'Index2'))) + ;; || is_a($data, 'WC_Index') + (previous-line-ends-with-closing-bracket + (setq + match-type + 'line-after-line-that-ends-with-closing-bracket) + ;; Backtrack to line were bracket started + ;; and use indentation from that line for this line (forward-line (* -1 move-length1)) (end-of-line) - (search-backward-regexp "," nil t) ;; Skip trailing comma - (let ((not-found-bracket-start t) + (let ((not-found t) (reference-line) - (found-colon) - (reference-line-started-bracket) + (reference-line2) + (reference-indentation) (parenthesis-level 0)) (while (and - not-found-bracket-start + not-found (search-backward-regexp - "\\([][(),]\\|=>\\)" + "[][(){}]" nil t)) (let ((match (match-string-no-properties 0))) @@ -1233,405 +1312,331 @@ ((or (string= "(" match) - (string= "[" match)) + (string= "[" match) + (string= "{" match)) (setq parenthesis-level (1+ parenthesis-level)) - (when (= parenthesis-level 1) - (unless found-colon - (setq - reference-line-started-bracket - t) - (setq - reference-line - (buffer-substring-no-properties - (line-beginning-position) - (line-end-position)))) + (when (= parenthesis-level 0) (setq - not-found-bracket-start + not-found nil))) ((or (string= ")" match) - (string= "]" match)) + (string= "]" match) + (string= "}" match)) (setq parenthesis-level - (1- parenthesis-level))) - - ;; The second occurence of a colon - ;; is a significant marker of - ;; a starting bracket row - ((string= "," match) - (when (= parenthesis-level 0) - (if found-colon - (setq - not-found-bracket-start - nil) - (setq - found-colon - t) - (setq - reference-line - (buffer-substring-no-properties - (line-beginning-position) - (line-end-position)))))) - - ;; The first occurrence of a => - ;; is a significant marker of - ;; a starting bracket row - ((string= "=>" match) + (1- parenthesis-level)) (when (= parenthesis-level 0) (setq - reference-line - (buffer-substring-no-properties - (line-beginning-position) - (line-end-position))) - (setq - not-found-bracket-start + not-found nil))) ))) - - (when reference-line - ;; (message "reference-line-2: %S" reference-line) + (unless not-found (setq - new-indentation + reference-line + (buffer-substring-no-properties + (line-beginning-position) + (line-end-position))) + (setq + reference-line2 + (buffer-substring-no-properties + (point) + (line-end-position))) + (setq + reference-indentation (phps-mode-indent--string-indentation reference-line)) - (when reference-line-started-bracket - (let ((reference-bracket-level - (phps-mode-indent--get-string-brackets-count - reference-line))) - ;; (message "reference-bracket-level: %S" reference-bracket-level) - ;; define('_PRIVATE_ROOT', - ;; 'here'); - ;; or - ;; ['abc', - ;; 'def']; - (when (> reference-bracket-level 0) - (setq - new-indentation - (+ new-indentation tab-width))))) - ) - - (when current-line-starts-with-closing-bracket (setq new-indentation - (- new-indentation tab-width)))) + reference-indentation) + (let ((reference-bracket-level + (phps-mode-indent--get-string-brackets-count + reference-line)) + (reference-bracket-level2 + (phps-mode-indent--get-string-brackets-count + reference-line2)) + (reference-contains-assignment + (string-match-p + "^[\t ]*$[a-zA-Z0-9_]+[\t ]*[^=!]*=\\($\\|[\t ]+.*[^,;]$\\)" + reference-line))) + ;; if ( + ;; (is_array($data) + ;; && !empty($data['index']) + ;; && (is_a($data['index'], 'Index') + ;; || is_a($data['Index'], 'Index2'))) + ;; || is_a($data, 'WC_Index') + ;; or + ;; $copies = method_exists($object, 'get_copies') + ;; ? true + ;; (message "reference-bracket-level: %S" reference-bracket-level) + ;; (message "reference-bracket-level2: %S" reference-bracket-level2) + + (when (or + reference-contains-assignment + (and + (> reference-bracket-level 0) + (> reference-bracket-level reference-bracket-level2))) + (setq + new-indentation + (+ new-indentation tab-width)))) - (goto-char point)) + (when current-line-starts-with-closing-bracket + (setq + new-indentation + (- new-indentation tab-width))) - ;; LINE AFTER ENDING OF COMMAND - ;; $var .= - ;; 'hello'; - ;; echo 'here'; + ) + + (goto-char point)) + + ) + + ;; LINE AFTER OPENING MULTI-LINE ASSIGNMENT + ;; $var = 'A line' . + ;; 'something'; ;; or - ;; $var = - ;; 25; - ;; echo 'here'; + ;; $var .= 'A line' . + ;; 'something' ;; or - ;; $var = array( - ;; 'here' - ;; ); - ;; echo 'here'; + ;; $var += 35 + + ;; 77 + ;; but ignore + ;; $var === true ;; or - ;; $var = <<<EOD - ;; OKASDOKASD - ;; EOD; - ;; echo 'here'; + ;; $var == 3 ;; or - ;; $var = myFunction( - ;; 'expression'); - ;; echo 'here'; + ;; $argument1 = 3, + ;; $argument2 = 4 ;; or - ;; return myFunction( - ;; 'expression'); - ;; echo 'here'; + ;; function myFunction( + ;; $abc = 3 + ;; ) { ;; or - ;; define('_PRIVATE_ROOT_', - ;; 'here'); - ;; echo 'here'; + ;; $abc != 3 ((and - previous-line-ends-with-terminus - (string= previous-line-ends-with-terminus ";") + (string-match-p + "^[\t ]*$[a-zA-Z0-9_]+[\t ]*[^=!]*=\\($\\|[\t ]+.*[^,;]$\\)" + previous-line-string) (not - (string-match-p - "^[\t ]*\\(echo[\t ]+\\|print[\t ]+\\)" - previous-line-string))) + current-line-starts-with-closing-bracket)) (setq match-type - 'line-after-ending-of-command) + 'line-after-opening-multiline-assignment) + (setq + new-indentation + (+ new-indentation tab-width))) - ;; Back-trace buffer from previous line - ;; Determine if semi-colon ended an multi-line assignment or bracket-less command or not - ;; If it's on the same line we ignore it - (forward-line (* -1 move-length1)) - (end-of-line) - (search-backward-regexp ";" nil t) ;; Skip the semi-colon + ;; LINE THAT ENDS BRACKET AND COMMAND + ;; $variable = array( + ;; 'random' => + ;; 'hello' + ;; ); + ;; or + ;; $variable = [ + ;; 'random' => + ;; 'hello' + ;; ]; + ((string-match-p + "^[\t ]*\\()\\|]\\);[\t ]*$" + current-line-string) + (setq + match-type + 'line-that-ends-bracket-and-command) + (let ((old-point (point)) + (still-looking t) + (bracket-count -1)) - (let ((not-found t) - (is-assignment nil) - (is-string-doc) - (is-function-call) - (parenthesis-level 0) - (is-bracket-less-command nil) - (is-same-line-p t) - (bracket-opened-on-first-line)) + ;; Try to backtrack buffer until we reach start of bracket (while (and - not-found + still-looking (search-backward-regexp - "\\(;\\|{\\|[a-zA-Z_]+[a-zA-Z0-9_]*[\t ]*(\\|)\\|=$\\|=[^>]\\|return\\|echo[\t ]+\\|print[\t ]+\\|\n\\|<<<'?\"?[a-zA-Z0-9_]+'?\"?\\)" - nil - t)) - (let ((match (match-string-no-properties 0))) + "\\((\\|]\\|\\[\\|)\\)" nil t)) + (let ((match-string (match-string-no-properties 0))) (cond + ((or + (string= match-string "(") + (string= match-string "[")) + (setq bracket-count (1+ bracket-count))) + ((or + (string= match-string ")") + (string= match-string "]")) + (setq bracket-count (1- bracket-count))))) + (when (= bracket-count 0) + (setq still-looking nil))) - ((string= match "\n") - (setq is-same-line-p nil)) - - ((string-match-p - "<<<'?\"?[a-zA-Z0-9_]+'?\"?" - match) - (setq - is-string-doc - t) - (setq - not-found - nil)) - - ((string-match-p - "[a-zA-Z_]+[a-zA-Z0-9_]*[\t ]*(" - match) - (setq - parenthesis-level - (1+ parenthesis-level)) - (when (= parenthesis-level 0) - (setq - is-function-call - t) - (setq - not-found - nil))) - - ((string= match ")") - (setq - parenthesis-level - (1- parenthesis-level))) - - ((= parenthesis-level 0) - (setq is-assignment (string-match-p "=" match)) - (setq is-bracket-less-command - (string-match-p - "\\(echo[\t ]+\\|print[\t ]+\\|return[\t ]+\\)" - match)) - (setq not-found nil))))) - - ;; $var = <<<EOD - ;; OKASDOKASD - ;; EOD; - ;; echo 'here'; - (when is-string-doc - (setq - new-indentation - (phps-mode-indent--string-indentation - (buffer-substring-no-properties - (line-beginning-position) - (line-end-position))))) - - ;; When we have an assignment - ;; keep track if bracket was opened on first - ;; line - (when is-assignment - (let ((start-bracket-count - (phps-mode-indent--get-string-brackets-count + ;; Did we find bracket start line? + (unless still-looking + (let ((bracket-start-indentation + (phps-mode-indent--string-indentation (buffer-substring-no-properties (line-beginning-position) (line-end-position))))) - ;; (message "start-bracket-count: %S from %S" start-bracket-count (buffer-substring-no-properties - ;; (line-beginning-position) - ;; (line-end-position))) + ;; Use its indentation for this line as well (setq - bracket-opened-on-first-line - (> start-bracket-count 0)))) - - ;; (message "is-assignment: %S" is-assignment) - ;; (message "bracket-opened-on-first-line: %S" bracket-opened-on-first-line) - - ;; echo 'there' . - ;; 'here'; - ;; echo 'here'; - ;; or - ;; print 'there' . - ;; 'here'; - ;; echo 'here'; - ;; or - ;; $var = - ;; 'opkeokoek'; - ;; echo 'here' - - ;; ignore cases like - ;; $var = array( - ;; 'here' - ;; ); - ;; echo 'here'; - ;; but not cases like - ;; $var = 'abc' - ;; . 'def' . __( - ;; 'okeoke' - ;; ) . 'ere'; - ;; echo 'here'; - ;; NOTE stuff like $var = array(\n 4\n);\n - ;; will end assignment but also decrease previous-bracket-level - ;; NOTE but cases like $var = array(\n 4);\n should pass - (when (and - (not is-same-line-p) - (or - (and - is-assignment - (or - (not bracket-opened-on-first-line) - (not previous-line-starts-with-closing-bracket))) - is-bracket-less-command)) - (setq - new-indentation - (- new-indentation tab-width))) - - ;; define('_PRIVATE_ROOT', - ;; 'here'); - ;; echo 'here'; - ;; but ignore - ;; if (true) { - ;; define('_PRIVATE_ROOT', 'here'); - ;; echo 'here'; - (when (and - is-function-call - (not is-same-line-p)) - (setq - new-indentation - (- new-indentation tab-width))) - - ) + new-indentation + bracket-start-indentation))) - (goto-char point)) + ;; Reset point + (goto-char old-point))) - ;; LINE AFTER ALTERNATIVE CASE DEFINITION - ;; switch ($array): - ;; case 'Something'; - ((and + ;; LINE THAT CONTINUES MULTI-LINE CONCATENATION + ;; echo 'Something' + ;; . 'more'; + ;; or + ;; echo + ;; 'Something' + ;; . 'more'; + ;; or + ;; echo 'Something' . + ;; 'more'; + ;; or + ;; echo + ;; 'Something' . + ;; 'more'; + ((or (string-match-p - "^[\t ]*\\(case.+\\|default\\)\\(;\\|:\\)[\t ]*$" + "^[\t ]*\\." current-line-string) (string-match-p - "^[\t ]*\\(switch\\)[\t ]*(.+):$" + "\\.[\t ]*$" previous-line-string)) (setq match-type - 'line-after-alternative-case-definition) - (setq - new-indentation - (+ new-indentation tab-width))) + 'line-that-continues-multi-line-concatenation) + + ;; If previous line matched ending . + ;; we must backtrack at least two lines + ;; to find a good reference indentation + (let ((old-point (point)) + (match-string) + (previous-concatenation) + (keep-searching 1) + (concat-was-trailing-p + (string-match-p + "\\.[\t ]*$" + previous-line-string)) + (previous-concatenation2)) + (when concat-was-trailing-p + (setq + keep-searching + 2)) + (while keep-searching + (let ((previous-expression + (search-backward-regexp + "\\(^[\t ]*\\.\\|\\.[\t ]*$\\|[{}=;]\\)" nil t))) + (if previous-expression + (progn + (setq + match-string + (match-string-no-properties 0)) + (if (string-match-p + "[{}=;]" + match-string) + (setq + keep-searching + nil) + (setq + keep-searching + (1- keep-searching)) + (when (= keep-searching 0) + (setq + keep-searching + nil) + (when concat-was-trailing-p + (goto-char previous-concatenation2)) + (setq + previous-concatenation + match-string)) + (setq + previous-concatenation2 + (point)))) + (setq + keep-searching + nil)))) - ;; LINE AFTER ENDING OF DOC-COMMENT - ;; /** - ;; * - ;; */ - ;; echo 'here'; - ((= previous-bracket-level -1) - (setq - match-type - 'line-after-ending-of-doc-comment) - (setq - new-indentation - (1- new-indentation))) + (if previous-concatenation + (let ((first-concatenated-line-indent + (phps-mode-indent--string-indentation + (buffer-substring-no-properties + (line-beginning-position) + (line-end-position))))) + ;; We use previous concatenated lines indent + (setq + new-indentation + first-concatenated-line-indent))) - ;; LINE AFTER STARTING DOC-COMMENT - ;; /** - ;; * - ((= previous-bracket-level 1) - (setq - match-type - 'line-after-opening-doc-comment) - (setq - new-indentation - (+ new-indentation 1))) + ;; Reset point + (goto-char old-point))) - ;; LINE AFTER INCREASE IN BRACKETS - ;; array( - ;; 'here' + ;; LINE AFTER CASE DEFINITION + ;; case true: + ;; echo 'here'; ;; or - ;; [[ - ;; 'here' + ;; case true; + ;; echo 'here'; ;; or - ;; if (something) { + ;; default: ;; echo 'here'; - ((>= previous-bracket-level tab-width) - (setq - match-type - 'line-after-increase-in-brackets) - (setq - new-indentation - (+ new-indentation tab-width))) - - ;; LINE AFTER LINE THAT ENDS AND STARTS A BRACKET BLOCK - ;; ) { - ;; echo 'here' ;; or - ;; ][ - ;; 25 - ((and (= previous-bracket-level 0) - previous-line-starts-with-closing-bracket) + ;; default; + ;; echo 'here'; + ((and + (not + (string-match-p + "^[\t ]*\\(case[\t ]+\\|default\\)" + current-line-string)) + (or + (string-match-p + "^[\t ]*case[\t ]+.*\\(;\\|:\\)[\t ]*$" + previous-line-string) + (string-match-p + "^[\t ]*default.*\\(;\\|:\\)[\t ]*$" + previous-line-string))) (setq match-type - 'line-after-line-that-ends-and-starts-a-bracket-block) + 'line-after-case-definition) (setq new-indentation (+ new-indentation tab-width))) - ;; LINE THAT STARTS WITH CLOSING BRACKET - ;; [ - ;; 'hello' - ;; ] - ;; or - ;; array( - ;; 'hello' - ;; ) - ;; but ignore - ;; [ - ;; ] - ;; or - ;; array( - ;; ) + ;; LINE AFTER ENDING OF BRACKET AND COMMAND + ;; if (true) { + ;; $cacheKey = sprintf( + ;; 'key_%s', + ;; md5(json_encode($key)) + ;; ); + ;; $cache = ;; or - ;; if ( - ;; myFunction( - ;; 'random') - ;; ) { - ;; but ignore - ;; var_dump(array(<<<EOD - ;; ölöas - ;; EOD - ;; )); - ((and - current-line-starts-with-closing-bracket - (not previous-line-ends-with-opening-bracket)) + ;; if (true) { + ;; $cache = + ;; Cache::getInstance(); + ;; echo 'here'; + ((string-match-p + "[])][\t ]*;[\t ]*\\(\\?>[\t\n ]*\\)?$" + previous-line-string) (setq match-type - 'line-that-starts-with-closing-bracket) + 'line-after-ending-of-bracket-and-command) - ;; Backtrack to line were bracket started - ;; and use indentation from that line for this line + ;; Backtrack first to line were bracket started + ;; and then backwards until the line were statement / expression + ;; started and use indentation from that line from that line (forward-line (* -1 move-length1)) (end-of-line) - (let ((not-found t) + (search-backward-regexp ";" nil t) ;; Skip trailing comma + (let ((not-found-bracket-start t) (reference-line) - (reference-indentation) - (parenthesis-level -1)) + (parenthesis-level 0)) (while (and - not-found + not-found-bracket-start (search-backward-regexp - "[][(){}]" + "[][()]" nil t)) (let ((match (match-string-no-properties 0))) @@ -1639,90 +1644,85 @@ ((or (string= "(" match) - (string= "[" match) - (string= "{" match)) + (string= "[" match)) (setq parenthesis-level (1+ parenthesis-level)) (when (= parenthesis-level 0) (setq - not-found + not-found-bracket-start nil))) ((or (string= ")" match) - (string= "]" match) - (string= "}" match)) + (string= "]" match)) (setq parenthesis-level (1- parenthesis-level)) (when (= parenthesis-level 0) (setq - not-found + not-found-bracket-start nil))) ))) - (unless not-found + + ;; Found line were bracket started? + (unless not-found-bracket-start (setq reference-line (buffer-substring-no-properties (line-beginning-position) (line-end-position))) + ;; (message "reference-line-1: %S" reference-line) + + ;; Search for first line of statement / expression here + (let ((not-found-command-start t)) + (while + (and + not-found-command-start + (search-backward-regexp + "\\(;\\|}\\|{\\|^[\t ]*[^\t\n ]+.*$\\)" + nil + t)) + (let ((match (match-string-no-properties 1))) + ;; (message "match: %S" match) + (cond + + ;; End of expression / statement + ((or + (string= ";" match) + (string= "}" match) + (string= "{" match)) + (setq + not-found-command-start + nil)) + + ;; Non-empty line + (t + (setq + reference-line + (buffer-substring-no-properties + (line-beginning-position) + (line-end-position)))) + + ))))) + + (when reference-line + ;; (message "reference-line-2: %S" reference-line) (setq - reference-indentation + new-indentation (phps-mode-indent--string-indentation reference-line))) - (goto-char point) - - (when reference-indentation + (when + (and + current-line-starts-with-closing-bracket + (string= current-line-starts-with-closing-bracket "}")) (setq new-indentation - reference-indentation)))) - - ;; LINE AFTER LINE INSIDE DOC-COMMENT - ;; /** - ;; * here - ;; but ignore - ;; /** */ - ;; here - ((and - previous-line-starts-with-opening-doc-comment - (not previous-line-ends-with-closing-doc-comment)) - (setq - match-type - 'line-after-line-inside-doc-comment) - (setq - new-indentation - (+ new-indentation 1))) - - ;; LINE AFTER LINE THAT ENDS WITH ASSIGNMENT - ;; $var = - ((and - previous-line-ends-with-assignment - (<= previous-bracket-level 0)) - (setq - match-type - 'line-after-line-that-ends-with-assignment) - (setq - new-indentation - (+ new-indentation tab-width))) + (- new-indentation tab-width)))) - ;; LINE AFTER LINE THAT ENDS WITH OPENING BRACKET - ;; )) { - ;; echo 'here'; - ;; or - ;; ]][ - ;; 25 - ((and - previous-line-ends-with-opening-bracket - (< previous-bracket-level 0)) - (setq - match-type - 'line-after-line-that-ends-with-opening-bracket) - (setq - new-indentation - (+ new-indentation tab-width))) + (goto-char point)) )