@@ -24,10 +24,12 @@ def initialize
24
24
#
25
25
# @param [String,nil] history_file The file to load and persist commands to
26
26
# @param [String] name Human readable history context name
27
+ # @param [Symbol] input_library The input library to provide context for. :reline, :readline
27
28
# @param [Proc] block
28
29
# @return [nil]
29
- def with_context ( history_file : nil , name : nil , &block )
30
- push_context ( history_file : history_file , name : name )
30
+ def with_context ( history_file : nil , name : nil , input_library : nil , &block )
31
+ input_library ||= :readline # Default to Readline for backwards compatibility.
32
+ push_context ( history_file : history_file , name : name , input_library : input_library )
31
33
32
34
begin
33
35
block . call
@@ -65,9 +67,9 @@ def debug?
65
67
@debug
66
68
end
67
69
68
- def push_context ( history_file : nil , name : nil )
70
+ def push_context ( history_file : nil , name : nil , input_library : nil )
69
71
$stderr. puts ( "Push context before\n #{ JSON . pretty_generate ( _contexts ) } " ) if debug?
70
- new_context = { history_file : history_file , name : name }
72
+ new_context = { history_file : history_file , name : name , input_library : input_library }
71
73
72
74
switch_context ( new_context , @contexts . last )
73
75
@contexts . push ( new_context )
@@ -91,47 +93,91 @@ def readline_available?
91
93
defined? ( ::Readline )
92
94
end
93
95
96
+ def reline_available?
97
+ begin
98
+ require 'reline'
99
+ defined? ( ::Reline )
100
+ rescue ::LoadError => _e
101
+ false
102
+ end
103
+ end
104
+
94
105
def clear_readline
95
106
return unless readline_available?
96
107
97
108
::Readline ::HISTORY . length . times { ::Readline ::HISTORY . pop }
98
109
end
99
110
100
- def load_history_file ( history_file )
101
- return unless readline_available ?
111
+ def clear_reline
112
+ return unless reline_available ?
102
113
103
- clear_readline
104
- if File . exist? ( history_file )
105
- File . readlines ( history_file ) . each do |e |
106
- ::Readline ::HISTORY << e . chomp
114
+ ::Reline ::HISTORY . length . times { ::Reline ::HISTORY . pop }
115
+ end
116
+
117
+ def load_history_file ( context )
118
+ history_file = context [ :history_file ]
119
+ case context [ :input_library ]
120
+ when :readline
121
+ return unless readline_available?
122
+
123
+ clear_readline
124
+ if File . exist? ( history_file )
125
+ File . readlines ( history_file ) . each do |e |
126
+ ::Readline ::HISTORY << safe_undump ( e . chomp )
127
+ end
128
+ end
129
+ when :reline
130
+ return unless reline_available?
131
+
132
+ clear_reline
133
+ if File . exist? ( history_file )
134
+ File . readlines ( history_file ) . each do |e |
135
+ ::Reline ::HISTORY << safe_undump ( e . chomp )
136
+ end
107
137
end
108
138
end
109
139
end
110
140
111
- def store_history_file ( history_file )
112
- return unless readline_available?
141
+ def store_history_file ( context )
113
142
cmds = [ ]
114
- history_diff = ::Readline ::HISTORY . length < MAX_HISTORY ? ::Readline ::HISTORY . length : MAX_HISTORY
115
- history_diff . times do
116
- entry = ::Readline ::HISTORY . pop
117
- cmds . push ( entry ) unless entry . nil?
143
+ history_file = context [ :history_file ]
144
+
145
+ case context [ :input_library ]
146
+ when :readline
147
+ return unless readline_available?
148
+
149
+ history_diff = ::Readline ::HISTORY . length < MAX_HISTORY ? ::Readline ::HISTORY . length : MAX_HISTORY
150
+ history_diff . times do
151
+ entry = ::Readline ::HISTORY . pop . dump
152
+ cmds . push ( entry ) unless entry . nil?
153
+ end
154
+ when :reline
155
+ return unless reline_available?
156
+
157
+ history_diff = ::Reline ::HISTORY . length < MAX_HISTORY ? ::Reline ::HISTORY . length : MAX_HISTORY
158
+ history_diff . times do
159
+ entry = ::Reline ::HISTORY . pop . dump
160
+ cmds . push ( entry ) unless entry . nil?
161
+ end
118
162
end
119
163
120
164
write_history_file ( history_file , cmds )
121
165
end
122
166
123
167
def switch_context ( new_context , old_context = nil )
124
168
if old_context && old_context [ :history_file ]
125
- store_history_file ( old_context [ :history_file ] )
169
+ store_history_file ( old_context )
126
170
end
127
171
128
172
if new_context && new_context [ :history_file ]
129
- load_history_file ( new_context [ :history_file ] )
173
+ load_history_file ( new_context )
130
174
else
131
175
clear_readline
176
+ clear_reline
132
177
end
133
- rescue SignalException => e
178
+ rescue SignalException => _e
134
179
clear_readline
180
+ clear_reline
135
181
end
136
182
137
183
def write_history_file ( history_file , cmds )
@@ -159,6 +205,16 @@ def write_history_file(history_file, cmds)
159
205
@write_queue << event
160
206
@remaining_work << event
161
207
end
208
+
209
+ # @param [String] dumped A string that has been previously dumped
210
+ # @return [String] A string that is undumped if possible or the input if it can't be undumped.
211
+ def safe_undump ( dumped )
212
+ begin
213
+ dumped . undump
214
+ rescue ::RuntimeError => _e
215
+ dumped
216
+ end
217
+ end
162
218
end
163
219
164
220
end
0 commit comments