branch: externals/phps-mode commit 0e3889a12261f28e3f982afc64b9cdadfe82e78d Author: Christian Johansson <christ...@cvj.se> Commit: Christian Johansson <christ...@cvj.se>
Added indentation support for HTML/XML --- TODO.md | 10 ----- phps-mode-indent.el | 102 +++++++++++++++++++++++++++++++++++++++--- test/phps-mode-test-indent.el | 45 +++++++++++++++++++ 3 files changed, 141 insertions(+), 16 deletions(-) diff --git a/TODO.md b/TODO.md index 3832977c81..c234814e8e 100644 --- a/TODO.md +++ b/TODO.md @@ -2,22 +2,12 @@ ## Indentation -* Fix HTML/XML indentation support -* Strange case - - $A = - B:: - C($D, true); - // Comment - - ## Code intelligence * Bookkeeping of chained object operators like WC()->cart->subtotal * Bookkeeping of variables inside classes with multiple methods seems to not work * Move bookkeeping and imenu generation to main thread to be able to populate Sematic Subsystem in the future * Catch signaling from AST-generation, bookkeeping and imenu generation -* Remove support for incremental parsing if it speeds up * Lexer/parser fix for multiple cases like switch($here) { diff --git a/phps-mode-indent.el b/phps-mode-indent.el index 78e1e9abd7..deb16ecd08 100644 --- a/phps-mode-indent.el +++ b/phps-mode-indent.el @@ -124,17 +124,13 @@ 1)) (defun phps-mode-indent--get-string-brackets-count - (string &optional html-mode) - "Get bracket count for STRING optionally in HTML-MODE." + (string) + "Get bracket count for STRING." (let ((bracket-level 0) (start 0) (line-is-empty (string-match-p "^[ \t\f\r\n]*$" string)) (test-string "\\([\]{}()[]\\|^[\t ]/\\*\\*\\|^[\t\\* ]*\\*/\\)")) - (when html-mode - (setq - test-string - "\\([\]{}()[]\\|<[a-zA-Z]+\\|</[a-zA-Z]+\\|/>\\|^[\t ]/\\*\\*\\|^[\t\\* ]*\\*/\\)")) (unless line-is-empty ;; (message "string: %S" string) (while @@ -162,6 +158,64 @@ (setq bracket-level (- bracket-level tab-width))))))) bracket-level)) +(defun phps-mode-indent--get-html-string-bracket-level (string) + "Get HTML bracket-level for STRING." + (let* ((html-bracket-level 0) + (start 0) + (next-item + (string-match + "\\(<[^>]+>\\)" + string + start))) + (while next-item + (let ((match (match-string 0 string))) + (setq + start + (match-end 0)) + + (cond + + ;; Self-closing tag does not change indentation + ((string-match + "<\\([a-zA-Z]\\)+[^>]+/>" + match)) + + ;; Opening tag changes indentation for most tags + ((string-match + "<\\([a-zA-Z]+\\)" + match) + (let ((tag (match-string 1 match))) + (unless + (string-match-p + "^\\(html\\|meta\\|br\\|em\\|strong\\|i\\|b\\)$" + tag) + (setq + html-bracket-level + (1+ html-bracket-level))))) + + ;; Closing tag changes indentation for most tags + ((string-match + "</\\([a-zA-Z]+\\)" + match) + (let ((tag (match-string 1 match))) + (unless + (string-match-p + "^\\(html\\|meta\\|br\\|em\\|strong\\|i\\|b\\)$" + tag) + (setq + html-bracket-level + (1- html-bracket-level))))) + ) + (setq + next-item + (string-match + "\\(<[^>]+>\\)" + string + start)))) + (if (= html-bracket-level 0) + nil + html-bracket-level))) + (defun phps-mode-indent--get-previous-reference-index-line () "Get previous index line as reference, if any exist. A index line is a previous element line inside current bracket scope." (let ((reference-line)) @@ -568,6 +622,42 @@ (cond + + ((and + (or + (string-match-p + "^[\t ]*\\(<[^>]+>\\)+[\t ]*$" + previous-line-string) + (string-match-p + "^[\t ]*\\(<[^>]+>\\)+[\t ]*$" + current-line-string)) + (not + (string-match-p + "<\\?" + previous-line-string)) + (not + (string-match-p + "<\\?" + current-line-string))) + (setq + match-type + 'line-after-html-line) + (when-let ((html-bracket-level + (phps-mode-indent--get-html-string-bracket-level + previous-line-string))) + (when (> html-bracket-level 0) + (setq + new-indentation + (+ new-indentation tab-width)))) + + (when-let ((html-bracket-level + (phps-mode-indent--get-html-string-bracket-level + current-line-string))) + (when (< html-bracket-level 0) + (setq + new-indentation + (- new-indentation tab-width))))) + ;; LINE AFTER EXTENDS / IMPLEMENTS ;; class MyClass implements ;; myInterface diff --git a/test/phps-mode-test-indent.el b/test/phps-mode-test-indent.el index 1a6b7202f1..8e9e7f124c 100644 --- a/test/phps-mode-test-indent.el +++ b/test/phps-mode-test-indent.el @@ -213,6 +213,51 @@ (phps-mode-indent--get-previous-start-of-bracket-line t) nil))) + (should + (equal + (phps-mode-indent--get-html-string-bracket-level "<!DOCTYPE html>") + nil)) + (should + (equal + (phps-mode-indent--get-html-string-bracket-level "<html>") + nil)) + (should + (equal + (phps-mode-indent--get-html-string-bracket-level "</html>") + nil)) + (should + (equal + (phps-mode-indent--get-html-string-bracket-level "<body>") + 1)) + (should + (equal + (phps-mode-indent--get-html-string-bracket-level "</body>") + -1)) + (should + (equal + (phps-mode-indent--get-html-string-bracket-level "<meta>") + nil)) + (should + (equal + (phps-mode-indent--get-html-string-bracket-level "<meta />") + nil)) + (should + (equal + (phps-mode-indent--get-html-string-bracket-level "<button>") + 1)) + (should + (equal + (phps-mode-indent--get-html-string-bracket-level "<button />") + nil)) + (should + (equal + (phps-mode-indent--get-html-string-bracket-level "</button>") + -1)) + (should + (equal + (phps-mode-indent--get-html-string-bracket-level "</p>") + -1)) + (message "Passed tests for indentation helper functions")) (defun phps-mode-test-indent--get-lines-indent ()