Path: blob/main/python/pylang/src/output/stream.py
1398 views
# vim:fileencoding=utf-81# License: BSD Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>2from __python__ import hash_literals34from utils import make_predicate, defaults, repeat_string5from tokenizer import is_identifier_char67DANGEROUS = RegExp(8r"[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]",9"g")101112def as_hex(code, sz):13val = code.toString(16)14if val.length < sz:15val = '0'.repeat(sz - val.length) + val16return val171819def to_ascii(str_, identifier):20def f(ch):21code = ch.charCodeAt(0).toString(16)22if code.length <= 2 and not identifier:23return "\\x" + as_hex(code, 2)24else:25return '\\u' + as_hex(code, 4)2627return str_.replace(RegExp(r"[\u0080-\uffff]", "g"), f)282930def encode_string(str_):31def f(a):32return '\\u' + as_hex(a.charCodeAt(0), 4)3334return JSON.stringify(str_).replace(DANGEROUS, f)353637require_semi_colon_chars = make_predicate("( [ + * / - , .")3839output_stream_defaults = {40'indent_start': 0,41'indent_level': 4,42'quote_keys': False,43'space_colon': True,44'ascii_only': False,45'width': 80,46'max_line_len': 32000,47'ie_proof': True,48'beautify': False,49'source_map': None,50'bracketize': False,51'semicolons': True,52'comments': False,53'preserve_line': False,54'omit_baselib': False,55'baselib_plain': None,56'private_scope': True,57'keep_docstrings': False,58'discard_asserts': False,59'module_cache_dir': '',60'write_name': True,61}626364class OutputStream:65def __init__(self, options):66self.options = defaults(options, output_stream_defaults, True)67self._indentation = 068self.current_col = 069self.current_line = 170self.current_pos = 071self.OUTPUT = ""72self.might_need_space = False73self.might_need_semicolon = False74self._last = None75self._stack = []76self.index_counter = 077self.with_counter = 078self.try_else_counter = 07980def new_try_else_counter(self):81self.try_else_counter += 182return 'ρσ_try_else_' + self.try_else_counter8384def make_name(self, name):85name = name.toString()86if self.options.ascii_only:87name = to_ascii(name, True)8889return name9091def print_name(self, name):92self.print(self.make_name(name))9394def make_indent(self, back):95return repeat_string(96" ", self.options.indent_start + self._indentation -97back * self.options.indent_level)9899# -----[ beautification/minification ]-----100def last_char(self):101return self._last.charAt(self._last.length - 1)102103def maybe_newline(self):104if self.options.max_line_len and self.current_col > self.options.max_line_len:105self.print("\n")106107def print(self, str_):108str_ = String(str_)109ch = str_.charAt(0)110if self.might_need_semicolon:111if (not ch or ";}".indexOf(ch) < 0) and not RegExp(r"[;]").test(112self._last):113if self.options.semicolons or require_semi_colon_chars[ch]:114self.OUTPUT += ";"115self.current_col += 1116self.current_pos += 1117else:118self.OUTPUT += "\n"119self.current_pos += 1120self.current_line += 1121self.current_col = 0122123if not self.options.beautify:124self.might_need_space = False125126self.might_need_semicolon = False127self.maybe_newline()128129if not self.options.beautify and self.options.preserve_line and self._stack[130self._stack.length - 1]:131target_line = self._stack[self._stack.length - 1].start.line132while self.current_line < target_line:133self.OUTPUT += "\n"134self.current_pos += 1135self.current_line += 1136self.current_col = 0137self.might_need_space = False138139if self.might_need_space:140prev = self.last_char()141if (is_identifier_char(prev) and142(is_identifier_char(ch) or ch is "\\")143or RegExp(r"^[\+\-\/]$").test(ch) and ch is prev):144self.OUTPUT += " "145self.current_col += 1146self.current_pos += 1147148self.might_need_space = False149150a = str_.split(RegExp(r"\r?\n"))151n = a.length - 1152self.current_line += n153if n is 0:154self.current_col += a[n].length155else:156self.current_col = a[n].length157158self.current_pos += str_.length159self._last = str_160self.OUTPUT += str_161162def space(self):163if self.options.beautify:164self.print(' ')165else:166self.might_need_space = True167168def indent(self, half):169if self.options.beautify:170self.print(self.make_indent((0.5 if half else 0)))171172def with_indent(self, col, proceed):173if self.options.beautify:174if col is True:175col = self.next_indent()176177save_indentation = self._indentation178self._indentation = col179ret = proceed()180self._indentation = save_indentation181return ret182else:183return proceed()184185def indentation(self):186return self._indentation187188def set_indentation(self, val):189if self.options.beautify:190self._indentation = val191192def newline(self):193if self.options.beautify:194self.print("\n")195196def semicolon(self):197if self.options.beautify:198self.print(";")199else:200self.might_need_semicolon = True201202def force_semicolon(self):203self.might_need_semicolon = False204self.print(";")205206def next_indent(self):207return self._indentation + self.options.indent_level208209def spaced(self):210for i in range(len(arguments)):211if i > 0:212self.space()213if jstype(arguments[i].print) is 'function':214arguments[i].print(self)215else:216self.print(arguments[i])217218def end_statement(self):219self.semicolon()220self.newline()221222def with_block(self, cont):223ret = None224self.print("{")225self.newline()226227def f():228nonlocal ret229ret = cont()230231self.with_indent(self.next_indent(), f)232self.indent()233self.print("}")234return ret235236def with_parens(self, cont):237self.print("(")238ret = cont()239self.print(")")240return ret241242def with_square(self, cont):243self.print("[")244ret = cont()245self.print("]")246return ret247248def comma(self):249self.print(",")250self.space()251252def colon(self):253self.print(":")254if self.options.space_colon:255self.space()256257def get(self):258return self.OUTPUT259260toString = get261262def assign(self, name):263# generates: '[name] = '264if jstype(name) is "string":265self.print(name)266else:267name.print(self)268self.space()269self.print("=")270self.space()271272def current_width(self):273return self.current_col - self._indentation274275def should_break(self):276return self.options.width and self.current_width(277) >= self.options.width278279def last(self):280return self._last281282def print_string(self, str_):283self.print(encode_string(str_))284285def line(self):286return self.current_line287288def col(self):289return self.current_col290291def pos(self):292return self.current_pos293294def push_node(self, node):295self._stack.push(node)296297def pop_node(self):298return self._stack.pop()299300def stack(self):301return self._stack302303def parent(self, n):304return self._stack[self._stack.length - 2 - (n or 0)]305306307