Skip to content
Browse files


  • Loading branch information...
1 parent 03b3d40 commit b9a88d5d633ca33a5b018410516fe4c1e2dec3a2 @magnars committed
4 mode-mappings.el
@@ -35,6 +35,10 @@
(add-to-list 'auto-mode-alist '("Gemfile" . ruby-mode))
(add-to-list 'auto-mode-alist '("\\.erb$" . rhtml-mode))
+;; Groovy
+(autoload 'groovy-mode "groovy-mode")
+(add-to-list 'auto-mode-alist '("\\.groovy$" . groovy-mode))
;; SVG
(add-to-list 'auto-mode-alist '("\\.svg$" . image-mode))
10 site-lisp/groovy-mode/README
@@ -0,0 +1,10 @@
+This is a collection of (X)Emacs modes for use with Groovy-related technology -- Groovy, Grails, etc.
+The Groovy mode is a derived mode of Java mode which is itself a derived mode in CC Mode. Inspiration came
+from Dylan R.E. Moonfire's C# mode.
+This software is licenced using GNU General Public Licence version 2.
+The master of all the material is the Bazaar branch lp:groovy-emacs-mode. See
+Bazaar is used for development, with public feature branches being held on Launchpad.
339 site-lisp/groovy-mode/gpl.txt
@@ -0,0 +1,339 @@
+ Version 2, June 1991
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+ Preamble
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+ The precise terms and conditions for copying, distribution and
+modification follow.
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+ How to Apply These Terms to Your New Programs
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+ This program 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 2 of the License, or
+ (at your option) any later version.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ 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, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+Also add information on how to contact you by electronic and paper mail.
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
181 site-lisp/groovy-mode/grails-mode.el
@@ -0,0 +1,181 @@
+;;; grails-mode.el --- minor-mode that adds some Grails project management to a grails project
+;; Copyright (C) 2010 Jim Morris
+;; Author: Jim Morris <>
+;; Version: 0.1
+;; URL:
+;; This file is not currently part of GNU Emacs.
+;; This program 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 2, or (at
+;; your option) any later version.
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; General Public License for more details.
+;; You should have received a copy of the GNU General Public License
+;; along with this program ; see the file COPYING. If not, write to
+;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+;;; depends on
+;; groovy-mode
+;; find-cmd
+;; anything
+;; anything-config
+;;; Commentary:
+;; A minor mode that adds some useful commands for navigating around
+;; a grails project
+;; In the root of the grails project (where the grails-app directory is)
+;; add this to your .dir-locals.el file (v23+)
+;; (groovy-mode . ((grails-mode . 1)))
+;; (java-mode . ((grails-mode . 1)))
+;; (html-mode . ((grails-mode . 1)))
+;; This will turn on grails minor mode whenever a groovy, java or gsp file is opened,
+;; this presumes you have gsp files et to use html-mode adjust to whatever mode gsp files use
+;; or just add this to have grails mode with any file in that directory structure
+;; ((nil . ((grails-mode . 1))))
+;; The main addition is a view in anything that shows all the grails project files
+(require 'find-cmd)
+ (defvar anything-project-root))
+;; TODO
+(defun grails-jump-to-model ()
+ "Jump to the domain model for the given context."
+ (interactive)
+ (let (var1)
+ (setq var1 'some)
+ (message "jump to model at point")
+ )
+ )
+;; TODO
+(defun grails-jump-to-controller ()
+ "thisandthat."
+ (interactive)
+ (let (var1)
+ (setq var1 'some)
+ (message "jump to controller at point")
+ )
+ )
+;; TODO
+(defun grails-jump-to-view ()
+ "Jumps the view for the controller action we are in"
+ (interactive)
+ (let (var1)
+ (setq var1 'some)
+ (message "jump to view for given action")
+ )
+ )
+;; Handle anything integration with grails project view
+(defvar grails-root-extra-find-args
+ (find-to-string '(prune (name ".svn" ".git")))
+ "Extra find args that will be AND'd to the defaults (which are
+in `grails-root-file-find-process')")
+(defun grails-make-displayable-name (path)
+ "makes path into a displayable name. eg view(post): file, domain: file, controller: name"
+ (let ((dir (file-name-directory path))
+ (name (file-name-nondirectory path)))
+ (let
+ ((type (cond
+ ((string-match "/grails-app/views/\\([a-zA-Z0-9_]+\\)/" dir)
+ (concat "view(" (match-string 1 dir) ")"))
+ ((string-match "/grails-app/controllers/.*/\\([a-zA-Z0-9_]+\\)Controller" dir) "controller")
+ ((string-match "/grails-app/domain/" dir) "domain")
+ ((string-match "/grails-app/conf/" dir) "configuration")
+ ((string-match "/grails-app/i18n/" dir) "i18n")
+ ((string-match "/grails-app/services/" dir) "services")
+ ((string-match "/grails-app/taglib/" dir) "taglib")
+ ((string-match "/grails-app/utils/" dir) "utils")
+ ((string-match "/grails-app/\\([a-zA-Z0-9_]+\\)/" dir) (match-string 1 dir))
+ (t "misc file"))))
+ (concat type ": " (file-name-sans-extension name)))))
+(defun grails-list-project-files ()
+ "Returns a list of all files found under the grails project."
+ ;; find root of project
+ ;; TODO should also check for grails-app directory
+ (setq grails-project-root
+ (locate-dominating-file default-directory "build.xml"))
+ ;; get a list of all the relevant files
+ (setq grails-project-files-list
+ (split-string
+ (shell-command-to-string (concat "find " grails-project-root "grails-app "
+ (find-to-string
+ `(or (name "*.groovy")
+ (name "*.gsp")))))))
+ ;; convert the list into cons pair of (display . filepath) where
+ ;; display is a friendly name
+ (setq grails-project-files-list-display
+ (mapcar
+ (lambda (f)
+ (cons (grails-make-displayable-name f) f)) grails-project-files-list)))
+;; anything source for showing all grails project files
+(defvar anything-grails-project-files
+ '((name . "Files in Grails Project")
+ (candidates . grails-project-files-list-display)
+ (match anything-c-match-on-file-name)
+ ;(candidate-transformer nil)
+ (type . file)))
+(defun grails-show-project-files ()
+ "Uses Anything to show all the project files"
+ (interactive)
+ (grails-list-project-files)
+ (anything '(anything-grails-project-files)))
+(define-minor-mode grails-mode
+ "Grails Minor Mode.
+ With no argument, this command toggles the mode.
+ Non-null prefix argument turns on the mode.
+ Null prefix argument turns off the mode.
+ When Grails mode is enabled, several keys are enabled that
+ will allow navigation around a typical grails project."
+ ;; The initial value.
+ :init-value nil
+ ;; The indicator for the mode line.
+ :lighter " Grails"
+ ;; The minor mode bindings.
+ :keymap
+ '(("\C-c/m" . grails-jump-to-model)
+ ("\C-c/c" . grails-jump-to-controller)
+ ("\C-c/v" . grails-jump-to-view)
+ ("\C-ca" . grails-show-project-files)
+ )
+ :group 'grails)
+(provide 'grails-mode)
166 site-lisp/groovy-mode/groovy-electric.el
@@ -0,0 +1,166 @@
+;;; groovy-electric.el --- Electric mode for Groovy
+;; -*-Emacs-Lisp-*-
+;; Author: Jim Morris <>
+;; Created: 2009-12-11
+;; Copyright (C) 2009 Jim Morris
+;; This program 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 2 of the License, or
+;; (at your option) any later version.
+;; This program 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, write
+;; to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+;; Based on ruby-electric.el Copyright (C) 2005 by Dee Zsombor <dee dot zsombor at gmail dot com>.
+;; Due credit: original work was inspired by a code snippet posted by
+;; Frederick Ros at
+;;; Commentary:
+;; By default automatically inserts closing delimiter for {[('"
+;; Additionally when in a GString typing a $ will insert { } and place
+;; cursor between the braces. All these can be turned on or off
+;; individually in the customization window for groovy-electric
+;; Usage:
+;; 0) copy groovy-electric.el into directory where emacs can find it.
+;; 1) modify your startup file (.emacs or whatever) by adding
+;; following lines to load and enable the mode when groovy-mode loads
+;; (add-hook 'groovy-mode-hook
+;; '(lambda ()
+;; (require 'groovy-electric)
+;; (groovy-electric-mode)))
+;; or add this to your init file
+;; (require 'groovy-electric)
+;; note that you need to have font lock enabled beforehand.
+;; 2) toggle Groovy Electric Mode on/off with groovy-electric-mode.
+;;; History:
+;;; Code:
+(require 'groovy-mode)
+(defgroup groovy-electric nil
+ "Minor mode providing electric editing commands for groovy files"
+ :group 'groovy)
+(defvar groovy-electric-matching-delimeter-alist
+ '((?\[ . ?\])
+ (?\( . ?\))
+ (?\' . ?\')
+ (?\" . ?\")))
+(defcustom groovy-electric-expand-delimiters-list '(all)
+ "*List of contexts where matching delimiter should be inserted.
+The word 'all' will do all insertions."
+ :type '(set :extra-offset 8
+ (const :tag "Everything" all )
+ (const :tag "Curly brace" ?\{ )
+ (const :tag "Square brace" ?\[ )
+ (const :tag "Round brace" ?\( )
+ (const :tag "Quote" ?\' )
+ (const :tag "Double quote" ?\" )
+ (const :tag "Dollar in GStrings" ?\$ ))
+ :group 'groovy-electric)
+(defcustom groovy-electric-newline-before-closing-bracket nil
+ "*Controls whether a newline should be inserted before the
+closing bracket or not."
+ :type 'boolean :group 'groovy-electric)
+(define-minor-mode groovy-electric-mode
+ "Toggle Groovy Electric minor mode.
+With no argument, this command toggles the mode. Non-null prefix
+argument turns on the mode. Null prefix argument turns off the
+When Groovy Electric mode is enabled, simple, double and back
+quotes as well as braces are paired auto-magically. Expansion
+does not occur inside comments and strings. Note that you must
+have Font Lock enabled. ${ } is expanded when in a GString"
+ ;; initial value.
+ nil
+ ;;indicator for the mode line.
+ " Ge"
+ ;;keymap
+ groovy-mode-map
+ (groovy-electric-setup-keymap))
+(defun groovy-electric-setup-keymap()
+ (define-key groovy-mode-map "{" 'groovy-electric-curlies)
+ (define-key groovy-mode-map "(" 'groovy-electric-matching-char)
+ (define-key groovy-mode-map "[" 'groovy-electric-matching-char)
+ (define-key groovy-mode-map "\"" 'groovy-electric-matching-char)
+ (define-key groovy-mode-map "\'" 'groovy-electric-matching-char)
+ (define-key groovy-mode-map "\$" 'groovy-electric-pound)
+ )
+(defun groovy-electric-code-at-point-p()
+ (and groovy-electric-mode
+ (let* ((properties (text-properties-at (point))))
+ (and (null (memq 'font-lock-string-face properties))
+ (null (memq 'font-lock-comment-face properties))))))
+(defun groovy-electric-string-at-point-p()
+ (and groovy-electric-mode
+ (consp (memq 'font-lock-string-face (text-properties-at (point))))))
+;; This checks it is a GString ("...") not normal string '...'
+(defun groovy-electric-gstring-at-point-p()
+ (and groovy-electric-mode
+ (consp (memq 'font-lock-string-face (text-properties-at (point))))
+ (save-excursion
+ (char-equal ?\" (char-after (car (c-literal-limits)))))))
+(defun groovy-electric-is-last-command-char-expandable-punct-p()
+ (or (memq 'all groovy-electric-expand-delimiters-list)
+ (memq last-command-char groovy-electric-expand-delimiters-list)))
+(defun groovy-electric-curlies(arg)
+ (interactive "P")
+ (self-insert-command (prefix-numeric-value arg))
+ (when (and (groovy-electric-is-last-command-char-expandable-punct-p)
+ (groovy-electric-code-at-point-p))
+ (insert " ")
+ (save-excursion
+ (if groovy-electric-newline-before-closing-bracket
+ (newline))
+ (insert "}"))))
+(defun groovy-electric-matching-char(arg)
+ (interactive "P")
+ (self-insert-command (prefix-numeric-value arg))
+ (and (groovy-electric-is-last-command-char-expandable-punct-p)
+ (groovy-electric-code-at-point-p)
+ (save-excursion
+ (insert (cdr (assoc last-command-char
+ groovy-electric-matching-delimeter-alist))))))
+(defun groovy-electric-pound(arg)
+ (interactive "P")
+ (self-insert-command (prefix-numeric-value arg))
+ (when (and (groovy-electric-is-last-command-char-expandable-punct-p)
+ (groovy-electric-gstring-at-point-p)
+ (not (save-excursion ; make sure it is not escaped
+ (backward-char 1)
+ (char-equal ?\\ (preceding-char)))))
+ (insert "{}")
+ (backward-char 1)))
+(provide 'groovy-electric)
+;;; groovy-electric.el ends here
583 site-lisp/groovy-mode/groovy-mode.el
@@ -0,0 +1,583 @@
+;;; groovy-mode.el --- Groovy mode derived mode
+;; Author: Russel Winder <>
+;; Created: 2006-08-01
+;; Copyright (C) 2006,2009-10 Russel Winder
+;; This program 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 2 of the License, or
+;; (at your option) any later version.
+;; This program 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, write
+;; to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+;;; Authors:
+;; Russel Winder <>, 2006--
+;; Jim Morris <>, 2009--
+;;; Commentary:
+;; This mode was initially developed using the Java and Awk modes that are part of CC Mode (the 5.31 source
+;; was used) and C# Mode from Dylan R. E. Moonfire <> (the 0.5.0 source was used). This
+;; code may contain some code fragments from those sources that was cut-and-pasted then edited. All other
+;; code was newly entered by the author. Obviously changes have been made since then.
+;; NB This derived mode requires CC Mode 5.31 or later for the virtual semicolon code to work.
+;; There appears to be a problem in CC Mode 5.31 such that csharp-mode and groovy-mode crash XEmacs 21.4 if
+;; the files are byte compiled.
+;;; Bugs:
+;; Bug tracking is currently (2009-11-26) handled using the Groovy JIRA via the Emacs Mode component.
+;; cf.
+;;; Versions:
+;; 0.1.0 - will be the initial release when it is ready :-)
+;;; Notes:
+;; Need to think about the `*.', `?.', `.&' and `.@' operators. Also, `..' and `..<'. This probably means
+;; changing `c-after-id-concat-ops' but also `c-operators'.
+;; Need to deal with operator overloading (groovy has this but Java does not) so `c-overloadable-operators'
+;; needs investigating.
+;; Need to investigate how to support the triple string delimiters for multi-line strings.
+;; Should we support GString / template markup ( e.g. `<%' and `%>') specially?
+;; Need to think whether Groovy needs a different c-decl-prefix-re compared to Java. Certainly, Java will
+;; have to change to handle the generics.
+;; Probably need to change `c-block-prefix-disallowed-chars' as Groovy is not the same as Java.
+;; Probably need to change `c-type-decl-suffix-key' as Groovy is not the same as Java.
+;;; Changes:
+;; See the history in the Bazaar branch.
+;;; Code:
+(require 'cc-mode)
+;; CSharp mode comment says: These are only required at compile time to get the sources for the language
+;; constants. (The cc-fonts require and the font-lock related constants could additionally be put inside an
+;; (eval-after-load "font-lock" ...) but then some trickery is necessary to get them compiled.)
+ (let ((load-path
+ (if (and (boundp 'byte-compile-dest-file)
+ (stringp byte-compile-dest-file))
+ (cons (file-name-directory byte-compile-dest-file) load-path)
+ load-path)))
+ (load "cc-mode" nil t) ; C# mode has this
+ (load "cc-fonts" nil t) ; C# mode has this
+ (load "cc-langs" nil t) ; C# mode has this
+ (load "cc-bytecomp" nil t) ; Awk mode has this
+ (c-add-language 'groovy-mode 'java-mode))
+;; Groovy allows `?.' as well as `.' for creating identifiers.
+(c-lang-defconst c-identifier-ops
+ groovy '((left-assoc "." "?.")))
+;; Groovy allows operators such as `*.', `?.', `.&' and `.@'. Java mode puts `*' here to deal with
+;; import statement usage which we need for Groovy.
+(c-lang-defconst c-after-id-concat-ops
+ groovy '( "*" "&" "@" ))
+;;;; Should really do something with `c-string-escaped-newlines' and `c-multiline-string-start-char' to
+;;;; handle the triple delimeter multiline strings.
+;; Because of the above we have to redefine `c_operators' because no other language has `.&' and
+;; `.@' operators.
+(c-lang-defconst c-operators
+ "List describing all operators, along with their precedence and
+associativity. The order in the list corresponds to the precedence of
+the operators: The operators in each element is a group with the same
+precedence, and the group has higher precedence than the groups in all
+following elements. The car of each element describes the type of of
+the operator group, and the cdr is a list of the operator tokens in
+it. The operator group types are:
+'prefix Unary prefix operators.
+'postfix Unary postfix operators.
+ Unary postfix operators if and only if the chars have
+ parenthesis syntax.
+'left-assoc Binary left associative operators (i.e. a+b+c means (a+b)+c).
+'right-assoc Binary right associative operators (i.e. a=b=c means a=(b=c)).
+ Right associative operator that constitutes of a
+ sequence of tokens that separate expressions. All the
+ tokens in the group are in this case taken as
+ describing the sequence in one such operator, and the
+ order between them is therefore significant.
+Operators containing a character with paren syntax are taken to match
+with a corresponding open/close paren somewhere else. A postfix
+operator with close paren syntax is taken to end a postfix expression
+started somewhere earlier, rather than start a new one at point. Vice
+versa for prefix operators with open paren syntax.
+Note that operators like \".\" and \"->\" which in language references
+often are described as postfix operators are considered binary here,
+since CC Mode treats every identifier as an expression."
+ groovy `(
+ ;; Primary.
+ ,@(c-lang-const c-identifier-ops)
+ (postfix-if-paren "<" ">") ; Templates.
+ (prefix "super")
+ ;; Postfix.
+ (left-assoc "." "*." "?." ".&" ".@")
+ (postfix "++" "--" "[" "]" "(" ")" "<:" ":>")
+ ;; Unary.
+ (prefix "++" "--" "+" "-" "!" "~" "new" "(" ")")
+ ;; Multiplicative.
+ (left-assoc "*" "/" "%")
+ ;; Additive.
+ (left-assoc "+" "-")
+ ;; Shift.
+ (left-assoc "<<" ">>" ">>>")
+ ;; Relational.
+ (left-assoc "<" ">" "<=" ">=" "instanceof" "<=>")
+ ;; Matching.
+ (left-assoc "=~" "==~" )
+ ;; Equality.
+ (left-assoc "==" "!=" )
+ ;; Bitwise and.
+ (left-assoc "&")
+ ;; Bitwise exclusive or.
+ (left-assoc "^")
+ ;; Bitwise or.
+ (left-assoc "|")
+ ;; Logical and.
+ (left-assoc "&&")
+ ;; Logical or.
+ (left-assoc "||")
+ ;; Conditional.
+ (right-assoc-sequence "?" ":")
+ ;; Assignment.
+ (right-assoc ,@(c-lang-const c-assignment-operators))
+ ;; Exception.
+ ;(prefix "throw") ; Java mode didn't have this but c++ mode does. Humm...
+ ;; Sequence.
+ (left-assoc ",")
+ ;; Separator for parameter list and code in a closure.
+ (left-assoc "->")
+ ))
+;; Groovy can overload operators where Java cannot.
+(c-lang-defconst c-overloadable-operators
+ groovy '("+" "-" "*" "/" "%"
+ "&" "|" "^" "~" "<<" ">>" ">>>"
+ "==" "!=" ">" "<" ">=" "<="
+ "<=>"
+ "=~" "==~"
+ "++" "--" "+=" "-=" "*=" "/=" "%="
+ "&=" "|=" "^=" "~=" "<<=" ">>=" ">>>="
+ "!" "&&" "||"))
+;; Groovy allows newline to terminate a statement unlike Java and like Awk. We draw on the Awk
+;; Mode `Virtual semicolon material. The idea is to say when an EOL is a `virtual semicolon,
+;; i.e. a statement terminator.
+(c-lang-defconst c-stmt-delim-chars
+ groovy "^;{}\n\r?:")
+(c-lang-defconst c-stmt-delim-chars-with-comma
+ groovy "^;,{}\n\r?:")
+;; Is there a virtual semicolon at POS or point?
+;; A virtual semicolon is considered to lie just after the last non-syntactic-whitespace
+;; character on a line where the EOL is the statement terminator. A real semicolon never
+;; counts as a virtual one.
+(defun groovy-at-vsemi-p ( &optional pos )
+ (save-excursion
+ (let ((pos-or-point (if pos (goto-char pos) (point))))
+ (if (eq pos-or-point (point-min))
+ nil
+ (and
+ (not (char-equal (char-before) ?\;))
+ (groovy-ws-or-comment-to-eol-p pos-or-point)
+ (groovy-not-in-statement-p pos-or-point)
+ (groovy-not-if-or-else-etc-p pos-or-point))))))
+(c-lang-defconst c-at-vsemi-p-fn
+ groovy 'groovy-at-vsemi-p)
+;; see if end of line or comment on rest of line
+(defun groovy-ws-or-comment-to-eol-p ( pos )
+ (save-excursion
+ (goto-char pos)
+ (skip-chars-forward " \t")
+ (or
+ (char-equal (char-after) ?\n)
+ (looking-at "/[/*].*"))))
+(defun groovy-not-in-statement-p ( pos )
+ (save-excursion
+ (goto-char pos)
+ (if (equal (point) (point-min))
+ nil
+ (backward-char 1)
+ (or
+ (not (looking-at "[=+*%<{:]"))
+ (if (char-equal (char-after) ?>)
+ (if (equal (point) (point-min))
+ nil
+ (char-equal (char-before) ?-)))))))
+;; check for case of if(stuff) and nothing else on line
+;; ie
+;; if(x > y)
+;; if(x < y) do somehting will not match
+;; else blah blah will not match either
+(defun groovy-not-if-or-else-etc-p ( pos )
+ (save-excursion
+ (goto-char pos)
+ (back-to-indentation)
+ (not
+ (or
+ (and (looking-at "if") ; make sure nothing else on line
+ (progn (forward-sexp 2)
+ (groovy-ws-or-comment-to-eol-p (point))))
+ (and (looking-at "}?else")
+ (progn (forward-char)
+ (forward-sexp 1)
+ (groovy-ws-or-comment-to-eol-p (point))))))))
+(defun groovy-vsemi-status-unknown-p () nil)
+(c-lang-defconst c-vsemi-status-unknown-p-fn
+ groovy 'c-groovy-vsemi-status-unknown-p)
+;; Java does not do this but perhaps it should?
+(c-lang-defconst c-type-modifier-kwds
+ groovy '("volatile" "transient"))
+(c-lang-defconst c-typeless-decl-kwds
+ groovy (append (c-lang-const c-class-decl-kwds)
+ (c-lang-const c-brace-list-decl-kwds)
+ '("def")))
+;;;; Should we be tinkering with `c-block-stmt-1-key' or `c-block-stmt-2-key' to deal with closures
+;;;; following what appears to be function calls or even field names?
+;; Groovy allows use of `<%' and `%>' in template expressions.
+;(c-lang-defconst c-other-op-syntax-tokens
+; groovy '( "<%" "%>" ))
+;; Groovy does not allow the full set of Java keywords in the moifier category and, of course, there is the
+;; `def' modifier which Groovy introduces to support dynamic typing. Should `const' be treated
+;; as reserved here as it is in Java?
+(c-lang-defconst c-modifier-kwds
+ groovy '( "abstract" "def" "final" "private" "protected" "public" "static" "synchronized" ))
+;; Java does not define these pseudo-kewords as keywords, why not?
+(c-lang-defconst c-constant-kwds
+ groovy '( "true" "false" "null" ))
+;; Why does Java mode not put `super' into the `c-primary-expr-kwds?
+(c-lang-defconst c-primary-expr-kwds
+ groovy '( "this" "super" ))
+;; Groovy does not allow anonymous classes as Java does.
+(c-lang-defconst c-inexpr-class-kwds
+ groovy nil)
+(c-lang-defconst c-inexpr-brace-list-kwds
+ groovy nil)
+;;;; Should we be changing `c-opt-inexpr-brace-list-key' to deal with closures after function calls and
+;;;; field expressions?
+;; We need to include the "as" for the cast and "in" for for.
+(c-lang-defconst c-other-kwds
+ groovy '( "in" "as" ))
+(defconst groovy-font-lock-keywords-1 (c-lang-const c-matchers-1 groovy)
+ "Minimal highlighting for Groovy mode.
+Fontifies nothing except the syntactic fontification of strings and
+(defconst groovy-font-lock-keywords-2 (c-lang-const c-matchers-2 groovy)
+ "Fast normal highlighting for Groovy mode.
+In addition to `java-font-lock-keywords-1', this adds fontification of
+keywords, simple types, declarations that are easy to recognize, the
+user defined types on `java-font-lock-extra-types', and the doc
+comment styles specified by `c-doc-comment-style'.")
+(defconst groovy-font-lock-keywords-3 (c-lang-const c-matchers-3 groovy)
+ "Accurate normal highlighting for Groovy mode.
+Like `java-font-lock-keywords-2' but detects declarations in a more
+accurate way that works in most cases for arbitrary types without the
+need for `java-font-lock-extra-types'.")
+(defvar groovy-font-lock-keywords groovy-font-lock-keywords-3
+ "Default expressions to highlight in Groovy mode.")
+(defun groovy-font-lock-keywords-2 ()
+ (c-compose-keywords-list groovy-font-lock-keywords-2))
+(defun groovy-font-lock-keywords-3 ()
+ (c-compose-keywords-list groovy-font-lock-keywords-3))
+(defun groovy-font-lock-keywords ()
+ (c-compose-keywords-list groovy-font-lock-keywords))
+(defvar groovy-mode-syntax-table nil
+ "Syntax table used in Groovy mode buffers.")
+(or groovy-mode-syntax-table
+ (setq groovy-mode-syntax-table
+ (funcall (c-lang-const c-make-mode-syntax-table groovy))))
+(defvar groovy-mode-abbrev-table nil
+ "Abbreviation table used in groovy-mode buffers.")
+(c-define-abbrev-table 'groovy-mode-abbrev-table
+ ;; Keywords that if they occur first on a line might alter the syntactic context, and which
+ ;; therefore should trigger reindentation when they are completed.
+ '(("else" "else" c-electric-continued-statement 0)
+ ("while" "while" c-electric-continued-statement 0)
+ ("catch" "catch" c-electric-continued-statement 0)
+ ("finally" "finally" c-electric-continued-statement 0)))
+;; Jim Morris proposed changing to the following definition of groovy-mode-map 2009-11-27, but this change
+;; has not made so as to continue to use the same code structure as still used in the Java mode.
+;(defvar groovy-mode-map (let ((map (c-make-inherited-keymap)))
+; ;; Add bindings which are only useful for Groovy
+; map)
+; "Keymap used in groovy-mode buffers.")
+(defvar groovy-mode-map ()
+ "Keymap used in groovy-mode buffers.")
+(if groovy-mode-map
+ nil
+ (setq groovy-mode-map (c-make-inherited-keymap))
+ ;; add bindings which are only useful for Groovy
+ )
+;(easy-menu-define c-groovy-menu groovy-mode-map "Groovy Mode Commands"
+; (cons "Groovy" (c-lang-const c-mode-menu groovy)))
+;;; Autoload mode trigger
+;(add-to-list 'auto-mode-alist '("\\.groovy" . groovy-mode))
+;; Custom variables
+(defcustom groovy-mode-hook nil
+ "*Hook called by `groovy-mode'."
+ :type 'hook
+ :group 'c)
+;;; The following are used to overide cc-mode indentation behavior to match groovy
+;; if we are in a closure that has an argument eg ends with -> (excluding comment) then
+;; change indent else lineup with previous one
+(defun groovy-mode-fix-closure-with-argument (langelem)
+ (save-excursion
+ (back-to-indentation)
+ (c-backward-syntactic-ws)
+ (backward-char 2)
+ (if (looking-at "->") ; if the line has a -> in it
+ (vector (+ (current-indentation) c-basic-offset)) ; then indent from base
+ 0)))
+;; A helper function from:
+;; Originally named js-lineup-arglist, renamed to groovy-lineup-arglist
+(defun groovy-lineup-arglist (langelem)
+ ;; the "DWIM" in c-mode doesn't Do What I Mean.
+ ;; see doc of c-lineup-arglist for why I redefined this
+ (save-excursion
+ (let ((indent-pos (point)))
+ ;; Normal case. Indent to the token after the arglist open paren.
+ (goto-char (c-langelem-2nd-pos c-syntactic-element))
+ (if (and c-special-brace-lists
+ (c-looking-at-special-brace-list))
+ ;; Skip a special brace list opener like "({".
+ (progn (c-forward-token-2)
+ (forward-char))
+ (forward-char))
+ (let ((arglist-content-start (point)))
+ (c-forward-syntactic-ws)
+ (when (< (point) indent-pos)
+ (goto-char arglist-content-start)
+ (skip-chars-forward " \t"))
+ (vector (current-column))))))
+(defun is-groovy-mode ()
+ "return t if we are in groovy mode else nil"
+ (eq major-mode 'groovy-mode))
+;; use defadvice to override the syntactic type if we have a
+;; statement-cont, see if previous line has a virtual semicolon and if
+;; so make it statement.
+(defadvice c-guess-basic-syntax (after c-guess-basic-syntax-groovy activate)
+ (when (is-groovy-mode)
+ (save-excursion
+ (let* ((ankpos (progn
+ (beginning-of-line)
+ (c-backward-syntactic-ws)
+ (beginning-of-line)
+ (c-forward-syntactic-ws)
+ (point))) ; position to previous non-blank line
+ (curelem (c-langelem-sym (car ad-return-value))))
+ (end-of-line)
+ (cond
+ ((eq 'statement-cont curelem)
+ (when (groovy-at-vsemi-p) ; if there is a virtual semi there then make it a statement
+ (setq ad-return-value `((statement ,ankpos)))))
+ ((eq 'topmost-intro-cont curelem)
+ (when (groovy-at-vsemi-p) ; if there is a virtual semi there then make it a top-most-intro
+ (setq ad-return-value `((topmost-intro ,ankpos)))))
+ )))))
+;; This disables bracelists, as most of the time in groovy they are closures
+;; We need to check we are currently in groovy mode
+(defadvice c-inside-bracelist-p (around groovy-c-inside-bracelist-p activate)
+ (if (not (is-groovy-mode))
+ ad-do-it
+ (setq ad-return-value nil)))
+;; based on java-function-regexp
+;; Complicated regexp to match method declarations in interfaces or classes
+;; A nasty test case is:
+;; else if(foo instanceof bar) {
+;; which will get mistaken for a function as Groovy does not require types on arguments
+;; so we need to check for empty parens or comma separated list, or type args
+(defvar groovy-function-regexp
+ (concat
+ "^[ \t]*" ; leading white space
+ "\\(public\\|private\\|protected\\|" ; some of these 8 keywords
+ "abstract\\|final\\|static\\|"
+ "synchronized\\|native|def"
+ "\\|[ \t\n\r]\\)*" ; or whitespace
+ "[a-zA-Z0-9_$]*" ; optional return type
+ "[ \t\n\r]*[[]?[]]?" ; (could be array)
+ "[ \t\n\r]+" ; whitespace
+ "\\([a-zA-Z0-9_$]+\\)" ; the name we want
+ "[ \t\n\r]*" ; optional whitespace
+ "(" ; open the param list
+ "[ \t]*" ; optional whitespace
+ "\\("
+ "[ \t\n\r]*\\|" ; empty parens or
+ "[a-zA-Z0-9_$]+\\|" ; single param or
+ ".+?,.+?\\|" ; multi comma separated params or
+ "[a-zA-Z0-9_$]+" ; a type
+ "[ \t\n\r]*[[]?[]]?" ; optional array
+ "[ \t\n\r]+[a-zA-Z0-9_$]+" ; and param
+ "\\)"
+ "[ \t\n\r]*" ; optional whitespace
+ ")" ; end the param list
+ "[ \t\n\r]*" ; whitespace
+; "\\(throws\\([, \t\n\r]\\|[a-zA-Z0-9_$]\\)+\\)?{"
+ "\\(throws[^{;]+\\)?" ; optional exceptions
+ "[;{]" ; ending ';' (interfaces) or '{'
+ ; TODO groovy interfaces don't need to end in ;
+ )
+ "Matches method names in groovy code, select match 2")
+(defvar groovy-class-regexp
+ "^[ \t\n\r]*\\(final\\|abstract\\|public\\|[ \t\n\r]\\)*class[ \t\n\r]+\\([a-zA-Z0-9_$]+\\)[^;{]*{"
+ "Matches class names in groovy code, select match 2")
+(defvar groovy-interface-regexp
+ "^[ \t\n\r]*\\(abstract\\|public\\|[ \t\n\r]\\)*interface[ \t\n\r]+\\([a-zA-Z0-9_$]+\\)[^;]*;"
+ "Matches interface names in groovy code, select match 2")
+(defvar groovy-imenu-regexp
+ (list (list nil groovy-function-regexp 2)
+ (list ".CLASSES." groovy-class-regexp 2)
+ (list ".INTERFACES." groovy-interface-regexp 2)
+ (list ".CLOSURES." "def[ \t]+\\([a-zA-Z_][a-zA-Z0-9_]*\\)[ \t]*=[ \t]*{" 1))
+ "Imenu expression for Groovy")
+;; Setup imenu to extract functions, classes, interfaces and closures assigned to variables
+(defvar cc-imenu-groovy-generic-expression
+ groovy-imenu-regexp
+ "Imenu generic expression for Groovy mode. See `imenu-generic-expression'.")
+;;; The entry point into the mode
+(defun groovy-mode ()
+ "Major mode for editing Groovy code.
+The hook `c-mode-common-hook' is run with no args at mode
+initialization, then `groovy-mode-hook'.
+Key bindings:
+ (interactive)
+ (kill-all-local-variables)
+ (c-initialize-cc-mode t)
+ (set-syntax-table groovy-mode-syntax-table)
+ (setq major-mode 'groovy-mode
+ mode-name "Groovy"
+ local-abbrev-table groovy-mode-abbrev-table
+ abbrev-mode t)
+ (use-local-map groovy-mode-map)
+ (c-init-language-vars groovy-mode)
+ (c-common-init 'groovy-mode)
+ ;;(easy-menu-add groovy-menu)
+ (cc-imenu-init cc-imenu-groovy-generic-expression)
+ (c-run-mode-hooks 'c-mode-common-hook 'groovy-mode-hook)
+ ;; quick fix for misalignment of statements with =
+ (setq c-label-minimum-indentation 0)
+ ;; fix for indentation after a closure param list
+ (c-set-offset 'statement 'groovy-mode-fix-closure-with-argument)
+ ;; get arglists (in groovy lists or maps) to align properly
+ (c-set-offset 'arglist-close '(c-lineup-close-paren))
+ (c-set-offset 'arglist-cont 0)
+ (c-set-offset 'arglist-cont-nonempty '(groovy-lineup-arglist))
+ (c-set-offset 'arglist-intro '+)
+ (c-update-modeline))
+(provide 'groovy-mode)
+;;; groovy-mode.el ends here
349 site-lisp/groovy-mode/inf-groovy.el
@@ -0,0 +1,349 @@
+;;; -*-Emacs-Lisp-*-
+;;; Stuart Clayman
+;;; 2006-08-01 v1
+;;; 2010-04-07 v2 fixes for new groovy-mode
+;;; Inferior Groovy Mode - groovy process in a buffer.
+;;; adapted from cmuscheme.el and inf-haskell.el
+;;; Usage:
+;;; (1) modify .emacs to use groovy-mode
+;;; for example :
+;;; (autoload 'groovy-mode "groovy-mode"
+;;; "Mode for editing groovy source files" t)
+;;; (setq auto-mode-alist
+;;; (append '(("\\.groovy$" . groovy-mode)) auto-mode-alist))
+;;; (setq interpreter-mode-alist (append '(("groovy" . groovy-mode))
+;;; interpreter-mode-alist))
+;;; (2) set to load inf-groovy and set inf-groovy key definition in groovy-mode.
+;;; (autoload 'groovy-mode "groovy-mode" "Groovy mode." t)
+;;; (autoload 'run-groovy "inf-groovy" "Run an inferior Groovy process")
+;;; (autoload 'inf-groovy-keys "inf-groovy" "Set local key defs for inf-groovy in groovy-mode")
+;;; (add-hook 'groovy-mode-hook
+;;; '(lambda ()
+;;; (inf-groovy-keys)
+;;; ))
+;;; ;; can set groovy-home here, if not in environment
+;;; (setq inferior-groovy-mode-hook
+;;; '(lambda()
+;;; (setq groovy-home "/Users/sclayman/Downloads/groovy-1.7.1/")
+;;; ))
+;;; (3) execute
+;;; M-x run-groovy
+(require 'comint)
+(require 'compile)
+(require 'groovy-mode)
+;;;; for groovy
+(defvar groovy-home (getenv "GROOVY_HOME"))
+(defvar groovy-program-name "groovysh --color=false"
+ "*Program invoked by the run-groovy command")
+(defvar inferior-groovy-first-prompt-pattern "^groovy:.*> *"
+ "first prompt regex pattern of groovy interpreter.")
+(defvar inferior-groovy-prompt-pattern "^groovy:.*> *"
+ "prompt regex pattern of groovy interpreter.")
+;; mode variables
+(defvar inferior-groovy-mode-hook nil
+ "*Hook for customising inferior-groovy mode.")
+(defvar inferior-groovy-mode-map nil
+ "*Mode map for inferior-groovy-mode")
+(defconst inferior-groovy-error-regexp-alist
+ '(("SyntaxError: compile error\n^\\([^\(].*\\):\\([1-9][0-9]*\\):" 1 2)
+ ("^\tfrom \\([^\(].*\\):\\([1-9][0-9]*\\)\\(:in `.*'\\)?$" 1 2)))
+(cond ((not inferior-groovy-mode-map)
+ (setq inferior-groovy-mode-map
+ (copy-keymap comint-mode-map))
+; (define-key inferior-groovy-mode-map "\M-\C-x" ;gnu convention
+; 'groovy-send-definition)
+; (define-key inferior-groovy-mode-map "\C-x\C-e" 'groovy-send-last-sexp)
+ (define-key inferior-groovy-mode-map "\C-c\C-l" 'groovy-load-file)
+ (define-key inferior-groovy-mode-map "\C-c\C-m" 'inferior-groovy-newline-and-go)
+(defun inf-groovy-keys ()
+ "Set local key defs for inf-groovy in groovy-mode"
+ (define-key groovy-mode-map "\M-\C-x" 'groovy-send-definition)
+ (define-key groovy-mode-map "\C-x\C-e" 'groovy-send-last-sexp)
+ ;;(define-key groovy-mode-map "\C-c\M-b" 'groovy-send-block)
+ ;;(define-key groovy-mode-map "\C-c\C-b" 'groovy-send-block-and-go)
+ (define-key groovy-mode-map "\C-c\M-d" 'groovy-send-definition)
+ (define-key groovy-mode-map "\C-c\C-x" 'groovy-send-definition-and-go)
+ (define-key groovy-mode-map "\C-c\C-x" 'groovy-send-definition-and-go)
+ (define-key groovy-mode-map "\C-c\M-r" 'groovy-send-region)
+ (define-key groovy-mode-map "\C-c\C-r" 'groovy-send-region-and-go)
+ (define-key groovy-mode-map "\C-c\C-z" 'switch-to-groovy)
+ (define-key groovy-mode-map "\C-c\C-l" 'groovy-load-file)
+ (define-key groovy-mode-map "\C-c\C-s" 'run-groovy)
+(defvar groovy-buffer nil "current groovy (actually groovysh) process buffer.")
+(defun inferior-groovy-mode ()
+ "Major mode for interacting with an inferior groovy (groovysh) process.
+The following commands are available:
+A groovy process can be fired up with M-x run-groovy.
+Customisation: Entry to this mode runs the hooks on comint-mode-hook and
+inferior-groovy-mode-hook (in that order).
+You can send text to the inferior groovy process from other buffers containing
+Groovy source.
+ switch-to-groovy switches the current buffer to the groovy process buffer.
+ groovy-send-definition sends the current definition to the groovy process.
+ groovy-send-region sends the current region to the groovy process.
+ groovy-send-definition-and-go, groovy-send-region-and-go,
+ switch to the groovy process buffer after sending their text.
+For information on running multiple processes in multiple buffers, see
+documentation for variable groovy-buffer.
+Return after the end of the process' output sends the text from the
+ end of process to point.
+Return before the end of the process' output copies the sexp ending at point
+ to the end of the process' output, and sends it.
+Delete converts tabs to spaces as it moves back.
+Tab indents for groovy; with argument, shifts rest
+ of expression rigidly with the current line.
+C-M-q does Tab on each line starting within following expression.
+Paragraphs are separated only by blank lines. # start comments.
+If you accidentally suspend your process, use \\[comint-continue-subjob]
+to continue it."
+ (interactive)
+ (comint-mode)
+ ;; Customise in inferior-groovy-mode-hook
+ (setq comint-prompt-regexp inferior-groovy-prompt-pattern)
+ ;; (groovy-mode-variables)
+ (setq major-mode 'inferior-groovy-mode)
+ (setq mode-name "Inferior Groovy")
+ (setq mode-line-process '(":%s"))
+ (use-local-map inferior-groovy-mode-map)
+ (define-key inferior-groovy-mode-map "\C-c\C-m" 'inferior-groovy-newline-and-go)
+ (setq comint-input-filter (function groovy-input-filter))
+ (setq comint-get-old-input (function groovy-get-old-input))
+ (setq comint-use-prompt-regexp t) ;; added v2
+ (setq comint-process-echoes t) ;; added v2
+ (setq comint-eol-on-send t) ;; added v2
+ (compilation-shell-minor-mode t)
+ (make-local-variable 'compilation-error-regexp-alist)
+ (setq compilation-error-regexp-alist inferior-groovy-error-regexp-alist)
+ (run-hooks 'inferior-groovy-mode-hook))
+(defvar inferior-groovy-filter-regexp "\\`\\s *\\S ?\\S ?\\s *\\'"
+ "*Input matching this regexp are not saved on the history list.
+Defaults to a regexp ignoring all inputs of 0, 1, or 2 letters.")
+(defun inferior-groovy-newline-and-go()
+ (interactive)
+ (comint-send-input)
+ (let ((proc (groovy-proc)))
+ (comint-send-string proc "go\n")))
+(defun groovy-input-filter (str)
+ "Don't save anything matching inferior-groovy-filter-regexp"
+ (not (string-match inferior-groovy-filter-regexp str)))
+;; adapted from replace-in-string in XEmacs (subr.el)
+(defun remove-in-string (str regexp)
+ "Remove all matches in STR for REGEXP and returns the new string."
+ (let ((rtn-str "") (start 0) match prev-start)
+ (while (setq match (string-match regexp str start))
+ (setq prev-start start
+ start (match-end 0)
+ rtn-str (concat rtn-str (substring str prev-start match))))
+ (concat rtn-str (substring str start))))
+(defun groovy-get-old-input ()
+ "Snarf the sexp ending at point"
+ (save-excursion
+ (let ((end (point)))
+ (re-search-backward inferior-groovy-first-prompt-pattern)
+ (remove-in-string (buffer-substring (point) end)
+ inferior-groovy-prompt-pattern)
+ )))
+(defun groovy-args-to-list (string)
+ (let ((where (string-match "[ \t]" string)))
+ (cond ((null where) (list string))
+ ((not (= where 0))
+ (cons (substring string 0 where)
+ (groovy-args-to-list (substring string (+ 1 where)
+ (length string)))))
+ (t (let ((pos (string-match "[^ \t]" string)))
+ (if (null pos)
+ nil
+ (groovy-args-to-list (substring string pos
+ (length string)))))))))
+(defun run-groovy (cmd)
+ "Run an inferior Groovy process, input and output via buffer *groovy*.
+If there is a process already running in `*groovy*', switch to that buffer.
+With argument, allows you to edit the command line (default is value
+of `groovy-program-name'). Runs the hooks `inferior-groovy-mode-hook'
+\(after the `comint-mode-hook' is run).
+\(Type \\[describe-mode] in the process buffer for a list of commands.)"
+ (interactive (list (if current-prefix-arg
+ (read-string "Run Groovy: " groovy-program-name)
+ (concat groovy-home "/bin/" groovy-program-name))))
+ (if (not (comint-check-proc "*groovy*"))
+ (let ((cmdlist (groovy-args-to-list cmd)))
+ (set-buffer (apply 'make-comint "groovy" (car cmdlist)
+ nil (cdr cmdlist)))
+ (inferior-groovy-mode)))
+ ;(setq groovy-program-name cmd)
+ (setq groovy-buffer "*groovy*")
+ (pop-to-buffer "*groovy*")
+ (get-buffer-process groovy-buffer)
+ )
+(defun groovy-proc ()
+ "Returns the current groovy process. See variable groovy-buffer."
+ (let ((proc (get-buffer-process (if (eq major-mode 'inferior-groovy-mode)
+ (current-buffer)
+ groovy-buffer))))
+ (or proc
+ (call-interactively 'run-groovy))))
+ ;;; was (error "No current process. See variable groovy-buffer"))))
+(defun groovy-send-region (start end)
+ "Send the current region to the inferior Groovy process."
+ (interactive "r")
+ (save-excursion
+ (save-restriction
+ (let (( str (concat (buffer-substring start end) "\n"))
+ (proc (groovy-proc)))
+ (with-current-buffer (process-buffer proc)
+ (while (and
+ (goto-char comint-last-input-end)
+ (not (re-search-forward comint-prompt-regexp nil t))
+ (accept-process-output proc)))
+ (goto-char (process-mark proc))
+ (insert-before-markers str)
+ (move-marker comint-last-input-end (point))
+ (comint-send-string proc str)
+ (comint-send-string proc "go\n")
+ )
+ )
+ )))
+(defun groovy-send-definition ()
+ "Send the current definition to the inferior Groovy process."
+ (interactive)
+ (save-excursion
+ (c-end-of-defun)
+ (let ((end (point)))
+ (c-beginning-of-defun)
+ (groovy-send-region (point) end))))
+(defun groovy-send-last-sexp ()
+ "Send the previous sexp to the inferior Groovy process."
+ (interactive)
+ (groovy-send-region (save-excursion (backward-sexp) (point)) (point)))
+;; v2. current groovy-mode does not support beginning-of-block, end-of-block
+;; (defun groovy-send-block ()
+;; "Send the current block to the inferior Groovy process."
+;; (interactive)
+;; (save-excursion
+;; (groovy-end-of-block)
+;; (end-of-line)
+;; (let ((end (point)))
+;; (groovy-beginning-of-block)
+;; (groovy-send-region (point) end))))
+(defun switch-to-groovy (eob-p)
+ "Switch to the groovy process buffer.
+With argument, positions cursor at end of buffer."
+ (interactive "P")
+ (if (get-buffer groovy-buffer)
+ (pop-to-buffer groovy-buffer)
+ (error "No current process buffer. See variable groovy-buffer."))
+ (cond (eob-p
+ (push-mark)
+ (goto-char (point-max)))))
+(defun groovy-send-region-and-go (start end)
+ "Send the current region to the inferior Groovy process.
+Then switch to the process buffer."
+ (interactive "r")
+ (groovy-send-region start end)
+ (switch-to-groovy t))
+(defun groovy-send-definition-and-go ()
+ "Send the current definition to the inferior Groovy.
+Then switch to the process buffer."
+ (interactive)
+ (groovy-send-definition)
+ (switch-to-groovy t))
+;; (defun groovy-send-block-and-go ()
+;; "Send the current block to the inferior Groovy.
+;; Then switch to the process buffer."
+;; (interactive)
+;; (groovy-send-block)
+;; (switch-to-groovy t))
+(defvar groovy-source-modes '(groovy-mode)
+ "*Used to determine if a buffer contains Groovy source code.
+If it's loaded into a buffer that is in one of these major modes, it's
+considered a groovy source file by groovy-load-file.
+Used by these commands to determine defaults.")
+(defvar groovy-prev-l/c-dir/file nil
+ "Caches the last (directory . file) pair.
+Caches the last pair used in the last groovy-load-file command.
+Used for determining the default in the
+next one.")
+(defun groovy-load-file (file-name)
+ "Load a Groovy file into the inferior Groovy process."
+ (interactive (comint-get-source "Load Groovy file: " groovy-prev-l/c-dir/file
+ groovy-source-modes t)) ; T because LOAD
+ ; needs an exact name
+ (comint-check-source file-name) ; Check to see if buffer needs saved.
+ (setq groovy-prev-l/c-dir/file (cons (file-name-directory file-name)
+ (file-name-nondirectory file-name)))
+ (comint-send-string (groovy-proc) (concat "\\i "
+ file-name
+ "\n")))
+;;; Do the user's customisation...
+(defvar inf-groovy-load-hook nil
+ "This hook is run when inf-groovy is loaded in.
+This is a good place to put keybindings.")
+(run-hooks 'inf-groovy-load-hook)
+(provide 'inf-groovy)
+;;; inf-groovy.el ends here

0 comments on commit b9a88d5

Please sign in to comment.
Something went wrong with that request. Please try again.