Advertisement
banovski

Multicolumn text formatter

Apr 16th, 2025 (edited)
296
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Haskell 2.25 KB | Source Code | 0 0
  1. -- The utility reads a set of lines of text from stdin, modifies the
  2. -- lines and writes them to stdout. If a line contains several
  3. -- portions of text separated by horizontal tabulations, the utility
  4. -- replaces the horizontal tabulations with combinations of a
  5. -- non-breaking space, a rightwards arrow, and a space, and prepends
  6. -- the line with an index number, a period, and a space. If a line
  7. -- starts with an index number, a period, and a space and contains
  8. -- combinations of a non-breaking space, a rightwards arrow, and a
  9. -- space, the utility removes the index number, the period and the
  10. -- space, and replaces the combinations of a non-breaking space, a
  11. -- rightwards arrow, and a space with horizontal tabulations.
  12.  
  13. -- A line like this
  14. -- "foo bar baz"
  15. -- will become
  16. -- "1. foo → bar → baz"
  17. -- and a line like this
  18. -- "42. ham → spam → eggs"
  19. -- will become
  20. -- "ham spam    eggs"
  21.  
  22. import Data.List (group)
  23. import System.Exit (die)
  24.  
  25. main :: IO ()
  26. main = do
  27.   input <- getContents
  28.   if null input
  29.     then die "No data."
  30.     else mapM_ (putStrLn . dispatcher) $ zip [1 .. ] $ lines input
  31.  
  32. dispatcher :: (Int, String) ->  String
  33. dispatcher line@(_, string)
  34.   | isNumerated string = (removeNumeration . arrowsAndSpacesToTabs) string
  35.   | otherwise = (tabsToArrowsAndSpaces . numberLines) line
  36.  
  37. isNumerated :: String -> Bool
  38. isNumerated = (2 <) . length . takeWhile isSpacePeriodOrDigit
  39.  
  40. isSpacePeriodOrDigit :: Char -> Bool
  41. isSpacePeriodOrDigit = (`elem` " .0123456789")
  42.  
  43. removeNumeration :: String -> String
  44. removeNumeration = dropWhile isSpacePeriodOrDigit
  45.  
  46. arrowsAndSpacesToTabs :: String -> String
  47. arrowsAndSpacesToTabs [] = []
  48. arrowsAndSpacesToTabs [a] = [a]
  49. arrowsAndSpacesToTabs [a, b] = [a, b]
  50. arrowsAndSpacesToTabs (a:b:c:cs)
  51.   | a == '\160' && b == '\8594' && c == ' ' = '\t' : arrowsAndSpacesToTabs cs
  52.   | otherwise = a : arrowsAndSpacesToTabs (b : c : cs)
  53.  
  54. tabsToArrowsAndSpaces :: String -> String
  55. tabsToArrowsAndSpaces [] = []
  56. tabsToArrowsAndSpaces [x] = [x]
  57. tabsToArrowsAndSpaces lst = concatMap go (group lst)
  58.   where
  59.     go [] = []
  60.     go str@(x:_)
  61.       | x == '\t' = "\160\8594 "
  62.       | otherwise = str
  63.  
  64. numberLines :: (Int, String) -> String
  65. numberLines (number, string) = show number ++ ". " ++ string
  66.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement