aboutsummaryrefslogtreecommitdiff
path: root/Git/Filename.hs
diff options
context:
space:
mode:
authorGravatar Joey Hess <joey@kitenet.net>2011-12-22 20:14:35 -0400
committerGravatar Joey Hess <joey@kitenet.net>2011-12-23 01:05:16 -0400
commitcba3ce08dfaa3318aa80b414e4d6d4f40d843d15 (patch)
treecdb54dd767cb1530c88b92277b1150f961d06012 /Git/Filename.hs
parenta0872a8ec34894689489dd0cf47887d8609b9f47 (diff)
handle C-style escapes in Format
I was happily able to repurpose some code from Git.Filename to handle this. I remember writing that code... a whole afternoon at a coffee shop, after which I felt I'd struggled with Haskell and git, and sorta lost, in needing to write this nasty peice of code. But was also pleased at the use of a pair of functions and quickcheck that allowed me to get it 100% right. So, turns out I not only got it right, but the code wasn't as special-purpose as I'd feared. Yay!
Diffstat (limited to 'Git/Filename.hs')
-rw-r--r--Git/Filename.hs61
1 files changed, 3 insertions, 58 deletions
diff --git a/Git/Filename.hs b/Git/Filename.hs
index 35b553250..5e076d3b5 100644
--- a/Git/Filename.hs
+++ b/Git/Filename.hs
@@ -8,10 +8,7 @@
module Git.Filename where
-import qualified Codec.Binary.UTF8.String
-import Data.Char
-import Data.Word (Word8)
-import Text.Printf
+import Utility.Format (decode_c, encode_c)
import Common
@@ -19,64 +16,12 @@ decode :: String -> FilePath
decode [] = []
decode f@(c:s)
-- encoded strings will be inside double quotes
- | c == '"' && end s == ['"'] = unescape ("", beginning s)
+ | c == '"' && end s == ['"'] = decode_c $ beginning s
| otherwise = f
- where
- e = '\\'
- unescape (b, []) = b
- -- look for escapes starting with '\'
- unescape (b, v) = b ++ fst pair ++ unescape (handle $ snd pair)
- where
- pair = span (/= e) v
- isescape x = x == e
- -- \NNN is an octal encoded character
- handle (x:n1:n2:n3:rest)
- | isescape x && alloctal = (fromoctal, rest)
- where
- alloctal = isOctDigit n1 &&
- isOctDigit n2 &&
- isOctDigit n3
- fromoctal = [chr $ readoctal [n1, n2, n3]]
- readoctal o = Prelude.read $ "0o" ++ o :: Int
- -- \C is used for a few special characters
- handle (x:nc:rest)
- | isescape x = ([echar nc], rest)
- where
- echar 'a' = '\a'
- echar 'b' = '\b'
- echar 'f' = '\f'
- echar 'n' = '\n'
- echar 'r' = '\r'
- echar 't' = '\t'
- echar 'v' = '\v'
- echar a = a
- handle n = ("", n)
{- Should not need to use this, except for testing decode. -}
encode :: FilePath -> String
-encode s = foldl (++) "\"" (map echar s) ++ "\""
- where
- e c = '\\' : [c]
- echar '\a' = e 'a'
- echar '\b' = e 'b'
- echar '\f' = e 'f'
- echar '\n' = e 'n'
- echar '\r' = e 'r'
- echar '\t' = e 't'
- echar '\v' = e 'v'
- echar '\\' = e '\\'
- echar '"' = e '"'
- echar x
- | ord x < 0x20 = e_num x -- low ascii
- | ord x >= 256 = e_utf x
- | ord x > 0x7E = e_num x -- high ascii
- | otherwise = [x] -- printable ascii
- where
- showoctal i = '\\' : printf "%03o" i
- e_num c = showoctal $ ord c
- -- unicode character is decomposed to
- -- Word8s and each is shown in octal
- e_utf c = showoctal =<< (Codec.Binary.UTF8.String.encode [c] :: [Word8])
+encode s = "\"" ++ encode_c s ++ "\""
{- for quickcheck -}
prop_idempotent_deencode :: String -> Bool