Skip to content

Commit

Permalink
bpo-17535: IDLE editor line numbers (pythonGH-14030)
Browse files Browse the repository at this point in the history
  • Loading branch information
taleinat authored Jul 23, 2019
1 parent 1ebee37 commit 7123ea0
Show file tree
Hide file tree
Showing 18 changed files with 891 additions and 80 deletions.
17 changes: 13 additions & 4 deletions Doc/library/idle.rst
Original file line number Diff line number Diff line change
Expand Up @@ -290,22 +290,31 @@ Options menu (Shell and Editor)
Configure IDLE
Open a configuration dialog and change preferences for the following:
fonts, indentation, keybindings, text color themes, startup windows and
size, additional help sources, and extensions. On macOS, open the
size, additional help sources, and extensions. On macOS, open the
configuration dialog by selecting Preferences in the application
menu. For more, see
menu. For more details, see
:ref:`Setting preferences <preferences>` under Help and preferences.

Most configuration options apply to all windows or all future windows.
The option items below only apply to the active window.

Show/Hide Code Context (Editor Window only)
Open a pane at the top of the edit window which shows the block context
of the code which has scrolled above the top of the window. See
:ref:`Code Context <code-context>` in the Editing and Navigation section below.
:ref:`Code Context <code-context>` in the Editing and Navigation section
below.

Show/Hide Line Numbers (Editor Window only)
Open a column to the left of the edit window which shows the number
of each line of text. The default is off, which may be changed in the
preferences (see :ref:`Setting preferences <preferences>`).

Zoom/Restore Height
Toggles the window between normal size and maximum height. The initial size
defaults to 40 lines by 80 chars unless changed on the General tab of the
Configure IDLE dialog. The maximum height for a screen is determined by
momentarily maximizing a window the first time one is zoomed on the screen.
Changing screen settings may invalidate the saved height. This toogle has
Changing screen settings may invalidate the saved height. This toggle has
no effect when a window is maximized.

Window menu (Shell and Editor)
Expand Down
7 changes: 7 additions & 0 deletions Doc/whatsnew/3.7.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1017,6 +1017,13 @@ by right-clicking the button. (Contributed by Tal Einat in :issue:`1529353`.)

The changes above have been backported to 3.6 maintenance releases.

New in 3.7.5:

Add optional line numbers for IDLE editor windows. Windows
open without line numbers unless set otherwise in the General
tab of the configuration dialog.
(Contributed by Tal Einat and Saimadhav Heblikar in :issue:`17535`.)


importlib
---------
Expand Down
5 changes: 5 additions & 0 deletions Doc/whatsnew/3.8.rst
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,11 @@ for certain types of invalid or corrupt gzip files.
idlelib and IDLE
----------------

Add optional line numbers for IDLE editor windows. Windows
open without line numbers unless set otherwise in the General
tab of the configuration dialog.
(Contributed by Tal Einat and Saimadhav Heblikar in :issue:`17535`.)

Output over N lines (50 by default) is squeezed down to a button.
N can be changed in the PyShell section of the General page of the
Settings dialog. Fewer, but possibly extra long, lines can be squeezed by
Expand Down
35 changes: 27 additions & 8 deletions Lib/idlelib/codecontext.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from sys import maxsize as INFINITY

import tkinter
from tkinter.constants import TOP, X, SUNKEN
from tkinter.constants import NSEW, SUNKEN

from idlelib.config import idleConf

Expand Down Expand Up @@ -67,6 +67,7 @@ def __init__(self, editwin):

def _reset(self):
self.context = None
self.cell00 = None
self.t1 = None
self.topvisible = 1
self.info = [(0, -1, "", False)]
Expand Down Expand Up @@ -105,25 +106,37 @@ def toggle_code_context_event(self, event=None):
padx = 0
border = 0
for widget in widgets:
padx += widget.tk.getint(widget.pack_info()['padx'])
info = (widget.grid_info()
if widget is self.editwin.text
else widget.pack_info())
padx += widget.tk.getint(info['padx'])
padx += widget.tk.getint(widget.cget('padx'))
border += widget.tk.getint(widget.cget('border'))
self.context = tkinter.Text(
self.editwin.top, font=self.text['font'],
self.editwin.text_frame,
height=1,
width=1, # Don't request more than we get.
highlightthickness=0,
padx=padx, border=border, relief=SUNKEN, state='disabled')
self.update_font()
self.update_highlight_colors()
self.context.bind('<ButtonRelease-1>', self.jumptoline)
# Get the current context and initiate the recurring update event.
self.timer_event()
# Pack the context widget before and above the text_frame widget,
# thus ensuring that it will appear directly above text_frame.
self.context.pack(side=TOP, fill=X, expand=False,
before=self.editwin.text_frame)
# Grid the context widget above the text widget.
self.context.grid(row=0, column=1, sticky=NSEW)

