浏览代码

First stab at an interface for generating NSI scripts from Python code - ping @ahmadia

Thomas Kluyver 10 年之前
父节点
当前提交
139a47c124
共有 1 个文件被更改,包括 184 次插入0 次删除
  1. 184 0
      nsist/nsigen.py

+ 184 - 0
nsist/nsigen.py

@@ -0,0 +1,184 @@
+class Comment(object):
+    def __init__(self, content):
+        self.content = content
+
+    def generate(self, state=None):
+        yield "; " + self.content
+
+def _should_quote(arg):
+    return (' ' in arg) or ('$' in arg)
+
+def assemble_line(parts):
+    quoted_parts = [("%s" % p) if _should_quote(p) else p
+                    for p in parts if p is not None]
+    return ' '.join(quoted_parts)
+
+class Instruction(object):
+    def __init__(self, name, *parameters):
+        self.name = name
+        self.parameters = parameters
+
+    def generate(self, state=None):
+        yield assemble_line([self.name] + list(self.parameters))
+
+def make_instruction_class(name):
+    def __init__(self, *parameters):
+        Instruction.__init__(self, name, *parameters)
+
+    return type(name, (Instruction,), {'__init__': __init__})
+
+File = make_instruction_class('File')
+
+class Scope(object):
+    def __init__(self, contents=None):
+        self.contents = contents or []
+
+    def generate_children(self, state=None):
+        for child in self.contents:
+            for line in child.generate(state):
+                yield '  ' + line
+
+class Section(Scope):
+    def __init__(self, name=None, index_var=None, selected=True, contents=None):
+        super(Section, self).__init__(contents)
+        self.name = name
+        self.index_var = index_var
+        self.selected = selected
+
+    def generate(self, state=None):
+        parts = ['Section',
+                 None if self.selected else '/o',
+                 self.name, self.index_var]
+
+        yield assemble_line(parts)
+        for line in self.generate_children(state):
+            yield line
+        yield 'SectionEnd'
+        yield ''  # Blank line after a section
+
+class SectionGroup(Scope):
+    def __init__(self, name, index_var=None, expanded=False, contents=None):
+        super(SectionGroup, self).__init__(contents)
+        self.name = name
+        self.expanded = expanded
+        self.index_var = index_var
+
+    def generate(self, state=None):
+        parts = ['SectionGroup',
+                 '/e' if self.expanded else None,
+                 self.name, self.index_var]
+        yield assemble_line(parts)
+        for line in self.generate_children(state):
+            yield line
+        yield 'SectionGroupEnd'
+
+class Function(Scope):
+    def __init__(self, name, contents=None):
+        super(Function, self).__init__(contents)
+        self.name = name
+
+    def generate(self, state=None):
+        yield assemble_line(['Function', self.name])
+        for line in self.generate_children(state):
+            yield
+
+class Label(object):
+    def __init__(self, name):
+        self.name = name
+
+    def generate(self, scope):
+        yield self.name + ":"
+
+class Conditional(object):
+    # e.g. IfSilent, IntCmp
+    def __init__(self, name, *parameters, ifbody=None, elsebody=None):
+        self.name = name
+        self.parameters = parameters
+        self.ifbody = ifbody or []
+        self.elsebody = elsebody or []
+
+    def generate(self, state):
+        if_counter = state.get('if_counter', 1)
+        state['if_counter'] = if_counter + 1
+        yield assemble_line([self.name] + self.parameters + ["0",
+                     ("else%d" if self.elsebody else "endif%d") % if_counter])
+        for child in self.ifbody:
+            for line in child.generate(state):
+                yield "  " + line
+
+        if self.elsebody:
+            yield ("  Goto endif%d" % if_counter)
+            yield ("else%d:" % if_counter)
+            for child in self.elsebody:
+                for line in child.generate(state):
+                    yield "  " + line
+
+        yield ("endif%d:" % if_counter)
+
+
+class CompilerCommand(object):
+    def __init__(self, name, *parameters):
+        self.name = name
+        self.parameters = parameters
+
+    def generate(self, state=None):
+        yield "!" + assemble_line([self.name] + list(self.parameters))
+
+class CompilerConditional(object):
+    # ifdef etc
+    def __init__(self, name, parameters, ifbody=None, elsebody=None):
+        self.name = name
+        self.parameters = parameters
+        self.ifbody = ifbody or []
+        self.elsebody = elsebody or []
+
+    def generate(self, state=None):
+        yield "!" + assemble_line([self.name] + self.parameters)
+        for child in self.ifbody:
+            for line in child.generate(state):
+                yield '  ' + line
+        if self.elsebody:
+            yield "!else"
+            for child in self.elsebody:
+                for line in child.generate(state):
+                    yield '  ' + line
+
+        yield "!endif"
+
+def make_compiler_command_class(name):
+    def __init__(self, *parameters):
+        CompilerCommand.__init__(self, name, *parameters)
+
+    return type(name, (CompilerCommand,), {'__init__': __init__})
+
+define = make_compiler_command_class('define')
+insertmacro = make_compiler_command_class('insertmacro')
+
+class Macro(Scope):
+    def __init__(self, name, parameters):
+        super(Macro, self).__init__()
+        self.name = name
+        self.parameters = parameters
+
+    def generate(self, state=None):
+        yield "!" + assemble_line([self.name] + self.parameters)
+        for line in self.generate_children(state):
+            yield "  " + line
+        yield "!macroend"
+
+class Document(object):
+    def __init__(self, children=None):
+        self.children = children or []
+
+    def generate(self, state):
+        for child in self.children:
+            for line in child.generate(state):
+                yield line
+
+    def write(self, fileobj_or_path):
+        if isinstance(fileobj_or_path, str):
+            with open(fileobj_or_path, 'w') as f:
+                return self.write(f)
+
+        for line in self.generate(state={}):
+            fileobj_or_path.write(line + '\n')