3 changed files with 394 additions and 3 deletions
@ -0,0 +1,253 @@ |
|||
;;; ruby-block.el --- highlight matching block |
|||
|
|||
;; Copyright (C) 2007-2009 khiker |
|||
|
|||
;; Author: khiker <khiker.mail+elisp@gmail.com> |
|||
;; Keywords: languages, faces, ruby |
|||
|
|||
;; 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 2, 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 GNU Emacs; see the file COPYING. If not, write to |
|||
;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
|||
;; Boston, MA 02110-1301, USA. |
|||
|
|||
;;; Commentary: |
|||
|
|||
;;; Usage: |
|||
|
|||
;; Add this line to your .emacs |
|||
;; |
|||
;; (require 'ruby-block) |
|||
;; (ruby-block-mode t) |
|||
;; |
|||
;; In addition, you can also add this line too. |
|||
;; |
|||
;; ;; do overlay |
|||
;; (setq ruby-block-highlight-toggle 'overlay) |
|||
;; ;; display to minibuffer |
|||
;; (setq ruby-block-highlight-toggle 'minibuffer) |
|||
;; ;; display to minibuffer and do overlay |
|||
;; (setq ruby-block-highlight-toggle t) |
|||
;; |
|||
;; Default is minibuffer. |
|||
;; |
|||
;; Tested on Emacs 22.3.2 and Emacs 23.0.95.2. |
|||
|
|||
;;; Note: |
|||
|
|||
;; A ruby-mode.el is necessary to use this package. |
|||
|
|||
;;; Code: |
|||
|
|||
(require 'ruby-mode) |
|||
|
|||
;; Variables: |
|||
|
|||
(defconst ruby-block-version "0.0.8" |
|||
"Ruby block package version.") |
|||
|
|||
(defconst ruby-block-keyword-list |
|||
(list "end" "for" "while" "until" "if" "class" "module" |
|||
"case" "unless" "def" "begin" "do") |
|||
"Keyword for highlighting.") |
|||
|
|||
(defconst ruby-block-keyword-regex |
|||
"\\(end\\|for\\|while\\|until\\|if\\|class\\|module\\|case\\|unless\\|def\\|begin\\|do\\)" |
|||
"Rregular expression to look for correspondence.") |
|||
|
|||
(defgroup ruby-block nil |
|||
"Ruby block" |
|||
:tag "Ruby block" |
|||
:group 'ruby-block) |
|||
|
|||
(defcustom ruby-block-delay 0.50 |
|||
"*Time in seconds to delay before showing a matching paren." |
|||
:type 'number |
|||
:group 'ruby-block) |
|||
|
|||
(defcustom ruby-block-highlight-face 'highlight |
|||
"*Face for block highlighting." |
|||
:type 'face |
|||
:group 'ruby-block) |
|||
|
|||
(defcustom ruby-block-highlight-toggle 'minibuffer |
|||
"*How do you display corresponding line. |
|||
Default is minibuffer. display to minibuffer. |
|||
|
|||
The possible choice is as follows. |
|||
|
|||
nil => nothing |
|||
minibuffer => minibuffer |
|||
overlay => overlay |
|||
t => minibuffer and overlay" |
|||
:type '(choice (const :tag "nothing" nil) |
|||
(const :tag "minibuffer" minibuffer) |
|||
(const :tag "overlay" overlay) |
|||
(const :tag "minibuffer and overlay" t)) |
|||
:group 'ruby-block) |
|||
|
|||
(defvar ruby-block-timer nil) |
|||
|
|||
(defvar ruby-block-highlight-overlay nil) |
|||
|
|||
|
|||
;; Functions: |
|||
|
|||
(define-minor-mode ruby-block-mode |
|||
"In ruby-mode, Displays the line where there is keyword corresponding |
|||
to END keyword. this is Minor mode for ruby-mode only." |
|||
:init-value t |
|||
:global nil |
|||
:keymap nil |
|||
:lighter " RBlock" |
|||
(if ruby-block-mode |
|||
(ruby-block-start-timer) |
|||
(ruby-block-stop-timer))) |
|||
|
|||
(defun ruby-block-start-timer () |
|||
"start timer." |
|||
(when ruby-block-timer |
|||
(cancel-timer ruby-block-timer)) |
|||
(setq ruby-block-timer |
|||
(run-with-idle-timer ruby-block-delay t 'ruby-block-hook))) |
|||
|
|||
(defun ruby-block-stop-timer () |
|||
"stop timer." |
|||
(when ruby-block-timer |
|||
(cancel-timer ruby-block-timer) |
|||
(setq ruby-block-timer nil))) |
|||
|
|||
(defun ruby-block-hook () |
|||
"When Major-mode is ruby-mode, this package is running." |
|||
(if (eq major-mode 'ruby-mode) |
|||
(condition-case err |
|||
(ruby-block-function) |
|||
(error |
|||
(setq ruby-block-mode nil) |
|||
(message "Error: %S; ruby-block-mode now disabled." err))) |
|||
(setq ruby-block-mode nil))) |
|||
|
|||
(defun ruby-block-get-line-start-pos () |
|||
(save-excursion |
|||
(let ((xor '(lambda (a b) (and (or a b) (not (and a b))))) |
|||
(point (point)) |
|||
(count 0)) |
|||
(while (and (not (funcall xor (bobp) (eolp))) |
|||
(> point (point-min))) |
|||
(setq point (1- point)) |
|||
(goto-char (1- (point)))) |
|||
;; delete linefeed of start point. |
|||
(when (and (eolp) (>= (point-max) (1+ point))) |
|||
(setq point (1+ point))) |
|||
point))) |
|||
|
|||
(defun ruby-block-get-line-end-pos () |
|||
(save-excursion |
|||
(let ((xor '(lambda (a b) (and (or a b) (not (and a b))))) |
|||
(point (point))) |
|||
(while (and (not (funcall xor (eobp) (eolp))) |
|||
(>= (point-max) point)) |
|||
(setq point (1+ point)) |
|||
(goto-char (1+ (point)))) |
|||
point))) |
|||
|
|||
(defun ruby-block-function () |
|||
"Point position's word decides behavior." |
|||
(let ((current (current-word))) |
|||
(setq current (car (member current ruby-block-keyword-list))) |
|||
(cond |
|||
;; not keyword |
|||
((null current) |
|||
nil) |
|||
;; keyword "end" |
|||
((and (string= "end" current) |
|||
(eq 'font-lock-keyword-face (get-text-property (point) 'face))) |
|||
(let ((point (ruby-block-get-corresponding-point)) |
|||
(slinep 0)(elinep 0)) |
|||
;; get whole line(exists point). and, display minibuffer. |
|||
(when (> point 0) |
|||
(save-excursion |
|||
(goto-char point) |
|||
(setq slinep (ruby-block-get-line-start-pos) |
|||
elinep (ruby-block-get-line-end-pos))) |
|||
;; display line contents to minibuffer |
|||
(when (or (eq ruby-block-highlight-toggle t) |
|||
(eq ruby-block-highlight-toggle 'minibuffer)) |
|||
(message "%d: %s" (1+ (count-lines (point-min) slinep)) |
|||
(buffer-substring slinep elinep))) |
|||
;; do overlay. |
|||
(when (or (eq ruby-block-highlight-toggle t) |
|||
(eq ruby-block-highlight-toggle 'overlay)) |
|||
(ruby-block-do-highlight slinep elinep))))) |
|||
;; keyword except "end" |
|||
(t |
|||
nil)))) |
|||
|
|||
(defun ruby-block-get-corresponding-point () |
|||
"Get point of corresponding line." |
|||
(let ((orig-col (- (point) (ruby-block-get-line-start-pos))) |
|||
(recent-col (- (point) (ruby-block-get-line-start-pos))) |
|||
(count 1)(check t)(point 0)(face "")(string "")) |
|||
(save-excursion |
|||
(while check |
|||
(if (re-search-backward ruby-block-keyword-regex (point-min) t 1) |
|||
(setq point (match-beginning 1) |
|||
face (get-text-property point 'face) |
|||
string (current-word)) |
|||
(setq point -1 face "" string "" check nil)) |
|||
(when (and (eq face 'font-lock-keyword-face) |
|||
(not (string= string "elsif")) |
|||
(member string ruby-block-keyword-list) |
|||
;; case: STMT if(or unless, while, untill) EXPR |
|||
(if (member string '("if" "unless" "while" "until")) |
|||
(let ((col (- point (ruby-block-get-line-start-pos)))) |
|||
(if (or (> (+ orig-col 3) col) |
|||
(> (+ recent-col 3) col)) |
|||
t nil)) |
|||
t)) |
|||
(if (and (string= string "end") check) |
|||
(setq count (1+ count) |
|||
recent-col (- (point) (ruby-block-get-line-start-pos))) |
|||
(setq count (1- count)))) |
|||
(when (= count 0) |
|||
(setq check nil))) |
|||
point))) |
|||
|
|||
(defun ruby-block-do-highlight (beg end) |
|||
"Do overlay corresponding line." |
|||
(if ruby-block-highlight-overlay |
|||
(move-overlay ruby-block-highlight-overlay beg end) |
|||
(setq ruby-block-highlight-overlay (make-overlay beg end))) |
|||
(overlay-put ruby-block-highlight-overlay |
|||
'face ruby-block-highlight-face) |
|||
(add-hook 'pre-command-hook 'ruby-block-highlight-done)) |
|||
|
|||
(defun ruby-block-highlight-done () |
|||
"After do overlay, restore the line to original color." |
|||
(remove-hook 'pre-command-hook 'ruby-block-highlight-done) |
|||
(if ruby-block-highlight-overlay |
|||
(delete-overlay ruby-block-highlight-overlay))) |
|||
|
|||
(defun ruby-block-highlight-toggle () |
|||
"Switch on/off for ruby-block-mode." |
|||
(interactive) |
|||
(if ruby-block-highlight-toggle |
|||
(setq ruby-block-highlight-toggle nil) |
|||
(setq ruby-block-highlight-toggle t))) |
|||
|
|||
(provide 'ruby-block) |
|||
|
|||
;; Local Variables: |
|||
;; Coding: iso-2022-7bit |
|||
;; End: |
|||
|
|||
;;; ruby-block.el ends here |
|||
@ -0,0 +1,138 @@ |
|||
;;; ruby-end.el --- Automatic insertion of end blocks for Ruby |
|||
|
|||
;; Copyright (C) 2010 Johan Andersson |
|||
|
|||
;; Author: Johan Andersson <johan.rejeep@gmail.com> |
|||
;; Maintainer: Johan Andersson <johan.rejeep@gmail.com> |
|||
;; Version: 0.1.0 |
|||
;; Keywords: speed, convenience |
|||
;; URL: http://github.com/rejeep/ruby-end |
|||
|
|||
;; This file is NOT part of GNU Emacs. |
|||
|
|||
|
|||
;;; License: |
|||
|
|||
;; 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 3, 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 GNU Emacs; see the file COPYING. If not, write to the |
|||
;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
|||
;; Boston, MA 02110-1301, USA. |
|||
|
|||
|
|||
;;; Commentary: |
|||
|
|||
;; ruby-end is a minor mode for Emacs that can be used with ruby-mode |
|||
;; to automatically close blocks by inserting "end" when typing a |
|||
;; block-keyword, followed by a space. |
|||
;; |
|||
;; To use ruby-end-mode, make sure that this file is in Emacs load-path: |
|||
;; (add-to-list 'load-path "/path/to/directory/or/file") |
|||
;; |
|||
;; Then require ruby-end: |
|||
;; (require 'ruby-end) |
|||
;; |
|||
;; ruby-end-mode is automatically started in ruby-mode. |
|||
|
|||
|
|||
;;; Code: |
|||
|
|||
(defvar ruby-end-expand-key "SPC" |
|||
"Space key name.") |
|||
|
|||
(defvar ruby-end-mode-map |
|||
(let ((map (make-sparse-keymap)) |
|||
(key (read-kbd-macro ruby-end-expand-key))) |
|||
(define-key map key 'ruby-end-space) |
|||
map) |
|||
"Keymap for `ruby-end-mode'.") |
|||
|
|||
(defcustom ruby-end-check-statement-modifiers t |
|||
"*Disable or enable expansion (insertion of end) for statement modifiers" |
|||
:type 'boolean |
|||
:group 'ruby) |
|||
|
|||
(defconst ruby-end-expand-postfix-modifiers-before-re |
|||
"\\(?:if\\|unless\\|while\\)" |
|||
"Regular expression matching statements before point.") |
|||
|
|||
(defconst ruby-end-expand-prefix-check-modifiers-re |
|||
"^\\s-*" |
|||
"Prefix for regular expression to prevent expansion with statement modifiers") |
|||
|
|||
(defconst ruby-end-expand-prefix-re |
|||
"\\(?:^\\|\\s-+\\)" |
|||
"Prefix for regular expression") |
|||
|
|||
(defconst ruby-end-expand-keywords-before-re |
|||
"\\(?:^\\|\\s-+\\)\\(?:do\\|def\\|class\\|module\\|case\\|for\\|begin\\)" |
|||
"Regular expression matching blocks before point.") |
|||
|
|||
|
|||
(defconst ruby-end-expand-after-re |
|||
"\\s-*$" |
|||
"Regular expression matching after point.") |
|||
|
|||
(defun ruby-end-space () |
|||
"Called when SPC-key is pressed." |
|||
(interactive) |
|||
(cond |
|||
((ruby-end-expand-p) |
|||
(ruby-end-insert-end) |
|||
(insert " ")) |
|||
(t |
|||
(let ((ruby-end-mode nil)) |
|||
(call-interactively |
|||
(key-binding |
|||
(read-kbd-macro ruby-end-expand-key))))))) |
|||
|
|||
(defun ruby-end-insert-end () |
|||
"Closes block by inserting end." |
|||
(save-excursion |
|||
(newline) |
|||
(insert "end") |
|||
(indent-according-to-mode))) |
|||
|
|||
(defun ruby-end-expand-p () |
|||
"Checks if expansion (insertion of end) should be done." |
|||
(let ((ruby-end-expand-statement-modifiers-before-re |
|||
(concat |
|||
(if ruby-end-check-statement-modifiers |
|||
ruby-end-expand-prefix-check-modifiers-re |
|||
ruby-end-expand-prefix-re) |
|||
ruby-end-expand-postfix-modifiers-before-re))) |
|||
(and |
|||
(ruby-end-code-at-point-p) |
|||
(or |
|||
(looking-back ruby-end-expand-statement-modifiers-before-re) |
|||
(looking-back ruby-end-expand-keywords-before-re)) |
|||
(looking-at ruby-end-expand-after-re)))) |
|||
|
|||
(defun ruby-end-code-at-point-p () |
|||
"Checks if point is code, or comment or string." |
|||
(let ((properties (text-properties-at (point)))) |
|||
(and |
|||
(null (memq 'font-lock-string-face properties)) |
|||
(null (memq 'font-lock-comment-face properties))))) |
|||
|
|||
;;;###autoload |
|||
(define-minor-mode ruby-end-mode |
|||
"Automatic insertion of end blocks for Ruby." |
|||
:init-value nil |
|||
:lighter " end" |
|||
:keymap ruby-end-mode-map) |
|||
|
|||
(add-hook 'ruby-mode-hook 'ruby-end-mode) |
|||
|
|||
(provide 'ruby-end) |
|||
|
|||
;;; ruby-end.el ends here |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue