Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 35 additions & 28 deletions plantuml-mode.el
Original file line number Diff line number Diff line change
Expand Up @@ -568,28 +568,35 @@ Uses prefix (as PREFIX) to choose where to display it:
;; (Note: the line with the comment should not contain any text matching other indent
;; regexp or this user-control instruction will be ignored; also at most will count
;; per line ...)
;; Quirks of elisp REGEXes:
;; \s is NOT translated to mean any whitespace character as in other
;; regex flavours, but instead translates to ' ' (= one empty
;; space). This does not match e.g. tabs. Use [[:blank:]] instead, to
;; match 'classic' whitespace chars. [[:space:]] seems an option, but
;; also matches linebreaks, etc. which could cause problems, as more
;; than one line might be matched.
(defvar plantuml-indent-regexp-block-start "^.*{\s*$"
"Indentation regex for all plantuml elements that might define a {} block.
Plantuml elements like skinparam, rectangle, sprite, package, etc.
The opening { has to be the last visible character in the line (whitespace
might follow).")
(defvar plantuml-indent-regexp-note-start "^\s*\\(floating\s+\\)?[hr]?note\s+\\(right\\|left\\|top\\|bottom\\|over\\)[^:]*?$" "simplyfied regex; note syntax is especially inconsistent across diagrams")
(defvar plantuml-indent-regexp-group-start "^\s*\\(alt\\|else\\|opt\\|loop\\|par\\|break\\|critical\\|group\\)\\(?:\s+.+\\|$\\)"
(defvar plantuml-indent-regexp-note-start "^[[:blank:]]*\\(floating\s+\\)?[hr]?note\s+\\(right\\|left\\|top\\|bottom\\|over\\)[^:]*?$" "simplyfied regex; note syntax is especially inconsistent across diagrams")
(defvar plantuml-indent-regexp-group-start "^[[:blank:]]*\\(alt\\|else\\|opt\\|loop\\|par\\|break\\|critical\\|group\\)\\(?:\s+.+\\|$\\)"
"Indentation regex for plantuml group elements that are defined for sequence diagrams.
Two variants for groups: keyword is either followed by whitespace and some text
or it is followed by line end.")
(defvar plantuml-indent-regexp-activate-start "^\s*activate\s+.+$")
(defvar plantuml-indent-regexp-box-start "^\s*box\s+.+$")
(defvar plantuml-indent-regexp-ref-start "^\s*ref\s+over\s+[^:]+?$")
(defvar plantuml-indent-regexp-title-start "^\s*title\s*\\('.*\\)?$")
(defvar plantuml-indent-regexp-header-start "^\s*\\(?:\\(?:center\\|left\\|right\\)\s+header\\|header\\)\s*\\('.*\\)?$")
(defvar plantuml-indent-regexp-footer-start "^\s*\\(?:\\(?:center\\|left\\|right\\)\s+footer\\|footer\\)\s*\\('.*\\)?$")
(defvar plantuml-indent-regexp-legend-start "^\s*\\(?:legend\\|legend\s+\\(?:bottom\\|top\\)\\|legend\s+\\(?:center\\|left\\|right\\)\\|legend\s+\\(?:bottom\\|top\\)\s+\\(?:center\\|left\\|right\\)\\)\s*\\('.*\\)?$")
(defvar plantuml-indent-regexp-activate-start "^[[:blank:]]*activate\s+.+$")
(defvar plantuml-indent-regexp-box-start "^[[:blank:]]*box\s+.+$")
(defvar plantuml-indent-regexp-ref-start "^[[:blank:]]*ref\s+over\s+[^:]+?$")
(defvar plantuml-indent-regexp-title-start "^[[:blank:]]*title\s*\\('.*\\)?$")
(defvar plantuml-indent-regexp-header-start "^[[:blank:]]*\\(?:\\(?:center\\|left\\|right\\)\s+header\\|header\\)\s*\\('.*\\)?$")
(defvar plantuml-indent-regexp-footer-start "^[[:blank:]]*\\(?:\\(?:center\\|left\\|right\\)\s+footer\\|footer\\)\s*\\('.*\\)?$")
(defvar plantuml-indent-regexp-legend-start "^[[:blank:]]*\\(?:legend\\|legend\s+\\(?:bottom\\|top\\)\\|legend\s+\\(?:center\\|left\\|right\\)\\|legend\s+\\(?:bottom\\|top\\)\s+\\(?:center\\|left\\|right\\)\\)\s*\\('.*\\)?$")
(defvar plantuml-indent-regexp-oldif-start "^.*if\s+\".*\"\s+then\s*\\('.*\\)?$" "used in current activity diagram, sometimes already mentioned as deprecated")
(defvar plantuml-indent-regexp-newif-start "^\s*\\(?:else\\)?if\s+(.*)\s+then\s*.*$")
(defvar plantuml-indent-regexp-loop-start "^\s*\\(?:repeat\s*\\|while\s+(.*).*\\)$")
(defvar plantuml-indent-regexp-fork-start "^\s*\\(?:fork\\|split\\)\\(?:\s+again\\)?\s*$")
(defvar plantuml-indent-regexp-macro-start "^\s*!definelong.*$")
(defvar plantuml-indent-regexp-newif-start "^[[:blank:]]*\\(?:else\\)?if\s+(.*)\s+then\s*.*$")
(defvar plantuml-indent-regexp-loop-start "^[[:blank:]]*\\(?:repeat\s*\\|while\s+(.*).*\\)$")
(defvar plantuml-indent-regexp-fork-start "^[[:blank:]]*\\(?:fork\\|split\\)\\(?:\s+again\\)?\s*$")
(defvar plantuml-indent-regexp-macro-start "^[[:blank:]]*!definelong.*$")
(defvar plantuml-indent-regexp-user-control-start "^.*'.*\s*PLANTUML_MODE_INDENT_INCREASE\s*.*$")
(defvar plantuml-indent-regexp-start (list plantuml-indent-regexp-block-start
plantuml-indent-regexp-group-start
Expand All @@ -607,21 +614,21 @@ or it is followed by line end.")
plantuml-indent-regexp-macro-start
plantuml-indent-regexp-oldif-start
plantuml-indent-regexp-user-control-start))
(defvar plantuml-indent-regexp-block-end "^\s*\\(?:}\\|endif\\|else\s*.*\\|end\\)\s*\\('.*\\)?$")
(defvar plantuml-indent-regexp-note-end "^\s*\\(end\s+note\\|end[rh]note\\)\s*\\('.*\\)?$")
(defvar plantuml-indent-regexp-group-end "^\s*end\s*\\('.*\\)?$")
(defvar plantuml-indent-regexp-activate-end "^\s*deactivate\s+.+$")
(defvar plantuml-indent-regexp-box-end "^\s*end\s+box\s*\\('.*\\)?$")
(defvar plantuml-indent-regexp-ref-end "^\s*end\s+ref\s*\\('.*\\)?$")
(defvar plantuml-indent-regexp-title-end "^\s*end\s+title\s*\\('.*\\)?$")
(defvar plantuml-indent-regexp-header-end "^\s*endheader\s*\\('.*\\)?$")
(defvar plantuml-indent-regexp-footer-end "^\s*endfooter\s*\\('.*\\)?$")
(defvar plantuml-indent-regexp-legend-end "^\s*endlegend\s*\\('.*\\)?$")
(defvar plantuml-indent-regexp-oldif-end "^\s*\\(endif\\|else\\)\s*\\('.*\\)?$")
(defvar plantuml-indent-regexp-newif-end "^\s*\\(endif\\|elseif\\|else\\)\s*.*$")
(defvar plantuml-indent-regexp-loop-end "^\s*\\(repeat\s*while\\|endwhile\\)\s*.*$")
(defvar plantuml-indent-regexp-fork-end "^\s*\\(\\(fork\\|split\\)\s+again\\|end\s+\\(fork\\|split\\)\\)\s*$")
(defvar plantuml-indent-regexp-macro-end "^\s*!enddefinelong\s*\\('.*\\)?$")
(defvar plantuml-indent-regexp-block-end "^[[:blank:]]*\\(?:}\\|endif\\|else\s*.*\\|end\\)\s*\\('.*\\)?$")
(defvar plantuml-indent-regexp-note-end "^[[:blank:]]*\\(end\s+note\\|end[rh]note\\)\s*\\('.*\\)?$")
(defvar plantuml-indent-regexp-group-end "^[[:blank:]]*end\s*\\('.*\\)?$")
(defvar plantuml-indent-regexp-activate-end "^[[:blank:]]*deactivate\s+.+$")
(defvar plantuml-indent-regexp-box-end "^[[:blank:]]*end\s+box\s*\\('.*\\)?$")
(defvar plantuml-indent-regexp-ref-end "^[[:blank:]]*end\s+ref\s*\\('.*\\)?$")
(defvar plantuml-indent-regexp-title-end "^[[:blank:]]*end\s+title\s*\\('.*\\)?$")
(defvar plantuml-indent-regexp-header-end "^[[:blank:]]*endheader\s*\\('.*\\)?$")
(defvar plantuml-indent-regexp-footer-end "^[[:blank:]]*endfooter\s*\\('.*\\)?$")
(defvar plantuml-indent-regexp-legend-end "^[[:blank:]]*endlegend\s*\\('.*\\)?$")
(defvar plantuml-indent-regexp-oldif-end "^[[:blank:]]*\\(endif\\|else\\)\s*\\('.*\\)?$")
(defvar plantuml-indent-regexp-newif-end "^[[:blank:]]*\\(endif\\|elseif\\|else\\)\s*.*$")
(defvar plantuml-indent-regexp-loop-end "^[[:blank:]]*\\(repeat\s*while\\|endwhile\\)\s*.*$")
(defvar plantuml-indent-regexp-fork-end "^[[:blank:]]*\\(\\(fork\\|split\\)\s+again\\|end\s+\\(fork\\|split\\)\\)\s*$")
(defvar plantuml-indent-regexp-macro-end "^[[:blank:]]*!enddefinelong\s*\\('.*\\)?$")
(defvar plantuml-indent-regexp-user-control-end "^.*'.*\s*PLANTUML_MODE_INDENT_DECREASE\s*.*$")
(defvar plantuml-indent-regexp-end (list plantuml-indent-regexp-block-end
plantuml-indent-regexp-group-end
Expand Down
111 changes: 111 additions & 0 deletions test/plantuml-indentation-with-tabs-test.el
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
;;; plantuml-indentation-with-tabs-test.el --- PlantUML Mode indentation tests -*- lexical-binding: t; -*-

;; Author: René Schmelzer, Tobias Marczewski (mtoboid)
;; Maintainer: Carlo Sciolla (skuro)
;; URL: https://github.com/skuro/plantuml-mode

;;; Commentary:

;; Test indentation for class diagrams, specifically using tabs.

;;; Code:

(ert-deftest plantuml-test-indentation/tabs/nested-modules ()
"Test correct indentation of plantuml class diagram elements.
These code examples are taken from www.plantuml.com"
(plantuml-test-indent-block-with-tabs

"
@startuml

'some comment
package org.example.module1 {
interface A {
doStuff(): String
getList(): List<Integer>
}

class B {
-name: String
+getName(): String
}
}

package org.example.module2 {
class C {
-count: int
+getCount(): int
}
}

A <|.. B
A <|.. C

@enduml
"
"
@startuml

'some comment
package org.example.module1 {
interface A {
doStuff(): String
getList(): List<Integer>
}

class B {
-name: String
+getName(): String
}
}

package org.example.module2 {
class C {
-count: int
+getCount(): int
}
}

A <|.. B
A <|.. C

@enduml
"))


(ert-deftest plantuml-test-block-indentation/tabs/package-empty ()
"Test correct indentation of an empty package block."
(plantuml-test-indent-block-with-tabs
"
package APackage ()
interface Inter
"
"
package APackage ()
interface Inter
"))


(ert-deftest platuml-test-block-indentation/tabs/package-interface-nested ()
"Test correct indentation of two nested blocks, a package and an interface
Note: package is used in deployment and object diagrams as well, see there for more tests."
(plantuml-test-indent-block-with-tabs
"
package foo {
interface Bar {
baz
}
}
"
"
package foo {
interface Bar {
baz
}
}
"))


(provide 'plantuml-indentation-with-tabs-test)

;;; plantuml-indentation-with-tabs-test.el ends here
32 changes: 32 additions & 0 deletions test/test-helper.el
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,38 @@ Finally, the indented text in the buffer will be compared with AFTER."
(indent-region (point-min) (point-max))
(should (equal (buffer-string) after))))

;; FIXME
;; This function is just a copy of the above plantuml-test-indent-block with
;; some minor changes to use indentation with tabs. Perhaps merge the two
;; functions?
(defun plantuml-test-indent-block-with-tabs (before after)
"Helper for the block indentation tests with tabs.

BEFORE is the text block to be inserted into a temporary buffer.
AFTER is the expected text block after indentation.

The temporary buffer will be put into `plantuml-mode'. The whole buffer
will be indented with one tab for each level of indentation.

Finally, the indented text in the buffer will be compared with AFTER."

;; ensure that plantuml-indent-level is the default value 8
(let ((indent-tabs-mode t)
(plantuml-indent-level 8)
;; fix the JAR location prior to mode initialization
;; for some reason, plantuml-mode disregards the setq-local
(plantuml-jar-path plantuml-test-jar-path))

(with-temp-buffer
(plantuml-init-once 'jar)

(insert before)
(goto-char (point-min))
(plantuml-mode)

(indent-region (point-min) (point-max))
(should (equal (buffer-string) after)))))

;; enable code coverage
(when (require 'undercover nil t)
(undercover "plantuml-mode.el"))
Expand Down