lisp_codegen.py

来自「用python写的ide开发环境,巨强大,不过需要wxpython的支持」· Python 代码 · 共 1,352 行 · 第 1/4 页

PY
1,352
字号
    global for_version    try:        for_version = tuple([int(t) for t in                             app_attrs['for_version'].split('.')[:2]])    except (KeyError, ValueError):        if common.app_tree is not None:            for_version = common.app_tree.app.for_version        else:            for_version = (2, 4) # default...    try:        _use_gettext = int(app_attrs['use_gettext'])    except (KeyError, ValueError):        _use_gettext = False    try: _overwrite = int(app_attrs['overwrite'])    except (KeyError, ValueError): _overwrite = False    # add coding (PEP 263)    try: _encoding = app_attrs['encoding']    except (KeyError, ValueError): _encoding = None    classes = {}    _current_extra_modules = {}    header_lines = [';;; generated by wxGlade %s on %s%s\n\n' % \                    (common.version, time.asctime(), common.generated_from()),                    '(asdf:operate \'asdf:load-op \'wxcl)\n',                    '(use-package \"FFI\")\n'                    '(ffi:default-foreign-language :stdc)\n\n'                    ]    if not config.preferences.write_timestamp:        header_lines[0] = ';;; generated by wxGlade %s%s\n\n' % \                          (common.version, common.generated_from())    import_packages = set (["wxCL", "wxFrame", "wx_main", "wx_wrapper",                            "wxWindow", "wxColour", "wxEvtHandler", "wxEvent"])# add coding (PEP 263)#    if _encoding:#       header_lines.insert(0, "# -*- coding: %s -*-\n" % _encoding)    multiple_files = multi_files    if not multiple_files:        global output_file, output_file_name        if not _overwrite and os.path.isfile(out_path):            # the file exists, we must keep all the lines not inside a wxGlade            # block. NOTE: this may cause troubles if out_path is not a valid            # lisp file, so be careful!            previous_source = SourceFileContent(out_path)        else:            # if the file doesn't exist, create it and write the ``intro''            previous_source = None            output_file = cStringIO.StringIO()            output_file_name = out_path#-SKS            for line in header_lines:#-SKS                output_file.write(line)            output_file.write('<%swxGlade extra_modules>\n' % nonce)            output_file.write('\n')    else:        previous_source = None        global out_dir        if not os.path.isdir(out_path):            raise XmlParsingError("'path' must be a directory when generating"\                                  " multiple output files")        out_dir = out_pathdef finalize():    """\    Writer ``finalization'' function: flushes buffers, closes open files, ...    """    if previous_source is not None:        # insert all the new custom classes inside the old file        tag = '<%swxGlade insert new_classes>' % nonce        if previous_source.new_classes:            code = "".join(previous_source.new_classes)        else:            code = ""        previous_source.content = previous_source.content.replace(tag, code)        tag = '<%swxGlade extra_modules>\n' % nonce        code = "".join(_current_extra_modules.keys())        previous_source.content = previous_source.content.replace(tag, code)        # now remove all the remaining <123415wxGlade ...> tags from the        # source: this may happen if we're not generating multiple files,        # and one of the container class names is changed        tags = re.findall('(<%swxGlade replace ([a-zA-Z_]\w*) +\w+>)' % nonce,                          previous_source.content)        for tag in tags:            indent = previous_source.spaces.get(tag[1], tabs(2))            comment = '%s# content of this block not found: ' \                      'did you rename this class?\n%spass\n' % (indent, indent)            previous_source.content = previous_source.content.replace(tag[0],                                                                      comment)        # ALB 2004-12-05        tags = re.findall('<%swxGlade event_handlers \w+>' % nonce,                          previous_source.content)        for tag in tags:            previous_source.content = previous_source.content.replace(tag, "")        # write the new file contents to disk        common.save_file(previous_source.name, previous_source.content,                         'codegen')    elif not multiple_files:        global output_file        em = "".join(_current_extra_modules.keys())        content = output_file.getvalue().replace(            '<%swxGlade extra_modules>\n' % nonce, em)        output_file.close()        try:            common.save_file(output_file_name, content, 'codegen')            # make the file executable            if _app_added:                os.chmod(output_file_name, 0755)        except IOError, e:            raise XmlParsingError(str(e))        except OSError: pass # this isn't necessary a bad error        del output_filedef test_attribute(obj):    """\    Returns True if 'obj' should be added as an attribute of its parent's    class, False if it should be created as a local variable of __do_layout.    To do so, tests for the presence of the special property 'attribute'    """    try: return int(obj.properties['attribute'])    except (KeyError, ValueError): return True # this is the defaultdef add_object(top_obj, sub_obj):    """\    adds the code to build 'sub_obj' to the class body of 'top_obj'.    """    global import_packages            try: klass = classes[top_obj.klass]    except KeyError: klass = classes[top_obj.klass] = ClassLines()    try: builder = obj_builders[sub_obj.base]    except KeyError:        # no code generator found: write a comment about it        klass.init.extend(['\n', ';;; code for %s (type %s) not generated: '                           'no suitable writer found' % (sub_obj.name,                                                         sub_obj.klass),'\n'])    else:        try:            sub_obj.name = sub_obj.name.replace('_','-')            sub_obj.parent.name = sub_obj.parent.name.replace('_','-')            if(sub_obj.name != "spacer"):                class_lines.append(sub_obj.name)            if (sub_obj.klass == "wxBoxSizer" or sub_obj.klass == "wxStaticBoxSizer"                or sub_obj.klass == "wxGridSizer" or sub_obj.klass == "wxFlexGridSizer"):                import_packages = import_packages | set(["wxSizer"])            else:                if (sub_obj.klass != "spacer"):                    import_packages = import_packages | set([sub_obj.klass])            if (sub_obj.klass == "wxMenuBar" ):                import_packages = import_packages | set(["wxMenu"])            init, props, layout = builder.get_code(sub_obj)        except:            print sub_obj            raise # this shouldn't happen        if sub_obj.in_windows: # the object is a wxWindow instance            # --- patch 2002-08-26 ------------------------------------------            if sub_obj.is_container and not sub_obj.is_toplevel:                init.reverse()                klass.parents_init.extend(init)            else: klass.init.extend(init)            # ---------------------------------------------------------------            # ALB 2004-12-05            mycn = getattr(builder, 'cn', cn)            if hasattr(builder, 'get_events'):                evts = builder.get_events(sub_obj)                for id, event, handler in evts:                    klass.event_handlers.append((id, mycn(event), handler))            elif 'events' in sub_obj.properties:                id_name, id = generate_code_id(sub_obj)                #if id == '-1': id = 'self.%s.GetId()' % sub_obj.name                if id == '-1': id = '#obj.%s' % sub_obj.name                for event, handler in sub_obj.properties['events'].iteritems():                    klass.event_handlers.append((id, mycn(event), handler))        else: # the object is a sizer            # ALB 2004-09-17: workaround (hack) for static box sizers...# SKS-           if sub_obj.base == 'wxStaticBoxSizer': #SKS-               klass.parents_init.insert(1, init.pop(0))            klass.sizers_init.extend(init)        klass.props.extend(props)        klass.layout.extend(layout)        if multiple_files and \               (sub_obj.is_toplevel and sub_obj.base != sub_obj.klass):            key = 'from %s import %s\n' % (sub_obj.klass, sub_obj.klass)            klass.dependencies[key] = 1##         for dep in _widget_extra_modules.get(sub_obj.base, []):        for dep in getattr(obj_builders.get(sub_obj.base),                           'import_modules', []):            klass.dependencies[dep] = 1def add_sizeritem(toplevel, sizer, obj, option, flag, border):    """\    writes the code to add the object 'obj' to the sizer 'sizer'    in the 'toplevel' object.    """    # an ugly hack to allow the addition of spacers: if obj_name can be parsed    # as a couple of integers, it is the size of the spacer to add    global import_packages            sizer.name = sizer.name.replace('_','-')    obj_name = obj.name    try: w, h = [ int(s) for s in obj_name.split(',') ]    except ValueError:        if obj.base == 'wxNotebook' and for_version < (2, 5):              obj_name = cn('wxNotebookSizer') + '(%s)' % obj_name    else:        obj_name = '(%d, %d)' % (w, h) # it was the dimension of a spacer    try: klass = classes[toplevel.klass]    except KeyError: klass = classes[toplevel.klass] = ClassLines()    flag = '%s' % cn_f(flag)    flag = flag.strip().replace('|',' ')    if flag.find(' ') != -1:        flag = '(logior %s)' % flag    if (obj.klass == "wxBoxSizer" or obj.klass == "wxStaticBoxSizer"        or obj.klass == "wxGridSizer" or obj.klass == "wxFlexGridSizer"):        buffer = '(wxSizer_AddSizer (slot-%s  obj) (slot-%s obj) %s %s %s nil)\n' % \                 (sizer.name, obj_name, option, flag, cn_f(border))    else:        buffer = '(wxSizer_AddWindow (slot-%s obj) (slot-%s obj) %s %s %s nil)\n' % \                 (sizer.name, obj_name, option, flag,cn_f(border))    print     klass.layout.append(buffer)def add_class(code_obj):    """\    Generates the code for a custom class.    """    global _current_extra_modules, import_packages    if not multiple_files:        # in this case, previous_source is the SourceFileContent instance        # that keeps info about the single file to generate        prev_src = previous_source    else:        # let's see if the file to generate exists, and in this case        # create a SourceFileContent instance        filename = os.path.join(out_dir,                                code_obj.klass.replace('.', '_') + '.py')        if _overwrite or not os.path.exists(filename): prev_src = None        else: prev_src = SourceFileContent(filename)        _current_extra_modules = {}    if classes.has_key(code_obj.klass) and classes[code_obj.klass].done:        return # the code has already been generated    try:#SKS-        builder = obj_builders[code_obj.base]        builder=""        mycn = getattr(builder, 'cn', cn)        mycn_f = getattr(builder, 'cn_f', cn_f)    except KeyError:        raise # this is an error, let the exception be raised    if prev_src is not None and prev_src.classes.has_key(code_obj.klass):        is_new = False        indentation = prev_src.spaces[code_obj.klass]    else:        # this class wasn't in the previous version of the source (if any)        is_new = True        indentation = tabs(2)##         mods = _widget_extra_modules.get(code_obj.base)        mods = getattr(builder, 'extra_modules', [])        if mods:            for m in mods: _current_extra_modules[m] = 1    buffer = []    write = buffer.append    for l in header_lines: write(l)    for l in import_packages: write('(use-package :%s)\n' % l)        if not classes.has_key(code_obj.klass):        # if the class body was empty, create an empty ClassLines        classes[code_obj.klass] = ClassLines()##     # first thing to do, call the property writer: we do this now because it##     # can have side effects that modify the ClassLines instance (this is used##     # in the toplevel menubar)##     props_builder = obj_properties.get(code_obj.base)##     write_body = len(classes[code_obj.klass].props)##     if props_builder:##         obj_p = obj_properties[code_obj.base](code_obj)##         if not write_body: write_body = len(obj_p)##     else: obj_p = []    tab = indentation     if is_new:        base = mycn(code_obj.base)        if code_obj.preview and code_obj.klass == base:            import random            klass = code_obj.klass + ('_%d' % random.randrange(10**8, 10**9))        else:            klass = code_obj.klass        write('\n(defclass %s()\n' % klass)        write("\t((top-window :initform nil :accessor slot-top-window)")        for l in class_lines: write("\n"+tab+"("+l+" :initform nil :accessor slot-"+l+")")        write("))\n")        write("\n(defun make-%s ()\n" % klass)        write(tab+"(let ((obj (make-instance '%s)))\n" % klass)        write(tab+"  (init obj)\n")        write(tab+"  (set-properties obj)\n")        write(tab+"  (do-layout obj)\n")        write(tab+"  obj))\n")                write('\n(defmethod init ((obj %s))\n' % klass)        write("\"Method creates the objects contained in the class.\"\n")    # __init__ begin tag    write(indentation + ';;;begin wxGlade: %s.__init__\n' % code_obj.klass)    prop = code_obj.properties    style = prop.get("style", None)    if style: style = mycn_f(style)    style = style.strip().replace('.','')    style = style.replace('|',' ')    if style.find(' ') != -1:        style = '(logior %s)' % style    if code_obj.base == "wxFrame":        write(indentation + "(setf (slot-top-window obj) (wxFrame_create nil -1 \"\" -1 -1 -1 -1 %s))\n" % style)    else:        if code_obj.base == "wxDialog":            write(indentation + "(setf (slot-top-window obj) (wxDialog_create nil -1 \"\" -1 -1 -1 -1 %s))\n" % style)            import_packages = import_packages | set(['wxDialog'])

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?