
apfelmus wrote:
Tommy M McGuire wrote:
(Plus, interact is scary. :-D )
You have a scary feeling for a moment, then it passes. ;)
tabwidth = 4
-- tabstop !! (col-1) == there is a tabstop at column col -- This is an infinite list, so no need to limit the line width tabstops = map (\col -> col `mod` tabwidth == 1) [1..]
-- calculate spaces needed to fill to the next tabstop in advance tabspaces = snd $ mapAccumR addspace [] tabstops addspace cs isstop = let cs'=' ':cs in (if isstop then [] else cs',cs')
Are you using mapAccumR (mapAccumR? (!)) to share space among the space strings? If so, wouldn't this be better: tabstops = map (\col -> col `mod` tabwidth == 1) [1..tabwidth] tabspaces = cycle $ snd $ mapAccumR addspace [] tabstops On the other hand, wouldn't this make for less head scratching: tabspaces = map (\col -> replicate (spacesFor col) ' ') [1..] where spacesFor col = tabwidth - ((col - 1) `mod` tabwidth)
main = interact $ unlines . map detabLine . lines where detabLine = concat $ zipWith replace tabspaces
I think you mean "concat . zipWith...". (You're doing this from memory, aren't you?)
replace cs '\t' = cs -- replace with adequate number of spaces replace _ char = [char] -- pass through
How about that?
It doesn't produce the same output, although I almost like it enough not
to care:
$ od -a test
0000000 ht c o l sp 1 ht 2 ht 3 4 ht r e s t
0000020 nl
0000021
$ runhaskell detab.hs