Allow clearing the history, and saving the history on demand

Let the session tab show all of the history
Fix case-sensitive searches to actually allow case-insensitive
Make wx.WXK_NUMPAD_ENTER equivalent to wx.WXK_RETURN


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@37696 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Robin Dunn
2006-02-24 01:21:26 +00:00
parent 4251af7e75
commit e773f79b19
4 changed files with 90 additions and 37 deletions

View File

@@ -63,7 +63,7 @@ class Crust(wx.SplitterWindow):
self.notebook.AddPage(page=self.calltip, text='Calltip') self.notebook.AddPage(page=self.calltip, text='Calltip')
self.sessionlisting = SessionListing(parent=self.notebook) self.sessionlisting = SessionListing(parent=self.notebook)
self.notebook.AddPage(page=self.sessionlisting, text='Session') self.notebook.AddPage(page=self.sessionlisting, text='History')
self.dispatcherlisting = DispatcherListing(parent=self.notebook) self.dispatcherlisting = DispatcherListing(parent=self.notebook)
self.notebook.AddPage(page=self.dispatcherlisting, text='Dispatcher') self.notebook.AddPage(page=self.dispatcherlisting, text='Dispatcher')
@@ -162,6 +162,10 @@ class Calltip(wx.TextCtrl):
self.SetBackgroundColour(wx.Colour(255, 255, 208)) self.SetBackgroundColour(wx.Colour(255, 255, 208))
dispatcher.connect(receiver=self.display, signal='Shell.calltip') dispatcher.connect(receiver=self.display, signal='Shell.calltip')
df = self.GetFont()
font = wx.Font(df.GetPointSize(), wx.TELETYPE, wx.NORMAL, wx.NORMAL)
self.SetFont(font)
def display(self, calltip): def display(self, calltip):
"""Receiver for Shell.calltip signal.""" """Receiver for Shell.calltip signal."""
## self.SetValue(calltip) # Caused refresh problem on Windows. ## self.SetValue(calltip) # Caused refresh problem on Windows.
@@ -177,17 +181,29 @@ class SessionListing(wx.TextCtrl):
style = (wx.TE_MULTILINE | wx.TE_READONLY | style = (wx.TE_MULTILINE | wx.TE_READONLY |
wx.TE_RICH2 | wx.TE_DONTWRAP) wx.TE_RICH2 | wx.TE_DONTWRAP)
wx.TextCtrl.__init__(self, parent, id, style=style) wx.TextCtrl.__init__(self, parent, id, style=style)
dispatcher.connect(receiver=self.push, signal='Interpreter.push') dispatcher.connect(receiver=self.addHistory, signal="Shell.addHistory")
dispatcher.connect(receiver=self.clearHistory, signal="Shell.clearHistory")
dispatcher.connect(receiver=self.loadHistory, signal="Shell.loadHistory")
def push(self, command, more): df = self.GetFont()
"""Receiver for Interpreter.push signal.""" font = wx.Font(df.GetPointSize(), wx.TELETYPE, wx.NORMAL, wx.NORMAL)
if command and not more: self.SetFont(font)
def loadHistory(self, history):
# preload the existing history, if any
hist = history[:]
hist.reverse()
self.SetValue('\n'.join(hist) + '\n')
self.SetInsertionPointEnd()
def addHistory(self, command):
if command:
self.SetInsertionPointEnd() self.SetInsertionPointEnd()
start, end = self.GetSelection()
if start != end:
self.SetSelection(0, 0)
self.AppendText(command + '\n') self.AppendText(command + '\n')
def clearHistory(self):
self.SetValue("")
class DispatcherListing(wx.TextCtrl): class DispatcherListing(wx.TextCtrl):
"""Text control containing all dispatches for session.""" """Text control containing all dispatches for session."""
@@ -198,6 +214,10 @@ class DispatcherListing(wx.TextCtrl):
wx.TextCtrl.__init__(self, parent, id, style=style) wx.TextCtrl.__init__(self, parent, id, style=style)
dispatcher.connect(receiver=self.spy) dispatcher.connect(receiver=self.spy)
df = self.GetFont()
font = wx.Font(df.GetPointSize(), wx.TELETYPE, wx.NORMAL, wx.NORMAL)
self.SetFont(font)
def spy(self, signal, sender): def spy(self, signal, sender):
"""Receiver for Any signal from Any sender.""" """Receiver for Any signal from Any sender."""
text = '%r from %s' % (signal, sender) text = '%r from %s' % (signal, sender)