line_number_colors = idleConf.GetHighlight(idleConf.CurrentTheme(),
'linenumber')
self.cell00 = tkinter.Frame(self.editwin.text_frame,
bg=line_number_colors['background'])
self.cell00.grid(row=0, column=0, sticky=NSEW)
menu_status = 'Hide'
else:
self.context.destroy()
self.context = None
self.cell00.destroy()
self.cell00 = None
self.text.after_cancel(self.t1)
self._reset()
menu_status = 'Show'
Expand Down Expand Up @@ -221,8 +234,9 @@ def timer_event(self):
self.update_code_context()
self.t1 = self.text.after(self.UPDATEINTERVAL, self.timer_event)

def update_font(self, font):
def update_font(self):
if self.context is not None:
font = idleConf.GetFont(self.text, 'main', 'EditorWindow')
self.context['font'] = font

def update_highlight_colors(self):
Expand All @@ -231,6 +245,11 @@ def update_highlight_colors(self):
self.context['background'] = colors['background']
self.context['foreground'] = colors['foreground']

if self.cell00 is not None:
line_number_colors = idleConf.GetHighlight(idleConf.CurrentTheme(),
'linenumber')
self.cell00.config(bg=line_number_colors['background'])


CodeContext.reload()

Expand Down
14 changes: 10 additions & 4 deletions Lib/idlelib/config-highlight.def
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ hit-foreground= #ffffff
hit-background= #000000
error-foreground= #000000
error-background= #ff7777
context-foreground= #000000
context-background= lightgray
linenumber-foreground= gray
linenumber-background= #ffffff
#cursor (only foreground can be set, restart IDLE)
cursor-foreground= black
#shell window
Expand All @@ -31,8 +35,6 @@ stderr-foreground= red
stderr-background= #ffffff
console-foreground= #770000
console-background= #ffffff
context-foreground= #000000
context-background= lightgray

[IDLE New]
normal-foreground= #000000
Expand All @@ -55,6 +57,10 @@ hit-foreground= #ffffff
hit-background= #000000
error-foreground= #000000
error-background= #ff7777
context-foreground= #000000
context-background= lightgray
linenumber-foreground= gray
linenumber-background= #ffffff
#cursor (only foreground can be set, restart IDLE)
cursor-foreground= black
#shell window
Expand All @@ -64,8 +70,6 @@ stderr-foreground= red
stderr-background= #ffffff
console-foreground= #770000
console-background= #ffffff
context-foreground= #000000
context-background= lightgray

[IDLE Dark]
comment-foreground = #dd0000
Expand Down Expand Up @@ -97,3 +101,5 @@ comment-background = #002240
break-foreground = #FFFFFF
context-foreground= #ffffff
context-background= #454545
linenumber-foreground= gray
linenumber-background= #002240
5 changes: 3 additions & 2 deletions Lib/idlelib/config-main.def
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
# Additional help sources are listed in the [HelpFiles] section below
# and should be viewable by a web browser (or the Windows Help viewer in
# the case of .chm files). These sources will be listed on the Help
# menu. The pattern, and two examples, are
# menu. The pattern, and two examples, are:
#
# <sequence_number = menu item;/path/to/help/source>
# 1 = IDLE;C:/Programs/Python36/Lib/idlelib/help.html
Expand All @@ -46,7 +46,7 @@
# platform specific because of path separators, drive specs etc.
#
# The default files should not be edited except to add new sections to
# config-extensions.def for added extensions . The user files should be
# config-extensions.def for added extensions. The user files should be
# modified through the Settings dialog.

[General]
Expand All @@ -65,6 +65,7 @@ font= TkFixedFont
font-size= 10
font-bold= 0
encoding= none
line-numbers-default= 0

