]> gitweb.michael.orlitzky.com - hath.git/commitdiff
Add a --sort flag to hath and document/test why it was needed after all. 0.4.0
authorMichael Orlitzky <michael@orlitzky.com>
Tue, 18 Apr 2017 15:50:01 +0000 (11:50 -0400)
committerMichael Orlitzky <michael@orlitzky.com>
Tue, 18 Apr 2017 15:50:01 +0000 (11:50 -0400)
doc/man1/hath.1
src/CommandLine.hs
src/Main.hs
test/shell/manpage-sort.test

index 488cebbf82e9580d022d0791a21bc3a5c0e5e0e9..69b362fe17079601c155d330918b91e48e61532c 100644 (file)
@@ -133,7 +133,6 @@ address:
 .I $ echo x127.0.0.1x | grep -Po $(echo 127.0.0.1/32 | hath -b)
 x127.0.0.1x
 .fi
 .I $ echo x127.0.0.1x | grep -Po $(echo 127.0.0.1/32 | hath -b)
 x127.0.0.1x
 .fi
-
 .IP \fB\-\-normalize\fR,\ \fB\-n\fR
 (reduced mode only)
 
 .IP \fB\-\-normalize\fR,\ \fB\-n\fR
 (reduced mode only)
 
@@ -148,6 +147,28 @@ see CIDRs that you did not input in the first place being removed.
 .I $ echo 127.0.0.1/8 | hath reduced --normalize
 127.0.0.0/8
 .fi
 .I $ echo 127.0.0.1/8 | hath reduced --normalize
 127.0.0.0/8
 .fi
