Safe Haskell | Safe-Inferred |
---|---|
Language | Haskell2010 |
Strongly typed indices and offsets.
The goal of this module is to make it as easy as possible to keep track of the various indexing schemes used by functions in the nvim API.
The core abstraction is the type Index
tagged with the sort of things it
is indexing (Byte
, CodePoint
, Line
) and whether things are 0-indexed
or 1-indexed.
Two constructors and two destructors are provided: toZeroIndexed
,
toOneIndexed
, fromZeroIndexed
, and fromOneIndexed
. They should only
be used to make external API calls, to unwrap input indices and to wrap
output indices. The names of those functions are self-documenting, indicating
the indexing scheme used by every index that goes in and out of the external
API.
Within Cornelis, indices remain typed at all times, using dedicated functions
to convert between 0/1-indexing (zeroIndex
, oneIndex
) and between
Byte
and CodePoint
indexing (toByte
, fromByte
).
Usually, indices are relative to a common origin (beginning of the same buffer
or line), so it doesn't make sense to add them. There is a separate type of
Offset
which can be added to indices using the operator (
.
And .+
)(
gives the offset between two indices..-.
)
i :: Index 'Byte 'ZeroIndexed i .+ Offset 42 :: Index 'Byte 'ZeroIndexed
Types of Pos
isitions (pairs of line and column indices) and Interval
s
(pairs of positions or indices) are also provided, and should be used
as much as possible to reduce the likelihood of mixing up indices.
When talking about Pos
, "(i,j)-indexed" means "i-indexed lines, j-indexed
columns".
Agda's indexing scheme (codepoints, (1,1)-indexed) is the preferred one (0- vs 1-indexing is heavily checked, so it doesn't matter much which we choose; codepoint indexing is preferred for manipulating unicode text (fewer invalid states than byte indexing)).
A secondary indexing scheme is bytes, (0,0)-indexed, used as a unified low-level representation right before talking to the nvim API.
Synopsis
- data Index (e :: Unit) (i :: Indexing)
- data Indexing
- data Unit
- newtype Offset (e :: Unit) = Offset Int
- data Pos e i j = Pos {}
- data Interval p = Interval {}
- type LineNumber = Index 'Line
- type AgdaIndex = Index 'CodePoint 'OneIndexed
- type AgdaOffset = Offset 'CodePoint
- type AgdaPos = Pos 'CodePoint 'OneIndexed 'OneIndexed
- type AgdaInterval = Interval AgdaPos
- type VimIndex = Index 'Byte 'ZeroIndexed
- type VimOffset = Offset 'Byte
- type VimPos = Pos 'Byte 'ZeroIndexed 'ZeroIndexed
- type VimInterval = Interval VimPos
- toZeroIndexed :: Integral a => a -> Index e 'ZeroIndexed
- toOneIndexed :: Integral a => a -> Index e 'OneIndexed
- fromZeroIndexed :: Num a => Index e 'ZeroIndexed -> a
- fromOneIndexed :: Num a => Index e 'OneIndexed -> a
- zeroIndex :: Index e 'OneIndexed -> Index e 'ZeroIndexed
- oneIndex :: Index e 'ZeroIndexed -> Index e 'OneIndexed
- incIndex :: Index e i -> Index e i
- (.+) :: Index e i -> Offset e -> Index e i
- (.-.) :: Index e i -> Index e i -> Offset e
- offsetPlus :: Offset a -> Offset a -> Offset a
- textToBytes :: Text -> Int
- charToBytes :: Char -> Int
- toBytes :: Text -> Index 'CodePoint 'ZeroIndexed -> Index 'Byte 'ZeroIndexed
- fromBytes :: HasCallStack => Text -> Index 'Byte 'ZeroIndexed -> Index 'CodePoint 'ZeroIndexed
- containsPoint :: Ord p => Interval p -> p -> Bool
- addCol :: Pos e i j -> Offset e -> Pos e i j
Documentation
data Index (e :: Unit) (i :: Indexing) Source #
The constructor is hidden, use toZeroIndexed
and toOneIndexed
to construct it,
and fromZeroIndexed
and fromOneIndexed
to destruct it.
Instances
FromJSON (Index e i) Source # | |
Defined in Cornelis.Offsets | |
Read (Index e i) Source # | |
Show (Index e i) Source # | |
Amor (Index e i) Source # | Ordered monoid action of offsets on indices. |
Origin (Index e 'ZeroIndexed) Source # | The zero in zero-indexing. |
Defined in Cornelis.Offsets origin :: Index e 'ZeroIndexed # | |
Eq (Index e i) Source # | |
Ord (Index e i) Source # | |
Defined in Cornelis.Offsets | |
Pretty (Index e i) Source # | |
Defined in Cornelis.Offsets | |
type Trans (Index e i) Source # | |
Defined in Cornelis.Offsets |
Indexing scheme: whether the first index is zero or one.
newtype Offset (e :: Unit) Source #
It doesn't seem worth the trouble to hide this constructor.
Instances
Position in a text file as line-column numbers. This type is indexed by
the units of the columns (Byte
or CodePoint
) and by the indexing scheme
of lines and columns.
Instances
FromJSON AgdaInterval Source # | |
Defined in Cornelis.Types parseJSON :: Value -> Parser AgdaInterval # parseJSONList :: Value -> Parser [AgdaInterval] # | |
Generic (Pos e i j) Source # | |
Show (Pos e i j) Source # | |
Eq (Pos e i j) Source # | |
Ord (Pos e i j) Source # | |
Defined in Cornelis.Offsets | |
type Rep (Pos e i j) Source # | |
Defined in Cornelis.Offsets type Rep (Pos e i j) = D1 ('MetaData "Pos" "Cornelis.Offsets" "cornelis-0.2.0.0-6a1gQdmcW6s9D29V5A3o0J" 'False) (C1 ('MetaCons "Pos" 'PrefixI 'True) (S1 ('MetaSel ('Just "p_line") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (Index 'Line i)) :*: S1 ('MetaSel ('Just "p_col") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (Index e j)))) |
Instances
type LineNumber = Index 'Line Source #
type AgdaOffset = Offset 'CodePoint Source #
type AgdaPos = Pos 'CodePoint 'OneIndexed 'OneIndexed Source #
type AgdaInterval = Interval AgdaPos Source #
type VimPos = Pos 'Byte 'ZeroIndexed 'ZeroIndexed Source #
type VimInterval = Interval VimPos Source #
toZeroIndexed :: Integral a => a -> Index e 'ZeroIndexed Source #
Mark a raw index as zero-indexed.
toOneIndexed :: Integral a => a -> Index e 'OneIndexed Source #
Mark a raw index as one-indexed.
fromZeroIndexed :: Num a => Index e 'ZeroIndexed -> a Source #
Unwrap a raw zero-indexed index.
fromOneIndexed :: Num a => Index e 'OneIndexed -> a Source #
Unwrap a raw zero-indexed index.
zeroIndex :: Index e 'OneIndexed -> Index e 'ZeroIndexed Source #
Convert from one- to zero-indexed.
oneIndex :: Index e 'ZeroIndexed -> Index e 'OneIndexed Source #
Convert from zero- to one-indexed.
toBytes :: Text -> Index 'CodePoint 'ZeroIndexed -> Index 'Byte 'ZeroIndexed Source #
Convert a character-based index into a byte-indexed one
fromBytes :: HasCallStack => Text -> Index 'Byte 'ZeroIndexed -> Index 'CodePoint 'ZeroIndexed Source #
Convert a byte-based index into a character-indexed one.