Skip to content

Commit e589a79

Browse files
committed
Merge pull request #986 from bergey/scc
Clean up SCC code
2 parents a8e924b + d8d61af commit e589a79

File tree

3 files changed

+83
-15
lines changed

3 files changed

+83
-15
lines changed

doc/haskell-mode.texi

+9
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,15 @@ and available packages.
278278
@image{anim/company-mode-import-statement}
279279
@end ifhtml
280280

281+
@section Profiling and Debugging support
282+
283+
When profiling code with GHC, it is often useful to add
284+
@uref{https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/profiling.html#cost-centres,
285+
cost centres} by hand. These allow finer-grained information about
286+
program behavior. @code{haskell-mode} provides the function
287+
@code{haskell-mode-toggle-scc-at-point} to make this more convenient.
288+
It will remove an SCC annotation at point if one is present, or add
289+
one if point is over whitespace. By default it is bound to @kbd{C-c C-s}.
281290

282291
@node Unicode support
283292
@chapter Unicode support

haskell-mode.el

+46-14
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ be set to the preferred literate style."
202202
(define-key map (kbd "C-c C-v") 'haskell-mode-enable-process-minor-mode)
203203
(define-key map (kbd "C-c C-t") 'haskell-mode-enable-process-minor-mode)
204204
(define-key map (kbd "C-c C-i") 'haskell-mode-enable-process-minor-mode)
205+
(define-key map (kbd "C-c C-s") 'haskell-mode-toggle-scc-at-point)
205206
map)
206207
"Keymap used in Haskell mode.")
207208

@@ -891,13 +892,15 @@ LOC = (list FILE LINE COL)"
891892

892893
;; From Bryan O'Sullivan's blog:
893894
;; http://www.serpentine.com/blog/2007/10/09/using-emacs-to-insert-scc-annotations-in-haskell-code/
894-
(defun haskell-mode-insert-scc-at-point ()
895-
"Insert an SCC annotation at point."
896-
(interactive)
897-
(if (or (looking-at "\\b\\|[ \t]\\|$") (and (not (bolp))
898-
(save-excursion
899-
(forward-char -1)
900-
(looking-at "\\b\\|[ \t]"))))
895+
(defun haskell-mode-try-insert-scc-at-point ()
896+
"Try to insert an SCC annotation at point. Return true if
897+
successful, nil otherwise."
898+
(if (or (looking-at "\\b\\|[ \t]\\|$")
899+
;; Allow SCC if point is on a non-letter with whitespace to the left
900+
(and (not (bolp))
901+
(save-excursion
902+
(forward-char -1)
903+
(looking-at "[ \t]"))))
901904
(let ((space-at-point (looking-at "[ \t]")))
902905
(unless (and (not (bolp)) (save-excursion
903906
(forward-char -1)
@@ -906,13 +909,23 @@ LOC = (list FILE LINE COL)"
906909
(insert "{-# SCC \"\" #-}")
907910
(unless space-at-point
908911
(insert " "))
909-
(forward-char (if space-at-point -5 -6)))
910-
(error "Not over an area of whitespace")))
912+
(forward-char (if space-at-point -5 -6))
913+
t )))
911914

912-
;; Also Bryan O'Sullivan's.
913-
(defun haskell-mode-kill-scc-at-point ()
914-
"Kill the SCC annotation at point."
915+
(defun haskell-mode-insert-scc-at-point ()
916+
"Insert an SCC annotation at point."
915917
(interactive)
918+
(if (not (haskell-mode-try-insert-scc-at-point))
919+
(error "Not over an area of whitespace")))
920+
921+
(make-obsolete
922+
'haskell-mode-insert-scc-at-point
923+
'haskell-mode-toggle-scc-at-point
924+
"2015-11-11")
925+
926+
(defun haskell-mode-try-kill-scc-at-point ()
927+
"Try to kill an SCC annotation at point. Return true if
928+
successful, nil otherwise."
916929
(save-excursion
917930
(let ((old-point (point))
918931
(scc "\\({-#[ \t]*SCC \"[^\"]*\"[ \t]*#-}\\)[ \t]*"))
@@ -921,8 +934,27 @@ LOC = (list FILE LINE COL)"
921934
(if (and (looking-at scc)
922935
(<= (match-beginning 1) old-point)
923936
(> (match-end 1) old-point))
924-
(kill-region (match-beginning 0) (match-end 0))
925-
(error "No SCC at point")))))
937+
(progn (kill-region (match-beginning 0) (match-end 0))
938+
t)))))
939+
940+
;; Also Bryan O'Sullivan's.
941+
(defun haskell-mode-kill-scc-at-point ()
942+
"Kill the SCC annotation at point."
943+
(interactive)
944+
(if (not (haskell-mode-try-kill-scc-at-point))
945+
(error "No SCC at point")))
946+
947+
(make-obsolete
948+
'haskell-mode-kill-scc-at-point
949+
'haskell-mode-toggle-scc-at-point
950+
"2015-11-11")
951+
952+
(defun haskell-mode-toggle-scc-at-point ()
953+
"If point is in an SCC annotation, kill the annotation. Otherwise, try to insert a new annotation."
954+
(interactive)
955+
(if (not (haskell-mode-try-kill-scc-at-point))
956+
(if (not (haskell-mode-try-insert-scc-at-point))
957+
(error "Could not insert or remove SCC"))))
926958

927959
(defun haskell-guess-module-name ()
928960
"Guess the current module name of the buffer."

tests/haskell-mode-tests.el

+28-1
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@
170170
(should (with-temp-buffer
171171
(haskell-mode)
172172
(insert "Äöèąċōïá")
173-
(string= "Äöèąċōïá" (haskell-ident-at-point)))))
173+
(string= "Äöèąċōïá" (haskell-ident-at-point)))))
174174

175175
(ert-deftest unicode-pos ()
176176
(should (with-temp-buffer
@@ -385,4 +385,31 @@ Also should respect 10 column fill."
385385
'("-- @| a b c d"
386386
"-- e")))
387387

388+
(ert-deftest insert-scc-feasible ()
389+
"insert an SCC where it's possible to do so"
390+
(should (with-temp-buffer
391+
(insert "hello world")
392+
(goto-char 6)
393+
(haskell-mode-toggle-scc-at-point)
394+
(string= "hello {-# SCC \"\" #-} world"
395+
(buffer-substring 1 (point-max))))))
396+
397+
(ert-deftest insert-scc-infeasible ()
398+
"insert an SCC where it's not possible to do so"
399+
(should-error (with-temp-buffer
400+
(insert "hello world")
401+
(goto-char 2)
402+
(haskell-mode-toggle-scc-at-point)
403+
(string= "hello world"
404+
(buffer-substring 1 (point-max))))))
405+
406+
(ert-deftest remove-scc ()
407+
"insert an SCC where it's possible to do so"
408+
(should (with-temp-buffer
409+
(insert "hello {-# SCC \"\" #-} world")
410+
(goto-char 10)
411+
(haskell-mode-toggle-scc-at-point)
412+
(string= "hello world"
413+
(buffer-substring 1 (point-max))))))
414+
388415
(provide 'haskell-mode-tests)

0 commit comments

Comments
 (0)