annotate CSP2/CSP2_env/env-d9b9114564458d9d-741b3de822f2aaca6c6caa4325c4afce/lib/python3.8/idlelib/history.py @ 68:5028fdace37b

planemo upload commit 2e9511a184a1ca667c7be0c6321a36dc4e3d116d
author jpayne
date Tue, 18 Mar 2025 16:23:26 -0400
parents
children
rev   line source
jpayne@68 1 "Implement Idle Shell history mechanism with History class"
jpayne@68 2
jpayne@68 3 from idlelib.config import idleConf
jpayne@68 4
jpayne@68 5
jpayne@68 6 class History:
jpayne@68 7 ''' Implement Idle Shell history mechanism.
jpayne@68 8
jpayne@68 9 store - Store source statement (called from pyshell.resetoutput).
jpayne@68 10 fetch - Fetch stored statement matching prefix already entered.
jpayne@68 11 history_next - Bound to <<history-next>> event (default Alt-N).
jpayne@68 12 history_prev - Bound to <<history-prev>> event (default Alt-P).
jpayne@68 13 '''
jpayne@68 14 def __init__(self, text):
jpayne@68 15 '''Initialize data attributes and bind event methods.
jpayne@68 16
jpayne@68 17 .text - Idle wrapper of tk Text widget, with .bell().
jpayne@68 18 .history - source statements, possibly with multiple lines.
jpayne@68 19 .prefix - source already entered at prompt; filters history list.
jpayne@68 20 .pointer - index into history.
jpayne@68 21 .cyclic - wrap around history list (or not).
jpayne@68 22 '''
jpayne@68 23 self.text = text
jpayne@68 24 self.history = []
jpayne@68 25 self.prefix = None
jpayne@68 26 self.pointer = None
jpayne@68 27 self.cyclic = idleConf.GetOption("main", "History", "cyclic", 1, "bool")
jpayne@68 28 text.bind("<<history-previous>>", self.history_prev)
jpayne@68 29 text.bind("<<history-next>>", self.history_next)
jpayne@68 30
jpayne@68 31 def history_next(self, event):
jpayne@68 32 "Fetch later statement; start with ealiest if cyclic."
jpayne@68 33 self.fetch(reverse=False)
jpayne@68 34 return "break"
jpayne@68 35
jpayne@68 36 def history_prev(self, event):
jpayne@68 37 "Fetch earlier statement; start with most recent."
jpayne@68 38 self.fetch(reverse=True)
jpayne@68 39 return "break"
jpayne@68 40
jpayne@68 41 def fetch(self, reverse):
jpayne@68 42 '''Fetch statement and replace current line in text widget.
jpayne@68 43
jpayne@68 44 Set prefix and pointer as needed for successive fetches.
jpayne@68 45 Reset them to None, None when returning to the start line.
jpayne@68 46 Sound bell when return to start line or cannot leave a line
jpayne@68 47 because cyclic is False.
jpayne@68 48 '''
jpayne@68 49 nhist = len(self.history)
jpayne@68 50 pointer = self.pointer
jpayne@68 51 prefix = self.prefix
jpayne@68 52 if pointer is not None and prefix is not None:
jpayne@68 53 if self.text.compare("insert", "!=", "end-1c") or \
jpayne@68 54 self.text.get("iomark", "end-1c") != self.history[pointer]:
jpayne@68 55 pointer = prefix = None
jpayne@68 56 self.text.mark_set("insert", "end-1c") # != after cursor move
jpayne@68 57 if pointer is None or prefix is None:
jpayne@68 58 prefix = self.text.get("iomark", "end-1c")
jpayne@68 59 if reverse:
jpayne@68 60 pointer = nhist # will be decremented
jpayne@68 61 else:
jpayne@68 62 if self.cyclic:
jpayne@68 63 pointer = -1 # will be incremented
jpayne@68 64 else: # abort history_next
jpayne@68 65 self.text.bell()
jpayne@68 66 return
jpayne@68 67 nprefix = len(prefix)
jpayne@68 68 while 1:
jpayne@68 69 pointer += -1 if reverse else 1
jpayne@68 70 if pointer < 0 or pointer >= nhist:
jpayne@68 71 self.text.bell()
jpayne@68 72 if not self.cyclic and pointer < 0: # abort history_prev
jpayne@68 73 return
jpayne@68 74 else:
jpayne@68 75 if self.text.get("iomark", "end-1c") != prefix:
jpayne@68 76 self.text.delete("iomark", "end-1c")
jpayne@68 77 self.text.insert("iomark", prefix)
jpayne@68 78 pointer = prefix = None
jpayne@68 79 break
jpayne@68 80 item = self.history[pointer]
jpayne@68 81 if item[:nprefix] == prefix and len(item) > nprefix:
jpayne@68 82 self.text.delete("iomark", "end-1c")
jpayne@68 83 self.text.insert("iomark", item)
jpayne@68 84 break
jpayne@68 85 self.text.see("insert")
jpayne@68 86 self.text.tag_remove("sel", "1.0", "end")
jpayne@68 87 self.pointer = pointer
jpayne@68 88 self.prefix = prefix
jpayne@68 89
jpayne@68 90 def store(self, source):
jpayne@68 91 "Store Shell input statement into history list."
jpayne@68 92 source = source.strip()
jpayne@68 93 if len(source) > 2:
jpayne@68 94 # avoid duplicates
jpayne@68 95 try:
jpayne@68 96 self.history.remove(source)
jpayne@68 97 except ValueError:
jpayne@68 98 pass
jpayne@68 99 self.history.append(source)
jpayne@68 100 self.pointer = None
jpayne@68 101 self.prefix = None
jpayne@68 102
jpayne@68 103
jpayne@68 104 if __name__ == "__main__":
jpayne@68 105 from unittest import main
jpayne@68 106 main('idlelib.idle_test.test_history', verbosity=2, exit=False)