tpp 1.3.1

Sign up to get free protection for your applications and to get access to all the features.
data/bin/tpp ADDED
@@ -0,0 +1,1764 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ version_number = "1.3.1"
4
+
5
+ # Loads the ncurses-ruby module and imports "Ncurses" into the
6
+ # current namespace. It stops the program if loading the
7
+ # ncurses-ruby module fails.
8
+ def load_ncurses
9
+ begin
10
+ require "rubygems"
11
+ require "ncurses"
12
+ include Ncurses
13
+ rescue LoadError
14
+ $stderr.print <<EOF
15
+ There is no Ncurses-Ruby package installed which is needed by TPP.
16
+ You can download it on: http://ncurses-ruby.berlios.de/
17
+ EOF
18
+ Kernel.exit(1)
19
+ end
20
+ end
21
+
22
+ # Maps color names to constants and indexes.
23
+ class ColorMap
24
+
25
+ # Maps color name _color_ to a constant
26
+ def ColorMap.get_color(color)
27
+ colors = { "white" => COLOR_WHITE,
28
+ "yellow" => COLOR_YELLOW,
29
+ "red" => COLOR_RED,
30
+ "green" => COLOR_GREEN,
31
+ "blue" => COLOR_BLUE,
32
+ "cyan" => COLOR_CYAN,
33
+ "magenta" => COLOR_MAGENTA,
34
+ "black" => COLOR_BLACK,
35
+ "default" => -1 }
36
+ colors[color]
37
+ end
38
+
39
+ # Maps color name to a color pair index
40
+ def ColorMap.get_color_pair(color)
41
+ colors = { "white" => 1,
42
+ "yellow" => 2,
43
+ "red" => 3,
44
+ "green" => 4,
45
+ "blue" => 5,
46
+ "cyan" => 6,
47
+ "magenta" => 7,
48
+ "black" => 8,
49
+ "default" =>-1}
50
+ colors[color]
51
+ end
52
+
53
+ end
54
+
55
+ # Opens a TPP source file, and splits it into the different pages.
56
+ class FileParser
57
+
58
+ def initialize(filename)
59
+ @filename = filename
60
+ @pages = []
61
+ end
62
+
63
+ # Parses the specified file and returns an array of Page objects
64
+ def get_pages
65
+ begin
66
+ f = File.open(@filename)
67
+ rescue
68
+ $stderr.puts "Error: couldn't open file: #{$!}"
69
+ Kernel.exit(1)
70
+ end
71
+
72
+ number_pages = 0
73
+
74
+ cur_page = Page.new("slide " + (number_pages + 1).to_s)
75
+
76
+ f.each_line do |line|
77
+ line.chomp!
78
+ case line
79
+ when /^--##/ # ignore comments
80
+ when /^--newpage/
81
+ @pages << cur_page
82
+ number_pages += 1
83
+ name = line.sub(/^--newpage/,"")
84
+ if name == "" then
85
+ name = "slide " + (number_pages+1).to_s
86
+ else
87
+ name.strip!
88
+ end
89
+ cur_page = Page.new(name)
90
+ else
91
+ cur_page.add_line(line)
92
+ end # case
93
+ end # each
94
+ @pages << cur_page
95
+ end
96
+ end # class FileParser
97
+
98
+
99
+ # Represents a page (aka `slide') in TPP. A page consists of a title and one or
100
+ # more lines.
101
+ class Page
102
+
103
+ def initialize(title)
104
+ @lines = []
105
+ @title = title
106
+ @cur_line = 0
107
+ @eop = false
108
+ end
109
+
110
+ # Appends a line to the page, but only if _line_ is not null
111
+ def add_line(line)
112
+ @lines << line if line
113
+ end
114
+
115
+ # Returns the next line. In case the last line is hit, then the end-of-page marker is set.
116
+ def next_line
117
+ line = @lines[@cur_line]
118
+ @cur_line += 1
119
+ if @cur_line >= @lines.size then
120
+ @eop = true
121
+ end
122
+ return line
123
+ end
124
+
125
+ # Returns whether end-of-page has been reached.
126
+ def eop?
127
+ @eop
128
+ end
129
+
130
+ # Resets the end-of-page marker and sets the current line marker to the first line
131
+ def reset_eop
132
+ @cur_line = 0
133
+ @eop = false
134
+ end
135
+
136
+ # Returns all lines in the page.
137
+ def lines
138
+ @lines
139
+ end
140
+
141
+ # Returns the page's title
142
+ def title
143
+ @title
144
+ end
145
+ end
146
+
147
+
148
+
149
+ # Implements a generic visualizer from which all other visualizers need to be
150
+ # derived. If Ruby supported abstract methods, all the do_* methods would be
151
+ # abstract.
152
+ class TppVisualizer
153
+
154
+ def initialize
155
+ # nothing
156
+ end
157
+
158
+ # Splits a line into several lines, where each of the result lines is at most
159
+ # _width_ characters long, caring about word boundaries, and returns an array
160
+ # of strings.
161
+ def split_lines(text,width)
162
+ lines = []
163
+ if text then
164
+ begin
165
+ i = width
166
+ if text.length <= i then # text length is OK -> add it to array and stop splitting
167
+ lines << text
168
+ text = ""
169
+ else
170
+ # search for word boundary (space actually)
171
+ while i > 0 and text[i] != ' '[0] do
172
+ i -= 1
173
+ end
174
+ # if we can't find any space character, simply cut it off at the maximum width
175
+ if i == 0 then
176
+ i = width
177
+ end
178
+ # extract line
179
+ x = text[0..i-1]
180
+ # remove extracted line
181
+ text = text[i+1..-1]
182
+ # added line to array
183
+ lines << x
184
+ end
185
+ end while text.length > 0
186
+ end
187
+ return lines
188
+ end
189
+
190
+ def do_footer(footer_text)
191
+ $stderr.puts "Error: TppVisualizer#do_footer has been called directly."
192
+ Kernel.exit(1)
193
+ end
194
+
195
+ def do_header(header_text)
196
+ $stderr.puts "Error: TppVisualizer#do_header has been called directly."
197
+ Kernel.exit(1)
198
+ end
199
+
200
+
201
+ def do_refresh
202
+ $stderr.puts "Error: TppVisualizer#do_refresh has been called directly."
203
+ Kernel.exit(1)
204
+ end
205
+
206
+ def new_page
207
+ $stderr.puts "Error: TppVisualizer#new_page has been called directly."
208
+ Kernel.exit(1)
209
+ end
210
+
211
+ def do_heading(text)
212
+ $stderr.puts "Error: TppVisualizer#do_heading has been called directly."
213
+ Kernel.exit(1)
214
+ end
215
+
216
+ def do_withborder
217
+ $stderr.puts "Error: TppVisualizer#do_withborder has been called directly."
218
+ Kernel.exit(1)
219
+ end
220
+
221
+ def do_horline
222
+ $stderr.puts "Error: TppVisualizer#do_horline has been called directly."
223
+ Kernel.exit(1)
224
+ end
225
+
226
+ def do_color(text)
227
+ $stderr.puts "Error: TppVisualizer#do_color has been called directly."
228
+ Kernel.exit(1)
229
+ end
230
+
231
+ def do_center(text)
232
+ $stderr.puts "Error: TppVisualizer#do_center has been called directly."
233
+ Kernel.exit(1)
234
+ end
235
+
236
+ def do_right(text)
237
+ $stderr.puts "Error: TppVisualizer#do_right has been called directly."
238
+ Kernel.exit(1)
239
+ end
240
+
241
+ def do_exec(cmdline)
242
+ $stderr.puts "Error: TppVisualizer#do_exec has been called directly."
243
+ Kernel.exit(1)
244
+ end
245
+
246
+ def do_wait
247
+ $stderr.puts "Error: TppVisualizer#do_wait has been called directly."
248
+ Kernel.exit(1)
249
+ end
250
+
251
+ def do_beginoutput
252
+ $stderr.puts "Error: TppVisualizer#do_beginoutput has been called directly."
253
+ Kernel.exit(1)
254
+ end
255
+
256
+ def do_beginshelloutput
257
+ $stderr.puts "Error: TppVisualizer#do_beginshelloutput has been called directly."
258
+ Kernel.exit(1)
259
+ end
260
+
261
+ def do_endoutput
262
+ $stderr.puts "Error: TppVisualizer#do_endoutput has been called directly."
263
+ Kernel.exit(1)
264
+ end
265
+
266
+ def do_endshelloutput
267
+ $stderr.puts "Error: TppVisualizer#do_endshelloutput has been called directly."
268
+ Kernel.exit(1)
269
+ end
270
+
271
+ def do_sleep(time2sleep)
272
+ $stderr.puts "Error: TppVisualizer#do_sleep has been called directly."
273
+ Kernel.exit(1)
274
+ end
275
+
276
+ def do_boldon
277
+ $stderr.puts "Error: TppVisualizer#do_boldon has been called directly."
278
+ Kernel.exit(1)
279
+ end
280
+
281
+ def do_boldoff
282
+ $stderr.puts "Error: TppVisualizer#do_boldoff has been called directly."
283
+ Kernel.exit(1)
284
+ end
285
+
286
+ def do_revon
287
+ $stderr.puts "Error: TppVisualizer#do_revon has been called directly."
288
+ Kernel.exit(1)
289
+ end
290
+
291
+ def do_revoff
292
+ $stderr.puts "Error: TppVisualizer#do_revoff has been called directly."
293
+ Kernel.exit(1)
294
+ end
295
+
296
+ def do_ulon
297
+ $stderr.puts "Error: TppVisualizer#do_ulon has been called directly."
298
+ Kernel.exit(1)
299
+ end
300
+
301
+ def do_uloff
302
+ $stderr.puts "Error: TppVisualizer#do_uloff has been called directly."
303
+ Kernel.exit(1)
304
+ end
305
+
306
+ def do_beginslideleft
307
+ $stderr.puts "Error: TppVisualizer#do_beginslideleft has been called directly."
308
+ Kernel.exit(1)
309
+ end
310
+
311
+ def do_endslide
312
+ $stderr.puts "Error: TppVisualizer#do_endslide has been called directly."
313
+ Kernel.exit(1)
314
+ end
315
+
316
+ def do_command_prompt
317
+ $stderr.puts "Error: TppVisualizer#do_command_prompt has been called directly."
318
+ Kernel.exit(1)
319
+ end
320
+
321
+ def do_beginslideright
322
+ $stderr.puts "Error: TppVisualizer#do_beginslideright has been called directly."
323
+ Kernel.exit(1)
324
+ end
325
+
326
+ def do_beginslidetop
327
+ $stderr.puts "Error: TppVisualizer#do_beginslidetop has been called directly."
328
+ Kernel.exit(1)
329
+ end
330
+
331
+ def do_beginslidebottom
332
+ $stderr.puts "Error: TppVisualizer#do_beginslidebottom has been called directly."
333
+ Kernel.exit(1)
334
+ end
335
+
336
+ def do_sethugefont
337
+ $stderr.puts "Error: TppVisualizer#do_sethugefont has been called directly."
338
+ Kernel.exit(1)
339
+ end
340
+
341
+ def do_huge(text)
342
+ $stderr.puts "Error: TppVisualizer#do_huge has been called directly."
343
+ Kernel.exit(1)
344
+ end
345
+
346
+ def print_line(line)
347
+ $stderr.puts "Error: TppVisualizer#print_line has been called directly."
348
+ Kernel.exit(1)
349
+ end
350
+
351
+ def do_title(title)
352
+ $stderr.puts "Error: TppVisualizer#do_title has been called directly."
353
+ Kernel.exit(1)
354
+ end
355
+
356
+ def do_author(author)
357
+ $stderr.puts "Error: TppVisualizer#do_author has been called directly."
358
+ Kernel.exit(1)
359
+ end
360
+
361
+ def do_date(date)
362
+ $stderr.puts "Error: TppVisualizer#do_date has been called directly."
363
+ Kernel.exit(1)
364
+ end
365
+
366
+ def do_bgcolor(color)
367
+ $stderr.puts "Error: TppVisualizer#do_bgcolor has been called directly."
368
+ Kernel.exit(1)
369
+ end
370
+
371
+ def do_fgcolor(color)
372
+ $stderr.puts "Error: TppVisualizer#do_fgcolor has been called directly."
373
+ Kernel.exit(1)
374
+ end
375
+
376
+ def do_color(color)
377
+ $stderr.puts "Error: TppVisualizer#do_color has been called directly."
378
+ Kernel.exit(1)
379
+ end
380
+
381
+ # Receives a _line_, parses it if necessary, and dispatches it
382
+ # to the correct method which then does the correct processing.
383
+ # It returns whether the controller shall wait for input.
384
+ def visualize(line,eop)
385
+ case line
386
+ when /^--heading /
387
+ text = line.sub(/^--heading /,"")
388
+ do_heading(text)
389
+ when /^--withborder/
390
+ do_withborder
391
+ when /^--horline/
392
+ do_horline
393
+ when /^--color /
394
+ text = line.sub(/^--color /,"")
395
+ text.strip!
396
+ do_color(text)
397
+ when /^--center /
398
+ text = line.sub(/^--center /,"")
399
+ do_center(text)
400
+ when /^--right /
401
+ text = line.sub(/^--right /,"")
402
+ do_right(text)
403
+ when /^--exec /
404
+ cmdline = line.sub(/^--exec /,"")
405
+ do_exec(cmdline)
406
+ when /^---/
407
+ do_wait
408
+ return true
409
+ when /^--beginoutput/
410
+ do_beginoutput
411
+ when /^--beginshelloutput/
412
+ do_beginshelloutput
413
+ when /^--endoutput/
414
+ do_endoutput
415
+ when /^--endshelloutput/
416
+ do_endshelloutput
417
+ when /^--sleep /
418
+ time2sleep = line.sub(/^--sleep /,"")
419
+ do_sleep(time2sleep)
420
+ when /^--boldon/
421
+ do_boldon
422
+ when /^--boldoff/
423
+ do_boldoff
424
+ when /^--revon/
425
+ do_revon
426
+ when /^--revoff/
427
+ do_revoff
428
+ when /^--ulon/
429
+ do_ulon
430
+ when /^--uloff/
431
+ do_uloff
432
+ when /^--beginslideleft/
433
+ do_beginslideleft
434
+ when /^--endslideleft/, /^--endslideright/, /^--endslidetop/, /^--endslidebottom/
435
+ do_endslide
436
+ when /^--beginslideright/
437
+ do_beginslideright
438
+ when /^--beginslidetop/
439
+ do_beginslidetop
440
+ when /^--beginslidebottom/
441
+ do_beginslidebottom
442
+ when /^--sethugefont /
443
+ params = line.sub(/^--sethugefont /,"")
444
+ do_sethugefont(params.strip)
445
+ when /^--huge /
446
+ figlet_text = line.sub(/^--huge /,"")
447
+ do_huge(figlet_text)
448
+ when /^--footer /
449
+ @footer_txt = line.sub(/^--footer /,"")
450
+ do_footer(@footer_txt)
451
+ when /^--header /
452
+ @header_txt = line.sub(/^--header /,"")
453
+ do_header(@header_txt)
454
+ when /^--title /
455
+ title = line.sub(/^--title /,"")
456
+ do_title(title)
457
+ when /^--author /
458
+ author = line.sub(/^--author /,"")
459
+ do_author(author)
460
+ when /^--date /
461
+ date = line.sub(/^--date /,"")
462
+ if date == "today" then
463
+ date = Time.now.strftime("%b %d %Y")
464
+ elsif date =~ /^today / then
465
+ date = Time.now.strftime(date.sub(/^today /,""))
466
+ end
467
+ do_date(date)
468
+ when /^--bgcolor /
469
+ color = line.sub(/^--bgcolor /,"").strip
470
+ do_bgcolor(color)
471
+ when /^--fgcolor /
472
+ color = line.sub(/^--fgcolor /,"").strip
473
+ do_fgcolor(color)
474
+ when /^--color /
475
+ color = line.sub(/^--color /,"").strip
476
+ do_color(color)
477
+ else
478
+ print_line(line)
479
+ end
480
+
481
+ return false
482
+ end
483
+
484
+ def close
485
+ # nothing
486
+ end
487
+
488
+ end
489
+
490
+ # Implements an interactive visualizer which builds on top of ncurses.
491
+ class NcursesVisualizer < TppVisualizer
492
+
493
+ def initialize
494
+ @figletfont = "standard"
495
+ Ncurses.initscr
496
+ Ncurses.curs_set(0)
497
+ Ncurses.cbreak # unbuffered input
498
+ Ncurses.noecho # turn off input echoing
499
+ Ncurses.stdscr.intrflush(false)
500
+ Ncurses.stdscr.keypad(true)
501
+ @screen = Ncurses.stdscr
502
+ setsizes
503
+ Ncurses.start_color()
504
+ Ncurses.use_default_colors()
505
+ do_bgcolor("black")
506
+ #do_fgcolor("white")
507
+ @fgcolor = ColorMap.get_color_pair("white")
508
+ @voffset = 5
509
+ @indent = 3
510
+ @cur_line = @voffset
511
+ @output = @shelloutput = false
512
+ end
513
+
514
+ def get_key
515
+ ch = @screen.getch
516
+ case ch
517
+ when Ncurses::KEY_RIGHT
518
+ return :keyright
519
+ when Ncurses::KEY_DOWN
520
+ return :keydown
521
+ when Ncurses::KEY_LEFT
522
+ return :keyleft
523
+ when Ncurses::KEY_UP
524
+ return :keyup
525
+ when Ncurses::KEY_RESIZE
526
+ return :keyresize
527
+ else
528
+ return ch
529
+ end
530
+ end
531
+
532
+ def clear
533
+ @screen.clear
534
+ @screen.refresh
535
+ end
536
+
537
+
538
+ def setsizes
539
+ @termwidth = Ncurses.getmaxx(@screen)
540
+ @termheight = Ncurses.getmaxy(@screen)
541
+ end
542
+
543
+ def do_refresh
544
+ @screen.refresh
545
+ end
546
+
547
+ def do_withborder
548
+ @withborder = true
549
+ draw_border
550
+ end
551
+
552
+ def do_command_prompt()
553
+ message = "Press any key to continue :)"
554
+ cursor_pos = 0
555
+ max_len = 50
556
+ prompt = "tpp@localhost:~ $ "
557
+ string = ""
558
+ window = @screen.dupwin
559
+ Ncurses.overwrite(window,@screen) # overwrite @screen with window
560
+ Ncurses.curs_set(1)
561
+ Ncurses.echo
562
+ window.move(@termheight/4,1)
563
+ window.clrtoeol()
564
+ window.clrtobot()
565
+ window.mvaddstr(@termheight/4,1,prompt) # add the prompt string
566
+
567
+ loop do
568
+ window.mvaddstr(@termheight/4,1+prompt.length,string) # add the code
569
+ window.move(@termheight/4,1+prompt.length+cursor_pos) # move cursor to the end of code
570
+ ch = window.getch
571
+ case ch
572
+ when Ncurses::KEY_ENTER, ?\n, ?\r
573
+ Ncurses.curs_set(0)
574
+ Ncurses.noecho
575
+ rc = Kernel.system(string)
576
+ if not rc then
577
+ @screen.mvaddstr(@termheight/4+1,1,"Error: exec \"#{string}\" failed with error code #{$?}")
578
+ @screen.mvaddstr(@termheight-2,@termwidth/2-message.length/2,message)
579
+ end
580
+ if rc then
581
+ @screen.mvaddstr(@termheight-2,@termwidth/2-message.length/2,message)
582
+ ch = Ncurses.getch()
583
+ @screen.refresh
584
+ end
585
+ return
586
+ when Ncurses::KEY_LEFT
587
+ cursor_pos = [0, cursor_pos-1].max # jump one character to the left
588
+ when Ncurses::KEY_RIGHT
589
+ cursor_pos = [0, cursor_pos+1].max # jump one character to the right
590
+ when Ncurses::KEY_BACKSPACE
591
+ string = string[0...([0, cursor_pos-1].max)] + string[cursor_pos..-1]
592
+ cursor_pos = [0, cursor_pos-1].max
593
+ window.mvaddstr(@termheight/4, 1+prompt.length+string.length, " ")
594
+ when " "[0]..255
595
+ if (cursor_pos < max_len)
596
+ string[cursor_pos,0] = ch.chr
597
+ cursor_pos += 1
598
+ else
599
+ Ncurses.beep
600
+ end
601
+ else
602
+ Ncurses.beep
603
+ end
604
+ end
605
+ Ncurses.curs_set(0)
606
+
607
+ end
608
+
609
+ def draw_border
610
+ @screen.move(0,0)
611
+ @screen.addstr(".")
612
+ (@termwidth-2).times { @screen.addstr("-") }; @screen.addstr(".")
613
+ @screen.move(@termheight-2,0)
614
+ @screen.addstr("`")
615
+ (@termwidth-2).times { @screen.addstr("-") }; @screen.addstr("'")
616
+ 1.upto(@termheight-3) do |y|
617
+ @screen.move(y,0)
618
+ @screen.addstr("|")
619
+ end
620
+ 1.upto(@termheight-3) do |y|
621
+ @screen.move(y,@termwidth-1)
622
+ @screen.addstr("|")
623
+ end
624
+ end
625
+
626
+ def new_page
627
+ @cur_line = @voffset
628
+ @output = @shelloutput = false
629
+ setsizes
630
+ @screen.clear
631
+ end
632
+
633
+ def do_heading(line)
634
+ @screen.attron(Ncurses::A_BOLD)
635
+ print_heading(line)
636
+ @screen.attroff(Ncurses::A_BOLD)
637
+ end
638
+
639
+ def do_horline
640
+ @screen.attron(Ncurses::A_BOLD)
641
+ @termwidth.times do |x|
642
+ @screen.move(@cur_line,x)
643
+ @screen.addstr("-")
644
+ end
645
+ @screen.attroff(Ncurses::A_BOLD)
646
+ end
647
+
648
+ def print_heading(text)
649
+ width = @termwidth - 2*@indent
650
+ lines = split_lines(text,width)
651
+ lines.each do |l|
652
+ @screen.move(@cur_line,@indent)
653
+ x = (@termwidth - l.length)/2
654
+ @screen.move(@cur_line,x)
655
+ @screen.addstr(l)
656
+ @cur_line += 1
657
+ end
658
+ end
659
+
660
+ def do_center(text)
661
+ width = @termwidth - 2*@indent
662
+ if @output or @shelloutput then
663
+ width -= 2
664
+ end
665
+ lines = split_lines(text,width)
666
+ lines.each do |l|
667
+ @screen.move(@cur_line,@indent)
668
+ if @output or @shelloutput then
669
+ @screen.addstr("| ")
670
+ end
671
+ x = (@termwidth - l.length)/2
672
+ @screen.move(@cur_line,x)
673
+ @screen.addstr(l)
674
+ if @output or @shelloutput then
675
+ @screen.move(@cur_line,@termwidth - @indent - 2)
676
+ @screen.addstr(" |")
677
+ end
678
+ @cur_line += 1
679
+ end
680
+ end
681
+
682
+ def do_right(text)
683
+ width = @termwidth - 2*@indent
684
+ if @output or @shelloutput then
685
+ width -= 2
686
+ end
687
+ lines = split_lines(text,width)
688
+ lines.each do |l|
689
+ @screen.move(@cur_line,@indent)
690
+ if @output or @shelloutput then
691
+ @screen.addstr("| ")
692
+ end
693
+ x = (@termwidth - l.length - 5)
694
+ @screen.move(@cur_line,x)
695
+ @screen.addstr(l)
696
+ if @output or @shelloutput then
697
+ @screen.addstr(" |")
698
+ end
699
+ @cur_line += 1
700
+ end
701
+ end
702
+
703
+ def show_help_page
704
+ help_text = [ "tpp help",
705
+ "",
706
+ "space bar ............................... display next entry within page",
707
+ "space bar, cursor-down, cursor-right .... display next page",
708
+ "b, cursor-up, cursor-left ............... display previous page",
709
+ "q, Q .................................... quit tpp",
710
+ "j, J .................................... jump directly to page",
711
+ "l, L .................................... reload current file",
712
+ "s, S .................................... jump to the first page",
713
+ "e, E .................................... jump to the last page",
714
+ "c, C .................................... start command line",
715
+ "?, h .................................... this help screen" ]
716
+ @screen.clear
717
+ y = @voffset
718
+ help_text.each do |line|
719
+ @screen.move(y,@indent)
720
+ @screen.addstr(line)
721
+ y += 1
722
+ end
723
+ @screen.move(@termheight - 2, @indent)
724
+ @screen.addstr("Press any key to return to slide")
725
+ @screen.refresh
726
+ end
727
+
728
+ def do_exec(cmdline)
729
+ rc = Kernel.system(cmdline)
730
+ if not rc then
731
+ # @todo: add error message
732
+ end
733
+ end
734
+
735
+ def do_wait
736
+ # nothing
737
+ end
738
+
739
+ def do_beginoutput
740
+ @screen.move(@cur_line,@indent)
741
+ @screen.addstr(".")
742
+ (@termwidth - @indent*2 - 2).times { @screen.addstr("-") }
743
+ @screen.addstr(".")
744
+ @output = true
745
+ @cur_line += 1
746
+ end
747
+
748
+ def do_beginshelloutput
749
+ @screen.move(@cur_line,@indent)
750
+ @screen.addstr(".")
751
+ (@termwidth - @indent*2 - 2).times { @screen.addstr("-") }
752
+ @screen.addstr(".")
753
+ @shelloutput = true
754
+ @cur_line += 1
755
+ end
756
+
757
+ def do_endoutput
758
+ if @output then
759
+ @screen.move(@cur_line,@indent)
760
+ @screen.addstr("`")
761
+ (@termwidth - @indent*2 - 2).times { @screen.addstr("-") }
762
+ @screen.addstr("'")
763
+ @output = false
764
+ @cur_line += 1
765
+ end
766
+ end
767
+
768
+ def do_title(title)
769
+ do_boldon
770
+ do_center(title)
771
+ do_boldoff
772
+ do_center("")
773
+ end
774
+
775
+ def do_footer(footer_txt)
776
+ @screen.move(@termheight - 3, (@termwidth - footer_txt.length)/2)
777
+ @screen.addstr(footer_txt)
778
+ end
779
+
780
+ def do_header(header_txt)
781
+ @screen.move(@termheight - @termheight+1, (@termwidth - header_txt.length)/2)
782
+ @screen.addstr(header_txt)
783
+ end
784
+
785
+ def do_author(author)
786
+ do_center(author)
787
+ do_center("")
788
+ end
789
+
790
+ def do_date(date)
791
+ do_center(date)
792
+ do_center("")
793
+ end
794
+
795
+ def do_endshelloutput
796
+ if @shelloutput then
797
+ @screen.move(@cur_line,@indent)
798
+ @screen.addstr("`")
799
+ (@termwidth - @indent*2 - 2).times { @screen.addstr("-") }
800
+ @screen.addstr("'")
801
+ @shelloutput = false
802
+ @cur_line += 1
803
+ end
804
+ end
805
+
806
+ def do_sleep(time2sleep)
807
+ Kernel.sleep(time2sleep.to_i)
808
+ end
809
+
810
+ def do_boldon
811
+ @screen.attron(Ncurses::A_BOLD)
812
+ end
813
+
814
+ def do_boldoff
815
+ @screen.attroff(Ncurses::A_BOLD)
816
+ end
817
+
818
+ def do_revon
819
+ @screen.attron(Ncurses::A_REVERSE)
820
+ end
821
+
822
+ def do_revoff
823
+ @screen.attroff(Ncurses::A_REVERSE)
824
+ end
825
+
826
+ def do_ulon
827
+ @screen.attron(Ncurses::A_UNDERLINE)
828
+ end
829
+
830
+ def do_uloff
831
+ @screen.attroff(Ncurses::A_UNDERLINE)
832
+ end
833
+
834
+ def do_beginslideleft
835
+ @slideoutput = true
836
+ @slidedir = "left"
837
+ end
838
+
839
+ def do_endslide
840
+ @slideoutput = false
841
+ end
842
+
843
+ def do_beginslideright
844
+ @slideoutput = true
845
+ @slidedir = "right"
846
+ end
847
+
848
+ def do_beginslidetop
849
+ @slideoutput = true
850
+ @slidedir = "top"
851
+ end
852
+
853
+ def do_beginslidebottom
854
+ @slideoutput = true
855
+ @slidedir = "bottom"
856
+ end
857
+
858
+ def do_sethugefont(params)
859
+ @figletfont = params
860
+ end
861
+
862
+ def do_huge(figlet_text)
863
+ output_width = @termwidth - @indent
864
+ output_width -= 2 if @output or @shelloutput
865
+ op = IO.popen("figlet -f #{@figletfont} -w #{output_width} -k \"#{figlet_text}\"","r")
866
+ op.readlines.each do |line|
867
+ print_line(line)
868
+ end
869
+ op.close
870
+ end
871
+
872
+ def do_bgcolor(color)
873
+ bgcolor = ColorMap.get_color(color) or COLOR_BLACK
874
+ Ncurses.init_pair(1, COLOR_WHITE, bgcolor)
875
+ Ncurses.init_pair(2, COLOR_YELLOW, bgcolor)
876
+ Ncurses.init_pair(3, COLOR_RED, bgcolor)
877
+ Ncurses.init_pair(4, COLOR_GREEN, bgcolor)
878
+ Ncurses.init_pair(5, COLOR_BLUE, bgcolor)
879
+ Ncurses.init_pair(6, COLOR_CYAN, bgcolor)
880
+ Ncurses.init_pair(7, COLOR_MAGENTA, bgcolor)
881
+ Ncurses.init_pair(8, COLOR_BLACK, bgcolor)
882
+ if @fgcolor then
883
+ Ncurses.bkgd(Ncurses.COLOR_PAIR(@fgcolor))
884
+ else
885
+ Ncurses.bkgd(Ncurses.COLOR_PAIR(1))
886
+ end
887
+ end
888
+
889
+ def do_fgcolor(color)
890
+ @fgcolor = ColorMap.get_color_pair(color)
891
+ Ncurses.attron(Ncurses.COLOR_PAIR(@fgcolor))
892
+ end
893
+
894
+ def do_color(color)
895
+ num = ColorMap.get_color_pair(color)
896
+ Ncurses.attron(Ncurses.COLOR_PAIR(num))
897
+ end
898
+
899
+ def type_line(l)
900
+ l.each_byte do |x|
901
+ @screen.addstr(x.chr)
902
+ @screen.refresh()
903
+ r = rand(20)
904
+ time_to_sleep = (5 + r).to_f / 250;
905
+ # puts "#{time_to_sleep} #{r}"
906
+ Kernel.sleep(time_to_sleep)
907
+ end
908
+ end
909
+
910
+ def slide_text(l)
911
+ return if l == ""
912
+ case @slidedir
913
+ when "left"
914
+ xcount = l.length-1
915
+ while xcount >= 0
916
+ @screen.move(@cur_line,@indent)
917
+ @screen.addstr(l[xcount..l.length-1])
918
+ @screen.refresh()
919
+ time_to_sleep = 1.to_f / 20
920
+ Kernel.sleep(time_to_sleep)
921
+ xcount -= 1
922
+ end
923
+ when "right"
924
+ (@termwidth - @indent).times do |pos|
925
+ @screen.move(@cur_line,@termwidth - pos - 1)
926
+ @screen.clrtoeol()
927
+ maxpos = (pos >= l.length-1) ? l.length-1 : pos
928
+ @screen.addstr(l[0..pos])
929
+ @screen.refresh()
930
+ time_to_sleep = 1.to_f / 20
931
+ Kernel.sleep(time_to_sleep)
932
+ end # do
933
+ when "top"
934
+ # ycount = @cur_line
935
+ new_scr = @screen.dupwin
936
+ 1.upto(@cur_line) do |i|
937
+ Ncurses.overwrite(new_scr,@screen) # overwrite @screen with new_scr
938
+ @screen.move(i,@indent)
939
+ @screen.addstr(l)
940
+ @screen.refresh()
941
+ Kernel.sleep(1.to_f / 10)
942
+ end
943
+ when "bottom"
944
+ new_scr = @screen.dupwin
945
+ (@termheight-1).downto(@cur_line) do |i|
946
+ Ncurses.overwrite(new_scr,@screen)
947
+ @screen.move(i,@indent)
948
+ @screen.addstr(l)
949
+ @screen.refresh()
950
+ Kernel.sleep(1.to_f / 10)
951
+ end
952
+ end
953
+ end
954
+
955
+ def print_line(line)
956
+ width = @termwidth - 2*@indent
957
+ if @output or @shelloutput then
958
+ width -= 2
959
+ end
960
+ lines = split_lines(line,width)
961
+ lines.each do |l|
962
+ @screen.move(@cur_line,@indent)
963
+ if (@output or @shelloutput) and ! @slideoutput then
964
+ @screen.addstr("| ")
965
+ end
966
+ if @shelloutput and (l =~ /^\$/ or l=~ /^%/ or l =~ /^#/) then # allow sh and csh style prompts
967
+ type_line(l)
968
+ elsif @slideoutput then
969
+ slide_text(l)
970
+ else
971
+ @screen.addstr(l)
972
+ end
973
+ if (@output or @shelloutput) and ! @slideoutput then
974
+ @screen.move(@cur_line,@termwidth - @indent - 2)
975
+ @screen.addstr(" |")
976
+ end
977
+ @cur_line += 1
978
+ end
979
+ end
980
+
981
+ def close
982
+ Ncurses.nocbreak
983
+ Ncurses.endwin
984
+ end
985
+
986
+ def read_newpage(pages,current_page)
987
+ page = []
988
+ @screen.clear()
989
+ col = 0
990
+ line = 2
991
+ pages.each_index do |i|
992
+ @screen.move(line,col*15 + 2)
993
+ if current_page == i then
994
+ @screen.printw("%2d %s <=",i+1,pages[i].title[0..80])
995
+ else
996
+ @screen.printw("%2d %s",i+1,pages[i].title[0..80])
997
+ end
998
+ line += 1
999
+ if line >= @termheight - 3 then
1000
+ line = 2
1001
+ col += 1
1002
+ end
1003
+ end
1004
+ prompt = "jump to slide: "
1005
+ prompt_indent = 12
1006
+ @screen.move(@termheight - 2, @indent + prompt_indent)
1007
+ @screen.addstr(prompt)
1008
+ # @screen.refresh();
1009
+ Ncurses.echo
1010
+ @screen.scanw("%d",page)
1011
+ Ncurses.noecho
1012
+ @screen.move(@termheight - 2, @indent + prompt_indent)
1013
+ (prompt.length + page[0].to_s.length).times { @screen.addstr(" ") }
1014
+ if page[0] then
1015
+ return page[0] - 1
1016
+ end
1017
+ return -1 # invalid page
1018
+ end
1019
+
1020
+ def store_screen
1021
+ @screen.dupwin
1022
+ end
1023
+
1024
+ def restore_screen(s)
1025
+ Ncurses.overwrite(s,@screen)
1026
+ end
1027
+
1028
+ def draw_slidenum(cur_page,max_pages,eop)
1029
+ @screen.move(@termheight - 2, @indent)
1030
+ @screen.attroff(Ncurses::A_BOLD) # this is bad
1031
+ @screen.addstr("[slide #{cur_page}/#{max_pages}]")
1032
+ if @footer_txt.to_s.length > 0 then
1033
+ do_footer(@footer_txt)
1034
+ end
1035
+ if @header_txt.to_s.length > 0 then
1036
+ do_header(@header_txt)
1037
+ end
1038
+
1039
+ if eop then
1040
+ draw_eop_marker
1041
+ end
1042
+ end
1043
+
1044
+ def draw_eop_marker
1045
+ @screen.move(@termheight - 2, @indent - 1)
1046
+ @screen.attron(A_BOLD)
1047
+ @screen.addstr("*")
1048
+ @screen.attroff(A_BOLD)
1049
+ end
1050
+
1051
+ end
1052
+
1053
+
1054
+ # Implements a visualizer which converts TPP source to LaTeX-beamer source (http://latex-beamer.sf.net/
1055
+ class LatexVisualizer < TppVisualizer
1056
+
1057
+ def initialize(outputfile)
1058
+ @filename = outputfile
1059
+ begin
1060
+ @f = File.open(@filename,"w+")
1061
+ rescue
1062
+ $stderr.print "Error: couldn't open file: #{$!}"
1063
+ Kernel.exit(1)
1064
+ end
1065
+ @slide_open = false
1066
+ @verbatim_open = false
1067
+ @width = 50
1068
+ @title = @date = @author = false
1069
+ @begindoc = false
1070
+ @f.puts '% Filename: tpp.tex
1071
+ % Purpose: template file for tpp latex export
1072
+ % Authors: (c) Andreas Gredler, Michael Prokop http://grml.org/
1073
+ % License: This file is licensed under the GPL v2.
1074
+ % Latest change: Fre Apr 15 20:34:37 CEST 2005
1075
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1076
+
1077
+ \documentclass{beamer}
1078
+
1079
+ \mode<presentation>
1080
+ {
1081
+ \usetheme{Montpellier}
1082
+ \setbeamercovered{transparent}
1083
+ }
1084
+
1085
+ \usepackage[german]{babel}
1086
+ \usepackage{umlaut}
1087
+ \usepackage[latin1]{inputenc}
1088
+ \usepackage{times}
1089
+ \usepackage[T1]{fontenc}
1090
+
1091
+ '
1092
+ end
1093
+
1094
+ def do_footer(footer_text)
1095
+ end
1096
+
1097
+ def do_header(header_text)
1098
+ end
1099
+
1100
+ def do_refresh
1101
+ end
1102
+
1103
+ def try_close
1104
+ if @verbatim_open then
1105
+ @f.puts '\end{verbatim}'
1106
+ @verbatim_open = false
1107
+ end
1108
+ if @slide_open then
1109
+ @f.puts '\end{frame}'
1110
+ @slide_open = false
1111
+ end
1112
+ end
1113
+
1114
+ def new_page
1115
+ try_close
1116
+ end
1117
+
1118
+ def do_heading(text)
1119
+ try_close
1120
+ @f.puts "\\section{#{text}}"
1121
+ end
1122
+
1123
+ def do_withborder
1124
+ end
1125
+
1126
+ def do_horline
1127
+ end
1128
+
1129
+ def do_color(text)
1130
+ end
1131
+
1132
+ def do_center(text)
1133
+ print_line(text)
1134
+ end
1135
+
1136
+ def do_right(text)
1137
+ print_line(text)
1138
+ end
1139
+
1140
+ def do_exec(cmdline)
1141
+ end
1142
+
1143
+ def do_wait
1144
+ end
1145
+
1146
+ def do_beginoutput
1147
+ # TODO: implement output stuff
1148
+ end
1149
+
1150
+ def do_beginshelloutput
1151
+ end
1152
+
1153
+ def do_endoutput
1154
+ end
1155
+
1156
+ def do_endshelloutput
1157
+ end
1158
+
1159
+ def do_sleep(time2sleep)
1160
+ end
1161
+
1162
+ def do_boldon
1163
+ end
1164
+
1165
+ def do_boldoff
1166
+ end
1167
+
1168
+ def do_revon
1169
+ end
1170
+
1171
+ def do_command_prompt
1172
+ end
1173
+ def do_revoff
1174
+ end
1175
+
1176
+ def do_ulon
1177
+ end
1178
+
1179
+ def do_uloff
1180
+ end
1181
+
1182
+ def do_beginslideleft
1183
+ end
1184
+
1185
+ def do_endslide
1186
+ end
1187
+
1188
+ def do_beginslideright
1189
+ end
1190
+
1191
+ def do_beginslidetop
1192
+ end
1193
+
1194
+ def do_beginslidebottom
1195
+ end
1196
+
1197
+ def do_sethugefont(text)
1198
+ end
1199
+
1200
+ def do_huge(text)
1201
+ end
1202
+
1203
+ def try_open
1204
+ if not @begindoc then
1205
+ @f.puts '\begin{document}'
1206
+ @begindoc = true
1207
+ end
1208
+ if not @slide_open then
1209
+ @f.puts '\begin{frame}[fragile]'
1210
+ @slide_open = true
1211
+ end
1212
+ if not @verbatim_open then
1213
+ @f.puts '\begin{verbatim}'
1214
+ @verbatim_open = true
1215
+ end
1216
+ end
1217
+
1218
+ def try_intro
1219
+ if @author and @title and @date and not @begindoc then
1220
+ @f.puts '\begin{document}'
1221
+ @begindoc = true
1222
+ end
1223
+ if @author and @title and @date then
1224
+ @f.puts '\begin{frame}
1225
+ \titlepage
1226
+ \end{frame}'
1227
+ end
1228
+ end
1229
+
1230
+ def print_line(line)
1231
+ try_open
1232
+ split_lines(line,@width).each do |l|
1233
+ @f.puts "#{l}"
1234
+ end
1235
+ end
1236
+
1237
+ def do_title(title)
1238
+ @f.puts "\\title[#{title}]{#{title}}"
1239
+ @title = true
1240
+ try_intro
1241
+ end
1242
+
1243
+ def do_author(author)
1244
+ @f.puts "\\author{#{author}}"
1245
+ @author = true
1246
+ try_intro
1247
+ end
1248
+
1249
+ def do_date(date)
1250
+ @f.puts "\\date{#{date}}"
1251
+ @date = true
1252
+ try_intro
1253
+ end
1254
+
1255
+ def do_bgcolor(color)
1256
+ end
1257
+
1258
+ def do_fgcolor(color)
1259
+ end
1260
+
1261
+ def do_color(color)
1262
+ end
1263
+
1264
+ def close
1265
+ try_close
1266
+ @f.puts '\end{document}
1267
+ %%%%% END OF FILE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%'
1268
+ @f.close
1269
+ end
1270
+
1271
+ end
1272
+
1273
+
1274
+ # Implements a generic controller from which all other controllers need to be derived.
1275
+ class TppController
1276
+
1277
+ def initialize
1278
+ $stderr.puts "Error: TppController.initialize has been called directly!"
1279
+ Kernel.exit(1)
1280
+ end
1281
+
1282
+ def close
1283
+ $stderr.puts "Error: TppController.close has been called directly!"
1284
+ Kernel.exit(1)
1285
+ end
1286
+
1287
+ def run
1288
+ $stderr.puts "Error: TppController.run has been called directly!"
1289
+ Kernel.exit(1)
1290
+ end
1291
+
1292
+ end
1293
+
1294
+ # Implements a non-interactive controller for ncurses. Useful for displaying
1295
+ # unattended presentation.
1296
+ class AutoplayController < TppController
1297
+
1298
+ def initialize(filename,secs,visualizer_class)
1299
+ @filename = filename
1300
+ @vis = visualizer_class.new
1301
+ @seconds = secs
1302
+ @cur_page = 0
1303
+ end
1304
+
1305
+ def close
1306
+ @vis.close
1307
+ end
1308
+
1309
+ def run
1310
+ begin
1311
+ @reload_file = false
1312
+ parser = FileParser.new(@filename)
1313
+ @pages = parser.get_pages
1314
+ if @cur_page >= @pages.size then
1315
+ @cur_page = @pages.size - 1
1316
+ end
1317
+ @vis.clear
1318
+ @vis.new_page
1319
+ do_run
1320
+ end while @reload_file
1321
+ end
1322
+
1323
+ def do_run
1324
+ loop do
1325
+ wait = false
1326
+ @vis.draw_slidenum(@cur_page + 1, @pages.size, false)
1327
+ # read and visualize lines until the visualizer says "stop" or we reached end of page
1328
+ begin
1329
+ line = @pages[@cur_page].next_line
1330
+ eop = @pages[@cur_page].eop?
1331
+ wait = @vis.visualize(line,eop)
1332
+ end while not wait and not eop
1333
+ # draw slide number on the bottom left and redraw:
1334
+ @vis.draw_slidenum(@cur_page + 1, @pages.size, eop)
1335
+ @vis.do_refresh
1336
+
1337
+ if eop then
1338
+ if @cur_page + 1 < @pages.size then
1339
+ @cur_page += 1
1340
+ else
1341
+ @cur_page = 0
1342
+ end
1343
+ @pages[@cur_page].reset_eop
1344
+ @vis.new_page
1345
+ end
1346
+
1347
+ Kernel.sleep(@seconds)
1348
+ end # loop
1349
+ end
1350
+
1351
+ end
1352
+
1353
+ # Implements an interactive controller which feeds the visualizer until it is
1354
+ # told to stop, and then reads a key press and executes the appropiate action.
1355
+ class InteractiveController < TppController
1356
+
1357
+ def initialize(filename,visualizer_class)
1358
+ @filename = filename
1359
+ @vis = visualizer_class.new
1360
+ @cur_page = 0
1361
+ end
1362
+
1363
+ def close
1364
+ @vis.close
1365
+ end
1366
+
1367
+ def run
1368
+ begin
1369
+ @reload_file = false
1370
+ parser = FileParser.new(@filename)
1371
+ @pages = parser.get_pages
1372
+ if @cur_page >= @pages.size then
1373
+ @cur_page = @pages.size - 1
1374
+ end
1375
+ @vis.clear
1376
+ @vis.new_page
1377
+ do_run
1378
+ end while @reload_file
1379
+ end
1380
+
1381
+ def do_run
1382
+ loop do
1383
+ wait = false
1384
+ @vis.draw_slidenum(@cur_page + 1, @pages.size, false)
1385
+ # read and visualize lines until the visualizer says "stop" or we reached end of page
1386
+ begin
1387
+ line = @pages[@cur_page].next_line
1388
+ eop = @pages[@cur_page].eop?
1389
+ wait = @vis.visualize(line,eop)
1390
+ end while not wait and not eop
1391
+ # draw slide number on the bottom left and redraw:
1392
+ @vis.draw_slidenum(@cur_page + 1, @pages.size, eop)
1393
+ @vis.do_refresh
1394
+
1395
+ # read a character from the keyboard
1396
+ # a "break" in the when means that it breaks the loop, i.e. goes on with visualizing lines
1397
+ loop do
1398
+ ch = @vis.get_key
1399
+ case ch
1400
+ when 'q'[0], 'Q'[0] # 'Q'uit
1401
+ return
1402
+ when 'r'[0], 'R'[0] # 'R'edraw slide
1403
+ changed_page = true # @todo: actually implement redraw
1404
+ when 'e'[0], 'E'[0]
1405
+ @cur_page = @pages.size - 1
1406
+ break
1407
+ when 's'[0], 'S'[0]
1408
+ @cur_page = 0
1409
+ break
1410
+ when 'j'[0], 'J'[0] # 'J'ump to slide
1411
+ screen = @vis.store_screen
1412
+ p = @vis.read_newpage(@pages,@cur_page)
1413
+ if p >= 0 and p < @pages.size
1414
+ @cur_page = p
1415
+ @pages[@cur_page].reset_eop
1416
+ @vis.new_page
1417
+ else
1418
+ @vis.restore_screen(screen)
1419
+ end
1420
+ break
1421
+ when 'l'[0], 'L'[0] # re'l'oad current file
1422
+ @reload_file = true
1423
+ return
1424
+ when 'c'[0], 'C'[0] # command prompt
1425
+ screen = @vis.store_screen
1426
+ @vis.do_command_prompt
1427
+ @vis.clear
1428
+ @vis.restore_screen(screen)
1429
+ when '?'[0], 'h'[0]
1430
+ screen = @vis.store_screen
1431
+ @vis.show_help_page
1432
+ ch = @vis.get_key
1433
+ @vis.clear
1434
+ @vis.restore_screen(screen)
1435
+ when :keyright, :keydown, ' '[0]
1436
+ if @cur_page + 1 < @pages.size and eop then
1437
+ @cur_page += 1
1438
+ @pages[@cur_page].reset_eop
1439
+ @vis.new_page
1440
+ end
1441
+ break
1442
+ when 'b'[0], 'B'[0], :keyleft, :keyup
1443
+ if @cur_page > 0 then
1444
+ @cur_page -= 1
1445
+ @pages[@cur_page].reset_eop
1446
+ @vis.new_page
1447
+ end
1448
+ break
1449
+ when :keyresize
1450
+ @vis.setsizes
1451
+ end
1452
+ end
1453
+ end # loop
1454
+ end
1455
+
1456
+ end
1457
+
1458
+
1459
+ # Implements a visualizer which converts TPP source to a nicely formatted text
1460
+ # file which can e.g. be used as handout.
1461
+ class TextVisualizer < TppVisualizer
1462
+
1463
+ def initialize(outputfile)
1464
+ @filename = outputfile
1465
+ begin
1466
+ @f = File.open(@filename,"w+")
1467
+ rescue
1468
+ $stderr.print "Error: couldn't open file: #{$!}"
1469
+ Kernel.exit(1)
1470
+ end
1471
+ @output_env = false
1472
+ @title = @author = @date = false
1473
+ @figletfont = "small"
1474
+ @width = 80
1475
+ end
1476
+
1477
+ def do_footer(footer_text)
1478
+ end
1479
+
1480
+ def do_header(header_text)
1481
+ end
1482
+
1483
+ def do_refresh
1484
+ end
1485
+
1486
+ def new_page
1487
+ @f.puts "--------------------------------------------"
1488
+ end
1489
+
1490
+ def do_heading(text)
1491
+ @f.puts "\n"
1492
+ split_lines(text,@width).each do |l|
1493
+ @f.puts "#{l}\n"
1494
+ end
1495
+ @f.puts "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
1496
+ end
1497
+
1498
+ def do_withborder
1499
+ end
1500
+
1501
+ def do_horline
1502
+ @f.puts "********************************************"
1503
+ end
1504
+
1505
+ def do_color(text)
1506
+ end
1507
+
1508
+ def do_exec(cmdline)
1509
+ end
1510
+
1511
+ def do_wait
1512
+ end
1513
+
1514
+ def do_beginoutput
1515
+ @f.puts ".---------------------------"
1516
+ @output_env = true
1517
+ end
1518
+
1519
+ def do_beginshelloutput
1520
+ do_beginoutput
1521
+ end
1522
+
1523
+ def do_endoutput
1524
+ @f.puts "`---------------------------"
1525
+ @output_env = false
1526
+ end
1527
+
1528
+ def do_endshelloutput
1529
+ do_endoutput
1530
+ end
1531
+
1532
+ def do_sleep(time2sleep)
1533
+ end
1534
+
1535
+ def do_boldon
1536
+ end
1537
+
1538
+ def do_boldoff
1539
+ end
1540
+
1541
+ def do_revon
1542
+ end
1543
+
1544
+ def do_command_prompt
1545
+ end
1546
+ def do_revoff
1547
+ end
1548
+
1549
+ def do_ulon
1550
+ end
1551
+
1552
+ def do_uloff
1553
+ end
1554
+
1555
+ def do_beginslideleft
1556
+ end
1557
+
1558
+ def do_endslide
1559
+ end
1560
+
1561
+ def do_beginslideright
1562
+ end
1563
+
1564
+ def do_beginslidetop
1565
+ end
1566
+
1567
+ def do_beginslidebottom
1568
+ end
1569
+
1570
+ def do_sethugefont(text)
1571
+ @figletfont = text
1572
+ end
1573
+
1574
+ def do_huge(text)
1575
+ output_width = @width
1576
+ output_width -= 2 if @output_env
1577
+ op = IO.popen("figlet -f #{@figletfont} -w @output_width -k \"#{text}\"","r")
1578
+ op.readlines.each do |line|
1579
+ print_line(line)
1580
+ end
1581
+ op.close
1582
+ end
1583
+
1584
+ def print_line(line)
1585
+ lines = split_lines(line,@width)
1586
+ lines.each do |l|
1587
+ if @output_env then
1588
+ @f.puts "| #{l}"
1589
+ else
1590
+ @f.puts "#{l}"
1591
+ end
1592
+ end
1593
+ end
1594
+
1595
+ def do_center(text)
1596
+ lines = split_lines(text,@width)
1597
+ lines.each do |line|
1598
+ spaces = (@width - line.length) / 2
1599
+ spaces = 0 if spaces < 0
1600
+ spaces.times { line = " " + line }
1601
+ print_line(line)
1602
+ end
1603
+ end
1604
+
1605
+ def do_right(text)
1606
+ lines = split_lines(text,@width)
1607
+ lines.each do |line|
1608
+ spaces = @width - line.length
1609
+ spaces = 0 if spaces < 0
1610
+ spaces.times { line = " " + line }
1611
+ print_line(line)
1612
+ end
1613
+ end
1614
+
1615
+ def do_title(title)
1616
+ @f.puts "Title: #{title}"
1617
+ @title = true
1618
+ if @title and @author and @date then
1619
+ @f.puts "\n\n"
1620
+ end
1621
+ end
1622
+
1623
+ def do_author(author)
1624
+ @f.puts "Author: #{author}"
1625
+ @author = true
1626
+ if @title and @author and @date then
1627
+ @f.puts "\n\n"
1628
+ end
1629
+ end
1630
+
1631
+ def do_date(date)
1632
+ @f.puts "Date: #{date}"
1633
+ @date = true
1634
+ if @title and @author and @date then
1635
+ @f.puts "\n\n"
1636
+ end
1637
+ end
1638
+
1639
+ def do_bgcolor(color)
1640
+ end
1641
+
1642
+ def do_fgcolor(color)
1643
+ end
1644
+
1645
+ def do_color(color)
1646
+ end
1647
+
1648
+ def close
1649
+ @f.close
1650
+ end
1651
+
1652
+ end
1653
+
1654
+ # Implements a non-interactive controller to control non-interactive
1655
+ # visualizers (i.e. those that are used for converting TPP source code into
1656
+ # another format)
1657
+ class ConversionController < TppController
1658
+
1659
+ def initialize(input,output,visualizer_class)
1660
+ parser = FileParser.new(input)
1661
+ @pages = parser.get_pages
1662
+ @vis = visualizer_class.new(output)
1663
+ end
1664
+
1665
+ def run
1666
+ @pages.each do |p|
1667
+ begin
1668
+ line = p.next_line
1669
+ eop = p.eop?
1670
+ @vis.visualize(line,eop)
1671
+ end while not eop
1672
+ end
1673
+ end
1674
+
1675
+ def close
1676
+ @vis.close
1677
+ end
1678
+
1679
+ end
1680
+
1681
+ # Prints a nicely formatted usage message.
1682
+ def usage
1683
+ $stderr.puts "usage: #{$0} [-t <type> -o <file>] <file>\n"
1684
+ $stderr.puts "\t -t <type>\tset filetype <type> as output format"
1685
+ $stderr.puts "\t -o <file>\twrite output to file <file>"
1686
+ $stderr.puts "\t -s <seconds>\twait <seconds> seconds between slides (with -t autoplay)"
1687
+ $stderr.puts "\t --version\tprint the version"
1688
+ $stderr.puts "\t --help\t\tprint this help"
1689
+ $stderr.puts "\n\t currently available types: ncurses (default), autoplay, latex, txt"
1690
+ Kernel.exit(1)
1691
+ end
1692
+
1693
+
1694
+
1695
+ ################################
1696
+ # Here starts the main program #
1697
+ ################################
1698
+
1699
+ input = nil
1700
+ output = nil
1701
+ type = "ncurses"
1702
+ time = 1
1703
+
1704
+ skip_next = false
1705
+
1706
+ ARGV.each_index do |i|
1707
+ if skip_next then
1708
+ skip_next = false
1709
+ else
1710
+ if ARGV[i] == '-v' or ARGV[i] == '--version' then
1711
+ printf "tpp - text presentation program %s\n", version_number
1712
+ Kernel.exit(1)
1713
+ elsif ARGV[i] == '-h' or ARGV[i] == '--help' then
1714
+ usage
1715
+ elsif ARGV[i] == '-t' then
1716
+ type = ARGV[i+1]
1717
+ skip_next = true
1718
+ elsif ARGV[i] == '-o' then
1719
+ output = ARGV[i+1]
1720
+ skip_next = true
1721
+ elsif ARGV[i] == "-s" then
1722
+ time = ARGV[i+1].to_i
1723
+ skip_next = true
1724
+ elsif input == nil then
1725
+ input = ARGV[i]
1726
+ end
1727
+ if output!=nil and output==input then
1728
+ $stderr.puts "Don't use the input file name as the output filename to prevent overwriting it. \n"
1729
+ Kernel.exit(1)
1730
+ end
1731
+ end
1732
+ end
1733
+
1734
+ if input == nil then
1735
+ usage
1736
+ end
1737
+
1738
+ ctrl = nil
1739
+
1740
+ case type
1741
+ when "ncurses"
1742
+ load_ncurses
1743
+ ctrl = InteractiveController.new(input,NcursesVisualizer)
1744
+ when "autoplay"
1745
+ load_ncurses
1746
+ ctrl = AutoplayController.new(input,time,NcursesVisualizer)
1747
+ when "txt"
1748
+ if output == nil then
1749
+ usage
1750
+ else
1751
+ ctrl = ConversionController.new(input,output,TextVisualizer)
1752
+ end
1753
+ when "latex"
1754
+ if output == nil then
1755
+ usage
1756
+ else
1757
+ ctrl = ConversionController.new(input,output,LatexVisualizer)
1758
+ end
1759
+ else
1760
+ usage
1761
+ end # case
1762
+
1763
+ ctrl.run
1764
+ ctrl.close