Skip to content

Commit

Permalink
kivy-mode for emacs based on yaml-mode
Browse files Browse the repository at this point in the history
  • Loading branch information
duelafn committed May 1, 2012
1 parent 2df010e commit a6e38c7
Showing 1 changed file with 241 additions and 0 deletions.
241 changes: 241 additions & 0 deletions kivy/tools/highlight/kivy-mode.el
Original file line number Diff line number Diff line change
@@ -0,0 +1,241 @@
;; kivy-mode.el --- Emacs major mode for editing Kivy files
;;
;; Author: Dean Serenevy <[email protected]>
;;
;; This document borrowed heavily from yaml-mode.el by Yoshiki Kurihara and
;; Marshall Vandegrift.
;;
;; This file is not part of Emacs


;; 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; version 3.

;; 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 GNU Emacs; see the file COPYING. If not, write to the Free Software
;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
;; USA.

;;; Installation:

;; To install, just drop this file into a directory in your `load-path' and
;; (optionally) byte-compile it. To automatically handle files ending in
;; '.kv', add something like:
;;
;; (require 'kivy-mode)
;; (add-to-list 'auto-mode-alist '("\\.kv$" . kivy-mode))
;;
;; to your .emacs file.
;;
;; Unlike python-mode, this mode follows the Emacs convention of not
;; binding the ENTER key to `newline-and-indent'. To get this behavior, add
;; the key definition to `kivy-mode-hook':
;;
;; (add-hook 'kivy-mode-hook
;; '(lambda ()
;; (define-key kivy-mode-map "\C-m" 'newline-and-indent)))



;; User definable variables

(defgroup kivy nil
"Support for the kivy user interface definition format"
:group 'languages
:prefix "kivy-")

(defcustom kivy-mode-hook nil
"*Hook run by `kivy-mode'."
:type 'hook
:group 'kivy)

