Skip to content

Commit 62aafde

Browse files
committed
Merge pull request #1098 from mrBliss/fix-1094
Follow comma style when arranging a Cabal section
2 parents fc9c57f + 5284059 commit 62aafde

File tree

2 files changed

+165
-10
lines changed

2 files changed

+165
-10
lines changed

haskell-cabal.el

Lines changed: 47 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -569,13 +569,28 @@ resulting buffer-content"
569569
(haskell-cabal-add-indentation (- ,old-l1-indent
570570
,new-l1-indent))))))))
571571

572+
(defun haskell-cabal-comma-separatorp (pos)
573+
"Return non-nil when the char at POS is a comma separator.
574+
Characters that are not a comma, or commas inside a commment or
575+
string, are not comma separators."
576+
(when (eq (char-after pos) ?,)
577+
(let ((ss (syntax-ppss pos)))
578+
(not
579+
(or
580+
;; inside a string
581+
(nth 3 ss)
582+
;; inside a comment
583+
(nth 4 ss))))))
584+
585+
572586
(defun haskell-cabal-strip-list ()
573-
"strip commas from comma-seperated list"
587+
"Strip commas from a comma-separated list."
574588
(goto-char (point-min))
575-
;; split list items on single line
589+
;; split list items on single line
576590
(while (re-search-forward
577-
"\\([^ \t,\n]\\)[ \t]*,[ \t]*\\([^ \t,\n]\\)" nil t)
578-
(replace-match "\\1\n\\2" nil nil))
591+
"\\([^ \t,\n]\\)[ \t]*\\(,\\)[ \t]*\\([^ \t,\n]\\)" nil t)
592+
(when (haskell-cabal-comma-separatorp (match-beginning 2))
593+
(replace-match "\\1\n\\3" nil nil)))
579594
(goto-char (point-min))
580595
(while (re-search-forward "^\\([ \t]*\\),\\([ \t]*\\)" nil t)
581596
(replace-match "" nil nil))
@@ -586,7 +601,7 @@ resulting buffer-content"
586601
(haskell-cabal-each-line (haskell-cabal-chomp-line)))
587602

588603
(defun haskell-cabal-listify ()
589-
"Add commas so that buffer contains a comma-seperated list"
604+
"Add commas so that the buffer contains a comma-seperated list"
590605
(cl-case haskell-cabal-list-comma-position
591606
('before
592607
(goto-char (point-min))
@@ -605,14 +620,36 @@ resulting buffer-content"
605620
(insert ",")
606621
(beginning-of-line))))))
607622

