experimental/text_layouter

    Dark Mode
Search:
  Source   Edit

..include:: text_layouter.rst

Types

Layout = ref object
  elements: seq[LayoutElement]
An object containing a sequence of directives to the console.   Source   Edit
LytAlignDirection = enum
  lAlignLeft, lAlignRight, lAlignCenter
  Source   Edit
LytBlock = ref object
  layoutCache: Table[Option[LytSolution], Option[LytSolution]]
  isBreaking* {.requiresInit.}: bool ## Whether or not this block should end the line
  breakMult* {.requiresInit.}: int ## Local line break cost change
  id {.requiresInit.}: int
  case kind*: LytBlockKind
  of bkVerb:
      textLines*: seq[LytStrSpan] ## Multiple lines of text
      firstNl*: bool         ## Insert newline at the block start
    
  of bkText:
      text*: LytStrSpan      ## A single line of text, free of carriage
                             ## returs etc.
    
  of bkWrap:
      prefix*: Option[LytStr]
      sep*: LytStr           ## Separator for block wraps
      wrapElements*: seq[LytBlock]

  of bkStack, bkChoice, bkLine:
      elements*: seq[LytBlock]

  of bkEmpty:
      nil

  
  Source   Edit
LytBlockKind = enum
  bkText,                   ## A layout consisting of a single line of unbroken text.
  bkLine,                   ## Horizontally stacked lines
  bkChoice,                 ## Several alternating layouts
  bkStack,                  ## Vertically stacked layouts
  bkWrap,                   ## Mulitple blocks wrapped to create lowerst-cost layout
  bkVerb,                   ## Multiple lines verbatim
  bkEmpty                    ## Empty layout block - ignored by `add` etc.
  Source   Edit
LytEvent = object
  case kind*: LytEventKind
  of layEvStr:
      str*: LytStr

  of layEvSpaces:
      spaces*: int

  of layEvNewline:
      nil

  
  Source   Edit
LytEventKind = enum
  layEvStr, layEvNewline, layEvSpaces
  Source   Edit
LytOptions = object
  leftMargin*: int           ## position of the first right margin. Expected `0`
  rightMargin*: int          ## position of the second right margin. Set for `80`
                             ## to wrap on default column limit.
  leftMarginCost*: float     ## cost (per character) beyond margin 0.
                             ## Expected value `~0.05`
  rightMarginCost*: float    ## cost (per character) beyond margin 1. Should
                             ## be much higher than `c0`. Expected value
                             ## `~100`
  linebreakCost*: int        ## cost per line-break
  indentSpaces*: int         ## spaces per indent
  cpack*: float              ## cost (per element) for packing justified layouts.
                             ## Expected value `~0.001`
  formatPolicy*: LytFormatPolicy
  Source   Edit
LytStr = object
  id*: LytStrId              ## Id of the original piece of text
  len*: int ## It's lengh in units (units are specified - can be ASCII or
            ## unicode or anything else)
  
Single layout string object. It contains all the information required to perform the layout and refer back to the original string piece if needed.   Source   Edit
LytStrId = distinct uint64
  Source   Edit
LytStrIdMask {.inject.} = distinct uint64
  Source   Edit
LytStrSpan = object
  strs: seq[LytStr]
  len: int
Span of multiple layout strings   Source   Edit
OutConsole = object
  leftMargin: int
  rightMargin: int
  hPos: int                  ## Horizontal position on the output console
  margins: seq[int]
  Source   Edit

Consts

