update plantuml-mode

As plantuml.jar has added a new option “-language” which shows the keywords/builtins used in plantuml, the new plantuml-mode tries to take advantage of this feature. Here it is

;; plantuml-mode.el -- Major mode for plantuml

;; Author: Zhang Weize (zwz)
;; Keywords: uml ascii

;; You can redistribute this program and/or modify it under the terms
;; of the GNU General Public License as published by the Free Software
;; Foundation; either version 2, or (at your option) any later
;; version.

;;; DESCRIPTION

;; 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
;; using a simple and intuitive language.

;;; HISTORY
;; version 0.2, 2010-09-20 Initialize the keywords from the -language output of plantuml.jar instead of the hard-coded way.
;; version 0.1, 2010-08-25 First version


(require 'thingatpt)

(defgroup plantuml-mode nil
  "Major mode for editing plantuml file."
  :group 'languages)

(defvar plantuml-jar-path (expand-file-name "~/plantuml.jar"))

(defvar plantuml-mode-hook nil "Standard hook for plantuml-mode.")

(defvar plantuml-mode-version nil "plantuml-mode version string.")

(defvar plantuml-mode-map nil "Keymap for plantuml-mode")

;;; syntax table
(defvar plantuml-mode-syntax-table
  (let ((synTable (make-syntax-table)))
    (modify-syntax-entry ?' "< b" synTable)
    (modify-syntax-entry ?\n "> b" synTable)
    (modify-syntax-entry ?! "w" synTable)
    (modify-syntax-entry ?@ "w" synTable)
    (modify-syntax-entry ?# "'" synTable)
    synTable)
  "Syntax table for `plantuml-mode'.")

(defvar plantuml-types nil)
(defvar plantuml-keywords nil)
(defvar plantuml-preprocessors nil)
(defvar plantuml-builtins nil)

;; keyword completion
(defvar plantuml-kwdList nil "plantuml keywords.")

;;; font-lock

(defun plantuml-init ()
  "Initialize the keywords or builtins from the cmdline language output"
  (unless (file-exists-p plantuml-jar-path)
    (error "Could not find plantuml.jar at %s" plantuml-jar-path))
  (with-temp-buffer
    (shell-command (concat "java -jar "
                           (shell-quote-argument plantuml-jar-path)
                           " -language") (current-buffer))
    (goto-char (point-min))
    (let ((found (search-forward ";" nil nil))
          (word "")
          (count 0)
          (pos 0))
      (while found
        (forward-char)
        (setq word (current-word))
        (if (string= word "EOF") (setq found nil)
            ;; else
            (forward-line)
            (setq count (string-to-number (current-word)))
            (beginning-of-line 2)
            (setq pos (point))
            (forward-line count)
            (cond ((string= word "type")
                   (setq plantuml-types
                     (split-string
                      (buffer-substring-no-properties pos (point)))))
                  ((string= word "keyword")
                   (setq plantuml-keywords
                     (split-string
                      (buffer-substring-no-properties pos (point)))))
                  ((string= word "preprocessor")
                   (setq plantuml-preprocessors
                     (split-string
                      (buffer-substring-no-properties pos (point)))))
                  (t (setq plantuml-builtins
                           (append
                            plantuml-builtins
                            (split-string
                             (buffer-substring-no-properties pos (point)))))))
;;                  ((string= word "skinparameter")
;;                  ((string= word "color")))
            (setq found (search-forward ";" nil nil)))))))

(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)))

  (setq plantuml-font-lock-keywords
        `(
          (,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
          ))



  (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)

  ;; 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))

(defun plantuml-complete-symbol ()
  "Perform keyword completion on word before cursor."
  (interactive)
  (let ((posEnd (point))
        (meat (thing-at-point 'symbol))
        maxMatchResult)

    (when (not meat) (setq meat ""))

    (setq maxMatchResult (try-completion meat plantuml-kwdList))
    (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
                (all-completions meat plantuml-kwdList)
                meat))
             (message "Making completion list...%s" "done")))))

(add-to-list 'auto-mode-alist '("\\.plu$" . plantuml-mode))

;;;###autoload
(defun plantuml-mode ()
  "Major mode for plantuml.

Shortcuts             Command Name
\\[plantuml-complete-symbol]      `plantuml-complete-symbol'"

  (interactive)
  (kill-all-local-variables)

;;  (python-mode) ; for indentation
  (setq major-mode 'plantuml-mode
        mode-name "plantuml")
  (set-syntax-table plantuml-mode-syntax-table)
  (use-local-map plantuml-mode-map)

  (make-local-variable 'font-lock-defaults)
  (setq font-lock-defaults '((plantuml-font-lock-keywords) nil t))

  (run-mode-hooks 'plantuml-mode-hook))

(provide 'plantuml-mode)

About these ads
This entry was posted in Uncategorized and tagged , , , , , , , , , , , . Bookmark the permalink.

4 Responses to update plantuml-mode

  1. Joonhwan Lee says:

    Would it be possible for you to share this in github or something? It’d be great if you do!

  2. I just created a GitHub repo to store it, I did my best to not claim ownership of the code. Feel free to ask me to remove it if you don’t fancy it to be there.

    https://github.com/skuro/plantuml-mode

  3. Reblogged this on Duong Bao Duy and commented:
    awesome about UML with org-mode on emacs.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s