623+
(defun haskell-cabal-comma-separatedp ()
624+
"Return non-nil when the current buffer contains a comma-separated list.
625+
When the buffer contains at least one comma separator (checked
626+
with `haskell-cabal-comma-separatorp'), the buffer is considered
627+
to be a comma-separated list."
628+
(let ((comma-separatedp nil))
629+
(goto-char (point-min))
630+
(while (and (not comma-separatedp)
631+
(search-forward "," (point-max) t))
632+
(when (haskell-cabal-comma-separatorp (match-beginning 0))
633+
(setq comma-separatedp t))
634+
;; Make sure we don't find the same comma every time
635+
(forward-char 1))
636+
comma-separatedp))
608637

609638

610639
(defmacro haskell-cabal-with-cs-list (&rest funs)
611-
"format buffer so that each line contains a list element "
612-
`(progn
613-
(save-excursion (haskell-cabal-strip-list))
614-
(unwind-protect (progn ,@funs)
615-
(haskell-cabal-listify))))
640+
"Format the buffer so that each line contains a list element.
641+
Keep the lines comma-separated if and only if they were in the
642+
first place."
643+
(let ((comma-separatedp (make-symbol "comma-separatedp")))
644+
`(let ((,comma-separatedp
645+
(save-excursion
646+
(prog1
647+
(haskell-cabal-comma-separatedp)
648+
(haskell-cabal-strip-list)))))
649+
(unwind-protect (progn ,@funs)
650+
;; Only reinsert commas when it already was comma-separated.
651+
(when ,comma-separatedp
652+
(haskell-cabal-listify))))))
616653

617654

618655
(defun haskell-cabal-sort-lines-key-fun ()

tests/haskell-cabal-tests.el

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,124 @@
5050
(haskell-cabal-previous-subsection)
5151
(haskell-cabal-previous-section))))
5252

53+
(ert-deftest haskell-cabal-subsection-arrange-lines-keep-commas ()
54+
(should (with-temp-buffer
55+
(insert "Executable bin-1
56+
Main-Is: TestParsing.hs
57+
Build-Depends: base,
58+
bytestring,
59+
directory,
60+
filepath,
61+
text
62+
Ghc-Options: -O -Wall
63+
")
64+
(haskell-cabal-mode)
65+
(goto-char (point-min))
66+
(search-forward "Build-Depends:")
67+
(haskell-cabal-subsection-arrange-lines)
68+
(string= (buffer-string)
69+
"Executable bin-1
70+
Main-Is: TestParsing.hs
71+
Build-Depends: base
72+
, bytestring
73+
, directory
74+
, filepath
75+
, text
76+
Ghc-Options: -O -Wall
77+
"))))
78+
79+
(ert-deftest haskell-cabal-subsection-arrange-lines-no-commas ()
80+
(should (with-temp-buffer
81+
(insert "Executable bin-1
82+
Main-Is: TestParsing.hs
83+
Other-Modules: Some.Module
84+
Some.Other.Other.Module
85+
Some.Other.Module
86+
")
87+
(haskell-cabal-mode)
88+
(goto-char (point-min))
89+
(search-forward "Other-Modules:")
90+
(haskell-cabal-subsection-arrange-lines)
91+
(string= (buffer-string)
92+
"Executable bin-1
93+
Main-Is: TestParsing.hs
94+
Other-Modules: Some.Module
95+
Some.Other.Module
96+
Some.Other.Other.Module
97+
"))))
98+
99+
100+
(ert-deftest haskell-cabal-subsection-arrange-lines-quoted-items ()
101+
(should (with-temp-buffer
102+
(insert "Executable bin-1
103+
Main-Is: TestParsing.hs
104+
GHC-Options: -fprof-auto \"-with-rtsopts=-N -p -s -h -i0.1\"
105+
")
106+
(haskell-cabal-mode)
107+
(goto-char (point-min))
108+
(search-forward "GHC-Options:")
109+
(haskell-cabal-subsection-arrange-lines)
110+
(string= (buffer-string)
111+
"Executable bin-1
112+
Main-Is: TestParsing.hs
113+
GHC-Options: -fprof-auto \"-with-rtsopts=-N -p -s -h -i0.1\"
114+
"))))
115+
116+
(ert-deftest haskell-cabal-subsection-arrange-lines-no-commas-quoted-comma ()
117+
(should (with-temp-buffer
118+
(insert "Executable bin-1
119+
Main-Is: TestParsing.hs
120+
GHC-Options: -Wall -fprof-auto \"foo, bar\"
121+
")
122+
(haskell-cabal-mode)
123+
(goto-char (point-min))
124+
(search-forward "GHC-Options:")
125+
(haskell-cabal-subsection-arrange-lines)
126+
(string= (buffer-string)
127+
"Executable bin-1
128+
Main-Is: TestParsing.hs
129+
GHC-Options: -Wall -fprof-auto \"foo, bar\"
130+
"))))
131+
132+
(ert-deftest haskell-cabal-subsection-arrange-lines-commas-quoted-comma ()
133+
(should (with-temp-buffer
134+
(insert "Executable bin-1
135+
Main-Is: TestParsing.hs
136+
GHC-Options: -Wall, -fprof-auto \"foo, bar\"
137+
")
138+
(haskell-cabal-mode)
139+
(goto-char (point-min))
140+
(search-forward "GHC-Options:")
141+
(haskell-cabal-subsection-arrange-lines)
142+
(string= (buffer-string)
143+
"Executable bin-1
144+
Main-Is: TestParsing.hs
145+
GHC-Options: -Wall
146+
, -fprof-auto \"foo, bar\"
147+
"))))
148+
149+
(ert-deftest haskell-cabal-subsection-arrange-lines-comma-in-commment ()
150+
(should (with-temp-buffer
151+
(insert "Executable bin-1
152+
Main-Is: TestParsing.hs
153+
Other-Modules: Some.Module
154+
Some.Other.Other.Module
155+
Some.Other.Module
156+
-- Foo, bar
157+
")
158+
(haskell-cabal-mode)
159+
(goto-char (point-min))
160+
(search-forward "Other-Modules:")
161+
(haskell-cabal-subsection-arrange-lines)
162+
(string= (buffer-string)
163+
"Executable bin-1
164+
Main-Is: TestParsing.hs
165+
Other-Modules: Some.Module
166+
Some.Other.Module
167+
Some.Other.Other.Module
168+
-- Foo, bar
169+
"))))
170+
53171
(provide 'haskell-cabal-tests)
54172

55173
;;; haskell-cabal-tests.el ends here

0 commit comments

Comments
 (0)