@@ -58,23 +58,44 @@ const historyContainerId = "history-container"
5858var historyNode: Node
5959
6060# === history input track ===
61- type HistoryTrackPos = object
62- offset: Natural # # neg order
61+ import std/ options
62+ type
63+ Historyinfo = tuple [prompt, info: kstring]
64+ HistoryTrackPos = object
65+ offset: Natural # # neg order
66+ incomplete: Option [HistoryInfo ]
67+ useInComplete: bool
68+
69+ proc pushInCompleteHistory * (self: var HistoryTrackPos , ps, inp: kstring) =
70+ self.incomplete = some (ps, inp)
71+
72+ proc popInCompleteHistory * (self: var HistoryTrackPos ) =
73+ if self.incomplete.isSome:
74+ self.incomplete = none HistoryInfo
6375
6476proc reset * (self: var HistoryTrackPos ) = self.offset = 0
6577
6678proc stepToPastImpl (self: var HistoryTrackPos ) =
6779 let hi = stream.high
80+ if self.useInComplete:
81+ self.useInComplete = false
82+ return
6883 self.offset =
6984 if self.offset == hi: hi
7085 else : self.offset + 1
7186proc stepToNowImpl (self: var HistoryTrackPos ) =
7287 self.offset =
73- if self.offset == 0 : 0
88+ if self.offset == 0 :
89+ if self.incomplete.isSome:
90+ self.useInComplete = true
91+ 0
7492 else : self.offset - 1
7593
7694template getHistoryRecord (self: HistoryTrackPos ): untyped =
77- stream[stream.high - self.offset]
95+ if self.useInComplete:
96+ assert self.incomplete.isSome
97+ self.incomplete.unsafeGet ()
98+ else : stream[stream.high - self.offset]
7899
79100{.push noconv .}
80101proc createRange (doc: Document ): Range {.importcpp .}
@@ -83,6 +104,7 @@ proc collapse(rng: Range, b: bool) {.importcpp.}
83104proc addRange (s: Selection , rng: Range ){.importcpp .}
84105{.pop .}
85106
107+ import std/ jsconsole
86108proc setCursorPos (element: Node , position: int ) =
87109 # # .. note:: position is starting from 1, not 0
88110 # from JS code:
@@ -93,6 +115,9 @@ proc setCursorPos(element: Node, position: int) =
93115 let textNode = element.firstChild
94116
95117 # Set the position
118+ if textNode.isNil:
119+ # happend if last incomplete history input is empty
120+ return
96121 range .setStart (textNode, position)
97122 range .collapse (true )
98123
@@ -134,9 +159,9 @@ proc pushHistory(prompt: kstring, exp: string) =
134159 historyInputPos.reset
135160
136161 # auto scroll down when the inputing line is to go down the view
137- let last = historyNode.lastChild
138- if last .isNil: return
139- last .scrollIntoView (ScrollIntoViewOptions (
162+ let incomplete = historyNode.lastChild
163+ if incomplete .isNil: return
164+ incomplete .scrollIntoView (ScrollIntoViewOptions (
140165 `block`: " start" , inline: " start" , behavior: " instant" ))
141166
142167const isEditingClass = " isEditing"
@@ -177,13 +202,18 @@ proc createDom(): VNode =
177202 ,
178203 block :
179204 proc onKeydown (ev: Event , n: VNode ) =
205+ template getCurInput : kstring = n.dom.textContent
180206 case KeyboardEvent (ev).key # .keyCode is deprecated
181207 of " Enter" :
182- var input = $ n.dom.textContent
208+ historyInputPos.popInCompleteHistory ()
209+ let kInput = getCurInput ()
210+ let input = $ kInput
183211 pushHistory (prompt, input)
184212 interactivePython (input)
185213 n.dom.innerHTML = kstring " "
186214 of " ArrowUp" :
215+ let kInput = getCurInput ()
216+ historyInputPos.pushIncompleteHistory (prompt, kInput)
187217 historyInputPos.stepToPast n.dom
188218 of " ArrowDown" :
189219 historyInputPos.stepToNow n.dom
0 commit comments