+.IP \fB\-\-sort\fR,\ \fB\-s\fR
+(reduced mode only)
+
+Sort the output CIDRs numerically by octet. The \(dqsort\(dq utility
+doesn't understand IP addresses, so the default pipe-to-sort approach
+fails in some cases:
+
+.nf
+.I $ echo \(dq10.0.121.32/28 10.0.93.248/29\(dq | hath reduced | sort
+10.0.121.32/28
+10.0.93.248/29
+.I $ echo \(dq10.0.121.32/28 10.0.93.248/29\(dq | hath reduced | sort -n
+10.0.121.32/28
+10.0.93.248/29
+.fi
+
+That failure justifies adding the additional option to hath:
+
+.nf
+.I $ echo \(dq10.0.121.32/28 10.0.93.248/29\(dq | hath reduced --sort
+10.0.93.248/29
+10.0.121.32/28
 .SH BUGS
 
 Send bugs to michael@orlitzky.com.
 .SH BUGS
 
 Send bugs to michael@orlitzky.com.
index 9d409ac89c6fb07852d06a8e002a80796458ce4f..8e6b49cfdef35fd22ce6dcd9badfcec9fc4fffba 100644 (file)
@@ -51,10 +51,15 @@ barriers_help =
 
 normalize_help :: String
 normalize_help =
 
 normalize_help :: String
 normalize_help =
-  "(reduced mode) normalize the output CIDRS, replacing any " ++
+  "(reduced mode) normalize the output CIDRs, replacing any " ++
   "masked bits by zeros; e.g. '127.0.0.1/8' -> '127.0.0.0/8'"
 
 
   "masked bits by zeros; e.g. '127.0.0.1/8' -> '127.0.0.0/8'"
 
 
+sort_help :: String
+sort_help =
+  "(reduced mode) sort the output CIDRs by their octets"
+
+
 -- | The Args type represents the possible command-line options. The
 --   duplication here seems necessary; CmdArgs' magic requires us to
 --   define some things explicitly.
 -- | The Args type represents the possible command-line options. The
 --   duplication here seems necessary; CmdArgs' magic requires us to
 --   define some things explicitly.
@@ -64,11 +69,11 @@ normalize_help =
 --   same options and arguments.
 --
 data Args =
 --   same options and arguments.
 --
 data Args =
-  Regexed { barriers :: Bool, normalize :: Bool } |
-  Reduced { barriers :: Bool, normalize :: Bool } |
-  Duped { barriers :: Bool, normalize :: Bool } |
-  Diffed { barriers :: Bool, normalize :: Bool } |
-  Listed { barriers :: Bool, normalize :: Bool }
+  Regexed { barriers :: Bool, normalize :: Bool, sort :: Bool } |
+  Reduced { barriers :: Bool, normalize :: Bool, sort :: Bool } |
+  Duped { barriers :: Bool, normalize :: Bool, sort :: Bool } |
+  Diffed { barriers :: Bool, normalize :: Bool, sort :: Bool } |
+  Listed { barriers :: Bool, normalize :: Bool, sort :: Bool }
   deriving (Data, Show)
 
 -- | Description of the 'Regexed' mode.
   deriving (Data, Show)
 
 -- | Description of the 'Regexed' mode.
@@ -113,15 +118,18 @@ arg_spec =
                    name "v",
                    groupname "Common flags"]
   where
                    name "v",
                    groupname "Common flags"]
   where
-    make_mode :: (Bool -> Bool -> Args) -> String -> (Annotate Ann)
+    make_mode :: (Bool -> Bool -> Bool -> Args) -> String -> (Annotate Ann)
     make_mode ctor desc =
     make_mode ctor desc =
-      record (ctor def def)
+      record (ctor def def def)
                [ barriers := def
                    += groupname "Common flags"
                    += help barriers_help,
                  normalize := def
                    += groupname "Common flags"
                [ barriers := def
                    += groupname "Common flags"
                    += help barriers_help,
                  normalize := def
                    += groupname "Common flags"
-                   += help normalize_help ]
+                   += help normalize_help,
+                 sort := def
+                   += groupname "Common flags"
+                   += help sort_help ]
                += details ["  " ++ desc]
 
     regexed  = make_mode Regexed regexed_description
                += details ["  " ++ desc]
 
     regexed  = make_mode Regexed regexed_description
index 0ebfafa67aaadcf06e3148b22f0574967b8b7fd8..4774c8778e5904a42378e53e2673ef112f3cdef7 100644 (file)
@@ -3,6 +3,7 @@ where
 
 import Control.Monad (when)
 import Data.List ((\\), intercalate)
 
 import Control.Monad (when)
 import Data.List ((\\), intercalate)
+import qualified Data.List as List (sort)
 import Data.Maybe (catMaybes, isNothing)
 import System.Exit (ExitCode( ExitFailure ), exitWith)
 import System.IO (stderr, hPutStrLn)
 import Data.Maybe (catMaybes, isNothing)
 import System.Exit (ExitCode( ExitFailure ), exitWith)
 import System.IO (stderr, hPutStrLn)
@@ -22,7 +23,7 @@ import Cidr (
   min_octet4 )
 import qualified Cidr ( normalize )
 import CommandLine(
   min_octet4 )
 import qualified Cidr ( normalize )
 import CommandLine(
-  Args( Regexed, Reduced, Duped, Diffed, Listed, barriers, normalize ),
+  Args( Regexed, Reduced, Duped, Diffed, Listed, barriers, normalize, sort ),
   get_args )
 import ExitCodes ( exit_invalid_cidr )
 import Octet ()
   get_args )
 import ExitCodes ( exit_invalid_cidr )
 import Octet ()
@@ -130,7 +131,8 @@ main = do
     Reduced{} -> do
       -- Pre-normalize all CIDRs if the user asked for it.
       let nrml_func = if (normalize args) then Cidr.normalize else id
     Reduced{} -> do
       -- Pre-normalize all CIDRs if the user asked for it.
       let nrml_func = if (normalize args) then Cidr.normalize else id
-      mapM_ print (combine_all (map nrml_func valid_cidrs))
+      let sort_func = if (sort args) then List.sort else id :: [Cidr] -> [Cidr]
+      mapM_ (print . nrml_func) (sort_func $ combine_all valid_cidrs)
     Duped{} ->
        mapM_ print dupes
        where
     Duped{} ->
        mapM_ print dupes
        where
index 56dd0254aaa83da354e82f6a06773c34e0173272..845aaedd6cf20dd94872035436c9db001243ef78 100644 (file)
@@ -1,7 +1,22 @@
-# Test the pipe-to-sort example from the man page.
+# Test --sort example from the man page.
 
 
-echo "192.168.0.100/24 192.167.1.200/24" | dist/build/hath/hath reduced | sort
+# The default pipe-to-sort doesn't work.
+echo "10.0.121.32/28 10.0.93.248/29" | dist/build/hath/hath reduced | sort
 >>>
 >>>
-192.167.1.200/24
-192.168.0.100/24
+10.0.121.32/28
+10.0.93.248/29
+>>>= 0
+
+# Neither does a numeric sort.
+echo "10.0.121.32/28 10.0.93.248/29" | dist/build/hath/hath reduced | sort -n
+>>>
+10.0.121.32/28
+10.0.93.248/29
+>>>= 0
+
+# But the CIDR sort order does.
+echo "10.0.121.32/28 10.0.93.248/29" | dist/build/hath/hath reduced --sort
+>>>
+10.0.93.248/29
+10.0.121.32/28
 >>>= 0
 >>>= 0