2016-10-10 20:30:00 +02:00
;;; plantuml-mode.el --- Major mode for PlantUML -*- lexical-binding: t; -*-
2012-06-11 13:31:49 +02:00
2016-10-10 20:30:00 +02:00
;; Filename: plantuml-mode.el
2015-07-14 16:50:41 +02:00
;; Description: Major mode for PlantUML diagrams sources
2018-08-14 21:59:34 +02:00
;; Compatibility: Tested with Emacs 25 through 27 (current master)
2012-06-11 13:31:49 +02:00
;; Author: Zhang Weize (zwz)
2015-07-13 23:04:33 +02:00
;; Maintainer: Carlo Sciolla (skuro)
2015-09-21 17:28:46 +02:00
;; Keywords: uml plantuml ascii
2018-08-15 10:59:25 +02:00
;; Version: 1.2.7
2018-08-14 21:59:34 +02:00
;; Package-Requires: ((emacs "25.0"))
2012-06-11 13:31:49 +02:00
2017-08-18 12:16:12 +02:00
;; This file is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 3, or (at your option)
;; any later version.
;; This file is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
2012-06-11 13:31:49 +02:00
2015-07-14 16:50:41 +02:00
;;; Commentary:
;;
2012-06-11 13:31:49 +02:00
;; A major mode for plantuml, see: http://plantuml.sourceforge.net/
;; Plantuml is an open-source tool in java that allows to quickly write :
;; - sequence diagram,
;; - use case diagram,
;; - class diagram,
;; - activity diagram,
;; - component diagram,
;; - state diagram
;; - object diagram
2015-07-14 16:50:41 +02:00
;;; Change log:
;;
2019-01-07 22:25:02 +01:00
;; version 1.2.8, 2019-01-07 Support indentation for activate / deactivate blocks; allow customization of `plantuml-java-args'
2018-08-16 12:08:10 +02:00
;; version 1.2.7, 2018-08-15 Added support for indentation; Fixed the comiling error when installing with melpa
2018-07-17 09:03:00 +02:00
;; 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
2017-08-19 19:31:30 +02:00
;; version 1.2.5, 2017-08-19 #53 Fixed installation warnings
;; version 1.2.4, 2017-08-18 #60 Licensed with GPLv3+ to be compatible with Emacs
2016-12-25 20:42:24 +01:00
;; version 1.2.3, 2016-12-25 #50 unicode support in generated output
2016-11-11 11:05:24 +01:00
;; version 1.2.2, 2016-11-11 Fixed java commands handling under windows; support spaces in `plantuml-jar-path'
2016-11-11 09:19:47 +01:00
;; version 1.2.1, 2016-11-11 Support for paths like `~/.plantuml/plantuml.jar' for `plantuml-jar-path' (the tilde was previously unsupported)
2016-11-09 12:21:12 +01:00
;; version 1.2.0, 2016-11-09 Added `plantuml-preview-current-buffer', courtesy of @7mamu4
2016-11-08 12:33:24 +01:00
;; version 1.1.1, 2016-11-08 Fix process handling with Windows native emacs; better file extention match for autoloading the mode
2016-10-18 13:18:58 +02:00
;; 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.
2016-10-17 16:27:10 +02:00
;; version 1.0.1, 2016-10-17 Bugfix release: proper auto-mode-alist regex; init delayed at mode load; avoid calling hooks twice.
;; 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.
2016-10-16 16:57:09 +02:00
;; version 0.6.7, 2016-10-11 [from puml-mode] Added deprecation warning in favor of plantuml-mode
;; version 0.6.6, 2016-07-19 [from puml-mode] Added autoload, minor bug fixes
;; version 0.6.5, 2016-03-24 [from puml-mode] Added UTF8 support and open in new window / frame shortcuts
;; version 0.6.4, 2015-12-12 [from puml-mode] Added support for comments (single and multiline) -- thanks to https://github.com/nivekuil
;; version 0.6.3, 2015-11-07 [from puml-mode] Added per-buffer configurability of output type (thanks to https://github.com/davazp)
;; version 0.6.2, 2015-11-07 [from puml-mode] Added debugging capabilities to improve issue analysis
;; version 0.6.1, 2015-09-26 [from puml-mode] Bugfix: use eq to compare symbols instead of cl-equalp
;; version 0.6, 2015-09-26 [from puml-mode] Fixed PNG preview
;; version 0.5, 2015-09-21 [from puml-mode] Added preview capabilities
;; version 0.4, 2015-06-14 [from puml-mode] Use a puml- prefix to distinguish from the other plantuml-mode
;; version 0.3, 2015-06-13 [from puml-mode] Compatibility with Emacs 24.x
;; 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.
;; version 0.1, 2010-08-25 [from puml-mode] First version
2012-06-11 13:31:49 +02:00
2015-07-13 23:04:33 +02:00
;;; Code:
2012-06-11 13:31:49 +02:00
( require 'thingatpt )
2016-10-10 20:30:00 +02:00
( defgroup plantuml-mode nil
2012-06-11 13:31:49 +02:00
" Major mode for editing plantuml file. "
:group 'languages )
2016-10-10 20:30:00 +02:00
( defcustom plantuml-jar-path
2015-07-14 17:02:09 +02:00
( expand-file-name " ~/plantuml.jar " )
2018-07-17 09:03:00 +02:00
" The location of the PlantUML executable JAR. "
:type 'string
:group 'plantuml )
2012-06-11 13:31:49 +02:00
2016-10-10 20:30:00 +02:00
( defvar plantuml-mode-hook nil " Standard hook for plantuml-mode. " )
2012-06-11 13:31:49 +02:00
2018-08-15 10:59:25 +02:00
( defconst plantuml-mode-version " 1.2.7 " " The plantuml-mode version string. " )
2012-06-11 13:31:49 +02:00
2016-10-10 20:30:00 +02:00
( defvar plantuml-mode-debug-enabled nil )
2015-12-07 16:45:40 +01:00
2016-10-10 20:30:00 +02:00
( defvar plantuml-font-lock-keywords nil )
2015-12-07 17:06:19 +01:00
2016-10-10 20:30:00 +02:00
( defvar plantuml-mode-map
2016-10-10 19:42:40 +02:00
( let ( ( keymap ( make-sparse-keymap ) ) )
2016-10-10 20:30:00 +02:00
( define-key keymap ( kbd " C-c C-c " ) 'plantuml-preview )
2015-09-26 11:41:33 +02:00
keymap )
2016-10-10 20:30:00 +02:00
" Keymap for plantuml-mode. " )
2012-06-11 13:31:49 +02:00
2016-10-18 11:38:28 +02:00
( defcustom plantuml-java-command " java "
2018-07-17 09:03:00 +02:00
" The java command used to execute PlantUML. "
:type 'string
:group 'plantuml )
2016-10-14 15:37:02 +02:00
2019-01-07 21:15:41 +01:00
( defcustom plantuml-java-args ( list " -Djava.awt.headless=true " " -jar " )
" The parameters passed to `plantuml-java-command' when executing PlantUML. "
:type ' ( repeat string )
:group 'plantuml )
2018-07-17 09:03:00 +02:00
2019-01-07 21:15:41 +01:00
( defcustom plantuml-jar-args ( list " -charset " " UTF-8 " )
" The parameters passed to `plantuml.jar' , when executing PlantUML. "
:type ' ( repeat string )
:group 'plantuml )
2016-10-14 21:37:53 +02:00
2016-10-18 11:38:28 +02:00
( defcustom plantuml-suppress-deprecation-warning t
2018-07-17 09:03:00 +02:00
" To silence the deprecation warning when `puml-mode' is found upon loading. "
:type 'boolean
:group 'plantuml )
2016-10-18 11:38:28 +02:00
2016-10-10 20:30:00 +02:00
( defun plantuml-render-command ( &rest arguments )
2016-10-10 20:05:27 +02:00
" Create a command line to execute PlantUML with arguments (as ARGUMENTS). "
2018-07-17 09:03:00 +02:00
( let* ( ( cmd-list ( append plantuml-java-args ( list ( expand-file-name plantuml-jar-path ) ) plantuml-jar-args arguments ) )
2016-11-08 12:33:24 +01:00
( cmd ( mapconcat 'identity cmd-list " | " ) ) )
2016-10-22 21:15:22 +02:00
( plantuml-debug ( format " Command is [%s] " cmd ) )
cmd-list ) )
2016-10-10 19:42:40 +02:00
2012-06-11 13:31:49 +02:00
;;; syntax table
2016-10-10 20:30:00 +02:00
( defvar plantuml-mode-syntax-table
2012-06-11 13:31:49 +02:00
( let ( ( synTable ( make-syntax-table ) ) )
2016-10-17 22:12:27 +02:00
( modify-syntax-entry ?\/ " . 14c " synTable )
( modify-syntax-entry ?' " < 23 " synTable )
2015-12-12 16:45:43 +01:00
( modify-syntax-entry ?\n " > " synTable )
( modify-syntax-entry ?\r " > " synTable )
( modify-syntax-entry ?! " w " synTable )
( modify-syntax-entry ?@ " w " synTable )
( modify-syntax-entry ?# " ' " synTable )
2012-06-11 13:31:49 +02:00
synTable )
2016-10-10 20:30:00 +02:00
" Syntax table for `plantuml-mode' . " )
2012-06-11 13:31:49 +02:00
2016-10-10 20:30:00 +02:00
( defvar plantuml-types nil )
( defvar plantuml-keywords nil )
( defvar plantuml-preprocessors nil )
( defvar plantuml-builtins nil )
2012-06-11 13:31:49 +02:00
;; keyword completion
2016-10-10 20:30:00 +02:00
( defvar plantuml-kwdList nil " The plantuml keywords. " )
2012-06-11 13:31:49 +02:00
2016-10-10 20:30:00 +02:00
( defun plantuml-enable-debug ( )
" Enables debug messages into the *PLANTUML Messages* buffer. "
2015-12-07 16:49:21 +01:00
( interactive )
2016-10-10 20:30:00 +02:00
( setq plantuml-mode-debug-enabled t ) )
2015-12-07 16:45:40 +01:00
2016-10-10 20:30:00 +02:00
( defun plantuml-disable-debug ( )
" Stops any debug messages to be added into the *PLANTUML Messages* buffer. "
2015-12-07 16:49:21 +01:00
( interactive )
2016-10-10 20:30:00 +02:00
( setq plantuml-mode-debug-enabled nil ) )
2015-12-07 16:45:40 +01:00
2016-10-10 20:30:00 +02:00
( defun plantuml-debug ( msg )
" Writes msg (as MSG) into the *PLANTUML Messages* buffer without annoying the user. "
( if plantuml-mode-debug-enabled
( let* ( ( log-buffer-name " *PLANTUML Messages* " )
2015-12-07 16:45:40 +01:00
( log-buffer ( get-buffer-create log-buffer-name ) ) )
( save-excursion
( with-current-buffer log-buffer
( goto-char ( point-max ) )
( insert msg )
( insert " \n " ) ) ) ) ) )
2012-06-11 13:31:49 +02:00
2016-10-10 20:30:00 +02:00
( defun plantuml-init ( )
2015-07-14 16:50:41 +02:00
" Initialize the keywords or builtins from the cmdline language output. "
2016-10-22 21:15:22 +02:00
( unless ( or ( eq system-type 'cygwin ) ( file-exists-p plantuml-jar-path ) )
2016-10-10 20:30:00 +02:00
( error " Could not find plantuml.jar at %s " plantuml-jar-path ) )
2012-06-11 13:31:49 +02:00
( with-temp-buffer
2016-10-22 21:15:22 +02:00
( let ( ( cmd-args ( append ( list plantuml-java-command nil t nil )
2018-07-17 09:03:00 +02:00
( plantuml-render-command " -language " ) ) ) )
2016-10-22 21:15:22 +02:00
( apply 'call-process cmd-args )
2016-10-18 11:38:28 +02:00
( goto-char ( point-min ) ) )
2015-07-02 19:09:55 +02:00
( let ( ( found ( search-forward " ; " nil t ) )
2012-06-11 13:31:49 +02:00
( word " " )
( count 0 )
( pos 0 ) )
( while found
( forward-char )
( setq word ( current-word ) )
( if ( string= word " EOF " ) ( setq found nil )
2016-10-10 20:05:27 +02:00
;; else
( forward-line )
( setq count ( string-to-number ( current-word ) ) )
( beginning-of-line 2 )
( setq pos ( point ) )
( forward-line count )
( cond ( ( string= word " type " )
2016-10-10 20:30:00 +02:00
( setq plantuml-types
2016-10-10 20:05:27 +02:00
( split-string
( buffer-substring-no-properties pos ( point ) ) ) ) )
( ( string= word " keyword " )
2016-10-10 20:30:00 +02:00
( setq plantuml-keywords
2016-10-10 20:05:27 +02:00
( split-string
( buffer-substring-no-properties pos ( point ) ) ) ) )
( ( string= word " preprocessor " )
2016-10-10 20:30:00 +02:00
( setq plantuml-preprocessors
2016-10-10 20:05:27 +02:00
( split-string
( buffer-substring-no-properties pos ( point ) ) ) ) )
2016-10-10 20:30:00 +02:00
( t ( setq plantuml-builtins
2016-10-10 20:05:27 +02:00
( append
2016-10-10 20:30:00 +02:00
plantuml-builtins
2016-10-10 20:05:27 +02:00
( split-string
( buffer-substring-no-properties pos ( point ) ) ) ) ) ) )
( setq found ( search-forward " ; " nil nil ) ) ) ) ) ) )
2012-06-11 13:31:49 +02:00
2016-10-10 20:30:00 +02:00
( defconst plantuml-preview-buffer " *PLANTUML Preview* " )
2015-09-14 12:04:32 +02:00
2016-10-10 20:30:00 +02:00
( defvar plantuml-output-type
2015-09-26 12:42:34 +02:00
( if ( not ( display-images-p ) )
" utxt "
( cond ( ( image-type-available-p 'svg ) " svg " )
2016-01-24 21:34:23 +01:00
( ( image-type-available-p 'png ) " png " )
( t " utxt " ) ) )
2015-09-26 12:39:16 +02:00
" Specify the desired output type to use for generated diagrams. " )
2016-10-10 20:30:00 +02:00
( defun plantuml-read-output-type ( )
2015-09-26 12:39:16 +02:00
" Read from the minibuffer a output type. "
( let* ( ( completion-ignore-case t )
( available-types
( append
( and ( image-type-available-p 'svg ) ' ( " svg " ) )
( and ( image-type-available-p 'png ) ' ( " png " ) )
' ( " utxt " ) ) ) )
2016-10-10 20:30:00 +02:00
( completing-read ( format " Output type [%s]: " plantuml-output-type )
2015-09-26 12:39:16 +02:00
available-types
nil
t
nil
nil
2016-10-10 20:30:00 +02:00
plantuml-output-type ) ) )
2015-09-26 12:39:16 +02:00
2016-10-10 20:30:00 +02:00
( defun plantuml-set-output-type ( type )
2015-12-07 17:06:19 +01:00
" Set the desired output type (as TYPE) for the current buffer.
2015-12-07 17:43:36 +01:00
If the
2016-10-10 20:30:00 +02:00
major mode of the current buffer mode is not plantuml-mode, set the
2015-09-26 12:39:16 +02:00
default output type for new buffers. "
2016-10-10 20:30:00 +02:00
( interactive ( list ( plantuml-read-output-type ) ) )
( setq plantuml-output-type type ) )
2015-09-26 12:39:16 +02:00
2016-10-10 20:30:00 +02:00
( defun plantuml-is-image-output-p ( )
2015-09-21 17:03:33 +02:00
" Return true if the diagram output format is an image, false if it's text based. "
2016-10-10 20:30:00 +02:00
( not ( equal " utxt " plantuml-output-type ) ) )
2015-09-21 17:03:33 +02:00
2016-10-10 20:30:00 +02:00
( defun plantuml-output-type-opt ( )
2015-09-21 17:03:33 +02:00
" Create the flag to pass to PlantUML to produce the selected output format. "
2016-10-10 20:30:00 +02:00
( concat " -t " plantuml-output-type ) )
2015-09-14 12:04:32 +02:00
2019-01-07 21:15:41 +01:00
( defun plantuml-start-process ( buf )
2016-10-18 11:38:28 +02:00
" Run PlantUML as an Emacs process and puts the output into the given buffer (as BUF). "
2019-01-07 21:15:41 +01:00
( apply #' start-process
" PLANTUML " buf plantuml-java-command
` ( ,@ plantuml-java-args
, ( expand-file-name plantuml-jar-path )
, ( plantuml-output-type-opt )
,@ plantuml-jar-args
" -p " ) ) )
2016-10-18 11:38:28 +02:00
2016-10-10 20:30:00 +02:00
( defun plantuml-preview-string ( prefix string )
2016-10-10 20:05:27 +02:00
" Preview diagram from PlantUML sources (as STRING), using prefix (as PREFIX)
to choose where to display it:
2016-03-24 23:25:51 +01:00
- 4 ( when prefixing the command with C-u ) -> new window
- 16 ( when prefixing the command with C-u C-u ) -> new frame.
- else -> new buffer "
2016-10-10 20:30:00 +02:00
( let ( ( b ( get-buffer plantuml-preview-buffer ) ) )
2015-09-14 12:04:32 +02:00
( when b
( kill-buffer b ) ) )
2015-12-07 17:43:36 +01:00
2015-09-26 13:05:00 +02:00
( let* ( ( imagep ( and ( display-images-p )
2016-10-10 20:30:00 +02:00
( plantuml-is-image-output-p ) ) )
2015-09-26 13:05:00 +02:00
( process-connection-type nil )
2016-10-10 20:30:00 +02:00
( buf ( get-buffer-create plantuml-preview-buffer ) )
2015-09-26 13:05:00 +02:00
( coding-system-for-read ( and imagep 'binary ) )
2015-12-07 17:43:36 +01:00
( coding-system-for-write ( and imagep 'binary ) ) )
2016-10-18 11:38:28 +02:00
( let ( ( ps ( plantuml-start-process buf ) ) )
2016-10-10 20:05:27 +02:00
( process-send-string ps string )
2015-09-14 12:04:32 +02:00
( process-send-eof ps )
2015-09-26 13:05:00 +02:00
( set-process-sentinel ps
2016-07-08 04:31:06 +02:00
( lambda ( _ps event )
2015-09-26 13:05:00 +02:00
( unless ( equal event " finished \n " )
2016-10-10 20:30:00 +02:00
( error " PLANTUML Preview failed: %s " event ) )
2016-03-21 16:32:17 +01:00
( cond
( ( = prefix 16 )
2016-10-10 20:30:00 +02:00
( switch-to-buffer-other-frame plantuml-preview-buffer ) )
2016-03-21 16:32:17 +01:00
( ( = prefix 4 )
2016-10-10 20:30:00 +02:00
( switch-to-buffer-other-window plantuml-preview-buffer ) )
( t ( switch-to-buffer plantuml-preview-buffer ) ) )
2015-09-26 13:05:00 +02:00
( when imagep
( image-mode )
( set-buffer-multibyte t ) ) ) ) ) ) )
2015-09-14 12:04:32 +02:00
2016-10-10 20:30:00 +02:00
( defun plantuml-preview-buffer ( prefix )
2016-10-10 20:05:27 +02:00
" Preview diagram from the PlantUML sources in the current buffer.
Uses prefix ( as PREFIX ) to choose where to display it:
- 4 ( when prefixing the command with C-u ) -> new window
- 16 ( when prefixing the command with C-u C-u ) -> new frame.
- else -> new buffer "
( interactive " p " )
2016-10-10 20:30:00 +02:00
( plantuml-preview-string prefix ( buffer-string ) ) )
2016-10-10 20:05:27 +02:00
2016-11-12 01:48:47 +01:00
( defun plantuml-preview-region ( prefix begin end )
" Preview diagram from the PlantUML sources in from BEGIN to END.
Uses the current region when called interactively.
2016-10-10 20:05:27 +02:00
Uses prefix ( as PREFIX ) to choose where to display it:
- 4 ( when prefixing the command with C-u ) -> new window
- 16 ( when prefixing the command with C-u C-u ) -> new frame.
- else -> new buffer "
2016-11-12 01:48:47 +01:00
( interactive " p \n r " )
2016-10-10 20:30:00 +02:00
( plantuml-preview-string prefix ( concat " @startuml \n "
2018-08-15 10:59:25 +02:00
( buffer-substring-no-properties
begin end )
" \n @enduml " ) ) )
2016-10-10 20:05:27 +02:00
2016-10-26 01:03:37 +02:00
( defun plantuml-preview-current-block ( prefix )
" Preview diagram from the PlantUML sources from the previous @startuml to the next @enduml.
Uses prefix ( as PREFIX ) to choose where to display it:
- 4 ( when prefixing the command with C-u ) -> new window
- 16 ( when prefixing the command with C-u C-u ) -> new frame.
- else -> new buffer "
( interactive " p " )
( save-restriction
( narrow-to-region
( search-backward " @startuml " ) ( search-forward " @enduml " ) )
( plantuml-preview-buffer prefix ) ) )
2016-10-10 20:30:00 +02:00
( defun plantuml-preview ( prefix )
2016-10-10 20:05:27 +02:00
" Preview diagram from the PlantUML sources.
Uses the current region if one is active, or the entire buffer otherwise.
Uses prefix ( as PREFIX ) to choose where to display it:
- 4 ( when prefixing the command with C-u ) -> new window
- 16 ( when prefixing the command with C-u C-u ) -> new frame.
- else -> new buffer "
( interactive " p " )
2016-10-14 00:20:25 +02:00
( if mark-active
2016-11-12 01:48:47 +01:00
( plantuml-preview-region prefix ( region-beginning ) ( region-end ) )
2018-08-15 10:59:25 +02:00
( plantuml-preview-buffer prefix ) ) )
2016-10-10 20:05:27 +02:00
2016-10-16 20:37:20 +02:00
( defun plantuml-init-once ( )
2016-10-18 11:38:28 +02:00
" Ensure initialization only happens once. "
2016-10-16 20:37:20 +02:00
( unless plantuml-kwdList
( plantuml-init )
( 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 \\ ) \\ ) \\ > \\ ) " ) )
( defvar plantuml-keywords-regexp ( concat " ^ \\ s * " ( regexp-opt plantuml-keywords 'words ) " \\ | \\ (< \\ |<| \\ | \\ * \\ |o \\ ) \\ ( \\ .+ \\ |-+ \\ ) \\ | \\ ( \\ .+ \\ |-+ \\ ) \\ (> \\ ||> \\ | \\ * \\ |o \\ ) \\ | \\ . \\ {2, \\ } \\ |- \\ {2, \\ } " ) )
( defvar plantuml-builtins-regexp ( regexp-opt plantuml-builtins 'words ) )
( defvar plantuml-preprocessors-regexp ( concat " ^ \\ s * " ( regexp-opt plantuml-preprocessors 'words ) ) )
2019-01-07 21:23:04 +01:00
( defvar plantuml-indent-regexp-start " ^[ \t ]* \\ ( \\ (?:.* \\ )? \s * \\ (?:[<>.*a-z-|]+ \\ )? \s * \\ (?: \\ [[a-zA-Z]+ \\ ] \\ )? \s +if \s +.* \\ |loop \s +.* \\ |group \s +.* \\ |par \s *$ \\ |opt \s +.* \\ |alt \s +.* \\ |else \\ |note \s +over \\ |note \s as \s .* \\ |note \s + \\ ( \\ (?: \\ (?:buttom \\ |left \\ |right \\ |top \\ ) \\ ) \\ ) \\ (?: \s +of \\ )? \\ | \\ (?:class \\ |enum \\ |package \\ |database \\ ) \s +.*{ \\ |activate \s +.+ \\ ) " )
( defvar plantuml-indent-regexp-end " ^[ \t ]* \\ (endif \\ |else \\ |end \\ |end \s +note \\ |.*} \\ |deactivate \s +.+ \\ ) " )
2016-10-17 08:21:00 +02:00
2016-10-16 20:37:20 +02:00
( setq plantuml-font-lock-keywords
2016-10-17 08:21:00 +02:00
` (
( , plantuml-types-regexp . font-lock-type-face )
( , plantuml-keywords-regexp . font-lock-keyword-face )
( , plantuml-builtins-regexp . font-lock-builtin-face )
( , plantuml-preprocessors-regexp . font-lock-preprocessor-face )
;; note: order matters
) )
2016-10-16 20:37:20 +02:00
( setq plantuml-kwdList ( make-hash-table :test 'equal ) )
( mapc ( lambda ( x ) ( puthash x t plantuml-kwdList ) ) plantuml-types )
( mapc ( lambda ( x ) ( puthash x t plantuml-kwdList ) ) plantuml-keywords )
( mapc ( lambda ( x ) ( puthash x t plantuml-kwdList ) ) plantuml-builtins )
( mapc ( lambda ( x ) ( puthash x t plantuml-kwdList ) ) plantuml-preprocessors )
( put 'plantuml-kwdList 'risky-local-variable t )
2016-10-17 08:21:00 +02:00
2016-10-16 20:37:20 +02:00
;; clear memory
( setq plantuml-types nil )
( setq plantuml-keywords nil )
( setq plantuml-builtins nil )
( setq plantuml-preprocessors nil )
( setq plantuml-types-regexp nil )
( setq plantuml-keywords-regexp nil )
( setq plantuml-builtins-regexp nil )
( setq plantuml-preprocessors-regexp nil ) ) )
2016-10-10 20:30:00 +02:00
( defun plantuml-complete-symbol ( )
2012-06-11 13:31:49 +02:00
" Perform keyword completion on word before cursor. "
( interactive )
( let ( ( posEnd ( point ) )
( meat ( thing-at-point 'symbol ) )
maxMatchResult )
( when ( not meat ) ( setq meat " " ) )
2016-10-10 20:30:00 +02:00
( setq maxMatchResult ( try-completion meat plantuml-kwdList ) )
2012-06-11 13:31:49 +02:00
( cond ( ( eq maxMatchResult t ) )
( ( null maxMatchResult )
( message " Can't find completion for \" %s \" " meat )
( ding ) )
( ( not ( string= meat maxMatchResult ) )
( delete-region ( - posEnd ( length meat ) ) posEnd )
( insert maxMatchResult ) )
( t ( message " Making completion list... " )
( with-output-to-temp-buffer " *Completions* "
( display-completion-list
2016-10-10 20:30:00 +02:00
( all-completions meat plantuml-kwdList ) ) )
2012-06-11 13:31:49 +02:00
( message " Making completion list...%s " " done " ) ) ) ) )
2018-08-14 23:08:29 +02:00
;; indentation
2018-08-16 11:32:44 +02:00
( defun plantuml-current-block-depth ( )
" Trace the current block indentation level by recursively looking back line by line. "
2018-08-16 12:02:30 +02:00
;; forward declare the lazy initialized constants
( defvar plantuml-indent-regexp-start )
( defvar plantuml-indent-regexp-end )
2018-08-14 23:08:29 +02:00
( save-excursion
2019-01-07 21:23:04 +01:00
( let ( ( relative-depth 0 ) )
;; current line
2018-08-16 11:32:44 +02:00
( beginning-of-line )
2019-01-07 21:23:04 +01:00
( if ( looking-at plantuml-indent-regexp-end )
( setq relative-depth ( 1- relative-depth ) ) )
;; from current line backwards to beginning of buffer
( while ( not ( bobp ) )
( forward-line -1 )
2018-08-14 23:08:29 +02:00
( if ( looking-at plantuml-indent-regexp-end )
2018-08-16 11:32:44 +02:00
( setq relative-depth ( 1- relative-depth ) ) )
2018-08-14 23:08:29 +02:00
( if ( looking-at plantuml-indent-regexp-start )
2019-01-07 21:23:04 +01:00
( setq relative-depth ( 1+ relative-depth ) ) ) )
2018-08-14 23:08:29 +02:00
2018-08-16 11:32:44 +02:00
( if ( <= relative-depth 0 )
2018-08-14 23:08:29 +02:00
0
2018-08-16 11:32:44 +02:00
relative-depth ) ) ) )
2018-08-14 23:08:29 +02:00
( defun plantuml-indent-line ( )
2019-01-07 21:23:04 +01:00
" Indent the current line to its desired indentation level.
Restore point to same position in text of the line as before indentation. "
2018-08-14 23:08:29 +02:00
( interactive )
2018-08-16 12:02:30 +02:00
;; forward declare the lazy initialized constants
( defvar plantuml-indent-regexp-start )
( defvar plantuml-indent-regexp-end )
2019-01-07 21:23:04 +01:00
;; store position of point in line measured from end of line
( let ( ( original-position-eol ( - ( line-end-position ) ( point ) ) ) )
2018-08-16 11:32:44 +02:00
( save-excursion
( beginning-of-line )
2019-01-07 21:23:04 +01:00
( indent-line-to ( * tab-width ( plantuml-current-block-depth ) ) ) )
;; restore position in text of line
( goto-char ( - ( line-end-position ) original-position-eol ) ) ) )
2018-08-14 23:08:29 +02:00
2016-07-08 04:32:08 +02:00
;;;###autoload
2016-10-22 16:13:52 +02:00
( add-to-list 'auto-mode-alist ' ( " \\ . \\ (plantuml \\ |pum \\ |plu \\ ) \\ ' " . plantuml-mode ) )
2012-06-11 13:31:49 +02:00
;;;###autoload
2016-10-10 20:30:00 +02:00
( define-derived-mode plantuml-mode prog-mode " plantuml "
2012-06-11 13:31:49 +02:00
" Major mode for plantuml.
Shortcuts Command Name
2016-10-10 20:30:00 +02:00
\\ [ plantuml-complete-symbol ] ` plantuml-complete-symbol ' "
2016-10-16 20:37:20 +02:00
( plantuml-init-once )
2016-10-10 20:30:00 +02:00
( make-local-variable 'plantuml-output-type )
2015-12-12 16:45:43 +01:00
( set ( make-local-variable 'comment-start-skip ) " \\ ('+ \\ |/'+ \\ ) \\ s * " )
( set ( make-local-variable 'comment-start ) " /' " )
( set ( make-local-variable 'comment-end ) " '/ " )
( set ( make-local-variable 'comment-multi-line ) t )
( set ( make-local-variable 'comment-style ) 'extra-line )
2018-08-14 23:08:29 +02:00
( set ( make-local-variable 'indent-line-function ) 'plantuml-indent-line )
2016-10-17 08:39:34 +02:00
( setq font-lock-defaults ' ( ( plantuml-font-lock-keywords ) nil t ) ) )
2016-10-10 20:25:07 +02:00
2016-10-14 21:27:20 +02:00
( defun plantuml-deprecation-warning ( )
" Warns the user about the deprecation of the `puml-mode' project. "
2016-10-14 21:37:53 +02:00
( if ( and plantuml-suppress-deprecation-warning
( featurep 'puml-mode ) )
2016-10-14 21:27:20 +02:00
( display-warning :warning
" `puml-mode' is now deprecated and no longer updated, but it's still present in your system. \
You should move your configuration to use ` plantuml-mode '. See https://github.com/sytac/plantuml-mode. \
See more at https://github.com/skuro/puml-mode/issues/26 " )))
( add-hook 'plantuml-mode-hook 'plantuml-deprecation-warning )
2016-10-10 20:30:00 +02:00
( provide 'plantuml-mode )
;;; plantuml-mode.el ends here