diff --git a/Utils.hs b/Utils.hs
new file mode 100644
--- /dev/null
+++ b/Utils.hs
@@ -0,0 +1,68 @@
+module Utils where
+
+import System.IO
+import Database.TxtSushi.FlatFile
+import Data.Char
+-- import Debug.Trace
+
+type Tbl = [[String]]
+
+mapTable ::(Tbl -> Tbl) -> String -> String
+mapTable f = formatTable csvFormat . f . parseTable csvFormat
+
+padTbl :: a -> [[a]] -> [[a]]
+padTbl _     [] = []
+padTbl dflt  xss0@(xs0:_)
+  = zipWith (padRow cols) [1::Int ..] $ xss0
+  where cols = length xs0
+        -- padRow = take cols (xs ++ repeat dflt)
+        padRow 0 _ []      = []
+        padRow 0 i _       = error $ "Row " ++ show i ++ " is too long"
+        padRow n _ []      = replicate n dflt
+        padRow n i (x:xs)  = x : padRow (n - 1) i xs
+
+getContentsFromFileOrStdin :: FilePath -> IO String
+getContentsFromFileOrStdin "-"  = hSetEncoding stdin latin1 >> getContents
+getContentsFromFileOrStdin fp   = readFile fp
+
+interactTable ::(Tbl -> Tbl) -> FilePath -> IO ()
+interactTable f = (putStr . mapTable f =<<) . getContentsFromFileOrStdin
+
+evalChar :: Char -> Char
+evalChar 'a'   = '\a'
+evalChar 'b'   = '\b'
+evalChar 'f'   = '\f'
+evalChar 'n'   = '\n'
+evalChar 'r'   = '\r'
+evalChar 't'   = '\t'
+evalChar 'v'   = '\v'
+evalChar x     = x
+
+evalStr :: String -> String
+evalStr ('\\':'0':'x':x:y:xs)  = chr (16 * digitToInt x + digitToInt y) : evalStr xs
+evalStr ('\\':x:xs)            = evalChar x  : evalStr xs
+evalStr (x:xs)                 = x           : evalStr xs
+evalStr []                     = []
+
+expandRanges :: String -> String
+expandRanges (x:'-':y:zs)  = [x..y]++expandRanges zs
+expandRanges (x:xs)        = x : expandRanges xs
+expandRanges []            = []
+
+addDefaultInput :: [String] -> [String]
+addDefaultInput [] = ["-"]
+addDefaultInput xs = xs
+
+getInput :: String -> [String] -> String
+getInput _ []  = "-"
+getInput _ [x] = x
+getInput d _   = d
+
+substChar :: Eq a => a -> a -> (a -> a)
+substChar s d x  | x == s     = d
+                 | otherwise  = x
+
+zipWith' :: [c] -> (a -> b -> c) -> [a] -> [b] -> [c]
+zipWith' _ _ []     []     = []
+zipWith' d f (x:xs) (y:ys) = f x y : zipWith' d f xs ys
+zipWith' d _ _      _      = d
diff --git a/csv-nptools.cabal b/csv-nptools.cabal
--- a/csv-nptools.cabal
+++ b/csv-nptools.cabal
@@ -1,6 +1,6 @@
 Name:           csv-nptools
 Cabal-Version:  >=1.4
-Version:        0.4.0
+Version:        0.4.1
 License:        GPL
 Copyright:      (c) Nicolas Pouillard
 Author:         Nicolas Pouillard
@@ -20,28 +20,34 @@
     main-is: csv2json.hs
     Build-depends: base>=3&&<5, txt-sushi, vector, bytestring, text, aeson
     ghc-options: -Wall -Odph
+    other-modules: Utils
 
 executable csv-add-id
     main-is: csv-add-id.hs
     Build-depends: base>=3&&<5, txt-sushi
     ghc-options: -Wall -Odph
+    other-modules: Utils
 
 executable csv-reformat
     main-is: csv-reformat.hs
     Build-depends: base>=3&&<5, txt-sushi
     ghc-options: -Wall -Odph
+    other-modules: Utils
 
 executable csv-tr
     main-is: csv-tr.hs
     Build-depends: base>=3&&<5, txt-sushi
     ghc-options: -Wall -Odph
+    other-modules: Utils
 
 executable csv-transpose
     main-is: csv-transpose.hs
     Build-depends: base>=3&&<5, txt-sushi
     ghc-options: -Wall -Odph
+    other-modules: Utils
 
 executable csv-pad
     main-is: csv-pad.hs
     Build-depends: base>=3&&<5, txt-sushi
     ghc-options: -Wall -Odph
+    other-modules: Utils
