Skip to content

Commit 19872a2

Browse files
committed
Detect and respect the comma style of a section
Previously, `haskell-cabal-list-comma-position' was always used when calling `haskell-cabal-subsection-arrange-lines'. In #1098, `haskell-cabal-list-comma-position' was respected unless the no commas were found. Instead of respecting `haskell-cabal-list-comma-position', detect the currently used style and respect it when rearranging the section. Possible styles: before: a comma at the start of each line (except the first), e.g. Foo , Bar after: a comma at the end of each line (except the last), e.g. Foo, Bar single: everything on a single line, but comma-separated, e.g. Foo, Bar nil: no commas, e.g. Foo Bar If the styles are mixed, the position of the first comma determines the style.
1 parent 62aafde commit 19872a2

File tree

2 files changed

+148
-48
lines changed

2 files changed

+148
-48
lines changed

haskell-cabal.el

Lines changed: 62 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -582,27 +582,56 @@ string, are not comma separators."
582582
;; inside a comment
583583
(nth 4 ss))))))
584584

585+
(defun haskell-cabal-strip-list-and-detect-style ()
586+
"Strip commas from a comma-separated list.
587+
Detect and return the comma style. The possible options are:
585588
586-
(defun haskell-cabal-strip-list ()
587-
"Strip commas from a comma-separated list."
588-
(goto-char (point-min))
589-
;; split list items on single line
590-
(while (re-search-forward
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)))
594-
(goto-char (point-min))
595-
(while (re-search-forward "^\\([ \t]*\\),\\([ \t]*\\)" nil t)
596-
(replace-match "" nil nil))
597-
(goto-char (point-min))
598-
(while (re-search-forward ",[ \t]*$" nil t)
599-
(replace-match "" nil nil))
600-
(goto-char (point-min))
601-
(haskell-cabal-each-line (haskell-cabal-chomp-line)))
589+
before: a comma at the start of each line (except the first), e.g.
590+
Foo
591+
, Bar
592+
593+
after: a comma at the end of each line (except the last), e.g.
594+
Foo,
595+
Bar
596+
597+
single: everything on a single line, but comma-separated, e.g.
598+
Foo, Bar
599+
600+
nil: no commas, e.g.
601+
Foo Bar
602+
603+
If the styles are mixed, the position of the first comma
604+
determines the style."
605+
(let (comma-style)
606+
;; split list items on single line
607+
(goto-char (point-min))
608+
(while (re-search-forward
609+
"\\([^ \t,\n]\\)[ \t]*\\(,\\)[ \t]*\\([^ \t,\n]\\)" nil t)
610+
(when (haskell-cabal-comma-separatorp (match-beginning 2))
611+
(setq comma-style 'single)
612+
(replace-match "\\1\n\\3" nil nil)))
613+
;; remove commas before
614+
(goto-char (point-min))
615+
(while (re-search-forward "^\\([ \t]*\\),\\([ \t]*\\)" nil t)
616+
(setq comma-style 'before)
617+
(replace-match "" nil nil))
618+
;; remove trailing commas
619+
(goto-char (point-min))
620+
(while (re-search-forward ",[ \t]*$" nil t)
621+
(unless (eq comma-style 'before)
622+
(setq comma-style 'after))
623+
(replace-match "" nil nil))
624+
(goto-char (point-min))
602625

603-
(defun haskell-cabal-listify ()
604-
"Add commas so that the buffer contains a comma-seperated list"
605-
(cl-case haskell-cabal-list-comma-position
626+
(haskell-cabal-each-line (haskell-cabal-chomp-line))
627+
comma-style))
628+
629+
(defun haskell-cabal-listify (comma-style)
630+
"Add commas so that the buffer contains a comma-separated list.
631+
Respect the COMMA-STYLE, see
632+
`haskell-cabal-strip-list-and-detect-style' for the possible
633+
styles."
634+
(cl-case comma-style
606635
('before
607636
(goto-char (point-min))
608637
(while (haskell-cabal-ignore-line-p) (forward-line))
@@ -618,38 +647,25 @@ string, are not comma separators."
618647
(forward-line -1)
619648
(end-of-line)
620649
(insert ",")
621-
(beginning-of-line))))))
622-
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))
637-
650+
(beginning-of-line))))
651+
('single
652+
(goto-char (point-min))
653+
(while (not (eobp))
654+
(end-of-line)
655+
(unless (eobp)
656+
(insert ", ")
657+
(delete-char 1)
658+
(just-one-space))))))
638659

