├── .gitignore ├── test ├── resources │ ├── a-b.puml │ ├── unicode.puml │ ├── a-b.png │ ├── a-b.txt │ ├── unicode.txt │ ├── init.el │ └── unindented.plantuml ├── plantuml-indentation-object-test.el ├── plantuml-mode-custom-jar-location-test.el ├── plantuml-mode-test.el ├── plantuml-config-test.el ├── plantuml-indentation-ie-test.el ├── plantuml-indentation-component-test.el ├── plantuml-preview-test.el ├── plantuml-indentation-deployment-test.el ├── test-helper.el ├── plantuml-server-test.el ├── plantuml-indentation-state-test.el ├── plantuml-indentation-activity-old-test.el ├── plantuml-indentation-commons-test.el ├── plantuml-indentation-class-test.el ├── plantuml-indentation-sequence-test.el ├── plantuml-indentation-basics-test.el ├── plantuml-indentation-activity-new-test.el └── plantuml-indentation-notes-test.el ├── banner.png ├── .github ├── ISSUE_TEMPLATE └── stale.yml ├── Cask ├── Makefile ├── bin ├── download-plantuml.sh └── set-version.sh ├── .circleci └── config.yml ├── README.md ├── LICENSE.txt └── plantuml-mode.el /.gitignore: -------------------------------------------------------------------------------- 1 | .cask 2 | .coveralls.yml 3 | -------------------------------------------------------------------------------- /test/resources/a-b.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | 3 | A -> B 4 | 5 | @enduml 6 | -------------------------------------------------------------------------------- /banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skuro/plantuml-mode/HEAD/banner.png -------------------------------------------------------------------------------- /test/resources/unicode.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | 3 | lang -> 日本語 4 | 5 | @enduml 6 | -------------------------------------------------------------------------------- /test/resources/a-b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skuro/plantuml-mode/HEAD/test/resources/a-b.png -------------------------------------------------------------------------------- /test/resources/a-b.txt: -------------------------------------------------------------------------------- 1 | ┌─┐ ┌─┐ 2 | │A│ │B│ 3 | └┬┘ └┬┘ 4 | │ │ 5 | │───────────>│ 6 | ┌┴┐ ┌┴┐ 7 | │A│ │B│ 8 | └─┘ └─┘ 9 | -------------------------------------------------------------------------------- /test/resources/unicode.txt: -------------------------------------------------------------------------------- 1 | ┌────┐ ┌───┐ 2 | │lang│ │日本語│ 3 | └─┬──┘ └─┬─┘ 4 | │ │ 5 | │ ─────────────>│ 6 | ┌─┴──┐ ┌─┴─┐ 7 | │lang│ │日本語│ 8 | └────┘ └───┘ 9 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | > Write here the summary of your changes 4 | 5 | # Checklist for pull requests 6 | 7 | - [ ] I'm fine with my code being released under the GPLv2 license 8 | - [ ] the pull request is filed against the `develop` branch instead of `master` 9 | -------------------------------------------------------------------------------- /Cask: -------------------------------------------------------------------------------- 1 | (source gnu) 2 | (source melpa) 3 | 4 | (package-file "plantuml-mode.el") 5 | 6 | (development 7 | (depends-on "f") 8 | (depends-on "dash") 9 | (depends-on "ecukes") 10 | (depends-on "ert-runner") 11 | (depends-on "el-mock") 12 | (depends-on "undercover") 13 | (depends-on "deflate" "0.0.4")) 14 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Programs used in the make goals 3 | # 4 | export CASK ?= cask 5 | export EMACS ?= emacs 6 | 7 | # 8 | # General configuration 9 | # 10 | export CASK_DIR ?= `${CASK} package-directory` 11 | export BATCH = --batch -q -l .emacs/init.el 12 | export COVERALLS_REPO_TOKEN = 61YFD7RG1RRJTs0kEuj1aZX7VBgUPiMNO 13 | 14 | all: version test 15 | 16 | version: 17 | $(EMACS) $(BATCH) --version 18 | 19 | test: install unit integration 20 | 21 | unit: 22 | ${CASK} exec ert-runner -t !server 23 | 24 | integration: 25 | ${CASK} exec ert-runner -t server 26 | 27 | install: 28 | ${CASK} install 29 | 30 | clean: 31 | rm -Rf .emacs.d 32 | rm -Rf .cask 33 | 34 | .PHONY: all test unit install clean 35 | -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Number of days of inactivity before an issue becomes stale 2 | daysUntilStale: 90 3 | # Number of days of inactivity before a stale issue is closed 4 | daysUntilClose: 10 5 | # Issues with these labels will never be considered stale 6 | exemptLabels: 7 | - help-wanted 8 | - enhancement 9 | # Label to use when marking an issue as stale 10 | staleLabel: wontfix 11 | # Comment to post when marking an issue as stale. Set to `false` to disable 12 | markComment: > 13 | This issue has been automatically marked as stale because it has not had 14 | recent activity. It will be closed if no further activity occurs. Thank you 15 | for your contributions. 16 | # Comment to post when closing a stale issue. Set to `false` to disable 17 | closeComment: false 18 | -------------------------------------------------------------------------------- /test/resources/init.el: -------------------------------------------------------------------------------- 1 | ;; Used to test `plantuml-mode' installations 2 | 3 | (setq user-emacs-directory "./.emacs.d") 4 | 5 | (require 'subr-x) 6 | (setq local-repository 7 | (concat 8 | (string-trim (shell-command-to-string "cask package-directory")) 9 | "/../testing")) 10 | (custom-set-variables `(package-archive-upload-base ,local-repository)) 11 | 12 | (require 'package-x) 13 | (defun -package-upload (file) 14 | (with-temp-buffer 15 | (insert-file-contents file) 16 | (let ((pkg-desc (package-buffer-info))) 17 | (package-upload-buffer-internal pkg-desc "el")))) 18 | (-package-upload "plantuml-mode.el") 19 | 20 | (setq package-archives `(("local" . ,local-repository))) 21 | (package-initialize) 22 | 23 | (package-install 'plantuml-mode) 24 | (require 'plantuml-mode) 25 | 26 | (message 27 | (concat "Successfully installed plantuml-mode v" plantuml-mode-version)) 28 | -------------------------------------------------------------------------------- /test/plantuml-indentation-object-test.el: -------------------------------------------------------------------------------- 1 | ;;; plantuml-indentation-object-test.el --- PlantUML Mode indentation tests -*- lexical-binding: t; -*- 2 | 3 | ;; Author: René Schmelzer 4 | ;; Maintainer: Carlo Sciolla (skuro) 5 | ;; URL: https://github.com/skuro/plantuml-mode 6 | 7 | ;;; Commentary: 8 | 9 | ;; Test indentation for object diagrams. 10 | 11 | ;;; Code: 12 | 13 | (ert-deftest plantuml-test-indentation/object-diagram () 14 | "Test correct indentation of plantuml object diagram elements. 15 | These code examples are taken from www.plantuml.com 16 | Note: object diagrams use many elements defined for class diagrams." 17 | (plantuml-test-indent-block 18 | 19 | " 20 | object user { 21 | name = \"Dummy\" 22 | id = 123 23 | } 24 | " 25 | " 26 | object user { 27 | name = \"Dummy\" 28 | id = 123 29 | } 30 | ")) 31 | 32 | (provide 'plantuml-indentation-object-test) 33 | 34 | ;;; plantuml-indentation-object-test.el ends here 35 | -------------------------------------------------------------------------------- /bin/download-plantuml.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Where the script is executed 4 | CURRENT_PATH="$(dirname "$0")" 5 | 6 | # Where to download the file 7 | OUTPUT_PATH="${CURRENT_PATH}/plantuml.jar" 8 | 9 | # Retrieve the list of versions, in XML format, only one result (the latest) 10 | VERSIONS_URL='https://search.maven.org/solrsearch/select?q=g:net.sourceforge.plantuml+AND+a:plantuml&core=gav&start=0&rows=1&wt=xml' 11 | 12 | # Only match the contents of the version (name="v") XML tag 13 | LATEST_VERSION="$(curl -s "${VERSIONS_URL}" | grep ''| sed 's/.*//g'|sed 's/<\/str>.*//')" 14 | 15 | # Compose the download link 16 | DOWNLOAD_URL="https://search.maven.org/remotecontent?filepath=net/sourceforge/plantuml/plantuml/${LATEST_VERSION}/plantuml-${LATEST_VERSION}.jar" 17 | 18 | # finally, download the JAR file 19 | echo "Downloading PlantUML v${LATEST_VERSION} into ${OUTPUT_PATH}" 20 | wget -O "${OUTPUT_PATH}" "${DOWNLOAD_URL}" 2>/dev/null 21 | -------------------------------------------------------------------------------- /bin/set-version.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Retrieves the version from the changelog in plantuml-mode.el 4 | function grab_version(){ 5 | grep ';; version' plantuml-mode.el | \ 6 | head -n1 | \ 7 | cut -f3 -d' ' | \ 8 | tr -d ',' 9 | } 10 | 11 | # Updates the version in-place 12 | function update_version(){ 13 | NEW_VERSION="${1}" 14 | sed -i -E "s/plantuml-mode-version \"[0-9\.]+\"/plantuml-mode-version \"${1}\"/" plantuml-mode.el 15 | } 16 | 17 | case "$(git rev-parse --abbrev-ref HEAD)" in 18 | 'master') 19 | VERSION="$(grab_version)" 20 | update_version "${VERSION}" 21 | git add plantuml-mode.el 22 | ;; 23 | 24 | 'develop') 25 | VERSION="$(TZ='UTC' date '+%Y%m%d.%-H%M')" # MELPA style 26 | update_version "${VERSION}" 27 | git add plantuml-mode.el 28 | ;; 29 | 30 | *) 31 | ## do nothing 32 | ;; 33 | esac 34 | -------------------------------------------------------------------------------- /test/plantuml-mode-custom-jar-location-test.el: -------------------------------------------------------------------------------- 1 | ;;; plantuml-mode-custom-jar-location-test.el --- PlantUML Mode JAR location tests -*- lexical-binding: t; -*- 2 | 3 | ;; Author: Carlo Sciolla (skuro) 4 | ;; Maintainer: Carlo Sciolla (skuro) 5 | ;; URL: https://github.com/skuro/plantuml-mode 6 | 7 | ;;; Commentary: 8 | 9 | ;;; Code: 10 | 11 | (ert-deftest custom-jar-location () 12 | (setq-local plantuml-jar-path "~/.plantuml/plantuml.jar") 13 | (should (equal `("-Djava.awt.headless=true" "-jar" "--illegal-access=deny" 14 | ,(expand-file-name "~/.plantuml/plantuml.jar") 15 | "-charset" "UTF-8") 16 | (plantuml-jar-render-command))) 17 | 18 | (setq-local plantuml-jar-path "/path/with spaces/plantuml.jar") 19 | (should (equal `("-Djava.awt.headless=true" "-jar" "--illegal-access=deny" "/path/with spaces/plantuml.jar" "-charset" "UTF-8") 20 | (plantuml-jar-render-command)))) 21 | 22 | (provide 'plantuml-mode-custom-jar-location-test) 23 | 24 | ;;; plantuml-mode-custom-jar-location-test.el ends here 25 | -------------------------------------------------------------------------------- /test/plantuml-mode-test.el: -------------------------------------------------------------------------------- 1 | ;;; plantuml-mode-test.el --- PlantUML Mode tests -*- lexical-binding: t; -*- 2 | 3 | ;; Author: Carlo Sciolla (skuro) 4 | ;; Maintainer: Carlo Sciolla (skuro) 5 | ;; URL: https://github.com/skuro/plantuml-mode 6 | 7 | ;;; Commentary: 8 | 9 | ;;; Code: 10 | 11 | (ert-deftest initial-jar-location () 12 | (should (equal (expand-file-name "~/plantuml.jar") 13 | plantuml-jar-path))) 14 | 15 | (ert-deftest can-unload-plantuml () 16 | (unload-feature 'plantuml-mode t) 17 | (should (eq nil (boundp 'plantuml-jar-path))) 18 | (load-plantuml-mode) 19 | (should (not (eq nil (boundp 'plantuml-jar-path))))) 20 | 21 | (ert-deftest debug-install-issues () 22 | (unload-feature 'plantuml-mode t) 23 | 24 | (condition-case nil 25 | (require 'package) 26 | (add-to-list 'package-archives 27 | '("melpa" . "https://melpa.milkbox.net/packages/")) 28 | (package-install "plantuml-mode") 29 | (unload-feature 'plantuml-mode t)) 30 | 31 | (load-plantuml-mode)) 32 | 33 | (provide 'plantuml-mode-test) 34 | 35 | ;;; plantuml-mode-test.el ends here 36 | -------------------------------------------------------------------------------- /test/plantuml-config-test.el: -------------------------------------------------------------------------------- 1 | ;;; plantuml-config-test.el --- tests for plantuml-mode configuration knobs -*- lexical-binding: t; -*- 2 | 3 | ;; Author: Carlo Sciolla 4 | ;; Maintainer: Carlo Sciolla 5 | ;; URL: https://github.com/skuro/plantuml-mode 6 | 7 | ;;; Commentary: 8 | 9 | ;; Test user-accessible configuration knobs 10 | 11 | ;;; Code: 12 | 13 | (require 'plantuml-mode) 14 | 15 | (ert-deftest plantuml-config-test/set-exec-mode-happy-path () 16 | "Test switching execution modes" 17 | (let ((orig-mode plantuml-exec-mode)) 18 | ;; happy flows: 19 | (plantuml-set-exec-mode "server") 20 | (should (equal 'server plantuml-exec-mode)) 21 | (plantuml-set-exec-mode "jar") 22 | (should (equal 'jar plantuml-exec-mode)) 23 | (plantuml-set-exec-mode "executable") 24 | (should (equal 'executable plantuml-exec-mode)) 25 | 26 | (setq plantuml-exec-mode orig-mode))) 27 | 28 | (ert-deftest plantuml-config-test/set-exec-mode-wrong-mode () 29 | "Test setting the exec mode with the wrong text" 30 | (should-error (plantuml-set-exec-mode "turing-machine"))) 31 | 32 | (provide 'plantuml-mode-config-test) 33 | 34 | ;;; plantuml-config-test.el ends here 35 | -------------------------------------------------------------------------------- /test/plantuml-indentation-ie-test.el: -------------------------------------------------------------------------------- 1 | ;;; plantuml-indentation-ie-test.el --- PlantUML Mode indentation tests -*- lexical-binding: t; -*- 2 | 3 | ;; Author: Carlo Sciolla (skuro) 4 | ;; Maintainer: Carlo Sciolla (skuro) 5 | ;; URL: https://github.com/skuro/plantuml-mode 6 | 7 | ;;; Commentary: 8 | 9 | ;; Test indentation of Information Engineering (IE) notation. 10 | ;; See https://github.com/plantuml/plantuml/pull/31 11 | 12 | ;;; Code: 13 | 14 | (ert-deftest plantuml-test-block-indentation/ie-entity () 15 | "Test correct indentation of an entity block." 16 | (plantuml-test-indent-block 17 | " 18 | entity Entity { 19 | * identifying_attribute 20 | -- 21 | * mandatory_attribute 22 | optional_attribute 23 | } 24 | " 25 | " 26 | entity Entity { 27 | * identifying_attribute 28 | -- 29 | * mandatory_attribute 30 | optional_attribute 31 | } 32 | " 33 | )) 34 | 35 | (ert-deftest plantuml-test-indendation/ie-arrows () 36 | "Test correct indentation of IE-style arrows." 37 | (plantuml-test-indent-block 38 | " 39 | foo1 --{ bar1 40 | foo1 --{ bar2 41 | foo1 --{ bar3 42 | 43 | aa --o{ bb 44 | aa --o{ cc 45 | aa --o{ dd 46 | " 47 | " 48 | foo1 --{ bar1 49 | foo1 --{ bar2 50 | foo1 --{ bar3 51 | 52 | aa --o{ bb 53 | aa --o{ cc 54 | aa --o{ dd 55 | ")) 56 | 57 | 58 | ;;; plantuml-indentation-ie-test.el ends here 59 | -------------------------------------------------------------------------------- /test/plantuml-indentation-component-test.el: -------------------------------------------------------------------------------- 1 | ;;; plantuml-indentation-component-test.el --- PlantUML Mode indentation tests -*- lexical-binding: t; -*- 2 | 3 | ;; Author: René Schmelzer 4 | ;; Maintainer: Carlo Sciolla (skuro) 5 | ;; URL: https://github.com/skuro/plantuml-mode 6 | 7 | ;;; Commentary: 8 | 9 | ;; Test indentation for component diagrams. 10 | 11 | ;;; Code: 12 | 13 | (ert-deftest plantuml-test-indentation/component-diagram () 14 | "Test correct indentation of plantuml component diagram elements. 15 | These code examples are taken from www.plantuml.com" 16 | (plantuml-test-indent-block 17 | 18 | " 19 | package \"Some Group\" { 20 | HTTP - [First Component] 21 | [Another Component] 22 | } 23 | 24 | node \"Other Groups\" { 25 | FTP - [Second Component] 26 | [First Component] --> FTP 27 | } 28 | 29 | cloud { 30 | [Example 1] 31 | } 32 | 33 | database \"MySql\" { 34 | folder \"This is my folder\" { 35 | [Folder 3] 36 | } 37 | frame \"Foo\" { 38 | [Frame 4] 39 | } 40 | } 41 | " 42 | " 43 | package \"Some Group\" { 44 | HTTP - [First Component] 45 | [Another Component] 46 | } 47 | 48 | node \"Other Groups\" { 49 | FTP - [Second Component] 50 | [First Component] --> FTP 51 | } 52 | 53 | cloud { 54 | [Example 1] 55 | } 56 | 57 | database \"MySql\" { 58 | folder \"This is my folder\" { 59 | [Folder 3] 60 | } 61 | frame \"Foo\" { 62 | [Frame 4] 63 | } 64 | } 65 | ")) 66 | 67 | (provide 'plantuml-indentation-component-test) 68 | 69 | ;;; plantuml-indentation-component-test.el ends here 70 | -------------------------------------------------------------------------------- /test/plantuml-preview-test.el: -------------------------------------------------------------------------------- 1 | ;;; plantuml-mode-preview-test.el --- PlantUML Mode preview tests -*- lexical-binding: t; -*- 2 | 3 | ;; Author: Carlo Sciolla (skuro) 4 | ;; Maintainer: Carlo Sciolla (skuro) 5 | ;; URL: https://github.com/skuro/plantuml-mode 6 | 7 | ;;; Commentary: 8 | 9 | ;;; Code: 10 | 11 | (defun assert-preview (puml output &optional format mode) 12 | "Ensure the source PUML is translated into OUTPUT. 13 | Use FORMAT to define the output type (default: txt). 14 | Use MODE to switch between jar and server execution mode." 15 | (if format 16 | (setq plantuml-output-type format) 17 | (setq plantuml-output-type "txt")) 18 | (if mode 19 | (setq plantuml-exec-mode mode) 20 | (setq plantuml-exec-mode 'jar)) 21 | (plantuml-preview-string 42 (read-test-file puml)) 22 | (sleep-for 3) 23 | (should (equal (format-preview-output (replace-regexp-in-string " " "~" (read-test-file output))) 24 | (format-preview-output (replace-regexp-in-string " " "~" (read-preview-buffer)))))) 25 | 26 | (ert-deftest preview-txt-test () 27 | (setq-local plantuml-jar-path plantuml-test-jar-path) 28 | (assert-preview "a-b.puml" "a-b.txt")) 29 | 30 | ;; for unknown reason, unicode preview brakes on ert-runner but works locally :-/ 31 | ;;(ert-deftest preview-unicode-test () 32 | ;; (setq-local plantuml-jar-path plantuml-test-jar-path) 33 | ;; (assert-preview "unicode.puml" "unicode.txt")) 34 | 35 | (provide 'plantuml-mode-preview-test) 36 | 37 | ;;; plantuml-mode-preview-test.el ends here 38 | -------------------------------------------------------------------------------- /test/plantuml-indentation-deployment-test.el: -------------------------------------------------------------------------------- 1 | ;;; plantuml-indentation-deployment-test.el --- PlantUML Mode indentation tests -*- lexical-binding: t; -*- 2 | 3 | ;; Author: René Schmelzer 4 | ;; Maintainer: Carlo Sciolla (skuro) 5 | ;; URL: https://github.com/skuro/plantuml-mode 6 | 7 | ;;; Commentary: 8 | 9 | ;; Test indentation for deployment diagrams. 10 | ;; Most plantuml code examples are taken from www.plantuml.com 11 | 12 | ;;; Code: 13 | 14 | (ert-deftest plantuml-test-indentation/deployment-diagram () 15 | "Test correct indentation of plantuml deployment diagram elements." 16 | (plantuml-test-indent-block 17 | 18 | " 19 | artifact Foo1 { 20 | folder Foo2 21 | } 22 | 23 | folder Foo3 { 24 | artifact Foo4 25 | } 26 | 27 | frame Foo5 { 28 | database Foo6 29 | } 30 | 31 | cloud vpc { 32 | node ec2 { 33 | stack stack 34 | } 35 | } 36 | 37 | node Foo1 { 38 | cloud Foo2 39 | } 40 | 41 | cloud Foo3 { 42 | frame Foo4 43 | } 44 | 45 | database Foo5 { 46 | storage Foo6 47 | } 48 | 49 | storage Foo7 { 50 | storage Foo8 51 | } 52 | " 53 | " 54 | artifact Foo1 { 55 | folder Foo2 56 | } 57 | 58 | folder Foo3 { 59 | artifact Foo4 60 | } 61 | 62 | frame Foo5 { 63 | database Foo6 64 | } 65 | 66 | cloud vpc { 67 | node ec2 { 68 | stack stack 69 | } 70 | } 71 | 72 | node Foo1 { 73 | cloud Foo2 74 | } 75 | 76 | cloud Foo3 { 77 | frame Foo4 78 | } 79 | 80 | database Foo5 { 81 | storage Foo6 82 | } 83 | 84 | storage Foo7 { 85 | storage Foo8 86 | } 87 | ")) 88 | 89 | (ert-deftest plantuml-test-block-indentation/package-database-nested () 90 | "Test correct indentation of two nested blocks, a package and a database. 91 | Note: package is used in class and object diagrams as well, see there for more tests." 92 | (plantuml-test-indent-block 93 | " 94 | package APackage { 95 | database ADatabase { 96 | A -> B 97 | } 98 | } 99 | " 100 | " 101 | package APackage { 102 | database ADatabase { 103 | A -> B 104 | } 105 | } 106 | ")) 107 | 108 | 109 | (provide 'plantuml-indentation-deployment-test) 110 | 111 | ;;; plantuml-indentation-deployment-test.el ends here 112 | -------------------------------------------------------------------------------- /test/test-helper.el: -------------------------------------------------------------------------------- 1 | ;;; test-helper.el --- PlantUML Mode test initialization -*- lexical-binding: t; -*- 2 | 3 | ;; Author: Carlo Sciolla (skuro) 4 | ;; Maintainer: Carlo Sciolla (skuro) 5 | ;; URL: https://github.com/skuro/plantuml-mode 6 | 7 | ;;; Commentary: 8 | 9 | ;;; Code: 10 | 11 | (require 'f) 12 | (require 'subr-x) 13 | 14 | (defvar package-test-path 15 | (f-dirname (f-this-file))) 16 | 17 | (defvar package-code-path 18 | (f-parent package-test-path)) 19 | 20 | (defvar plantuml-test-resources-path 21 | (f-join package-code-path "test/resources")) 22 | 23 | (defvar plantuml-test-jar-path 24 | (f-join package-code-path "bin/plantuml.jar")) 25 | 26 | (defun read-buffer (bufname) 27 | (with-current-buffer (get-buffer bufname) 28 | (buffer-string))) 29 | 30 | (defun read-preview-buffer () 31 | (read-buffer plantuml-preview-buffer)) 32 | 33 | (defun read-test-file (path) 34 | (f-read (f-join plantuml-test-resources-path path) 'utf-8)) 35 | 36 | (defun load-plantuml-mode () 37 | (require 'plantuml-mode (f-expand "plantuml-mode.el" package-code-path))) 38 | 39 | (defun format-preview-output (s) 40 | "Make the preview output as S more readable in test output." 41 | (concat "\n" s)) 42 | 43 | (defun plantuml-test-indent-block (before after) 44 | "The common code for the block indentation tests. 45 | 46 | BEFORE is the text block to be inserted into a temporary buffer. 47 | AFTER is the expected text block after indentation. 48 | 49 | The temporary buffer will be put into `plantuml-mode'. The whole buffer 50 | will be indented with two spaces for each level of indentation. 51 | 52 | Finally, the indented text in the buffer will be compared with AFTER." 53 | 54 | (with-temp-buffer 55 | ;; fix the JAR location prior to mode initialization 56 | ;; for some reason, plantuml-mode disregards the setq-local 57 | (setq plantuml-jar-path plantuml-test-jar-path) 58 | (plantuml-init-once 'jar) 59 | 60 | (insert before) 61 | (goto-char (point-min)) 62 | (plantuml-mode) 63 | ;; use 2 spaces instead of one tab for indentation 64 | (setq indent-tabs-mode nil) 65 | (setq plantuml-indent-level 2) 66 | 67 | (indent-region (point-min) (point-max)) 68 | (should (equal (buffer-string) after)))) 69 | 70 | (defun plantuml-test-server (body) 71 | "Execute BODY while ensuring the PlantUML server is reachable." 72 | (with-temp-buffer 73 | (setq plantuml-server-url "http://localhost:8080") 74 | (setq plantuml-output-type "txt") 75 | (plantuml-init-once 'server) 76 | 77 | (funcall body))) 78 | 79 | ;; enable code coverage 80 | (when (require 'undercover nil t) 81 | (undercover "plantuml-mode.el")) 82 | 83 | (load-plantuml-mode) 84 | 85 | ;;; test-helper.el ends here 86 | -------------------------------------------------------------------------------- /test/resources/unindented.plantuml: -------------------------------------------------------------------------------- 1 | /' This is a manual test for you to test different use-cases '/ 2 | 3 | participant API 4 | participant Instance 5 | 6 | alt deploy success 7 | Instance -> API: Deploy successful 8 | else deploy failure 9 | Instance -> API: Deploy failed 10 | else deploy timeout 11 | Instance -> API: Deploy failed 12 | end 13 | 14 | 15 | package "kuaishow-common-proto" { 16 | component Kwai 17 | component KwaiGo 18 | component AcFun 19 | } 20 | 21 | package "kwaigo-log-proto" { 22 | [KwaiGo] ..> [KwaiGo Client->Data] : split 23 | } 24 | 25 | package "kwaigo-api-proto" { 26 | [KwaiGo] ..> [KwaiGo Client->Server] : split 27 | } 28 | 29 | cloud "log server\n" { 30 | [KwaiGo Client->Data] -->[KwaiGo Log Server] : upload 31 | } 32 | 33 | cloud "api server\n" { 34 | [KwaiGo Api Server] 35 | } 36 | 37 | [KwaiGo Client->Server] --> [KwaiGo Api Server] : request 38 | [KwaiGo Api Server] --> [KwaiGo Client->Server] : response 39 | 40 | database "LogSql" { 41 | folder "Log" { 42 | [ReportEvent] 43 | } 44 | frame "event" { 45 | [EventPackage] 46 | } 47 | 48 | frame "stat" { 49 | [StatPackage] 50 | } 51 | } 52 | 53 | [KwaiGo Log Server] --> [ReportEvent] : save 54 | [ReportEvent] --> [EventPackage] 55 | [ReportEvent] --> [StatPackage] 56 | 57 | database "ApiSql" { 58 | folder "kwaigo" { 59 | [KwaiGoData] 60 | } 61 | frame "user" { 62 | [UserData] 63 | } 64 | 65 | frame "photo" { 66 | [PhotoData] 67 | } 68 | } 69 | 70 | [KwaiGo Api Server] --> [KwaiGoData] : request 71 | [KwaiGoData] --> [KwaiGo Api Server] : compute 72 | 73 | [KwaiGoData] --> [UserData] 74 | [KwaiGoData] --> [PhotoData] 75 | 76 | 77 | Nobody -> [APIGateway] 78 | 79 | package APackage { 80 | A -> B 81 | B -> A 82 | } 83 | 84 | package "APP Stack" { 85 | [APIGateway] --> [Lambda] 86 | } 87 | 88 | package haha {} 89 | 90 | package "Streams Stack" { 91 | database Kinesis 92 | [Lambda] --> Kinesis 93 | } 94 | 95 | package foo { 96 | package bar { 97 | foo --> bar 98 | } 99 | 100 | package bar { 101 | foo --> bar 102 | } 103 | 104 | } 105 | 106 | 107 | package "Roles And Policies" { 108 | [Lambda] --> [IAM Roles] 109 | [APIGateway] --> [IAM Roles] 110 | } 111 | 112 | package "SharedResources" { 113 | [Lambda] ----> [LambdaCodeBucket] 114 | 115 | note as N1 116 | This belongs to a separate set 117 | of resources we should clean up 118 | separately. 119 | end note 120 | } 121 | 122 | note right of Lambda 123 | This thing is end of life 124 | end note 125 | 126 | note left of Nobody 127 | There is no traffic coming 128 | into the service. 129 | end note 130 | 131 | 132 | @startuml 133 | 134 | participant API 135 | participant Instance 136 | 137 | alt deploy success 138 | Instance -> API: Deploy successful 139 | else deploy failure 140 | Instance -> API: Deploy failed 141 | else deploy timeout 142 | Instance -> API: Deploy failed 143 | end 144 | 145 | @enduml 146 | -------------------------------------------------------------------------------- /test/plantuml-server-test.el: -------------------------------------------------------------------------------- 1 | ;;; plantuml-server-test.el --- Test against PlantUML servers (regular and pico) -*- lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2025 Carlo Sciolla 4 | 5 | ;; Author: Carlo Sciolla 6 | ;; Keywords: text, data 7 | 8 | ;; This program is free software; you can redistribute it and/or modify 9 | ;; it under the terms of the GNU General Public License as published by 10 | ;; the Free Software Foundation, either version 3 of the License, or 11 | ;; (at your option) any later version. 12 | 13 | ;; This program is distributed in the hope that it will be useful, 14 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | ;; GNU General Public License for more details. 17 | 18 | ;; You should have received a copy of the GNU General Public License 19 | ;; along with this program. If not, see . 20 | 21 | ;;; Commentary: 22 | 23 | ;; PlantUML offers two flavors of server-based rendering, here we test against 24 | ;; both of them 25 | 26 | ;;; Code: 27 | 28 | (ert-deftest plantuml-server-test/server-available () 29 | "Just to see if tagging works." 30 | :tags '(server) 31 | 32 | (plantuml-test-server 33 | (lambda () 34 | (plantuml-server-get-language (current-buffer))))) 35 | 36 | (ert-deftest plantuml-server-test/hex-encoding () 37 | "Test HEX encoding." 38 | :tags '(server) 39 | 40 | (plantuml-test-server 41 | (lambda () 42 | (setq-local plantuml-server-encode-mode 'hex) 43 | (plantuml-server-preview-string 0 "@startuml\nA -> B\n@enduml" (current-buffer)) 44 | 45 | (should (equal (concat " ┌─┐ ┌─┐\n" 46 | " │A│ │B│\n" 47 | " └┬┘ └┬┘\n" 48 | " │ │ \n" 49 | " │───────────>│ \n" 50 | " ┌┴┐ ┌┴┐\n" 51 | " │A│ │B│\n" 52 | " └─┘ └─┘\n") 53 | (buffer-string)))))) 54 | 55 | (ert-deftest plantuml-server-test/deflate-encoding () 56 | "Test DEFLATE encoding." 57 | :tags '(server) 58 | 59 | (plantuml-test-server 60 | (lambda () 61 | (setq-local plantuml-server-encode-mode 'deflate) 62 | (plantuml-server-preview-string 0 "@startuml\nA -> B\n@enduml" (current-buffer)) 63 | 64 | (should (equal (concat " ┌─┐ ┌─┐\n" 65 | " │A│ │B│\n" 66 | " └┬┘ └┬┘\n" 67 | " │ │ \n" 68 | " │───────────>│ \n" 69 | " ┌┴┐ ┌┴┐\n" 70 | " │A│ │B│\n" 71 | " └─┘ └─┘\n") 72 | (buffer-string)))))) 73 | 74 | 75 | 76 | (provide 'plantuml-server-test) 77 | ;;; plantuml-server-test.el ends here 78 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2.0 2 | 3 | # Default actions to perform on each Emacs version 4 | default: &default-steps 5 | steps: 6 | - restore_cache: 7 | name: Restore Emacs deps 8 | keys: 9 | - cask-{{ checksum "Cask" }} 10 | - run: 11 | name: Update APT packages 12 | command: apt-get update 13 | - run: 14 | name: Install prerequisites 15 | command: apt-get install -y openjdk-17-jre 16 | - checkout 17 | - run: 18 | # Note: this makes it hard to reproduce builds but easier to spot incompatibilities with 19 | # newer PlantUML releases. Current trade off seems acceptable. 20 | name: Download the latest PlantUML release 21 | command: sh ./bin/download-plantuml.sh 22 | - run: 23 | name: Download Cask deps 24 | command: cask install 25 | - run: 26 | name: Run the tests 27 | command: make unit 28 | - save_cache: 29 | name: Restore Emacs deps 30 | key: cask-{{ checksum "Cask" }} 31 | paths: 32 | - ~/.emacs.d 33 | 34 | # Enumerated list of Emacs versions 35 | jobs: 36 | test-emacs-25: 37 | docker: 38 | - image: silex/emacs:25-ci-cask 39 | entrypoint: bash 40 | <<: *default-steps 41 | 42 | test-emacs-26: 43 | docker: 44 | - image: silex/emacs:26-ci-cask 45 | entrypoint: bash 46 | <<: *default-steps 47 | 48 | test-emacs-27: 49 | docker: 50 | - image: silex/emacs:27-ci-cask 51 | entrypoint: bash 52 | <<: *default-steps 53 | 54 | test-emacs-28: 55 | docker: 56 | - image: silex/emacs:28-ci-cask 57 | entrypoint: bash 58 | <<: *default-steps 59 | 60 | test-emacs-29: 61 | docker: 62 | - image: silex/emacs:29-ci-cask 63 | entrypoint: bash 64 | <<: *default-steps 65 | 66 | test-emacs-30: 67 | docker: 68 | - image: silex/emacs:30-ci-cask 69 | entrypoint: bash 70 | <<: *default-steps 71 | 72 | test-emacs-master: 73 | docker: 74 | - image: silex/emacs:master-ci-cask 75 | entrypoint: bash 76 | <<: *default-steps 77 | 78 | test-plantuml-server: 79 | docker: 80 | - image: silex/emacs:30-ci-cask 81 | entrypoint: bash 82 | ## Server listens at port 8080 83 | - image: plantuml/plantuml-server:jetty 84 | steps: 85 | - checkout 86 | - restore_cache: 87 | name: Restore Emacs deps 88 | keys: 89 | - cask-{{ checksum "Cask" }} 90 | - run: 91 | name: Download Cask deps 92 | command: cask install 93 | - run: 94 | name: Run the tests 95 | command: make integration 96 | - run: 97 | name: Download Cask deps 98 | command: cask install 99 | - save_cache: 100 | name: Restore Emacs deps 101 | key: cask-{{ checksum "Cask" }} 102 | paths: 103 | - ~/.emacs.d 104 | 105 | # Executing in parallel 106 | workflows: 107 | version: 2 108 | ci-test-matrix: 109 | jobs: 110 | - test-emacs-25 111 | - test-emacs-26 112 | - test-emacs-27 113 | - test-emacs-28 114 | - test-emacs-29 115 | - test-emacs-30 116 | - test-emacs-master 117 | server: 118 | jobs: 119 | - test-plantuml-server 120 | -------------------------------------------------------------------------------- /test/plantuml-indentation-state-test.el: -------------------------------------------------------------------------------- 1 | ;;; plantuml-indentation-state-test.el --- PlantUML Mode indentation tests -*- lexical-binding: t; -*- 2 | 3 | ;; Author: René Schmelzer 4 | ;; Maintainer: Carlo Sciolla (skuro) 5 | ;; URL: https://github.com/skuro/plantuml-mode 6 | 7 | ;;; Commentary: 8 | 9 | ;; Test indentation for state diagrams. 10 | 11 | ;;; Code: 12 | 13 | (ert-deftest plantuml-test-indentation/state-diagram () 14 | "Test correct indentation of plantuml state diagram elements. 15 | These code examples are taken from www.plantuml.com" 16 | (plantuml-test-indent-block 17 | 18 | " 19 | state NotShooting { 20 | [*] --> Idle 21 | Idle --> Configuring : EvConfig 22 | Configuring --> Idle : EvConfig 23 | } 24 | 25 | state Configuring { 26 | [*] --> NewValueSelection 27 | NewValueSelection --> NewValuePreview : EvNewValue 28 | NewValuePreview --> NewValueSelection : EvNewValueRejected 29 | NewValuePreview --> NewValueSelection : EvNewValueSaved 30 | 31 | state NewValuePreview { 32 | State1 -> State2 33 | } 34 | 35 | } 36 | 37 | state State3 { 38 | state \"Accumulate Enough Data\\nLong State Name\" as long1 39 | long1 : Just a test 40 | [*] --> long1 41 | long1 --> long1 : New Data 42 | long1 --> ProcessData : Enough Data 43 | } 44 | 45 | state Active { 46 | [*] -> NumLockOff 47 | NumLockOff --> NumLockOn : EvNumLockPressed 48 | NumLockOn --> NumLockOff : EvNumLockPressed 49 | -- 50 | [*] -> CapsLockOff 51 | CapsLockOff --> CapsLockOn : EvCapsLockPressed 52 | CapsLockOn --> CapsLockOff : EvCapsLockPressed 53 | -- 54 | [*] -> ScrollLockOff 55 | ScrollLockOff --> ScrollLockOn : EvCapsLockPressed 56 | ScrollLockOn --> ScrollLockOff : EvCapsLockPressed 57 | } 58 | 59 | state \"Not Shooting State\" as NotShooting { 60 | state \"Idle mode\" as Idle 61 | state \"Configuring mode\" as Configuring 62 | [*] --> Idle 63 | Idle --> Configuring : EvConfig 64 | Configuring --> Idle : EvConfig 65 | } 66 | " 67 | " 68 | state NotShooting { 69 | [*] --> Idle 70 | Idle --> Configuring : EvConfig 71 | Configuring --> Idle : EvConfig 72 | } 73 | 74 | state Configuring { 75 | [*] --> NewValueSelection 76 | NewValueSelection --> NewValuePreview : EvNewValue 77 | NewValuePreview --> NewValueSelection : EvNewValueRejected 78 | NewValuePreview --> NewValueSelection : EvNewValueSaved 79 | 80 | state NewValuePreview { 81 | State1 -> State2 82 | } 83 | 84 | } 85 | 86 | state State3 { 87 | state \"Accumulate Enough Data\\nLong State Name\" as long1 88 | long1 : Just a test 89 | [*] --> long1 90 | long1 --> long1 : New Data 91 | long1 --> ProcessData : Enough Data 92 | } 93 | 94 | state Active { 95 | [*] -> NumLockOff 96 | NumLockOff --> NumLockOn : EvNumLockPressed 97 | NumLockOn --> NumLockOff : EvNumLockPressed 98 | -- 99 | [*] -> CapsLockOff 100 | CapsLockOff --> CapsLockOn : EvCapsLockPressed 101 | CapsLockOn --> CapsLockOff : EvCapsLockPressed 102 | -- 103 | [*] -> ScrollLockOff 104 | ScrollLockOff --> ScrollLockOn : EvCapsLockPressed 105 | ScrollLockOn --> ScrollLockOff : EvCapsLockPressed 106 | } 107 | 108 | state \"Not Shooting State\" as NotShooting { 109 | state \"Idle mode\" as Idle 110 | state \"Configuring mode\" as Configuring 111 | [*] --> Idle 112 | Idle --> Configuring : EvConfig 113 | Configuring --> Idle : EvConfig 114 | } 115 | ")) 116 | 117 | (provide 'plantuml-indentation-state-test) 118 | 119 | ;;; plantuml-indentation-state-test.el ends here 120 | -------------------------------------------------------------------------------- /test/plantuml-indentation-activity-old-test.el: -------------------------------------------------------------------------------- 1 | ;;; plantuml-indentation-activity-old-test.el --- PlantUML Mode indentation tests -*- lexical-binding: t; -*- 2 | 3 | ;; Author: René Schmelzer 4 | ;; Maintainer: Carlo Sciolla (skuro) 5 | ;; URL: https://github.com/skuro/plantuml-mode 6 | 7 | ;;; Commentary: 8 | 9 | ;; Test indentation for activity (old version) diagrams. 10 | 11 | ;;; Code: 12 | 13 | 14 | (ert-deftest plantuml-test-indentation/activity-old-diagram/branches () 15 | "Test correct indentation of plantuml activity-old diagram elements: branches. 16 | These code examples are taken from www.plantuml.com" 17 | (plantuml-test-indent-block 18 | " 19 | if \"Some Test\" then 20 | -->[true] \"Some Activity\" 21 | --> \"Another activity\" 22 | -right-> (*) 23 | else 24 | ->[false] \"Something else\" 25 | -->[Ending process] (*) 26 | endif 27 | 28 | (*) --> \"check input\" 29 | If \"input is verbose\" then 30 | --> [Yes] \"turn on verbosity\" 31 | --> \"run command\" 32 | else 33 | --> \"run command\" 34 | Endif 35 | -->(*) 36 | " 37 | " 38 | if \"Some Test\" then 39 | -->[true] \"Some Activity\" 40 | --> \"Another activity\" 41 | -right-> (*) 42 | else 43 | ->[false] \"Something else\" 44 | -->[Ending process] (*) 45 | endif 46 | 47 | (*) --> \"check input\" 48 | If \"input is verbose\" then 49 | --> [Yes] \"turn on verbosity\" 50 | --> \"run command\" 51 | else 52 | --> \"run command\" 53 | Endif 54 | -->(*) 55 | " 56 | )) 57 | 58 | (ert-deftest plantuml-test-indentation/activity-old-diagram/more-on-branches () 59 | "Test correct indentation of plantuml activity-old diagram elements: more on branches. 60 | These code examples are taken from www.plantuml.com" 61 | (plantuml-test-indent-block 62 | 63 | " 64 | (*) --> if \"Some Test\" then 65 | 66 | -->[true] \"activity 1\" 67 | 68 | if \"\" then 69 | -> \"activity 3\" as a3 70 | else 71 | if \"Other test\" then 72 | -left-> \"activity 5\" 73 | else 74 | --> \"activity 6\" 75 | endif 76 | endif 77 | 78 | else 79 | 80 | ->[false] \"activity 2\" 81 | 82 | endif 83 | 84 | a3 --> if \"last test\" then 85 | --> \"activity 7\" 86 | else 87 | -> \"activity 8\" 88 | endif 89 | " 90 | " 91 | (*) --> if \"Some Test\" then 92 | 93 | -->[true] \"activity 1\" 94 | 95 | if \"\" then 96 | -> \"activity 3\" as a3 97 | else 98 | if \"Other test\" then 99 | -left-> \"activity 5\" 100 | else 101 | --> \"activity 6\" 102 | endif 103 | endif 104 | 105 | else 106 | 107 | ->[false] \"activity 2\" 108 | 109 | endif 110 | 111 | a3 --> if \"last test\" then 112 | --> \"activity 7\" 113 | else 114 | -> \"activity 8\" 115 | endif 116 | " 117 | )) 118 | 119 | (ert-deftest plantuml-test-indentation/activity-old-diagram/partitions () 120 | "Test correct indentation of plantuml activity-old diagram elements: partitions. 121 | These code examples are taken from www.plantuml.com" 122 | (plantuml-test-indent-block 123 | 124 | " 125 | partition Conductor { 126 | (*) --> \"Climbs on Platform\" 127 | --> === S1 === 128 | --> Bows 129 | } 130 | 131 | partition Audience #LightSkyBlue { 132 | === S1 === --> Applauds 133 | } 134 | 135 | partition Conductor { 136 | Bows --> === S2 === 137 | --> WavesArmes 138 | Applauds --> === S2 === 139 | } 140 | 141 | partition Orchestra #CCCCEE { 142 | WavesArmes --> Introduction 143 | --> \"Play music\" 144 | } 145 | " 146 | " 147 | partition Conductor { 148 | (*) --> \"Climbs on Platform\" 149 | --> === S1 === 150 | --> Bows 151 | } 152 | 153 | partition Audience #LightSkyBlue { 154 | === S1 === --> Applauds 155 | } 156 | 157 | partition Conductor { 158 | Bows --> === S2 === 159 | --> WavesArmes 160 | Applauds --> === S2 === 161 | } 162 | 163 | partition Orchestra #CCCCEE { 164 | WavesArmes --> Introduction 165 | --> \"Play music\" 166 | } 167 | ")) 168 | 169 | (ert-deftest plantuml-test-indentation/activity-old-diagram/complete-example () 170 | "Test correct indentation of plantuml activity-old diagram elements: complete example. 171 | These code examples are taken from www.plantuml.com" 172 | (plantuml-test-indent-block 173 | 174 | " 175 | title Servlet Container 176 | 177 | (*) --> \"ClickServlet.handleRequest()\" 178 | --> \"new Page\" 179 | 180 | if \"Page.onSecurityCheck\" then 181 | ->[true] \"Page.onInit()\" 182 | 183 | if \"isForward?\" then 184 | ->[no] \"Process controls\" 185 | 186 | if \"continue processing?\" then 187 | -->[yes] ===RENDERING=== 188 | else 189 | -->[no] ===REDIRECT_CHECK=== 190 | endif 191 | 192 | else 193 | -->[yes] ===RENDERING=== 194 | endif 195 | 196 | if \"is Post?\" then 197 | -->[yes] \"Page.onPost()\" 198 | --> \"Page.onRender()\" as render 199 | --> ===REDIRECT_CHECK=== 200 | else 201 | -->[no] \"Page.onGet()\" 202 | --> render 203 | endif 204 | 205 | else 206 | -->[false] ===REDIRECT_CHECK=== 207 | endif 208 | 209 | if \"Do redirect?\" then 210 | ->[yes] \"redirect request\" 211 | --> ==BEFORE_DESTROY=== 212 | else 213 | if \"Do Forward?\" then 214 | -left->[yes] \"Forward request\" 215 | --> ==BEFORE_DESTROY=== 216 | else 217 | -right->[no] \"Render page template\" 218 | --> ==BEFORE_DESTROY=== 219 | endif 220 | endif 221 | 222 | --> \"Page.onDestroy()\" 223 | -->(*) 224 | " 225 | " 226 | title Servlet Container 227 | 228 | (*) --> \"ClickServlet.handleRequest()\" 229 | --> \"new Page\" 230 | 231 | if \"Page.onSecurityCheck\" then 232 | ->[true] \"Page.onInit()\" 233 | 234 | if \"isForward?\" then 235 | ->[no] \"Process controls\" 236 | 237 | if \"continue processing?\" then 238 | -->[yes] ===RENDERING=== 239 | else 240 | -->[no] ===REDIRECT_CHECK=== 241 | endif 242 | 243 | else 244 | -->[yes] ===RENDERING=== 245 | endif 246 | 247 | if \"is Post?\" then 248 | -->[yes] \"Page.onPost()\" 249 | --> \"Page.onRender()\" as render 250 | --> ===REDIRECT_CHECK=== 251 | else 252 | -->[no] \"Page.onGet()\" 253 | --> render 254 | endif 255 | 256 | else 257 | -->[false] ===REDIRECT_CHECK=== 258 | endif 259 | 260 | if \"Do redirect?\" then 261 | ->[yes] \"redirect request\" 262 | --> ==BEFORE_DESTROY=== 263 | else 264 | if \"Do Forward?\" then 265 | -left->[yes] \"Forward request\" 266 | --> ==BEFORE_DESTROY=== 267 | else 268 | -right->[no] \"Render page template\" 269 | --> ==BEFORE_DESTROY=== 270 | endif 271 | endif 272 | 273 | --> \"Page.onDestroy()\" 274 | -->(*) 275 | " 276 | )) 277 | 278 | 279 | (provide 'plantuml-indentation-activity-old-test) 280 | 281 | ;;; plantuml-indentation-activity-old-test.el ends here 282 | -------------------------------------------------------------------------------- /test/plantuml-indentation-commons-test.el: -------------------------------------------------------------------------------- 1 | ;;; plantuml-indentation-commons-test.el --- PlantUML Mode indentation tests -*- lexical-binding: t; -*- 2 | 3 | ;; Author: René Schmelzer 4 | ;; Maintainer: Carlo Sciolla (skuro) 5 | ;; URL: https://github.com/skuro/plantuml-mode 6 | 7 | ;;; Commentary: 8 | 9 | ;; Test indentation of structures and elements that are common 10 | ;; to many/all diagrams. 11 | 12 | ;;; Code: 13 | 14 | (ert-deftest plantuml-test-indentation/commons/skinparam () 15 | "Test correct indentation of skinparam elements, which are common to many plantuml diagrams:" 16 | (plantuml-test-indent-block 17 | 18 | " 19 | skinparam roundcorner 20 20 | 21 | skinparam rectangle { 22 | roundCorner<> 25 23 | } 24 | " 25 | " 26 | skinparam roundcorner 20 27 | 28 | skinparam rectangle { 29 | roundCorner<> 25 30 | } 31 | ")) 32 | 33 | (ert-deftest plantuml-test-indentation/commons/rectangle () 34 | "Test correct indentation of rectangle elements, which are common to many plantuml diagrams:" 35 | (plantuml-test-indent-block 36 | 37 | " 38 | rectangle \"Concept Model\" <> { 39 | rectangle \"Example 1\" <> as ex1 40 | rectangle \"Another rectangle\" 41 | } 42 | " 43 | " 44 | rectangle \"Concept Model\" <> { 45 | rectangle \"Example 1\" <> as ex1 46 | rectangle \"Another rectangle\" 47 | } 48 | ")) 49 | 50 | (ert-deftest plantuml-test-indentation/commons/title () 51 | "Test correct indentation of title elements, which are common to many plantuml diagrams:" 52 | (plantuml-test-indent-block 53 | " 54 | title 55 | Warning: 56 | Do not use in production. 57 | end title 58 | " 59 | " 60 | title 61 | Warning: 62 | Do not use in production. 63 | end title 64 | " )) 65 | 66 | (ert-deftest plantuml-test-indentation/commons/header () 67 | "Test correct indentation of header elements, which are common to many plantuml diagrams:" 68 | (plantuml-test-indent-block 69 | " 70 | header 71 | this is a header 72 | endheader 73 | 74 | center header 75 | this is a centered header 76 | endheader 77 | 78 | right header 79 | this is a header on right 80 | endheader 81 | 82 | left header 83 | this is a header on left 84 | endheader 85 | 86 | center left header 87 | this is no correct header 88 | endheader 89 | 90 | header left 91 | this is no correct a header 92 | endheader 93 | " 94 | " 95 | header 96 | this is a header 97 | endheader 98 | 99 | center header 100 | this is a centered header 101 | endheader 102 | 103 | right header 104 | this is a header on right 105 | endheader 106 | 107 | left header 108 | this is a header on left 109 | endheader 110 | 111 | center left header 112 | this is no correct header 113 | endheader 114 | 115 | header left 116 | this is no correct a header 117 | endheader 118 | " )) 119 | 120 | (ert-deftest plantuml-test-indentation/commons/footer () 121 | "Test correct indentation of footer elements, which are common to many plantuml diagrams:" 122 | (plantuml-test-indent-block 123 | " 124 | footer 125 | this is a footer 126 | endfooter 127 | 128 | center footer 129 | this is a centered footer 130 | endfooter 131 | 132 | right footer 133 | this is a footer on right 134 | endfooter 135 | 136 | left footer 137 | this is a footer on left 138 | endfooter 139 | 140 | center left footer 141 | this is no correct footer 142 | endfooter 143 | 144 | footer left 145 | this is no correct a footer 146 | endfooter 147 | " 148 | " 149 | footer 150 | this is a footer 151 | endfooter 152 | 153 | center footer 154 | this is a centered footer 155 | endfooter 156 | 157 | right footer 158 | this is a footer on right 159 | endfooter 160 | 161 | left footer 162 | this is a footer on left 163 | endfooter 164 | 165 | center left footer 166 | this is no correct footer 167 | endfooter 168 | 169 | footer left 170 | this is no correct a footer 171 | endfooter 172 | " )) 173 | 174 | 175 | (ert-deftest plantuml-test-indentation/commons/legend () 176 | "Test correct indentation of legend elements, which are common to many plantuml diagrams:" 177 | (plantuml-test-indent-block 178 | " 179 | legend 180 | Short legend 181 | endlegend 182 | 183 | legend bottom 184 | bottom legend 185 | endlegend 186 | 187 | legend top 188 | top legend 189 | endlegend 190 | 191 | legend center 192 | centered legend 193 | endlegend 194 | 195 | legend right 196 | legend on right 197 | endlegend 198 | 199 | legend left 200 | legend on left 201 | endlegend 202 | 203 | legend bottom left 204 | legend on bottom left 205 | endlegend 206 | 207 | legend top left 208 | legend on top left 209 | endlegend 210 | 211 | legend bottom right 212 | legend on bottom right 213 | endlegend 214 | 215 | legend top right 216 | legend on top right 217 | endlegend 218 | " 219 | " 220 | legend 221 | Short legend 222 | endlegend 223 | 224 | legend bottom 225 | bottom legend 226 | endlegend 227 | 228 | legend top 229 | top legend 230 | endlegend 231 | 232 | legend center 233 | centered legend 234 | endlegend 235 | 236 | legend right 237 | legend on right 238 | endlegend 239 | 240 | legend left 241 | legend on left 242 | endlegend 243 | 244 | legend bottom left 245 | legend on bottom left 246 | endlegend 247 | 248 | legend top left 249 | legend on top left 250 | endlegend 251 | 252 | legend bottom right 253 | legend on bottom right 254 | endlegend 255 | 256 | legend top right 257 | legend on top right 258 | endlegend 259 | " )) 260 | 261 | 262 | (ert-deftest plantuml-test-indentation/commons/legend-noindent () 263 | "Test the not-indentation of false legend elements." 264 | (plantuml-test-indent-block 265 | " 266 | legend bottom top 267 | this is no correct legend 268 | endlegend 269 | 270 | legend right bottom 271 | this is no correct legend 272 | endlegend 273 | 274 | legend left top 275 | this is no correct legend 276 | endlegend 277 | 278 | legend center right 279 | this is no correct legend 280 | endlegend 281 | 282 | legend center left 283 | this is no correct legend 284 | endlegend 285 | 286 | legend right left 287 | this is no correct legend 288 | endlegend 289 | " 290 | " 291 | legend bottom top 292 | this is no correct legend 293 | endlegend 294 | 295 | legend right bottom 296 | this is no correct legend 297 | endlegend 298 | 299 | legend left top 300 | this is no correct legend 301 | endlegend 302 | 303 | legend center right 304 | this is no correct legend 305 | endlegend 306 | 307 | legend center left 308 | this is no correct legend 309 | endlegend 310 | 311 | legend right left 312 | this is no correct legend 313 | endlegend 314 | " 315 | )) 316 | 317 | (ert-deftest plantuml-test-indentation/commons/multiline-macro () 318 | "Test the indentation of multiline macro elements." 319 | (plantuml-test-indent-block 320 | 321 | " 322 | !define DOUBLE(x) x x 323 | !definelong AUTHEN(x,y) 324 | x -> y : DOUBLE(hello) 325 | y -> x : ok 326 | !enddefinelong 327 | 328 | AUTHEN(Bob,Alice) 329 | " 330 | " 331 | !define DOUBLE(x) x x 332 | !definelong AUTHEN(x,y) 333 | x -> y : DOUBLE(hello) 334 | y -> x : ok 335 | !enddefinelong 336 | 337 | AUTHEN(Bob,Alice) 338 | " 339 | )) 340 | ;;; plantuml-indentation-commons-test.el ends here 341 | -------------------------------------------------------------------------------- /test/plantuml-indentation-class-test.el: -------------------------------------------------------------------------------- 1 | ;;; plantuml-indentation-class-test.el --- PlantUML Mode indentation tests -*- lexical-binding: t; -*- 2 | 3 | ;; Author: René Schmelzer 4 | ;; Maintainer: Carlo Sciolla (skuro) 5 | ;; URL: https://github.com/skuro/plantuml-mode 6 | 7 | ;;; Commentary: 8 | 9 | ;; Test indentation for class diagrams. 10 | 11 | ;;; Code: 12 | 13 | (ert-deftest plantuml-test-indentation/class-diagram () 14 | "Test correct indentation of plantuml class diagram elements. 15 | These code examples are taken from www.plantuml.com" 16 | (plantuml-test-indent-block 17 | 18 | " 19 | class Dummy { 20 | String data 21 | void methods() 22 | } 23 | 24 | class Flight { 25 | flightNumber : Integer 26 | departureTime : Date 27 | } 28 | 29 | class Dummy1 { 30 | {field} A field (despite parentheses) 31 | {method} Some method 32 | } 33 | 34 | class Dummy2 { 35 | -field1 36 | #field2 37 | ~method1() 38 | +method2() 39 | } 40 | 41 | class Dummy3 { 42 | {static} String id 43 | {abstract} void methods() 44 | } 45 | 46 | class Foo1 { 47 | You can use 48 | several lines 49 | .. 50 | as you want 51 | and group 52 | == 53 | things together. 54 | __ 55 | You can have as many groups 56 | as you want 57 | -- 58 | End of class 59 | } 60 | 61 | class User { 62 | .. Simple Getter .. 63 | + getName() 64 | + getAddress() 65 | .. Some setter .. 66 | + setName() 67 | __ private data __ 68 | int age 69 | -- encrypted -- 70 | String password 71 | } 72 | 73 | class ArrayList { 74 | Object[] elementData 75 | size() 76 | } 77 | 78 | enum TimeUnit { 79 | DAYS 80 | HOURS 81 | MINUTES 82 | } 83 | 84 | class Dummy4 <> { 85 | String name 86 | } 87 | 88 | class Foo { 89 | int size() 90 | } 91 | 92 | abtract class AbstractC { 93 | int size() 94 | } 95 | 96 | interface InterfaceC { 97 | int size() 98 | } 99 | 100 | package \"Classic Collections\" #DDDDDD { 101 | Object <|-- ArrayList 102 | } 103 | 104 | package net.sourceforge.plantuml { 105 | Object <|-- Demo1 106 | Demo1 *- Demo2 107 | } 108 | 109 | package foo1 <> { 110 | class Class1 111 | } 112 | 113 | package foo2 <> { 114 | class Class2 115 | } 116 | 117 | package foo3 <> { 118 | class Class3 119 | } 120 | 121 | package foo4 <> { 122 | class Class4 123 | } 124 | 125 | package foo5 <> { 126 | class Class5 127 | } 128 | 129 | package foo6 <> { 130 | class Class6 131 | } 132 | 133 | package foo1.foo2 { 134 | class ObjectFoo1Foo2 135 | } 136 | 137 | package foo1.foo2.foo3 { 138 | class Objectfoo1.foo2.foo3 139 | } 140 | 141 | namespace net.dummy #DDDDDD { 142 | .BaseClass <|-- Person 143 | Meeting o-- Person 144 | 145 | .BaseClass <|- Meeting 146 | } 147 | 148 | namespace net.foo { 149 | net.dummy.Person <|- Person 150 | .BaseClass <|-- Person 151 | 152 | net.dummy.Meeting o-- Person 153 | } 154 | 155 | set namespaceSeparator :: 156 | class X1::X2::foo { 157 | some info 158 | } 159 | 160 | together { 161 | class Together1 162 | class Together2 163 | class Together3 164 | } 165 | " 166 | " 167 | class Dummy { 168 | String data 169 | void methods() 170 | } 171 | 172 | class Flight { 173 | flightNumber : Integer 174 | departureTime : Date 175 | } 176 | 177 | class Dummy1 { 178 | {field} A field (despite parentheses) 179 | {method} Some method 180 | } 181 | 182 | class Dummy2 { 183 | -field1 184 | #field2 185 | ~method1() 186 | +method2() 187 | } 188 | 189 | class Dummy3 { 190 | {static} String id 191 | {abstract} void methods() 192 | } 193 | 194 | class Foo1 { 195 | You can use 196 | several lines 197 | .. 198 | as you want 199 | and group 200 | == 201 | things together. 202 | __ 203 | You can have as many groups 204 | as you want 205 | -- 206 | End of class 207 | } 208 | 209 | class User { 210 | .. Simple Getter .. 211 | + getName() 212 | + getAddress() 213 | .. Some setter .. 214 | + setName() 215 | __ private data __ 216 | int age 217 | -- encrypted -- 218 | String password 219 | } 220 | 221 | class ArrayList { 222 | Object[] elementData 223 | size() 224 | } 225 | 226 | enum TimeUnit { 227 | DAYS 228 | HOURS 229 | MINUTES 230 | } 231 | 232 | class Dummy4 <> { 233 | String name 234 | } 235 | 236 | class Foo { 237 | int size() 238 | } 239 | 240 | abtract class AbstractC { 241 | int size() 242 | } 243 | 244 | interface InterfaceC { 245 | int size() 246 | } 247 | 248 | package \"Classic Collections\" #DDDDDD { 249 | Object <|-- ArrayList 250 | } 251 | 252 | package net.sourceforge.plantuml { 253 | Object <|-- Demo1 254 | Demo1 *- Demo2 255 | } 256 | 257 | package foo1 <> { 258 | class Class1 259 | } 260 | 261 | package foo2 <> { 262 | class Class2 263 | } 264 | 265 | package foo3 <> { 266 | class Class3 267 | } 268 | 269 | package foo4 <> { 270 | class Class4 271 | } 272 | 273 | package foo5 <> { 274 | class Class5 275 | } 276 | 277 | package foo6 <> { 278 | class Class6 279 | } 280 | 281 | package foo1.foo2 { 282 | class ObjectFoo1Foo2 283 | } 284 | 285 | package foo1.foo2.foo3 { 286 | class Objectfoo1.foo2.foo3 287 | } 288 | 289 | namespace net.dummy #DDDDDD { 290 | .BaseClass <|-- Person 291 | Meeting o-- Person 292 | 293 | .BaseClass <|- Meeting 294 | } 295 | 296 | namespace net.foo { 297 | net.dummy.Person <|- Person 298 | .BaseClass <|-- Person 299 | 300 | net.dummy.Meeting o-- Person 301 | } 302 | 303 | set namespaceSeparator :: 304 | class X1::X2::foo { 305 | some info 306 | } 307 | 308 | together { 309 | class Together1 310 | class Together2 311 | class Together3 312 | } 313 | ")) 314 | 315 | 316 | (ert-deftest plantuml-test-block-indentation/class/package-empty () 317 | "Test correct indentation of an empty package block." 318 | (plantuml-test-indent-block 319 | " 320 | package APackage () 321 | interface Inter 322 | " 323 | " 324 | package APackage () 325 | interface Inter 326 | ")) 327 | 328 | 329 | (ert-deftest platuml-test-block-indentation/class/package-interface-nested () 330 | "Test correct indentation of two nested blocks, a package and an interface 331 | Note: package is used in deployment and object diagrams as well, see there for more tests." 332 | (plantuml-test-indent-block 333 | " 334 | package foo { 335 | interface Bar { 336 | baz 337 | } 338 | } 339 | " 340 | " 341 | package foo { 342 | interface Bar { 343 | baz 344 | } 345 | } 346 | ")) 347 | 348 | 349 | (provide 'plantuml-indentation-class-test) 350 | 351 | ;;; plantuml-indentation-class-test.el ends here 352 | -------------------------------------------------------------------------------- /test/plantuml-indentation-sequence-test.el: -------------------------------------------------------------------------------- 1 | ;;; plantuml-indentation-sequence-test.el --- PlantUML Mode indentation tests -*- lexical-binding: t; -*- 2 | 3 | ;; Author: René Schmelzer 4 | ;; Maintainer: Carlo Sciolla (skuro) 5 | ;; URL: https://github.com/skuro/plantuml-mode 6 | 7 | ;;; Commentary: 8 | 9 | ;; Test indentation for sequence diagrams. 10 | 11 | ;;; Code: 12 | 13 | 14 | (ert-deftest platuml-test-block-indentation/sequence/box () 15 | "Test correct indentation of a box block" 16 | (plantuml-test-indent-block 17 | " 18 | box \"Device with USB connector\" 19 | actor Human 20 | participant UsbDetector 21 | end box 22 | " 23 | " 24 | box \"Device with USB connector\" 25 | actor Human 26 | participant UsbDetector 27 | end box 28 | " )) 29 | 30 | (ert-deftest platuml-test-block-indentation/sequence/ref () 31 | "Test correct indentation of a ref block" 32 | (plantuml-test-indent-block 33 | " 34 | participant Alice 35 | actor Bob 36 | participant \"Great Cesar\" 37 | 38 | ref over Alice, Bob : init 39 | 40 | Alice -> Bob : hello 41 | 42 | ref over Bob, \"Great Cesar\" 43 | This can be on 44 | several lines 45 | end ref 46 | 47 | ref over Bob 48 | This is a ref over Bob 49 | end ref 50 | 51 | ref over \"Great Cesar\" 52 | This is a ref over \"Great Cesar\" 53 | end ref 54 | " 55 | 56 | " 57 | participant Alice 58 | actor Bob 59 | participant \"Great Cesar\" 60 | 61 | ref over Alice, Bob : init 62 | 63 | Alice -> Bob : hello 64 | 65 | ref over Bob, \"Great Cesar\" 66 | This can be on 67 | several lines 68 | end ref 69 | 70 | ref over Bob 71 | This is a ref over Bob 72 | end ref 73 | 74 | ref over \"Great Cesar\" 75 | This is a ref over \"Great Cesar\" 76 | end ref 77 | " )) 78 | 79 | 80 | (ert-deftest plantuml-test-block-indentation/sequence/alt-end () 81 | "Test correct indentation of an alt-end block. 82 | The alt-keyword is NOT followed by some text." 83 | (plantuml-test-indent-block 84 | " 85 | alt 86 | A -> B 87 | end 88 | " 89 | " 90 | alt 91 | A -> B 92 | end 93 | " )) 94 | 95 | (ert-deftest plantuml-test-block-indentation/sequence/alt-end-with-label () 96 | "Test correct indentation of an alt-end block. 97 | The alt-keyword is followed by some text." 98 | (plantuml-test-indent-block 99 | " 100 | alt choice 1 101 | A -> B 102 | end 103 | " 104 | " 105 | alt choice 1 106 | A -> B 107 | end 108 | " )) 109 | 110 | (ert-deftest plantuml-test-block-indentation/sequence/alt-else-end () 111 | "Test correct indentation of an alt-else-end block." 112 | (plantuml-test-indent-block 113 | " 114 | alt choice 1 115 | A -> B 116 | else 117 | B -> C 118 | end 119 | " 120 | " 121 | alt choice 1 122 | A -> B 123 | else 124 | B -> C 125 | end 126 | " )) 127 | 128 | (ert-deftest plantuml-test-block-indentation/sequence/opt () 129 | "Test correct indentation of an opt block. 130 | The opt-keyword is NOT followed by some text." 131 | (plantuml-test-indent-block 132 | " 133 | opt 134 | A -> B 135 | end 136 | " 137 | " 138 | opt 139 | A -> B 140 | end 141 | " )) 142 | 143 | (ert-deftest plantuml-test-block-indentation/sequence/opt-with-label () 144 | "Test correct indentation of an opt block. 145 | The opt-keyword is followed by some text." 146 | (plantuml-test-indent-block 147 | " 148 | opt event triggered 149 | A -> B 150 | end 151 | " 152 | " 153 | opt event triggered 154 | A -> B 155 | end 156 | " )) 157 | 158 | (ert-deftest plantuml-test-block-indentation/sequence/par () 159 | "Test correct indentation of a par block. 160 | The par-keyword is NOT followed by some text." 161 | (plantuml-test-indent-block 162 | " 163 | par 164 | A -> B 165 | else 166 | C -> B 167 | end 168 | " 169 | " 170 | par 171 | A -> B 172 | else 173 | C -> B 174 | end 175 | " )) 176 | 177 | (ert-deftest plantuml-test-block-indentation/sequence/par-with-label () 178 | "Test correct indentation of a par block. 179 | The par-keyword is followed by some text." 180 | (plantuml-test-indent-block 181 | " 182 | par a text label 183 | A -> B 184 | else 185 | C -> B 186 | end 187 | " 188 | " 189 | par a text label 190 | A -> B 191 | else 192 | C -> B 193 | end 194 | " )) 195 | 196 | (ert-deftest plantuml-test-block-indentation/sequence/group () 197 | "Test correct indentation of a group block. 198 | The group-keyword is NOT followed by some text." 199 | (plantuml-test-indent-block 200 | " 201 | group 202 | A -> B 203 | else 204 | C -> B 205 | end 206 | " 207 | " 208 | group 209 | A -> B 210 | else 211 | C -> B 212 | end 213 | " )) 214 | 215 | (ert-deftest plantuml-test-block-indentation/sequence/group-with-label () 216 | "Test correct indentation of a group block. 217 | The group-keyword is followed by some text." 218 | (plantuml-test-indent-block 219 | " 220 | group my own label 221 | A -> B 222 | else 223 | C -> B 224 | end 225 | " 226 | " 227 | group my own label 228 | A -> B 229 | else 230 | C -> B 231 | end 232 | " )) 233 | 234 | (ert-deftest plantuml-test-block-indentation/sequence/critical () 235 | "Test correct indentation of a critical block. 236 | The critical-keyword is NOT followed by some text." 237 | (plantuml-test-indent-block 238 | " 239 | critical 240 | A -> B 241 | else 242 | C -> B 243 | end 244 | " 245 | " 246 | critical 247 | A -> B 248 | else 249 | C -> B 250 | end 251 | " )) 252 | 253 | (ert-deftest plantuml-test-block-indentation/sequence/critical-with-label () 254 | "Test correct indentation of a critical block. 255 | The critical-keyword is followed by some text." 256 | (plantuml-test-indent-block 257 | " 258 | critical my own label 259 | A -> B 260 | else 261 | C -> B 262 | end 263 | " 264 | " 265 | critical my own label 266 | A -> B 267 | else 268 | C -> B 269 | end 270 | " )) 271 | 272 | 273 | (ert-deftest plantuml-test-block-indentation/sequence/activate-deactivate () 274 | "Test correct indentation of an activate-deactivate block." 275 | (plantuml-test-indent-block 276 | " 277 | activate participant_1 278 | participant_1 -> participant_2 : f() 279 | deactivate participant_1 280 | " 281 | " 282 | activate participant_1 283 | participant_1 -> participant_2 : f() 284 | deactivate participant_1 285 | ")) 286 | 287 | (ert-deftest plantuml-test-block-indentation/sequence/activate-deactivate-nested () 288 | "Test correct indentation of two nested activate-deactivate blocks." 289 | (plantuml-test-indent-block 290 | " 291 | activate participant_1 292 | activate participant_2 293 | participant_1 -> participant_2 : f() 294 | deactivate participant_2 295 | deactivate participant_1 296 | " 297 | " 298 | activate participant_1 299 | activate participant_2 300 | participant_1 -> participant_2 : f() 301 | deactivate participant_2 302 | deactivate participant_1 303 | ")) 304 | 305 | 306 | (ert-deftest plantuml-test-indentation/sequence-diagram () 307 | "Test correct indentation of plantuml sequence diagram elements. 308 | These code examples are taken from www.plantuml.com." 309 | (plantuml-test-indent-block 310 | " 311 | Alice -> Bob: Authentication Request 312 | 313 | alt successful case 314 | 315 | Bob -> Alice: Authentication Accepted 316 | 317 | else some kind of failure 318 | 319 | Bob -> Alice: Authentication Failure 320 | group My own label 321 | Alice -> Log : Log attack start 322 | loop 1000 times 323 | Alice -> Bob: DNS Attack 324 | end 325 | Alice -> Log : Log attack end 326 | end 327 | 328 | else Another type of failure 329 | 330 | Bob -> Alice: Please repeat 331 | 332 | end 333 | " 334 | " 335 | Alice -> Bob: Authentication Request 336 | 337 | alt successful case 338 | 339 | Bob -> Alice: Authentication Accepted 340 | 341 | else some kind of failure 342 | 343 | Bob -> Alice: Authentication Failure 344 | group My own label 345 | Alice -> Log : Log attack start 346 | loop 1000 times 347 | Alice -> Bob: DNS Attack 348 | end 349 | Alice -> Log : Log attack end 350 | end 351 | 352 | else Another type of failure 353 | 354 | Bob -> Alice: Please repeat 355 | 356 | end 357 | ")) 358 | 359 | 360 | (provide 'plantuml-indentation-sequence-test) 361 | 362 | ;;; plantuml-indentation-sequence-test.el ends here 363 | -------------------------------------------------------------------------------- /test/plantuml-indentation-basics-test.el: -------------------------------------------------------------------------------- 1 | ;;; plantuml-indentation-basics-test.el --- PlantUML Mode indentation tests -*- lexical-binding: t; -*- 2 | 3 | ;; Author: Raymond Huang (rymndhng) 4 | ;; Maintainer: Carlo Sciolla (skuro) 5 | ;; URL: https://github.com/skuro/plantuml-mode 6 | 7 | ;;; Commentary: 8 | 9 | ;; Test basics like single correct indentation depth etc. Focus is not on diagram contents 10 | ;; and context; such things are tested in the diagram specific indentation tests. 11 | ;; Test setup is inspired/taken from clojure-mode-indentation-tests 12 | 13 | ;;; Code: 14 | 15 | (defun plantuml-test-add-text-and-position-cursor (txt) 16 | "Test helper for `plantuml-mode'. 17 | Add TXT into the buffer, move cursor to the position of the marker 18 | ?| and delete the marker." 19 | (insert txt) 20 | (goto-char (point-min)) 21 | (search-forward "|") 22 | (delete-char -1)) 23 | 24 | (defun plantuml-test-assert-block-depth (expected txt) 25 | "Test helper for `plantuml-mode'. 26 | Assert the EXPECTED indentation level for the given TXT." 27 | (with-temp-buffer 28 | (plantuml-test-add-text-and-position-cursor txt) 29 | (let ((actual (plantuml-current-block-depth))) 30 | (should (equal expected actual))))) 31 | 32 | (ert-deftest plantuml-test-current-block-depth_bob () 33 | "Test `plantuml-current-block-depth' level 0 at beginning of buffer." 34 | (setq-local plantuml-jar-path plantuml-test-jar-path) 35 | (plantuml-init-once) 36 | 37 | (plantuml-test-assert-block-depth 0 "| 38 | activate p1 39 | activate p2 40 | foo 41 | deactivate p2 42 | deactivate p1 43 | ")) 44 | 45 | (ert-deftest plantuml-test-current-block-depth_0 () 46 | "Test `plantuml-current-block-depth' level 0 at beginning of first line." 47 | (setq-local plantuml-jar-path plantuml-test-jar-path) 48 | (plantuml-init-once) 49 | 50 | (plantuml-test-assert-block-depth 0 " 51 | |activate p1 52 | activate p2 53 | foo 54 | deactivate p2 55 | deactivate p1 56 | ")) 57 | 58 | (ert-deftest plantuml-test-current-block-depth_1 () 59 | "Test `plantuml-current-block-depth' level 0 at middle of first line." 60 | (setq-local plantuml-jar-path plantuml-test-jar-path) 61 | (plantuml-init-once) 62 | 63 | (plantuml-test-assert-block-depth 0 " 64 | acti|vate p1 65 | activate p2 66 | foo 67 | deactivate p2 68 | deactivate p1 69 | ")) 70 | 71 | (ert-deftest plantuml-test-current-block-depth_2 () 72 | "Test `plantuml-current-block-depth' level 0 at end of first line" 73 | (setq-local plantuml-jar-path plantuml-test-jar-path) 74 | (plantuml-init-once) 75 | 76 | (plantuml-test-assert-block-depth 0 " 77 | activate p1| 78 | activate p2 79 | foo 80 | deactivate p2 81 | deactivate p1 82 | ")) 83 | 84 | (ert-deftest plantuml-test-current-block-depth_3 () 85 | "Test `plantuml-current-block-depth' level 1 at beginning of 2nd line." 86 | 87 | (plantuml-test-assert-block-depth 1 " 88 | activate p1 89 | |activate p2 90 | foo 91 | deactivate p2 92 | deactivate p1 93 | ")) 94 | 95 | (ert-deftest plantuml-test-current-block-depth_4 () 96 | "Test `plantuml-current-block-depth' level 2 at beginning of 3rd line." 97 | 98 | (plantuml-test-assert-block-depth 2 " 99 | activate p1 100 | activate p2 101 | |foo 102 | deactivate p2 103 | deactivate p1 104 | ")) 105 | 106 | (ert-deftest plantuml-test-current-block-depth_5 () 107 | "Test `plantuml-current-block-depth' level 1 at beginning of 4th line." 108 | 109 | (plantuml-test-assert-block-depth 1 " 110 | activate p1 111 | activate p2 112 | foo 113 | |deactivate p2 114 | deactivate p1 115 | ")) 116 | 117 | (ert-deftest plantuml-test-current-block-depth_6 () 118 | "Test `plantuml-current-block-depth' level 0 at beginning of 5th line." 119 | 120 | (plantuml-test-assert-block-depth 0 " 121 | activate p1 122 | activate p2 123 | foo 124 | deactivate p2 125 | |deactivate p1 126 | ")) 127 | 128 | (ert-deftest plantuml-test-current-block-depth_eob () 129 | "Test `plantuml-current-block-depth' level 0 at end of buffer." 130 | 131 | (plantuml-test-assert-block-depth 0 " 132 | activate p1 133 | activate p2 134 | foo 135 | deactivate p2 136 | deactivate p1 137 | |")) 138 | 139 | (defun plantuml-test-indent-line (before after) 140 | "The common code for the line indentation tests. 141 | 142 | BEFORE is the text to be inserted into a temporary buffer. 143 | AFTER is the expected text after indentation. 144 | 145 | Both, BEFORE and AFTER need to specify point with char |. The 146 | temporary buffer will be put into `plantuml-mode', the char | 147 | representing point will be removed from text. The line with the 148 | removed | will be indented (just this line!) with two spaces for each 149 | level of indentation. 150 | 151 | Finally, 152 | 1) the indented line will be compared with the same line in AFTER 153 | 2) the position of point in the indented line will be compared with 154 | the position of | in AFTER." 155 | 156 | (let* ((expected-cursor-pos (1+ (s-index-of "|" after))) 157 | (expected-state (delete ?| after))) 158 | (with-temp-buffer 159 | ;; fix the JAR location prior to mode initialization 160 | ;; for some reason, plantuml-mode disregards the setq-local 161 | (setq-local plantuml-jar-path plantuml-test-jar-path) 162 | (plantuml-init-once) 163 | 164 | (plantuml-test-add-text-and-position-cursor before) 165 | (plantuml-mode) 166 | 167 | ;; use 2 spaces instead of one tab for indentation 168 | (setq-local indent-tabs-mode nil) 169 | (setq-local tab-width 2) 170 | (indent-according-to-mode) 171 | 172 | (should (equal expected-state (buffer-string))) 173 | (should (equal expected-cursor-pos (point)))))) 174 | 175 | (ert-deftest plantuml-test-line-indentation/empty-line-l0 () 176 | "Test correct indentation of empty line - indentation level 0." 177 | (plantuml-test-indent-line "|" "|")) 178 | 179 | (ert-deftest plantuml-test-line-indentation/bol-notindent-l0 () 180 | "Test correct indentation of a not indented line with point at beginning of line - indentation level 0." 181 | (plantuml-test-indent-line "|participant A" 182 | "|participant A")) 183 | 184 | (ert-deftest plantuml-test-line-indentation/mol-notindent-l0 () 185 | "Test correct indentation of a not indented line with point at middle of line - indentation level 0." 186 | (plantuml-test-indent-line "parti|cipant" 187 | "parti|cipant")) 188 | 189 | (ert-deftest plantuml-test-line-indentation/eol-notindent-l0 () 190 | "Test correct indentation of a not indented line with point at end of line - indentation level 0." 191 | (plantuml-test-indent-line "participant A|" 192 | "participant A|")) 193 | 194 | (ert-deftest plantuml-test-line-indentation/bol-indented-l0 () 195 | "Test correct indentation of an indented line with point at beginning of line - indentation level 0." 196 | (plantuml-test-indent-line " |participant A" 197 | "|participant A")) 198 | 199 | (ert-deftest plantuml-test-line-indentation/mol-indented-l0 () 200 | "Test correct indentation of an indented line with point at middle of line - indentation level 0." 201 | (plantuml-test-indent-line " parti|cipant" 202 | "parti|cipant")) 203 | 204 | (ert-deftest plantuml-test-line-indentation/eol-indented-l0 () 205 | "Test correct indentation of an indented line with point at end of line - indentation level 0." 206 | (plantuml-test-indent-line " participant A|" 207 | "participant A|")) 208 | 209 | (ert-deftest plantuml-test-line-indentation/empty-line-l1 () 210 | "Test correct indentation of empty line - indentation level 1." 211 | (plantuml-test-indent-line 212 | "opt A 213 | |" 214 | "opt A 215 | |")) 216 | 217 | (ert-deftest plantuml-test-line-indentation/bol-notindent-l1 () 218 | "Test correct indentation of a not indented line with point at beginning of line - indentation level 1." 219 | (plantuml-test-indent-line "opt A 220 | |foofoo" 221 | "opt A 222 | |foofoo")) 223 | 224 | (ert-deftest plantuml-test-line-indentation/mol-notindent-l1 () 225 | "Test correct indentation of a not indented line with point at middle of line - indentation level 1." 226 | (plantuml-test-indent-line "opt A 227 | foo|foo" 228 | "opt A 229 | foo|foo")) 230 | 231 | (ert-deftest plantuml-test-line-indentation/eol-notindent-l1 () 232 | "Test correct indentation of a not indented line with point at end of line - indentation level 1." 233 | (plantuml-test-indent-line "opt A 234 | foofoo|" 235 | "opt A 236 | foofoo|")) 237 | 238 | (ert-deftest plantuml-test-line-indentation/bol-indented-l1 () 239 | "Test correct indentation of an indented line with point at beginning of line - indentation level 1." 240 | (plantuml-test-indent-line " opt A 241 | |foofoo" 242 | " opt A 243 | |foofoo")) 244 | 245 | (ert-deftest plantuml-test-line-indentation/mol-indented-l1 () 246 | "Test correct indentation of an indented line with point at middle of line - indentation level 1." 247 | (plantuml-test-indent-line " opt A 248 | foo|foo" 249 | " opt A 250 | foo|foo")) 251 | 252 | (ert-deftest plantuml-test-line-indentation/eol-indented-l1 () 253 | "Test correct indentation of an indented line with point at end of line - indentation level 1." 254 | (plantuml-test-indent-line " opt A 255 | foofoo|" 256 | " opt A 257 | foofoo|")) 258 | 259 | 260 | 261 | (provide 'plantuml-indentation-basics-test) 262 | 263 | ;;; plantuml-indentation-basics-test.el ends here 264 | -------------------------------------------------------------------------------- /test/plantuml-indentation-activity-new-test.el: -------------------------------------------------------------------------------- 1 | ;;; plantuml-indentation-activity-old-test.el --- PlantUML Mode indentation tests -*- lexical-binding: t; -*- 2 | 3 | ;; Author: René Schmelzer 4 | ;; Maintainer: Carlo Sciolla (skuro) 5 | ;; URL: https://github.com/skuro/plantuml-mode 6 | 7 | ;;; Commentary: 8 | 9 | ;; Test indentation for activity (old version) diagrams. 10 | 11 | ;;; Code: 12 | 13 | 14 | (ert-deftest plantuml-test-indentation/activity-new/start-stop () 15 | "Test correct indentation of plantuml activity-new diagram elements: start-stop. 16 | These code examples are taken from www.plantuml.com" 17 | (plantuml-test-indent-block 18 | "@startuml 19 | start 20 | :Hello world; 21 | :This is defined on 22 | several **lines**; 23 | end 24 | @enduml" 25 | 26 | "@startuml 27 | start 28 | :Hello world; 29 | :This is defined on 30 | several **lines**; 31 | end 32 | @enduml")) 33 | 34 | (ert-deftest plantuml-test-indentation/activity-new/conditional () 35 | "Test correct indentation of plantuml activity-new diagram conditionals. 36 | These code examples are taken from www.plantuml.com" 37 | (plantuml-test-indent-block 38 | "@startuml 39 | start 40 | if (condition A) then (yes) 41 | :Text 1; 42 | elseif (condition B) then (yes) 43 | :Text 2; 44 | stop 45 | elseif (condition C) then (yes) 46 | :Text 3; 47 | elseif (condition D) then (yes) 48 | :Text 4; 49 | else (nothing) 50 | :Text else; 51 | endif 52 | stop 53 | @enduml" 54 | 55 | "@startuml 56 | start 57 | if (condition A) then (yes) 58 | :Text 1; 59 | elseif (condition B) then (yes) 60 | :Text 2; 61 | stop 62 | elseif (condition C) then (yes) 63 | :Text 3; 64 | elseif (condition D) then (yes) 65 | :Text 4; 66 | else (nothing) 67 | :Text else; 68 | endif 69 | stop 70 | @enduml")) 71 | 72 | (ert-deftest plantuml-test-indentation/activity-new/repeat-loop () 73 | "Test correct indentation of plantuml activity-new repeat loop. 74 | These code examples are taken from www.plantuml.com" 75 | (plantuml-test-indent-block 76 | "@startuml 77 | 78 | start 79 | 80 | repeat 81 | :read data; 82 | :generate diagrams; 83 | repeat while (more data?) is (yes) 84 | ->no; 85 | stop 86 | 87 | @enduml" 88 | 89 | "@startuml 90 | 91 | start 92 | 93 | repeat 94 | :read data; 95 | :generate diagrams; 96 | repeat while (more data?) is (yes) 97 | ->no; 98 | stop 99 | 100 | @enduml")) 101 | 102 | 103 | (ert-deftest plantuml-test-indentation/activity-new/while-loop () 104 | "Test correct indentation of plantuml activity-new while loop. 105 | These code examples are taken from www.plantuml.com" 106 | (plantuml-test-indent-block 107 | "@startuml 108 | 109 | start 110 | 111 | while (data available?) 112 | :read data; 113 | :generate diagrams; 114 | endwhile 115 | 116 | stop 117 | 118 | @enduml" 119 | 120 | "@startuml 121 | 122 | start 123 | 124 | while (data available?) 125 | :read data; 126 | :generate diagrams; 127 | endwhile 128 | 129 | stop 130 | 131 | @enduml") 132 | 133 | (plantuml-test-indent-block 134 | "@startuml 135 | while (check filesize ?) is (not empty) 136 | :read file; 137 | endwhile (empty) 138 | :close file; 139 | @enduml" 140 | 141 | "@startuml 142 | while (check filesize ?) is (not empty) 143 | :read file; 144 | endwhile (empty) 145 | :close file; 146 | @enduml")) 147 | 148 | (ert-deftest plantuml-test-indentation/activity-new/fork () 149 | "Test correct indentation of plantuml activity-new forks. 150 | These code examples are taken from www.plantuml.com" 151 | (plantuml-test-indent-block 152 | "@startuml 153 | 154 | start 155 | 156 | if (multiprocessor?) then (yes) 157 | fork 158 | :Treatment 1; 159 | fork again 160 | :Treatment 2; 161 | end fork 162 | else (monoproc) 163 | :Treatment 1; 164 | :Treatment 2; 165 | endif 166 | 167 | @enduml" 168 | "@startuml 169 | 170 | start 171 | 172 | if (multiprocessor?) then (yes) 173 | fork 174 | :Treatment 1; 175 | fork again 176 | :Treatment 2; 177 | end fork 178 | else (monoproc) 179 | :Treatment 1; 180 | :Treatment 2; 181 | endif 182 | 183 | @enduml")) 184 | 185 | (ert-deftest plantuml-test-indentation/activity-new/fork-with-label () 186 | "Test correct indentation of plantuml activity-new forks. 187 | These code examples are taken from www.plantuml.com" 188 | (plantuml-test-indent-block 189 | "@startuml 190 | start 191 | fork 192 | :action A; 193 | fork again 194 | :action B; 195 | end fork {or} 196 | stop 197 | @enduml 198 | " 199 | "@startuml 200 | start 201 | fork 202 | :action A; 203 | fork again 204 | :action B; 205 | end fork {or} 206 | stop 207 | @enduml 208 | ")) 209 | 210 | (ert-deftest plantuml-test-indentation/activity-new/notes () 211 | "Test correct indentation of plantuml activity-new notes. 212 | These code examples are taken from www.plantuml.com" 213 | (plantuml-test-indent-block 214 | "@startuml 215 | 216 | start 217 | :foo1; 218 | floating note left: This is a note 219 | :foo2; 220 | note right 221 | This note is on several 222 | //lines// and can 223 | contain HTML 224 | ==== 225 | * Calling the method \"foo()\" is prohibited 226 | end note 227 | stop 228 | 229 | @enduml" 230 | 231 | "@startuml 232 | 233 | start 234 | :foo1; 235 | floating note left: This is a note 236 | :foo2; 237 | note right 238 | This note is on several 239 | //lines// and can 240 | contain HTML 241 | ==== 242 | * Calling the method \"foo()\" is prohibited 243 | end note 244 | stop 245 | 246 | @enduml")) 247 | 248 | (ert-deftest plantuml-test-indentation/activity-new/grouping () 249 | "Test correct indentation of plantuml activity-new grouping. 250 | These code examples are taken from www.plantuml.com" 251 | (plantuml-test-indent-block 252 | "@startuml 253 | start 254 | partition Initialization { 255 | :read config file; 256 | :init internal variable; 257 | } 258 | partition Running { 259 | :wait for user interaction; 260 | :print information; 261 | } 262 | 263 | stop 264 | @enduml" 265 | 266 | "@startuml 267 | start 268 | partition Initialization { 269 | :read config file; 270 | :init internal variable; 271 | } 272 | partition Running { 273 | :wait for user interaction; 274 | :print information; 275 | } 276 | 277 | stop 278 | @enduml")) 279 | 280 | (ert-deftest plantuml-test-indentation/activity-new/sdl+splits () 281 | "Test correct indentation of plantuml activity-new sdl rendering and splits. 282 | These code examples are taken from www.plantuml.com" 283 | (plantuml-test-indent-block 284 | "@startuml 285 | :Ready; 286 | :next(o)| 287 | :Receiving; 288 | split 289 | :nak(i)< 290 | :ack(o)> 291 | split again 292 | :ack(i)< 293 | :next(o) 294 | on several lines| 295 | :i := i + 1] 296 | :ack(o)> 297 | split again 298 | :err(i)< 299 | :nak(o)> 300 | split again 301 | :foo/ 302 | split again 303 | :i > 5} 304 | stop 305 | end split 306 | :finish; 307 | @enduml" 308 | 309 | "@startuml 310 | :Ready; 311 | :next(o)| 312 | :Receiving; 313 | split 314 | :nak(i)< 315 | :ack(o)> 316 | split again 317 | :ack(i)< 318 | :next(o) 319 | on several lines| 320 | :i := i + 1] 321 | :ack(o)> 322 | split again 323 | :err(i)< 324 | :nak(o)> 325 | split again 326 | :foo/ 327 | split again 328 | :i > 5} 329 | stop 330 | end split 331 | :finish; 332 | @enduml")) 333 | 334 | (ert-deftest plantuml-test-indentation/activity-new/complete () 335 | "Test correct indentation of plantuml activity-new complete example. 336 | These code examples are taken from www.plantuml.com" 337 | (plantuml-test-indent-block 338 | "@startuml 339 | 340 | start 341 | :ClickServlet.handleRequest(); 342 | :new page; 343 | if (Page.onSecurityCheck) then (true) 344 | :Page.onInit(); 345 | if (isForward?) then (no) 346 | :Process controls; 347 | if (continue processing?) then (no) 348 | stop 349 | endif 350 | 351 | if (isPost?) then (yes) 352 | :Page.onPost(); 353 | else (no) 354 | :Page.onGet(); 355 | endif 356 | :Page.onRender(); 357 | endif 358 | else (false) 359 | endif 360 | 361 | if (do redirect?) then (yes) 362 | :redirect process; 363 | else 364 | if (do forward?) then (yes) 365 | :Forward request; 366 | else (no) 367 | :Render page template; 368 | endif 369 | endif 370 | 371 | stop 372 | 373 | @enduml" 374 | 375 | "@startuml 376 | 377 | start 378 | :ClickServlet.handleRequest(); 379 | :new page; 380 | if (Page.onSecurityCheck) then (true) 381 | :Page.onInit(); 382 | if (isForward?) then (no) 383 | :Process controls; 384 | if (continue processing?) then (no) 385 | stop 386 | endif 387 | 388 | if (isPost?) then (yes) 389 | :Page.onPost(); 390 | else (no) 391 | :Page.onGet(); 392 | endif 393 | :Page.onRender(); 394 | endif 395 | else (false) 396 | endif 397 | 398 | if (do redirect?) then (yes) 399 | :redirect process; 400 | else 401 | if (do forward?) then (yes) 402 | :Forward request; 403 | else (no) 404 | :Render page template; 405 | endif 406 | endif 407 | 408 | stop 409 | 410 | @enduml")) 411 | 412 | (ert-deftest plantuml-test-indentation/activity-new/switch-1 () 413 | "Test correct indentation of plantuml activity-new complete example. 414 | These code examples are taken from www.plantuml.com" 415 | (plantuml-test-indent-block 416 | "@startuml 417 | start 418 | switch (test?) 419 | case ( condition A ) 420 | :Text 1; 421 | case ( condition B ) 422 | :Text 2; 423 | case ( condition C ) 424 | :Text 3; 425 | case ( condition D ) 426 | :Text 4; 427 | case ( condition E ) 428 | :Text 5; 429 | endswitch 430 | stop 431 | @enduml" 432 | 433 | "@startuml 434 | start 435 | switch (test?) 436 | case ( condition A ) 437 | :Text 1; 438 | case ( condition B ) 439 | :Text 2; 440 | case ( condition C ) 441 | :Text 3; 442 | case ( condition D ) 443 | :Text 4; 444 | case ( condition E ) 445 | :Text 5; 446 | endswitch 447 | stop 448 | @enduml")) 449 | 450 | (ert-deftest plantuml-test-indentation/activity-new/switch-2 () 451 | "Test correct indentation of plantuml activity-new complete example. 452 | These code examples are taken from www.plantuml.com" 453 | (plantuml-test-indent-block 454 | "@startuml 455 | start 456 | switch (test? (is it?)) 457 | case ( condition (A) ) 458 | :Text 1; 459 | case ( condition B (we do not care whether parentheses match or not) 460 | :Text 2; 461 | case ( condition C ))) 462 | :Text 3; 463 | case ( condition D ) 464 | :Text 4; 465 | case ( condition E ) 466 | :Text 5; 467 | endswitch 468 | stop 469 | @enduml" 470 | 471 | "@startuml 472 | start 473 | switch (test? (is it?)) 474 | case ( condition (A) ) 475 | :Text 1; 476 | case ( condition B (we do not care whether parentheses match or not) 477 | :Text 2; 478 | case ( condition C ))) 479 | :Text 3; 480 | case ( condition D ) 481 | :Text 4; 482 | case ( condition E ) 483 | :Text 5; 484 | endswitch 485 | stop 486 | @enduml")) 487 | 488 | (provide 'plantuml-indentation-activity-new-test) 489 | ;;; plantuml-indentation-activity-new-test.el ends here 490 | -------------------------------------------------------------------------------- /test/plantuml-indentation-notes-test.el: -------------------------------------------------------------------------------- 1 | ;;; plantuml-indentation-notes-test.el --- PlantUML Mode indentation tests -*- lexical-binding: t; -*- 2 | 3 | ;; Author: René Schmelzer 4 | ;; Maintainer: Carlo Sciolla (skuro) 5 | ;; URL: https://github.com/skuro/plantuml-mode 6 | 7 | ;;; Commentary: 8 | 9 | ;; Test indentation of note elements. 10 | ;; Notes are used in almost all diagrams, but not all types of notes 11 | ;; are supported in every diagram type. 12 | 13 | ;;; Code: 14 | 15 | (ert-deftest plantuml-test-block-indentation/note-simple () 16 | "Test correct indentation of a simple note block." 17 | (plantuml-test-indent-block 18 | " 19 | note right: single line note 20 | 21 | note right 22 | multi line note 23 | end note 24 | " 25 | " 26 | note right: single line note 27 | 28 | note right 29 | multi line note 30 | end note 31 | " 32 | )) 33 | 34 | (ert-deftest plantuml-test-block-indentation/note-left-right () 35 | "Test correct indentation of a note left/right block." 36 | (plantuml-test-indent-block 37 | " 38 | (*) --> \"Some Activity\" 39 | note right: This activity has to be defined 40 | \"Some Activity\" --> (*) 41 | 42 | note right 43 | This note is on 44 | several lines 45 | end note 46 | 47 | (*) --> \"Some Activity\" 48 | note left: This activity has to be defined 49 | \"Some Activity\" --> (*) 50 | 51 | note left 52 | This note is on 53 | several lines 54 | end note 55 | " 56 | " 57 | (*) --> \"Some Activity\" 58 | note right: This activity has to be defined 59 | \"Some Activity\" --> (*) 60 | 61 | note right 62 | This note is on 63 | several lines 64 | end note 65 | 66 | (*) --> \"Some Activity\" 67 | note left: This activity has to be defined 68 | \"Some Activity\" --> (*) 69 | 70 | note left 71 | This note is on 72 | several lines 73 | end note 74 | " )) 75 | 76 | (ert-deftest plantuml-test-block-indentation/note-xxx-of () 77 | "Test correct indentation of a note xxx of block. 78 | plantuml.com: 79 | You can use the note left of, note right of, note top of, 80 | note bottom of keywords to define notes related to a single 81 | object." 82 | (plantuml-test-indent-block 83 | " 84 | note right of Alice: This is displayed right of Alice. 85 | 86 | note left of Alice #aqua 87 | This is displayed 88 | left of Alice. 89 | end note 90 | 91 | note left of Alice: This is displayed left of Alice. 92 | 93 | note right of Alice #aqua 94 | This is displayed 95 | right of Alice. 96 | end note 97 | 98 | note right of (Use) 99 | A note can also 100 | be on several lines 101 | end note 102 | 103 | note left of HTTP : Web Service only 104 | 105 | note right of [First Component] 106 | A note can also 107 | be on several lines 108 | end note 109 | " 110 | " 111 | note right of Alice: This is displayed right of Alice. 112 | 113 | note left of Alice #aqua 114 | This is displayed 115 | left of Alice. 116 | end note 117 | 118 | note left of Alice: This is displayed left of Alice. 119 | 120 | note right of Alice #aqua 121 | This is displayed 122 | right of Alice. 123 | end note 124 | 125 | note right of (Use) 126 | A note can also 127 | be on several lines 128 | end note 129 | 130 | note left of HTTP : Web Service only 131 | 132 | note right of [First Component] 133 | A note can also 134 | be on several lines 135 | end note 136 | " 137 | )) 138 | 139 | (ert-deftest plantuml-test-block-indentation/note-on-link () 140 | "Test correct indentation of a note xxx of block. 141 | plantuml.com: 142 | “You can also use note left on link, note right on link, 143 | note top on link, note bottom on link if you want to change 144 | the relative position of the note with the label.”" 145 | (plantuml-test-indent-block 146 | " 147 | class Dummy 148 | Dummy --> Foo : A link 149 | note on link #red: note that is red 150 | 151 | Dummy --> Foo2 : Another link 152 | note right on link #blue 153 | this is my note on right link 154 | and in blue 155 | end note 156 | 157 | note left on link #00FFFF 158 | this is my note on left link 159 | and in color as number 160 | end note 161 | " 162 | " 163 | class Dummy 164 | Dummy --> Foo : A link 165 | note on link #red: note that is red 166 | 167 | Dummy --> Foo2 : Another link 168 | note right on link #blue 169 | this is my note on right link 170 | and in blue 171 | end note 172 | 173 | note left on link #00FFFF 174 | this is my note on left link 175 | and in color as number 176 | end note 177 | " 178 | )) 179 | 180 | (ert-deftest plantuml-test-block-indentation/note-over () 181 | "Test correct indentation of a note-over block." 182 | (plantuml-test-indent-block 183 | " 184 | note over Alice: This is displayed over Alice. 185 | 186 | note over Alice, Bob #FFAAAA: This is displayed over Bob and Alice. 187 | 188 | note over Bob, Alice 189 | This is yet another 190 | example of 191 | a long note. 192 | end note 193 | " 194 | " 195 | note over Alice: This is displayed over Alice. 196 | 197 | note over Alice, Bob #FFAAAA: This is displayed over Bob and Alice. 198 | 199 | note over Bob, Alice 200 | This is yet another 201 | example of 202 | a long note. 203 | end note 204 | " 205 | )) 206 | 207 | ;; Here we have an inconsistency (again) in plantuml syntax 208 | ;; single line ‘note as …’ does not contain a ?: 209 | ;; 210 | ;; (ert-deftest plantuml-test-block-indentation/note-as () 211 | ;; "Test correct indentation of a note-as block." 212 | ;; (plantuml-test-indent-block 213 | ;; " 214 | ;; :Main Admin: as Admin 215 | ;; (Use the application) as (Use) 216 | 217 | ;; User -> (Start) 218 | ;; User --> (Use) 219 | 220 | ;; Admin ---> (Use) 221 | 222 | ;; note right of Admin : This is an example. 223 | 224 | ;; note right of (Use) 225 | ;; A note can also 226 | ;; be on several lines 227 | ;; end note 228 | 229 | ;; note \"This note is connected to several objects.\" as N2 #RED 230 | ;; (Start) .. N2 231 | ;; N2 .. (Use) 232 | 233 | ;; note as N3 #blue 234 | ;; This note is connected 235 | ;; to several objects as well. 236 | ;; end note 237 | ;; (Start) .. N3 238 | ;; N3 .. Admin 239 | ;; " 240 | ;; " 241 | ;; :Main Admin: as Admin 242 | ;; (Use the application) as (Use) 243 | 244 | ;; User -> (Start) 245 | ;; User --> (Use) 246 | 247 | ;; Admin ---> (Use) 248 | 249 | ;; note right of Admin : This is an example. 250 | 251 | ;; note right of (Use) 252 | ;; A note can also 253 | ;; be on several lines 254 | ;; end note 255 | 256 | ;; note \"This note is connected to several objects.\" as N2 #RED 257 | ;; (Start) .. N2 258 | ;; N2 .. (Use) 259 | 260 | ;; note as N3 #blue 261 | ;; This note is connected 262 | ;; to several objects as well. 263 | ;; end note 264 | 265 | ;; (Start) .. N3 266 | ;; N3 .. Admin 267 | ;; " 268 | ;; )) 269 | 270 | (ert-deftest plantuml-test-block-indentation/note-floating () 271 | "Test correct indentation of a floating note block." 272 | (plantuml-test-indent-block 273 | 274 | " 275 | floating note left: This is a note 276 | :foo2; 277 | 278 | floating note right 279 | This note is on several 280 | //lines// and can 281 | contain HTML 282 | ==== 283 | * Calling the method \"\"foo()\"\" is prohibited 284 | end note 285 | " 286 | " 287 | floating note left: This is a note 288 | :foo2; 289 | 290 | floating note right 291 | This note is on several 292 | //lines// and can 293 | contain HTML 294 | ==== 295 | * Calling the method \"\"foo()\"\" is prohibited 296 | end note 297 | " 298 | )) 299 | 300 | (ert-deftest plantuml-test-block-indentation/note-h-r-note () 301 | "Test correct indentation of a [hr]note block." 302 | (plantuml-test-indent-block 303 | " 304 | caller -> server : conReq 305 | rnote over caller : idle 306 | hnote over caller : idle 307 | caller <- server : conConf 308 | 309 | rnote over server 310 | r as rectangle 311 | h as hexagon 312 | endrnote 313 | 314 | hnote over server 315 | r as rectangle 316 | h as hexagon 317 | endrnote 318 | " 319 | " 320 | caller -> server : conReq 321 | rnote over caller : idle 322 | hnote over caller : idle 323 | caller <- server : conConf 324 | 325 | rnote over server 326 | r as rectangle 327 | h as hexagon 328 | endrnote 329 | 330 | hnote over server 331 | r as rectangle 332 | h as hexagon 333 | endrnote 334 | " 335 | )) 336 | 337 | (ert-deftest plantuml-test-block-indentation/note-creole-html () 338 | "Test correct indentation of a note block with creole/html." 339 | (plantuml-test-indent-block 340 | 341 | " 342 | participant Alice 343 | participant \"The **Famous** Bob\" as Bob 344 | 345 | Alice -> Bob : hello --there-- 346 | ... Some ~~long delay~~ ... 347 | Bob -> Alice : ok 348 | note left 349 | This is **bold** 350 | This is //italics// 351 | This is \"\"monospaced\"\" 352 | This is --stroked-- 353 | This is __underlined__ 354 | This is ~~waved~~ 355 | end note 356 | 357 | Alice -> Bob : A //well formatted// message 358 | note right of Alice 359 | This is displayed 360 | __left of__ Alice. 361 | end note 362 | note left of Bob 363 | This is displayed 364 | **left of Alice Bob**. 365 | end note 366 | note over Alice, Bob 367 | This is hosted by 368 | end note 369 | 370 | " 371 | " 372 | participant Alice 373 | participant \"The **Famous** Bob\" as Bob 374 | 375 | Alice -> Bob : hello --there-- 376 | ... Some ~~long delay~~ ... 377 | Bob -> Alice : ok 378 | note left 379 | This is **bold** 380 | This is //italics// 381 | This is \"\"monospaced\"\" 382 | This is --stroked-- 383 | This is __underlined__ 384 | This is ~~waved~~ 385 | end note 386 | 387 | Alice -> Bob : A //well formatted// message 388 | note right of Alice 389 | This is displayed 390 | __left of__ Alice. 391 | end note 392 | note left of Bob 393 | This is displayed 394 | **left of Alice Bob**. 395 | end note 396 | note over Alice, Bob 397 | This is hosted by 398 | end note 399 | 400 | " 401 | )) 402 | 403 | (ert-deftest plantuml-test-block-indentation/note-on-field-or-method () 404 | "Test correct indentation of notes attached to fields or methods." 405 | (plantuml-test-indent-block 406 | 407 | " 408 | @startuml 409 | class Foo { 410 | + method() 411 | } 412 | 413 | note left of Foo 414 | this indents fine 415 | end note 416 | 417 | note left of Foo::method 418 | this used not to indent 419 | end note 420 | 421 | class Bar { 422 | all lines after the second note also are not indented 423 | } 424 | @enduml" 425 | 426 | " 427 | @startuml 428 | class Foo { 429 | + method() 430 | } 431 | 432 | note left of Foo 433 | this indents fine 434 | end note 435 | 436 | note left of Foo::method 437 | this used not to indent 438 | end note 439 | 440 | class Bar { 441 | all lines after the second note also are not indented 442 | } 443 | @enduml")) 444 | 445 | ;;; plantuml-indentation-notes-test.el ends here 446 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![MELPA](http://melpa.org/packages/plantuml-mode-badge.svg)](http://melpa.org/#/plantuml-mode) [![downloads](https://melpastats-2761cf.gitlab.io/badges/plantuml-mode-badge.svg)](http://melpa.org/#/plantuml-mode) [![MELPA Stable](http://stable.melpa.org/packages/plantuml-mode-badge.svg)](http://stable.melpa.org/#/plantuml-mode) [![CircleCI](https://circleci.com/gh/skuro/plantuml-mode.svg?style=svg)](https://circleci.com/gh/skuro/plantuml-mode) [![Coverage Status](https://coveralls.io/repos/github/skuro/plantuml-mode/badge.svg?branch=HEAD)](https://coveralls.io/github/skuro/plantuml-mode?branch=HEAD) 2 | 3 | # PlantUML mode for Emacs 4 | 5 | plantuml-mode in action 7 | 8 | > “Pummel me all you want," I say. "Pummel me to death, in fact. My answers will not change." 9 | > The Invierno step back, frowning. "You must love her very much," he says, not unkindly.” 10 | > 11 | > from [The Bitter Kingdom - Fire and Thorns #3](https://www.goodreads.com/book/show/11431896-the-bitter-kingdom) 12 | 13 | A [PlantUML](http://plantuml.sourceforge.net/) major mode for Emacs. 14 | 15 | # Quick Guide 16 | 17 | 1. Install with `M-x package-install` 18 | 2. Enable mode for current buffer `M-x plantuml-mode` 19 | 3. Write some PlantUML: 20 | 21 | ``` 22 | @startuml 23 | Alice -> Bob: Authentication Request 24 | Bob --> Alice: Authentication Response 25 | 26 | Alice -> Bob: Another authentication Request 27 | Alice <-- Bob: Another authentication Response 28 | @enduml 29 | ``` 30 | 31 | 4. Preview diagrams with `C-c C-c` (`plantuml-preview`). 32 | 33 | **WARNING:** This may send information to 34 | `"https://www.plantuml.com/plantuml"`! Check that 35 | `plantuml-default-exec-mode` is configured correctly for your use case 36 | before previewing any sensitive material. 37 | 38 | ```lisp 39 | ;; Sample jar configuration 40 | (setq plantuml-jar-path "/path/to/your/copy/of/plantuml.jar") 41 | (setq plantuml-default-exec-mode 'jar) 42 | 43 | ;; Sample executable configuration 44 | (setq plantuml-executable-path "/path/to/your/copy/of/plantuml.bin") 45 | (setq plantuml-default-exec-mode 'executable) 46 | ``` 47 | 48 | See [Execution modes](#execution-modes) for more information. 49 | 50 | # Installation 51 | 52 | Make sure you have [MELPA](http://melpa.org/) enabled in your ``emacs.d``. Then, you can just 53 | 54 | M-x package-install 55 | plantuml-mode 56 | 57 | Also, to enable preview you need to tell `plantuml-mode` where to locate the PlantUML JAR file. By default it will look for it in `~/plantuml.jar`, but you can specify any location with: 58 | 59 | M-x customize-variable 60 | plantuml-jar-path 61 | 62 | You can also download the latest version of PlantUML straight into `plantuml-jar-path`: 63 | 64 | M-x plantuml-download-jar 65 | 66 | # Features 67 | 68 | - Syntax highlight 69 | - Autocompletion 70 | - Preview of buffer or region 71 | - Use either local JAR or remote server for preview 72 | - Set default custom theme (unless explicitly set in the diagram source) 73 | 74 | # Enable the major mode 75 | 76 | You can automatically enable `plantuml-mode` for files with extension `.plantuml` by adding the following to your `.emacsrc`: 77 | 78 | ;; Enable plantuml-mode for PlantUML files 79 | (add-to-list 'auto-mode-alist '("\\.plantuml\\'" . plantuml-mode)) 80 | 81 | Of course, you can always enable manually the major mode by typing `M-x plantuml-mode` once in the desired PlantUML file buffer. 82 | 83 | # Usage 84 | 85 | You can tell `plantuml-mode` to autocomplete the word before the cursor by typing `M-x plantuml-complete-symbol`. This will open a popup with all the available completions as found in the list of keywords given by running PlantUML with the `-language` flag. 86 | 87 | To render the PlantUML diagram within Emacs, you can hit `M-x plantuml-preview`. This will run PlantUML and display the result in the `*PLANTUML-Preview*` buffer. The format used to render the diagram is automagically chosen from what's supported by your Emacs. It will be one of the following, in order of preference: 88 | 89 | - SVG 90 | - PNG 91 | - Unicode ASCII art 92 | 93 | The diagram will be either created from the selected region if one is available in the current buffer, or using the whole buffer otherwise. 94 | 95 | If you want to force a specific output format, you can customize the variable `plantuml-output-type` to the value you prefer. 96 | 97 | ## Configuration 98 | 99 | The following custom variables are available: 100 | 101 | - `plantuml-jar-path`: the local path to the `plantuml.jar` file to use when running in `jar` execution mode 102 | - `plantuml-executable-path`: the local path to the `plantuml` executable file to use when running in `executable` mode 103 | - `plantuml-executable-args`: the arguments passed to the `plantuml-executable-path` commandh 104 | - `plantuml-java-command`: the name of the `java` command to use when running in `jar` execution mode 105 | - `plantuml-java-args`: the arguments passed to the `plantuml-java-command` 106 | - `plantuml-server-url`: the URL of the PlantUML server to contact when running in `server` execution mode 107 | - `plantuml-default-exec-mode`: one of `jar` / `server` / `executable` 108 | - `plantuml-output-type`: one of `"svg"` / `"png"` / `"txt"` 109 | - `plantuml-suppress-deprecation-warning`: whether to silence the warning if the deprecated `puml-mode` is found 110 | - `plantuml-indent-level`: the indentation level to use for PlantUML blocks 111 | - `plantuml-preview-default-theme`: the default `!theme` to use when rendering diagrams when no explicit `!theme` directive is found 112 | - `plantuml-server-encode-mode`: how to generate the URL when in `server` execution mode, either compress with `'deflate` (better for network) or encode with `'hex` (better for CPU usage), see [the official PlantUML docs] (https://plantuml.com/text-encoding) 113 | - `plantuml-svg-background`: set to a valid color to force a background when using `"svg"` as `plantuml-output-type` or `nil` to leave the default transparent background 114 | 115 | ## Default key bindings 116 | 117 | The following shortcuts are enabled by default: 118 | 119 | C-c C-c plantuml-preview: renders a PlantUML diagram from the current buffer in the best supported format 120 | 121 | C-u C-c C-c plantuml-preview in other window 122 | 123 | C-u C-u C-c C-c plantuml-preview in other frame 124 | 125 | ## Integration with `org-mode` 126 | 127 | You can use `plantuml-mode` to edit PlantUML source snippets within an [`org-mode`](http://orgmode.org/) document. To do so, you need to first register it with the `plantuml` language: 128 | 129 | ``` 130 | (add-to-list 131 | 'org-src-lang-modes '("plantuml" . plantuml)) 132 | ``` 133 | 134 | Then you can edit a `plantuml` code block with `plantuml-mode` by hitting `C-c '` while inside of the code block itself: 135 | 136 | ```elisp 137 | #+BEGIN_SRC plantuml 138 | 139 | #+END_SRC 140 | ``` 141 | 142 | When in the `plantuml-mode` buffer you can then hit again `C-'` to return to the original `org-mode` document. 143 | 144 | # Execution modes 145 | 146 | **EXPERIMENTAL** 147 | 148 | As of `v1.3.0` support is added for switching execution mode. The following three modes are available: 149 | 150 | - `jar` (traditional) to run PlantUML as a local JAR file. This is the traditional system used by `plantuml-mode` 151 | - `server` (default) to let an instance of [`plantuml-server`](https://github.com/plantuml/plantuml-server) render the preview 152 | - `executable` to run PlantUML as a local executable file. This is useful if your package manager provides a executable for PlantUML. 153 | 154 | You can customize `plantuml-default-exec-mode` or run `plantuml-set-exec-mode` from a `plantuml-mode` buffer to switch modes. 155 | 156 | ## Configure server rendering 157 | 158 | When selecting `server` execution modes, you can customize the following variable to set the server to use for rendering: 159 | 160 | ``` 161 | plantuml-server-url 162 | ``` 163 | 164 | It defaults to `"https://www.plantuml.com/plantuml"`. 165 | 166 | # Migration from `puml-mode` 167 | 168 | If you were previously using `puml-mode`, you should change any reference to a `puml-..` variable or function to its `plantuml-..` counterpart. Most notably, `puml-plantuml-jar-path` is now just `plantuml-jar-path`. 169 | 170 | ## Deprecation warning 171 | 172 | If `puml-mode` is still being loaded by your Emacs, a Warning will be shown any time you open a PlantUML file. This is to remind you that you are running deprecated software. If you want to suppress the (intentionally) annoying warning, you can customize the variable `plantuml-suppress-deprecation-warning`. 173 | 174 | # Troubleshooting 175 | 176 | ## Debug messages 177 | 178 | As of `v0.6.2` the following commands have been added to help resolving problems: 179 | 180 | ``` 181 | plantuml-enable-debug 182 | plantuml-disable-debug 183 | ``` 184 | 185 | With debug enabled, the actual command used to invoke PlantUML is printed into a buffer called `*PLANTUML Messages*`. You can inspect that buffer to make sure that PlantUML is properly set up, or use it to supply extra information when opening [issues](https://github.com/skuro/plantuml-mode/issues). 186 | 187 | ## Blank previews 188 | 189 | If you are using SVG rendering and `plantuml-preview` shows you an empty buffer, chances are something is wrong with the PlantUML output. While inside the preview buffer, hit `C-c C-c` to switch to 190 | the textual mode and see if the output is valid SVG. 191 | 192 | ## Development 193 | 194 | Development happens mostly on the `develop` branch, which is released on MELPA at every commit. The `master` branch is used to generate tags which are then released to [MELPA 195 | stable](https://stable.melpa.org). 196 | 197 | In order to contribute to `plantuml-mode` make sure to: 198 | 199 | - agree with the [GPLv3+ licencing terms](#License) as they are mandated by Emacs 200 | - install [`cask`](https://github.com/cask/cask) 201 | - always test your code and run the full test suite with `cask exec ert-runner` (or just by `make`) 202 | - ensure you always target `develop` in your pull requests 203 | 204 | For collaborators who have merge access to the repo: 205 | - make sure [`set-version.sh`](./blob/develop/bin/set-version.sh) is run as part of your [`pre-commit` git hooks](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) 206 | - always merge PRs on the command line 207 | - when releasing a new stable version, add the proper entry in the changelog within `plantuml-mode.el` to ensure the right version is set for `plantuml-mode-version` 208 | 209 | # Credits 210 | 211 | This project stemmed from the great work of [Zhang Weize](http://zhangweize.wordpress.com/2010/09/20/update-plantuml-mode/), 212 | and the current code still borrows a lot from it. 213 | 214 | Thanks to [Pavel G. Koukoushkin](https://github.com/svargellin) for implementing the preview functionality. 215 | Thanks to [Raymond Huang](https://github.com/rymndhng) for implementing the first drop of the indentation support. 216 | 217 | Thanks to [all the awesome contributors](https://github.com/skuro/plantuml-mode/graphs/contributors), you rock! 218 | 219 | # See also 220 | 221 | - [PlantUML](http://plantuml.com/) 222 | - [`flycheck-plantuml`](https://github.com/alexmurray/flycheck-plantuml) 223 | 224 | # License 225 | 226 | Released under the terms of [GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html) or (at your option) any later version. See [LICENSE.txt](https://github.com/skuro/plantuml-mode/blob/master/LICENSE.txt). 227 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /plantuml-mode.el: -------------------------------------------------------------------------------- 1 | ;;; plantuml-mode.el --- Major mode for PlantUML -*- lexical-binding: t; -*- 2 | 3 | ;; Filename: plantuml-mode.el 4 | ;; Description: Major mode for PlantUML diagrams sources 5 | ;; Compatibility: Tested with Emacs 25 through 27 (current master) 6 | ;; Author: Zhang Weize (zwz) 7 | ;; Maintainer: Carlo Sciolla (skuro) 8 | ;; Keywords: files text processes tools 9 | ;; Version: 1.8.0 10 | ;; Package-Version: 1.8.0 11 | ;; Package-Requires: ((dash "2.0.0") (emacs "25.1") (deflate "0.0.3")) 12 | ;; Homepage: https://github.com/skuro/plantuml-mode 13 | 14 | ;; This file is free software; you can redistribute it and/or modify 15 | ;; it under the terms of the GNU General Public License as published by 16 | ;; the Free Software Foundation; either version 3, or (at your option) 17 | ;; any later version. 18 | 19 | ;; This file is distributed in the hope that it will be useful, 20 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | ;; GNU General Public License for more details. 23 | 24 | ;; You should have received a copy of the GNU General Public License 25 | ;; along with this program. If not, see . 26 | 27 | ;;; Commentary: 28 | ;; 29 | ;; A major mode for plantuml, see: http://plantuml.sourceforge.net/ 30 | ;; Plantuml is an open-source tool in java that allows to quickly write : 31 | ;; - sequence diagram, 32 | ;; - use case diagram, 33 | ;; - class diagram, 34 | ;; - activity diagram, 35 | ;; - component diagram, 36 | ;; - state diagram 37 | ;; - object diagram 38 | 39 | ;;; Change log: 40 | ;; 41 | ;; version 1.8.0, 2025-07-04 Support for `'hex' and `'deflate' modes for server URL encoding 42 | ;; version 1.7.0, 2025-05-24 Support for `completion-at-point' 43 | ;; version 1.6.0, 2025-05-15 Fix server exec mode; various indentation enhancements and bug fixes; better preview buffer management 44 | ;; version 1.5.0, 2025-05-14 Fixed warnings with new Java versions #157; updated versions to let CI work again 45 | ;; version 1.4.1, 2019-09-03 Better indentation; more bugfixing; actually adding `executable' mode 46 | ;; version 1.4.0, 2019-08-21 Added `executable' exec mode to use locally installed `plantuml' binaries, various bugfixes 47 | ;; version 1.3.1, 2019-08-02 Fixed interactive behavior of `plantuml-set-exec-mode' 48 | ;; version 1.3.0, 2019-05-31 Added experimental support for multiple rendering modes and, specifically, preview using a PlantUML server 49 | ;; version 1.2.11, 2019-04-09 Added `plantuml-download-jar' 50 | ;; version 1.2.10, 2019-04-03 Avoid messing with window layouts and buffers -- courtesy of https://github.com/wailo 51 | ;; version 1.2.9, Revamped indentation support, now working with a greater number of keywords 52 | ;; version 1.2.8, 2019-01-07 Support indentation for activate / deactivate blocks; allow customization of `plantuml-java-args' 53 | ;; version 1.2.7, 2018-08-15 Added support for indentation; Fixed the comiling error when installing with melpa 54 | ;; version 1.2.6, 2018-07-17 Introduced custom variable `plantuml-jar-args' to control which arguments are passed to PlantUML jar. Fix the warning of failing to specify types of 'defcustom' variables 55 | ;; version 1.2.5, 2017-08-19 #53 Fixed installation warnings 56 | ;; version 1.2.4, 2017-08-18 #60 Licensed with GPLv3+ to be compatible with Emacs 57 | ;; version 1.2.3, 2016-12-25 #50 unicode support in generated output 58 | ;; version 1.2.2, 2016-11-11 Fixed java commands handling under windows; support spaces in `plantuml-jar-path' 59 | ;; version 1.2.1, 2016-11-11 Support for paths like `~/.plantuml/plantuml.jar' for `plantuml-jar-path' (the tilde was previously unsupported) 60 | ;; version 1.2.0, 2016-11-09 Added `plantuml-preview-current-buffer', courtesy of @7mamu4 61 | ;; version 1.1.1, 2016-11-08 Fix process handling with Windows native emacs; better file extention match for autoloading the mode 62 | ;; version 1.1.0, 2016-10-18 Make PlantUML run headless by default; introduced custom variable `plantuml-java-args' to control which arguments are passed to Plantuml. 63 | ;; version 1.0.1, 2016-10-17 Bugfix release: proper auto-mode-alist regex; init delayed at mode load; avoid calling hooks twice. 64 | ;; version 1.0.0, 2016-10-16 Moved the mode to plantuml-mode, superseding zwz/plantuml-mode and skuro/puml-mode. Added preview for the currently selected region. 65 | ;; version 0.6.7, 2016-10-11 [from puml-mode] Added deprecation warning in favor of plantuml-mode 66 | ;; version 0.6.6, 2016-07-19 [from puml-mode] Added autoload, minor bug fixes 67 | ;; version 0.6.5, 2016-03-24 [from puml-mode] Added UTF8 support and open in new window / frame shortcuts 68 | ;; version 0.6.4, 2015-12-12 [from puml-mode] Added support for comments (single and multiline) -- thanks to https://github.com/nivekuil 69 | ;; version 0.6.3, 2015-11-07 [from puml-mode] Added per-buffer configurability of output type (thanks to https://github.com/davazp) 70 | ;; version 0.6.2, 2015-11-07 [from puml-mode] Added debugging capabilities to improve issue analysis 71 | ;; version 0.6.1, 2015-09-26 [from puml-mode] Bugfix: use eq to compare symbols instead of cl-equalp 72 | ;; version 0.6, 2015-09-26 [from puml-mode] Fixed PNG preview 73 | ;; version 0.5, 2015-09-21 [from puml-mode] Added preview capabilities 74 | ;; version 0.4, 2015-06-14 [from puml-mode] Use a puml- prefix to distinguish from the other plantuml-mode 75 | ;; version 0.3, 2015-06-13 [from puml-mode] Compatibility with Emacs 24.x 76 | ;; version 0.2, 2010-09-20 [from puml-mode] Initialize the keywords from the -language output of plantuml.jar instead of the hard-coded way. 77 | ;; version 0.1, 2010-08-25 [from puml-mode] First version 78 | 79 | ;;; Code: 80 | (require 'cl-lib) 81 | (require 'dash) 82 | (require 'deflate) 83 | (require 'thingatpt) 84 | (require 'xml) 85 | 86 | (defgroup plantuml nil "Major mode for editing plantuml file." 87 | :group 'languages) 88 | 89 | (defcustom plantuml-jar-path 90 | (expand-file-name "~/plantuml.jar") 91 | "The location of the PlantUML executable JAR." 92 | :type 'string 93 | :group 'plantuml) 94 | 95 | (defcustom plantuml-executable-path 96 | "plantuml" 97 | "The location of the PlantUML executable." 98 | :type 'string 99 | :group 'plantuml) 100 | 101 | (defvar plantuml-mode-hook nil "Standard hook for plantuml-mode.") 102 | 103 | (defconst plantuml-mode-version "1.5.0" "The plantuml-mode version string.") 104 | 105 | (defvar plantuml-mode-debug-enabled nil) 106 | 107 | (defvar plantuml-font-lock-keywords nil) 108 | 109 | (defvar plantuml-mode-map 110 | (let ((keymap (make-sparse-keymap))) 111 | (define-key keymap (kbd "C-c C-c") 'plantuml-preview) 112 | keymap) 113 | "Keymap for plantuml-mode.") 114 | 115 | (defcustom plantuml-java-command "java" 116 | "The java command used to execute PlantUML." 117 | :type 'string 118 | :group 'plantuml) 119 | 120 | (defcustom plantuml-java-args (list "-Djava.awt.headless=true" "-jar" "--illegal-access=deny") 121 | "The parameters passed to `plantuml-java-command' when executing PlantUML." 122 | :type '(repeat string) 123 | :group 'plantuml) 124 | 125 | (defcustom plantuml-jar-args (list "-charset" "UTF-8" ) 126 | "The parameters passed to `plantuml.jar', when executing PlantUML." 127 | :type '(repeat string) 128 | :group 'plantuml) 129 | 130 | (defcustom plantuml-server-url "https://www.plantuml.com/plantuml" 131 | "The base URL of the PlantUML server." 132 | :type 'string 133 | :group 'plantuml) 134 | 135 | (defcustom plantuml-executable-args (list "-headless") 136 | "The parameters passed to plantuml executable when executing PlantUML." 137 | :type '(repeat string) 138 | :group 'plantuml) 139 | 140 | (defcustom plantuml-default-exec-mode 'server 141 | "Default execution mode for PlantUML. Valid values are: 142 | - `jar': run PlantUML as a JAR file 143 | - `server': contact the PlantUML server at `plantuml-server-url' 144 | - `executable' run the PlantUML executable at `plantuml-executable-path' 145 | 146 | The `jar' exec mode requires a local install of the PlantUML JAR file, 147 | see `plantuml-jar-path'. 148 | 149 | The `executable' exec mode requires a local install of the PlantUML JAR file, 150 | see `plantuml-executable-path'." 151 | :type 'symbol 152 | :group 'plantuml 153 | :options '(jar server executable)) 154 | 155 | (defcustom plantuml-suppress-deprecation-warning t 156 | "To silence the deprecation warning when `puml-mode' is found upon loading." 157 | :type 'boolean 158 | :group 'plantuml) 159 | 160 | (defcustom plantuml-indent-level 8 161 | "Indentation level of PlantUML lines." 162 | :type 'natnum 163 | :group 'plantuml) 164 | 165 | (defcustom plantuml-preview-default-theme nil 166 | "Sets the default theme to use when rendering diagrams. 167 | Works only if `!theme' does not appear in the diagram to be displayed." 168 | :type 'string 169 | :group 'plantuml 170 | :safe #'stringp) 171 | 172 | (defcustom plantuml-server-encode-mode 'deflate 173 | "Whether to encode the server URL using HEX or DEFLATE." 174 | :type 'symbol 175 | :group 'plantuml 176 | :options '(deflate hex)) 177 | 178 | (defcustom plantuml-svg-background nil 179 | "The color SVG rendering will use as background. 180 | Useful when the default transparent color makes the diagram hard to see." 181 | :type 'string 182 | :group 'plantuml) 183 | 184 | (defun plantuml-jar-render-command (&rest arguments) 185 | "Create a command line to execute PlantUML with arguments (as ARGUMENTS)." 186 | (let* ((cmd-list (append plantuml-java-args (list (expand-file-name plantuml-jar-path)) plantuml-jar-args arguments)) 187 | (cmd (mapconcat #'identity cmd-list "|"))) 188 | (plantuml-debug (format "Command is [%s]" cmd)) 189 | cmd-list)) 190 | 191 | ;;; syntax table 192 | (defvar plantuml-mode-syntax-table 193 | (let ((synTable (make-syntax-table))) 194 | (modify-syntax-entry ?\/ ". 14c" synTable) 195 | (modify-syntax-entry ?' "< 23" synTable) 196 | (modify-syntax-entry ?\n ">" synTable) 197 | (modify-syntax-entry ?\r ">" synTable) 198 | (modify-syntax-entry ?! "w" synTable) 199 | (modify-syntax-entry ?@ "w" synTable) 200 | (modify-syntax-entry ?# "'" synTable) 201 | synTable) 202 | "Syntax table for `plantuml-mode'.") 203 | 204 | (defvar plantuml-types nil) 205 | (defvar plantuml-keywords nil) 206 | (defvar plantuml-preprocessors nil) 207 | (defvar plantuml-builtins nil) 208 | 209 | ;; keyword completion 210 | (defvar plantuml-kwdList nil "The plantuml keywords.") 211 | 212 | ;; PlantUML execution mode 213 | (defvar-local plantuml-exec-mode nil 214 | "The Plantuml execution mode override. 215 | See `plantuml-default-exec-mode' for acceptable values.") 216 | 217 | (defun plantuml-set-exec-mode (mode) 218 | "Set the execution mode MODE for PlantUML." 219 | (interactive (let* ((completion-ignore-case t) 220 | (supported-modes '("jar" "server" "executable"))) 221 | (list (completing-read (format "Exec mode [%s]: " plantuml-exec-mode) 222 | supported-modes 223 | nil 224 | t 225 | nil 226 | nil 227 | plantuml-exec-mode)))) 228 | (if (member mode '("jar" "server" "executable")) 229 | (setq plantuml-exec-mode (intern mode)) 230 | (error (concat "Unsupported mode:" mode)))) 231 | 232 | (defun plantuml-get-exec-mode () 233 | "Retrieves the currently active PlantUML exec mode." 234 | (or plantuml-exec-mode 235 | plantuml-default-exec-mode)) 236 | 237 | (defun plantuml-enable-debug () 238 | "Enables debug messages into the *PLANTUML Messages* buffer." 239 | (interactive) 240 | (setq plantuml-mode-debug-enabled t)) 241 | 242 | (defun plantuml-disable-debug () 243 | "Stops any debug messages to be added into the *PLANTUML Messages* buffer." 244 | (interactive) 245 | (setq plantuml-mode-debug-enabled nil)) 246 | 247 | (defun plantuml-debug (msg) 248 | "Writes MSG into the *PLANTUML Messages* buffer without annoying the user." 249 | (if plantuml-mode-debug-enabled 250 | (let* ((log-buffer-name "*PLANTUML Messages*") 251 | (log-buffer (get-buffer-create log-buffer-name))) 252 | (save-excursion 253 | (with-current-buffer log-buffer 254 | (goto-char (point-max)) 255 | (insert msg) 256 | (insert "\n")))))) 257 | 258 | (defun plantuml-download-jar () 259 | "Download the latest PlantUML JAR file and install it into `plantuml-jar-path'." 260 | (interactive) 261 | (if (y-or-n-p (format "Download the latest PlantUML JAR file into %s? " plantuml-jar-path)) 262 | (if (or (not (file-exists-p plantuml-jar-path)) 263 | (y-or-n-p (format "The PlantUML jar file already exists at %s, overwrite? " plantuml-jar-path))) 264 | (with-current-buffer (url-retrieve-synchronously "https://search.maven.org/solrsearch/select?q=g:net.sourceforge.plantuml+AND+a:plantuml&core=gav&start=0&rows=1&wt=xml") 265 | (mkdir (file-name-directory plantuml-jar-path) t) 266 | (let* ((parse-tree (xml-parse-region)) 267 | (doc (->> parse-tree 268 | (assq 'response) 269 | (assq 'result) 270 | (assq 'doc))) 271 | (strs (xml-get-children doc 'str)) 272 | (version (->> strs 273 | (--filter (string-equal "v" (xml-get-attribute it 'name))) 274 | (car) 275 | (xml-node-children) 276 | (car)))) 277 | (message (concat "Downloading PlantUML v" version " into " plantuml-jar-path)) 278 | (url-copy-file (format "https://search.maven.org/remotecontent?filepath=net/sourceforge/plantuml/plantuml/%s/plantuml-%s.jar" version version) plantuml-jar-path t) 279 | (kill-buffer))) 280 | (message "Aborted.")) 281 | (message "Aborted."))) 282 | 283 | (defun plantuml-jar-java-version () 284 | "Inspects the Java runtime version of the configured Java command. 285 | The actual command is taken from in `plantuml-java-command'." 286 | (save-excursion 287 | (save-match-data 288 | (with-temp-buffer 289 | (call-process plantuml-java-command nil t nil "-XshowSettings:properties" "-version") 290 | (re-search-backward "java.version = \\(1.\\)?\\([[:digit:]]+\\)") 291 | (string-to-number (match-string 2)))))) 292 | 293 | (defun plantuml-jar-get-language (buf) 294 | "Retrieve the language specification from the PlantUML JAR file. 295 | The language spec is pasted into the buffer BUF." 296 | (unless (or (eq system-type 'cygwin) (file-exists-p plantuml-jar-path)) 297 | (error "Could not find plantuml.jar at %s" plantuml-jar-path)) 298 | (with-current-buffer buf 299 | (let ((cmd-args (append (list plantuml-java-command nil t nil) 300 | (plantuml-jar-render-command "-language")))) 301 | (apply #'call-process cmd-args) 302 | (goto-char (point-min))))) 303 | 304 | (defun plantuml-server-get-language (buf) 305 | "Retrieve the language specification from the PlantUML server. 306 | The language spec is pasted into the buffer BUF." 307 | (let ((lang-url (concat plantuml-server-url "/language"))) 308 | (with-current-buffer buf 309 | (url-insert-file-contents lang-url)))) 310 | 311 | (defun plantuml-executable-get-language (buf) 312 | "Retrieve the language specification from the PlantUML executable. 313 | The language spec is pasted into the buffer BUF." 314 | (with-current-buffer buf 315 | (let ((cmd-args (append (list plantuml-executable-path nil t nil) (list "-language")))) 316 | (apply #'call-process cmd-args) 317 | (goto-char (point-min))))) 318 | 319 | (defun plantuml-get-language (mode buf) 320 | "Retrieve the language spec using the preferred PlantUML execution mode MODE. 321 | Paste the result into BUF." 322 | (let ((get-fn (pcase mode 323 | ('jar #'plantuml-jar-get-language) 324 | ('server #'plantuml-server-get-language) 325 | ('executable #'plantuml-executable-get-language)))) 326 | (if get-fn 327 | (funcall get-fn buf) 328 | (error "Unsupported execution mode %s" mode)))) 329 | 330 | (defun plantuml-init (mode) 331 | "Initialize the keywords or builtins from the cmdline language output. 332 | Use exec mode MODE to load the language details." 333 | (with-temp-buffer 334 | (plantuml-get-language mode (current-buffer)) 335 | (let ((found (search-forward ";" nil t)) 336 | (word "") 337 | (count 0) 338 | (pos 0)) 339 | (while found 340 | (forward-char) 341 | (setq word (current-word)) 342 | (if (string= word "EOF") (setq found nil) 343 | ;; else 344 | (forward-line) 345 | (setq count (string-to-number (current-word))) 346 | (beginning-of-line 2) 347 | (setq pos (point)) 348 | (forward-line count) 349 | (cond ((string= word "type") 350 | (setq plantuml-types 351 | (split-string 352 | (buffer-substring-no-properties pos (point))))) 353 | ((string= word "keyword") 354 | (setq plantuml-keywords 355 | (split-string 356 | (buffer-substring-no-properties pos (point))))) 357 | ((string= word "preprocessor") 358 | (setq plantuml-preprocessors 359 | (split-string 360 | (buffer-substring-no-properties pos (point))))) 361 | (t (setq plantuml-builtins 362 | (append 363 | plantuml-builtins 364 | (split-string 365 | (buffer-substring-no-properties pos (point))))))) 366 | (setq found (search-forward ";" nil nil))))))) 367 | 368 | (defconst plantuml-preview-buffer "*PLANTUML Preview*") 369 | 370 | (defvar plantuml-output-type 371 | (if (not (display-images-p)) 372 | "txt" 373 | (cond ((image-type-available-p 'svg) "svg") 374 | ((image-type-available-p 'png) "png") 375 | (t "txt"))) 376 | "Specify the desired output type to use for generated diagrams.") 377 | 378 | (defun plantuml-read-output-type () 379 | "Read from the minibuffer a output type." 380 | (let* ((completion-ignore-case t) 381 | (available-types 382 | (append 383 | (and (image-type-available-p 'svg) '("svg")) 384 | (and (image-type-available-p 'png) '("png")) 385 | '("txt")))) 386 | (completing-read (format "Output type [%s]: " plantuml-output-type) 387 | available-types 388 | nil 389 | t 390 | nil 391 | nil 392 | plantuml-output-type))) 393 | 394 | (defun plantuml-set-output-type (type) 395 | "Set the desired output TYPE for the current buffer. 396 | If the 397 | major mode of the current buffer mode is not plantuml-mode, set the 398 | default output type for new buffers." 399 | (interactive (list (plantuml-read-output-type))) 400 | (setq plantuml-output-type type)) 401 | 402 | (defun plantuml-is-image-output-p () 403 | "Return t if `plantuml-output-type' denotes an image, nil if it's text based." 404 | (not (equal "txt" plantuml-output-type))) 405 | 406 | (defun plantuml-jar-output-type-opt (output-type) 407 | "Create the flag to pass to PlantUML according to OUTPUT-TYPE. 408 | Note that output type `txt' is promoted to `utxt' for better rendering." 409 | (concat "-t" (pcase output-type 410 | ("txt" "utxt") 411 | (_ output-type)))) 412 | 413 | (defun plantuml-jar-start-process (buf) 414 | "Run the PlantUML JAR and puts the output into the given buffer BUF." 415 | (let ((java-args (if (<= 8 (plantuml-jar-java-version)) 416 | (remove "--illegal-access=deny" plantuml-java-args) 417 | plantuml-java-args))) 418 | (apply #'start-process 419 | "PLANTUML" buf plantuml-java-command 420 | `(,@java-args 421 | ,(expand-file-name plantuml-jar-path) 422 | ,(plantuml-jar-output-type-opt plantuml-output-type) 423 | ,@plantuml-jar-args 424 | "-p")))) 425 | 426 | (defun plantuml-executable-start-process (buf) 427 | "Run the PlantUML executable and puts the output into the given buffer BUF." 428 | (apply #'start-process 429 | "PLANTUML" buf plantuml-executable-path 430 | `(,@plantuml-executable-args 431 | ,(plantuml-jar-output-type-opt plantuml-output-type) 432 | "-p"))) 433 | 434 | (defun plantuml-update-preview-buffer (prefix buf) 435 | "Show the preview in the preview buffer BUF. 436 | Window is selected according to PREFIX: 437 | - 4 (when prefixing the command with C-u) -> new window 438 | - 16 (when prefixing the command with C-u C-u) -> new frame. 439 | - else -> new buffer" 440 | (let ((imagep (and (display-images-p) 441 | (plantuml-is-image-output-p))) 442 | ;; capture the output type before switching context to `buf' 443 | ;; as `plantuml-output-type' can be local 444 | (output-type plantuml-output-type)) 445 | (cond 446 | ((= prefix 16) (switch-to-buffer-other-frame buf)) 447 | ((= prefix 4) (switch-to-buffer-other-window buf)) 448 | (t (display-buffer buf))) 449 | (when imagep 450 | (with-current-buffer buf 451 | (image-mode) 452 | (set-buffer-multibyte t) 453 | (when (and (equal "svg" output-type)) 454 | (let ((inhibit-read-only t) 455 | (svg-data (buffer-string))) 456 | (erase-buffer) 457 | (insert-image (create-image svg-data 'svg t :background plantuml-svg-background)))))) 458 | (set-window-point (get-buffer-window buf 'visible) (point-min)))) 459 | 460 | (defun plantuml-jar-preview-string (prefix string buf) 461 | "Preview the diagram from STRING by running the PlantUML JAR. 462 | Put the result into buffer BUF. Window is selected according to PREFIX: 463 | - 4 (when prefixing the command with C-u) -> new window 464 | - 16 (when prefixing the command with C-u C-u) -> new frame. 465 | - else -> new buffer" 466 | (let* ((process-connection-type nil) 467 | (ps (plantuml-jar-start-process buf))) 468 | (process-send-string ps string) 469 | (process-send-eof ps) 470 | (set-process-sentinel ps 471 | (lambda (_ps event) 472 | (unless (equal event "finished\n") 473 | (error "PLANTUML Preview failed: %s" event)) 474 | (plantuml-update-preview-buffer prefix buf))))) 475 | 476 | (defun plantuml-server-hex-encode-url (string) 477 | "HEX-encode STRING into a URL suitable for PlantUML server interactions." 478 | (let* ((coding-system (or buffer-file-coding-system 479 | 'utf-8)) 480 | (str (encode-coding-string string coding-system)) 481 | (encoded-string (mapconcat (lambda(x)(format "%02X" x)) str))) 482 | (concat plantuml-server-url "/" plantuml-output-type "/~h" encoded-string))) 483 | 484 | (defconst plantuml-server-base64-char-table 485 | (let ((translation-table (make-char-table 'translation-table)) 486 | (base64-chars "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=") 487 | (plantuml-chars "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_=")) 488 | (dotimes (i (length base64-chars)) 489 | (aset translation-table 490 | (aref base64-chars i) 491 | (aref plantuml-chars i))) 492 | translation-table)) 493 | 494 | (defun plantuml-server-deflate-encode-url (string) 495 | "DEFLATE-encode STRING into a URL suitable for PlantUML server interactions." 496 | (let* ((compressed-bytes (deflate-zlib-compress string 'dynamic)) 497 | (base64-encoded (base64-encode-string (apply #'unibyte-string compressed-bytes)))) 498 | (with-temp-buffer 499 | (insert base64-encoded) 500 | (translate-region (point-min) (point-max) plantuml-server-base64-char-table) 501 | (concat plantuml-server-url "/" plantuml-output-type "/~1" (buffer-string))))) 502 | 503 | (defun plantuml-server-encode-url (string) 504 | "Encode STRING into a URL suitable for PlantUML server interactions." 505 | (let ((encode-mode (or plantuml-server-encode-mode 'deflate))) 506 | (cl-case encode-mode 507 | (deflate (plantuml-server-deflate-encode-url string)) 508 | (hex (plantuml-server-hex-encode-url string))))) 509 | 510 | (defun plantuml-server-preview-string (prefix string buf) 511 | "Preview the diagram from STRING as rendered by the PlantUML server. 512 | Put the result into buffer BUF and place it according to PREFIX: 513 | - 4 (when prefixing the command with C-u) -> new window 514 | - 16 (when prefixing the command with C-u C-u) -> new frame. 515 | - else -> new buffer" 516 | (let* ((url-request-location (plantuml-server-encode-url string))) 517 | (let* ((response-buf (url-retrieve-synchronously url-request-location))) 518 | (save-current-buffer 519 | (save-match-data 520 | (with-current-buffer response-buf 521 | (set-buffer-multibyte t) 522 | (decode-coding-region (point-min) (point-max) 'utf-8) 523 | (goto-char (point-min)) 524 | (while (not (looking-at "\n")) 525 | (forward-line)) 526 | (kill-region (point-min) (+ 1 (point))) 527 | (copy-to-buffer buf (point-min) (point-max)) 528 | (plantuml-update-preview-buffer prefix buf))))))) 529 | 530 | (defun plantuml-executable-preview-string (prefix string buf) 531 | "Preview the diagram from STRING by running the PlantUML JAR. 532 | Put the result into buffer BUF. Window is selected according to PREFIX: 533 | - 4 (when prefixing the command with C-u) -> new window 534 | - 16 (when prefixing the command with C-u C-u) -> new frame. 535 | - else -> new buffer" 536 | (let* ((process-connection-type nil) 537 | (ps (plantuml-executable-start-process buf))) 538 | (process-send-string ps string) 539 | (process-send-eof ps) 540 | (set-process-sentinel ps 541 | (lambda (_ps event) 542 | (unless (equal event "finished\n") 543 | (error "PLANTUML Preview failed: %s" event)) 544 | (plantuml-update-preview-buffer prefix buf))))) 545 | 546 | (defun plantuml-exec-mode-preview-string (prefix mode string buf) 547 | "Preview the diagram from STRING using the execution mode MODE. 548 | Put the result into buffer BUF, selecting the window according to PREFIX: 549 | - 4 (when prefixing the command with C-u) -> new window 550 | - 16 (when prefixing the command with C-u C-u) -> new frame. 551 | - else -> new buffer" 552 | (let ((preview-fn (pcase mode 553 | ('jar #'plantuml-jar-preview-string) 554 | ('server #'plantuml-server-preview-string) 555 | ('executable #'plantuml-executable-preview-string)))) 556 | (if preview-fn 557 | (funcall preview-fn prefix string buf) 558 | (error "Unsupported execution mode %s" mode)))) 559 | 560 | (defun plantuml-themed-p (string) 561 | "Return non-nil if STRING is a PlantUML source with explicit theme directive." 562 | ;; check for beginning of line with word boundary 563 | (string-match-p "^\\s-*!theme\\b" string)) 564 | 565 | (defun plantuml-set-theme (string theme) 566 | "Add the THEME to the diagram STRING." 567 | (replace-regexp-in-string "^@startuml" 568 | (concat "@startuml\n!theme " theme) 569 | string)) 570 | 571 | (defun plantuml-preview-string (prefix string) 572 | "Preview diagram from PlantUML sources (as STRING), using prefix (as PREFIX) 573 | to choose where to display it. 574 | Put the result into buffer BUF, selecting the window according to PREFIX: 575 | - 4 (when prefixing the command with C-u) -> new window 576 | - 16 (when prefixing the command with C-u C-u) -> new frame. 577 | - else -> new buffer" 578 | (when-let ((b (get-buffer plantuml-preview-buffer)) 579 | (inhibit-read-only t)) 580 | (with-current-buffer b 581 | (erase-buffer))) 582 | 583 | (let* ((imagep (and (display-images-p) 584 | (plantuml-is-image-output-p))) 585 | (buf (get-buffer-create plantuml-preview-buffer)) 586 | (coding-system-for-read (and imagep 'binary)) 587 | (coding-system-for-write (and imagep 'binary)) 588 | (themed (plantuml-themed-p string))) 589 | (if (and (not (plantuml-themed-p string)) 590 | plantuml-preview-default-theme) 591 | ;; override the theme 592 | (plantuml-exec-mode-preview-string prefix 593 | (plantuml-get-exec-mode) 594 | (plantuml-set-theme string plantuml-preview-default-theme) 595 | buf) 596 | (plantuml-exec-mode-preview-string prefix 597 | (plantuml-get-exec-mode) 598 | string 599 | buf)))) 600 | 601 | (defun plantuml-preview-buffer (prefix) 602 | "Preview diagram from the PlantUML sources in the current buffer. 603 | Uses prefix (as PREFIX) to choose where to display it: 604 | - 4 (when prefixing the command with C-u) -> new window 605 | - 16 (when prefixing the command with C-u C-u) -> new frame. 606 | - else -> new buffer" 607 | (interactive "p") 608 | (plantuml-preview-string prefix (buffer-string))) 609 | 610 | (defun plantuml-preview-region (prefix begin end) 611 | "Preview diagram from the PlantUML sources in from BEGIN to END. 612 | Uses the current region when called interactively. 613 | Uses prefix (as PREFIX) to choose where to display it: 614 | - 4 (when prefixing the command with C-u) -> new window 615 | - 16 (when prefixing the command with C-u C-u) -> new frame. 616 | - else -> new buffer" 617 | (interactive "p\nr") 618 | (plantuml-preview-string prefix (concat "@startuml\n" 619 | (buffer-substring-no-properties 620 | begin end) 621 | "\n@enduml"))) 622 | 623 | (defun plantuml-preview-current-block (prefix) 624 | "Preview diagram from the PlantUML sources for the current block. 625 | The block is defined as starting from the previous @startuml to the next 626 | @enduml. Uses prefix (as PREFIX) to choose where to display it: 627 | - 4 (when prefixing the command with C-u) -> new window 628 | - 16 (when prefixing the command with C-u C-u) -> new frame. 629 | - else -> new buffer" 630 | (interactive "p") 631 | (save-restriction 632 | (narrow-to-region 633 | (search-backward "@startuml") (search-forward "@enduml")) 634 | (plantuml-preview-buffer prefix))) 635 | 636 | (defun plantuml-preview (prefix) 637 | "Preview diagram from the PlantUML sources. 638 | Uses the current region if one is active, or the entire buffer otherwise. 639 | Uses prefix (as PREFIX) to choose where to display it: 640 | - 4 (when prefixing the command with C-u) -> new window 641 | - 16 (when prefixing the command with C-u C-u) -> new frame. 642 | - else -> new buffer" 643 | (interactive "p") 644 | (if mark-active 645 | (plantuml-preview-region prefix (region-beginning) (region-end)) 646 | (plantuml-preview-buffer prefix))) 647 | 648 | (defun plantuml-deprecation-warning () 649 | "Warns the user about the deprecation of the `puml-mode' project." 650 | (if (and plantuml-suppress-deprecation-warning 651 | (featurep 'puml-mode)) 652 | (display-warning :warning 653 | "`puml-mode' is now deprecated and no longer updated, but it's still present in your system. \ 654 | You should move your configuration to use `plantuml-mode'. \ 655 | See more at https://github.com/skuro/puml-mode/issues/26"))) 656 | 657 | (defun plantuml-init-once (&optional mode) 658 | "Ensure initialization only happens once. 659 | Use exec mode MODE to load the language details 660 | or by first querying `plantuml-get-exec-mode'." 661 | (plantuml-deprecation-warning) 662 | (let ((mode (or mode (plantuml-get-exec-mode)))) 663 | (unless plantuml-kwdList 664 | (plantuml-init mode) 665 | (defvar plantuml-types-regexp (concat "^\\s *\\(" (regexp-opt plantuml-types 'words) "\\|\\<\\(note\\s +over\\|note\\s +\\(left\\|right\\|bottom\\|top\\)\\s +\\(of\\)?\\)\\>\\|\\<\\(\\(left\\|center\\|right\\)\\s +\\(header\\|footer\\)\\)\\>\\)")) 666 | (defvar plantuml-keywords-regexp (concat "^\\s *" (regexp-opt plantuml-keywords 'words) "\\|\\(<\\|<|\\|\\*\\|o\\)\\(\\.+\\|-+\\)\\|\\(\\.+\\|-+\\)\\(>\\||>\\|\\*\\|o\\)\\|\\.\\{2,\\}\\|-\\{2,\\}")) 667 | (defvar plantuml-builtins-regexp (regexp-opt plantuml-builtins 'words)) 668 | (defvar plantuml-preprocessors-regexp (concat "^\\s *" (regexp-opt plantuml-preprocessors 'words))) 669 | 670 | ;; Below are the regexp's for indentation. 671 | ;; Notes: 672 | ;; - there is some control on what it is indented by overriding some of below 673 | ;; X-start and X-end regexp before plantuml-mode is loaded. E.g., to disable 674 | ;; indentation on activate, you might define in your .emacs something like 675 | ;; (setq plantuml-indent-regexp-activate-start 676 | ;; "NEVER MATCH THIS EXPRESSION"); define _before_ load plantuml-mode! 677 | ;; (setq plantuml-indent-regexp-activate-end 678 | ;; "NEVER MATCH THIS EXPRESSION"); define _before_ load plantuml-mode! 679 | ;; - due to the nature of using (context-insensitive) regexp, indentation have 680 | ;; following limitations 681 | ;; - commands commented out by /' ... '/ will _not_ be ignored 682 | ;; and potentially lead to miss-indentation 683 | ;; - you can though somewhat correct mis-indentation by adding in '-comment lines 684 | ;; PLANTUML_MODE_INDENT_INCREASE and/or PLANTUML_MODE_INDENT_DECREASE 685 | ;; to increase and/or decrease the level of indentation 686 | ;; (Note: the line with the comment should not contain any text matching other indent 687 | ;; regexp or this user-control instruction will be ignored; also at most will count 688 | ;; per line ...) 689 | (defvar plantuml-indent-regexp-block-start "^.*{\s*$" 690 | "Indentation regex for all plantuml elements that might define a {} block. 691 | Plantuml elements like skinparam, rectangle, sprite, package, etc. 692 | The opening { has to be the last visible character in the line (whitespace 693 | might follow).") 694 | (defvar plantuml-indent-regexp-note-start "^\s*\\(floating\s+\\)?[hr]?note\s+\\(right\\|left\\|top\\|bottom\\|over\\|as\\)[^:]*\\(\\:\\:[^:]+\\)?$" "simplyfied regex; note syntax is especially inconsistent across diagrams") 695 | (defvar plantuml-indent-regexp-group-start "^\s*\\(alt\\|else\\|opt\\|loop\\|par\\|break\\|critical\\|group\\)\\(?:\s+.+\\|$\\)" 696 | "Indentation regex for plantuml group elements defined for sequence diagrams. 697 | Two variants for groups: keyword is either followed by whitespace and some text 698 | or it is followed by line end.") 699 | (defvar plantuml-indent-regexp-activate-start "^\s*activate\s+.+$") 700 | (defvar plantuml-indent-regexp-box-start "^\s*box\s+.+$") 701 | (defvar plantuml-indent-regexp-ref-start "^\s*ref\s+over\s+[^:]+?$") 702 | (defvar plantuml-indent-regexp-title-start "^\s*title\s*\\('.*\\)?$") 703 | (defvar plantuml-indent-regexp-header-start "^\s*\\(?:\\(?:center\\|left\\|right\\)\s+header\\|header\\)\s*\\('.*\\)?$") 704 | (defvar plantuml-indent-regexp-footer-start "^\s*\\(?:\\(?:center\\|left\\|right\\)\s+footer\\|footer\\)\s*\\('.*\\)?$") 705 | (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*\\('.*\\)?$") 706 | (defvar plantuml-indent-regexp-oldif-start "^.*if\s+\".*\"\s+then\s*\\('.*\\)?$" 707 | "used in current activity diagram, sometimes already mentioned as deprecated") 708 | (defvar plantuml-indent-regexp-newif-start "^\s*\\(?:else\\)?if\s+(.*)\s+then\s*.*$") 709 | (defvar plantuml-indent-regexp-loop-start "^\s*\\(?:repeat\s*\\|while\s+(.*).*\\)$") 710 | (defvar plantuml-indent-regexp-fork-start "^\s*\\(?:fork\\|split\\)\\(?:\s+again\\)?\s*$") 711 | (defvar plantuml-indent-regexp-case-start "^\s*\\(?:switch\\|case\\)\s-*(.*)\s*$") 712 | (defvar plantuml-indent-regexp-macro-start "^\s*!definelong.*$") 713 | (defvar plantuml-indent-regexp-user-control-start "^.*'.*\s*PLANTUML_MODE_INDENT_INCREASE\s*.*$") 714 | (defvar plantuml-indent-regexp-start (list plantuml-indent-regexp-block-start 715 | plantuml-indent-regexp-group-start 716 | plantuml-indent-regexp-activate-start 717 | plantuml-indent-regexp-box-start 718 | plantuml-indent-regexp-ref-start 719 | plantuml-indent-regexp-legend-start 720 | plantuml-indent-regexp-note-start 721 | plantuml-indent-regexp-newif-start 722 | plantuml-indent-regexp-loop-start 723 | plantuml-indent-regexp-fork-start 724 | plantuml-indent-regexp-case-start 725 | plantuml-indent-regexp-title-start 726 | plantuml-indent-regexp-header-start 727 | plantuml-indent-regexp-footer-start 728 | plantuml-indent-regexp-macro-start 729 | plantuml-indent-regexp-oldif-start 730 | plantuml-indent-regexp-user-control-start)) 731 | (defvar plantuml-indent-regexp-block-end "^\s*\\(?:}\\|endif\\|else\s*.*\\|end\\)\s*\\('.*\\)?$") 732 | (defvar plantuml-indent-regexp-note-end "^\s*\\(end\s+note\\|end[rh]note\\)\s*\\('.*\\)?$") 733 | (defvar plantuml-indent-regexp-group-end "^\s*end\s*\\('.*\\)?$") 734 | (defvar plantuml-indent-regexp-activate-end "^\s*deactivate\s+.+$") 735 | (defvar plantuml-indent-regexp-box-end "^\s*end\s+box\s*\\('.*\\)?$") 736 | (defvar plantuml-indent-regexp-ref-end "^\s*end\s+ref\s*\\('.*\\)?$") 737 | (defvar plantuml-indent-regexp-title-end "^\s*end\s+title\s*\\('.*\\)?$") 738 | (defvar plantuml-indent-regexp-header-end "^\s*endheader\s*\\('.*\\)?$") 739 | (defvar plantuml-indent-regexp-footer-end "^\s*endfooter\s*\\('.*\\)?$") 740 | (defvar plantuml-indent-regexp-legend-end "^\s*endlegend\s*\\('.*\\)?$") 741 | (defvar plantuml-indent-regexp-oldif-end "^\s*\\(endif\\|else\\)\s*\\('.*\\)?$") 742 | (defvar plantuml-indent-regexp-newif-end "^\s*\\(endif\\|elseif\\|else\\)\s*.*$") 743 | (defvar plantuml-indent-regexp-loop-end "^\s*\\(repeat\s*while\\|endwhile\\)\s*.*$") 744 | (defvar plantuml-indent-regexp-fork-end "^\s*\\(\\(fork\\|split\\)\s+again\\|end\s+\\(fork\\|split\\)\\)\s*\\(\{.*\}\\)?\s*$") 745 | (defvar plantuml-indent-regexp-case-end "^\s*\\(case\s-*(.*)\\|endswitch\\)\s*\\('.*\\)?$") 746 | (defvar plantuml-indent-regexp-macro-end "^\s*!enddefinelong\s*\\('.*\\)?$") 747 | (defvar plantuml-indent-regexp-user-control-end "^.*'.*\s*PLANTUML_MODE_INDENT_DECREASE\s*.*$") 748 | (defvar plantuml-indent-regexp-end (list plantuml-indent-regexp-block-end 749 | plantuml-indent-regexp-group-end 750 | plantuml-indent-regexp-activate-end 751 | plantuml-indent-regexp-box-end 752 | plantuml-indent-regexp-ref-end 753 | plantuml-indent-regexp-legend-end 754 | plantuml-indent-regexp-note-end 755 | plantuml-indent-regexp-newif-end 756 | plantuml-indent-regexp-loop-end 757 | plantuml-indent-regexp-fork-end 758 | plantuml-indent-regexp-case-end 759 | plantuml-indent-regexp-title-end 760 | plantuml-indent-regexp-header-end 761 | plantuml-indent-regexp-footer-end 762 | plantuml-indent-regexp-macro-end 763 | plantuml-indent-regexp-oldif-end 764 | plantuml-indent-regexp-user-control-end)) 765 | (setq plantuml-font-lock-keywords 766 | `( 767 | (,plantuml-types-regexp . font-lock-type-face) 768 | (,plantuml-keywords-regexp . font-lock-keyword-face) 769 | (,plantuml-builtins-regexp . font-lock-builtin-face) 770 | (,plantuml-preprocessors-regexp . font-lock-preprocessor-face) 771 | ;; note: order matters 772 | )) 773 | 774 | (setq plantuml-kwdList (make-hash-table :test 'equal)) 775 | (mapc (lambda (x) (puthash x t plantuml-kwdList)) plantuml-types) 776 | (mapc (lambda (x) (puthash x t plantuml-kwdList)) plantuml-keywords) 777 | (mapc (lambda (x) (puthash x t plantuml-kwdList)) plantuml-builtins) 778 | (mapc (lambda (x) (puthash x t plantuml-kwdList)) plantuml-preprocessors) 779 | (put 'plantuml-kwdList 'risky-local-variable t) 780 | 781 | ;; clear memory 782 | (setq plantuml-types nil) 783 | (setq plantuml-keywords nil) 784 | (setq plantuml-builtins nil) 785 | (setq plantuml-preprocessors nil) 786 | (setq plantuml-types-regexp nil) 787 | (setq plantuml-keywords-regexp nil) 788 | (setq plantuml-builtins-regexp nil) 789 | (setq plantuml-preprocessors-regexp nil)))) 790 | 791 | (defun plantuml-complete-symbol () 792 | "Perform keyword completion on word before cursor." 793 | (interactive) 794 | (let ((posEnd (point)) 795 | (meat (thing-at-point 'symbol)) 796 | maxMatchResult) 797 | 798 | (when (not meat) (setq meat "")) 799 | 800 | (setq maxMatchResult (try-completion meat plantuml-kwdList)) 801 | (cond ((eq maxMatchResult t)) 802 | ((null maxMatchResult) 803 | (message "Can't find completion for \"%s\"" meat) 804 | (ding)) 805 | ((not (string= meat maxMatchResult)) 806 | (delete-region (- posEnd (length meat)) posEnd) 807 | (insert maxMatchResult)) 808 | (t (message "Making completion list...") 809 | (with-output-to-temp-buffer "*Completions*" 810 | (display-completion-list 811 | (all-completions meat plantuml-kwdList))) 812 | (message "Making completion list...%s" "done"))))) 813 | 814 | (make-obsolete 'plantuml-complete-symbol 815 | "Use `completion-at-point' (C-M-i) instead" 816 | "1.7.0") 817 | 818 | (defun plantuml-completion-at-point-function () 819 | "Complete symbol at point using `plantuml-kwdList'. 820 | See `completion-at-point-functions'." 821 | (let ((thing-start (beginning-of-thing 'symbol)) 822 | (thing-end (end-of-thing 'symbol))) 823 | 824 | (list thing-start 825 | thing-end 826 | plantuml-kwdList 827 | '(:exclusive no)))) 828 | 829 | 830 | ;; indentation 831 | 832 | 833 | (defun plantuml-current-block-depth () 834 | "Trace the current block indentation level by looking back line by line." 835 | (save-excursion 836 | (let ((relative-depth 0)) 837 | ;; current line 838 | (beginning-of-line) 839 | (if (-any? 'looking-at plantuml-indent-regexp-end) 840 | (setq relative-depth (1- relative-depth))) 841 | 842 | ;; from current line backwards to beginning of buffer 843 | (while (not (bobp)) 844 | (forward-line -1) 845 | (if (-any? 'looking-at plantuml-indent-regexp-end) 846 | (setq relative-depth (1- relative-depth))) 847 | (if (-any? 'looking-at plantuml-indent-regexp-start) 848 | (setq relative-depth (1+ relative-depth)))) 849 | 850 | (if (<= relative-depth 0) 851 | 0 852 | relative-depth)))) 853 | 854 | (defun plantuml-indent-line () 855 | "Indent the current line to its desired indentation level. 856 | Restore point to same position in text of the line as before indentation." 857 | (interactive) 858 | ;; store position of point in line measured from end of line 859 | (let ((original-position-eol (- (line-end-position) (point)))) 860 | (save-excursion 861 | (beginning-of-line) 862 | (indent-line-to (* plantuml-indent-level (plantuml-current-block-depth)))) 863 | 864 | ;; restore position in text of line, but not before the beginning of the 865 | ;; current line 866 | (goto-char (max (line-beginning-position) 867 | (- (line-end-position) original-position-eol))))) 868 | 869 | 870 | ;;;###autoload 871 | (add-to-list 'auto-mode-alist '("\\.\\(pu\\|uml\\|plantuml\\|pum\\|plu\\)\\'" . plantuml-mode)) 872 | 873 | ;;;###autoload 874 | (define-derived-mode plantuml-mode prog-mode "plantuml" 875 | "Major mode for plantuml. 876 | 877 | Shortcuts Command Name 878 | \\[plantuml-complete-symbol] `plantuml-complete-symbol'" 879 | (plantuml-init-once) 880 | (make-local-variable 'plantuml-output-type) 881 | (set (make-local-variable 'comment-start-skip) "\\('+\\|/'+\\)\\s *") 882 | (set (make-local-variable 'comment-start) "/'") 883 | (set (make-local-variable 'comment-end) "'/") 884 | (set (make-local-variable 'comment-multi-line) t) 885 | (set (make-local-variable 'comment-style) 'extra-line) 886 | (set (make-local-variable 'indent-line-function) 'plantuml-indent-line) 887 | (make-local-variable 'plantuml-preview-default-theme) 888 | (setq font-lock-defaults '((plantuml-font-lock-keywords) nil t)) 889 | (setq-local completion-at-point-functions (list #'plantuml-complete-symbol))) 890 | 891 | (provide 'plantuml-mode) 892 | ;;; plantuml-mode.el ends here 893 | --------------------------------------------------------------------------------