Emacs config utilizing prelude as a base
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

253 lines
8.0 KiB

  1. ;;; ruby-block.el --- highlight matching block
  2. ;; Copyright (C) 2007-2009 khiker
  3. ;; Author: khiker <khiker.mail+elisp@gmail.com>
  4. ;; Keywords: languages, faces, ruby
  5. ;; This file is free software; you can redistribute it and/or modify
  6. ;; it under the terms of the GNU General Public License as published by
  7. ;; the Free Software Foundation; either version 2, or (at your option)
  8. ;; any later version.
  9. ;; This file is distributed in the hope that it will be useful,
  10. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. ;; GNU General Public License for more details.
  13. ;; You should have received a copy of the GNU General Public License
  14. ;; along with GNU Emacs; see the file COPYING. If not, write to
  15. ;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  16. ;; Boston, MA 02110-1301, USA.
  17. ;;; Commentary:
  18. ;;; Usage:
  19. ;; Add this line to your .emacs
  20. ;;
  21. ;; (require 'ruby-block)
  22. ;; (ruby-block-mode t)
  23. ;;
  24. ;; In addition, you can also add this line too.
  25. ;;
  26. ;; ;; do overlay
  27. ;; (setq ruby-block-highlight-toggle 'overlay)
  28. ;; ;; display to minibuffer
  29. ;; (setq ruby-block-highlight-toggle 'minibuffer)
  30. ;; ;; display to minibuffer and do overlay
  31. ;; (setq ruby-block-highlight-toggle t)
  32. ;;
  33. ;; Default is minibuffer.
  34. ;;
  35. ;; Tested on Emacs 22.3.2 and Emacs 23.0.95.2.
  36. ;;; Note:
  37. ;; A ruby-mode.el is necessary to use this package.
  38. ;;; Code:
  39. (require 'ruby-mode)
  40. ;; Variables:
  41. (defconst ruby-block-version "0.0.8"
  42. "Ruby block package version.")
  43. (defconst ruby-block-keyword-list
  44. (list "end" "for" "while" "until" "if" "class" "module"
  45. "case" "unless" "def" "begin" "do")
  46. "Keyword for highlighting.")
  47. (defconst ruby-block-keyword-regex
  48. "\\(end\\|for\\|while\\|until\\|if\\|class\\|module\\|case\\|unless\\|def\\|begin\\|do\\)"
  49. "Rregular expression to look for correspondence.")
  50. (defgroup ruby-block nil
  51. "Ruby block"
  52. :tag "Ruby block"
  53. :group 'ruby-block)
  54. (defcustom ruby-block-delay 0.50
  55. "*Time in seconds to delay before showing a matching paren."
  56. :type 'number
  57. :group 'ruby-block)
  58. (defcustom ruby-block-highlight-face 'highlight
  59. "*Face for block highlighting."
  60. :type 'face
  61. :group 'ruby-block)
  62. (defcustom ruby-block-highlight-toggle 'minibuffer
  63. "*How do you display corresponding line.
  64. Default is minibuffer. display to minibuffer.
  65. The possible choice is as follows.
  66. nil => nothing
  67. minibuffer => minibuffer
  68. overlay => overlay
  69. t => minibuffer and overlay"
  70. :type '(choice (const :tag "nothing" nil)
  71. (const :tag "minibuffer" minibuffer)
  72. (const :tag "overlay" overlay)
  73. (const :tag "minibuffer and overlay" t))
  74. :group 'ruby-block)
  75. (defvar ruby-block-timer nil)
  76. (defvar ruby-block-highlight-overlay nil)
  77. ;; Functions:
  78. (define-minor-mode ruby-block-mode
  79. "In ruby-mode, Displays the line where there is keyword corresponding
  80. to END keyword. this is Minor mode for ruby-mode only."
  81. :init-value t
  82. :global nil
  83. :keymap nil
  84. :lighter " RBlock"
  85. (if ruby-block-mode
  86. (ruby-block-start-timer)
  87. (ruby-block-stop-timer)))
  88. (defun ruby-block-start-timer ()
  89. "start timer."
  90. (when ruby-block-timer
  91. (cancel-timer ruby-block-timer))
  92. (setq ruby-block-timer
  93. (run-with-idle-timer ruby-block-delay t 'ruby-block-hook)))
  94. (defun ruby-block-stop-timer ()
  95. "stop timer."
  96. (when ruby-block-timer
  97. (cancel-timer ruby-block-timer)
  98. (setq ruby-block-timer nil)))
  99. (defun ruby-block-hook ()
  100. "When Major-mode is ruby-mode, this package is running."
  101. (if (eq major-mode 'ruby-mode)
  102. (condition-case err
  103. (ruby-block-function)
  104. (error
  105. (setq ruby-block-mode nil)
  106. (message "Error: %S; ruby-block-mode now disabled." err)))
  107. (setq ruby-block-mode nil)))
  108. (defun ruby-block-get-line-start-pos ()
  109. (save-excursion
  110. (let ((xor '(lambda (a b) (and (or a b) (not (and a b)))))
  111. (point (point))
  112. (count 0))
  113. (while (and (not (funcall xor (bobp) (eolp)))
  114. (> point (point-min)))
  115. (setq point (1- point))
  116. (goto-char (1- (point))))
  117. ;; delete linefeed of start point.
  118. (when (and (eolp) (>= (point-max) (1+ point)))
  119. (setq point (1+ point)))
  120. point)))
  121. (defun ruby-block-get-line-end-pos ()
  122. (save-excursion
  123. (let ((xor '(lambda (a b) (and (or a b) (not (and a b)))))
  124. (point (point)))
  125. (while (and (not (funcall xor (eobp) (eolp)))
  126. (>= (point-max) point))
  127. (setq point (1+ point))
  128. (goto-char (1+ (point))))
  129. point)))
  130. (defun ruby-block-function ()
  131. "Point position's word decides behavior."
  132. (let ((current (current-word)))
  133. (setq current (car (member current ruby-block-keyword-list)))
  134. (cond
  135. ;; not keyword
  136. ((null current)
  137. nil)
  138. ;; keyword "end"
  139. ((and (string= "end" current)
  140. (eq 'font-lock-keyword-face (get-text-property (point) 'face)))
  141. (let ((point (ruby-block-get-corresponding-point))
  142. (slinep 0)(elinep 0))
  143. ;; get whole line(exists point). and, display minibuffer.
  144. (when (> point 0)
  145. (save-excursion
  146. (goto-char point)
  147. (setq slinep (ruby-block-get-line-start-pos)
  148. elinep (ruby-block-get-line-end-pos)))
  149. ;; display line contents to minibuffer
  150. (when (or (eq ruby-block-highlight-toggle t)
  151. (eq ruby-block-highlight-toggle 'minibuffer))
  152. (message "%d: %s" (1+ (count-lines (point-min) slinep))
  153. (buffer-substring slinep elinep)))
  154. ;; do overlay.
  155. (when (or (eq ruby-block-highlight-toggle t)
  156. (eq ruby-block-highlight-toggle 'overlay))
  157. (ruby-block-do-highlight slinep elinep)))))
  158. ;; keyword except "end"
  159. (t
  160. nil))))
  161. (defun ruby-block-get-corresponding-point ()
  162. "Get point of corresponding line."
  163. (let ((orig-col (- (point) (ruby-block-get-line-start-pos)))
  164. (recent-col (- (point) (ruby-block-get-line-start-pos)))
  165. (count 1)(check t)(point 0)(face "")(string ""))
  166. (save-excursion
  167. (while check
  168. (if (re-search-backward ruby-block-keyword-regex (point-min) t 1)
  169. (setq point (match-beginning 1)
  170. face (get-text-property point 'face)
  171. string (current-word))
  172. (setq point -1 face "" string "" check nil))
  173. (when (and (eq face 'font-lock-keyword-face)
  174. (not (string= string "elsif"))
  175. (member string ruby-block-keyword-list)
  176. ;; case: STMT if(or unless, while, untill) EXPR
  177. (if (member string '("if" "unless" "while" "until"))
  178. (let ((col (- point (ruby-block-get-line-start-pos))))
  179. (if (or (> (+ orig-col 3) col)
  180. (> (+ recent-col 3) col))
  181. t nil))
  182. t))
  183. (if (and (string= string "end") check)
  184. (setq count (1+ count)
  185. recent-col (- (point) (ruby-block-get-line-start-pos)))
  186. (setq count (1- count))))
  187. (when (= count 0)
  188. (setq check nil)))
  189. point)))
  190. (defun ruby-block-do-highlight (beg end)
  191. "Do overlay corresponding line."
  192. (if ruby-block-highlight-overlay
  193. (move-overlay ruby-block-highlight-overlay beg end)
  194. (setq ruby-block-highlight-overlay (make-overlay beg end)))
  195. (overlay-put ruby-block-highlight-overlay
  196. 'face ruby-block-highlight-face)
  197. (add-hook 'pre-command-hook 'ruby-block-highlight-done))
  198. (defun ruby-block-highlight-done ()
  199. "After do overlay, restore the line to original color."
  200. (remove-hook 'pre-command-hook 'ruby-block-highlight-done)
  201. (if ruby-block-highlight-overlay
  202. (delete-overlay ruby-block-highlight-overlay)))
  203. (defun ruby-block-highlight-toggle ()
  204. "Switch on/off for ruby-block-mode."
  205. (interactive)
  206. (if ruby-block-highlight-toggle
  207. (setq ruby-block-highlight-toggle nil)
  208. (setq ruby-block-highlight-toggle t)))
  209. (provide 'ruby-block)
  210. ;; Local Variables:
  211. ;; Coding: iso-2022-7bit
  212. ;; End:
  213. ;;; ruby-block.el ends here