639660
(defmacro haskell-cabal-with-cs-list (&rest funs)
640661
"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
662+
Respect the comma style."
663+
(let ((comma-style (make-symbol "comma-style")))
664+
`(let ((,comma-style
645665
(save-excursion
646-
(prog1
647-
(haskell-cabal-comma-separatedp)
648-
(haskell-cabal-strip-list)))))
666+
(haskell-cabal-strip-list-and-detect-style))))
649667
(unwind-protect (progn ,@funs)
650-
;; Only reinsert commas when it already was comma-separated.
651-
(when ,comma-separatedp
652-
(haskell-cabal-listify))))))
668+
(haskell-cabal-listify ,comma-style)))))
653669

654670

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

tests/haskell-cabal-tests.el

Lines changed: 86 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,16 +50,42 @@
5050
(haskell-cabal-previous-subsection)
5151
(haskell-cabal-previous-section))))
5252

53-
(ert-deftest haskell-cabal-subsection-arrange-lines-keep-commas ()
53+
(ert-deftest haskell-cabal-subsection-arrange-lines-keep-trailing-commas ()
5454
(should (with-temp-buffer
5555
(insert "Executable bin-1
5656
Main-Is: TestParsing.hs
57+
Build-Depends: base,
58+
bytestring,
59+
filepath,
60+
directory,
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
5771
Build-Depends: base,
5872
bytestring,
5973
directory,
6074
filepath,
6175
text
6276
Ghc-Options: -O -Wall
77+
"))))
78+
79+
(ert-deftest haskell-cabal-subsection-arrange-lines-keep-commas-before ()
80+
(should (with-temp-buffer
81+
(insert "Executable bin-1
82+
Main-Is: TestParsing.hs
83+
Build-Depends: base
84+
, bytestring
85+
, filepath
86+
, directory
87+
, text
88+
Ghc-Options: -O -Wall
6389
")
6490
(haskell-cabal-mode)
6591
(goto-char (point-min))
@@ -96,6 +122,29 @@
96122
Some.Other.Other.Module
97123
"))))
98124

125+
(ert-deftest haskell-cabal-subsection-arrange-lines-mixed-styles ()
126+
(should (with-temp-buffer
127+
(insert "Executable bin-1
128+
Main-Is: TestParsing.hs
129+
Build-Depends: base
130+
, bytestring,
131+
filepath, directory, text
132+
Ghc-Options: -O -Wall
133+
")
134+
(haskell-cabal-mode)
135+
(goto-char (point-min))
136+
(search-forward "Build-Depends:")
137+
(haskell-cabal-subsection-arrange-lines)
138+
(string= (buffer-string)
139+
"Executable bin-1
140+
Main-Is: TestParsing.hs
141+
Build-Depends: base
142+
, bytestring
143+
, directory
144+
, filepath
145+
, text
146+
Ghc-Options: -O -Wall
147+
"))))
99148

100149
(ert-deftest haskell-cabal-subsection-arrange-lines-quoted-items ()
101150
(should (with-temp-buffer
@@ -129,11 +178,46 @@
129178
GHC-Options: -Wall -fprof-auto \"foo, bar\"
130179
"))))
131180

132-
(ert-deftest haskell-cabal-subsection-arrange-lines-commas-quoted-comma ()
181+
(ert-deftest haskell-cabal-subsection-arrange-lines-single-line-quoted-comma ()
133182
(should (with-temp-buffer
134183
(insert "Executable bin-1
135184
Main-Is: TestParsing.hs
185+
GHC-Options: -Wall,-fprof-auto \"foo, bar\"
186+
")
187+
(haskell-cabal-mode)
188+
(goto-char (point-min))
189+
(search-forward "GHC-Options:")
190+
(haskell-cabal-subsection-arrange-lines)
191+
(string= (buffer-string)
192+
"Executable bin-1
193+
Main-Is: TestParsing.hs
136194
GHC-Options: -Wall, -fprof-auto \"foo, bar\"
195+
"))))
196+
197+
(ert-deftest haskell-cabal-subsection-arrange-lines-trailing-commas-quoted-comma ()
198+
(should (with-temp-buffer
199+
(insert "Executable bin-1
200+
Main-Is: TestParsing.hs
201+
GHC-Options: -Wall,
202+
-fprof-auto \"foo, bar\"
203+
")
204+
(haskell-cabal-mode)
205+
(goto-char (point-min))
206+
(search-forward "GHC-Options:")
207+
(haskell-cabal-subsection-arrange-lines)
208+
(string= (buffer-string)
209+
"Executable bin-1
210+
Main-Is: TestParsing.hs
211+
GHC-Options: -Wall,
212+
-fprof-auto \"foo, bar\"
213+
"))))
214+
215+
(ert-deftest haskell-cabal-subsection-arrange-lines-commas-before-quoted-comma ()
216+
(should (with-temp-buffer
217+
(insert "Executable bin-1
218+
Main-Is: TestParsing.hs
219+
GHC-Options: -Wall
220+
, -fprof-auto \"foo, bar\"
137221
")
138222
(haskell-cabal-mode)
139223
(goto-char (point-min))

0 commit comments

Comments
 (0)