blob: d800589bc51fda4adfd1ec3cff4ad9470b953358 [file] [log] [blame]
Guido van Rossum3b4ca0d1998-10-10 18:48:31 +00001import string
2
3class AutoIndent:
4
5 def __init__(self, text, prefertabs=0, spaceindent=4*" "):
6 self.text = text
7 self.prefertabs = prefertabs
8 self.spaceindent = spaceindent
9 text.bind("<<newline-and-indent>>", self.autoindent)
10 text.bind("<<indent-region>>", self.indentregion)
11 text.bind("<<dedent-region>>", self.dedentregion)
12 text.bind("<<comment-region>>", self.commentregion)
13 text.bind("<<uncomment-region>>", self.uncommentregion)
14
15 def config(self, **options):
16 for key, value in options.items():
17 if key == 'prefertabs':
18 self.prefertabs = value
19 elif key == 'spaceindent':
20 self.spaceindent = value
21 else:
22 raise KeyError, "bad option name: %s" % `key`
23
24 def autoindent(self, event):
25 text = self.text
26 line = text.get("insert linestart", "insert")
27 i, n = 0, len(line)
28 while i < n and line[i] in " \t":
29 i = i+1
30 indent = line[:i]
31 lastchar = text.get("insert -1c")
32 if lastchar == ":":
33 if not indent:
34 if self.prefertabs:
35 indent = "\t"
36 else:
37 indent = self.spaceindent
38 elif indent[-1] == "\t":
39 indent = indent + "\t"
40 else:
41 indent = indent + self.spaceindent
42 text.insert("insert", "\n" + indent)
43 text.see("insert")
44 return "break"
45
46 def indentregion(self, event):
47 head, tail, chars, lines = self.getregion()
48 for pos in range(len(lines)):
49 line = lines[pos]
50 if line:
51 i, n = 0, len(line)
52 while i < n and line[i] in " \t":
53 i = i+1
54 line = line[:i] + " " + line[i:]
55 lines[pos] = line
56 self.setregion(head, tail, chars, lines)
57 return "break"
58
59 def dedentregion(self, event):
60 head, tail, chars, lines = self.getregion()
61 for pos in range(len(lines)):
62 line = lines[pos]
63 if line:
64 i, n = 0, len(line)
65 while i < n and line[i] in " \t":
66 i = i+1
67 indent, line = line[:i], line[i:]
68 if indent:
69 if indent == "\t" or indent[-2:] == "\t\t":
70 indent = indent[:-1] + " "
71 elif indent[-4:] == " ":
72 indent = indent[:-4]
73 else:
74 indent = string.expandtabs(indent, 8)
75 indent = indent[:-4]
76 line = indent + line
77 lines[pos] = line
78 self.setregion(head, tail, chars, lines)
79 return "break"
80
81 def commentregion(self, event):
82 head, tail, chars, lines = self.getregion()
83 for pos in range(len(lines)):
84 line = lines[pos]
85 if not line:
86 continue
87 lines[pos] = '##' + line
88 self.setregion(head, tail, chars, lines)
89
90 def uncommentregion(self, event):
91 head, tail, chars, lines = self.getregion()
92 for pos in range(len(lines)):
93 line = lines[pos]
94 if not line:
95 continue
96 if line[:2] == '##':
97 line = line[2:]
98 elif line[:1] == '#':
99 line = line[1:]
100 lines[pos] = line
101 self.setregion(head, tail, chars, lines)
102
103 def getregion(self):
104 text = self.text
105 head = text.index("sel.first linestart")
106 tail = text.index("sel.last -1c lineend +1c")
107 if not (head and tail):
108 head = text.index("insert linestart")
109 tail = text.index("insert lineend +1c")
110 chars = text.get(head, tail)
111 lines = string.split(chars, "\n")
112 return head, tail, chars, lines
113
114 def setregion(self, head, tail, chars, lines):
115 text = self.text
116 newchars = string.join(lines, "\n")
117 if newchars == chars:
118 text.bell()
119 return
120 text.tag_remove("sel", "1.0", "end")
121 text.mark_set("insert", head)
122 text.delete(head, tail)
123 text.insert(head, newchars)
124 text.tag_add("sel", head, "insert")