sexpr_writer.py 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. # Flexlay - A Generic 2D Game Editor
  2. # Copyright (C) 2014 Ingo Ruhnke <grumbel@gmail.com>
  3. #
  4. # This program is free software: you can redistribute it and/or modify
  5. # it under the terms of the GNU General Public License as published by
  6. # the Free Software Foundation, either version 3 of the License, or
  7. # (at your option) any later version.
  8. #
  9. # This program is distributed in the hope that it will be useful,
  10. # but WITHOUT ANY WARRANTY without even the implied warranty of
  11. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. # GNU General Public License for more details.
  13. #
  14. # You should have received a copy of the GNU General Public License
  15. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. from typing import Any, IO, Optional, Union
  17. from flexlay.math.point import Point, Pointf
  18. from flexlay.math.rect import Rect, Rectf
  19. from flexlay.math.size import Size, Sizef
  20. from flexlay.field import Field
  21. SExprValue = Union[bool, int, float, str, list]
  22. def write_sexpr(fout: IO[str], sexpr: SExprValue, indent: int = 0) -> None:
  23. if isinstance(sexpr, list):
  24. fout.write("(\n")
  25. for i, e in enumerate(sexpr):
  26. write_sexpr(fout, e)
  27. if i != len(sexpr) - 1:
  28. fout.write(" \n")
  29. fout.write(")\n")
  30. else:
  31. # if sexpr.is_a?(Symbol):
  32. # fout.write(str(sexpr))
  33. # else:
  34. fout.write(repr(sexpr))
  35. class SExprWriter:
  36. def __init__(self, fout: IO[str]) -> None:
  37. self.fout = fout
  38. self.indent_depth = 0
  39. def write_comment(self, comment: str) -> None:
  40. self.fout.write(";; " + comment + "\n")
  41. def begin_list(self, listname: str) -> None:
  42. self.indent()
  43. self.fout.write("(" + listname + "\n")
  44. self.indent_depth += 2
  45. def end_list(self, listname: Optional[str] = None) -> None:
  46. self.indent_depth -= 2
  47. self.indent()
  48. self.fout.write(")\n")
  49. def write(self, name: str, value: SExprValue) -> None:
  50. if isinstance(value, bool):
  51. self.write_bool(name, value)
  52. elif isinstance(value, int):
  53. self.write_int(name, value)
  54. elif isinstance(value, float):
  55. self.write_float(name, value)
  56. elif isinstance(value, str):
  57. self.write_string(name, value)
  58. elif isinstance(value, list):
  59. self.write_vector(name, value)
  60. else:
  61. raise RuntimeError("unknown requested in generic write(): %r" % type(value))
  62. def write_bool(self, name: str, value: bool) -> None:
  63. self.indent()
  64. self.fout.write("(" + name + " ")
  65. if value:
  66. self.fout.write("#t")
  67. else:
  68. self.fout.write("#f")
  69. self.fout.write(")\n")
  70. def write_int(self, name: str, value: int) -> None:
  71. self.indent()
  72. self.fout.write("(%s %d)\n" % (name, value))
  73. def write_float(self, name: str, value: float) -> None:
  74. self.indent()
  75. # %f makes ugly floats, e.g. 45.000000, %s gives nicely
  76. # trimmed ones, e.g. "45.0"
  77. self.fout.write("(%s %s)\n" % (name, value))
  78. def write_tr_string(self, name: str, value: str) -> None:
  79. self.write_string(name, value, translatable=True)
  80. def write_string(self, name: str, value: str, translatable: bool = False) -> None:
  81. self.indent()
  82. self.fout.write("(" + name)
  83. if translatable:
  84. self.fout.write(" (_ \"" + value.replace('"', '\\"') + "\"))\n")
  85. else:
  86. self.fout.write(" \"" + value.replace('"', '\\"') + "\")\n")
  87. def write_rgb(self, name: str, color: list[float]) -> None:
  88. self.indent()
  89. self.fout.write("(" + name)
  90. self.fout.write(" %s %s %s)\n" % (color[0], color[1], color[2]))
  91. def write_inline_point(self, pos: Point) -> None:
  92. self.write_int("x", pos.x)
  93. self.write_int("y", pos.y)
  94. def write_inline_pointf(self, pos: Pointf) -> None:
  95. if pos.x != 0.0:
  96. self.write_float("x", pos.x)
  97. if pos.y != 0.0:
  98. self.write_float("y", pos.y)
  99. def write_inline_size(self, size: Size) -> None:
  100. self.write_int("width", size.width)
  101. self.write_int("height", size.height)
  102. def write_inline_sizef(self, size: Sizef) -> None:
  103. self.write_float("width", size.width)
  104. self.write_float("height", size.height)
  105. def write_inline_rect(self, rect: Rect) -> None:
  106. # ugly this way around, but for compatibilty with the C# supertux-editor
  107. self.write_int("width", rect.width)
  108. self.write_int("height", rect.height)
  109. self.write_int("x", rect.left)
  110. self.write_int("y", rect.top)
  111. def write_inline_rectf(self, rect: Rectf) -> None:
  112. # ugly this way around, but for compatibilty with the C# supertux-editor
  113. self.write_float("width", rect.width)
  114. self.write_float("height", rect.height)
  115. self.write_float("x", rect.left)
  116. self.write_float("y", rect.top)
  117. def write_vector(self, name: str, values: list[Any]) -> None:
  118. self.indent()
  119. self.fout.write("(" + name)
  120. for i in values:
  121. self.fout.write(" %r" % i)
  122. self.fout.write(")\n")
  123. def write_color(self, name: str, values: list[float]) -> None:
  124. self.indent()
  125. self.fout.write("(" + name)
  126. for i in values:
  127. if i == 1.0:
  128. self.fout.write(" 1")
  129. elif i == 0:
  130. self.fout.write(" 0")
  131. else:
  132. self.fout.write(" %r" % i)
  133. self.fout.write(")\n")
  134. def write_field(self, name: str, field: Field) -> None:
  135. self.indent()
  136. self.fout.write("(%s\n" % name)
  137. for y in range(0, field.height):
  138. self.indent()
  139. for x in range(0, field.width):
  140. if x < field.width - 1:
  141. self.fout.write("%d " % field.at(x, y))
  142. else:
  143. self.fout.write("%d" % field.at(x, y))
  144. self.fout.write("\n")
  145. self.indent()
  146. self.fout.write(")\n")
  147. def indent(self) -> None:
  148. self.fout.write(" " * self.indent_depth)
  149. # EOF #