View File

@@ -251,13 +251,13 @@ class EditWindow(stc.StyledTextCtrl):
def DoFindNext(self, findData, findDlg=None): def DoFindNext(self, findData, findDlg=None):
backward = not (findData.GetFlags() & wx.FR_DOWN) backward = not (findData.GetFlags() & wx.FR_DOWN)
matchcase = findData.GetFlags() & wx.FR_MATCHCASE matchcase = (findData.GetFlags() & wx.FR_MATCHCASE) != 0
end = self.GetLastPosition() end = self.GetLastPosition()
textstring = self.GetRange(0, end) textstring = self.GetRange(0, end)
findstring = findData.GetFindString() findstring = findData.GetFindString()
if not matchcase: if not matchcase:
textstring.lower() textstring = textstring.lower()
findstring.lower() findstring = findstring.lower()
if backward: if backward:
start = self.GetSelection()[0] start = self.GetSelection()[0]
loc = textstring.rfind(findstring, 0, start) loc = textstring.rfind(findstring, 0, start)

View File

@@ -8,6 +8,7 @@ import wx
import os import os
from version import VERSION from version import VERSION
import editwindow import editwindow
import dispatcher
ID_NEW = wx.ID_NEW ID_NEW = wx.ID_NEW
ID_OPEN = wx.ID_OPEN ID_OPEN = wx.ID_OPEN
@@ -44,6 +45,8 @@ ID_USEAA = wx.NewId()
ID_SHOW_LINENUMBERS = wx.NewId() ID_SHOW_LINENUMBERS = wx.NewId()
ID_AUTO_SAVESETTINGS = wx.NewId() ID_AUTO_SAVESETTINGS = wx.NewId()
ID_SAVEHISTORY = wx.NewId() ID_SAVEHISTORY = wx.NewId()
ID_SAVEHISTORYNOW = wx.NewId()
ID_CLEARHISTORY = wx.NewId()
ID_SAVESETTINGS = wx.NewId() ID_SAVESETTINGS = wx.NewId()
ID_DELSETTINGSFILE = wx.NewId() ID_DELSETTINGSFILE = wx.NewId()
ID_EDITSTARTUPSCRIPT = wx.NewId() ID_EDITSTARTUPSCRIPT = wx.NewId()
@@ -138,9 +141,9 @@ class Frame(wx.Frame):
m.Append(ID_SELECTALL, 'Select A&ll \tCtrl+A', m.Append(ID_SELECTALL, 'Select A&ll \tCtrl+A',
'Select all text') 'Select all text')
m.AppendSeparator() m.AppendSeparator()
m.Append(ID_EMPTYBUFFER, 'E&mpty Buffer', m.Append(ID_EMPTYBUFFER, 'E&mpty Buffer...',
'Delete all the contents of the edit buffer') 'Delete all the contents of the edit buffer')
m.Append(ID_FIND, '&Find Text \tCtrl+F', m.Append(ID_FIND, '&Find Text... \tCtrl+F',
'Search for text in the edit buffer') 'Search for text in the edit buffer')
m.Append(ID_FINDNEXT, 'Find &Next \tF3', m.Append(ID_FINDNEXT, 'Find &Next \tF3',
'Find next/previous instance of the search text') 'Find next/previous instance of the search text')
@@ -180,14 +183,22 @@ class Frame(wx.Frame):
'Use anti-aliased fonts', wx.ITEM_CHECK) 'Use anti-aliased fonts', wx.ITEM_CHECK)
m.AppendSeparator() m.AppendSeparator()
m.Append(ID_SAVEHISTORY, '&Save History',
self.historyMenu = wx.Menu()
self.historyMenu.Append(ID_SAVEHISTORY, '&Autosave History',
'Automatically save history on close', wx.ITEM_CHECK) 'Automatically save history on close', wx.ITEM_CHECK)
self.historyMenu.Append(ID_SAVEHISTORYNOW, '&Save History Now',
'Save history')
self.historyMenu.Append(ID_CLEARHISTORY, '&Clear History ',
'Clear history')
m.AppendMenu(-1, "&History", self.historyMenu, "History Options")
self.startupMenu = wx.Menu() self.startupMenu = wx.Menu()
self.startupMenu.Append(ID_EXECSTARTUPSCRIPT, self.startupMenu.Append(ID_EXECSTARTUPSCRIPT,
'E&xecute Startup Script', 'E&xecute Startup Script',
'Execute Startup Script', wx.ITEM_CHECK) 'Execute Startup Script', wx.ITEM_CHECK)
self.startupMenu.Append(ID_EDITSTARTUPSCRIPT, self.startupMenu.Append(ID_EDITSTARTUPSCRIPT,
'&Edit Startup Script', '&Edit Startup Script...',
'Edit Startup Script') 'Edit Startup Script')
m.AppendMenu(ID_STARTUP, '&Startup', self.startupMenu, 'Startup Options') m.AppendMenu(ID_STARTUP, '&Startup', self.startupMenu, 'Startup Options')
@@ -249,6 +260,8 @@ class Frame(wx.Frame):
self.Bind(wx.EVT_MENU, self.OnShowLineNumbers, id=ID_SHOW_LINENUMBERS) self.Bind(wx.EVT_MENU, self.OnShowLineNumbers, id=ID_SHOW_LINENUMBERS)
self.Bind(wx.EVT_MENU, self.OnAutoSaveSettings, id=ID_AUTO_SAVESETTINGS) self.Bind(wx.EVT_MENU, self.OnAutoSaveSettings, id=ID_AUTO_SAVESETTINGS)
self.Bind(wx.EVT_MENU, self.OnSaveHistory, id=ID_SAVEHISTORY) self.Bind(wx.EVT_MENU, self.OnSaveHistory, id=ID_SAVEHISTORY)
self.Bind(wx.EVT_MENU, self.OnSaveHistoryNow, id=ID_SAVEHISTORYNOW)
self.Bind(wx.EVT_MENU, self.OnClearHistory, id=ID_CLEARHISTORY)
self.Bind(wx.EVT_MENU, self.OnSaveSettings, id=ID_SAVESETTINGS) self.Bind(wx.EVT_MENU, self.OnSaveSettings, id=ID_SAVESETTINGS)
self.Bind(wx.EVT_MENU, self.OnDelSettingsFile, id=ID_DELSETTINGSFILE) self.Bind(wx.EVT_MENU, self.OnDelSettingsFile, id=ID_DELSETTINGSFILE)
self.Bind(wx.EVT_MENU, self.OnEditStartupScript, id=ID_EDITSTARTUPSCRIPT) self.Bind(wx.EVT_MENU, self.OnEditStartupScript, id=ID_EDITSTARTUPSCRIPT)
@@ -288,6 +301,8 @@ class Frame(wx.Frame):
self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_DELSETTINGSFILE) self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_DELSETTINGSFILE)
self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_EXECSTARTUPSCRIPT) self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_EXECSTARTUPSCRIPT)
self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_SAVEHISTORY) self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_SAVEHISTORY)
self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_SAVEHISTORYNOW)
self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_CLEARHISTORY)
self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_EDITSTARTUPSCRIPT) self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_EDITSTARTUPSCRIPT)
self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_FIND) self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_FIND)
self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_FINDNEXT) self.Bind(wx.EVT_UPDATE_UI, self.OnUpdateMenu, id=ID_FINDNEXT)
@@ -436,7 +451,13 @@ class Frame(wx.Frame):
win.SetUseAntiAliasing(event.IsChecked()) win.SetUseAntiAliasing(event.IsChecked())
def OnSaveHistory(self, event): def OnSaveHistory(self, event):
self.saveHistory = event.IsChecked() self.autoSaveHistory = event.IsChecked()
def OnSaveHistoryNow(self, event):
self.SaveHistory()
def OnClearHistory(self, event):
self.shell.clearHistory()
def OnAutoSaveSettings(self, event): def OnAutoSaveSettings(self, event):
self.autoSaveSettings = event.IsChecked() self.autoSaveSettings = event.IsChecked()
@@ -474,6 +495,9 @@ class Frame(wx.Frame):
self.findDlg.Show() self.findDlg.Show()
def OnFindNext(self, event): def OnFindNext(self, event):
if not self.findData.GetFindString():
self.OnFindText(event)
return
if isinstance(event, wx.FindDialogEvent): if isinstance(event, wx.FindDialogEvent):
win = self.findDlg.GetParent() win = self.findDlg.GetParent()
else: else:
@@ -567,8 +591,14 @@ class Frame(wx.Frame):
event.Enable(self.config is not None) event.Enable(self.config is not None)
elif id == ID_SAVEHISTORY: elif id == ID_SAVEHISTORY:
event.Check(self.saveHistory) event.Check(self.autoSaveHistory)
event.Enable(self.dataDir is not None) event.Enable(self.dataDir is not None)
elif id == ID_SAVEHISTORYNOW:
event.Enable(self.dataDir is not None and
hasattr(self, 'SaveHistory'))
elif id == ID_CLEARHISTORY:
event.Enable(self.dataDir is not None)
elif id == ID_EDITSTARTUPSCRIPT: elif id == ID_EDITSTARTUPSCRIPT:
event.Enable(hasattr(self, 'EditStartupScript')) event.Enable(hasattr(self, 'EditStartupScript'))
event.Enable(self.dataDir is not None) event.Enable(self.dataDir is not None)
@@ -576,9 +606,8 @@ class Frame(wx.Frame):
elif id == ID_FIND: elif id == ID_FIND:
event.Enable(hasattr(win, 'DoFindNext')) event.Enable(hasattr(win, 'DoFindNext'))
elif id == ID_FINDNEXT: elif id == ID_FINDNEXT:
event.Enable(hasattr(win, 'DoFindNext') and event.Enable(hasattr(win, 'DoFindNext'))
self.findData.GetFindString() != '')
else: else:
event.Enable(False) event.Enable(False)
except AttributeError: except AttributeError:
@@ -645,7 +674,7 @@ class ShellFrameMixin:
self.startupScript = os.path.join(self.dataDir, 'startup') self.startupScript = os.path.join(self.dataDir, 'startup')
self.autoSaveSettings = False self.autoSaveSettings = False
self.saveHistory = False self.autoSaveHistory = False
# We need this one before we have a chance to load the settings... # We need this one before we have a chance to load the settings...
self.execStartupScript = True self.execStartupScript = True
@@ -672,7 +701,7 @@ class ShellFrameMixin:
if self.config is not None: if self.config is not None:
self.autoSaveSettings = self.config.ReadBool('Options/AutoSaveSettings', False) self.autoSaveSettings = self.config.ReadBool('Options/AutoSaveSettings', False)
self.execStartupScript = self.config.ReadBool('Options/ExecStartupScript', True) self.execStartupScript = self.config.ReadBool('Options/ExecStartupScript', True)
self.saveHistory = self.config.ReadBool('Options/SaveHistory', False) self.autoSaveHistory = self.config.ReadBool('Options/AutoSaveHistory', False)
self.LoadHistory() self.LoadHistory()
@@ -681,8 +710,9 @@ class ShellFrameMixin:
# always save this one # always save this one
self.config.WriteBool('Options/AutoSaveSettings', self.autoSaveSettings) self.config.WriteBool('Options/AutoSaveSettings', self.autoSaveSettings)
if self.autoSaveSettings: if self.autoSaveSettings:
self.config.WriteBool('Options/SaveHistory', self.saveHistory) self.config.WriteBool('Options/AutoSaveHistory', self.autoSaveHistory)
self.config.WriteBool('Options/ExecStartupScript', self.execStartupScript) self.config.WriteBool('Options/ExecStartupScript', self.execStartupScript)
if self.autoSaveHistory:
self.SaveHistory() self.SaveHistory()
@@ -690,20 +720,17 @@ class ShellFrameMixin:
def SaveHistory(self): def SaveHistory(self):
if self.dataDir: if self.dataDir:
try: try:
# always open the file so that when we are not
# saving the history, the old file is emptied.
name = os.path.join(self.dataDir, 'history') name = os.path.join(self.dataDir, 'history')
f = file(name, 'w') f = file(name, 'w')
if self.saveHistory: hist = '\x00\n'.join(self.shell.history)
hist = '\n'.join(self.shell.history) f.write(hist)
f.write(hist)
f.close() f.close()
except: except:
d = wx.MessageDialog(self, "Error saving history file.", d = wx.MessageDialog(self, "Error saving history file.",
"Error", wx.ICON_EXCLAMATION) "Error", wx.ICON_EXCLAMATION)
d.ShowModal() d.ShowModal()
d.Destroy() d.Destroy()
raise
def LoadHistory(self): def LoadHistory(self):
if self.dataDir: if self.dataDir:
@@ -713,7 +740,8 @@ class ShellFrameMixin:
f = file(name, 'U') f = file(name, 'U')
hist = f.read() hist = f.read()
f.close() f.close()
self.shell.history = hist.split('\n') self.shell.history = hist.split('\x00\n')
dispatcher.send(signal="Shell.loadHistory", history=self.shell.history)
except: except:
d = wx.MessageDialog(self, "Error loading history file.", d = wx.MessageDialog(self, "Error loading history file.",
"Error", wx.ICON_EXCLAMATION) "Error", wx.ICON_EXCLAMATION)

