/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

Large files are truncated click here to view the full file

  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. (hask