EmptyLytStr = (id: 0'u64, len: 0)
  Source   Edit
EmptyLytStrId = 0'u64
  Source   Edit
LytSpacesId = 9223372036854775687'u64
  Source   Edit

Procs

proc `$`(blc: LytBlock): string {....raises: [ValueError], tags: [].}
  Source   Edit
func `$`(id: LytStrId): string {....raises: [], tags: [].}
  Source   Edit
func `$`(le: LayoutElement): string {....raises: [ValueError], tags: [].}
  Source   Edit
proc `$`(sln: LytSolution): string {....raises: [ValueError, CatchableError],
                                     tags: [].}
  Source   Edit
proc `$`(sln: Option[LytSolution]): string {.
    ...raises: [ValueError, CatchableError], tags: [].}
  Source   Edit
func `==`(i1, i2: LytStrId): bool {....raises: [], tags: [].}
  Source   Edit
func `==`(m1`gensym3, m2`gensym3: LytStrIdMask): bool {.inject, ...raises: [],
    tags: [].}
  Source   Edit
func `[]`(blc: LytBlock; idx: int): LytBlock {....raises: [], tags: [].}
  Source   Edit
func `[]`(blc: var LytBlock; idx: int): var LytBlock {....raises: [], tags: [].}
  Source   Edit
proc add(target: var LytBlock; other: varargs[LytBlock]) {....raises: [], tags: [].}
  Source   Edit
proc alignLeft(span: sink LytStrSpan; target: int): LytStrSpan {....raises: [],
    tags: [].}
  Source   Edit
proc convertBlock(bk: LytBlock; newKind: LytBlockKind): LytBlock {....raises: [],
    tags: [].}
  Source   Edit
proc doOptLayout(self: var LytBlock; rest: var Option[LytSolution];
                 opts: LytOptions): Option[LytSolution] {.
    ...raises: [ValueError, CatchableError, Exception, KeyError],
    tags: [RootEffect].}
  Source   Edit
proc expectValid(bl: LytBlock; msg: string = "") {....raises: [], tags: [].}
  Source   Edit
func filterEmpty(blocks: openArray[LytBlock]): seq[LytBlock] {....raises: [],
    tags: [].}
  Source   Edit
func flatten(bl: LytBlock; kind: set[LytBlockKind]): LytBlock {....raises: [],
    tags: [].}
  Source   Edit
func getMask(id`gensym3: LytStrId): LytStrIdMask {.inject, ...raises: [], tags: [].}
  Source   Edit
proc initAlignedGrid(blocks: seq[seq[LytBlock]]; aligns: openArray[
    tuple[leftPad, rightPad: int, direction: LytAlignDirection]]): LytBlock {.
    ...raises: [], tags: [].}
  Source   Edit
proc initAlignedGrid(blocks: seq[seq[LytBlock]];
                     aligns: openArray[LytAlignDirection]): LytBlock {.
    ...raises: [], tags: [].}
  Source   Edit
proc initBlock(kind: LytBlockKind; breakMult: int = 1): LytBlock {....raises: [],
    tags: [].}
  Source   Edit
proc initChoiceBlock(elems: openArray[LytBlock]; breakMult: int = 1): LytBlock {.
    ...raises: [], tags: [].}
  Source   Edit
func initEmptyBlock(): LytBlock {....raises: [], tags: [].}
  Source   Edit
proc initHSeparated(blocks: seq[LytBlock]; sep: LytBlock): LytBlock {.
    ...raises: [], tags: [].}
  Source   Edit
proc initIndentBlock(blc: LytBlock; indent: int; breakMult: int = 1): LytBlock {.
    ...raises: [], tags: [].}
  Source   Edit
proc initLineBlock(elems: openArray[LytBlock]; breakMult: int = 1): LytBlock {.
    ...raises: [], tags: [].}
  Source   Edit
proc initLytOptions(): LytOptions {....raises: [], tags: [].}
  Source   Edit
proc initSeparated(blocks: seq[LytBlock]; vertical: bool; sep: LytBlock): LytBlock {.
    ...raises: [], tags: [].}
  Source   Edit
proc initStackBlock(elems: openArray[LytBlock]; breakMult: int = 1): LytBlock {.
    ...raises: [], tags: [].}
  Source   Edit
proc initTextBlock(text: LytStr; breakMult: int = 1; breaking: bool = false): LytBlock {.
    ...raises: [], tags: [].}
  Source   Edit
proc initTextBlock(text: LytStrSpan; breakMult: int = 1; breaking: bool = false): LytBlock {.
    ...raises: [], tags: [].}
  Source   Edit
proc initVerbBlock(textLines: openArray[LytStrSpan]; breaking: bool = true;
                   firstNl: bool = false; breakMult: int = 1): LytBlock {.
    ...raises: [], tags: [].}
  Source   Edit
proc initVSeparated(blocks: seq[LytBlock]; sep: LytBlock): LytBlock {.
    ...raises: [], tags: [].}
  Source   Edit
proc initWrapBlock(elems: openArray[LytBlock]; sep: LytStr; breakMult: int = 1): LytBlock {.
    ...raises: [], tags: [].}
  Source   Edit
func isEmpty(bl: LytBlock): bool {.inline, ...raises: [], tags: [].}
  Source   Edit
func isEmpty(s: LytStr): bool {....raises: [], tags: [].}
  Source   Edit
func isNil(i: LytStrId): bool {....raises: [], tags: [].}
  Source   Edit
func isSpaces(s: LytStr): bool {....raises: [], tags: [].}
  Source   Edit
proc join(blocks: LytBlock; sep: LytBlock; vertLines: bool = true): LytBlock {.
    ...raises: [], tags: [].}
  Source   Edit
proc join(blocks: seq[LytBlock]; sep: LytBlock; direction: LytBlockKind): LytBlock {.
    ...raises: [], tags: [].}
  Source   Edit
func len(blc: LytBlock): int {....raises: [], tags: [].}
  Source   Edit
proc lytSpaces(count: int = 1): LytStr {....raises: [], tags: [].}
  Source   Edit
func lytStrIdx(idx: int; len: int): LytStr {....raises: [], tags: [].}
Create layout string object from the element index   Source   Edit
func lytStrSpan(str: LytStr): LytStrSpan {....raises: [], tags: [].}
Construct layout string span with single element   Source   Edit
func lytStrSpan(strs: openArray[LytStr]): LytStrSpan {....raises: [], tags: [].}
Construct layout string span from multiple elements   Source   Edit
func popMask(id`gensym3: LytStrId): LytStrId {.inject, ...raises: [], tags: [].}
  Source   Edit
func setMask(id`gensym3: var LytStrId; mask`gensym3: LytStrIdMask) {.inject,
    ...raises: [], tags: [].}
  Source   Edit
func toIndex(id: LytStrId): int {....raises: [], tags: [].}
  Source   Edit
proc toLayout(bl: LytBlock; opts: LytOptions): Layout {.
    ...raises: [ValueError, CatchableError, Exception, KeyError],
    tags: [RootEffect].}
Return first best formatting layout for a given block. This is the procedure you should be using unless you need to have access to all the possible layouts.   Source   Edit
proc toLayouts(bl: LytBlock; opts: LytOptions): seq[Layout] {.
    ...raises: [ValueError, CatchableError, Exception, KeyError],
    tags: [RootEffect].}
Return all possible formatting layouts for a given block with provided options. The best layout will be the first in the returned sequence.   Source   Edit
func toLytStrId(idx: int): LytStrId {....raises: [], tags: [].}
  Source   Edit
proc treeRepr(inBl: LytBlock; getStr: proc (str: LytStr): string = nil): string {.
    ...raises: [ValueError, Exception], tags: [RootEffect].}
  Source   Edit
func treeRepr(self: Layout; getStr: proc (s: LytStr): string = nil;
              level: int = 0): string {....raises: [ValueError, Exception],
                                        tags: [RootEffect].}
  Source   Edit
func treeRepr(self: LytSolution; getStr: proc (s: LytStr): string = nil;
              level: int = 0): string {....raises: [ValueError, Exception],
                                        tags: [RootEffect].}
  Source   Edit

Iterators

iterator formatEvents(lyt: Layout): LytEvent {....raises: [], tags: [].}
Generate formatting events for the given layout. The events are backend-agnostic and can be interpreted further by the user depending on their needs.   Source   Edit
iterator items(blc: LytBlock): LytBlock {....raises: [], tags: [].}
  Source   Edit
iterator mitems(blc: var LytBlock): var LytBlock {....raises: [], tags: [].}
  Source   Edit
iterator mpairs(blc: var LytBlock): (int, var LytBlock) {....raises: [], tags: [].}
  Source   Edit
iterator pairs(blc: LytBlock): (int, LytBlock) {....raises: [], tags: [].}
  Source   Edit
iterator rmpairs[T](s: var seq[T]): (int, var T)
Iterate over mutable sequence starting from the right   Source   Edit
iterator zip[T1, T2, T3, T4, T5](s1: seq[T1]; s2: seq[T2]; s3: seq[T3];
                                 s4: seq[T4]; s5: seq[T5]): tuple[v1: T1,
    v2: T2, v3: T3, v4: T4, v5: T5]
  Source   Edit

Templates

template addItBlock(res: LytBlock; item: typed; expr: untyped; join: LytBlock): untyped
  Source   Edit
template findSingle(elems: typed; targetKind: typed): untyped
  Source   Edit
template initBlockFormatDSL() {.dirty.}
  Source   Edit
template joinItBlock(direction: LytBlockKind; item: typed; expr: untyped;
                     join: LytBlock): untyped
  Source   Edit
template joinItLine(item: typed; expr: untyped; join: LytBlock): untyped
  Source   Edit