View File

@@ -147,10 +147,9 @@ Ctrl+[ Decrease font size.
Ctrl+= Default font size. Ctrl+= Default font size.
Ctrl-Space Show Auto Completion. Ctrl-Space Show Auto Completion.
Ctrl-Alt-Space Show Call Tip. Ctrl-Alt-Space Show Call Tip.
Alt+Shift+C Clear Screen.
Shift+Enter Complete Text from History. Shift+Enter Complete Text from History.
Ctrl+F Search (backwards) TODO: regexp-wholeWords-... Ctrl+F Search
Ctrl+G Search next F3 Search next
Ctrl+H "hide" lines containing selection / "unhide" Ctrl+H "hide" lines containing selection / "unhide"
F12 on/off "free-edit" mode F12 on/off "free-edit" mode
""" """
@@ -321,6 +320,11 @@ class Shell(editwindow.EditWindow):
wx.CallAfter(self.ScrollToLine, 0) wx.CallAfter(self.ScrollToLine, 0)
def clearHistory(self):
self.history = []
self.historyIndex = -1
dispatcher.send(signal="Shell.clearHistory")
def destroy(self): def destroy(self):
del self.interp del self.interp
@@ -416,7 +420,7 @@ Platform: %s""" % \
currpos = self.GetCurrentPos() currpos = self.GetCurrentPos()
stoppos = self.promptPosEnd stoppos = self.promptPosEnd
# Return (Enter) needs to be ignored in this handler. # Return (Enter) needs to be ignored in this handler.
if key == wx.WXK_RETURN: if key in [wx.WXK_RETURN, wx.WXK_NUMPAD_ENTER]:
pass pass
elif key in self.autoCompleteKeys: elif key in self.autoCompleteKeys:
# Usually the dot (period) key activates auto completion. # Usually the dot (period) key activates auto completion.
@@ -512,17 +516,17 @@ Platform: %s""" % \
# Return (Enter) is used to submit a command to the # Return (Enter) is used to submit a command to the
# interpreter. # interpreter.
if (not controlDown and not shiftDown and not altDown) and key == wx.WXK_RETURN: if (not controlDown and not shiftDown and not altDown) and key in [wx.WXK_RETURN, wx.WXK_NUMPAD_ENTER]:
if self.CallTipActive(): if self.CallTipActive():
self.CallTipCancel() self.CallTipCancel()
self.processLine() self.processLine()
# Complete Text (from already typed words) # Complete Text (from already typed words)
elif shiftDown and key == wx.WXK_RETURN: elif shiftDown and key in [wx.WXK_RETURN, wx.WXK_NUMPAD_ENTER]:
self.OnShowCompHistory() self.OnShowCompHistory()
# Ctrl+Return (Ctrl+Enter) is used to insert a line break. # Ctrl+Return (Ctrl+Enter) is used to insert a line break.
elif controlDown and key == wx.WXK_RETURN: elif controlDown and key in [wx.WXK_RETURN, wx.WXK_NUMPAD_ENTER]:
if self.CallTipActive(): if self.CallTipActive():
self.CallTipCancel() self.CallTipCancel()
if currpos == endpos: if currpos == endpos:
@@ -918,6 +922,7 @@ Platform: %s""" % \
if command != '' \ if command != '' \
and (len(self.history) == 0 or command != self.history[0]): and (len(self.history) == 0 or command != self.history[0]):
self.history.insert(0, command) self.history.insert(0, command)
dispatcher.send(signal="Shell.addHistory", command=command)
def write(self, text): def write(self, text):
"""Display text in the shell. """Display text in the shell.