##// END OF EJS Templates
don't try to replace history when rl history unchanged...
don't try to replace history when rl history unchanged preserves readlines consecutive duplicate removal for single lines

File last commit:

r4872:34c10438
r5254:197ca03b
Show More
ipython_history.py
510 lines | 20.5 KiB | text/x-python | PythonLexer
/ IPython / deathrow / gui / wx / ipython_history.py
ville
initialization (no svn history)
r988 #!/usr/bin/python
# -*- coding: iso-8859-15 -*-
import wx
import wx.stc as stc
import keyword
#-----------------------------------------
# History widget for IPython
__version__ = 0.5
__author__ = "Laurent Dufrechou"
__email__ = "laurent.dufrechou _at_ gmail.com"
__license__ = "BSD"
#-----------------------------------------
Brian Granger
More work addressing review comments for Fernando's branch....
r2499
ville
initialization (no svn history)
r988 class IPythonHistoryPanel(wx.Panel):
def __init__(self, parent,flt_empty=True,
flt_doc=True,flt_cmd=True,flt_magic=True):
Bernardo B. Marques
remove all trailling spaces
r4872
ville
initialization (no svn history)
r988 wx.Panel.__init__(self,parent,-1)
#text_ctrl = wx.TextCtrl(self, -1, style=wx.TE_MULTILINE)
text_ctrl = PythonSTC(self, -1)
Bernardo B. Marques
remove all trailling spaces
r4872
ville
initialization (no svn history)
r988 st_filt = wx.StaticText(self, -1, " Filter:")
self.filter_empty = wx.CheckBox(self, -1, "Empty commands")
self.filter_doc = wx.CheckBox(self, -1, "?: Doc commands")
self.filter_cmd = wx.CheckBox(self, -1, "!: Sys commands")
self.filter_magic = wx.CheckBox(self, -1, "%: Magic keys")
ldufrechou
[gui/wx] added options save/restore for history widget
r1176 self.options={'filter_empty':{'value':'True',
laurent.dufrechou@gmail.com
some more little cleanup and a bug correction with prompt that comes with last commit
r1817 'checkbox':self.filter_empty, \
'True':True,'False':False,
'setfunc':lambda x:None},
ldufrechou
[gui/wx] added options save/restore for history widget
r1176 'filter_doc':{'value':'True',
laurent.dufrechou@gmail.com
some more little cleanup and a bug correction with prompt that comes with last commit
r1817 'checkbox':self.filter_doc, \
'True':True,'False':False,
'setfunc':lambda x:None},
ldufrechou
[gui/wx] added options save/restore for history widget
r1176 'filter_cmd':{'value':'True',
laurent.dufrechou@gmail.com
some more little cleanup and a bug correction with prompt that comes with last commit
r1817 'checkbox':self.filter_cmd, \
'True':True,'False':False,
'setfunc':lambda x:None},
ldufrechou
[gui/wx] added options save/restore for history widget
r1176 'filter_magic':{'value':'True',
laurent.dufrechou@gmail.com
some more little cleanup and a bug correction with prompt that comes with last commit
r1817 'checkbox':self.filter_magic, \
'True':True,'False':False,
'setfunc':lambda x:None},
ldufrechou
[gui/wx] added options save/restore for history widget
r1176 }
self.reloadOptions(self.options)
self.filter_empty.Bind(wx.EVT_CHECKBOX, self.evtCheckEmptyFilter)
self.filter_doc.Bind(wx.EVT_CHECKBOX, self.evtCheckDocFilter)
self.filter_cmd.Bind(wx.EVT_CHECKBOX, self.evtCheckCmdFilter)
self.filter_magic.Bind(wx.EVT_CHECKBOX, self.evtCheckMagicFilter)
Bernardo B. Marques
remove all trailling spaces
r4872
ldufrechou
[gui/wx] added options save/restore for history widget
r1176 #self.filter_empty.SetValue(flt_empty)
#self.filter_doc.SetValue(flt_doc)
#self.filter_cmd.SetValue(flt_cmd)
#self.filter_magic.SetValue(flt_magic)
Bernardo B. Marques
remove all trailling spaces
r4872
ville
initialization (no svn history)
r988 sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(text_ctrl, 1, wx.EXPAND)
sizer.AddMany( [(5,5),
st_filt,
(10,10),
self.filter_empty,
self.filter_doc,
self.filter_cmd,
self.filter_magic,
(10,10),
])
self.SetAutoLayout(True)
sizer.Fit(self)
sizer.SetSizeHints(self)
self.SetSizer(sizer)
self.text_ctrl=text_ctrl
#text_ctrl.SetText(demoText + open('Main.py').read())
text_ctrl.EmptyUndoBuffer()
text_ctrl.Colourise(0, -1)
# line numbers in the margin
text_ctrl.SetMarginType(1, stc.STC_MARGIN_NUMBER)
text_ctrl.SetMarginWidth(1, 15)
Bernardo B. Marques
remove all trailling spaces
r4872
ville
initialization (no svn history)
r988 def write(self,history_line):
add = True
if self.filter_empty.GetValue() == True and history_line == '':
add = False
if len(history_line)>0:
if self.filter_doc.GetValue() == True and history_line[-1:] == '?':
add = False
if self.filter_cmd.GetValue() == True and history_line[0] == '!':
add = False
if self.filter_magic.GetValue() == True and history_line[0] == '%':
add = False
Gael Varoquaux
Changed tabs to whitespace in the wx frontend...
r1103 if add:
self.text_ctrl.AppendText(history_line+'\n')
ville
initialization (no svn history)
r988
ldufrechou
[gui/wx] added options save/restore for history widget
r1176 #------------------------ Option Section -----------------------------------
def processOptionCheckedEvt(self, event, name):
if event.IsChecked():
self.options[name]['value']='True'
else:
self.options[name]['value']='False'
self.updateOptionTracker(name,
self.options[name]['value'])
Bernardo B. Marques
remove all trailling spaces
r4872
ldufrechou
[gui/wx] added options save/restore for history widget
r1176 def evtCheckEmptyFilter(self, event):
self.processOptionCheckedEvt(event, 'filter_empty')
Bernardo B. Marques
remove all trailling spaces
r4872
ldufrechou
[gui/wx] added options save/restore for history widget
r1176 def evtCheckDocFilter(self, event):
self.processOptionCheckedEvt(event, 'filter_doc')
def evtCheckCmdFilter(self, event):
self.processOptionCheckedEvt(event, 'filter_cmd')
def evtCheckMagicFilter(self, event):
self.processOptionCheckedEvt(event, 'filter_magic')
Bernardo B. Marques
remove all trailling spaces
r4872
ldufrechou
[gui/wx] added options save/restore for history widget
r1176 def getOptions(self):
return self.options
Bernardo B. Marques
remove all trailling spaces
r4872
ldufrechou
[gui/wx] added options save/restore for history widget
r1176 def reloadOptions(self,options):
self.options = options
for key in self.options.keys():
value = self.options[key]['value']
self.options[key]['checkbox'].SetValue(self.options[key][value])
self.options[key]['setfunc'](value)
#------------------------ Hook Section -----------------------------------
def updateOptionTracker(self,name,value):
'''
Default history tracker (does nothing)
'''
pass
Bernardo B. Marques
remove all trailling spaces
r4872
ldufrechou
[gui/wx] added options save/restore for history widget
r1176 def setOptionTrackerHook(self,func):
'''
Define a new history tracker
'''
self.updateOptionTracker = func
ville
initialization (no svn history)
r988
Bernardo B. Marques
remove all trailling spaces
r4872
ville
initialization (no svn history)
r988 #----------------------------------------------------------------------
# Font definition for Styled Text Control
if wx.Platform == '__WXMSW__':
faces = { 'times': 'Times New Roman',
'mono' : 'Courier New',
'helv' : 'Arial',
'other': 'Comic Sans MS',
'size' : 8,
'size2': 6,
}
elif wx.Platform == '__WXMAC__':
faces = { 'times': 'Times New Roman',
'mono' : 'Monaco',
'helv' : 'Arial',
'other': 'Comic Sans MS',
'size' : 8,
'size2': 6,
}
else:
faces = { 'times': 'Times',
'mono' : 'Courier',
'helv' : 'Helvetica',
'other': 'new century schoolbook',
'size' : 8,
'size2': 6,
}
#----------------------------------------------------------------------
class PythonSTC(stc.StyledTextCtrl):
fold_symbols = 3
Bernardo B. Marques
remove all trailling spaces
r4872
ville
initialization (no svn history)
r988 def __init__(self, parent, ID,
pos=wx.DefaultPosition, size=wx.DefaultSize,
style=0):
stc.StyledTextCtrl.__init__(self, parent, ID, pos, size, style)
#self.CmdKeyAssign(ord('B'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMIN)
#self.CmdKeyAssign(ord('N'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMOUT)
self.SetLexer(stc.STC_LEX_PYTHON)
self.SetKeyWords(0, " ".join(keyword.kwlist))
#self.SetProperty("fold", "1")
#self.SetProperty("tab.timmy.whinge.level", "1")
#self.SetMargins(0,0)
#self.SetViewWhiteSpace(False)
#self.SetBufferedDraw(False)
#self.SetViewEOL(True)
self.SetEOLMode(stc.STC_EOL_CRLF)
#self.SetUseAntiAliasing(True)
Bernardo B. Marques
remove all trailling spaces
r4872
ville
initialization (no svn history)
r988 self.SetEdgeMode(stc.STC_EDGE_LINE)
self.SetEdgeColumn(80)
self.SetEdgeColour(wx.LIGHT_GREY)
self.SetLayoutCache(stc.STC_CACHE_PAGE)
# Setup a margin to hold fold markers
Bernardo B. Marques
remove all trailling spaces
r4872 #self.SetFoldFlags(16)
laurent.dufrechou@gmail.com
some more little cleanup and a bug correction with prompt that comes with last commit
r1817 ### WHAT IS THIS VALUE? WHAT ARE THE OTHER FLAGS? DOES IT MATTER?
ville
initialization (no svn history)
r988 self.SetMarginType(2, stc.STC_MARGIN_SYMBOL)
self.SetMarginMask(2, stc.STC_MASK_FOLDERS)
self.SetMarginSensitive(2, True)
self.SetMarginWidth(2, 12)
if self.fold_symbols == 0:
Bernardo B. Marques
remove all trailling spaces
r4872 # Arrow pointing right for contracted folders,
laurent.dufrechou@gmail.com
some more little cleanup and a bug correction with prompt that comes with last commit
r1817 # arrow pointing down for expanded
self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, \
stc.STC_MARK_ARROWDOWN, "black", "black")
self.MarkerDefine(stc.STC_MARKNUM_FOLDER, \
stc.STC_MARK_ARROW, "black", "black")
self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, \
stc.STC_MARK_EMPTY, "black", "black")
self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, \
stc.STC_MARK_EMPTY, "black", "black")
self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, \
stc.STC_MARK_EMPTY, "white", "black")
self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, \
stc.STC_MARK_EMPTY, "white", "black")
self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, \
stc.STC_MARK_EMPTY, "white", "black")
Bernardo B. Marques
remove all trailling spaces
r4872
ville
initialization (no svn history)
r988 elif self.fold_symbols == 1:
# Plus for contracted folders, minus for expanded
laurent.dufrechou@gmail.com
some more little cleanup and a bug correction with prompt that comes with last commit
r1817 self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, \
stc.STC_MARK_MINUS, "white", "black")
self.MarkerDefine(stc.STC_MARKNUM_FOLDER, \
stc.STC_MARK_PLUS, "white", "black")
self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, \
stc.STC_MARK_EMPTY, "white", "black")
self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, \
stc.STC_MARK_EMPTY, "white", "black")
self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, \
stc.STC_MARK_EMPTY, "white", "black")
self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, \
stc.STC_MARK_EMPTY, "white", "black")
self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, \
stc.STC_MARK_EMPTY, "white", "black")
ville
initialization (no svn history)
r988
elif self.fold_symbols == 2:
# Like a flattened tree control using circular headers and curved joins
laurent.dufrechou@gmail.com
some more little cleanup and a bug correction with prompt that comes with last commit
r1817 self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, \
stc.STC_MARK_CIRCLEMINUS, "white", "#404040")
self.MarkerDefine(stc.STC_MARKNUM_FOLDER, \
stc.STC_MARK_CIRCLEPLUS, "white", "#404040")
self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, \
stc.STC_MARK_VLINE, "white", "#404040")
self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, \
stc.STC_MARK_LCORNERCURVE, "white", "#404040")
self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, \
stc.STC_MARK_CIRCLEPLUSCONNECTED, "white", "#404040")
self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, \
stc.STC_MARK_CIRCLEMINUSCONNECTED, "white", "#404040")
self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, \
stc.STC_MARK_TCORNERCURVE, "white", "#404040")
ville
initialization (no svn history)
r988
elif self.fold_symbols == 3:
# Like a flattened tree control using square headers
laurent.dufrechou@gmail.com
some more little cleanup and a bug correction with prompt that comes with last commit
r1817 self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, \
stc.STC_MARK_BOXMINUS, "white", "#808080")
self.MarkerDefine(stc.STC_MARKNUM_FOLDER, \
stc.STC_MARK_BOXPLUS, "white", "#808080")
self.MarkerDefine(stc.STC_MARKNUM_FOLDERSUB, \
stc.STC_MARK_VLINE, "white", "#808080")
self.MarkerDefine(stc.STC_MARKNUM_FOLDERTAIL, \
stc.STC_MARK_LCORNER, "white", "#808080")
self.MarkerDefine(stc.STC_MARKNUM_FOLDEREND, \
stc.STC_MARK_BOXPLUSCONNECTED, "white", "#808080")
self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPENMID, \
stc.STC_MARK_BOXMINUSCONNECTED, "white", "#808080")
self.MarkerDefine(stc.STC_MARKNUM_FOLDERMIDTAIL, \
stc.STC_MARK_TCORNER, "white", "#808080")
ville
initialization (no svn history)
r988
self.Bind(stc.EVT_STC_UPDATEUI, self.OnUpdateUI)
self.Bind(stc.EVT_STC_MARGINCLICK, self.OnMarginClick)
self.Bind(wx.EVT_KEY_DOWN, self.OnKeyPressed)
# Make some styles, The lexer defines what each style is used for, we
# just have to define what each style looks like. This set is adapted from
# Scintilla sample property files.
# Global default styles for all languages
self.StyleSetSpec(stc.STC_STYLE_DEFAULT, "face:%(helv)s,size:%(size)d" % faces)
self.StyleClearAll() # Reset all to be like the default
# Global default styles for all languages
self.StyleSetSpec(stc.STC_STYLE_DEFAULT, "face:%(helv)s,size:%(size)d" % faces)
self.StyleSetSpec(stc.STC_STYLE_LINENUMBER, "back:#C0C0C0,face:%(helv)s,size:%(size2)d" % faces)
self.StyleSetSpec(stc.STC_STYLE_CONTROLCHAR, "face:%(other)s" % faces)
self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT, "fore:#FFFFFF,back:#0000FF,bold")
self.StyleSetSpec(stc.STC_STYLE_BRACEBAD, "fore:#000000,back:#FF0000,bold")
# Python styles
Bernardo B. Marques
remove all trailling spaces
r4872 # Default
ville
initialization (no svn history)
r988 self.StyleSetSpec(stc.STC_P_DEFAULT, "fore:#000000,face:%(helv)s,size:%(size)d" % faces)
# Comments
self.StyleSetSpec(stc.STC_P_COMMENTLINE, "fore:#007F00,face:%(other)s,size:%(size)d" % faces)
# Number
self.StyleSetSpec(stc.STC_P_NUMBER, "fore:#007F7F,size:%(size)d" % faces)
# String
self.StyleSetSpec(stc.STC_P_STRING, "fore:#7F007F,face:%(helv)s,size:%(size)d" % faces)
# Single quoted string
self.StyleSetSpec(stc.STC_P_CHARACTER, "fore:#7F007F,face:%(helv)s,size:%(size)d" % faces)
# Keyword
self.StyleSetSpec(stc.STC_P_WORD, "fore:#00007F,bold,size:%(size)d" % faces)
# Triple quotes
self.StyleSetSpec(stc.STC_P_TRIPLE, "fore:#7F0000,size:%(size)d" % faces)
# Triple double quotes
self.StyleSetSpec(stc.STC_P_TRIPLEDOUBLE, "fore:#7F0000,size:%(size)d" % faces)
# Class name definition
self.StyleSetSpec(stc.STC_P_CLASSNAME, "fore:#0000FF,bold,underline,size:%(size)d" % faces)
# Function or method name definition
self.StyleSetSpec(stc.STC_P_DEFNAME, "fore:#007F7F,bold,size:%(size)d" % faces)
# Operators
self.StyleSetSpec(stc.STC_P_OPERATOR, "bold,size:%(size)d" % faces)
# Identifiers
self.StyleSetSpec(stc.STC_P_IDENTIFIER, "fore:#000000,face:%(helv)s,size:%(size)d" % faces)
# Comment-blocks
self.StyleSetSpec(stc.STC_P_COMMENTBLOCK, "fore:#7F7F7F,size:%(size)d" % faces)
# End of line where string is not closed
self.StyleSetSpec(stc.STC_P_STRINGEOL, "fore:#000000,face:%(mono)s,back:#E0C0E0,eol,size:%(size)d" % faces)
self.SetCaretForeground("BLUE")
# register some images for use in the AutoComplete box.
#self.RegisterImage(1, images.getSmilesBitmap())
Bernardo B. Marques
remove all trailling spaces
r4872 #self.RegisterImage(2,
ville
initialization (no svn history)
r988 # wx.ArtProvider.GetBitmap(wx.ART_NEW, size=(16,16)))
Bernardo B. Marques
remove all trailling spaces
r4872 #self.RegisterImage(3,
ville
initialization (no svn history)
r988 # wx.ArtProvider.GetBitmap(wx.ART_COPY, size=(16,16)))
def OnKeyPressed(self, event):
if self.CallTipActive():
self.CallTipCancel()
key = event.GetKeyCode()
if key == 32 and event.ControlDown():
pos = self.GetCurrentPos()
# Tips
if event.ShiftDown():
self.CallTipSetBackground("yellow")
self.CallTipShow(pos, 'lots of of text: blah, blah, blah\n\n'
'show some suff, maybe parameters..\n\n'
'fubar(param1, param2)')
# Code completion
else:
#lst = []
#for x in range(50000):
# lst.append('%05d' % x)
#st = " ".join(lst)
#print len(st)
#self.AutoCompShow(0, st)
kw = keyword.kwlist[:]
Bernardo B. Marques
remove all trailling spaces
r4872
ville
initialization (no svn history)
r988 kw.sort() # Python sorts are case sensitive
self.AutoCompSetIgnoreCase(False) # so this needs to match
# Images are specified with a appended "?type"
for i in range(len(kw)):
if kw[i] in keyword.kwlist:
kw[i] = kw[i]# + "?1"
self.AutoCompShow(0, " ".join(kw))
else:
event.Skip()
def OnUpdateUI(self, evt):
# check for matching braces
braceAtCaret = -1
braceOpposite = -1
charBefore = None
caretPos = self.GetCurrentPos()
if caretPos > 0:
charBefore = self.GetCharAt(caretPos - 1)
styleBefore = self.GetStyleAt(caretPos - 1)
# check before
if charBefore and chr(charBefore) in "[]{}()" and styleBefore == stc.STC_P_OPERATOR:
braceAtCaret = caretPos - 1
# check after
if braceAtCaret < 0:
charAfter = self.GetCharAt(caretPos)
styleAfter = self.GetStyleAt(caretPos)
Bernardo B. Marques
remove all trailling spaces
r4872
ville
initialization (no svn history)
r988 if charAfter and chr(charAfter) in "[]{}()" and styleAfter == stc.STC_P_OPERATOR:
braceAtCaret = caretPos
if braceAtCaret >= 0:
braceOpposite = self.BraceMatch(braceAtCaret)
if braceAtCaret != -1 and braceOpposite == -1:
self.BraceBadLight(braceAtCaret)
else:
self.BraceHighlight(braceAtCaret, braceOpposite)
#pt = self.PointFromPosition(braceOpposite)
#self.Refresh(True, wxRect(pt.x, pt.y, 5,5))
#print pt
#self.Refresh(False)
def OnMarginClick(self, evt):
# fold and unfold as needed
if evt.GetMargin() == 2:
if evt.GetShift() and evt.GetControl():
self.FoldAll()
else:
lineClicked = self.LineFromPosition(evt.GetPosition())
if self.GetFoldLevel(lineClicked) & stc.STC_FOLDLEVELHEADERFLAG:
if evt.GetShift():
self.SetFoldExpanded(lineClicked, True)
self.Expand(lineClicked, True, True, 1)
elif evt.GetControl():
if self.GetFoldExpanded(lineClicked):
self.SetFoldExpanded(lineClicked, False)
self.Expand(lineClicked, False, True, 0)
else:
self.SetFoldExpanded(lineClicked, True)
self.Expand(lineClicked, True, True, 100)
else:
self.ToggleFold(lineClicked)
def FoldAll(self):
lineCount = self.GetLineCount()
expanding = True
# find out if we are folding or unfolding
for lineNum in range(lineCount):
if self.GetFoldLevel(lineNum) & stc.STC_FOLDLEVELHEADERFLAG:
expanding = not self.GetFoldExpanded(lineNum)
break
lineNum = 0
while lineNum < lineCount:
level = self.GetFoldLevel(lineNum)
if level & stc.STC_FOLDLEVELHEADERFLAG and \
(level & stc.STC_FOLDLEVELNUMBERMASK) == stc.STC_FOLDLEVELBASE:
if expanding:
self.SetFoldExpanded(lineNum, True)
lineNum = self.Expand(lineNum, True)
lineNum = lineNum - 1
else:
lastChild = self.GetLastChild(lineNum, -1)
self.SetFoldExpanded(lineNum, False)
if lastChild > lineNum:
self.HideLines(lineNum+1, lastChild)
lineNum = lineNum + 1
def Expand(self, line, doExpand, force=False, visLevels=0, level=-1):
lastChild = self.GetLastChild(line, level)
line = line + 1
while line <= lastChild:
if force:
if visLevels > 0:
self.ShowLines(line, line)
else:
self.HideLines(line, line)
else:
if doExpand:
self.ShowLines(line, line)
if level == -1:
level = self.GetFoldLevel(line)
if level & stc.STC_FOLDLEVELHEADERFLAG:
if force:
if visLevels > 1:
self.SetFoldExpanded(line, True)
else:
self.SetFoldExpanded(line, False)
line = self.Expand(line, doExpand, force, visLevels-1)
else:
if doExpand and self.GetFoldExpanded(line):
line = self.Expand(line, True, force, visLevels-1)
else:
line = self.Expand(line, False, force, visLevels-1)
else:
line = line + 1
return line
#----------------------------------------------------------------------