loc 0.1.2.1 → 0.1.2.2
raw patch · 4 files changed
+647/−1 lines, 4 filesbinary-addedPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- README.md +230/−0
- example.png binary
- example.svg +411/−0
- loc.cabal +6/−1
+ README.md view
@@ -0,0 +1,230 @@+# loc++Overview of the concepts:++++* `Loc` - a cursor position, starting at the origin `1:1`+* `Span` - a nonempty contiguous region between two locs+* `Area` - a set of zero or more spans with gaps between them++See also:++* [loc-test](https://hackage.haskell.org/package/loc-test) -+ Test-related utilities for this package.++## `Pos`++Since all of the numbers we're dealing with in this domain are positive, we+define a "positive integer" type. This is a newtype for `Natural` that doesn't+allow zero.++```haskell+newtype Pos = Pos Natural+ deriving (Eq, Ord)++instance Num Pos where+ fromInteger = Pos . checkForUnderflow . fromInteger+ Pos x + Pos y = Pos (x + y)+ Pos x - Pos y = Pos (checkForUnderflow (x - y))+ Pos x * Pos y = Pos (x * y)+ abs = id+ signum _ = Pos 1+ negate _ = throw Underflow++checkForUnderflow :: Natural -> Natural+checkForUnderflow n =+ if n == 0 then throw Underflow else n+```++`Pos` does not have an `Integral` instance, because that would require+implementing `quotRem :: Pos -> Pos -> (Pos, Pos)`, which doesn't make much+sense. Therefore we can't use `toInteger` on `Pos`. Instead we use our own+`ToNat` class to convert positive numbers to natural numbers.++```haskell+class ToNat a where+ toNat :: a -> Natural++instance ToNat Pos where+ toNat (Pos n) = n+```++## `Line`, `Column`++We then add some newtypes to be more specific about whether we're talking about+line or column numbers.++```haskell+newtype Line = Line Pos+ deriving (Eq, Ord, Num, Real, Enum, ToNat)++newtype Column = Column Pos+ deriving (Eq, Ord, Num, Real, Enum, ToNat)+```++## `Loc`++A `Loc` is a `Line` and a `Column`.++```haskell+data Loc = Loc+ { line :: Line+ , column :: Column+ }+ deriving (Eq, Ord)+```++Note that this library has chosen to be remain entirely agnostic of the text+that the positions are referring to. Therefore there is no "plus one" operation+on `Loc`, because the next `Loc` after *4:17* could be either *4:18* or *5:1* -+we can't tell without knowing the line lengths.++## `Span`++A `Span` is a start `Loc` and an end `Loc`.++```haskell+data Span = Span+ { start :: Loc+ , end :: Loc+ } deriving (Eq, Ord)+```++A `Span` is not allowed to be empty; in other words, `start` and `end` must be+different.++There are two functions for constructing a `Span`. They both reorder their+arguments as appropriate to make sure the start comes before the end (so that+spans are never backwards). They take different approaches to ensuring that+spans are never empty: the first can throw an exception, whereas the second is+typed as `Maybe`.++```haskell+fromTo :: Loc -> Loc -> Span+fromTo a b =+ maybe (throw EmptySpan) id (fromToMay a b)++fromToMay :: Loc -> Loc -> Maybe Span+fromToMay a b =+ case compare a b of+ LT -> Just (Span a b)+ GT -> Just (Span b a)+ EQ -> Nothing+```++The choice to use an exclusive upper bound *\[start, end)* rather than two+inclusive bounds *\[start, end\]* is forced by the decision to be text-agnostic.+With inclusive ranges, you couldn't tell whether span *4:16-4:17* abuts span+*5:1-5:2* without knowing whether the character at position *4:17* is a newline.++## `Area`++Conceptually, an area is a set of spans. To support efficient union and+difference operations, `Area` is defined like this:++```haskell+data Terminus = Start | End+ deriving (Eq, Ord)++newtype Area = Area (Map Loc Terminus)+ deriving (Eq, Ord)+```++You can think of this as a sorted list of the spans' start and end positions,+along with a tag indicating whether each is a start or an end.++## `Show`++We define custom `Show` and `Read` instances to be able to write terse+[doctests](https://hackage.haskell.org/package/doctest) like++```haskell+>>> addSpan (read "1:1-6:1") (read "[1:1-3:1,6:1-6:2,7:4-7:5]")+[1:1-6:2,7:4-7:5]+```++These are the `showsPrec` implementations for `Loc` and `Span`:++```haskell+locShowsPrec :: Int -> Loc -> ShowS+locShowsPrec _ (Loc l c) =+ shows l .+ showString ":" .+ shows c++spanShowsPrec :: Int -> Span -> ShowS+spanShowsPrec _ (Span a b) =+ locShowsPrec 10 a .+ showString "-" .+ locShowsPrec 10 b+```++## `Read`++The parser for `Pos` is based on the parser for `Natural`, applying `mfilter (/=+0)` to make the parser fail if the input represents a zero.++```haskell+posReadPrec :: ReadPrec Pos+posReadPrec =+ Pos <$> mfilter (/= 0) readPrec+```++As a reminder, the type of `mfilter` is:++```haskell+mfilter :: MonadPlus m => (a -> Bool) -> m a -> m a+```++The `Loc` parser uses a very typical `Applicative` pattern:++```haskell+-- | Parses a single specific character.+readPrecChar :: Char -> ReadPrec ()+readPrecChar = void . readP_to_Prec . const . ReadP.char++locReadPrec :: ReadPrec Loc+locReadPrec =+ Loc <$>+ readPrec <*+ readPrecChar ':' <*>+ readPrec+```++We used `mfilter` above to introduce failure into the `Pos` parser; for `Span`+we use `empty`.++```haskell+empty :: Alternative f => f a+```++First we use `fromToMay` to produce a `Maybe Span`, and then in the case where+the result is `Nothing` we use `empty` to make the parser fail.++```haskell+spanReadPrec :: ReadPrec Span+spanReadPrec =+ locReadPrec >>= \a ->+ readPrecChar '-' *>+ locReadPrec >>= \b ->+ maybe empty pure (fromToMay a b)+```++## Comparison to similar packages++### `srcloc`++[srcloc](https://hackage.haskell.org/package/srcloc) has a similar general+purpose: defining types related to positions in text files.++Some differences:++* `srcloc`'s `Pos` type (comparable to our `Loc` type) has a `FilePath`+ parameter, whereas this library doesn't consider file paths at all.+* `srcloc` has nothing comparable to the `Area` type.++There are some undocumented aspects of `srcloc` we find confusing:++* What does "character offset" mean?+* Does `srcloc`'s `Loc` type use inclusive or exclusive bounds?
+ example.png view
binary file changed (absent → 58574 bytes)
+ example.svg view
@@ -0,0 +1,411 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!-- Created with Inkscape (http://www.inkscape.org/) -->++<svg+ xmlns:dc="http://purl.org/dc/elements/1.1/"+ xmlns:cc="http://creativecommons.org/ns#"+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"+ xmlns:svg="http://www.w3.org/2000/svg"+ xmlns="http://www.w3.org/2000/svg"+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"+ width="119.54762mm"+ height="52.56461mm"+ viewBox="0 0 119.54762 52.56461"+ version="1.1"+ id="svg8"+ inkscape:version="0.92.0 r15299"+ sodipodi:docname="example.svg"+ inkscape:export-filename="/home/chris/chris-martin.org/in/posts/2017-05-09-loc/example.png"+ inkscape:export-xdpi="185.481"+ inkscape:export-ydpi="185.481">+ <defs+ id="defs2" />+ <sodipodi:namedview+ id="base"+ pagecolor="#ffffff"+ bordercolor="#666666"+ borderopacity="1.0"+ inkscape:pageopacity="0.0"+ inkscape:pageshadow="2"+ inkscape:zoom="1.4"+ inkscape:cx="184.29443"+ inkscape:cy="134.58074"+ inkscape:document-units="mm"+ inkscape:current-layer="layer1"+ showgrid="false"+ inkscape:snap-nodes="false"+ inkscape:snap-global="false"+ inkscape:window-width="1920"+ inkscape:window-height="1016"+ inkscape:window-x="0"+ inkscape:window-y="27"+ inkscape:window-maximized="1"+ fit-margin-top="2"+ fit-margin-left="2"+ fit-margin-right="2"+ fit-margin-bottom="2" />+ <metadata+ id="metadata5">+ <rdf:RDF>+ <cc:Work+ rdf:about="">+ <dc:format>image/svg+xml</dc:format>+ <dc:type+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />+ <dc:title></dc:title>+ </cc:Work>+ </rdf:RDF>+ </metadata>+ <g+ inkscape:label="Layer 1"+ inkscape:groupmode="layer"+ id="layer1"+ transform="translate(-40.943916,-27.525532)">+ <rect+ style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.13800001;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#898200;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.14111111;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"+ id="rect4898"+ width="12.552429"+ height="4.21416"+ x="74.334846"+ y="48.584148" />+ <text+ xml:space="preserve"+ style="font-style:normal;font-weight:normal;font-size:4.23333311px;line-height:4.93888903px;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+ x="43.832203"+ y="52.181114"+ id="text4487"><tspan+ sodipodi:role="line"+ id="tspan4485"+ x="43.832203"+ y="52.181114"+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.23333311px;line-height:4.93888903px;font-family:'Fira Mono';-inkscape-font-specification:'Fira Mono';stroke-width:0.26458332px">Lorem ipsum dolor sit amet, consectetur</tspan><tspan+ sodipodi:role="line"+ x="43.832203"+ y="57.202133"+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.23333311px;line-height:4.93888903px;font-family:'Fira Mono';-inkscape-font-specification:'Fira Mono';stroke-width:0.26458332px"+ id="tspan4489">adipiscing elit, sed do eiusmod tempor</tspan><tspan+ sodipodi:role="line"+ x="43.832203"+ y="62.223156"+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.23333311px;line-height:4.93888903px;font-family:'Fira Mono';-inkscape-font-specification:'Fira Mono';stroke-width:0.26458332px"+ id="tspan4491">incididunt ut labore et dolore magna aliqua.</tspan></text>+ <path+ style="fill:none;fill-rule:evenodd;stroke:#d69000;stroke-width:0.35277778;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"+ d="m 53.861606,47.913689 v 5.575149"+ id="path4493"+ inkscape:connector-curvature="0" />+ <text+ xml:space="preserve"+ style="font-style:normal;font-weight:normal;font-size:4.23333311px;line-height:4.93888903px;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#d69000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+ x="52.474232"+ y="40.50515"+ id="text4497"><tspan+ sodipodi:role="line"+ id="tspan4495"+ x="52.474232"+ y="40.50515"+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.23333311px;font-family:Merriweather;-inkscape-font-specification:Merriweather;fill:#d69000;fill-opacity:1;stroke-width:0.26458332px">Loc 1:5</tspan></text>+ <text+ id="text4787"+ y="37.443539"+ x="79.263298"+ style="font-style:normal;font-weight:normal;font-size:4.23333311px;line-height:4.93888903px;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#898200;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+ xml:space="preserve"><tspan+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.23333311px;font-family:Merriweather;-inkscape-font-specification:Merriweather;fill:#898200;fill-opacity:1;stroke-width:0.26458332px"+ y="37.443539"+ x="79.263298"+ sodipodi:role="line"+ id="tspan4853">Span 1:13-1:18</tspan></text>+ <path+ style="fill:#d69000;fill-opacity:1;fill-rule:evenodd;stroke:#d69000;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"+ d="m 53.821401,41.54614 v 4.482401"+ id="path4499"+ inkscape:connector-curvature="0"+ sodipodi:nodetypes="cc" />+ <path+ sodipodi:type="star"+ style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#d69000;fill-opacity:1;fill-rule:nonzero;stroke:#d69000;stroke-width:0.33763754;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"+ id="path4815"+ sodipodi:sides="3"+ sodipodi:cx="53.721176"+ sodipodi:cy="45.499374"+ sodipodi:r1="1.7372519"+ sodipodi:r2="0.86862594"+ sodipodi:arg1="1.5707963"+ sodipodi:arg2="2.6179939"+ inkscape:flatsided="false"+ inkscape:rounded="0"+ inkscape:randomized="0"+ d="m 53.721176,47.236626 -0.752252,-1.302939 -0.752252,-1.302939 1.504504,0 1.504504,0 -0.752252,1.302939 z"+ inkscape:transform-center-y="0.068559171"+ transform="matrix(0.42264893,0,0,0.41327698,31.116206,27.39379)" />+ <path+ inkscape:connector-curvature="0"+ id="path4817"+ d="m 44.069338,47.913689 v 5.575149"+ style="fill:none;fill-rule:evenodd;stroke:#d60000;stroke-width:0.35277778;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />+ <text+ id="text4839"+ y="32.671593"+ x="42.741344"+ style="font-style:normal;font-weight:normal;font-size:4.23333311px;line-height:4.93888903px;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#d60000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+ xml:space="preserve"><tspan+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.23333311px;font-family:Merriweather;-inkscape-font-specification:Merriweather;fill:#d60000;fill-opacity:1;stroke-width:0.26458332px"+ y="32.671593"+ x="42.741344"+ id="tspan4837"+ sodipodi:role="line">Loc 1:1</tspan></text>+ <path+ inkscape:connector-curvature="0"+ id="path4841"+ d="m 43.899526,33.806143 v 12.2224"+ style="fill:#d60000;fill-opacity:1;fill-rule:evenodd;stroke:#d60000;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"+ sodipodi:nodetypes="cc" />+ <path+ transform="matrix(0.42264893,0,0,0.41327698,21.194331,27.39379)"+ inkscape:transform-center-y="0.068559171"+ d="m 53.721176,47.236626 -0.752252,-1.302939 -0.752252,-1.302939 1.504504,0 1.504504,0 -0.752252,1.302939 z"+ inkscape:randomized="0"+ inkscape:rounded="0"+ inkscape:flatsided="false"+ sodipodi:arg2="2.6179939"+ sodipodi:arg1="1.5707963"+ sodipodi:r2="0.86862594"+ sodipodi:r1="1.7372519"+ sodipodi:cy="45.499374"+ sodipodi:cx="53.721176"+ sodipodi:sides="3"+ id="path4843"+ style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#d60000;fill-opacity:1;fill-rule:nonzero;stroke:#d60000;stroke-width:0.33763754;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"+ sodipodi:type="star" />+ <path+ inkscape:connector-curvature="0"+ id="path4857"+ d="m 80.468723,38.834159 v 7.723547"+ style="fill:#898200;fill-opacity:1;fill-rule:evenodd;stroke:#898200;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />+ <path+ transform="matrix(0.42264893,0,0,0.41327698,57.763529,27.922957)"+ inkscape:transform-center-y="0.068559171"+ d="m 53.721176,47.236626 -0.752252,-1.302939 -0.752252,-1.302939 1.504504,0 1.504504,0 -0.752252,1.302939 z"+ inkscape:randomized="0"+ inkscape:rounded="0"+ inkscape:flatsided="false"+ sodipodi:arg2="2.6179939"+ sodipodi:arg1="1.5707963"+ sodipodi:r2="0.86862594"+ sodipodi:r1="1.7372519"+ sodipodi:cy="45.499374"+ sodipodi:cx="53.721176"+ sodipodi:sides="3"+ id="path4859"+ style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#898200;fill-opacity:1;fill-rule:nonzero;stroke:#898200;stroke-width:0.33763754;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"+ sodipodi:type="star" />+ <path+ inkscape:connector-curvature="0"+ id="path4888"+ d="m 142.76163,47.913689 v 5.575149"+ style="fill:none;fill-rule:evenodd;stroke:#6ab59b;stroke-width:0.35277778;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />+ <text+ id="text4892"+ y="40.50515"+ x="141.37424"+ style="font-style:normal;font-weight:normal;font-size:4.23333311px;line-height:4.93888903px;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#6ab59b;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+ xml:space="preserve"><tspan+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.23333311px;font-family:Merriweather;-inkscape-font-specification:Merriweather;fill:#6ab59b;fill-opacity:1;stroke-width:0.26458332px"+ y="40.50515"+ x="141.37424"+ id="tspan4890"+ sodipodi:role="line">Loc 1:40</tspan></text>+ <path+ inkscape:connector-curvature="0"+ id="path4894"+ d="m 142.72142,41.612956 v 4.482401"+ style="fill:#6ab59b;fill-opacity:1;fill-rule:evenodd;stroke:#6ab59b;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"+ sodipodi:nodetypes="cc" />+ <path+ transform="matrix(0.42264893,0,0,0.41327698,120.01621,27.460606)"+ inkscape:transform-center-y="0.068559171"+ d="m 53.721176,47.236626 -0.752252,-1.302939 -0.752252,-1.302939 1.504504,0 1.504504,0 -0.752252,1.302939 z"+ inkscape:randomized="0"+ inkscape:rounded="0"+ inkscape:flatsided="false"+ sodipodi:arg2="2.6179939"+ sodipodi:arg1="1.5707963"+ sodipodi:r2="0.86862594"+ sodipodi:r1="1.7372519"+ sodipodi:cy="45.499374"+ sodipodi:cx="53.721176"+ sodipodi:sides="3"+ id="path4896"+ style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#6ab59b;fill-opacity:1;fill-rule:nonzero;stroke:#6ab59b;stroke-width:0.33763754;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"+ sodipodi:type="star" />+ <rect+ style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.18600003;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#2865a3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.14111111;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"+ id="rect4898-4"+ width="15.331899"+ height="4.3347769"+ x="86.98941"+ y="53.612862" />+ <path+ inkscape:connector-curvature="0"+ id="path4915"+ d="m 74.332062,48.592293 v 4.215314"+ style="fill:none;fill-rule:evenodd;stroke:#898200;stroke-width:0.35277778;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />+ <path+ style="fill:none;fill-rule:evenodd;stroke:#898200;stroke-width:0.35277778;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"+ d="m 86.965246,48.592293 v 4.215314"+ id="path4917"+ inkscape:connector-curvature="0" />+ <path+ inkscape:connector-curvature="0"+ id="path4915-3"+ d="m 86.965246,53.626655 v 4.321584"+ style="fill:none;fill-rule:evenodd;stroke:#2865a3;stroke-width:0.35277778;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />+ <path+ style="fill:none;fill-rule:evenodd;stroke:#2865a3;stroke-width:0.35277778;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"+ d="m 102.39444,53.626655 v 4.321584"+ id="path4934"+ inkscape:connector-curvature="0" />+ <rect+ y="53.570915"+ x="125.20956"+ height="4.7904701"+ width="15.331899"+ id="rect4936"+ style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.18600003;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#2865a3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.14111111;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />+ <path+ style="fill:none;fill-rule:evenodd;stroke:#2865a3;stroke-width:0.35277778;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"+ d="m 125.18544,53.586154 v 4.775892"+ id="path4938"+ inkscape:connector-curvature="0" />+ <rect+ style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.18600003;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#2865a3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.14111111;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"+ id="rect4898-4-7"+ width="10.019917"+ height="4.5752463"+ x="43.959404"+ y="58.546028" />+ <path+ style="fill:none;fill-rule:evenodd;stroke:#2865a3;stroke-width:0.35277778;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"+ d="m 54.005945,58.560582 v 4.561323"+ id="path4934-3"+ inkscape:connector-curvature="0" />+ <rect+ style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.18600003;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#2865a3;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.14111111;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"+ id="rect4898-4-8"+ width="15.331899"+ height="4.568501"+ x="79.387222"+ y="58.50029" />+ <path+ inkscape:connector-curvature="0"+ id="path4915-3-0"+ d="m 79.363058,58.514829 v 4.554598"+ style="fill:none;fill-rule:evenodd;stroke:#2865a3;stroke-width:0.35277778;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />+ <path+ style="fill:none;fill-rule:evenodd;stroke:#2865a3;stroke-width:0.35277778;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"+ d="m 94.792252,58.514829 v 4.554598"+ id="path4934-9"+ inkscape:connector-curvature="0" />+ <text+ xml:space="preserve"+ style="font-style:normal;font-weight:normal;font-size:4.23333311px;line-height:4.93888903px;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#2865a3;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"+ x="52.028664"+ y="77.157898"+ id="text4992"><tspan+ id="tspan4990"+ sodipodi:role="line"+ x="52.028664"+ y="77.157898"+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.23333311px;font-family:Merriweather;-inkscape-font-specification:Merriweather;fill:#2865a3;fill-opacity:1;stroke-width:0.26458332px">Area [2:18-2:24, 2:33-3:5, 3:15-3:21]</tspan></text>+ <path+ inkscape:connector-curvature="0"+ id="path4841-7"+ d="M 96.163115,73.02495 V 59.589093"+ style="fill:#2865a3;fill-opacity:1;fill-rule:evenodd;stroke:#2865a3;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />+ <path+ transform="matrix(0.42264894,0,0,-0.41327697,73.457922,78.223848)"+ inkscape:transform-center-y="-0.068556884"+ d="m 53.721176,47.236626 -0.752252,-1.302939 -0.752252,-1.302939 1.504504,0 1.504504,0 -0.752252,1.302939 z"+ inkscape:randomized="0"+ inkscape:rounded="0"+ inkscape:flatsided="false"+ sodipodi:arg2="2.6179939"+ sodipodi:arg1="1.5707963"+ sodipodi:r2="0.86862594"+ sodipodi:r1="1.7372519"+ sodipodi:cy="45.499374"+ sodipodi:cx="53.721176"+ sodipodi:sides="3"+ id="path4843-9"+ style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#2865a3;fill-opacity:1;fill-rule:nonzero;stroke:#2865a3;stroke-width:0.33763754;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"+ sodipodi:type="star" />+ <path+ style="fill:#2865a3;fill-opacity:1;fill-rule:evenodd;stroke:#2865a3;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"+ d="M 86.638115,73.038044 V 64.88076"+ id="path5014"+ inkscape:connector-curvature="0" />+ <path+ sodipodi:type="star"+ style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#2865a3;fill-opacity:1;fill-rule:nonzero;stroke:#2865a3;stroke-width:0.33763754;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"+ id="path5016"+ sodipodi:sides="3"+ sodipodi:cx="53.721176"+ sodipodi:cy="45.499374"+ sodipodi:r1="1.7372519"+ sodipodi:r2="0.86862594"+ sodipodi:arg1="1.5707963"+ sodipodi:arg2="2.6179939"+ inkscape:flatsided="false"+ inkscape:rounded="0"+ inkscape:randomized="0"+ d="m 53.721176,47.236626 -0.752252,-1.302939 -0.752252,-1.302939 1.504504,0 1.504504,0 -0.752252,1.302939 z"+ inkscape:transform-center-y="-0.068556884"+ transform="matrix(0.42264894,0,0,-0.41327697,63.932922,83.515515)" />+ <path+ style="fill:#2865a3;fill-opacity:1;fill-rule:evenodd;stroke:#2865a3;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"+ d="M 127.51224,73.02495 V 59.589093"+ id="path5022"+ inkscape:connector-curvature="0" />+ <path+ sodipodi:type="star"+ style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#2865a3;fill-opacity:1;fill-rule:nonzero;stroke:#2865a3;stroke-width:0.33763754;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"+ id="path5024"+ sodipodi:sides="3"+ sodipodi:cx="53.721176"+ sodipodi:cy="45.499374"+ sodipodi:r1="1.7372519"+ sodipodi:r2="0.86862594"+ sodipodi:arg1="1.5707963"+ sodipodi:arg2="2.6179939"+ inkscape:flatsided="false"+ inkscape:rounded="0"+ inkscape:randomized="0"+ d="m 53.721176,47.236626 -0.752252,-1.302939 -0.752252,-1.302939 1.504504,0 1.504504,0 -0.752252,1.302939 z"+ inkscape:transform-center-y="-0.068556884"+ transform="matrix(0.42264894,0,0,-0.41327697,104.80703,78.223848)" />+ <path+ inkscape:connector-curvature="0"+ id="path5026"+ d="M 53.434247,73.038044 V 64.88076"+ style="fill:#2865a3;fill-opacity:1;fill-rule:evenodd;stroke:#2865a3;stroke-width:0.26499999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />+ <path+ transform="matrix(0.42264894,0,0,-0.41327697,30.729054,83.515515)"+ inkscape:transform-center-y="-0.068556884"+ d="m 53.721176,47.236626 -0.752252,-1.302939 -0.752252,-1.302939 1.504504,0 1.504504,0 -0.752252,1.302939 z"+ inkscape:randomized="0"+ inkscape:rounded="0"+ inkscape:flatsided="false"+ sodipodi:arg2="2.6179939"+ sodipodi:arg1="1.5707963"+ sodipodi:r2="0.86862594"+ sodipodi:r1="1.7372519"+ sodipodi:cy="45.499374"+ sodipodi:cx="53.721176"+ sodipodi:sides="3"+ id="path5028"+ style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#2865a3;fill-opacity:1;fill-rule:nonzero;stroke:#2865a3;stroke-width:0.33763754;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"+ sodipodi:type="star" />+ </g>+</svg>
loc.cabal view
@@ -3,7 +3,7 @@ -- see: https://github.com/sol/hpack name: loc-version: 0.1.2.1+version: 0.1.2.2 synopsis: Types representing line and column positions and ranges in text files. description: The package name /loc/ stands for “location” and is also an allusion to the@@ -20,6 +20,11 @@ license-file: license.txt build-type: Simple cabal-version: >= 1.10++extra-source-files:+ example.png+ example.svg+ README.md library hs-source-dirs: