PageRenderTime 66ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/vendor/haskell-mode/haskell-indent.el

http://github.com/rejeep/emacs
Emacs Lisp | 1581 lines | 1196 code | 121 blank | 264 comment | 29 complexity | 6fdab41c0a16f04b469cfd5fb5ed123c MD5 | raw file
Possible License(s): GPL-2.0
  1. ;;; haskell-indent.el --- "semi-intelligent" indentation module for Haskell Mode
  2. ;; Copyright 2004, 2005, 2007, 2008, 2009 Free Software Foundation, Inc.
  3. ;; Copyright 1997-1998 Guy Lapalme
  4. ;; Author: 1997-1998 Guy Lapalme <lapalme@iro.umontreal.ca>
  5. ;; Keywords: indentation Haskell layout-rule
  6. ;; Version: 1.2
  7. ;; URL: http://www.iro.umontreal.ca/~lapalme/layout/index.html
  8. ;;; This file is not part of GNU Emacs.
  9. ;; This file is free software; you can redistribute it and/or modify
  10. ;; it under the terms of the GNU General Public License as published by
  11. ;; the Free Software Foundation; either version 3, or (at your option)
  12. ;; any later version.
  13. ;; This file is distributed in the hope that it will be useful,
  14. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. ;; GNU General Public License for more details.
  17. ;; You should have received a copy of the GNU General Public License
  18. ;; along with GNU Emacs; see the file COPYING. If not, write to the
  19. ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  20. ;; Boston, MA 02111-1307, USA.
  21. ;;; Commentary:
  22. ;; Purpose:
  23. ;;
  24. ;; To support automatic indentation of Haskell programs using
  25. ;; the layout rule described in section 1.5 and appendix B.3 of the
  26. ;; the Haskell report. The rationale and the implementation principles
  27. ;; are described in an article to appear in Journal of Functional Programming.
  28. ;; "Dynamic tabbing for automatic indentation with the layout rule"
  29. ;;
  30. ;; It supports literate scripts.
  31. ;; Haskell indentation is performed
  32. ;; within \begin{code}...\end{code} sections of a literate script
  33. ;; and in lines beginning with > with Bird style literate script
  34. ;; TAB aligns to the left column outside of these sections.
  35. ;;
  36. ;; Installation:
  37. ;;
  38. ;; To turn indentation on for all Haskell buffers under the Haskell
  39. ;; mode of Moss&Thorn <http://www.haskell.org/haskell-mode/>
  40. ;; add this to .emacs:
  41. ;;
  42. ;; (add-hook 'haskell-mode-hook 'turn-on-haskell-indent)
  43. ;;
  44. ;; Otherwise, call `turn-on-haskell-indent'.
  45. ;;
  46. ;;
  47. ;; Customisation:
  48. ;; The "standard" offset for statements is 4 spaces.
  49. ;; It can be changed by setting the variable "haskell-indent-offset" to
  50. ;; another value
  51. ;;
  52. ;; The default number of blanks after > in a Bird style literate script
  53. ;; is 1; it can be changed by setting the variable
  54. ;; "haskell-indent-literate-Bird-default-offset"
  55. ;;
  56. ;; `haskell-indent-hook' is invoked if not nil.
  57. ;;
  58. ;; All functions/variables start with
  59. ;; `(turn-(on/off)-)haskell-indent' or `haskell-indent-'.
  60. ;; This file can also be used as a hook for the Hugs Mode developed by
  61. ;; Chris Van Humbeeck <chris.vanhumbeeck@cs.kuleuven.ac.be>
  62. ;; It can be obtained at:
  63. ;; http://www-i2.informatik.rwth-aachen.de/Forschung/FP/Haskell/hugs-mode.el
  64. ;;
  65. ;; For the Hugs mode put the following in your .emacs
  66. ;;
  67. ;;(setq auto-mode-alist (append auto-mode-alist '(("\\.hs\\'" . hugs-mode))))
  68. ;;(autoload 'hugs-mode "hugs-mode" "Go into hugs mode" t)
  69. ;;
  70. ;; If only the indentation mode is used then replace the two
  71. ;; preceding lines with
  72. ;;(setq auto-mode-alist (append auto-mode-alist
  73. ;; '(("\\.hs\\'" . turn-on-haskell-indent))))
  74. ;;(autoload 'turn-on-haskell-indent "hindent" "Indentation mode for Haskell" t)
  75. ;;
  76. ;; For indentation in both cases then add the following to your .emacs
  77. ;;(add-hook 'hugs-mode-hook 'turn-on-haskell-indent)
  78. ;;(autoload 'haskell-indent-cycle "hindent" "Indentation cycle for Haskell" t)
  79. ;;
  80. ;;; Code:
  81. (eval-when-compile (require 'cl)) ;need defs of push and pop
  82. (defvar haskell-literate)
  83. (defgroup haskell-indent nil
  84. "Haskell indentation."
  85. :group 'haskell
  86. :prefix "haskell-indent-")
  87. (defcustom haskell-indent-offset 4
  88. "Indentation of Haskell statements with respect to containing block."
  89. :type 'integer
  90. :group 'haskell-indent)
  91. (defcustom haskell-indent-literate-Bird-default-offset 1
  92. "Default number of blanks after > in a Bird style literate script."
  93. :type 'integer
  94. :group 'haskell-indent)
  95. (defcustom haskell-indent-rhs-align-column 0
  96. "Column on which to align right-hand sides (use 0 for ad-hoc alignment)."
  97. :type 'integer
  98. :group 'haskell-indent)
  99. (defun haskell-indent-point-to-col (apoint)
  100. "Return the column number of APOINT."
  101. (save-excursion
  102. (goto-char apoint)
  103. (current-column)))
  104. (defconst haskell-indent-start-keywords-re
  105. (concat "\\<"
  106. (regexp-opt '("class" "data" "import" "infix" "infixl" "infixr"
  107. "instance" "module" "newtype" "primitive" "type") t)
  108. "\\>")
  109. "Regexp for keywords to complete when standing at the first word of a line.")
  110. ;; Customizations for different kinds of environments
  111. ;; in which dealing with low-level events are different.
  112. (defun haskell-indent-mark-active ()
  113. (if (featurep 'xemacs)
  114. (if zmacs-regions
  115. zmacs-region-active-p
  116. t)
  117. mark-active))
  118. ;; for pushing indentation information
  119. (defvar haskell-indent-info) ;Used with dynamic scoping.
  120. (defun haskell-indent-push-col (col &optional name)
  121. "Push indentation information for the column COL.
  122. The info is followed by NAME (if present).
  123. Makes sure that the same indentation info is not pushed twice.
  124. Uses free var `haskell-indent-info'."
  125. (let ((tmp (cons col name)))
  126. (if (member tmp haskell-indent-info)
  127. haskell-indent-info
  128. (push tmp haskell-indent-info))))
  129. (defun haskell-indent-push-pos (pos &optional name)
  130. "Push indentation information for POS followed by NAME (if present)."
  131. (haskell-indent-push-col (haskell-indent-point-to-col pos) name))
  132. ;; (defvar haskell-indent-tab-align nil
  133. ;; "Align all indentations on TAB stops.")
  134. (defun haskell-indent-column+offset (column offset)
  135. (unless offset (setq offset haskell-indent-offset))
  136. (setq column (+ column offset))
  137. ;; (if (and haskell-indent-tab-align (> offset 0))
  138. ;; (* 8 (/ (+ column 7) 8))
  139. column) ;; )
  140. (defun haskell-indent-push-pos-offset (pos &optional offset)
  141. "Pushes indentation information for the column corresponding to POS
  142. followed by an OFFSET (if present use its value otherwise use
  143. `haskell-indent-offset')."
  144. (haskell-indent-push-col (haskell-indent-column+offset
  145. (haskell-indent-point-to-col pos)
  146. offset)))
  147. ;; redefinition of some Emacs function for dealing with
  148. ;; Bird Style literate scripts
  149. (defun haskell-indent-bolp ()
  150. "`bolp' but dealing with Bird-style literate scripts."
  151. (or (bolp)
  152. (and (eq haskell-literate 'bird)
  153. (<= (current-column) (1+ haskell-indent-literate-Bird-default-offset))
  154. (eq (char-after (line-beginning-position)) ?\>))))
  155. (defun haskell-indent-empty-line-p ()
  156. "Checks if the current line is empty; deals with Bird style scripts."
  157. (save-excursion
  158. (beginning-of-line)
  159. (if (and (eq haskell-literate 'bird)
  160. (eq (following-char) ?\>))
  161. (forward-char 1))
  162. (looking-at "[ \t]*$")))
  163. (defun haskell-indent-back-to-indentation ()
  164. "`back-to-indentation' function but dealing with Bird-style literate scripts."
  165. (if (and (eq haskell-literate 'bird)
  166. (progn (beginning-of-line) (eq (following-char) ?\>)))
  167. (progn
  168. (forward-char 1)
  169. (skip-chars-forward " \t"))
  170. (back-to-indentation)))
  171. (defun haskell-indent-current-indentation ()
  172. "`current-indentation' function dealing with Bird-style literate scripts."
  173. (if (eq haskell-literate 'bird)
  174. (save-excursion
  175. (haskell-indent-back-to-indentation)
  176. (current-column))
  177. (current-indentation)))
  178. (defun haskell-indent-backward-to-indentation (n)
  179. "`backward-to-indentation' function dealing with Bird-style literate scripts."
  180. (if (eq haskell-literate 'bird)
  181. (progn
  182. (forward-line (- n))
  183. (haskell-indent-back-to-indentation))
  184. (backward-to-indentation n)))
  185. (defun haskell-indent-forward-line (&optional n)
  186. "`forward-line' function but dealing with Bird-style literate scripts."
  187. (prog1
  188. (forward-line n)
  189. (if (and (eq haskell-literate 'bird) (eq (following-char) ?\>))
  190. (progn (forward-char 1) ; skip > and initial blanks...
  191. (skip-chars-forward " \t")))))
  192. (defun haskell-indent-line-to (n)
  193. "`indent-line-to' function but dealing with Bird-style literate scripts."
  194. (if (eq haskell-literate 'bird)
  195. (progn
  196. (beginning-of-line)
  197. (if (eq (following-char) ?\>)
  198. (delete-char 1))
  199. (delete-horizontal-space) ; remove any starting TABs so
  200. (indent-line-to n) ; that indent-line only adds spaces
  201. (save-excursion
  202. (beginning-of-line)
  203. (if (> n 0) (delete-char 1)) ; delete the first space before
  204. (insert ?\>))) ; inserting a >
  205. (indent-line-to n)))
  206. (defun haskell-indent-skip-blanks-and-newlines-forward (end)
  207. "Skip forward blanks, tabs and newlines until END.
  208. Take account of Bird-style literate scripts."
  209. (skip-chars-forward " \t\n" end)
  210. (if (eq haskell-literate 'bird)
  211. (while (and (bolp) (eq (following-char) ?\>))
  212. (forward-char 1) ; skip >
  213. (skip-chars-forward " \t\n" end))))
  214. (defun haskell-indent-skip-blanks-and-newlines-backward (start)
  215. "Skip backward blanks, tabs and newlines up to START.
  216. Take account of Bird-style literate scripts."
  217. (skip-chars-backward " \t\n" start)
  218. (if (eq haskell-literate 'bird)
  219. (while (and (eq (current-column) 1)
  220. (eq (preceding-char) ?\>))
  221. (forward-char -1) ; skip back >
  222. (skip-chars-backward " \t\n" start))))
  223. ;; specific functions for literate code
  224. (defun haskell-indent-within-literate-code ()
  225. "Check if point is within a part of literate Haskell code.
  226. If so, return its start; otherwise return nil:
  227. If it is Bird-style, then return the position of the >;
  228. otherwise return the ending position of \\begin{code}."
  229. (save-excursion
  230. (case haskell-literate
  231. (bird
  232. (beginning-of-line)
  233. (if (or (eq (following-char) ?\>)
  234. (and (bolp) (forward-line -1) (eq (following-char) ?\>)))
  235. (progn
  236. (while (and (zerop (forward-line -1))
  237. (eq (following-char) ?\>)))
  238. (if (not (eq (following-char) ?\>))
  239. (forward-line))
  240. (point))))
  241. ;; Look for a \begin{code} or \end{code} line.
  242. ((latex tex)
  243. (if (re-search-backward
  244. "^\\(\\\\begin{code}$\\)\\|\\(\\\\end{code}$\\)" nil t)
  245. ;; within a literate code part if it was a \\begin{code}.
  246. (match-end 1)))
  247. (t (error "haskell-indent-within-literate-code: should not happen!")))))
  248. (defun haskell-indent-put-region-in-literate (beg end &optional arg)
  249. "Put lines of the region as a piece of literate code.
  250. With prefix arg, remove indication that the region is literate code.
  251. It deals with both Bird style and non Bird-style scripts."
  252. (interactive "r\nP")
  253. (unless haskell-literate
  254. (error "Cannot put a region in literate in a non literate script"))
  255. (if (eq haskell-literate 'bird)
  256. (let ((comment-start "> ") ; Change dynamic bindings for
  257. (comment-start-skip "^> ?") ; comment-region.
  258. (comment-end "")
  259. (comment-end-skip "\n")
  260. (comment-style 'plain))
  261. (comment-region beg end arg))
  262. ;; Not Bird style.
  263. (if arg ; Remove the literate indication.
  264. (save-excursion
  265. (goto-char end) ; Remove end.
  266. (if (re-search-backward "^\\\\end{code}[ \t\n]*\\="
  267. (line-beginning-position -2) t)
  268. (delete-region (point) (line-beginning-position 2)))
  269. (goto-char beg) ; Remove end.
  270. (beginning-of-line)
  271. (if (looking-at "\\\\begin{code}")
  272. (kill-line 1)))
  273. (save-excursion ; Add the literate indication.
  274. (goto-char end)
  275. (unless (bolp) (newline))
  276. (insert "\\end{code}\n")
  277. (goto-char beg)
  278. (unless (bolp) (newline))
  279. (insert "\\begin{code}\n")))))
  280. ;;; Start of indentation code
  281. (defcustom haskell-indent-look-past-empty-line t
  282. "If nil, indentation engine will not look past an empty line for layout points."
  283. :group 'haskell-indent
  284. :type 'boolean)
  285. (defun haskell-indent-start-of-def ()
  286. "Return the position of the start of a definition.
  287. The start of a def is expected to be recognizable by starting in column 0,
  288. unless `haskell-indent-look-past-empty-line' is nil, in which case we
  289. take a coarser approximation and stop at the first empty line."
  290. (save-excursion
  291. (let ((start-code (and haskell-literate
  292. (haskell-indent-within-literate-code)))
  293. (top-col (if (eq haskell-literate 'bird) 2 0))
  294. (save-point (point)))
  295. ;; determine the starting point of the current piece of code
  296. (setq start-code (if start-code (1+ start-code) (point-min)))
  297. ;; go backward until the first preceding empty line
  298. (haskell-indent-forward-line -1)
  299. (while (and (if haskell-indent-look-past-empty-line
  300. (or (> (haskell-indent-current-indentation) top-col)
  301. (haskell-indent-empty-line-p))
  302. (and (> (haskell-indent-current-indentation) top-col)
  303. (not (haskell-indent-empty-line-p))))
  304. (> (point) start-code)
  305. (= 0 (haskell-indent-forward-line -1))))
  306. ;; go forward after the empty line
  307. (if (haskell-indent-empty-line-p)
  308. (haskell-indent-forward-line 1))
  309. (setq start-code (point))
  310. ;; find the first line of code which is not a comment
  311. (forward-comment (point-max))
  312. (if (> (point) save-point)
  313. start-code
  314. (point)))))
  315. (defun haskell-indent-open-structure (start end)
  316. "If any structure (list or tuple) is not closed, between START and END,
  317. returns the location of the opening symbol, nil otherwise."
  318. (save-excursion
  319. (nth 1 (parse-partial-sexp start end))))
  320. (defun haskell-indent-in-string (start end)
  321. "If a string is not closed , between START and END, returns the
  322. location of the opening symbol, nil otherwise."
  323. (save-excursion
  324. (let ((pps (parse-partial-sexp start end)))
  325. (if (nth 3 pps) (nth 8 pps)))))
  326. (defun haskell-indent-in-comment (start end)
  327. "Check, starting from START, if END is at or within a comment.
  328. Returns the location of the start of the comment, nil otherwise."
  329. (let (pps)
  330. (assert (<= start end))
  331. (cond ((= start end) nil)
  332. ((nth 4 (save-excursion (setq pps (parse-partial-sexp start end))))
  333. (nth 8 pps))
  334. ;; We also want to say that we are *at* the beginning of a comment.
  335. ((and (not (nth 8 pps))
  336. (>= (point-max) (+ end 2))
  337. (nth 4 (save-excursion
  338. (setq pps (parse-partial-sexp end (+ end 2))))))
  339. (nth 8 pps)))))
  340. (defvar haskell-indent-off-side-keywords-re
  341. "\\<\\(do\\|let\\|of\\|where\\)\\>[ \t]*")
  342. (defun haskell-indent-type-at-point ()
  343. "Return the type of the line (also puts information in `match-data')."
  344. (cond
  345. ((haskell-indent-empty-line-p) 'empty)
  346. ((haskell-indent-in-comment (point-min) (point)) 'comment)
  347. ((looking-at "\\(\\([[:alpha:]]\\(\\sw\\|'\\)*\\)\\|_\\)[ \t\n]*")
  348. 'ident)
  349. ((looking-at "\\(|[^|]\\)[ \t\n]*") 'guard)
  350. ((looking-at "\\(=[^>=]\\|::\\|->\\|<-\\)[ \t\n]*") 'rhs)
  351. (t 'other)))
  352. (defvar haskell-indent-current-line-first-ident ""
  353. "Global variable that keeps track of the first ident of the line to indent.")
  354. (defun haskell-indent-contour-line (start end)
  355. "Generate contour information between START and END points."
  356. (if (< start end)
  357. (save-excursion
  358. (goto-char end)
  359. (haskell-indent-skip-blanks-and-newlines-backward start)
  360. (let ((cur-col (current-column)) ; maximum column number
  361. (fl 0) ; number of lines that forward-line could not advance
  362. contour)
  363. (while (and (> cur-col 0) (= fl 0) (>= (point) start))
  364. (haskell-indent-back-to-indentation)
  365. (if (< (point) start) (goto-char start))
  366. (and (not (member (haskell-indent-type-at-point)
  367. '(empty comment))) ; skip empty and comment lines
  368. (< (current-column) cur-col) ; less indented column found
  369. (push (point) contour) ; new contour point found
  370. (setq cur-col (current-column)))
  371. (setq fl (haskell-indent-forward-line -1)))
  372. contour))))
  373. (defun haskell-indent-next-symbol (end)
  374. "Move point to the next symbol."
  375. (skip-syntax-forward ")" end)
  376. (if (< (point) end)
  377. (progn
  378. (forward-sexp 1)
  379. (haskell-indent-skip-blanks-and-newlines-forward end))))
  380. (defun haskell-indent-next-symbol-safe (end)
  381. "Puts point to the next following symbol, or to end if there are no more symbols in the sexp."
  382. (condition-case errlist (haskell-indent-next-symbol end)
  383. (error (goto-char end))))
  384. (defun haskell-indent-separate-valdef (start end)
  385. "Return a list of positions for important parts of a valdef."
  386. (save-excursion
  387. (let (valname valname-string aft-valname
  388. guard aft-guard
  389. rhs-sign aft-rhs-sign
  390. type)
  391. ;; "parse" a valdef separating important parts
  392. (goto-char start)
  393. (setq type (haskell-indent-type-at-point))
  394. (if (or (memq type '(ident other))) ; possible start of a value def
  395. (progn
  396. (if (eq type 'ident)
  397. (progn
  398. (setq valname (match-beginning 0))
  399. (setq valname-string (match-string 0))
  400. (goto-char (match-end 0)))
  401. (skip-chars-forward " \t" end)
  402. (setq valname (point)) ; type = other
  403. (haskell-indent-next-symbol-safe end))
  404. (while (and (< (point) end)
  405. (setq type (haskell-indent-type-at-point))
  406. (or (memq type '(ident other))))
  407. (if (null aft-valname)
  408. (setq aft-valname (point)))
  409. (haskell-indent-next-symbol-safe end))))
  410. (if (and (< (point) end) (eq type 'guard)) ; start of a guard
  411. (progn
  412. (setq guard (match-beginning 0))
  413. (goto-char (match-end 0))
  414. (while (and (< (point) end)
  415. (setq type (haskell-indent-type-at-point))
  416. (not (eq type 'rhs)))
  417. (if (null aft-guard)
  418. (setq aft-guard (point)))
  419. (haskell-indent-next-symbol-safe end))))
  420. (if (and (< (point) end) (eq type 'rhs)) ; start of a rhs
  421. (progn
  422. (setq rhs-sign (match-beginning 0))
  423. (goto-char (match-end 0))
  424. (if (< (point) end)
  425. (setq aft-rhs-sign (point)))))
  426. (list valname valname-string aft-valname
  427. guard aft-guard rhs-sign aft-rhs-sign))))
  428. (defsubst haskell-indent-no-otherwise (guard)
  429. "Check if there is no otherwise at GUARD."
  430. (save-excursion
  431. (goto-char guard)
  432. (not (looking-at "|[ \t]*otherwise\\>"))))
  433. (defun haskell-indent-guard (start end end-visible indent-info)
  434. "Find indentation information for a line starting with a guard."
  435. (save-excursion
  436. (let* ((haskell-indent-info indent-info)
  437. (sep (haskell-indent-separate-valdef start end))
  438. (valname (nth 0 sep))
  439. (guard (nth 3 sep))
  440. (rhs-sign (nth 5 sep)))
  441. ;; push information indentation for the visible part
  442. (if (and guard (< guard end-visible) (haskell-indent-no-otherwise guard))
  443. (haskell-indent-push-pos guard)
  444. (if rhs-sign
  445. (haskell-indent-push-pos rhs-sign) ; probably within a data definition...
  446. (if valname
  447. (haskell-indent-push-pos-offset valname))))
  448. haskell-indent-info)))
  449. (defun haskell-indent-rhs (start end end-visible indent-info)
  450. "Find indentation information for a line starting with a rhs."
  451. (save-excursion
  452. (let* ((haskell-indent-info indent-info)
  453. (sep (haskell-indent-separate-valdef start end))
  454. (valname (nth 0 sep))
  455. (guard (nth 3 sep))
  456. (rhs-sign (nth 5 sep)))
  457. ;; push information indentation for the visible part
  458. (if (and rhs-sign (< rhs-sign end-visible))
  459. (haskell-indent-push-pos rhs-sign)
  460. (if (and guard (< guard end-visible))
  461. (haskell-indent-push-pos-offset guard)
  462. (if valname ; always visible !!
  463. (haskell-indent-push-pos-offset valname))))
  464. haskell-indent-info)))
  465. (defconst haskell-indent-decision-table
  466. (let ((or "\\)\\|\\("))
  467. (concat "\\("
  468. "1.1.11" or ; 1= vn gd rh arh
  469. "1.1.10" or ; 2= vn gd rh
  470. "1.1100" or ; 3= vn gd agd
  471. "1.1000" or ; 4= vn gd
  472. "1.0011" or ; 5= vn rh arh
  473. "1.0010" or ; 6= vn rh
  474. "110000" or ; 7= vn avn
  475. "100000" or ; 8= vn
  476. "001.11" or ; 9= gd rh arh
  477. "001.10" or ;10= gd rh
  478. "001100" or ;11= gd agd
  479. "001000" or ;12= gd
  480. "000011" or ;13= rh arh
  481. "000010" or ;14= rh
  482. "000000" ;15=
  483. "\\)")))
  484. (defun haskell-indent-find-case (test)
  485. "Find the index that matches TEST in the decision table."
  486. (if (string-match haskell-indent-decision-table test)
  487. ;; use the fact that the resulting match-data is a list of the form
  488. ;; (0 6 [2*(n-1) nil] 0 6) where n is the number of the matching regexp
  489. ;; so n= ((length match-data)/2)-1
  490. (- (/ (length (match-data 'integers)) 2) 1)
  491. (error "haskell-indent-find-case: impossible case: %s" test)))
  492. (defun haskell-indent-empty (start end end-visible indent-info)
  493. "Find indentation points for an empty line."
  494. (save-excursion
  495. (let* ((haskell-indent-info indent-info)
  496. (sep (haskell-indent-separate-valdef start end))
  497. (valname (pop sep))
  498. (valname-string (pop sep))
  499. (aft-valname (pop sep))
  500. (guard (pop sep))
  501. (aft-guard (pop sep))
  502. (rhs-sign (pop sep))
  503. (aft-rhs-sign (pop sep))
  504. (last-line (= end end-visible))
  505. (test (string
  506. (if valname ?1 ?0)
  507. (if (and aft-valname (< aft-valname end-visible)) ?1 ?0)
  508. (if (and guard (< guard end-visible)) ?1 ?0)
  509. (if (and aft-guard (< aft-guard end-visible)) ?1 ?0)
  510. (if (and rhs-sign (< rhs-sign end-visible)) ?1 ?0)
  511. (if (and aft-rhs-sign (< aft-rhs-sign end-visible)) ?1 ?0))))
  512. (if (and valname-string ; special case for start keywords
  513. (string-match haskell-indent-start-keywords-re valname-string))
  514. (progn
  515. (haskell-indent-push-pos valname)
  516. ;; very special for data keyword
  517. (if (string-match "\\<data\\>" valname-string)
  518. (if rhs-sign (haskell-indent-push-pos rhs-sign)
  519. (haskell-indent-push-pos-offset valname))
  520. (haskell-indent-push-pos-offset valname)))
  521. (case ; general case
  522. (haskell-indent-find-case test)
  523. ;; "1.1.11" 1= vn gd rh arh
  524. (1 (haskell-indent-push-pos valname)
  525. (haskell-indent-push-pos valname valname-string)
  526. (if (haskell-indent-no-otherwise guard) (haskell-indent-push-pos guard "| "))
  527. (haskell-indent-push-pos aft-rhs-sign))
  528. ;; "1.1.10" 2= vn gd rh
  529. (2 (haskell-indent-push-pos valname)
  530. (haskell-indent-push-pos valname valname-string)
  531. (if last-line
  532. (haskell-indent-push-pos-offset guard)
  533. (if (haskell-indent-no-otherwise guard) (haskell-indent-push-pos guard "| "))))
  534. ;; "1.1100" 3= vn gd agd
  535. (3 (haskell-indent-push-pos valname)
  536. (haskell-indent-push-pos aft-guard)
  537. (if last-line (haskell-indent-push-pos-offset valname)))
  538. ;; "1.1000" 4= vn gd
  539. (4 (haskell-indent-push-pos valname)
  540. (if last-line (haskell-indent-push-pos-offset guard 2)))
  541. ;; "1.0011" 5= vn rh arh
  542. (5 (haskell-indent-push-pos valname)
  543. (if (or (and aft-valname (= (char-after rhs-sign) ?\=))
  544. (= (char-after rhs-sign) ?\:))
  545. (haskell-indent-push-pos valname valname-string))
  546. (haskell-indent-push-pos aft-rhs-sign))
  547. ;; "1.0010" 6= vn rh
  548. (6 (haskell-indent-push-pos valname)
  549. (haskell-indent-push-pos valname valname-string)
  550. (if last-line (haskell-indent-push-pos-offset valname)))
  551. ;; "110000" 7= vn avn
  552. (7 (haskell-indent-push-pos valname)
  553. (if last-line
  554. (haskell-indent-push-pos aft-valname)
  555. (haskell-indent-push-pos valname valname-string)))
  556. ;; "100000" 8= vn
  557. (8 (haskell-indent-push-pos valname))
  558. ;; "001.11" 9= gd rh arh
  559. (9 (if (haskell-indent-no-otherwise guard) (haskell-indent-push-pos guard "| "))
  560. (haskell-indent-push-pos aft-rhs-sign))
  561. ;; "001.10" 10= gd rh
  562. (10 (if (haskell-indent-no-otherwise guard) (haskell-indent-push-pos guard "| "))
  563. (if last-line (haskell-indent-push-pos-offset guard)))
  564. ;; "001100" 11= gd agd
  565. (11 (if (haskell-indent-no-otherwise guard) (haskell-indent-push-pos guard "| "))
  566. (haskell-indent-push-pos aft-guard))
  567. ;; "001000" 12= gd
  568. (12 (if (haskell-indent-no-otherwise guard) (haskell-indent-push-pos guard "| "))
  569. (if last-line (haskell-indent-push-pos-offset guard 2)))
  570. ;; "000011" 13= rh arh
  571. (13 (haskell-indent-push-pos aft-rhs-sign))
  572. ;; "000010" 14= rh
  573. (14 (if last-line (haskell-indent-push-pos-offset rhs-sign 2 )))
  574. ;; "000000" 15=
  575. (t (error "haskell-indent-empty: %s impossible case" test ))))
  576. haskell-indent-info)))
  577. (defun haskell-indent-ident (start end end-visible indent-info)
  578. "Find indentation points for a line starting with an identifier."
  579. (save-excursion
  580. (let*
  581. ((haskell-indent-info indent-info)
  582. (sep (haskell-indent-separate-valdef start end))
  583. (valname (pop sep))
  584. (valname-string (pop sep))
  585. (aft-valname (pop sep))
  586. (guard (pop sep))
  587. (aft-guard (pop sep))
  588. (rhs-sign (pop sep))
  589. (aft-rhs-sign (pop sep))
  590. (last-line (= end end-visible))
  591. (is-where
  592. (string-match "where[ \t]*" haskell-indent-current-line-first-ident))
  593. (diff-first ; not a function def with the same name
  594. (not(string= valname-string haskell-indent-current-line-first-ident)))
  595. ;; (is-type-def
  596. ;; (and rhs-sign (eq (char-after rhs-sign) ?\:)))
  597. (test (string
  598. (if valname ?1 ?0)
  599. (if (and aft-valname (< aft-valname end-visible)) ?1 ?0)
  600. (if (and guard (< guard end-visible)) ?1 ?0)
  601. (if (and aft-guard (< aft-guard end-visible)) ?1 ?0)
  602. (if (and rhs-sign (< rhs-sign end-visible)) ?1 ?0)
  603. (if (and aft-rhs-sign (< aft-rhs-sign end-visible)) ?1 ?0))))
  604. (if (and valname-string ; special case for start keywords
  605. (string-match haskell-indent-start-keywords-re valname-string))
  606. (progn
  607. (haskell-indent-push-pos valname)
  608. (if (string-match "\\<data\\>" valname-string)
  609. ;; very special for data keyword
  610. (if aft-rhs-sign (haskell-indent-push-pos aft-rhs-sign)
  611. (haskell-indent-push-pos-offset valname))
  612. (if (not (string-match
  613. haskell-indent-start-keywords-re
  614. haskell-indent-current-line-first-ident))
  615. (haskell-indent-push-pos-offset valname))))
  616. (if (string= haskell-indent-current-line-first-ident "::")
  617. (if valname (haskell-indent-push-pos valname))
  618. (case ; general case
  619. (haskell-indent-find-case test)
  620. ;; "1.1.11" 1= vn gd rh arh
  621. (1 (if is-where
  622. (haskell-indent-push-pos guard)
  623. (haskell-indent-push-pos valname)
  624. (if diff-first (haskell-indent-push-pos aft-rhs-sign))))
  625. ;; "1.1.10" 2= vn gd rh
  626. (2 (if is-where
  627. (haskell-indent-push-pos guard)
  628. (haskell-indent-push-pos valname)
  629. (if last-line
  630. (haskell-indent-push-pos-offset guard))))
  631. ;; "1.1100" 3= vn gd agd
  632. (3 (if is-where
  633. (haskell-indent-push-pos-offset guard)
  634. (haskell-indent-push-pos valname)
  635. (if diff-first
  636. (haskell-indent-push-pos aft-guard))))
  637. ;; "1.1000" 4= vn gd
  638. (4 (if is-where
  639. (haskell-indent-push-pos guard)
  640. (haskell-indent-push-pos valname)
  641. (if last-line
  642. (haskell-indent-push-pos-offset guard 2))))
  643. ;; "1.0011" 5= vn rh arh
  644. (5 (if is-where
  645. (haskell-indent-push-pos-offset valname)
  646. (haskell-indent-push-pos valname)
  647. (if diff-first
  648. (haskell-indent-push-pos aft-rhs-sign))))
  649. ;; "1.0010" 6= vn rh
  650. (6 (if is-where
  651. (haskell-indent-push-pos-offset valname)
  652. (haskell-indent-push-pos valname)
  653. (if last-line
  654. (haskell-indent-push-pos-offset valname))))
  655. ;; "110000" 7= vn avn
  656. (7 (if is-where
  657. (haskell-indent-push-pos-offset valname)
  658. (haskell-indent-push-pos valname)
  659. (if last-line
  660. (haskell-indent-push-pos aft-valname))))
  661. ;; "100000" 8= vn
  662. (8 (if is-where
  663. (haskell-indent-push-pos-offset valname)
  664. (haskell-indent-push-pos valname)))
  665. ;; "001.11" 9= gd rh arh
  666. (9 (if is-where
  667. (haskell-indent-push-pos guard)
  668. (haskell-indent-push-pos aft-rhs-sign)))
  669. ;; "001.10" 10= gd rh
  670. (10 (if is-where
  671. (haskell-indent-push-pos guard)
  672. (if last-line
  673. (haskell-indent-push-pos-offset guard))))
  674. ;; "001100" 11= gd agd
  675. (11 (if is-where
  676. (haskell-indent-push-pos guard)
  677. (if (haskell-indent-no-otherwise guard)
  678. (haskell-indent-push-pos aft-guard))))
  679. ;; "001000" 12= gd
  680. (12 (if last-line (haskell-indent-push-pos-offset guard 2)))
  681. ;; "000011" 13= rh arh
  682. (13 (haskell-indent-push-pos aft-rhs-sign))
  683. ;; "000010" 14= rh
  684. (14 (if last-line (haskell-indent-push-pos-offset rhs-sign 2)))
  685. ;; "000000" 15=
  686. (t (error "haskell-indent-ident: %s impossible case" test )))))
  687. haskell-indent-info)))
  688. (defun haskell-indent-other (start end end-visible indent-info)
  689. "Find indentation points for a non-empty line starting with something other
  690. than an identifier, a guard or rhs."
  691. (save-excursion
  692. (let* ((haskell-indent-info indent-info)
  693. (sep (haskell-indent-separate-valdef start end))
  694. (valname (pop sep))
  695. (valname-string (pop sep))
  696. (aft-valname (pop sep))
  697. (guard (pop sep))
  698. (aft-guard (pop sep))
  699. (rhs-sign (pop sep))
  700. (aft-rhs-sign (pop sep))
  701. (last-line (= end end-visible))
  702. (test (string
  703. (if valname ?1 ?0)
  704. (if (and aft-valname (< aft-valname end-visible)) ?1 ?0)
  705. (if (and guard (< guard end-visible)) ?1 ?0)
  706. (if (and aft-guard (< aft-guard end-visible)) ?1 ?0)
  707. (if (and rhs-sign (< rhs-sign end-visible)) ?1 ?0)
  708. (if (and aft-rhs-sign (< aft-rhs-sign end-visible)) ?1 ?0))))
  709. (if (and valname-string ; special case for start keywords
  710. (string-match haskell-indent-start-keywords-re valname-string))
  711. (haskell-indent-push-pos-offset valname)
  712. (case ; general case
  713. (haskell-indent-find-case test)
  714. ;; "1.1.11" 1= vn gd rh arh
  715. (1 (haskell-indent-push-pos aft-rhs-sign))
  716. ;; "1.1.10" 2= vn gd rh
  717. (2 (if last-line
  718. (haskell-indent-push-pos-offset guard)
  719. (haskell-indent-push-pos-offset rhs-sign 2)))
  720. ;; "1.1100" 3= vn gd agd
  721. (3 (haskell-indent-push-pos aft-guard))
  722. ;; "1.1000" 4= vn gd
  723. (4 (haskell-indent-push-pos-offset guard 2))
  724. ;; "1.0011" 5= vn rh arh
  725. (5 (haskell-indent-push-pos valname)
  726. (haskell-indent-push-pos aft-rhs-sign))
  727. ;; "1.0010" 6= vn rh
  728. (6 (if last-line
  729. (haskell-indent-push-pos-offset valname)
  730. (haskell-indent-push-pos-offset rhs-sign 2)))
  731. ;; "110000" 7= vn avn
  732. (7 (haskell-indent-push-pos-offset aft-valname))
  733. ;; "100000" 8= vn
  734. (8 (haskell-indent-push-pos valname))
  735. ;; "001.11" 9= gd rh arh
  736. (9 (haskell-indent-push-pos aft-rhs-sign))
  737. ;; "001.10" 10= gd rh
  738. (10 (if last-line
  739. (haskell-indent-push-pos-offset guard)
  740. (haskell-indent-push-pos-offset rhs-sign 2)))
  741. ;; "001100" 11= gd agd
  742. (11 (if (haskell-indent-no-otherwise guard)
  743. (haskell-indent-push-pos aft-guard)))
  744. ;; "001000" 12= gd
  745. (12 (if last-line (haskell-indent-push-pos-offset guard 2)))
  746. ;; "000011" 13= rh arh
  747. (13 (haskell-indent-push-pos aft-rhs-sign))
  748. ;; "000010" 14= rh
  749. (14 (if last-line (haskell-indent-push-pos-offset rhs-sign 2)))
  750. ;; "000000" 15=
  751. (t (error "haskell-indent-other: %s impossible case" test ))))
  752. haskell-indent-info)))
  753. (defun haskell-indent-valdef-indentation (start end end-visible curr-line-type
  754. indent-info)
  755. "Find indentation information for a value definition."
  756. (let ((haskell-indent-info indent-info))
  757. (if (< start end-visible)
  758. (case curr-line-type
  759. (empty (haskell-indent-empty start end end-visible indent-info))
  760. (ident (haskell-indent-ident start end end-visible indent-info))
  761. (guard (haskell-indent-guard start end end-visible indent-info))
  762. (rhs (haskell-indent-rhs start end end-visible indent-info))
  763. (comment (error "Comment indent should never happen"))
  764. (other (haskell-indent-other start end end-visible indent-info)))
  765. haskell-indent-info)))
  766. (defun haskell-indent-line-indentation (line-start line-end end-visible
  767. curr-line-type indent-info)
  768. "Compute indentation info between LINE-START and END-VISIBLE.
  769. Separate a line of program into valdefs between offside keywords
  770. and find indentation info for each part."
  771. (save-excursion
  772. ;; point is (already) at line-start
  773. (assert (eq (point) line-start))
  774. (let ((haskell-indent-info indent-info)
  775. (start (or (haskell-indent-in-comment line-start line-end)
  776. (haskell-indent-in-string line-start line-end))))
  777. (if start ; if comment at the end
  778. (setq line-end start)) ; end line before it
  779. ;; loop on all parts separated by off-side-keywords
  780. (while (and (re-search-forward haskell-indent-off-side-keywords-re
  781. line-end t)
  782. (not (or (haskell-indent-in-comment line-start (point))
  783. (haskell-indent-in-string line-start (point)))))
  784. (let ((beg-match (match-beginning 0)) ; save beginning of match
  785. (end-match (match-end 0))) ; save end of match
  786. ;; Do not try to find indentation points if off-side-keyword at
  787. ;; the start...
  788. (if (or (< line-start beg-match)
  789. ;; Actually, if we're looking at a "let" inside a "do", we
  790. ;; should add the corresponding indentation point.
  791. (eq (char-after beg-match) ?l))
  792. (setq haskell-indent-info
  793. (haskell-indent-valdef-indentation line-start beg-match
  794. end-visible
  795. curr-line-type
  796. haskell-indent-info)))
  797. ;; ...but keep the start of the line if keyword alone on the line
  798. (if (= line-end end-match)
  799. (haskell-indent-push-pos beg-match))
  800. (setq line-start end-match)
  801. (goto-char line-start)))
  802. (haskell-indent-valdef-indentation line-start line-end end-visible
  803. curr-line-type haskell-indent-info))))
  804. (defun haskell-indent-layout-indent-info (start contour-line)
  805. (let ((haskell-indent-info nil)
  806. (curr-line-type (haskell-indent-type-at-point))
  807. line-start line-end end-visible)
  808. (save-excursion
  809. (if (eq curr-line-type 'ident)
  810. (let ; guess the type of line
  811. ((sep
  812. (haskell-indent-separate-valdef
  813. (point) (line-end-position))))
  814. ;; if the first ident is where or the start of a def
  815. ;; keep it in a global variable
  816. (setq haskell-indent-current-line-first-ident
  817. (if (string-match "where[ \t]*" (nth 1 sep))
  818. (nth 1 sep)
  819. (if (nth 5 sep) ; is there a rhs-sign
  820. (if (= (char-after (nth 5 sep)) ?\:) ;is it a typdef
  821. "::" (nth 1 sep))
  822. "")))))
  823. (while contour-line ; explore the contour points
  824. (setq line-start (pop contour-line))
  825. (goto-char line-start)
  826. (setq line-end (line-end-position))
  827. (setq end-visible ; visible until the column of the
  828. (if contour-line ; next contour point
  829. (save-excursion
  830. (move-to-column
  831. (haskell-indent-point-to-col (car contour-line)))
  832. (point))
  833. line-end))
  834. (unless (or (haskell-indent-open-structure start line-start)
  835. (haskell-indent-in-comment start line-start))
  836. (setq haskell-indent-info
  837. (haskell-indent-line-indentation line-start line-end
  838. end-visible curr-line-type
  839. haskell-indent-info)))))
  840. haskell-indent-info))
  841. (defun haskell-indent-find-matching-start (regexp limit &optional pred start)
  842. (let ((open (haskell-indent-open-structure limit (point))))
  843. (if open (setq limit (1+ open))))
  844. (unless start (setq start (point)))
  845. (when (re-search-backward regexp limit t)
  846. (let ((nestedcase (match-end 1))
  847. (outer (or (haskell-indent-in-string limit (point))
  848. (haskell-indent-in-comment limit (point))
  849. (haskell-indent-open-structure limit (point))
  850. (if (and pred (funcall pred start)) (point)))))
  851. (cond
  852. (outer
  853. (goto-char outer)
  854. (haskell-indent-find-matching-start regexp limit pred start))
  855. (nestedcase
  856. ;; Nested case.
  857. (and (haskell-indent-find-matching-start regexp limit pred)
  858. (haskell-indent-find-matching-start regexp limit pred start)))
  859. (t (point))))))
  860. (defun haskell-indent-filter-let-no-in (start)
  861. "Return non-nil if point is in front of a `let' that has no `in'.
  862. START is the position of the presumed `in'."
  863. ;; We're looking at either `in' or `let'.
  864. (when (looking-at "let")
  865. (ignore-errors
  866. (save-excursion
  867. (forward-word 1)
  868. (forward-comment (point-max))
  869. (if (looking-at "{")
  870. (progn
  871. (forward-sexp 1)
  872. (forward-comment (point-max))
  873. (< (point) start))
  874. ;; Use the layout rule to see whether this let is already closed
  875. ;; without an `in'.
  876. (let ((col (current-column)))
  877. (while (progn (forward-line 1) (haskell-indent-back-to-indentation)
  878. (< (point) start))
  879. (when (< (current-column) col)
  880. (setq col nil)
  881. (goto-char start)))
  882. (null col)))))))
  883. (defun haskell-indent-comment (open start)
  884. "Compute indent info for comments and text inside comments.
  885. OPEN is the start position of the comment in which point is."
  886. ;; Ideally we'd want to guess whether it's commented out code or
  887. ;; whether it's text. Instead, we'll assume it's text.
  888. (save-excursion
  889. (if (= open (point))
  890. ;; We're actually just in front of a comment: align with following
  891. ;; code or with comment on previous line.
  892. (let ((prev-line-info
  893. (cond
  894. ((eq (char-after) ?\{) nil) ;Align as if it were code.
  895. ((and (forward-comment -1)
  896. (> (line-beginning-position 3) open))
  897. ;; We're after another comment and there's no empty line
  898. ;; between us.
  899. (list (list (haskell-indent-point-to-col (point)))))
  900. (t nil)))) ;Else align as if it were code
  901. ;; Align with following code.
  902. (forward-comment (point-max))
  903. ;; There are several possible indentation points for this code-line,
  904. ;; but the only valid indentation point for the comment is the one
  905. ;; that the user will select for the code-line. Obviously we can't
  906. ;; know that, so we just assume that the code-line is already at its
  907. ;; proper place.
  908. ;; Strictly speaking "assume it's at its proper place" would mean
  909. ;; we'd just use (current-column), but since this is using info from
  910. ;; lines further down and it's common to reindent line-by-line,
  911. ;; we'll align not with the current indentation, but with the
  912. ;; one that auto-indentation "will" select.
  913. (append
  914. prev-line-info
  915. (let ((indent-info (save-excursion
  916. (haskell-indent-indentation-info start)))
  917. (col (current-column)))
  918. ;; Sort the indent-info so that the current indentation comes
  919. ;; out first.
  920. (setq indent-info
  921. (sort indent-info
  922. (lambda (x y)
  923. (<= (abs (- col (car x))) (abs (- col (car y)))))))
  924. indent-info)))
  925. ;; We really are inside a comment.
  926. (if (looking-at "-}")
  927. (progn
  928. (forward-char 2)
  929. (forward-comment -1)
  930. (list (list (1+ (haskell-indent-point-to-col (point))))))
  931. (let ((offset (if (looking-at "--?")
  932. (- (match-beginning 0) (match-end 0)))))
  933. (forward-line -1) ;Go to previous line.
  934. (haskell-indent-back-to-indentation)
  935. (if (< (point) start) (goto-char start))
  936. (list (list (if (looking-at comment-start-skip)
  937. (if offset
  938. (+ 2 offset (haskell-indent-point-to-col (point)))
  939. (haskell-indent-point-to-col (match-end 0)))
  940. (haskell-indent-point-to-col (point))))))))))
  941. (defcustom haskell-indent-thenelse 0
  942. "If non-nil, \"then\" and \"else\" are indented.
  943. This is necessary in the \"do\" layout under Haskell-98.
  944. See http://hackage.haskell.org/trac/haskell-prime/wiki/DoAndIfThenElse"
  945. :group 'haskell-indent
  946. :type 'integer)
  947. (defun haskell-indent-closing-keyword (start)
  948. (let ((open (save-excursion
  949. (haskell-indent-find-matching-start
  950. (case (char-after)
  951. (?i "\\<\\(?:\\(in\\)\\|let\\)\\>")
  952. (?o "\\<\\(?:\\(of\\)\\|case\\)\\>")
  953. (?t "\\<\\(?:\\(then\\)\\|if\\)\\>")
  954. (?e "\\<\\(?:\\(else\\)\\|if\\)\\>"))
  955. start
  956. (if (eq (char-after) ?i)
  957. ;; Filter out the `let's that have no `in'.
  958. 'haskell-indent-filter-let-no-in)))))
  959. ;; For a "hanging let/case/if at EOL" we should use a different
  960. ;; indentation scheme.
  961. (save-excursion
  962. (goto-char open)
  963. (if (haskell-indent-hanging-p)
  964. (setq open (haskell-indent-virtual-indentation start))))
  965. ;; FIXME: we should try and figure out if the `if' is in a `do' layout
  966. ;; before using haskell-indent-thenelse.
  967. (list (list (+ (if (memq (char-after) '(?t ?e)) haskell-indent-thenelse 0)
  968. (haskell-indent-point-to-col open))))))
  969. (defcustom haskell-indent-after-keywords
  970. '(("where" 2 0)
  971. ("of" 2)
  972. ("do" 2)
  973. ("in" 2 0)
  974. ("{" 2)
  975. "if"
  976. "then"
  977. "else"
  978. "let")
  979. "Keywords after which indentation should be indented by some offset.
  980. Each keyword info can have the following forms:
  981. KEYWORD | (KEYWORD OFFSET [OFFSET-HANGING])
  982. If absent OFFSET-HANGING defaults to OFFSET.
  983. If absent OFFSET defaults to `haskell-indent-offset'.
  984. OFFSET-HANGING is the offset to use in the case where the keyword
  985. is at the end of an otherwise-non-empty line."
  986. :group 'haskell-indent
  987. :type '(repeat (choice string
  988. (cons :tag "" (string :tag "keyword:")
  989. (cons :tag "" (integer :tag "offset")
  990. (choice (const nil)
  991. (list :tag ""
  992. (integer :tag "offset-pending"))))))))
  993. (defun haskell-indent-skip-lexeme-forward ()
  994. (and (zerop (skip-syntax-forward "w"))
  995. (skip-syntax-forward "_")
  996. (skip-syntax-forward "(")
  997. (skip-syntax-forward ")")))
  998. (defvar haskell-indent-inhibit-after-offset nil)
  999. (defun haskell-indent-offset-after-info ()
  1000. "Return the info from `haskell-indent-after-keywords' for keyword at point."
  1001. (let ((id (buffer-substring
  1002. (point)
  1003. (save-excursion
  1004. (haskell-indent-skip-lexeme-forward)
  1005. (point)))))
  1006. (or (assoc id haskell-indent-after-keywords)
  1007. (car (member id haskell-indent-after-keywords)))))
  1008. (defcustom haskell-indent-dont-hang '("(")
  1009. "Lexemes that should never be considered as hanging."
  1010. :group 'haskell-indent
  1011. :type '(repeat string))
  1012. (defun haskell-indent-hanging-p ()
  1013. ;; A Hanging keyword is one that's at the end of a line except it's not at
  1014. ;; the beginning of a line.
  1015. (not (or (= (current-column) (haskell-indent-current-indentation))
  1016. (save-excursion
  1017. (let ((lexeme
  1018. (buffer-substring
  1019. (point)
  1020. (progn (haskell-indent-skip-lexeme-forward) (point)))))
  1021. (or (member lexeme haskell-indent-dont-hang)
  1022. (> (line-end-position)
  1023. (progn (forward-comment (point-max)) (point)))))))))
  1024. (defun haskell-indent-after-keyword-column (offset-info start &optional default)
  1025. (unless offset-info
  1026. (setq offset-info (haskell-indent-offset-after-info)))
  1027. (unless default (setq default haskell-indent-offset))
  1028. (setq offset-info
  1029. (if haskell-indent-inhibit-after-offset '(0) (cdr-safe offset-info)))
  1030. (if (not (haskell-indent-hanging-p))
  1031. (haskell-indent-column+offset (current-column)
  1032. (or (car offset-info) default))
  1033. ;; The keyword is hanging at the end of the line.
  1034. (haskell-indent-column+offset
  1035. (haskell-indent-virtual-indentation start)
  1036. (or (cadr offset-info) (car offset-info) default))))
  1037. (defun haskell-indent-inside-paren (open)
  1038. ;; there is an open structure to complete
  1039. (if (looking-at "\\s)\\|[;,]")
  1040. ;; A close-paren or a , or ; can only correspond syntactically to
  1041. ;; the open-paren at `open'. So there is no ambiguity.
  1042. (progn
  1043. (if (or (and (eq (char-after) ?\;) (eq (char-after open) ?\())
  1044. (and (eq (char-after) ?\,) (eq (char-after open) ?\{)))
  1045. (message "Mismatched punctuation: `%c' in %c...%c"
  1046. (char-after) (char-after open)
  1047. (if (eq (char-after open) ?\() ?\) ?\})))
  1048. (save-excursion
  1049. (goto-char open)
  1050. (list (list
  1051. (if (haskell-indent-hanging-p)
  1052. (haskell-indent-virtual-indentation nil)
  1053. (haskell-indent-point-to-col open))))))
  1054. ;; There might still be layout within the open structure.
  1055. (let* ((end (point))
  1056. (basic-indent-info
  1057. ;; Anything else than a ) is subject to layout.
  1058. (if (looking-at "\\s.\\|\\$ ")
  1059. (haskell-indent-point-to-col open) ; align a punct with (
  1060. (let ((follow (save-excursion
  1061. (goto-char (1+ open))
  1062. (haskell-indent-skip-blanks-and-newlines-forward end)
  1063. (point))))
  1064. (if (= follow end)
  1065. (save-excursion
  1066. (goto-char open)
  1067. (haskell-indent-after-keyword-column nil nil 1))
  1068. (haskell-indent-point-to-col follow)))))
  1069. (open-column (haskell-indent-point-to-col open))
  1070. (contour-line (haskell-indent-contour-line (1+ open) end)))
  1071. (if (null contour-line)
  1072. (list (list basic-indent-info))
  1073. (let ((indent-info
  1074. (haskell-indent-layout-indent-info
  1075. (1+ open) contour-line)))
  1076. ;; Fix up indent info.
  1077. (let ((base-elem (assoc open-column indent-info)))
  1078. (if base-elem
  1079. (progn (setcar base-elem basic-indent-info)
  1080. (setcdr base-elem nil))
  1081. (setq indent-info
  1082. (append indent-info (list (list basic-indent-info)))))
  1083. indent-info))))))
  1084. (defun haskell-indent-virtual-indentation (start)
  1085. "Compute the \"virtual indentation\" of text at point.
  1086. The \"virtual indentation\" is the indentation that text at point would have
  1087. had, if it had been placed on its own line."
  1088. (let ((col (current-column))
  1089. (haskell-indent-inhibit-after-offset (haskell-indent-hanging-p)))
  1090. (if (save-excursion (skip-chars-backward " \t") (bolp))
  1091. ;; If the text is indeed on its own line, than the virtual indent is
  1092. ;; the current indentation.
  1093. col
  1094. ;; Else, compute the indentation that it would have had.
  1095. (let ((info (haskell-indent-indentation-info start))
  1096. (max -1))
  1097. ;; `info' is a list of possible indent points. Each indent point is
  1098. ;; assumed to correspond to a different parse. So we need to find
  1099. ;; the parse that corresponds to the case at hand (where there's no
  1100. ;; line break), which is assumed to always be the
  1101. ;; deepest indentation.
  1102. (dolist (x info)
  1103. (setq x (car x))
  1104. ;; Sometimes `info' includes the current indentation (or yet
  1105. ;; deeper) by mistake, because haskell-indent-indentation-info
  1106. ;; wasn't designed to be called on a piece of text that is not at
  1107. ;; BOL. So ignore points past `col'.
  1108. (if (and (> x max) (not (>= x col)))
  1109. (setq max x)))
  1110. ;; In case all the indent points are past `col', just use `col'.
  1111. (if (>= max 0) max col)))))
  1112. (defun haskell-indent-indentation-info (&optional start)
  1113. "Return a list of possible indentations for the current line.
  1114. These are then used by `haskell-indent-cycle'.
  1115. START if non-nil is a presumed start pos of the current definition."
  1116. (unless start (setq start (haskell-indent-start-of-def)))
  1117. (let (open contour-line)
  1118. (cond
  1119. ;; in string?
  1120. ((setq open (haskell-indent-in-string start (point)))
  1121. (list (list (+ (haskell-indent-point-to-col open)
  1122. (if (looking-at "\\\\") 0 1)))))
  1123. ;; in comment ?
  1124. ((setq open (haskell-indent-in-comment start (point)))
  1125. (haskell-indent-comment open start))
  1126. ;; Closing the declaration part of a `let' or the test exp part of a case.
  1127. ((looking-at "\\(?:in\\|of\\|then\\|else\\)\\>")
  1128. (haskell-indent-closing-keyword start))
  1129. ;; Right after a special keyword.
  1130. ((save-excursion
  1131. (forward-comment (- (point-max)))
  1132. (when (and (not (zerop (skip-syntax-backward "w")))
  1133. (setq open (haskell-indent-offset-after-info)))
  1134. (list (list (haskell-indent-after-keyword-column open start))))))
  1135. ;; open structure? ie ( { [
  1136. ((setq open (haskell-indent-open-structure start (point)))
  1137. (haskell-indent-inside-paren open))
  1138. ;; full indentation
  1139. ((setq contour-line (haskell-indent-contour-line start (point)))
  1140. (haskell-indent-layout-indent-info start contour-line))
  1141. (t
  1142. ;; simple contour just one indentation at start
  1143. (list (list (if (and (eq haskell-literate 'bird)
  1144. (eq (haskell-indent-point-to-col start) 1))
  1145. ;; for a Bird style literate script put default offset
  1146. ;; in the case of no indentation
  1147. (1+ haskell-indent-literate-Bird-default-offset)
  1148. (haskell-indent-point-to-col start))))))))
  1149. (defvar haskell-indent-last-info nil)
  1150. (defun haskell-indent-cycle ()
  1151. "Indentation cycle.
  1152. We stay in the cycle as long as the TAB key is pressed."
  1153. (interactive "*")
  1154. (if (and haskell-literate
  1155. (not (haskell-indent-within-literate-code)))
  1156. ;; use the ordinary tab for text...
  1157. (funcall (default-value 'indent-line-function))
  1158. (let ((marker (if (> (current-column) (haskell-indent-current-indentation))
  1159. (point-marker)))
  1160. (bol (progn (beginning-of-line) (point))))
  1161. (haskell-indent-back-to-indentation)
  1162. (unless (and (eq last-command this-command)
  1163. (eq bol (car haskell-indent-last-info)))
  1164. (save-excursion
  1165. (setq haskell-indent-last-info
  1166. (list bol (haskell-indent-indentation-info) 0 0))))
  1167. (let* ((il (nth 1 haskell-indent-last-info))
  1168. (index (nth 2 haskell-indent-last-info))
  1169. (last-insert-length (nth 3 haskell-indent-last-info))
  1170. (indent-info (nth index il)))
  1171. (haskell-indent-line-to (car indent-info)) ; insert indentation
  1172. (delete-char last-insert-length)
  1173. (setq last-insert-length 0)
  1174. (let ((text (cdr indent-info)))
  1175. (if text
  1176. (progn
  1177. (insert text)
  1178. (setq last-insert-length (length text)))))
  1179. (setq haskell-indent-last-info
  1180. (list bol il (% (1+ index) (length il)) last-insert-length))
  1181. (if (= (length il) 1)
  1182. (message "Sole indentation")
  1183. (message "Indent cycle (%d)..." (length il)))
  1184. (if marker
  1185. (goto-char (marker-position marker)))))))
  1186. (defun haskell-indent-region (start end)
  1187. (error "Auto-reindentation of a region is not supported"))
  1188. ;;; alignment functions
  1189. (defun haskell-indent-shift-columns (dest-column region-stack)
  1190. "Shift columns in REGION-STACK to go to DEST-COLUMN.
  1191. Elements of the stack are pairs of points giving the start and end
  1192. of the regions to move."
  1193. (let (reg col diffcol reg-end)
  1194. (while (setq reg (pop region-stack))
  1195. (setq reg-end (copy-marker (cdr reg)))
  1196. (goto-char (car reg))
  1197. (setq col (current-column))
  1198. (setq diffcol (- dest-column col))
  1199. (if (not (zerop diffcol))
  1200. (catch 'end-of-buffer
  1201. (while (<= (point) (marker-position reg-end))
  1202. (if (< diffcol 0)
  1203. (backward-delete-char-untabify (- diffcol) nil)
  1204. (insert-char ?\ diffcol))
  1205. (end-of-line 2) ; should be (forward-line 1)
  1206. (if (eobp) ; but it adds line at the end...
  1207. (throw 'end-of-buffer nil))
  1208. (move-to-column col)))))))
  1209. (defun haskell-indent-align-def (p-arg type)
  1210. "Align guards or rhs within the current definition before point.
  1211. If P-ARG is t align all defs up to the mark.
  1212. TYPE is either 'guard or 'rhs."
  1213. (save-excursion
  1214. (let (start-block end-block
  1215. (maxcol (if (eq type 'rhs) haskell-indent-rhs-align-column 0))
  1216. contour sep defname defnamepos
  1217. defcol pos lastpos
  1218. regstack eqns-start start-found)
  1219. ;; find the starting and ending boundary points for alignment
  1220. (if p-arg
  1221. (if (mark) ; aligning everything in the region
  1222. (progn
  1223. (when (> (mark) (point)) (exchange-point-and-mark))
  1224. (setq start-block
  1225. (save-excursion
  1226. (goto-char (mark))
  1227. (line-beginning-position)))
  1228. (setq end-block
  1229. (progn (if (haskell-indent-bolp)
  1230. (haskell-indent-forward-line -1))
  1231. (line-end-position))))
  1232. (error "The mark is not set for aligning definitions"))
  1233. ;; aligning the current definition
  1234. (setq start-block (haskell-indent-start-of-def))
  1235. (setq end-block (line-end-position)))
  1236. ;; find the start of the current valdef using the contour line
  1237. ;; in reverse order because we need the nearest one from the end
  1238. (setq contour
  1239. (reverse (haskell-indent-contour-line start-block end-block)))
  1240. (setq pos (car contour)) ; keep the start of the first contour
  1241. ;; find the nearest start of a definition
  1242. (while (and (not defname) contour)
  1243. (goto-char (pop contour))
  1244. (if (haskell-indent-open-structure start-block (point))
  1245. nil
  1246. (setq sep (haskell-indent-separate-valdef (point) end-block))
  1247. (if (nth 5 sep) ; is there a rhs?
  1248. (progn (setq defnamepos (nth 0 sep))
  1249. (setq defname (nth 1 sep))))))
  1250. ;; start building the region stack
  1251. (if defnamepos
  1252. (progn ; there is a valdef
  1253. ;; find the start of each equation or guard
  1254. (if p-arg ; when indenting a region
  1255. ;; accept any start of id or pattern as def name
  1256. (setq defname "\\<\\|("))
  1257. (setq defcol (haskell-indent-point-to-col defnamepos))
  1258. (goto-char pos)
  1259. (setq end-block (line-end-position))
  1260. (catch 'top-of-buffer
  1261. (while (and (not start-found)
  1262. (>= (point) start-block))
  1263. (if (<= (haskell-indent-current-indentation) defcol)
  1264. (progn
  1265. (move-to-column defcol)
  1266. (if (and (looking-at defname) ; start of equation
  1267. (not (haskell-indent-open-structure start-block (point))))
  1268. (push (cons (point) 'eqn) eqns-start)
  1269. ;; found a less indented point not starting an equation
  1270. (setq start-found t)))
  1271. ;; more indented line
  1272. (haskell-indent-back-to-indentation)
  1273. (if (and (eq (haskell-indent-type-at-point) 'guard) ; start of a guard
  1274. (not (haskell-indent-open-structure start-block (point))))
  1275. (push (cons (point) 'gd) eqns-start)))
  1276. (if (bobp)
  1277. (throw 'top-of-buffer nil)
  1278. (haskell-indent-backward-to-indentation 1))))
  1279. ;; remove the spurious guards before the first equation
  1280. (while (and eqns-start (eq (cdar eqns-start) 'gd))
  1281. (pop eqns-start))
  1282. ;; go through each equation to find the region to indent
  1283. (while eqns-start
  1284. (let ((eqn (caar eqns-start)))
  1285. (setq lastpos (if (cdr eqns-start)
  1286. (save-excursion
  1287. (goto-char (caadr eqns-start))
  1288. (haskell-indent-forward-line -1)
  1289. (line-end-position))
  1290. end-block))
  1291. (setq sep (haskell-indent-separate-valdef eqn lastpos)))
  1292. (if (eq type 'guard)
  1293. (setq pos (nth 3 sep))
  1294. ;; check if what follows a rhs sign is more indented or not
  1295. (let ((rhs (nth 5 sep))
  1296. (aft-rhs (nth 6 sep)))
  1297. (if (and rhs aft-rhs
  1298. (> (haskell-indent-point-to-col rhs)
  1299. (haskell-indent-point-to-col aft-rhs)))
  1300. (setq pos aft-rhs)
  1301. (setq pos rhs))))
  1302. (if pos
  1303. (progn ; update region stack
  1304. (push (cons pos (or lastpos pos)) regstack)
  1305. (setq maxcol ; find the highest column number
  1306. (max maxcol
  1307. (progn ;find the previous non-empty column
  1308. (goto-char pos)
  1309. (skip-chars-backward
  1310. " \t"
  1311. (line-beginning-position))
  1312. (if (haskell-indent-bolp)
  1313. ;;if on an empty prefix
  1314. (haskell-indent-point-to-col pos) ;keep original indent
  1315. (1+ (haskell-indent-point-to-col (point)))))))))
  1316. (pop eqns-start))
  1317. ;; now shift according to the region stack
  1318. (if regstack
  1319. (haskell-indent-shift-columns maxcol regstack)))))))
  1320. (defun haskell-indent-align-guards-and-rhs (start end)
  1321. "Align the guards and rhs of functions in the region, which must be active."
  1322. ;; The `start' and `end' args are dummys right now: they're just there so
  1323. ;; we can use the "r" interactive spec which properly signals an error.
  1324. (interactive "*r")
  1325. (haskell-indent-align-def t 'guard)
  1326. (haskell-indent-align-def t 'rhs))
  1327. ;;; insertion functions
  1328. (defun haskell-indent-insert-equal ()
  1329. "Insert an = sign and align the previous rhs of the current function."
  1330. (interactive "*")
  1331. (if (or (haskell-indent-bolp)
  1332. (/= (preceding-char) ?\ ))
  1333. (insert ?\ ))
  1334. (insert "= ")
  1335. (haskell-indent-align-def (haskell-indent-mark-active) 'rhs))
  1336. (defun haskell-indent-insert-guard (&optional text)
  1337. "Insert and align a guard sign (|) followed by optional TEXT.
  1338. Alignment works only if all guards are to the south-east of their |."
  1339. (interactive "*")
  1340. (let ((pc (if (haskell-indent-bolp) ?\012
  1341. (preceding-char)))
  1342. (pc1 (or (char-after (- (point) 2)) 0)))
  1343. ;; check what guard to insert depending on the previous context
  1344. (if (= pc ?\ ) ; x = any char other than blank or |
  1345. (if (/= pc1 ?\|)
  1346. (insert "| ") ; after " x"
  1347. ()) ; after " |"
  1348. (if (= pc ?\|)
  1349. (if (= pc1 ?\|)
  1350. (insert " | ") ; after "||"
  1351. (insert " ")) ; after "x|"
  1352. (insert " | "))) ; general case
  1353. (if text (insert text))
  1354. (haskell-indent-align-def (haskell-indent-mark-active) 'guard)))
  1355. (defun haskell-indent-insert-otherwise ()
  1356. "Insert a guard sign (|) followed by `otherwise'.
  1357. Also align the previous guards of the current function."
  1358. (interactive "*")
  1359. (haskell-indent-insert-guard "otherwise")
  1360. (haskell-indent-insert-equal))
  1361. (defun haskell-indent-insert-where ()
  1362. "Insert a where keyword at point and indent resulting line.
  1363. One indentation cycle is used."
  1364. (interactive "*")
  1365. (insert "where ")
  1366. (haskell-indent-cycle))
  1367. ;;; haskell-indent-mode
  1368. (defvar haskell-indent-mode nil
  1369. "Non-nil if the semi-intelligent Haskell indentation mode is in effect.")
  1370. (make-variable-buffer-local 'haskell-indent-mode)
  1371. (defvar haskell-indent-map
  1372. (let ((map (make-sparse-keymap)))
  1373. ;; Removed: remapping DEL seems a bit naughty --SDM
  1374. ;; (define-key map "\177" 'backward-delete-char-untabify)
  1375. ;; The binding to TAB is already handled by indent-line-function. --Stef
  1376. ;; (define-key map "\t" 'haskell-indent-cycle)
  1377. (define-key map [?\C-c ?\C-=] 'haskell-indent-insert-equal)
  1378. (define-key map [?\C-c ?\C-|] 'haskell-indent-insert-guard)
  1379. ;; Alternate binding, in case C-c C-| is too inconvenient to type.
  1380. ;; Duh, C-g is a special key, let's not use it here.
  1381. ;; (define-key map [?\C-c ?\C-g] 'haskell-indent-insert-guard)
  1382. (define-key map [?\C-c ?\C-o] 'haskell-indent-insert-otherwise)
  1383. (define-key map [?\C-c ?\C-w] 'haskell-indent-insert-where)
  1384. (define-key map [?\C-c ?\C-.] 'haskell-indent-align-guards-and-rhs)
  1385. (define-key map [?\C-c ?\C->] 'haskell-indent-put-region-in-literate)
  1386. map))
  1387. (defun turn-on-haskell-indent ()
  1388. "Turn on ``intelligent'' Haskell indentation mode."
  1389. (set (make-local-variable 'indent-line-function) 'haskell-indent-cycle)
  1390. (set (make-local-variable 'indent-region-function) 'haskell-indent-region)
  1391. (setq haskell-indent-mode t)
  1392. ;; Activate our keymap.
  1393. (let ((map (current-local-map)))
  1394. (while (and map (not (eq map haskell-indent-map)))
  1395. (setq map (keymap-parent map)))
  1396. (if map
  1397. ;; haskell-indent-map is already active: nothing to do.
  1398. nil
  1399. ;; Put our keymap on top of the others. We could also put it in
  1400. ;; second place, or in a minor-mode. The minor-mode approach would be
  1401. ;; easier, but it's harder for the user to override it. This approach
  1402. ;; is the closest in behavior compared to the previous code that just
  1403. ;; used a bunch of local-set-key.
  1404. (set-keymap-parent haskell-indent-map (current-local-map))
  1405. ;; Protect our keymap.
  1406. (setq map (make-sparse-keymap))
  1407. (set-keymap-parent map haskell-indent-map)
  1408. (use-local-map map)))
  1409. (run-hooks 'haskell-indent-hook))
  1410. (defun turn-off-haskell-indent ()
  1411. "Turn off ``intelligent'' Haskell indentation mode."
  1412. (kill-local-variable 'indent-line-function)
  1413. ;; Remove haskell-indent-map from the local map.
  1414. (let ((map (current-local-map)))
  1415. (while map
  1416. (let ((parent (keymap-parent map)))
  1417. (if (eq haskell-indent-map parent)
  1418. (set-keymap-parent map (keymap-parent parent))
  1419. (setq map parent)))))
  1420. (setq haskell-indent-mode nil))
  1421. ;; Put this minor mode on the global minor-mode-alist.
  1422. (or (assq 'haskell-indent-mode (default-value 'minor-mode-alist))
  1423. (setq-default minor-mode-alist
  1424. (append (default-value 'minor-mode-alist)
  1425. '((haskell-indent-mode " Ind")))))
  1426. ;;;###autoload
  1427. (defun haskell-indent-mode (&optional arg)
  1428. "``Intelligent'' Haskell indentation mode.
  1429. This deals with the layout rule of Haskell.
  1430. \\[haskell-indent-cycle] starts the cycle which proposes new
  1431. possibilities as long as the TAB key is pressed. Any other key
  1432. or mouse click terminates the cycle and is interpreted except for
  1433. RET which merely exits the cycle.
  1434. Other special keys are:
  1435. \\[haskell-indent-insert-equal]
  1436. inserts an =
  1437. \\[haskell-indent-insert-guard]
  1438. inserts an |
  1439. \\[haskell-indent-insert-otherwise]
  1440. inserts an | otherwise =
  1441. these functions also align the guards and rhs of the current definition
  1442. \\[haskell-indent-insert-where]
  1443. inserts a where keyword
  1444. \\[haskell-indent-align-guards-and-rhs]
  1445. aligns the guards and rhs of the region
  1446. \\[haskell-indent-put-region-in-literate]
  1447. makes the region a piece of literate code in a literate script
  1448. Invokes `haskell-indent-hook' if not nil."
  1449. (interactive "P")
  1450. (setq haskell-indent-mode
  1451. (if (null arg) (not haskell-indent-mode)
  1452. (> (prefix-numeric-value arg) 0)))
  1453. (if haskell-indent-mode
  1454. (turn-on-haskell-indent)
  1455. (turn-off-haskell-indent)))
  1456. (provide 'haskell-indent)
  1457. ;; arch-tag: e4e5e90a-12e2-4002-b5cb-7b2375710013
  1458. ;;; haskell-indent.el ends here