Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
document.py313 linesDownload Raw Back to scintilla
1import codecs2import re3import string4 5import win32con6import win32ui7from pywin import default_scintilla_encoding8from pywin.mfc import docview9 10from . import scintillacon11 12crlf_bytes = "\r\n".encode("ascii")13lf_bytes = "\n".encode("ascii")14 15# re from pep263 - but we use it both on bytes and strings.16re_encoding_bytes = re.compile("coding[:=]\s*([-\w.]+)".encode("ascii"))17re_encoding_text = re.compile("coding[:=]\s*([-\w.]+)")18 19ParentScintillaDocument = docview.Document20 21 22class CScintillaDocument(ParentScintillaDocument):23    "A SyntEdit document."24 25    def __init__(self, *args):26        self.bom = None  # the BOM, if any, read from the file.27        # the encoding we detected from the source.  Might have28        # detected via the BOM or an encoding decl.  Note that in29        # the latter case (ie, while self.bom is None), it can't be30        # trusted - the user may have edited the encoding decl between31        # open and save.32        self.source_encoding = None33        ParentScintillaDocument.__init__(self, *args)34 35    def DeleteContents(self):36        pass37 38    def OnOpenDocument(self, filename):39        # init data members40        # print "Opening", filename41        self.SetPathName(filename)  # Must set this early!42        try:43            # load the text as binary we can get smart44            # about detecting any existing EOL conventions.45            f = open(filename, "rb")46            try:47                self._LoadTextFromFile(f)48            finally:49                f.close()50        except IOError:51            rc = win32ui.MessageBox(52                "Could not load the file from %s\n\nDo you want to create a new file?"53                % filename,54                "Pythonwin",55                win32con.MB_YESNO | win32con.MB_ICONWARNING,56            )57            if rc == win32con.IDNO:58                return 059            assert rc == win32con.IDYES, rc60            try:61                f = open(filename, "wb+")62                try:63                    self._LoadTextFromFile(f)64                finally:65                    f.close()66            except IOError as e:67                rc = win32ui.MessageBox("Cannot create the file %s" % filename)68        return 169 70    def SaveFile(self, fileName, encoding=None):71        view = self.GetFirstView()72        ok = view.SaveTextFile(fileName, encoding=encoding)73        if ok:74            view.SCISetSavePoint()75        return ok76 77    def ApplyFormattingStyles(self):78        self._ApplyOptionalToViews("ApplyFormattingStyles")79 80    # #####################81    # File related functions82    # Helper to transfer text from the MFC document to the control.83    def _LoadTextFromFile(self, f):84        # detect EOL mode - we don't support \r only - so find the85        # first '\n' and guess based on the char before.86        l = f.readline()87        l2 = f.readline()88        # If line ends with \r\n or has no line ending, use CRLF.89        if l.endswith(crlf_bytes) or not l.endswith(lf_bytes):90            eol_mode = scintillacon.SC_EOL_CRLF91        else:92            eol_mode = scintillacon.SC_EOL_LF93 94        # Detect the encoding - first look for a BOM, and if not found,95        # look for a pep263 encoding declaration.96        for bom, encoding in (97            (codecs.BOM_UTF8, "utf8"),98            (codecs.BOM_UTF16_LE, "utf_16_le"),99            (codecs.BOM_UTF16_BE, "utf_16_be"),100        ):101            if l.startswith(bom):102                self.bom = bom103                self.source_encoding = encoding104                l = l[len(bom) :]  # remove it.105                break106        else:107            # no bom detected - look for pep263 encoding decl.108            for look in (l, l2):109                # Note we are looking at raw bytes here: so110                # both the re itself uses bytes and the result111                # is bytes - but we need the result as a string.112                match = re_encoding_bytes.search(look)113                if match is not None:114                    self.source_encoding = match.group(1).decode("ascii")115                    break116 117        # reading by lines would be too slow?  Maybe we can use the118        # incremental encoders? For now just stick with loading the119        # entire file in memory.120        text = l + l2 + f.read()121 122        # Translate from source encoding to UTF-8 bytes for Scintilla123        source_encoding = self.source_encoding124        # If we don't know an encoding, try utf-8 - if that fails we will125        # fallback to latin-1 to treat it as bytes...126        if source_encoding is None:127            source_encoding = "utf-8"128        # we could optimize this by avoiding utf8 to-ing and from-ing,129        # but then we would lose the ability to handle invalid utf8130        # (and even then, the use of encoding aliases makes this tricky)131        # To create an invalid utf8 file:132        # >>> open(filename, "wb").write(codecs.BOM_UTF8+"bad \xa9har\r\n")133        try:134            dec = text.decode(source_encoding)135        except UnicodeError:136            print(137                "WARNING: Failed to decode bytes from '%s' encoding - treating as latin1"138                % source_encoding139            )140            dec = text.decode("latin1")141        except LookupError:142            print(143                "WARNING: Invalid encoding '%s' specified - treating as latin1"144                % source_encoding145            )146            dec = text.decode("latin1")147        # and put it back as utf8 - this shouldn't fail.148        text = dec.encode(default_scintilla_encoding)149 150        view = self.GetFirstView()151        if view.IsWindow():152            # Turn off undo collection while loading153            view.SendScintilla(scintillacon.SCI_SETUNDOCOLLECTION, 0, 0)154            # Make sure the control isnt read-only155            view.SetReadOnly(0)156            view.SendScintilla(scintillacon.SCI_CLEARALL)157            view.SendMessage(scintillacon.SCI_ADDTEXT, text)158            view.SendScintilla(scintillacon.SCI_SETUNDOCOLLECTION, 1, 0)159            view.SendScintilla(win32con.EM_EMPTYUNDOBUFFER, 0, 0)160            # set EOL mode161            view.SendScintilla(scintillacon.SCI_SETEOLMODE, eol_mode)162 163    def _SaveTextToFile(self, view, filename, encoding=None):164        s = view.GetTextRange()  # already decoded from scintilla's encoding165        source_encoding = encoding166        if source_encoding is None:167            if self.bom:168                source_encoding = self.source_encoding169            else:170                # no BOM - look for an encoding.171                bits = re.split("[\r\n]+", s, 3)172                for look in bits[:-1]:173                    match = re_encoding_text.search(look)174                    if match is not None:175                        source_encoding = match.group(1)176                        self.source_encoding = source_encoding177                        break178 179            if source_encoding is None:180                source_encoding = "utf-8"181 182        ## encode data before opening file so script is not lost if encoding fails183        file_contents = s.encode(source_encoding)184        # Open in binary mode as scintilla itself ensures the185        # line endings are already appropriate186        f = open(filename, "wb")187        try:188            if self.bom:189                f.write(self.bom)190            f.write(file_contents)191        finally:192            f.close()193        self.SetModifiedFlag(0)194 195    def FinalizeViewCreation(self, view):196        pass197 198    def HookViewNotifications(self, view):199        parent = view.GetParentFrame()200        parent.HookNotify(201            ViewNotifyDelegate(self, "OnBraceMatch"), scintillacon.SCN_CHECKBRACE202        )203        parent.HookNotify(204            ViewNotifyDelegate(self, "OnMarginClick"), scintillacon.SCN_MARGINCLICK205        )206        parent.HookNotify(207            ViewNotifyDelegate(self, "OnNeedShown"), scintillacon.SCN_NEEDSHOWN208        )209 210        parent.HookNotify(211            DocumentNotifyDelegate(self, "OnSavePointReached"),212            scintillacon.SCN_SAVEPOINTREACHED,213        )214        parent.HookNotify(215            DocumentNotifyDelegate(self, "OnSavePointLeft"),216            scintillacon.SCN_SAVEPOINTLEFT,217        )218        parent.HookNotify(219            DocumentNotifyDelegate(self, "OnModifyAttemptRO"),220            scintillacon.SCN_MODIFYATTEMPTRO,221        )222        # Tell scintilla what characters should abort auto-complete.223        view.SCIAutoCStops(string.whitespace + "()[]:;+-/*=\\?'!#@$%^&,<>\"'|")224 225        if view != self.GetFirstView():226            view.SCISetDocPointer(self.GetFirstView().SCIGetDocPointer())227 228    def OnSavePointReached(self, std, extra):229        self.SetModifiedFlag(0)230 231    def OnSavePointLeft(self, std, extra):232        self.SetModifiedFlag(1)233 234    def OnModifyAttemptRO(self, std, extra):235        self.MakeDocumentWritable()236 237    # All Marker functions are 1 based.238    def MarkerAdd(self, lineNo, marker):239        self.GetEditorView().SCIMarkerAdd(lineNo - 1, marker)240 241    def MarkerCheck(self, lineNo, marker):242        v = self.GetEditorView()243        lineNo = lineNo - 1  # Make 0 based244        markerState = v.SCIMarkerGet(lineNo)245        return markerState & (1 << marker) != 0246 247    def MarkerToggle(self, lineNo, marker):248        v = self.GetEditorView()249        if self.MarkerCheck(lineNo, marker):250            v.SCIMarkerDelete(lineNo - 1, marker)251        else:252            v.SCIMarkerAdd(lineNo - 1, marker)253 254    def MarkerDelete(self, lineNo, marker):255        self.GetEditorView().SCIMarkerDelete(lineNo - 1, marker)256 257    def MarkerDeleteAll(self, marker):258        self.GetEditorView().SCIMarkerDeleteAll(marker)259 260    def MarkerGetNext(self, lineNo, marker):261        return self.GetEditorView().SCIMarkerNext(lineNo - 1, 1 << marker) + 1262 263    def MarkerAtLine(self, lineNo, marker):264        markerState = self.GetEditorView().SCIMarkerGet(lineNo - 1)265        return markerState & (1 << marker)266 267    # Helper for reflecting functions to views.268    def _ApplyToViews(self, funcName, *args):269        for view in self.GetAllViews():270            func = getattr(view, funcName)271            func(*args)272 273    def _ApplyOptionalToViews(self, funcName, *args):274        for view in self.GetAllViews():275            func = getattr(view, funcName, None)276            if func is not None:277                func(*args)278 279    def GetEditorView(self):280        # Find the first frame with a view,281        # then ask it to give the editor view282        # as it knows which one is "active"283        try:284            frame_gev = self.GetFirstView().GetParentFrame().GetEditorView285        except AttributeError:286            return self.GetFirstView()287        return frame_gev()288 289 290# Delegate to the correct view, based on the control that sent it.291class ViewNotifyDelegate:292    def __init__(self, doc, name):293        self.doc = doc294        self.name = name295 296    def __call__(self, std, extra):297        (hwndFrom, idFrom, code) = std298        for v in self.doc.GetAllViews():299            if v.GetSafeHwnd() == hwndFrom:300                return getattr(v, self.name)(*(std, extra))301 302 303# Delegate to the document, but only from a single view (as each view sends it seperately)304class DocumentNotifyDelegate:305    def __init__(self, doc, name):306        self.doc = doc307        self.delegate = getattr(doc, name)308 309    def __call__(self, std, extra):310        (hwndFrom, idFrom, code) = std311        if hwndFrom == self.doc.GetEditorView().GetSafeHwnd():312            self.delegate(*(std, extra))313 
codekingpro/portable-devtools · Team Ai