First attempt at Python port, expand tests.
This commit is contained in:
		@@ -6,18 +6,39 @@ const testName = process.argv[2]
 | 
			
		||||
 | 
			
		||||
const tests = {
 | 
			
		||||
  'linedata:basic': async () => {
 | 
			
		||||
    const { level, line, head, tail, next } = useDocument(createStdinReader())
 | 
			
		||||
    while(await next()) {
 | 
			
		||||
      console.log(`level: ${level()} | head: ${head()} | tail: ${tail()} | line: ${line()}`)
 | 
			
		||||
    const lineData = createLineData('')
 | 
			
		||||
    const next = createStdinReader()
 | 
			
		||||
 | 
			
		||||
    while ((lineData.line = await next()) != null) {
 | 
			
		||||
      parseLine(lineData)
 | 
			
		||||
      const { level, indent, offsetHead, offsetTail, line } = lineData
 | 
			
		||||
      console.log(`| level ${level} | indent ${indent} | offsetHead ${offsetHead} | offsetTail ${offsetTail} | line ${line} |`)
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  'linedata:tabs': async () => {
 | 
			
		||||
    const { level, line, head, tail, next } = useDocument(createStdinReader(), '\t')
 | 
			
		||||
    while(await next()) {
 | 
			
		||||
      console.log(`level: ${level()} | head: ${head()} | tail: ${tail()} | line: ${line()}`)
 | 
			
		||||
    const lineData = createLineData('', '\t')
 | 
			
		||||
    const next = createStdinReader()
 | 
			
		||||
 | 
			
		||||
    while ((lineData.line = await next()) != null) {
 | 
			
		||||
      parseLine(lineData)
 | 
			
		||||
      const { level, indent, offsetHead, offsetTail, line } = lineData
 | 
			
		||||
      console.log(`| level ${level} | indent ${indent} | offsetHead ${offsetHead} | offsetTail ${offsetTail} | line ${line} |`)
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  'linedata:head-tail': async () => {
 | 
			
		||||
    const lineData = createLineData('')
 | 
			
		||||
    const next = createStdinReader()
 | 
			
		||||
 | 
			
		||||
    while ((lineData.line = await next()) != null) {
 | 
			
		||||
      parseLine(lineData)
 | 
			
		||||
      const { level, indent, offsetHead, offsetTail, line } = lineData
 | 
			
		||||
      const head = line.slice(offsetHead, offsetTail)
 | 
			
		||||
      const tail = line.slice(offsetTail + 1)
 | 
			
		||||
 | 
			
		||||
      console.log(`| head ${head} | tail ${tail} |`)
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const test = tests[testName]
 | 
			
		||||
await test()
 | 
			
		||||
await test()
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										0
									
								
								packages/python/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								packages/python/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										
											BIN
										
									
								
								packages/python/__pycache__/parser.cpython-310.pyc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								packages/python/__pycache__/parser.cpython-310.pyc
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										8
									
								
								packages/python/package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								packages/python/package.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "@terrace/python",
 | 
			
		||||
  "version": "0.0.1",
 | 
			
		||||
  "license": "MIT",
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "test": "python3 ./test/index.py"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										35
									
								
								packages/python/parser.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								packages/python/parser.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,35 @@
 | 
			
		||||
from typing import TypedDict
 | 
			
		||||
 | 
			
		||||
class LineData(TypedDict):
 | 
			
		||||
  line: str
 | 
			
		||||
  indent: str
 | 
			
		||||
  level: int
 | 
			
		||||
  offsetHead: int
 | 
			
		||||
  offsetTail: int
 | 
			
		||||
 | 
			
		||||
def createLineData(line: str = '', indent: str = ' ') -> LineData:
 | 
			
		||||
  return { "line": line, "indent": indent, "level": 0, "offsetHead": 0, "offsetTail": 0 }
 | 
			
		||||
 | 
			
		||||
def parseLine(lineData: LineData) -> LineData:
 | 
			
		||||
  # if ((typeof lineData !== 'object' || !lineData) || typeof lineData.level !== 'number') throw new Error(`'lineData' must be an object with string line and numeric level properties`)
 | 
			
		||||
  # if (typeof lineData.indent !== 'string' || lineData.indent.length === 0 || lineData.indent.length > 1) throw new Error(`'lineData.indent' must be a single-character string`)
 | 
			
		||||
  # if (typeof lineData.line !== 'string') throw new Error(`'lineData.line' must be a string`)
 | 
			
		||||
 | 
			
		||||
  level = 0
 | 
			
		||||
 | 
			
		||||
  # Repeat previous level for blank lines.
 | 
			
		||||
  if len(lineData['line']) == 0:
 | 
			
		||||
    lineData['level'] = lineData['level']
 | 
			
		||||
    lineData['offsetHead'] = 0
 | 
			
		||||
    lineData['offsetTail'] = 0
 | 
			
		||||
  else:
 | 
			
		||||
    while level < len(lineData['line']) and lineData['line'][level] == lineData['indent'] and level <= lineData['level'] + 1:
 | 
			
		||||
      level += 1
 | 
			
		||||
    lineData['level'] = level
 | 
			
		||||
    lineData['offsetHead'] = level
 | 
			
		||||
    lineData['offsetTail'] = level
 | 
			
		||||
 | 
			
		||||
    while lineData['offsetTail'] < len(lineData['line']) and lineData['line'][lineData['offsetTail']] != ' ':
 | 
			
		||||
      lineData['offsetTail'] += 1
 | 
			
		||||
 | 
			
		||||
  return lineData
 | 
			
		||||
							
								
								
									
										58
									
								
								packages/python/test/index.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								packages/python/test/index.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,58 @@
 | 
			
		||||
import sys
 | 
			
		||||
import os
 | 
			
		||||
 | 
			
		||||
sys.path.insert(1, os.path.join(sys.path[0], '..'))
 | 
			
		||||
 | 
			
		||||
from parser import createLineData, parseLine
 | 
			
		||||
 | 
			
		||||
def next():
 | 
			
		||||
  return sys.stdin.readline().rstrip('\n')
 | 
			
		||||
 | 
			
		||||
def linedata_basic ():
 | 
			
		||||
  lineData = createLineData('')
 | 
			
		||||
 | 
			
		||||
  while l := next():
 | 
			
		||||
    lineData['line'] = l
 | 
			
		||||
    parseLine(lineData)
 | 
			
		||||
    print("| level {level} | indent {indent} | offsetHead {offsetHead} | offsetTail {offsetTail} | line {line} |".format(
 | 
			
		||||
      level = lineData['level'], indent = lineData['indent'], offsetHead = lineData['offsetHead'], offsetTail = lineData['offsetTail'], line = lineData['line']
 | 
			
		||||
    ))
 | 
			
		||||
 | 
			
		||||
def linedata_tabs ():
 | 
			
		||||
  lineData = createLineData('', '\t')
 | 
			
		||||
 | 
			
		||||
  while l := next():
 | 
			
		||||
    lineData['line'] = l
 | 
			
		||||
    parseLine(lineData)
 | 
			
		||||
    print("| level {level} | indent {indent} | offsetHead {offsetHead} | offsetTail {offsetTail} | line {line} |".format(
 | 
			
		||||
      level = lineData['level'], indent = lineData['indent'], offsetHead = lineData['offsetHead'], offsetTail = lineData['offsetTail'], line = lineData['line']
 | 
			
		||||
    ))
 | 
			
		||||
 | 
			
		||||
def linedata_head_tail ():
 | 
			
		||||
  lineData = createLineData('')
 | 
			
		||||
 | 
			
		||||
  while l := next():
 | 
			
		||||
    lineData['line'] = l
 | 
			
		||||
    parseLine(lineData)
 | 
			
		||||
    head = lineData['line'][lineData['offsetHead']:lineData['offsetTail']] if len(lineData['line']) > lineData['offsetTail'] else ''
 | 
			
		||||
    tail = lineData['line'][lineData['offsetTail'] + 1:] if len(lineData['line']) > lineData['offsetTail'] + 1 else ''
 | 
			
		||||
 | 
			
		||||
    print("| head {head} | tail {tail} |".format(
 | 
			
		||||
      head = head, tail = tail
 | 
			
		||||
    ))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
tests = {
 | 
			
		||||
  'linedata:basic': linedata_basic,
 | 
			
		||||
  'linedata:tabs': linedata_tabs,
 | 
			
		||||
  'linedata:head-tail': linedata_head_tail
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def main():
 | 
			
		||||
  testName = sys.argv[1]
 | 
			
		||||
  test = tests[testName]
 | 
			
		||||
  test()
 | 
			
		||||
 | 
			
		||||
if __name__ == "__main__":
 | 
			
		||||
  main()
 | 
			
		||||
		Reference in New Issue
	
	Block a user