meyfa/selena-ide

View on GitHub
src/formatter/format.ts

Summary

Maintainability
A
0 mins
Test Coverage
import { tokenize, TokenType } from 'selena'
import { Formatter, Separator } from './formatter.js'
import { WhitespaceMemory } from './whitespace-memory.js'
import { matching, matchingAnything, matchingNothing } from './pattern/patterns.js'
import { Pattern } from './pattern/pattern.js'

function formatOptions (): Pattern {
  return matching(TokenType.PAREN_LEFT)
    .any({})
    .repeat()
    .until(TokenType.PAREN_RIGHT)
}

function formatReturn (): Pattern {
  return matching(TokenType.WORD, 'return')
    .matching({ before: Separator.SPACE }, TokenType.STRING)
}

function formatMessageBlock (): Pattern {
  return matching(TokenType.BLOCK_LEFT)
    .withOneOf({ before: Separator.NEWLINE, after: Separator.NEWLINE }, [
      formatReturn,
      formatFoundMessage,
      formatMessage,
      matchingAnything
    ])
    .repeat()
    .indentContent()
    .until(TokenType.BLOCK_RIGHT)
}

function formatMessage (): Pattern {
  return matching(TokenType.ARROW)
    .with({ after: Separator.SPACE }, formatOptions)
    .any({}) // target
    .matching({ before: Separator.SPACE }, TokenType.STRING)
    .with({ before: Separator.SPACE }, formatMessageBlock)
}

function formatFoundMessage (): Pattern {
  return matching(TokenType.WORD, '*')
    .with({}, formatMessage)
}

function formatObject (): Pattern {
  return matching(TokenType.WORD, 'object')
    .with({}, formatOptions)
    .any({ before: Separator.SPACE }) // name
    .any({ before: Separator.SPACE, after: Separator.SPACE }) // '='
    .any({}) // label
}

function formatAll (): Pattern {
  return matchingNothing()
    .withOneOf({ after: Separator.NEWLINE }, [
      formatObject,
      formatFoundMessage,
      formatMessage,
      matchingAnything
    ])
    .repeat()
}

export function format (input: string): string {
  const tokens = tokenize(input)
  const formatter = new Formatter(tokens, new WhitespaceMemory(input), {
    keepEmptyLines: 1
  })

  formatAll().apply(formatter)

  return formatter.getResult()
}