summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Tools/idle/AutoIndent.py112
-rw-r--r--Tools/idle/EditorWindow.py22
-rw-r--r--Tools/idle/FormatParagraph.py2
3 files changed, 77 insertions, 59 deletions
diff --git a/Tools/idle/AutoIndent.py b/Tools/idle/AutoIndent.py
index 7784254..66a0aec 100644
--- a/Tools/idle/AutoIndent.py
+++ b/Tools/idle/AutoIndent.py
@@ -3,9 +3,6 @@ import string
#import tkMessageBox
#import tkSimpleDialog
-# The default tab setting for a Text widget, in average-width characters.
-TK_TABWIDTH_DEFAULT = 8
-
###$ event <<newline-and-indent>>
###$ win <Key-Return>
###$ win <KP_Enter>
@@ -101,7 +98,7 @@ class AutoIndent:
# Nobody expects this, so for now tabwidth should never be changed.
usetabs = 1
indentwidth = 4
- tabwidth = TK_TABWIDTH_DEFAULT
+ tabwidth = 8 # for IDLE use, must remain 8 until Tk is fixed
# If context_use_ps1 is true, parsing searches back for a ps1 line;
# else searches for a popular (if, def, ...) Python stmt.
@@ -139,8 +136,6 @@ class AutoIndent:
# character means.
def set_indentation_params(self, ispythonsource, guess=1):
- text = self.text
-
if guess and ispythonsource:
i = self.guess_indent()
if 2 <= i <= 8:
@@ -148,39 +143,47 @@ class AutoIndent:
if self.indentwidth != self.tabwidth:
self.usetabs = 0
- current_tabs = text['tabs']
- if current_tabs == "" and self.tabwidth == TK_TABWIDTH_DEFAULT:
- pass
- else:
- # Reconfigure the Text widget by measuring the width
- # of a tabwidth-length string in pixels, forcing the
- # widget's tab stops to that.
- need_tabs = text.tk.call("font", "measure", text['font'],
- "-displayof", text.master,
- "n" * self.tabwidth)
- if current_tabs != need_tabs:
- text.configure(tabs=need_tabs)
+ self.editwin.set_tabwidth(self.tabwidth)
def smart_backspace_event(self, event):
text = self.text
- try:
- first = text.index("sel.first")
- last = text.index("sel.last")
- except: # Was catching TclError, but this doesnt work for
- first = last = None
+ first, last = self.editwin.get_selection_indices()
if first and last:
text.delete(first, last)
text.mark_set("insert", first)
return "break"
- # If we're at the end of leading whitespace, nuke one indent
- # level, else one character.
+ # Delete whitespace left, until hitting a real char or closest
+ # preceding virtual tab stop.
chars = text.get("insert linestart", "insert")
- raw, effective = classifyws(chars, self.tabwidth)
- if 0 < raw == len(chars):
- if effective >= self.indentwidth:
- self.reindent_to(effective - self.indentwidth)
- return "break"
- text.delete("insert-1c")
+ if chars == '':
+ if text.compare("insert", ">", "1.0"):
+ # easy: delete preceding newline
+ text.delete("insert-1c")
+ else:
+ text.bell() # at start of buffer
+ return "break"
+ if chars[-1] not in " \t":
+ # easy: delete preceding real char
+ text.delete("insert-1c")
+ return "break"
+ # Ick. It may require *inserting* spaces if we back up over a
+ # tab character! This is written to be clear, not fast.
+ expand, tabwidth = string.expandtabs, self.tabwidth
+ have = len(expand(chars, tabwidth))
+ assert have > 0
+ want = int((have - 1) / self.indentwidth) * self.indentwidth
+ ncharsdeleted = 0
+ while 1:
+ chars = chars[:-1]
+ ncharsdeleted = ncharsdeleted + 1
+ have = len(expand(chars, tabwidth))
+ if have <= want or chars[-1] not in " \t":
+ break
+ text.undo_block_start()
+ text.delete("insert-%dc" % ncharsdeleted, "insert")
+ if have < want:
+ text.insert("insert", ' ' * (want - have))
+ text.undo_block_stop()
return "break"
def smart_indent_event(self, event):
@@ -190,11 +193,7 @@ class AutoIndent:
# do indent-region & return
# indent one level
text = self.text
- try:
- first = text.index("sel.first")
- last = text.index("sel.last")
- except: # Was catching TclError, but this doesnt work for
- first = last = None
+ first, last = self.editwin.get_selection_indices()
text.undo_block_start()
try:
if first and last:
@@ -223,11 +222,7 @@ class AutoIndent:
def newline_and_indent_event(self, event):
text = self.text
- try:
- first = text.index("sel.first")
- last = text.index("sel.last")
- except: # Was catching TclError, but this doesnt work for
- first = last = None
+ first, last = self.editwin.get_selection_indices()
text.undo_block_start()
try:
if first and last:
@@ -256,8 +251,8 @@ class AutoIndent:
# start new line
text.insert("insert", '\n')
- # adjust indentation for continuations and block open/close
- # first need to find the last stmt
+ # adjust indentation for continuations and block
+ # open/close first need to find the last stmt
lno = index2line(text.index('insert'))
y = PyParse.Parser(self.indentwidth, self.tabwidth)
for context in self.num_context_lines:
@@ -280,15 +275,15 @@ class AutoIndent:
elif c == PyParse.C_BRACKET:
# line up with the first (if any) element of the
# last open bracket structure; else indent one
- # level beyond the indent of the line with the last
- # open bracket
+ # level beyond the indent of the line with the
+ # last open bracket
self.reindent_to(y.compute_bracket_indent())
elif c == PyParse.C_BACKSLASH:
# if more than one line in this stmt already, just
- # mimic the current indent; else if initial line has
- # a start on an assignment stmt, indent to beyond
- # leftmost =; else to beyond first chunk of non-
- # whitespace on initial line
+ # mimic the current indent; else if initial line
+ # has a start on an assignment stmt, indent to
+ # beyond leftmost =; else to beyond first chunk of
+ # non-whitespace on initial line
if y.get_num_lines_in_stmt() > 1:
text.insert("insert", indent)
else:
@@ -298,8 +293,8 @@ class AutoIndent:
return "break"
# This line starts a brand new stmt; indent relative to
- # indentation of initial line of closest preceding interesting
- # stmt.
+ # indentation of initial line of closest preceding
+ # interesting stmt.
indent = y.get_base_indent_string()
text.insert("insert", indent)
if y.is_block_opener():
@@ -313,9 +308,10 @@ class AutoIndent:
auto_indent = newline_and_indent_event
- # Our editwin provides a is_char_in_string function that works with
- # a Tk text index, but PyParse only knows about offsets into a string.
- # This builds a function for PyParse that accepts an offset.
+ # Our editwin provides a is_char_in_string function that works
+ # with a Tk text index, but PyParse only knows about offsets into
+ # a string. This builds a function for PyParse that accepts an
+ # offset.
def _build_char_in_string_func(self, startindex):
def inner(offset, _startindex=startindex,
@@ -413,9 +409,11 @@ class AutoIndent:
def get_region(self):
text = self.text
- head = text.index("sel.first linestart")
- tail = text.index("sel.last -1c lineend +1c")
- if not (head and tail):
+ first, last = self.editwin.get_selection_indices()
+ if first and last:
+ head = text.index(first + " linestart")
+ tail = text.index(last + "-1c lineend +1c")
+ else:
head = text.index("insert linestart")
tail = text.index("insert lineend +1c")
chars = text.get(head, tail)
diff --git a/Tools/idle/EditorWindow.py b/Tools/idle/EditorWindow.py
index bc4edde..0f23b15 100644
--- a/Tools/idle/EditorWindow.py
+++ b/Tools/idle/EditorWindow.py
@@ -9,6 +9,9 @@ import tkMessageBox
import idlever
import WindowList
+# The default tab setting for a Text widget, in average-width characters.
+TK_TABWIDTH_DEFAULT = 8
+
# File menu
#$ event <<open-module>>
@@ -599,7 +602,7 @@ class EditorWindow:
# If a selection is defined in the text widget, return (start,
# end) as Tkinter text indices, otherwise return (None, None)
- def get_selection_index(self):
+ def get_selection_indices(self):
try:
first = self.text.index("sel.first")
last = self.text.index("sel.last")
@@ -607,6 +610,23 @@ class EditorWindow:
except TclError:
return None, None
+ # Return the text widget's current view of what a tab stop means
+ # (equivalent width in spaces).
+
+ def get_tabwidth(self):
+ current = self.text['tabs'] or TK_TABWIDTH_DEFAULT
+ return int(current)
+
+ # Set the text widget's current view of what a tab stop means.
+
+ def set_tabwidth(self, newtabwidth):
+ text = self.text
+ if self.get_tabwidth() != newtabwidth:
+ pixels = text.tk.call("font", "measure", text["font"],
+ "-displayof", text.master,
+ "n" * newtabwith)
+ text.configure(tabs=pixels)
+
def prepstr(s):
# Helper to extract the underscore from a string, e.g.
# prepstr("Co_py") returns (2, "Copy").
diff --git a/Tools/idle/FormatParagraph.py b/Tools/idle/FormatParagraph.py
index 6d2d475..671b303 100644
--- a/Tools/idle/FormatParagraph.py
+++ b/Tools/idle/FormatParagraph.py
@@ -38,7 +38,7 @@ class FormatParagraph:
def format_paragraph_event(self, event):
text = self.editwin.text
- first, last = self.editwin.get_selection_index()
+ first, last = self.editwin.get_selection_indices()
if first and last:
data = text.get(first, last)
comment_header = ''