loc-0.2.0.0: src/Data/Loc.hs
module Data.Loc
( -- * Concepts
-- $concepts
-- * Imports
-- $imports
-- * Core types
Line,
Column,
Loc,
Span,
SpanOrLoc,
Area,
-- * Constructing
-- ** Loc
loc,
origin,
-- ** Span
spanFromTo,
spanFromToMay,
-- ** SpanOrLoc
spanOrLocFromTo,
-- ** Area
areaFromTo,
spanArea,
-- * Deconstructing
-- ** Loc
locLine,
locColumn,
-- ** Span
spanStart,
spanEnd,
-- ** SpanOrLoc
spanOrLocStart,
spanOrLocEnd,
-- ** Area
areaStart,
areaEnd,
areaSpansAsc,
-- * Combining
-- ** Span
spanUnion,
spanDifference,
-- ** Area
areaUnion,
areaDifference,
-- * Miscellaneous
Positive,
OneToTwo,
ZeroToTwo,
LocException (..),
)
where
import Data.Loc.Area (Area)
import Data.Loc.Area qualified as Area
import Data.Loc.Exception (LocException (..))
import Data.Loc.Internal.Prelude
import Data.Loc.List.OneToTwo (OneToTwo)
import Data.Loc.List.ZeroToTwo (ZeroToTwo)
import Data.Loc.Loc (Loc)
import Data.Loc.Loc qualified as Loc
import Data.Loc.Pos (Column, Line)
import Data.Loc.Span (Span)
import Data.Loc.Span qualified as Span
import Data.Loc.SpanOrLoc (SpanOrLoc)
import Data.Loc.SpanOrLoc qualified as SpanOrLoc
import Integer.Positive (Positive)
-- | The smallest location: @'loc' 1 1@
--
-- /This is an alias for 'Loc.origin'./
origin :: Loc
origin = Loc.origin
-- | Create a 'Loc' from a line number and column number
--
-- /This is an alias for 'Loc.loc'./
loc :: Line -> Column -> Loc
loc = Loc.loc
-- | /This is an alias for 'Loc.line'./
locLine :: Loc -> Line
locLine = Loc.line
-- | /This is an alias for 'Loc.column'./
locColumn :: Loc -> Column
locColumn = Loc.column
-- | Attempt to construct a 'Span' from two 'Loc's
--
-- The lesser loc will be the start, and the greater loc will be the end.
-- The two locs must not be equal, or else this throws 'EmptySpan'.
--
-- /The safe version of this function is 'spanFromToMay'./
--
-- /This is an alias for 'Span.fromTo'./
spanFromTo :: Loc -> Loc -> Span
spanFromTo = Span.fromTo
-- | Attempt to construct a 'Span' from two 'Loc's
--
-- The lesser loc will be the start, and the greater loc will be the end.
-- If the two locs are equal, the result is 'Nothing', because a span cannot be empty.
--
-- /This is the safe version of 'spanFromTo', which throws an exception instead./
--
-- /This is an alias for 'Span.fromToMay'./
spanFromToMay :: Loc -> Loc -> Maybe Span
spanFromToMay = Span.fromToMay
-- | Construct a 'SpanOrLoc' from two 'Loc's
--
-- If the two locs are not equal, the lesser loc will be the start,
-- and the greater loc will be the end.
--
-- /This is an alias for 'SpanOrLoc.fromTo'./
spanOrLocFromTo :: Loc -> Loc -> SpanOrLoc
spanOrLocFromTo = SpanOrLoc.fromTo
-- | /This is an alias for 'SpanOrLoc.start'./
spanOrLocStart :: SpanOrLoc -> Loc
spanOrLocStart = SpanOrLoc.start
-- | /This is an alias for 'SpanOrLoc.end'./
spanOrLocEnd :: SpanOrLoc -> Loc
spanOrLocEnd = SpanOrLoc.end
-- | Construct a contiguous 'Area' consisting of a single 'Span' specified by two 'Loc's
--
-- The lesser loc will be the start, and the greater loc will be the end.
-- If the two locs are equal, the area will be empty.
--
-- /This is an alias for 'Area.fromTo'./
areaFromTo :: Loc -> Loc -> Area
areaFromTo = Area.fromTo
-- | The union of two 'Area's
--
-- Spans that overlap or abut will be merged in the result.
--
-- /This is an alias for 'Area.+'./
areaUnion :: Area -> Area -> Area
areaUnion = (Area.+)
-- | The difference between two 'Area's
--
-- @a `'areaDifference'` b@ contains what is covered by @a@ and not covered by @b@.
--
-- /This is an alias for 'Area.-'./
areaDifference :: Area -> Area -> Area
areaDifference = (Area.-)
-- | A list of the 'Span's that constitute an 'Area', sorted in ascending order
--
-- /This is an alias for 'Area.spansAsc'./
areaSpansAsc :: Area -> [Span]
areaSpansAsc = Area.spansAsc
-- | Construct an 'Area' consisting of a single 'Span'
--
-- /This is an alias for 'Area.spanArea'./
spanArea :: Span -> Area
spanArea = Area.spanArea
-- | Combine two 'Span's, merging them if they abut or overlap
--
-- /This is an alias for 'Span.+'./
spanUnion :: Span -> Span -> OneToTwo Span
spanUnion = (Span.+)
-- | The difference between two 'Spans's
--
-- @a '-' b@ contains what is covered by @a@ and not covered by @b@.
--
-- /This is an alias for 'Span.-'./
spanDifference :: Span -> Span -> ZeroToTwo Span
spanDifference = (Span.-)
-- |
-- /This is an alias for 'Span.start'./
spanStart :: Span -> Loc
spanStart = Span.start
-- |
-- /This is an alias for 'Span.end'./
spanEnd :: Span -> Loc
spanEnd = Span.end
-- |
-- /This is an alias for 'Area.start'./
areaStart :: Area -> Maybe Loc
areaStart = Area.start
-- |
-- /This is an alias for 'Area.end'./
areaEnd :: Area -> Maybe Loc
areaEnd = Area.end
-- $concepts
--
-- 'Line' and 'Column' are positive integers representing line and column numbers.
--
-- The product of 'Line' and 'Column' is a 'Loc', which represents a position
-- between characters in multiline text. The smallest loc is 'origin': line 1,
-- column 1.
--
-- Here's a small piece of text for illustration:
--
-- > 1 2
-- > 12345678901234567890123456789
-- > ┌───────────────────────────────┐
-- > 1 │ I have my reasons, you │
-- > 2 │ have yours. What's obvious │
-- > 3 │ to me isn't to everyone else, │
-- > 4 │ and vice versa. │
-- > └───────────────────────────────┘
--
-- In this example, the word “obvious” starts at line 2, column 20, and it ends at
-- line 2, column 27. The 'Show' instance uses a shorthand notation denoting
-- these locs as @2:20@ and @2:27@.
--
-- A 'Span' is a nonempty contiguous region of text between two locs; think of it
-- like a highlighted area in a simple text editor. In the above example, a span
-- that covers the word “obvious” starts at @2:20@ and ends at @2:27@. The 'Show'
-- instance describes this tersely as @2:20-2:27@.
--
-- Multiple non-overlapping regions form an 'Area'. You may also think of an
-- area like a span that can be empty or have “gaps”. In the example above, the
-- first three words “I have my”, and not the spaces between them, are covered by
-- the area @[1:1-1:2,1:3-1:7,1:8-1:10]@.
-- $imports
--
-- Recommended import:
--
-- > import Data.Loc.Types
-- > import qualified Data.Loc as Loc