View Source LogicalFile (LogicalFile v1.0.4)
LogicalFile
One file from many
LogicalFile is a way of creating a logical representation of a unit of lines of text (e.g. a source code file) supplied by one or more backing files, presumably separate files on disk. It also provides for a system of macros that can transform the logical text.
A typical use case for LogicalFile would be to implement a compiler that has
#include
style functionality. The compiler works on the whole text but
can translate logical line numbers back to specific files and local line
numbers (for example when an error occurs it can pinpoint the specific file
and line the error arose in).
Link to this section Summary
Functions
assemble/2
returns a LogicalFile
composed of the Section
s specified in
the second argument. This is mainly intended for internal use when modifying
a LogicalFile
during macro processing.
contains_source?/2
returns true if at least one section from the given
LogicalFile
originates from the specified source_path
.
insert/3
inserts a new Section
into the LogicalFile
at the specified
logical line number at_line
and containing the contents of the source_path
.
last_line_number/1
returns the line number of the last line in the
specified LogicalFile
.
line/2
returns the specified logical line number from the LogicalFile
at lno
.
lines/1
returns a list of all lines in the LogicalFile
in line number
order.
lines/2
takes a LogicalFile
and a range of logical line numbers and
returns a list of tuples in the form {file, line}
for the corresponding
lines.
partition_sections/2
accepts a list of Section
s and a logical
line number at_line
representing an insertion point. It returns a tuple
{sections_before, insert_section, sections_after}
by finding the Section
containing at_line
and partitioning the remaining Section
s around it.
read/3
returns a new LogicalFile
containing Section
s that
represent the contents of the file specified by source_path
relative to
base_path
and as modified by the macros it is initialised with.
resolve_line/2
takes a logical line number logical_lno
and returns a
tuple {file, local_line_no}
representing the file and file line number
that logical line represents.
section_including_line/2
returns the Section
that contains the logical
line lno
.
sections_in_order/1
takes the Section
s backing a LogicalFile
and
returns them as a list, ordered by the range of logical line numbers they
represent.
sections_to_map/1
takes a list of Section
s and returns a Map
whose
keys are the logical line number ranges of the sections, mapped to the
corresponding sections.
size/1
returns the number of lines in the LogicalFile
.
update_line/3
replaces the content of line lno
in the specified
LogicalFile
by passing the current contents of the line to the specified
transformation function. This function is expected to return the new
contents of the line.
Link to this section Types
Specs
Link to this section Functions
assemble/2
returns a LogicalFile
composed of the Section
s specified in
the second argument. This is mainly intended for internal use when modifying
a LogicalFile
during macro processing.
contains_source?/2
returns true if at least one section from the given
LogicalFile
originates from the specified source_path
.
Examples
iex> file = LogicalFile.read("test/support", "main.source")
iex> invalid_path = Path.expand("test/support/player.source")
iex> assert not LogicalFile.contains_source?(file, invalid_path)
iex> valid_path = Path.expand("test/support/main.source")
iex> assert LogicalFile.contains_source?(file, valid_path)
insert/3
inserts a new Section
into the LogicalFile
at the specified
logical line number at_line
and containing the contents of the source_path
.
It guarantees that all sections and the logical file remains contiguous.
Examples
last_line_number/1
returns the line number of the last line in the
specified LogicalFile
.
Examples
iex> alias LogicalFile.Section
iex> file = LogicalFile.read("test/support", "main.source")
iex> assert 11 = LogicalFile.last_line_number(file)
line/2
returns the specified logical line number from the LogicalFile
at lno
.
Example
iex> file = LogicalFile.read("test/support", "main.source")
iex> assert "%(include.source)" = LogicalFile.line(file, 6)
lines/1
returns a list of all lines in the LogicalFile
in line number
order.
lines/2
takes a LogicalFile
and a range of logical line numbers and
returns a list of tuples in the form {file, line}
for the corresponding
lines.
partition_sections/2
accepts a list of Section
s and a logical
line number at_line
representing an insertion point. It returns a tuple
{sections_before, insert_section, sections_after}
by finding the Section
containing at_line
and partitioning the remaining Section
s around it.
read/3
returns a new LogicalFile
containing Section
s that
represent the contents of the file specified by source_path
relative to
base_path
and as modified by the macros it is initialised with.
Macros should implement the LogicalFile.Macro
behaviours and should be
specified as a list of tuples of the form {module, [options keyword list]}
.
See LogicalFile.Macro
for further details.
Examples
iex> file = LogicalFile.read("test/support", "main.source")
iex> assert 11 = LogicalFile.size(file)
resolve_line/2
takes a logical line number logical_lno
and returns a
tuple {file, local_line_no}
representing the file and file line number
that logical line represents.
Examples
iex> alias LogicalFile.Macros.Include
iex> file = LogicalFile.read("test/support", "main.source")
iex> path = Path.expand("test/support/main.source")
iex> assert {^path, 1} = LogicalFile.resolve_line(file, 1)
section_including_line/2
returns the Section
that contains the logical
line lno
.
Examples
iex> alias LogicalFile.Section
iex> section1 = Section.new("test/support/main.source")
iex> section2 = Section.new("test/support/include.source") |> Section.shift(Section.size(section1))
iex> map = LogicalFile.assemble("test/support", [section1, section2])
iex> assert ^section1 = LogicalFile.section_including_line(map, section1.range.first)
iex> assert ^section2 = LogicalFile.section_including_line(map, section2.range.first)
sections_in_order/1
takes the Section
s backing a LogicalFile
and
returns them as a list, ordered by the range of logical line numbers they
represent.
sections_to_map/1
takes a list of Section
s and returns a Map
whose
keys are the logical line number ranges of the sections, mapped to the
corresponding sections.
size/1
returns the number of lines in the LogicalFile
.
Examples
iex> file = LogicalFile.read("test/support", "main.source")
iex> 11 = LogicalFile.size(file)
update_line/3
replaces the content of line lno
in the specified
LogicalFile
by passing the current contents of the line to the specified
transformation function. This function is expected to return the new
contents of the line.
Examples
iex> assert " " =
...> LogicalFile.read("test/support", "main.source")
...> |> LogicalFile.update_line(6, fn line -> String.duplicate(" ", String.length(line)) end)
...> |> LogicalFile.line(6)