[PyShell]
auto-squeeze-min-lines= 50
Expand Down
10 changes: 7 additions & 3 deletions Lib/idlelib/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,10 @@ def GetThemeDict(self, type, themeName):
'hit-background':'#000000',
'error-foreground':'#ffffff',
'error-background':'#000000',
'context-foreground':'#000000',
'context-background':'#ffffff',
'linenumber-foreground':'#000000',
'linenumber-background':'#ffffff',
#cursor (only foreground can be set)
'cursor-foreground':'#000000',
#shell window
Expand All @@ -328,11 +332,11 @@ def GetThemeDict(self, type, themeName):
'stderr-background':'#ffffff',
'console-foreground':'#000000',
'console-background':'#ffffff',
'context-foreground':'#000000',
'context-background':'#ffffff',
}
for element in theme:
if not cfgParser.has_option(themeName, element):
if not (cfgParser.has_option(themeName, element) or
# Skip warning for new elements.
element.startswith(('context-', 'linenumber-'))):
# Print warning that will return a default color
warning = ('\n Warning: config.IdleConf.GetThemeDict'
' -\n problem retrieving theme element %r'
Expand Down
26 changes: 26 additions & 0 deletions Lib/idlelib/configdialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -819,6 +819,7 @@ def create_page_highlight(self):
'Shell Error Text': ('error', '12'),
'Shell Stdout Text': ('stdout', '13'),
'Shell Stderr Text': ('stderr', '14'),
'Line Number': ('linenumber', '16'),
}
self.builtin_name = tracers.add(
StringVar(self), self.var_changed_builtin_name)
Expand Down Expand Up @@ -866,6 +867,11 @@ def create_page_highlight(self):
('stderr', 'stderr'), ('\n\n', 'normal'))
for texttag in text_and_tags:
text.insert(END, texttag[0], texttag[1])
n_lines = len(text.get('1.0', END).splitlines())
for lineno in range(1, n_lines + 1):
text.insert(f'{lineno}.0',
f'{lineno:{len(str(n_lines))}d} ',
'linenumber')
for element in self.theme_elements:
def tem(event, elem=element):
# event.widget.winfo_top_level().highlight_target.set(elem)
Expand Down Expand Up @@ -1827,6 +1833,9 @@ def create_page_general(self):
frame_format: Frame
format_width_title: Label
(*)format_width_int: Entry - format_width
frame_line_numbers_default: Frame
line_numbers_default_title: Label
(*)line_numbers_default_bool: Checkbutton - line_numbers_default
frame_context: Frame
context_title: Label
(*)context_int: Entry - context_lines
Expand Down Expand Up @@ -1866,6 +1875,9 @@ def create_page_general(self):
IntVar(self), ('main', 'General', 'autosave'))
self.format_width = tracers.add(
StringVar(self), ('extensions', 'FormatParagraph', 'max-width'))
self.line_numbers_default = tracers.add(
BooleanVar(self),
('main', 'EditorWindow', 'line-numbers-default'))
self.context_lines = tracers.add(
StringVar(self), ('extensions', 'CodeContext', 'maxlines'))

Expand Down Expand Up @@ -1944,6 +1956,14 @@ def create_page_general(self):
validatecommand=self.digits_only, validate='key',
)

frame_line_numbers_default = Frame(frame_editor, borderwidth=0)
line_numbers_default_title = Label(
frame_line_numbers_default, text='Show line numbers in new windows')
self.line_numbers_default_bool = Checkbutton(
frame_line_numbers_default,
variable=self.line_numbers_default,
width=1)

frame_context = Frame(frame_editor, borderwidth=0)
context_title = Label(frame_context, text='Max Context Lines :')
self.context_int = Entry(
Expand Down Expand Up @@ -2021,6 +2041,10 @@ def create_page_general(self):
frame_format.pack(side=TOP, padx=5, pady=0, fill=X)
format_width_title.pack(side=LEFT, anchor=W, padx=5, pady=5)
self.format_width_int.pack(side=TOP, padx=10, pady=5)
# frame_line_numbers_default.
frame_line_numbers_default.pack(side=TOP, padx=5, pady=0, fill=X)
line_numbers_default_title.pack(side=LEFT, anchor=W, padx=5, pady=5)
self.line_numbers_default_bool.pack(side=LEFT, padx=5, pady=5)
# frame_context.
frame_context.pack(side=TOP, padx=5, pady=0, fill=X)
context_title.pack(side=LEFT, anchor=W, padx=5, pady=5)
Expand Down Expand Up @@ -2063,6 +2087,8 @@ def load_general_cfg(self):
'main', 'General', 'autosave', default=0, type='bool'))
self.format_width.set(idleConf.GetOption(
'extensions', 'FormatParagraph', 'max-width', type='int'))
self.line_numbers_default.set(idleConf.GetOption(
'main', 'EditorWindow', 'line-numbers-default', type='bool'))
self.context_lines.set(idleConf.GetOption(
'extensions', 'CodeContext', 'maxlines', type='int'))

Expand Down
Loading

0 comments on commit 7123ea0

Please sign in to comment.