| Safe Haskell | Safe-Inferred |
|---|---|
| Language | Haskell2010 |
Hakyllbars.Common
Synopsis
- (<|>) :: Alternative f => f a -> f a -> f a
- bracket :: IO a -> (a -> IO b) -> (a -> IO c) -> IO c
- join :: Monad m => m (m a) -> m a
- void :: Functor f => f a -> f ()
- (>=>) :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c
- (<=<) :: Monad m => (b -> m c) -> (a -> m b) -> a -> m c
- forM :: (Traversable t, Monad m) => t a -> (a -> m b) -> m (t b)
- class Monad m => MonadError e (m :: Type -> Type) | m -> e where
- throwError :: e -> m a
- catchError :: m a -> (e -> m a) -> m a
- lift :: (MonadTrans t, Monad m) => m a -> t m a
- second :: Bifunctor p => (b -> c) -> p a b -> p a c
- bimap :: Bifunctor p => (a -> b) -> (c -> d) -> p a c -> p b d
- first :: Bifunctor p => (a -> b) -> p a c -> p b c
- bool :: a -> a -> Bool -> a
- sequenceA_ :: (Foldable t, Applicative f) => t (f a) -> f ()
- (<&>) :: Functor f => f a -> (a -> b) -> f b
- intercalate :: [a] -> [[a]] -> [a]
- isSuffixOf :: Eq a => [a] -> [a] -> Bool
- isPrefixOf :: Eq a => [a] -> [a] -> Bool
- fromJust :: HasCallStack => Maybe a -> a
- fromMaybe :: a -> Maybe a -> a
- maybeToList :: Maybe a -> [a]
- maybe :: b -> (a -> b) -> Maybe a -> b
- isNothing :: Maybe a -> Bool
- isJust :: Maybe a -> Bool
- data ZonedTime
- formatTime :: FormatTime t => TimeLocale -> String -> t -> String
- parseTimeM :: (MonadFail m, ParseTime t) => Bool -> TimeLocale -> String -> String -> m t
- data TimeLocale
- data FeedConfiguration = FeedConfiguration {}
- data Redirect = Redirect {
- redirectTo :: String
- relativizeUrls :: Item String -> Compiler (Item String)
- escapeHtml :: String -> String
- toUrl :: FilePath -> String
- copyFileCompiler :: Compiler (Item CopyFile)
- rulesExtraDependencies :: [Dependency] -> Rules a -> Rules a
- route :: Routes -> Rules ()
- compile :: (Binary a, Typeable a, Writable a) => Compiler (Item a) -> Rules ()
- version :: String -> Rules () -> Rules ()
- create :: [Identifier] -> Rules () -> Rules ()
- match :: Pattern -> Rules () -> Rules ()
- data Rules a
- class Writable a where
- debugCompiler :: String -> Compiler ()
- withErrorMessage :: String -> Compiler a -> Compiler a
- noResult :: String -> Compiler a
- unsafeCompiler :: IO a -> Compiler a
- cached :: (Binary a, Typeable a) => String -> Compiler a -> Compiler a
- saveSnapshot :: (Binary a, Typeable a) => Snapshot -> Item a -> Compiler (Item a)
- getResourceString :: Compiler (Item String)
- getResourceBody :: Compiler (Item String)
- getRoute :: Identifier -> Compiler (Maybe FilePath)
- makeItem :: a -> Compiler (Item a)
- loadSnapshotBody :: (Binary a, Typeable a) => Identifier -> Snapshot -> Compiler a
- loadBody :: (Binary a, Typeable a) => Identifier -> Compiler a
- loadSnapshot :: (Binary a, Typeable a) => Identifier -> Snapshot -> Compiler (Item a)
- load :: (Binary a, Typeable a) => Identifier -> Compiler (Item a)
- withItemBody :: (a -> Compiler b) -> Item a -> Compiler (Item b)
- itemSetBody :: a -> Item b -> Item a
- data Item a = Item {
- itemIdentifier :: Identifier
- itemBody :: a
- type Snapshot = String
- data Compiler a
- composeRoutes :: Routes -> Routes -> Routes
- metadataRoute :: (Metadata -> Routes) -> Routes
- gsubRoute :: String -> (String -> String) -> Routes
- constRoute :: FilePath -> Routes
- customRoute :: (Identifier -> FilePath) -> Routes
- matchRoute :: Pattern -> Routes -> Routes
- setExtension :: String -> Routes
- idRoute :: Routes
- data Routes
- makePatternDependency :: MonadMetadata m => Pattern -> m Dependency
- lookupString :: String -> Metadata -> Maybe String
- type Metadata = Object
- getMatches :: MonadMetadata m => Pattern -> m [Identifier]
- getMetadata :: MonadMetadata m => Identifier -> m Metadata
- data Dependency
- (.||.) :: Pattern -> Pattern -> Pattern
- (.&&.) :: Pattern -> Pattern -> Pattern
- hasNoVersion :: Pattern
- hasVersion :: String -> Pattern
- fromRegex :: String -> Pattern
- fromList :: [Identifier] -> Pattern
- data Pattern
- toFilePath :: Identifier -> FilePath
- fromFilePath :: FilePath -> Identifier
- data Identifier
- doesFileExist :: FilePath -> IO Bool
- copyFile :: FilePath -> FilePath -> IO ()
- createDirectoryIfMissing :: Bool -> FilePath -> IO ()
- splitDirectories :: FilePath -> [FilePath]
- (</>) :: FilePath -> FilePath -> FilePath
- takeDirectory :: FilePath -> FilePath
- takeFileName :: FilePath -> FilePath
- splitFileName :: FilePath -> (String, String)
- dropExtension :: FilePath -> FilePath
Documentation
(<|>) :: Alternative f => f a -> f a -> f a infixl 3 #
An associative binary operation
Arguments
| :: IO a | computation to run first ("acquire resource") |
| -> (a -> IO b) | computation to run last ("release resource") |
| -> (a -> IO c) | computation to run in-between |
| -> IO c |
When you want to acquire a resource, do some work with it, and
then release the resource, it is a good idea to use bracket,
because bracket will install the necessary exception handler to
release the resource in the event that an exception is raised
during the computation. If an exception is raised, then bracket will
re-raise the exception (after performing the release).
A common example is opening a file:
bracket
(openFile "filename" ReadMode)
(hClose)
(\fileHandle -> do { ... })The arguments to bracket are in this order so that we can partially apply
it, e.g.:
withFile name mode = bracket (openFile name mode) hClose
Bracket wraps the release action with mask, which is sufficient to ensure
that the release action executes to completion when it does not invoke any
interruptible actions, even in the presence of asynchronous exceptions. For
example, hClose is uninterruptible when it is not racing other uses of the
handle. Similarly, closing a socket (from "network" package) is also
uninterruptible under similar conditions. An example of an interruptible
action is killThread. Completion of interruptible release actions can be
ensured by wrapping them in in uninterruptibleMask_, but this risks making
the program non-responsive to Control-C, or timeouts. Another option is to
run the release action asynchronously in its own thread:
void $ uninterruptibleMask_ $ forkIO $ do { ... }The resource will be released as soon as possible, but the thread that invoked bracket will not block in an uninterruptible state.
join :: Monad m => m (m a) -> m a #
The join function is the conventional monad join operator. It
is used to remove one level of monadic structure, projecting its
bound argument into the outer level.
'' can be understood as the join bssdo expression
do bs <- bss bs
Examples
A common use of join is to run an IO computation returned from
an STM transaction, since STM transactions
can't perform IO directly. Recall that
atomically :: STM a -> IO a
is used to run STM transactions atomically. So, by
specializing the types of atomically and join to
atomically:: STM (IO b) -> IO (IO b)join:: IO (IO b) -> IO b
we can compose them as
join.atomically:: STM (IO b) -> IO b
void :: Functor f => f a -> f () #
discards or ignores the result of evaluation, such
as the return value of an void valueIO action.
Examples
Replace the contents of a with unit:Maybe Int
>>>void NothingNothing>>>void (Just 3)Just ()
Replace the contents of an
with unit, resulting in an Either Int Int:Either Int ()
>>>void (Left 8675309)Left 8675309>>>void (Right 8675309)Right ()
Replace every element of a list with unit:
>>>void [1,2,3][(),(),()]
Replace the second element of a pair with unit:
>>>void (1,2)(1,())
Discard the result of an IO action:
>>>mapM print [1,2]1 2 [(),()]>>>void $ mapM print [1,2]1 2
(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c infixr 1 #
Left-to-right composition of Kleisli arrows.
'(bs ' can be understood as the >=> cs) ado expression
do b <- bs a cs b
forM :: (Traversable t, Monad m) => t a -> (a -> m b) -> m (t b) #
class Monad m => MonadError e (m :: Type -> Type) | m -> e where #
The strategy of combining computations that can throw exceptions by bypassing bound functions from the point an exception is thrown to the point that it is handled.
Is parameterized over the type of error information and
the monad type constructor.
It is common to use as the monad type constructor
for an error monad in which error descriptions take the form of strings.
In that case and many other common cases the resulting monad is already defined
as an instance of the Either StringMonadError class.
You can also define your own error type and/or use a monad type constructor
other than or Either String.
In these cases you will have to explicitly define instances of the Either IOErrorMonadError
class.
(If you are using the deprecated Control.Monad.Error or
Control.Monad.Trans.Error, you may also have to define an Error instance.)
Methods
throwError :: e -> m a #
Is used within a monadic computation to begin exception processing.
catchError :: m a -> (e -> m a) -> m a #
A handler function to handle previous errors and return to normal execution. A common idiom is:
do { action1; action2; action3 } `catchError` handlerwhere the action functions can call throwError.
Note that handler and the do-block must have the same return type.
Instances
lift :: (MonadTrans t, Monad m) => m a -> t m a #
Lift a computation from the argument monad to the constructed monad.
Case analysis for the Bool type. evaluates to bool x y px
when p is False, and evaluates to y when p is True.
This is equivalent to if p then y else x; that is, one can
think of it as an if-then-else construct with its arguments
reordered.
Examples
Basic usage:
>>>bool "foo" "bar" True"bar">>>bool "foo" "bar" False"foo"
Confirm that and bool x y pif p then y else x are
equivalent:
>>>let p = True; x = "bar"; y = "foo">>>bool x y p == if p then y else xTrue>>>let p = False>>>bool x y p == if p then y else xTrue
Since: base-4.7.0.0
sequenceA_ :: (Foldable t, Applicative f) => t (f a) -> f () #
Evaluate each action in the structure from left to right, and
ignore the results. For a version that doesn't ignore the results
see sequenceA.
sequenceA_ is just like sequence_, but generalised to Applicative
actions.
Examples
Basic usage:
>>>sequenceA_ [print "Hello", print "world", print "!"]"Hello" "world" "!"
intercalate :: [a] -> [[a]] -> [a] #
intercalate xs xss is equivalent to (.
It inserts the list concat (intersperse xs xss))xs in between the lists in xss and concatenates the
result.
>>>intercalate ", " ["Lorem", "ipsum", "dolor"]"Lorem, ipsum, dolor"
isSuffixOf :: Eq a => [a] -> [a] -> Bool #
The isSuffixOf function takes two lists and returns True iff
the first list is a suffix of the second. The second list must be
finite.
>>>"ld!" `isSuffixOf` "Hello World!"True
>>>"World" `isSuffixOf` "Hello World!"False
isPrefixOf :: Eq a => [a] -> [a] -> Bool #
\(\mathcal{O}(\min(m,n))\). The isPrefixOf function takes two lists and
returns True iff the first list is a prefix of the second.
>>>"Hello" `isPrefixOf` "Hello World!"True
>>>"Hello" `isPrefixOf` "Wello Horld!"False
fromJust :: HasCallStack => Maybe a -> a #
fromMaybe :: a -> Maybe a -> a #
The fromMaybe function takes a default value and a Maybe
value. If the Maybe is Nothing, it returns the default value;
otherwise, it returns the value contained in the Maybe.
Examples
Basic usage:
>>>fromMaybe "" (Just "Hello, World!")"Hello, World!"
>>>fromMaybe "" Nothing""
Read an integer from a string using readMaybe. If we fail to
parse an integer, we want to return 0 by default:
>>>import Text.Read ( readMaybe )>>>fromMaybe 0 (readMaybe "5")5>>>fromMaybe 0 (readMaybe "")0
maybeToList :: Maybe a -> [a] #
The maybeToList function returns an empty list when given
Nothing or a singleton list when given Just.
Examples
Basic usage:
>>>maybeToList (Just 7)[7]
>>>maybeToList Nothing[]
One can use maybeToList to avoid pattern matching when combined
with a function that (safely) works on lists:
>>>import Text.Read ( readMaybe )>>>sum $ maybeToList (readMaybe "3")3>>>sum $ maybeToList (readMaybe "")0
maybe :: b -> (a -> b) -> Maybe a -> b #
The maybe function takes a default value, a function, and a Maybe
value. If the Maybe value is Nothing, the function returns the
default value. Otherwise, it applies the function to the value inside
the Just and returns the result.
Examples
Basic usage:
>>>maybe False odd (Just 3)True
>>>maybe False odd NothingFalse
Read an integer from a string using readMaybe. If we succeed,
return twice the integer; that is, apply (*2) to it. If instead
we fail to parse an integer, return 0 by default:
>>>import Text.Read ( readMaybe )>>>maybe 0 (*2) (readMaybe "5")10>>>maybe 0 (*2) (readMaybe "")0
Apply show to a Maybe Int. If we have Just n, we want to show
the underlying Int n. But if we have Nothing, we return the
empty string instead of (for example) "Nothing":
>>>maybe "" show (Just 5)"5">>>maybe "" show Nothing""
A local time together with a time zone.
There is no Eq instance for ZonedTime.
If you want to compare local times, use zonedTimeToLocalTime.
If you want to compare absolute times, use zonedTimeToUTC.
Instances
| FromJSON ZonedTime | Supported string formats:
The first space may instead be a |
Defined in Data.Aeson.Types.FromJSON | |
| FromJSONKey ZonedTime | |
Defined in Data.Aeson.Types.FromJSON Methods | |
| ToJSON ZonedTime | |
| ToJSONKey ZonedTime | |
Defined in Data.Aeson.Types.ToJSON | |
| Data ZonedTime | |
Defined in Data.Time.LocalTime.Internal.ZonedTime Methods gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> ZonedTime -> c ZonedTime # gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c ZonedTime # toConstr :: ZonedTime -> Constr # dataTypeOf :: ZonedTime -> DataType # dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c ZonedTime) # dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c ZonedTime) # gmapT :: (forall b. Data b => b -> b) -> ZonedTime -> ZonedTime # gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> ZonedTime -> r # gmapQr :: forall r r'. (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> ZonedTime -> r # gmapQ :: (forall d. Data d => d -> u) -> ZonedTime -> [u] # gmapQi :: Int -> (forall d. Data d => d -> u) -> ZonedTime -> u # gmapM :: Monad m => (forall d. Data d => d -> m d) -> ZonedTime -> m ZonedTime # gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> ZonedTime -> m ZonedTime # gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> ZonedTime -> m ZonedTime # | |
| Show ZonedTime | For the time zone, this only shows the name, or offset if the name is empty. |
| NFData ZonedTime | |
Defined in Data.Time.LocalTime.Internal.ZonedTime | |
formatTime :: FormatTime t => TimeLocale -> String -> t -> String #
Substitute various time-related information for each %-code in the string, as per formatCharacter.
The general form is %<modifier><width><alternate><specifier>, where <modifier>, <width>, and <alternate> are optional.
<modifier>
glibc-style modifiers can be used before the specifier (here marked as z):
%-z- no padding
%_z- pad with spaces
%0z- pad with zeros
%^z- convert to upper case
%#z- convert to lower case (consistently, unlike glibc)
<width>
Width digits can also be used after any modifiers and before the specifier (here marked as z), for example:
%4z- pad to 4 characters (with default padding character)
%_12z- pad with spaces to 12 characters
<alternate>
An optional E character indicates an alternate formatting. Currently this only affects %Z and %z.
%Ez- alternate formatting
<specifier>
For all types (note these three are done by formatTime, not by formatCharacter):
%%%%t- tab
%n- newline
TimeZone
For TimeZone (and ZonedTime and UTCTime):
%z- timezone offset in the format
±HHMM %Ez- timezone offset in the format
±HH:MM %Z- timezone name (or else offset in the format
±HHMM) %EZ- timezone name (or else offset in the format
±HH:MM)
LocalTime
For LocalTime (and ZonedTime and UTCTime and UniversalTime):
%c- as
dateTimeFmtlocale(e.g.%a %b %e %H:%M:%S %Z %Y)
TimeOfDay
For TimeOfDay (and LocalTime and ZonedTime and UTCTime and UniversalTime):
%R- same as
%H:%M %T- same as
%H:%M:%S %X- as
timeFmtlocale(e.g.%H:%M:%S) %r- as
time12Fmtlocale(e.g.%I:%M:%S %p) %P- day-half of day from (
amPmlocale), converted to lowercase,am,pm %p- day-half of day from (
amPmlocale),AM,PM %H- hour of day (24-hour), 0-padded to two chars,
00-23 %k- hour of day (24-hour), space-padded to two chars,
0-23 %I- hour of day-half (12-hour), 0-padded to two chars,
01-12 %l- hour of day-half (12-hour), space-padded to two chars,
1-12 %M- minute of hour, 0-padded to two chars,
00-59 %S- second of minute (without decimal part), 0-padded to two chars,
00-60 %q- picosecond of second, 0-padded to twelve chars,
000000000000-999999999999. %Q- decimal point and fraction of second, up to 12 second decimals, without trailing zeros.
For a whole number of seconds,
%Qomits the decimal point unless padding is specified.
UTCTime and ZonedTime
For UTCTime and ZonedTime:
%s- number of whole seconds since the Unix epoch. For times before
the Unix epoch, this is a negative number. Note that in
%s.%qand%s%Qthe decimals are positive, not negative. For example, 0.9 seconds before the Unix epoch is formatted as-1.1with%s%Q.
DayOfWeek
For DayOfWeek (and Day and LocalTime and ZonedTime and UTCTime and UniversalTime):
%u- day of week number for Week Date format,
1(= Monday) -7(= Sunday) %w- day of week number,
0(= Sunday) -6(= Saturday) %a- day of week, short form (
sndfromwDayslocale),Sun-Sat %A- day of week, long form (
fstfromwDayslocale),Sunday-Saturday
Month
For Month (and Day and LocalTime and ZonedTime and UTCTime and UniversalTime):
%Y- year, no padding. Note
%0Yand%_Ypad to four chars %y- year of century, 0-padded to two chars,
00-99 %C- century, no padding. Note
%0Cand%_Cpad to two chars %B- month name, long form (
fstfrommonthslocale),January-December %b,%h- month name, short form (
sndfrommonthslocale),Jan-Dec %m- month of year, 0-padded to two chars,
01-12
Day
For Day (and LocalTime and ZonedTime and UTCTime and UniversalTime):
%D- same as
%m/%d/%y %F- same as
%Y-%m-%d %x- as
dateFmtlocale(e.g.%m/%d/%y) %d- day of month, 0-padded to two chars,
01-31 %e- day of month, space-padded to two chars,
1-31 %j- day of year, 0-padded to three chars,
001-366 %f- century for Week Date format, no padding. Note
%0fand%_fpad to two chars %V- week of year for Week Date format, 0-padded to two chars,
01-53 %U- week of year where weeks start on Sunday (as
sundayStartWeek), 0-padded to two chars,00-53 %W- week of year where weeks start on Monday (as
mondayStartWeek), 0-padded to two chars,00-53
Duration types
The specifiers for DiffTime, NominalDiffTime, CalendarDiffDays, and CalendarDiffTime are semantically
separate from the other types.
Specifiers on negative time differences will generally be negative (think rem rather than mod).
NominalDiffTime and DiffTime
Note that a "minute" of DiffTime is simply 60 SI seconds, rather than a minute of civil time.
Use NominalDiffTime to work with civil time, ignoring any leap seconds.
For NominalDiffTime and DiffTime:
%w- total whole weeks
%d- total whole days
%D- whole days of week
%h- total whole hours
%H- whole hours of day
%m- total whole minutes
%M- whole minutes of hour
%s- total whole seconds
%Es- total seconds, with decimal point and up to <width> (default 12) decimal places, without trailing zeros.
For a whole number of seconds,
%Esomits the decimal point unless padding is specified. %0Es- total seconds, with decimal point and <width> (default 12) decimal places.
%S- whole seconds of minute
%ES- seconds of minute, with decimal point and up to <width> (default 12) decimal places, without trailing zeros.
For a whole number of seconds,
%ESomits the decimal point unless padding is specified. %0ES- seconds of minute as two digits, with decimal point and <width> (default 12) decimal places.
CalendarDiffDays
For CalendarDiffDays (and CalendarDiffTime):
%y- total years
%b- total months
%B- months of year
%w- total weeks, not including months
%d- total days, not including months
%D- days of week
CalendarDiffTime
For CalendarDiffTime:
%h- total hours, not including months
%H- hours of day
%m- total minutes, not including months
%M- minutes of hour
%s- total whole seconds, not including months
%Es- total seconds, not including months, with decimal point and up to <width> (default 12) decimal places, without trailing zeros.
For a whole number of seconds,
%Esomits the decimal point unless padding is specified. %0Es- total seconds, not including months, with decimal point and <width> (default 12) decimal places.
%S- whole seconds of minute
%ES- seconds of minute, with decimal point and up to <width> (default 12) decimal places, without trailing zeros.
For a whole number of seconds,
%ESomits the decimal point unless padding is specified. %0ES- seconds of minute as two digits, with decimal point and <width> (default 12) decimal places.
Arguments
| :: (MonadFail m, ParseTime t) | |
| => Bool | Accept leading and trailing whitespace? |
| -> TimeLocale | Time locale. |
| -> String | Format string. |
| -> String | Input string. |
| -> m t | Return the time value, or fail if the input could not be parsed using the given format. |
Parses a time value given a format string.
Missing information will be derived from 1970-01-01 00:00 UTC (which was a Thursday).
Supports the same %-codes as formatTime, including %-, %_ and %0 modifiers, however padding widths are not supported.
Case is not significant in the input string.
Some variations in the input are accepted:
%z%Ez- accepts any of
±HHMMor±HH:MM. %Z%EZ- accepts any string of letters, or any of the formats accepted by
%z. %0Y- accepts exactly four digits.
%0G- accepts exactly four digits.
%0C- accepts exactly two digits.
%0f- accepts exactly two digits.
For example, to parse a date in YYYY-MM-DD format, while allowing the month
and date to have optional leading zeros (notice the - modifier used for %m
and %d):
Prelude Data.Time> parseTimeM True defaultTimeLocale "%Y-%-m-%-d" "2010-3-04" :: Maybe Day Just 2010-03-04
data TimeLocale #
Instances
| Show TimeLocale | |
Defined in Data.Time.Format.Locale Methods showsPrec :: Int -> TimeLocale -> ShowS # show :: TimeLocale -> String # showList :: [TimeLocale] -> ShowS # | |
| Eq TimeLocale | |
Defined in Data.Time.Format.Locale | |
| Ord TimeLocale | |
Defined in Data.Time.Format.Locale Methods compare :: TimeLocale -> TimeLocale -> Ordering # (<) :: TimeLocale -> TimeLocale -> Bool # (<=) :: TimeLocale -> TimeLocale -> Bool # (>) :: TimeLocale -> TimeLocale -> Bool # (>=) :: TimeLocale -> TimeLocale -> Bool # max :: TimeLocale -> TimeLocale -> TimeLocale # min :: TimeLocale -> TimeLocale -> TimeLocale # | |
data FeedConfiguration #
This is a data structure to keep the configuration of a feed.
Constructors
| FeedConfiguration | |
Fields
| |
Instances
| Show FeedConfiguration | |
Defined in Hakyll.Web.Feed Methods showsPrec :: Int -> FeedConfiguration -> ShowS # show :: FeedConfiguration -> String # showList :: [FeedConfiguration] -> ShowS # | |
| Eq FeedConfiguration | |
Defined in Hakyll.Web.Feed Methods (==) :: FeedConfiguration -> FeedConfiguration -> Bool # (/=) :: FeedConfiguration -> FeedConfiguration -> Bool # | |
This datatype can be used directly if you want a lower-level interface to
generate redirects. For example, if you want to redirect foo.html to
bar.jpg, you can use:
create ["foo.html"] $ do
route idRoute
compile $ makeItem $ Redirect "bar.jpg"Constructors
| Redirect | |
Fields
| |
relativizeUrls :: Item String -> Compiler (Item String) #
Compiler form of relativizeUrls which automatically picks the right root
path
escapeHtml :: String -> String #
HTML-escape a string
Example:
escapeHtml "Me & Dean"
Result:
"Me & Dean"
Convert a filepath to an URL starting from the site root
Example:
toUrl "foo/bar.html"
Result:
"/foo/bar.html"
This also sanitizes the URL, e.g. converting spaces into '%20'
rulesExtraDependencies :: [Dependency] -> Rules a -> Rules a #
Advanced usage: add extra dependencies to compilers. Basically this is needed when you're doing unsafe tricky stuff in the rules monad, but you still want correct builds.
A useful utility for this purpose is makePatternDependency.
Add (or replace) routing in the current Rules value.
This functions controls IF and WHERE the compiled results are written out
(use one of the match functions to control WHAT content is processed and
compile to control HOW).
See Routes and Identifier for
details on how output filepaths are computed.
Hint:
If there's no route attached to a rule, the compilation result is not written out.
However, the compilation result is saved to the Store
and can be loaded and used within another rule. This behavior is needed,
for example, for templates.
Examples
Rules with and without routing
-- e.g. file on disk: 'templates/post.html'
-- Rule 1 (without routing)
match "templates/*" $ do
-- compilation result saved to store with implicit identifier, e.g. 'templates/post.html'
compile templateCompiler
-- Rule 2 (with routing)
match "posts/**.md" $ do
route $ setExtension "html"
compile $ do
-- load compiled result of other rule with explicit identifier.
postTemplate <- loadBody "templates/post.html"
pandocCompiler >>= applyTemplate postTemplate defaultContextNote that we don't set a route in the first rule to avoid writing out our
compiled templates.
However, we can still load (or
loadBody) the compiled templates to apply them in a
second rule.
The content for templateCompiler comes implicitly from the
matched template files on disk. We don't have to pass that content around
manually. See match and compile for details.
To control where a compilation result will be written out (as done in the second
rule), use routing functions like setExtension.
See Hakyll.Web.Template for examples of templates and the templating syntax.
Arguments
| :: (Binary a, Typeable a, Writable a) | |
| => Compiler (Item a) | How to transform content |
| -> Rules () | Result |
Add (or replace) the given compilation steps within the given
Compiler value to the current Rules value.
This functions controls HOW the content within a rule is processed (use one
of the match functions to control WHAT content is processed).
The compilation result is saved to the Store under an
implicit identifier.
See Identifier for details.
If there's routing attached to the rule where this function is used, the
compilation result is also written out to a file according to that route.
See route and Routes for details.
Examples
Compile Markdown to HTML
-- Select all Markdown files in 'posts' directory
match "posts/**.md" $ do
route $ setExtension "html"
-- use pandoc to transform Markdown to HTML in a single step
compile pandocCompilerNote how we set the content to be processed with
pandocCompiler. The content comes implicitly from the
matched Markdown files on disk. We don't have to pass that content around
manually. Every file is processed the same way within this one rule.
To control where the compilation result will be written out, use routing
functions like setExtension.
Here the compilation result of a file like posts/hakyll.md is written out
to posts/hakyll.html.
Compile Markdown to HTML and embed it in a template
-- Select all Markdown files in 'posts' directory
match "posts/**.md" $ do
route $ setExtension "html"
compile $
pandocCompiler >>=
loadAndApplyTemplate "templates/post.html" defaultContext
-- To Hakyll templates are just plain files that have to be processed
-- and placed into the store like any other file (but without routing).
-- e.g. file on disk: 'templates/post.html'
match "templates/*" $ compile templateBodyCompilerNote how a Markdown post that is compiled to HTML using
pandocCompiler in a first step and then embedded into
a HTMl Template in a second step by using
loadAndApplyTemplate.
We can use templates to control the design and layout of a webpage.
A template may look as follows:
<h1>$title$</h1> $body$
See Hakyll.Web.Template to see examples of the templating syntax.
Add the given version name to the implicit identifier(s) under which the
compilation result of the given remaining Rules value is saved to the
Store.
See Identifier for details.
Use this wrapper function for example when you need to compile the same source file into two or more different results, each with a different version name. The version is needed to distinguish between these different compilation results in the store, otherwise they would get the same conflicting identifier in the store.
Warning:
If you add a version name with this function, you need to supply the same name
when you load the content from the store from
within another rule.
Examples
Compile source file into differently versioned outputs and load both
-- e.g. file on disk: 'posts/hakyll.md'
-- saved with implicit identifier ('posts/hakyll.md', no-version)
match "posts/*" $ do
route $ setExtension "html"
compile pandocCompiler
-- saved with implicit identifier ('posts/hakyll.md', version 'raw')
match "posts/*" $ version "raw" $ do
route idRoute
compile getResourceBody
-- use compilation results from rules above
create ["index.html"] $ do
route idRoute
compile $ do
-- load no-version version
compiledPost <- load (fromFilePath "posts/hakyll.md")
-- load version 'raw'
rawPost <- load . setVersion (Just "raw") $ fromFilePath "posts/hakyll.md"
...Note how a version name is needed to distinguish the unversioned and the "raw"
version when loading the Hakyll post for the index.html page.
To control where the compilation result will be written out, use routing
functions like idRoute and setExtension.
Arguments
| :: [Identifier] | Identifiers to assign to created content in next argument |
| -> Rules () | Remaining processing parts that must create content |
| -> Rules () | Resulting rule |
Assign (and thereby create) the given identifier(s) to content that has no
underlying source file on disk. That content must be created within the
compile part of the given remaining Rules value. The given identifier is the
id under which the compilation is saved to the Store (in
case you want to load it within another rule).
See Identifier for details.
Use this function for example to create an overview page that doesn't have or need its content prepared in a file (unlike blog posts which normally have a corresponding Markdown source file on disk).
Examples
Create a webpage without an underlying source file
-- saved with implicit identifier 'index.html' to Store
create ["index.html"] $ do
-- compilation result is written to '<destination-directory>/index.html'
route idRoute
-- create content without a source file from disk
compile $ makeItem ("<h1>Hello World</h1>" :: String)Note how you can use makeItem to create content inline
(to be processed as a Compiler value) as if that content
was loaded from a file (as it's the case when using match).
To control where the compilation result will be written out, use routing
functions like idRoute.
Add a selection of which source files to process (using the
given glob pattern) to the
given remaining Rules value.
The expanded, relative path of the matched source file on disk (relative to the
project directory configured with providerDirectory)
becomes the identifier under which the compilation result is saved to the
Store (in case you want to load it
within another rule).
See Identifier for details.
Examples
Select all markdown files within a directory (but without subdirectories)
-- Match all Markdown files in the immediate 'posts' directory
-- e.g. '<project-directory>/posts/hakyll.md'
-- but NOT '<project-directory>/posts/haskell/monad.md'
match "posts/*.md" $ do
route $ setExtension "html"
compile pandocCompilerSelect all markdown files within a directory (including subdirectories recursively)
-- Match all Markdown files in the 'posts' directory and any subdirectory
-- e.g. '<project-directory>/posts/hakyll.md'
-- and '<project-directory>/posts/haskell/monad.md'
match "posts/**.md" $ do
route $ setExtension "html"
compile pandocCompilerSee Pattern or search "glob patterns" online
for more details. To control where the compilation result will be written out,
use routing functions like setExtension.
The monad used to compose rules
Instances
| MonadFail Rules | |
Defined in Hakyll.Core.Rules.Internal | |
| Applicative Rules | |
| Functor Rules | |
| Monad Rules | |
| MonadMetadata Rules | |
Defined in Hakyll.Core.Rules.Internal Methods getMetadata :: Identifier -> Rules Metadata # getMatches :: Pattern -> Rules [Identifier] # getAllMetadata :: Pattern -> Rules [(Identifier, Metadata)] # | |
Describes an item that can be saved to the disk
debugCompiler :: String -> Compiler () #
Compiler for debugging purposes. Passes a message to the debug logger that is printed in verbose mode.
withErrorMessage :: String -> Compiler a -> Compiler a #
Prepend an error line to the error, if there is one. This allows you to add helpful context to error messages.
Since: hakyll-4.13.0
noResult :: String -> Compiler a #
Fail so that it is treated as non-defined in an $if()$ branching
Hakyll.Web.Template macro, and alternative
Contexts are tried
Since: hakyll-4.13.0
unsafeCompiler :: IO a -> Compiler a #
Run an IO computation without dependencies in a Compiler.
You probably want recompilingUnsafeCompiler instead.
cached :: (Binary a, Typeable a) => String -> Compiler a -> Compiler a #
Turn on caching for a compilation value to avoid recomputing it on subsequent Hakyll runs. The storage key consists of the underlying identifier of the compiled ressource and the given name.
saveSnapshot :: (Binary a, Typeable a) => Snapshot -> Item a -> Compiler (Item a) #
Save a snapshot of the item. This function returns the same item, which
convenient for building >>= chains.
getResourceString :: Compiler (Item String) #
Get the full contents of the matched source file as a string.
getResourceBody :: Compiler (Item String) #
Get the full contents of the matched source file as a string, but without metadata preamble, if there was one.
makeItem :: a -> Compiler (Item a) #
Create an item from the underlying identifier and a given value.
loadSnapshotBody :: (Binary a, Typeable a) => Identifier -> Snapshot -> Compiler a #
A shortcut for only requiring the body for a specific snapshot of an item
loadBody :: (Binary a, Typeable a) => Identifier -> Compiler a #
A shortcut for only requiring the body of an item.
loadBody = fmap itemBody . load
loadSnapshot :: (Binary a, Typeable a) => Identifier -> Snapshot -> Compiler (Item a) #
Require a specific snapshot of an item.
load :: (Binary a, Typeable a) => Identifier -> Compiler (Item a) #
Load an item compiled elsewhere. If the required item is not yet compiled, the build system will take care of that automatically.
withItemBody :: (a -> Compiler b) -> Item a -> Compiler (Item b) #
Perform a compiler action on the item body. This is the same as traverse,
but looks less intimidating.
withItemBody = traverse
itemSetBody :: a -> Item b -> Item a #
Constructors
| Item | |
Fields
| |
Instances
| Foldable Item | |
Defined in Hakyll.Core.Item Methods fold :: Monoid m => Item m -> m # foldMap :: Monoid m => (a -> m) -> Item a -> m # foldMap' :: Monoid m => (a -> m) -> Item a -> m # foldr :: (a -> b -> b) -> b -> Item a -> b # foldr' :: (a -> b -> b) -> b -> Item a -> b # foldl :: (b -> a -> b) -> b -> Item a -> b # foldl' :: (b -> a -> b) -> b -> Item a -> b # foldr1 :: (a -> a -> a) -> Item a -> a # foldl1 :: (a -> a -> a) -> Item a -> a # elem :: Eq a => a -> Item a -> Bool # maximum :: Ord a => Item a -> a # | |
| Traversable Item | |
| Functor Item | |
| Show a => Show (Item a) | |
| Binary a => Binary (Item a) | |
| FromValue (Item a) a Source # | |
Defined in Hakyllbars.Context Methods fromValue :: ContextValue a -> TemplateRunner a (Item a) Source # | |
| IntoValue (Item a) a Source # | |
Defined in Hakyllbars.Context Methods intoValue :: Item a -> ContextValue a Source # | |
Whilst compiling an item, it possible to save multiple snapshots of it, and not just the final result.
A monad which lets you compile items and takes care of dependency tracking for you.
Instances
Compose two routes where the first route is applied before the second.
So f `composeRoutes` g is more or less equivalent with g . f.
Warning: If the first route fails (e.g. when using matchRoute), Hakyll will
not apply the second route (if you need Hakyll to try the second route,
use <> on Routes instead).
Examples
Route that applies two transformations
-- e.g. file on disk: '<project-directory>/posts/hakyll.md'
-- 'hakyll.md' source file implicitly gets filepath as identifier:
-- 'posts/hakyll.md'
match "posts/*" $ do
-- compilation result is written to '<destination-directory>/hakyll.html'
route $ gsubRoute "posts/" (const "") `composeRoutes` setExtension "html"
compile pandocCompilerThe identifier here is that of the underlying item being processed and is
interpreted as an destination filepath.
See Identifier for details.
Note how we first remove the "posts/" substring from that destination filepath
with gsubRoute and then replace the extension with setExtension.
Wrapper function around other route construction functions to get access to the metadata (of the underlying item being processed) and use that for the destination filepath construction. Warning: you have to __ensure that the accessed metadata fields actually exists__.
Examples
Route that uses a custom slug markdown metadata field
To create a search engine optimized yet human-readable url, we can introduce a slug metadata field to our files, e.g. like in the following Markdown file: 'posts/hakyll.md'
--- title: Hakyll Post slug: awesome-post ... --- In this blog post we learn about Hakyll ...
Then we can construct a route whose destination filepath is based on that field:
match "posts/*" $ do
-- compilation result is written to '<destination-directory>/awesome-post.html'
route $ metadataRoute $ \meta ->
constRoute $ fromJust (lookupString "slug" meta) <> ".html"
compile pandocCompilerNote how we wrap metadataRoute around the constRoute function and how the
slug is looked up from the markdown field to construct the destination filepath.
You can use helper functions like lookupString to access
a specific metadata field.
Arguments
| :: String | Pattern to repeatedly match against in the underlying identifier |
| -> (String -> String) | Replacement function to apply to the matched substrings |
| -> Routes | Resulting route |
Create a "substituting" route that searches for substrings (in the
underlying identifier) that match the given pattern and transforms them
according to the given replacement function.
The identifier here is that of the underlying item being processed and is
interpreted as an destination filepath. It's normally the filepath of the
source file being processed.
See Identifier for details.
Hint: The name "gsub" comes from a similar function in [R](https://www.r-project.org) and can be read as "globally substituting" (globally in the Unix sense of repeated, not just once).
Examples
Route that replaces part of the filepath
-- e.g. file on disk: '<project-directory>/posts/hakyll.md'
-- 'hakyll.md' source file implicitly gets filepath as identifier:
-- 'posts/hakyll.md'
match "posts/*" $ do
-- compilation result is written to '<destination-directory>/haskell/hakyll.md'
route $ gsubRoute "posts/" (const "haskell/")
compile getResourceBodyNote that "posts/" is replaced with "haskell/" in the destination filepath.
Route that removes part of the filepath
-- implicitly gets identifier: 'tags/rss/bar.xml'
create ["tags/rss/bar.xml"] $ do
-- compilation result is written to '<destination-directory>/tags/bar.xml'
route $ gsubRoute "rss/" (const "")
compile ...Note that "rss/" is removed from the destination filepath.
constRoute :: FilePath -> Routes #
Create a route that writes the compiled item to the given destination filepath (ignoring any identifier or other data about the item being processed). Warning: you should __use a specific destination path only for a single file in a single compilation rule__. Otherwise it's unclear which of the contents should be written to that route.
Examples
Route to a specific filepath
-- implicitly gets identifier: 'main' (ignored on next line)
create ["main"] $ do
-- compilation result is written to '<destination-directory>/index.html'
route $ constRoute "index.html"
compile $ makeItem ("<h1>Hello World</h1>" :: String)Arguments
| :: (Identifier -> FilePath) | Destination filepath construction function |
| -> Routes | Resulting route |
Create a route where the destination filepath is built with the given
construction function. The provided identifier for that function is normally the
filepath of the source file being processed.
See Identifier for details.
Examples
Route that appends a custom extension
-- e.g. file on disk: '<project-directory>/posts/hakyll.md'
-- 'hakyll.md' source file implicitly gets filepath as identifier:
-- 'posts/hakyll.md'
match "posts/*" $ do
-- compilation result is written to '<destination-directory>/posts/hakyll.md.html'
route $ customRoute ((<> ".html") . toFilePath)
compile pandocCompilerNote that the last part of the destination filepath becomes .md.html
matchRoute :: Pattern -> Routes -> Routes #
Apply the route if the identifier matches the given pattern, fail otherwise
setExtension :: String -> Routes #
Create a route like idRoute that interprets the identifier (of the item
being processed) as the destination filepath but also sets (or replaces) the
extension suffix of that path. This identifier is normally the filepath of the
source file being processed.
See Identifier for details.
Examples
Route with an existing extension
-- e.g. file on disk: '<project-directory>/posts/hakyll.md'
-- 'hakyll.md' source file implicitly gets filepath as identifier:
-- 'posts/hakyll.md'
match "posts/*" $ do
-- compilation result is written to '<destination-directory>/posts/hakyll.html'
route (setExtension "html")
compile pandocCompilerRoute without an existing extension
-- implicitly gets identifier: 'about'
create ["about"] $ do
-- compilation result is written to '<destination-directory>/about.html'
route (setExtension "html")
compile $ makeItem ("Hello world" :: String)An "identity" route that interprets the identifier (of the item being
processed) as the destination filepath. This identifier is normally the
filepath of the source file being processed.
See Identifier for details.
Examples
Route when using match
-- e.g. file on disk: '<project-directory>/posts/hakyll.md'
-- 'hakyll.md' source file implicitly gets filepath as identifier:
-- 'posts/hakyll.md'
match "posts/*" $ do
-- compilation result is written to '<destination-directory>/posts/hakyll.md'
route idRoute
compile getResourceBodymakePatternDependency :: MonadMetadata m => Pattern -> m Dependency #
getMatches :: MonadMetadata m => Pattern -> m [Identifier] #
getMetadata :: MonadMetadata m => Identifier -> m Metadata #
data Dependency #
Instances
| Show Dependency | |
Defined in Hakyll.Core.Dependencies Methods showsPrec :: Int -> Dependency -> ShowS # show :: Dependency -> String # showList :: [Dependency] -> ShowS # | |
| Binary Dependency | |
Defined in Hakyll.Core.Dependencies | |
(.||.) :: Pattern -> Pattern -> Pattern infixr 2 #
|| for patterns: the given identifier must match any subterm
(.&&.) :: Pattern -> Pattern -> Pattern infixr 3 #
&& for patterns: the given identifier must match both subterms
hasNoVersion :: Pattern #
Match only if the identifier has no version set, e.g.
"foo/*.markdown" .&&. hasNoVersion
hasVersion :: String -> Pattern #
Specify a version, e.g.
"foo/*.markdown" .&&. hasVersion "pdf"
fromList :: [Identifier] -> Pattern #
Create a Pattern from a list of Identifiers it should match.
Warning: use this carefully with hasNoVersion and hasVersion. The
Identifiers in the list already have versions assigned, and the pattern
will then only match the intersection of both versions.
A more concrete example,
fromList ["foo.markdown"] .&&. hasVersion "pdf"
will not match anything! The "foo.markdown" Identifier has no version
assigned, so the LHS of .&&. will only match this Identifier with no
version. The RHS only matches Identifiers with version set to "pdf" --
hence, this pattern matches nothing.
The correct way to use this is:
fromList $ map (setVersion $ Just "pdf") ["foo.markdown"]
Type that allows matching on identifiers
toFilePath :: Identifier -> FilePath #
Convert an identifier back to a relative FilePath.
fromFilePath :: FilePath -> Identifier #
Parse an identifier from a file path string. For example,
-- e.g. file on disk: 'posts/hakyll.md'
match "posts/*" $ do -- saved with implicit identifier 'posts/hakyll.md'
compile pandocCompiler
match "about/*" $ do
compile $ do
compiledPost <- load (fromFilePath "posts/hakyll.md") -- load with explicit identifier
...
data Identifier #
A key data type to identify a compiled Item in the Store.
Conceptually, it's a combination of a file path and a version name.
The version is used only when a file is
compiled within a rule using the version wrapper function
(the same source file
can be compiled into several items in the store, so the version exists to distinguish
them).
Use functions like fromFilePath, setVersion, getMatches to build an Identifier.
Usage Examples
Normally, compiled items are saved to the store by Rules with an automatic, implicit identifier
and loaded from the store by the user in another rule with a manual, explicit identifier.
Identifiers when using match.
Using match builds an implicit identifier that corresponds to the expanded, relative path
of the source file on disk (relative to the project directory configured
with providerDirectory):
-- e.g. file on disk: 'posts/hakyll.md'
match "posts/*" $ do -- saved with implicit identifier 'posts/hakyll.md'
compile pandocCompiler
match "about/*" $ do
compile $ do
compiledPost <- load (fromFilePath "posts/hakyll.md") -- load with explicit identifier
...
Normally, the identifier is only explicitly created to pass to one of the load functions.
Identifiers when using create.
Using create (thereby inventing a file path with no underlying file on disk)
builds an implicit identifier that corresponds to the invented file path:
create ["index.html"] $ do -- saved with implicit identifier 'index.html'
compile $ makeItem ("Hello world" :: String)
match "about/*" $ do
compile $ do
compiledIndex <- load (fromFilePath "index.html") -- load with an explicit identifier
...
Identifiers when using versions.
With version the same file can be compiled into several items in the store.
A version name is needed to distinguish them:
-- e.g. file on disk: 'posts/hakyll.md'
match "posts/*" $ do -- saved with implicit identifier ('posts/hakyll.md', no-version)
compile pandocCompiler
match "posts/*" $ version "raw" $ do -- saved with implicit identifier ('posts/hakyll.md', version raw)
compile getResourceBody
match "about/*" $ do
compile $ do
compiledPost <- load (fromFilePath "posts/hakyll.md") -- load no-version version
rawPost <- load . setVersion (Just "raw") $ fromFilePath "posts/hakyll.md" -- load version raw
...
Use setVersion to set (or replace) the version of an identifier like fromFilePath "posts/hakyll.md".
Instances
| IsString Identifier | |
Defined in Hakyll.Core.Identifier Methods fromString :: String -> Identifier # | |
| Show Identifier | |
Defined in Hakyll.Core.Identifier Methods showsPrec :: Int -> Identifier -> ShowS # show :: Identifier -> String # showList :: [Identifier] -> ShowS # | |
| Binary Identifier | |
Defined in Hakyll.Core.Identifier | |
| NFData Identifier | |
Defined in Hakyll.Core.Identifier Methods rnf :: Identifier -> () # | |
| Eq Identifier | |
Defined in Hakyll.Core.Identifier | |
| Ord Identifier | |
Defined in Hakyll.Core.Identifier Methods compare :: Identifier -> Identifier -> Ordering # (<) :: Identifier -> Identifier -> Bool # (<=) :: Identifier -> Identifier -> Bool # (>) :: Identifier -> Identifier -> Bool # (>=) :: Identifier -> Identifier -> Bool # max :: Identifier -> Identifier -> Identifier # min :: Identifier -> Identifier -> Identifier # | |
doesFileExist :: FilePath -> IO Bool #
The operation doesFileExist returns True
if the argument file exists and is not a directory, and False otherwise.
Copy a file with its permissions. If the destination file already exists, it is replaced atomically. Neither path may refer to an existing directory. No exceptions are thrown if the permissions could not be copied.
Arguments
| :: Bool | Create its parents too? |
| -> FilePath | The path to the directory you want to make |
| -> IO () |
creates a new directory
createDirectoryIfMissing parents dirdir if it doesn't exist. If the first argument is True
the function will also create all parent directories if they are missing.
splitDirectories :: FilePath -> [FilePath] #
Just as splitPath, but don't add the trailing slashes to each element.
splitDirectories "/directory/file.ext" == ["/","directory","file.ext"]
splitDirectories "test/file" == ["test","file"]
splitDirectories "/test/file" == ["/","test","file"]
Windows: splitDirectories "C:\\test\\file" == ["C:\\", "test", "file"]
Valid x => joinPath (splitDirectories x) `equalFilePath` x
splitDirectories "" == []
Windows: splitDirectories "C:\\test\\\\\\file" == ["C:\\", "test", "file"]
splitDirectories "/test///file" == ["/","test","file"](</>) :: FilePath -> FilePath -> FilePath infixr 5 #
Combine two paths with a path separator.
If the second path starts with a path separator or a drive letter, then it returns the second.
The intention is that readFile (dir will access the same file as
</> file)setCurrentDirectory dir; readFile file.
Posix: "/directory" </> "file.ext" == "/directory/file.ext"
Windows: "/directory" </> "file.ext" == "/directory\\file.ext"
"directory" </> "/file.ext" == "/file.ext"
Valid x => (takeDirectory x </> takeFileName x) `equalFilePath` xCombined:
Posix: "/" </> "test" == "/test" Posix: "home" </> "bob" == "home/bob" Posix: "x:" </> "foo" == "x:/foo" Windows: "C:\\foo" </> "bar" == "C:\\foo\\bar" Windows: "home" </> "bob" == "home\\bob"
Not combined:
Posix: "home" </> "/bob" == "/bob" Windows: "home" </> "C:\\bob" == "C:\\bob"
Not combined (tricky):
On Windows, if a filepath starts with a single slash, it is relative to the
root of the current drive. In [1], this is (confusingly) referred to as an
absolute path.
The current behavior of </> is to never combine these forms.
Windows: "home" </> "/bob" == "/bob" Windows: "home" </> "\\bob" == "\\bob" Windows: "C:\\home" </> "\\bob" == "\\bob"
On Windows, from [1]: "If a file name begins with only a disk designator
but not the backslash after the colon, it is interpreted as a relative path
to the current directory on the drive with the specified letter."
The current behavior of </> is to never combine these forms.
Windows: "D:\\foo" </> "C:bar" == "C:bar" Windows: "C:\\foo" </> "C:bar" == "C:bar"
takeDirectory :: FilePath -> FilePath #
Get the directory name, move up one level.
takeDirectory "/directory/other.ext" == "/directory"
isPrefixOf (takeDirectory x) x || takeDirectory x == "."
takeDirectory "foo" == "."
takeDirectory "/" == "/"
takeDirectory "/foo" == "/"
takeDirectory "/foo/bar/baz" == "/foo/bar"
takeDirectory "/foo/bar/baz/" == "/foo/bar/baz"
takeDirectory "foo/bar/baz" == "foo/bar"
Windows: takeDirectory "foo\\bar" == "foo"
Windows: takeDirectory "foo\\bar\\\\" == "foo\\bar"
Windows: takeDirectory "C:\\" == "C:\\"takeFileName :: FilePath -> FilePath #
Get the file name.
takeFileName "/directory/file.ext" == "file.ext" takeFileName "test/" == "" isSuffixOf (takeFileName x) x takeFileName x == snd (splitFileName x) Valid x => takeFileName (replaceFileName x "fred") == "fred" Valid x => takeFileName (x </> "fred") == "fred" Valid x => isRelative (takeFileName x)
splitFileName :: FilePath -> (String, String) #
Split a filename into directory and file. </> is the inverse.
The first component will often end with a trailing slash.
splitFileName "/directory/file.ext" == ("/directory/","file.ext")
Valid x => uncurry (</>) (splitFileName x) == x || fst (splitFileName x) == "./"
Valid x => isValid (fst (splitFileName x))
splitFileName "file/bob.txt" == ("file/", "bob.txt")
splitFileName "file/" == ("file/", "")
splitFileName "bob" == ("./", "bob")
Posix: splitFileName "/" == ("/","")
Windows: splitFileName "c:" == ("c:","")
Windows: splitFileName "\\\\?\\A:\\fred" == ("\\\\?\\A:\\","fred")dropExtension :: FilePath -> FilePath #
Remove last extension, and the "." preceding it.
dropExtension "/directory/path.ext" == "/directory/path" dropExtension x == fst (splitExtension x)