indent-hint.el 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. ;; -*- encoding: utf-8-unix; -*-
  2. ;; File-name: <indent-hint.el>
  3. ;; Create: <2012-09-10 12:04:07 ran9er>
  4. ;; Time-stamp: <2013-02-17 00:35:27 ran9er>
  5. ;; Mail: <2999am@gmail.com>
  6. ;; *init
  7. (setq ih-key 'ih
  8. ih-bg 'indent-hint-bg
  9. ih-overlay-pool nil
  10. ih-table nil
  11. )
  12. (defun ih-init(&optional l)
  13. (mapc
  14. (lambda(x) (or (local-variable-p x)
  15. (make-local-variable x)))
  16. '(ih-table ih-overlay-pool))
  17. (setq ih-table (make-hash-table :size 100 :test 'equal))
  18. (ih-bgo-init)
  19. (add-hook 'post-command-hook 'ih-bgo-mv t t)
  20. (font-lock-fontify-buffer))
  21. ;; *xpm
  22. (defun ih-make-xpm (width height color &optional lor)
  23. (let* ((w width)
  24. (h height)
  25. (s1 (concat "\"" (make-string w (string-to-char " ")) "\""))
  26. (s2 (cond
  27. ((eq lor 0)
  28. (concat "\"." (make-string (1- w) (string-to-char " ")) "\""))
  29. ((eq lor 1)
  30. (concat "\"" (make-string (1- w) (string-to-char " ")) ".\""))
  31. ((null lor)
  32. (concat "\"" (make-string (- (1- w)(/ (1- w) 2))(string-to-char " "))
  33. "." (make-string (/ (1- w) 2)(string-to-char " ")) "\""))))
  34. (sa (concat s1 ",\n" s2 ",\n")))
  35. (eval `(concat "/* XPM */
  36. static char * dot_vline_xpm[] = {
  37. \"" (number-to-string w) " " (number-to-string h) " 2 1\",
  38. \" c None\",
  39. \". c " color "\",\n"
  40. ,@(mapcar (lambda(x) sa)
  41. (make-list (1- (/ h 2)) 0))
  42. s1 ",\n" s2 "};"
  43. ))))
  44. (defvar ih-line-height (or (car (window-line-height)) 20))
  45. (defvar ih-img (ih-make-xpm 9 ih-line-height "#4D4D4D"))
  46. (defvar ih-img-lgc (ih-make-xpm 9 ih-line-height "#5d478b"))
  47. (defvar ih-img-mtd (ih-make-xpm 9 ih-line-height "khaki"))
  48. (defvar ih-img-dat (ih-make-xpm 9 ih-line-height "#008b45"))
  49. ;; *overlay
  50. ;; (defun ih-make-overlay (b e)
  51. ;; (let* ((p 'ih-overlay-pool)
  52. ;; (q (eval p))
  53. ;; (ov (or (car (prog1 q (set p (cdr q))))
  54. ;; (make-overlay b e))))
  55. ;; (move-overlay ov b e)
  56. ;; ov))
  57. (defun ih-make-overlay (b e)
  58. (let* ((p 'ih-overlay-pool)
  59. (q (eval p))
  60. (ov (car q)))
  61. (if ov
  62. (progn
  63. (set p (cdr-safe q))
  64. (move-overlay ov b e))
  65. (setq ov (make-overlay b e)))
  66. ov))
  67. (defun ih-delete-overlay (o)
  68. (let ((ov o)
  69. (p 'ih-overlay-pool))
  70. ;; (overlay-put ov ih-key nil)
  71. (delete-overlay ov)
  72. (set p (cons ov (eval p)))))
  73. (defun ih-overlay-exist (k p q)
  74. (let (r o (l (overlays-in p q)))
  75. (while (and l
  76. (null
  77. (if (overlay-get (setq o (car l)) k)
  78. (setq r t)
  79. nil)))
  80. (setq l (cdr l)))
  81. (if r o)))
  82. (defun ih-make-head()
  83. (make-temp-name ""))
  84. ;; (defun ih-make-head1()
  85. ;; (let* ((p (point))
  86. ;; (q (1+ p))
  87. ;; o)
  88. ;; (or
  89. ;; (setq o (ih-overlay-exist ih-head p q))
  90. ;; (progn
  91. ;; (setq o (ih-make-overlay p p))
  92. ;; (overlay-put o ih-head t)))
  93. ;; o))
  94. ;; *table
  95. (defun ih-put (k v)
  96. (let ((h ih-table))
  97. (puthash k v h)))
  98. (defun ih-get (k)
  99. (let ((h ih-table))
  100. (gethash k h)))
  101. (defun ih-rem (k)
  102. (let ((h ih-table))
  103. (remhash k h)
  104. ;; debug
  105. ;; (ih-table-length)
  106. ))
  107. ;; *count-line
  108. (defun ih-count-line(&optional pos)
  109. (let* ((p (or pos (point)))
  110. (c (save-excursion
  111. (goto-char p)
  112. (current-column)))
  113. (x 0)(r 0) w)
  114. (save-excursion
  115. (while
  116. (and (> (point-max)(line-end-position))
  117. (or
  118. (and (ih-white-line)
  119. (setq x (1+ x)
  120. w (cons r w)))
  121. (and (< c (current-indentation))
  122. (setq x 0))))
  123. (forward-line)
  124. (move-to-column c)
  125. (setq r (1+ r))))
  126. (cons (- r x) (nthcdr x w))))
  127. ;; *white line
  128. (defun ih-white-line()
  129. (save-excursion
  130. (move-to-column (current-indentation))
  131. (eolp)))
  132. (defun ihwl-create()
  133. )
  134. (defun ihwl-destroy()
  135. )
  136. (defun ihwl-insert(col k &optional img color)
  137. )
  138. (defun ihwl-delete()
  139. )
  140. ;; *draw-indent-hint-line
  141. (defun draw-indent-hint-line (&optional column img color)
  142. (interactive "P")
  143. (save-excursion
  144. (let* ((i (or column (current-indentation)))
  145. (h (ih-make-head))
  146. (m (progn (forward-line)
  147. (move-to-column i)
  148. (ih-count-line)))
  149. (x (car m))(y (cdr m)) lst)
  150. (if (> x 0)
  151. (progn
  152. (kill-indent-hint (point))
  153. (dotimes (n x)
  154. (if (memq n y)
  155. (ihwl-insert i h img color)
  156. (setq lst (cons (draw-indent-hint (point) h img color) lst)))
  157. (forward-line)
  158. (move-to-column i))
  159. (ih-put h (cons y lst)))))))
  160. ;; *draw-indent-hint
  161. (defun draw-indent-hint (pos id &optional img color)
  162. (let* ((img (or img ih-img))
  163. (color (or color "#4D4D4D"))
  164. (ov (ih-make-overlay pos (1+ pos))))
  165. (overlay-put ov ih-key id)
  166. ;; (overlay-put ov evaporate t)
  167. (funcall draw-indent-hint-func ov img color)
  168. ov))
  169. (setq draw-indent-hint-func
  170. (if (display-images-p)
  171. (lambda(o img color)
  172. (overlay-put o 'display
  173. `(display (image
  174. :type xpm
  175. :data ,img
  176. :pointer text
  177. :ascent center
  178. :mask (heuristic t))
  179. rear-nonsticky (display)
  180. fontified t)))
  181. (lambda(o img color)
  182. (overlay-put o 'display
  183. "|"))))
  184. ;; *erase-indent-hint
  185. (defun kill-indent-hint (m &optional n)
  186. (let ((n (or n (1+ m))))
  187. (mapc
  188. (lambda(x)(let ((i (overlay-get x ih-key)))
  189. (if i
  190. (progn
  191. (mapc
  192. (lambda(y)(ih-delete-overlay y))
  193. (cdr (ih-get i)))
  194. ;; (mapc
  195. ;; (lambda(x)(ihwl-delete x))
  196. ;; (car (ih-get i)))
  197. (ih-rem i)
  198. ))))
  199. (overlays-in m n))))
  200. (defun erase-indent-hint (overlay after? beg end &optional length)
  201. (let ((inhibit-modification-hooks t)
  202. p1 p2)
  203. (if after?
  204. (save-excursion
  205. (forward-line)
  206. ;; (setq p1 (point))
  207. (setq p1 (line-beginning-position)
  208. p2 (+ p1 (current-indentation)))
  209. (kill-indent-hint p1 p2)
  210. (font-lock-fontify-block))
  211. (setq p1 (line-beginning-position) ;; (point)
  212. p2 (+ p1 (current-indentation)))
  213. (kill-indent-hint p1 p2))))
  214. ;; *background overlay
  215. (defun ih-bgo-init (&optional r)
  216. (let* ((b (line-beginning-position))
  217. (e (+ b (current-indentation)))
  218. o)
  219. (setq r (or r 'ih-background-overlay))
  220. (make-local-variable r)
  221. (setq o (make-overlay b e))
  222. (overlay-put o ih-bg t)
  223. ;; debug
  224. ;; (overlay-put o 'face '((t (:background "grey40"))))
  225. (overlay-put o 'modification-hooks '(erase-indent-hint))
  226. (overlay-put o 'insert-in-front-hooks '(erase-indent-hint))
  227. (overlay-put o 'insert-behind-hooks '(erase-indent-hint))
  228. (set r o)))
  229. (defun ih-bgo-mv(&optional o)
  230. (let* ((o (or o ih-background-overlay))
  231. (b (line-beginning-position))
  232. (e (+ b (current-indentation))))
  233. (move-overlay o b e)))
  234. ;; *interface
  235. (defun indent-hint-current-column ()
  236. (save-excursion
  237. (goto-char (match-beginning 1))
  238. (current-column)))
  239. (defun indent-hint (&optional regexp column img color)
  240. (interactive)
  241. (let ((x (or regexp "^")))
  242. (font-lock-add-keywords
  243. nil `((,x
  244. (0 (draw-indent-hint-line ,column ,img ,color)))))))
  245. (defun indent-hint-mode (&optional lst l)
  246. (interactive)
  247. (let* ((c '(indent-hint-current-column))
  248. (lst (or lst '(("^[ \t]*\\([^ \t]\\)"))))
  249. (lst (if l lst (reverse lst))))
  250. (ih-init l)
  251. (dolist (x lst)
  252. (indent-hint (car x) c (cadr x)))))
  253. ;;;###autoload
  254. (defun indent-hint-lisp ()
  255. (interactive)
  256. (indent-hint-mode
  257. '(("^[ \t]*\\((\\)")
  258. ("\\((lambda\\|(defun\\|(defmacro\\)" ih-img-mtd)
  259. ("\\((let\\*?\\|(if\\|(while\\|(cond\\|(and\\|(or\\|(map.*\\|(save-excursion\\)" ih-img-lgc)
  260. ("\\((setq\\|(defvar\\)" ih-img-dat)
  261. ("[,`#']+\\((\\)" ih-img-dat))))
  262. ;;;###autoload
  263. (defun indent-hint-fixed(&optional img)
  264. (interactive)
  265. (indent-hint-mode
  266. `(( "^[ \t]*\\([^ \t]\\)"
  267. ,img))))
  268. ;;;###autoload
  269. (defun indent-hint-js ()
  270. (interactive)
  271. (indent-hint-mode
  272. '(("^[ \t]*\\([^ \t}(]\\)")
  273. ("\\(function\\|var\\)" ih-img-mtd)
  274. ("\\(if\\|for\\|else\\|switch\\)" ih-img-lgc)
  275. ("^[ \t]*\\((\\)" ih-img-dat))
  276. #@2:t))
  277. ;;;###autoload
  278. (defun indent-hint-test (&optional regexp)
  279. (interactive)
  280. (indent-hint (or regexp "\\(def\\|class\\|if\\)")
  281. '(indent-hint-current-column))
  282. (in-init))
  283. ;; **old
  284. (defun indent-vline-lisp ()
  285. (interactive)
  286. (in-init)
  287. (let ((c '(indent-hint-current-column))
  288. (blk "\\((let\\*?\\|(if\\|(while\\|(cond\\|(map.*\\|(defun\\|(save-excursion\\)"))
  289. (if indent-hint-lazy
  290. (progn
  291. (indent-hint "^[ \t]*\\((\\)" c)
  292. (indent-hint "\\((lambda\\|(setq\\|(defvar\\)" c 'ih-img-lst)
  293. (indent-hint blk c 'ih-img-blk)
  294. (indent-hint "[,`#']+\\((\\)" c 'ih-img-lst))
  295. (indent-hint "[,`#']+\\((\\)" c 'ih-img-lst)
  296. (indent-hint blk c 'ih-img-blk)
  297. (indent-hint "\\((lambda\\|(setq\\|(defvar\\)" c 'ih-img-lst)
  298. (indent-hint "^[ \t]*\\((\\)" c))))
  299. ;; *debug
  300. (defun ih-table-length()
  301. (interactive)
  302. (let ((l 0)
  303. (h ih-table))
  304. (maphash
  305. (lambda(x y)
  306. (setq l (1+ l)))
  307. h)
  308. (message (number-to-string l))))
  309. (defun what-overlays (&optional p)
  310. (interactive)
  311. (print
  312. (let ((pt (or p (point))))
  313. (cons (cons pt (current-column))
  314. (mapcar
  315. (lambda(x) (remove-if
  316. nil
  317. `(,x
  318. ,(overlay-get x ih-key)
  319. ;; ,(if (overlay-get x ih-head) 'head)
  320. ,(if (overlay-get x ih-bg) 'bg)
  321. ,(if (eq (overlay-get x 'face) 'hl-line) 'hl-line))))
  322. (overlays-in pt (1+ pt)))))))
  323. (when
  324. nil
  325. (what-overlays)
  326. (length indent-hint-list)
  327. (dolist (x indent-hint-list)
  328. (if (null (eval x))
  329. (and (unintern x)
  330. (setq indent-hint-list
  331. (delq x indent-hint-list)))))
  332. (setq overlay-no-buffer nil)
  333. (dolist (x indent-hint-list)
  334. (dolist (y (eval x))
  335. (if (null (overlay-buffer y))
  336. (setq overlay-no-buffer
  337. (cons y overlay-no-buffer)))))
  338. )