17aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererimport os
2bfbaa6b206abdb8b1c3861926f4334b879ec91ccTerry Jan Reedy
314fc4270da5db43574d46d055a5f794ed33b271fGeorg Brandlfrom tkinter import *
414fc4270da5db43574d46d055a5f794ed33b271fGeorg Brandlimport tkinter.messagebox as tkMessageBox
57aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
67aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
77aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererclass FileList:
87aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
92d7f6a079df2b4582d7ccc32a7a2a7287d0bf175Kurt B. Kaiser    # N.B. this import overridden in PyShellFileList.
106fa5bdc6e85ec48925bc0d856b134f59d01c300fTerry Jan Reedy    from idlelib.editor import EditorWindow
117aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
127aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def __init__(self, root):
137aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.root = root
147aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.dict = {}
157aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.inversedict = {}
167aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.vars = {} # For EditorWindow.getrawvar (shared Tcl variables)
177aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
187aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def open(self, filename, action=None):
197aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        assert filename
207aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        filename = self.canonize(filename)
217aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if os.path.isdir(filename):
22183403a271977a26c0b77dbcf62e19395c007288Kurt B. Kaiser            # This can happen when bad filename is passed on command line:
237aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            tkMessageBox.showerror(
24183403a271977a26c0b77dbcf62e19395c007288Kurt B. Kaiser                "File Error",
25183403a271977a26c0b77dbcf62e19395c007288Kurt B. Kaiser                "%r is a directory." % (filename,),
267aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                master=self.root)
277aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return None
287aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        key = os.path.normcase(filename)
29811c4e0b7cb1a3b43cda8dab0b1587983b44c58dGuido van Rossum        if key in self.dict:
307aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            edit = self.dict[key]
31183403a271977a26c0b77dbcf62e19395c007288Kurt B. Kaiser            edit.top.wakeup()
327aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return edit
33183403a271977a26c0b77dbcf62e19395c007288Kurt B. Kaiser        if action:
34183403a271977a26c0b77dbcf62e19395c007288Kurt B. Kaiser            # Don't create window, perform 'action', e.g. open in same window
357aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return action(filename)
36183403a271977a26c0b77dbcf62e19395c007288Kurt B. Kaiser        else:
37105f60ee628842a20f70526f9e994bc8acfaa9c7Kurt B. Kaiser            edit = self.EditorWindow(self, filename, key)
38105f60ee628842a20f70526f9e994bc8acfaa9c7Kurt B. Kaiser            if edit.good_load:
39105f60ee628842a20f70526f9e994bc8acfaa9c7Kurt B. Kaiser                return edit
40105f60ee628842a20f70526f9e994bc8acfaa9c7Kurt B. Kaiser            else:
41105f60ee628842a20f70526f9e994bc8acfaa9c7Kurt B. Kaiser                edit._close()
42105f60ee628842a20f70526f9e994bc8acfaa9c7Kurt B. Kaiser                return None
437aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
44df8a40fbf57b7dd794803365a856b1f0f235d915Kurt B. Kaiser    def gotofileline(self, filename, lineno=None):
45df8a40fbf57b7dd794803365a856b1f0f235d915Kurt B. Kaiser        edit = self.open(filename)
46df8a40fbf57b7dd794803365a856b1f0f235d915Kurt B. Kaiser        if edit is not None and lineno is not None:
47df8a40fbf57b7dd794803365a856b1f0f235d915Kurt B. Kaiser            edit.gotoline(lineno)
48df8a40fbf57b7dd794803365a856b1f0f235d915Kurt B. Kaiser
49d2f4861a0b52a2af5ea3395267a5c56541352f8fKurt B. Kaiser    def new(self, filename=None):
50d2f4861a0b52a2af5ea3395267a5c56541352f8fKurt B. Kaiser        return self.EditorWindow(self, filename)
517aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
5210e05e17a3e7657ecdc4c7986d35275d76c6d603Ronald Oussoren    def close_all_callback(self, *args, **kwds):
53b5a755e46c66c7e7d709431399f1781ea9e582dfGuido van Rossum        for edit in list(self.inversedict):
547aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            reply = edit.close()
557aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            if reply == "cancel":
567aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                break
577aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        return "break"
587aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
598ce8a784bd672ba42975dec752848392ff9a7797Guido van Rossum    def unregister_maybe_terminate(self, edit):
607aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        try:
617aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            key = self.inversedict[edit]
627aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        except KeyError:
63be19ed77ddb047e02fe94d142181062af6d99dccGuido van Rossum            print("Don't know this EditorWindow object.  (close)")
647aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return
657aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if key:
667aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            del self.dict[key]
677aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        del self.inversedict[edit]
687aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if not self.inversedict:
697aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.root.quit()
707aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
717aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def filename_changed_edit(self, edit):
727aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        edit.saved_change_hook()
737aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        try:
747aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            key = self.inversedict[edit]
757aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        except KeyError:
76be19ed77ddb047e02fe94d142181062af6d99dccGuido van Rossum            print("Don't know this EditorWindow object.  (rename)")
777aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return
787aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        filename = edit.io.filename
797aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if not filename:
807aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            if key:
817aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                del self.dict[key]
827aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.inversedict[edit] = None
837aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return
847aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        filename = self.canonize(filename)
857aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        newkey = os.path.normcase(filename)
867aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if newkey == key:
877aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return
88811c4e0b7cb1a3b43cda8dab0b1587983b44c58dGuido van Rossum        if newkey in self.dict:
897aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            conflict = self.dict[newkey]
907aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.inversedict[conflict] = None
917aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            tkMessageBox.showerror(
927aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                "Name Conflict",
9370a6b49821a3226f55e9716f32d802d06640cb89Walter Dörwald                "You now have multiple edit windows open for %r" % (filename,),
947aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                master=self.root)
957aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.dict[newkey] = edit
967aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.inversedict[edit] = newkey
977aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if key:
987aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            try:
997aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                del self.dict[key]
1007aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            except KeyError:
1017aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                pass
1027aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
1037aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def canonize(self, filename):
1047aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if not os.path.isabs(filename):
1057aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            try:
1067aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                pwd = os.getcwd()
107786fbd8db707c7cb302a1adf2b57a0b3f8ba078cAndrew Svetlov            except OSError:
1087aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                pass
1097aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            else:
1107aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                filename = os.path.join(pwd, filename)
1117aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        return os.path.normpath(filename)
1127aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
1137aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
114df8a40fbf57b7dd794803365a856b1f0f235d915Kurt B. Kaiserdef _test():
1156fa5bdc6e85ec48925bc0d856b134f59d01c300fTerry Jan Reedy    from idlelib.editor import fixwordbreaks
1167aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    import sys
1177aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    root = Tk()
1187aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    fixwordbreaks(root)
1197aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    root.withdraw()
1207aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    flist = FileList(root)
1217aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    if sys.argv[1:]:
1227aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        for filename in sys.argv[1:]:
1237aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            flist.open(filename)
1247aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    else:
1257aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        flist.new()
1267aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    if flist.inversedict:
1277aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        root.mainloop()
1287aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
1297aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererif __name__ == '__main__':
130df8a40fbf57b7dd794803365a856b1f0f235d915Kurt B. Kaiser    _test()
131