forked from kivy/kivy
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
kivy-mode for emacs based on yaml-mode
- Loading branch information
Showing
1 changed file
with
241 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |