only 0.0.5.0 → 0.0.6.0
raw patch · 11 files changed
+116/−20 lines, 11 files
Files
- ChangeLog +17/−0
- only.1 +2/−2
- only.cabal +8/−1
- only.hs +40/−16
- tests/e-semi.txt +6/−0
- tests/i-all.sh +13/−1
- tests/t-cut-2.sh +6/−0
- tests/t-cut-semi.sh +6/−0
- tests/t-eq-no-debug.sh +6/−0
- tests/t-head.sh +6/−0
- tests/t-tail.sh +6/−0
+ ChangeLog view
@@ -0,0 +1,17 @@+0.0.3.0+ [AJR] Initial public release.++0.0.4.0+ [AJR] Fixed various bugs.++0.0.5.0+ [AJR] Added testing framework.+ [AJR] Added /begin/:/end/ expressions.++0.0.6.0+ [AJR] Fixed a sign problem in getIndex.+ [AJR] Fixed issues in the manpage.++ + +
only.1 view
@@ -143,7 +143,7 @@ expr = do optional numeric c <- punct ; regex ; c- (try c ; regex ; c ; optional num+ (try c ; regex ; c ; optional num | optional numeric) | numeric | regex@@ -181,7 +181,7 @@ .I M are known as .I relative indices. -Absolute indices will take the list of matches (the list of tokens that were matched by the regular expression), and apply use the numbers in M as the indices of this list. This gives you the ability to select the first match (1) or the last match (-1). If you use negative numbers, then it will count from the end of file going backwards, so (-2) would be the second to last match. Relative indices will take the list of matches, the original list of tokens, and for each match, it forms a virtual list where 0 refers to the match's index in the list of tokens. This allows one to emulate+Absolute indices will take the list of matches (the list of tokens that were matched by the regular expression), and apply use the numbers in N as the indices of this list. This gives you the ability to select the first match (1) or the last match (-1). If you use negative numbers, then it will count from the end of file going backwards, so (-2) would be the second to last match. Relative indices will take the list of matches, the original list of tokens, and for each match, it forms a virtual list where 0 refers to the match's index in the list of tokens. This allows one to emulate .B grep's \-A (after) and \-B (before) options. .P
only.cabal view
@@ -1,5 +1,5 @@ Cabal-version: >= 1.2.0.0-version: 0.0.5.0+version: 0.0.6.0 name: only license: GPL@@ -16,16 +16,21 @@ you search with 'only -l patt' but you can select the n-th match with '-l n\/patt\/' and the next 3 lines with '-l \/patt\/0:3'. extra-source-files:+ ChangeLog AUTHORS LICENSE README only.1 tests/e-both.txt+ tests/e-semi.txt tests/i-all.sh tests/Makefile tests/README+ tests/t-cut-2.sh+ tests/t-cut-semi.sh tests/t-eq-abs.sh tests/t-eq-nil.sh+ tests/t-eq-no-debug.sh tests/t-eq-regex-char.sh tests/t-eq-regex-zero.sh tests/t-eq-regex.sh@@ -33,6 +38,8 @@ tests/t-grep-before.sh tests/t-grep-dot.sh tests/t-grep-to.sh+ tests/t-head.sh+ tests/t-tail.sh executable only main-is: only.hs
only.hs view
@@ -7,6 +7,7 @@ import Control.Monad (when, unless) import Data.IORef import Data.Maybe+import Data.List import System.Console.GetOpt import System.Environment (getArgs) import System.Exit@@ -20,7 +21,7 @@ progName = "only" -- usage stuff-version = "only (GNU Only) 0.0.5.0\n"+version = "only (GNU Only) 0.0.6.0\n" header = unlines [ version,@@ -69,6 +70,7 @@ -- , Option ['b'] ["bits"] (ReqArg (\x -> ('b', x)) "EXPR") "Bit expression" -- , Option ['B'] ["bytes"] (ReqArg (\x -> ('B', x)) "EXPR") "Byte expression" -- , Option ['c'] ["chars"] (ReqArg (\x -> ('c', x)) "EXPR") "Character expression"+ , Option ['W'] ["wordsep"] (ReqArg (\x -> ('W', x)) "EXPR") "Word seperator" , Option ['w'] ["words"] (ReqArg (\x -> ('w', x)) "EXPR") "Word expression" , Option ['l'] ["lines"] (ReqArg (\x -> ('l', x)) "EXPR") "Line expression"] -- , Option ['f'] ["files"] (ReqArg (\x -> ('f', x)) "EXPR") "File expression"@@ -89,10 +91,10 @@ ocParts :: [OnlyCtx]} deriving (Read, Show, Eq) data OnlyMode = NoMode- | FileMode- | ByteMode String- | CharMode String- | WordMode String+ | FileMode -- not implemented+ | ByteMode String -- not implemented+ | CharMode String -- not implemented+ | WordMode String [Char] | LineMode String deriving (Read, Show, Eq) @@ -123,12 +125,14 @@ number = do num <- parseNum return [num]+ range :: CharParser () [Int] range = do start <- parseNum char ':' end <- parseNum return [start .. end]+ steps :: CharParser () [Int] steps = do start <- parseNum@@ -137,6 +141,7 @@ char ';' step <- parseNum return [start, (start + step) .. end]+ nexts :: CharParser () [Int] nexts = do start <- parseNum@@ -151,30 +156,36 @@ where word = do str <- many anyChar return (OnlyExpr [] str [])+ number = do abs <- parseNums if abs == [] then word else return (OnlyExpr abs "" [])+ regexChar = do ch <- noneOf $ ".,:;" ++ ['A'..'Z'] ++ ['a'..'z'] return ch+ regex = do ch <- regexChar pat <- many $ noneOf [ch] char ch return pat- pattIndex = do++ pattIndex = do -- N/regex/M expression abs <- parseNums pat <- regex rel <- parseNums return (OnlyExpr abs pat rel)- pattRange = do++ pattRange = do -- N/begin/:/end/ expression abs <- parseNums pat1 <- regex+-- rel1 <- parseNum -- only one number allowed! char ':' pat2 <- regex- rel <- parseNum -- only one number allowed!- return (OnlyRange abs pat1 pat2 rel)+ rel2 <- parseNum -- only one number allowed!+ return (OnlyRange abs pat1 pat2 rel2) readRegex :: FilePath -> String -> IO OnlyExpr@@ -234,15 +245,17 @@ notImpl = exitStr ExitSuccess "not implemented" -- option stuff-processOpt :: (Char, String) -> IO ()-processOpt (key, value) =+type Opt = (Char, String)+processOpt :: [Opt] -> Opt -> IO ()+processOpt opts (key, value) = case key of 'h' -> help 'V' -> showVersion -- 'H' -> helpMan -- 'b' -> modeAdd $ ByteMode value -- 'c' -> modeAdd $ CharMode value- 'w' -> modeAdd $ WordMode value+ 'W' -> return ()+ 'w' -> modeAdd $ WordMode value $ maybe [] id (lookup 'W' opts) 'l' -> modeAdd $ LineMode value --@@ -265,7 +278,7 @@ case context of OnlyCtx _ [OnlyLeaf] -> case mode of- WordMode expr -> doSep words expr context mode+ WordMode expr ch -> doSep (sepWith ch) expr context mode LineMode expr -> doSep lines expr context mode FileMode -> return context OnlyCtx _ ctxs -> do@@ -342,7 +355,7 @@ return (context {ocParts = parts}) simplify mode context = case mode of- WordMode _ -> unSep unwords context+ WordMode _ ch -> unSep (unsepWith ch) context LineMode _ -> unSep unlines context _ -> return context @@ -350,9 +363,20 @@ unSep unsep context = return $ context {ocParts = [OnlyLeaf], ocValue = unsep $ map ocValue (ocParts context)} +split :: Eq a => a -> [a] -> [[a]]+split c = map(tail).groupBy(const(c/=)).(c:)++sepWith :: [Char] -> String -> [String]+sepWith [c] str = split c str+sepWith [] str = words str++unsepWith :: [Char] -> [String] -> String+unsepWith [c] ls = concat $ intersperse [c] ls+unsepWith [] ls = unwords ls+ getIndex :: [a] -> Int -> a -> a getIndex xs n nil = if n < 1 - then xs !! ((length xs) - n)+ then xs !! ((length xs) + n) else if n > (length xs) then nil else xs !! (n - 1)@@ -368,7 +392,7 @@ (_, _, err) -> ioError$userError (concat err) -- process options- mapM processOpt opts+ mapM (processOpt opts) opts mapM fileAdd nonOpts -- handle some edge cases
+ tests/e-semi.txt view
@@ -0,0 +1,6 @@+1;Alfred;This is going to be the longest comment section of them all...+2;Barbra;She has nothing to say.+3;Cheese;Mice love it!+4;Dorsey;The only one who seems to know anything.+5;Edward;Not just a syllable anymore!+6;Finley;Someone who you might not want to meet.
tests/i-all.sh view
@@ -2,14 +2,26 @@ BASE="${NAME%.sh}" ONLY="../dist/build/only/only" GREP="grep"+HEAD="head"+TAIL="tail"+CUT="cut" cd "$(dirname $NAME)" function test-eq () { if [ x"$1" = x"$2" ] ; then echo -n PASS+ echo " : $BASE" else echo -n FAIL+ echo " : $BASE"+ echo "---"+ echo "$1"+ echo "+++"+ echo "does not equal:"+ echo "---"+ echo "$2"+ echo "+++"+ echo fi- echo " : $BASE" }
+ tests/t-cut-2.sh view
@@ -0,0 +1,6 @@+#!/bin/sh+. i-all.sh++test-eq \+ "$($CUT -d' ' -f1,2 e-both.txt)" \+ "$($ONLY -l// -w1,2 e-both.txt)"
+ tests/t-cut-semi.sh view
@@ -0,0 +1,6 @@+#!/bin/sh+. i-all.sh++test-eq \+ "$($CUT -d';' -f2 e-semi.txt)" \+ "$($ONLY -l// -W';' -w2 e-semi.txt)"
+ tests/t-eq-no-debug.sh view
@@ -0,0 +1,6 @@+#!/bin/sh+. i-all.sh++test-eq \+ "$($ONLY e-both.txt -l3)" \+ "3 Cheese - Mice love it!"
+ tests/t-head.sh view
@@ -0,0 +1,6 @@+#!/bin/sh+. i-all.sh++test-eq \+ "$($HEAD -n3 e-both.txt)" \+ "$($ONLY -l1:3 e-both.txt)"
+ tests/t-tail.sh view
@@ -0,0 +1,6 @@+#!/bin/sh+. i-all.sh++test-eq \+ "$($TAIL -n3 e-both.txt)" \+ "$($ONLY -l-3:-1 e-both.txt)"