1 -- This file is part of Diohsc
2 -- Copyright (C) 2020 Martin Bays <mbays@sdf.org>
4 -- This program is free software: you can redistribute it and/or modify
5 -- it under the terms of version 3 of the GNU General Public License as
6 -- published by the Free Software Foundation, or any later version.
8 -- You should have received a copy of the GNU General Public License
9 -- along with this program. If not, see http://www.gnu.org/licenses/.
11 {-# LANGUAGE OverloadedStrings #-}
12 {-# LANGUAGE TupleSections #-}
16 import Control
.Monad
(guard, msum)
17 import Data
.Char (isAlphaNum)
18 import Data
.List
(isPrefixOf)
19 import System
.Directory
20 import System
.FilePath
21 import System
.IO.Unsafe
(unsafeInterleaveIO
)
23 import qualified Data
.ByteString
as BS
24 import qualified Data
.Map
as Map
25 import qualified Data
.Text
as TS
26 import qualified Data
.Text
.Encoding
as TS
32 data URIWithIdName
= URIWithIdName
{ uriIdUri
:: URI
, uriIdId
:: Maybe String }
35 showUriWithId
:: URIWithIdName
-> String
36 showUriWithId
(URIWithIdName uri Nothing
) = show uri
37 showUriWithId
(URIWithIdName uri
(Just idName
)) = show uri
++ "[" ++ idName
++ "]"
39 readUriWithId
:: TS
.Text
-> Maybe URIWithIdName
40 readUriWithId s
= msum [ do
41 s
' <- TS
.stripSuffix
"]" s
42 let (u
,i
) = TS
.breakOn
"[" s
'
44 guard . not $ TS
.null idName
45 uri
<- parseUriAsAbsolute
. escapeIRI
$ TS
.unpack u
46 return . URIWithIdName uri
. Just
$ TS
.unpack idName
47 , (`URIWithIdName` Nothing
) <$> (parseUriAsAbsolute
. escapeIRI
$ TS
.unpack s
) ]
49 type Marks
= Map
.Map
String (Maybe URIWithIdName
)
52 emptyMarks
= Map
.empty
54 lookupMark
:: String -> Marks
-> Maybe URIWithIdName
55 lookupMark s marks
= do
56 (s
', Just uriId
) <- Map
.lookupGE s marks
57 guard $ s `
isPrefixOf` s
'
60 insertMark
:: String -> URIWithIdName
-> Marks
-> Marks
61 insertMark s
= Map
.insert s
. Just
63 loadMarks
:: FilePath -> IO Marks
65 (Map
.fromList
<$>) $ mapM lazyKeyVal
=<< ignoreIOErr
(listDirectory path
)
67 lazyKeyVal f
= (f
,) <$> unsafeInterleaveIO
(loadMark f
)
68 loadMark
:: FilePath -> IO (Maybe URIWithIdName
)
70 let filepath
= path
</> filename
71 in ignoreIOErrAlt
$ readUriWithId
. TS
.strip
. TS
.decodeUtf8
<$> BS
.readFile filepath
73 markNameValid
:: String -> Bool
74 markNameValid
= all isAlphaNum
76 saveMark
:: FilePath -> String -> URIWithIdName
-> IO ()
77 saveMark path mark uriId | markNameValid mark
=
78 let filepath
= path
</> mark
79 in isSubPath path filepath
>>? mkdirhierto filepath
>> writeFile filepath
(showUriWithId uriId
)
80 saveMark _ _ _
= pure
()
82 marksWithUri
:: URI
-> Marks
-> [(String,URIWithIdName
)]
83 marksWithUri uri
= Map
.toList
. Map
.filter ((==uri
) . uriIdUri
) . Map
.mapMaybe id
86 tempMarks
= (:[]) <$> ['0'..'9']