(defcustom kivy-indent-offset 4
"*Amount of offset per level of indentation."
:type 'integer
:group 'kivy)

(defcustom kivy-backspace-function 'backward-delete-char-untabify
"*Function called by `kivy-electric-backspace' when deleting backwards."
:type 'function
:group 'kivy)

(defface kivy-tab-face
'((((class color)) (:background "red" :foreground "red" :bold t))
(t (:reverse-video t)))
"Face to use for highlighting tabs in kivy files."
:group 'faces
:group 'kivy)

(defcustom kivy-imenu-generic-expression
'((nil "^\\([<>a-zA-Z_-]+\\):" 1))
"The imenu regex to parse an outline of the kivy file."
:type 'string
:group 'kivy)



;; Constants

(defconst kivy-mode-version "0.1.0" "Version of `kivy-mode.'")

(defconst kivy-blank-line-re "^ *$"
"Regexp matching a line containing only (valid) whitespace.")

(defconst kivy-comment-re "\\(?:^\\|\\s-+\\)\\(#.*\\)"
"Regexp matching a line containing a kivy comment or delimiter.")

(defconst kivy-directive-re "^\\(?:#:\\)\\(\\w+ +.*\\)"
"Regexp matching a line contatining a kivy directive.")

(defconst kivy-tag-re "^ *id: *\\([^ \n]+\\)$"
"Rexexp matching a kivy tag.")

(defconst kivy-bare-scalar-re
"\\(?:[^-:,#!\n{\\[ ]\\|[^#!\n{\\[ ]\\S-\\)[^#\n]*?"
"Rexexp matching a kivy bare scalar.")

(defconst kivy-hash-key-re
(concat "^ *"
"\\(" kivy-bare-scalar-re "\\) *:"
"\\(?: +\\|$\\)")
"Regexp matching a single kivy hash key.")

(defconst kivy-nested-map-re
(concat ".*: *$")
"Regexp matching a line beginning a kivy nested structure.")

(defconst kivy-constant-scalars-re
(concat "\\(?:^\\|\\(?::\\|-\\|,\\|{\\|\\[\\) +\\) *"
(regexp-opt
'("True" "False" "None") t)
" *$")
"Regexp matching certain scalar constants in scalar context")



;; Mode setup

(defvar kivy-mode-map ()
"Keymap used in `kivy-mode' buffers.")
(if kivy-mode-map
nil
(setq kivy-mode-map (make-sparse-keymap))
(define-key kivy-mode-map [backspace] 'kivy-electric-backspace)
)

(defvar kivy-mode-syntax-table nil
"Syntax table in use in kivy-mode buffers.")
(if kivy-mode-syntax-table
nil
(setq kivy-mode-syntax-table (make-syntax-table))
(modify-syntax-entry ?\' "\"" kivy-mode-syntax-table)
(modify-syntax-entry ?\" "\"" kivy-mode-syntax-table)
(modify-syntax-entry ?# "<" kivy-mode-syntax-table)
(modify-syntax-entry ?\n ">" kivy-mode-syntax-table)
(modify-syntax-entry ?\\ "\\" kivy-mode-syntax-table)
(modify-syntax-entry ?- "_" kivy-mode-syntax-table)
(modify-syntax-entry ?_ "w" kivy-mode-syntax-table)
)

(define-derived-mode kivy-mode fundamental-mode "kivy"
"Simple mode to edit kivy.
\\{kivy-mode-map}"
(set (make-local-variable 'comment-start) "# ")
(set (make-local-variable 'comment-start-skip) "#+ *")
(set (make-local-variable 'indent-line-function) 'kivy-indent-line)
(set (make-local-variable 'font-lock-defaults)
'(kivy-font-lock-keywords
nil nil nil nil
(font-lock-syntactic-keywords))))



;; Font-lock support

(defvar kivy-font-lock-keywords
(list
(cons kivy-comment-re '(1 font-lock-comment-face))
(cons kivy-constant-scalars-re '(1 font-lock-constant-face))
(cons kivy-tag-re '(1 font-lock-function-name-face))
(cons kivy-hash-key-re '(1 font-lock-variable-name-face t))
(cons kivy-directive-re '(1 font-lock-builtin-face))
'("^[\t]+" 0 'kivy-tab-face t))
"Additional expressions to highlight in kivy mode.")

(defvar kivy-font-lock-syntactic-keywords
(list '())
"Additional syntax features to highlight in kivy mode.")



;; Indentation and electric keys

(defun kivy-compute-indentation ()
"Calculate the maximum sensible indentation for the current line."
(save-excursion
(beginning-of-line)
(forward-line -1)
(while (and (looking-at kivy-blank-line-re)
(> (point) (point-min)))
(forward-line -1))
(+ (current-indentation)
(if (looking-at kivy-nested-map-re) kivy-indent-offset 0)
)))

(defun kivy-indent-line ()
"Indent the current line.
The first time this command is used, the line will be indented to the
maximum sensible indentation. Each immediately subsequent usage will
back-dent the line by `kivy-indent-offset' spaces. On reaching column
0, it will cycle back to the maximum sensible indentation."
(interactive "*")
(let ((ci (current-indentation))
(cc (current-column))
(need (kivy-compute-indentation)))
(save-excursion
(beginning-of-line)
(delete-horizontal-space)
(if (and (equal last-command this-command) (/= ci 0))
(indent-to (* (/ (- ci 1) kivy-indent-offset) kivy-indent-offset))
(indent-to need)))
(if (< (current-column) (current-indentation))
(forward-to-indentation 0))))

(defun kivy-electric-backspace (arg)
"Delete characters or back-dent the current line.
If invoked following only whitespace on a line, will back-dent to the
immediately previous multiple of `kivy-indent-offset' spaces."
(interactive "*p")
(if (or (/= (current-indentation) (current-column)) (bolp))
(funcall kivy-backspace-function arg)
(let ((ci (current-column)))
(beginning-of-line)
(delete-horizontal-space)
(indent-to (* (/ (- ci (* arg kivy-indent-offset))
kivy-indent-offset)
kivy-indent-offset)))))


(defun kivy-set-imenu-generic-expression ()
(make-local-variable 'imenu-generic-expression)
(make-local-variable 'imenu-create-index-function)
(setq imenu-create-index-function 'imenu-default-create-index-function)
(setq imenu-generic-expression kivy-imenu-generic-expression))

(add-hook 'kivy-mode-hook 'kivy-set-imenu-generic-expression)


(defun kivy-mode-version ()
"Diplay version of `kivy-mode'."
(interactive)
(message "kivy-mode %s" kivy-mode-version)
kivy-mode-version)

(provide 'kivy-mode)

0 comments on commit a6e38c7

Please sign in to comment.