This is an alternative site for discovering Elm packages. You may be looking for the official Elm package site instead.
1.0.1

Elm.Syntax.Range

Source Code Ranges

Types

type alias Range = { start : Location , end : Location }

Range for a piece of code with a start and end

type alias Location = { row : Int , column : Int }

Source location

Functions

emptyRange : Range

Construct an empty range

combine : List Range -> Range

Compute the smallest area of a list of ranges.

Json

encode : Range -> Value

Encode a range

decode : Decoder Range

Decode a range

module Elm.Syntax.Range exposing (Location, Range, combine, decode, emptyRange, encode)

{-| Source Code Ranges


# Types

@docs Range, Location


# Functions

@docs emptyRange, combine


# Json

@docs encode, decode

-}

import Json.Decode as JD exposing (Decoder)
import Json.Decode.Extra exposing (fromResult)
import Json.Encode as JE exposing (Value)


{-| Source location
-}
type alias Location =
    { row : Int
    , column : Int
    }


{-| Range for a piece of code with a start and end
-}
type alias Range =
    { start : Location
    , end : Location
    }


{-| Construct an empty range
-}
emptyRange : Range
emptyRange =
    { start = { row = 0, column = 0 }
    , end = { row = 0, column = 0 }
    }


{-| Encode a range
-}
encode : Range -> Value
encode { start, end } =
    JE.list
        [ JE.int start.row
        , JE.int start.column
        , JE.int end.row
        , JE.int end.column
        ]


{-| Decode a range
-}
decode : Decoder Range
decode =
    JD.list JD.int
        |> JD.andThen
            (fromList >> fromResult)


fromList : List Int -> Result String Range
fromList input =
    case input of
        [ a, b, c, d ] ->
            Ok
                { start = { row = a, column = b }
                , end = { row = c, column = d }
                }

        _ ->
            Err "Invalid input list"


{-| Compute the smallest area of a list of ranges.
-}
combine : List Range -> Range
combine ranges =
    let
        starts =
            List.map .start ranges |> sortLocations

        ends =
            List.map .end ranges |> sortLocations |> List.reverse
    in
    Maybe.map2 Range (List.head starts) (List.head ends)
        |> Maybe.withDefault emptyRange


{-| Could be faster via single fold
-}
sortLocations : List Location -> List Location
sortLocations =
    List.sortWith compareLocations


compareLocations : Location -> Location -> Order
compareLocations left right =
    if left.row < right.row then
        LT
    else if right.row < left.row then
        GT
    else
        compare left.column right.column