made it work, more or less, with ruby 1.9
[nyuron.git] / modules / console.rb
blob4e17266e84e5bd72342eeca6211ea3be2b1aa6b8
1 module CLI end
2 module Console
3         extend Console
4         extend CLI
6         VALID_CONSOLE_MODES = [:console, :search, :searchback]
7         SEARCH_MODES = [:search, :searchback]
8         PROMPT = {:console => ':', :search => '/', :searchback => '?'}
10         def last_search_mode
11                 @@last_search_mode
12         end
13         def get_history
14                 @@history
15         end
17         def self.initialize()
18                 @@tabfreeze = false
19                 @@tabindex = 0
20                 @@historyfreeze = false
21                 @@history = {}
22                 for mode in VALID_CONSOLE_MODES
23                         @@history[mode] = []
24                 end
25                 @@historywords = nil
26                 @@historyindex = 0
28                 @@mode = nil
29                 @@next = nil
30                 @@str = ''
31                 @@info = ''
32                 @@infotime = Time.at(0)
33                 @@pos = 0
34                 @@last_search_mode = nil
35         end
37         ## API {{{
39         def validate_pos(wrapping = false)
40                 if @@str.size == 0
41                         @@pos = 0
42                 elsif @@pos < 0
43                         if wrapping
44                                 @@pos += @@str.size + 1
45                                 @@pos = 0 if @@pos < 0
46                         else
47                                 @@pos = 0
48                         end
49                 elsif @@pos >= @@str.size
50                         @@pos = @@str.size - 1
51                 end
52         end
54         def len() @@str.size + 1 end
55         
56         def arrange_cursor()
57                 movi(UI.console_line, @@pos + 1)
58         end
60    def move_relative(n=0)
61                 @@tabfreeze = false
62                 @@historyfreeze = false
64                 newpos = @@pos + n
65                 return unless newpos.between? 0, @@str.size
66       @@pos = newpos
67                 arrange_cursor
68    end
70    def move_absolute(n=0)
71                 @@tabfreeze = false
72                 @@historyfreeze = false
74                 @@pos = n
75                 validate_pos(true)
76                 arrange_cursor
77    end
79         def puts(pos, str)
80                 puti(UI.console_line, pos, str)
81         end
83         def insert(str, at=nil)
84                 @@tabfreeze = false
85                 @@historyfreeze = false
87                 at ||= @@pos
88                 @@str.insert(at, str)
89                 @@pos += str.size
90                 arrange_cursor
91         end
93         def delete(mod = 0)
94                 @@tabfreeze = false
95                 @@historyfreeze = false
97                 at = @@pos + mod
98                 @@str.slice!(at, 1)
99                 @@pos += mod
100                 arrange_cursor
101 #               if at < 0 or at >= @str.size
102 #                       return
103 #               elsif at == @str.size - 1
104 #                       put @str.size, ' '
105 #                       @str.chop!
106 #               elsif at == 0
107 #                       @str = @str[1..-1]
108 #               else
109 #                       @str = @str[0...at] + @str[at+1..-1]
110 #               end
111 #               @pos = at
112         end
114         def empty?()
115                 @@str.empty?
116         end
118         ##--------}}}
120         def handle_key(c)
121                 case c
122                 when '<cr>'
123                         close
124                         cursor false
125                         clear
126                         history_add(@@str)
127                         case @@mode
128                         when :console
129                                 Command.run(@@str)
130                         when :search
131                                 API.scan(@@str, 1)
132                         when :searchback
133                                 API.scan(@@str, -1)
134                         end
135                 when '<redraw>'; Info.request_redraw = true
136                 when '<esc>'; close
137                 when '<up>'; history :backward
138                 when '<down>'; history :forward
139                 when '<right>'; move_relative +1
140                 when '<left>';  move_relative -1
141                 when '<del>'; delete
142                 when '<tab>'; tabcomplete :forward
143                 when '<s-tab>'; tabcomplete :backward
144                 when '<end>'; move_absolute -1
145                 when '<home>'; move_absolute 0
146                 when '<c-u>'; 
147                         @@str = ''
148                         @@pos = 0
149                         arrange_cursor
150                 when '<bs>'
151                         close if empty?
152                         delete(-1)
153                 when ' '..'~'; insert(c)
154                 end
155         end
157         ## valid modes: :console, :search, :searchback
158         def main_loop(mode=:console)
159                 @@mode = mode
160                 draw
161                 API.busy false
162                 arrange_cursor
163                 key = geti
164                 API.busy true
165                 handle_key(key)
166         end
168         def open(str = '', mode=:console, pos = -1)
169                 Info.where = mode
170                 @@str = str
171                 @@pos = pos
172                 if SEARCH_MODES.include? mode
173                         @@last_search_mode = mode
174                 end
175                 validate_pos(true)
176         end
178         def raise(arg=nil)
179                 arg ||= $!
180                 case arg
181                 when Exception
182                         write "#{arg.class}: #{arg.message}"
183                 when String
184                         write "Error: #{arg}"
185                 else
186                         write "Unknown or unspecified error!"
187                 end
188                 logerr @@info
189                 for bt in Exception === arg ? arg.backtrace : caller(1)
190                         logerr bt
191                 end
192                 @error = true
193         end
194         alias error raise
196         def write(string)
197                 @@info = string
198                 @@infotime = Time.now
199         end
201         def close()
202                 Info.where = :main
203         end
205         def time_left
206                 t = Query.get_time_left
207                 return unless t
208                 Convert.relative_time_to_string(t)
209         end
211         def clear
212                 attr_set(*Color.console.base)
213                 clear_content if !@info and Time.now - @@infotime > 10
214                 if @@info.empty?
215                         txt = "#{Opt.filter}   "
216                         txt << "brain[#{Query.db_size}] viewing[#{UI.list.size}]  "
217                         txt << "left[#{time_left}]"
218                         filter = " #{$now.strftime("%A %b %d#{$now.day.suffix}, %H:%M")} "
219                         txt = txt.ljust(cols-filter.size)[0..cols]
220                         txt << filter
221                         puts 0, txt.ljust(cols-1)[0..cols-1]
223                         attr_at(cols-filter.size+1, UI.console_line, -1, *Color.console.date)
224                         attr_at(0, UI.console_line, Opt.filter.size, *Color.console.tags)
225 #                       Ncurses.refresh
226 #                       sleep 1
227 #                       color_bold_at(UI.console_line, 0, Opt.filter.size, -1, -1)
228                 else
229                         if @error
230                                 attr_set(*Color.console.error)
231                         else
232                                 attr_set(*Color.console.info)
233                         end
234                         txt = @@info
235                         puts 0, txt.ljust(cols-1)[0..cols-1]
236                 end
237                 attr_set(*Color.console.base)
238         end
240         def clear_content
241                 @@info.clear!
242                 @error = false
243         end
245         def draw
246                 attr_set(*Color.console.base)
247                 rest = cols - @@str.size - 2
248                 
249                 str = (PROMPT[@@mode] + @@str + ' ' * rest)
250                 if str.size > cols - 1
251                         str = str[str.size-cols+1 .. -1]
252                 end
253                 puts 0, str
254                 arrange_cursor
255         end
257         def tabcomplete(direction = :forward)
258                 if @@tabfreeze
259                         if direction == :forward
260                                 @@tabindex += 1
261                                 test = @@tabwords[@@tabindex]
262                                 if not test
263                                         @@tabindex = 0
264                                 end
265                         elsif direction == :backward
266                                 @@tabindex -= 1
267                                 if @@tabindex < 0
268                                         @@tabindex = @@tabwords.size - 1
269 #                                       if @@tabwords.respond_to?(:size)
270 #                                               @@tabindex = @@tabwords.size - 1
271 #                                       else
272 #                                               size = 0
273 #                                               for item in @@tabwords
274 #                                                       size += 1
275 #                                                       break if size > 30
276 #                                               end
277 #                                               @@tabindex = size - 1
278 #                                       end
279                                 end
280                         else
281                                 return
282                         end
284                         test = @@tabwords[@@tabindex]
285                         if test
286                                 @@str[@@tabfreeze...@@tabend] = test
287                                 @@pos = @@tabfreeze + test.size
288                                 @@tabend = @@pos
289                         end
290                         
291                 else
292                         string = @@str[0...@@pos]
293                         words = string.split(' ')
294                         words << '' if @@str[@@pos-1] == ?\s
295                         if words.size == 1
296                                 @@tabwords = Completer.new(words.first, Cache.cmd.__table__.keys)
297                         else
298                                 @@tabwords = Command.tabcomp(string, @@pos, words.size - 1)
299                         end
300                         @@tabwordsize = (words.last.size rescue 0)
301                         @@tabfreeze = @@pos - @@tabwordsize
302                         @@tabend = @@pos
303                         @@tabindex = 0
304                         tabcomplete
305                 end
306         end
308         def history_add(str)
309                 unless @@str.empty? or @@history[@@mode].last == @@str
310                         @@history[@@mode].unshift @@str
311                         @@history[@@mode].pop if @@history[@@mode].size > (Opt.history_size || 30)
312                 end
313                 @@historyfreeze = false
314         end
316         def history(dir)
317                 unless @@historyfreeze
318                         @@historyfreeze = true
319                         @@historywords = Completer.new(@@str, @@history[@@mode])
320                         @@historyindex = 0
321                 end
323                 if dir == :backward
324                         @@historyindex += 1 unless @@historyindex >= @@historywords.size - 1
325                 elsif dir == :forward
326                         @@historyindex -= 1 unless @@historyindex <= 0
327                 else
328                         return
329                 end
331                 test = @@historywords[@@historyindex]
332                 if test
333                         @@str = test.dup
334                         @@pos = @@str.size
335                 end
336         end