present 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,4 @@
1
+ == 0.0.1 / 2008-08-31
2
+
3
+ * initial release
4
+
data/README ADDED
@@ -0,0 +1,41 @@
1
+
2
+ = present
3
+
4
+ Presentation tool for terminal.
5
+
6
+ == Description
7
+
8
+ This program is for terminal addicts.
9
+ You can present your slide by using your favorite terminal.
10
+
11
+ == Installation
12
+
13
+ === Archive Installation
14
+
15
+ rake install
16
+
17
+ === Gem Installation
18
+
19
+ gem install present
20
+
21
+
22
+ == Features/Problems
23
+
24
+
25
+ == Synopsis
26
+
27
+ present [options] file [duration] [page]
28
+
29
+ `file` specifies presentation file. there is an example in the sample/ dir.
30
+
31
+ `duration` specifies expected duration in minute. This is optional. The
32
+ default value is 5 min.
33
+
34
+ `page` specifies the page number which will be started from. This is
35
+ optional. The default value is 1.
36
+
37
+ == Copyright
38
+
39
+ Author:: Genki Takiuchi <genki@s21g.com>
40
+ Copyright:: Copyright (c) 2008 Genki Takiuchi
41
+ License::
@@ -0,0 +1,149 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/clean'
4
+ require 'rake/testtask'
5
+ require 'rake/packagetask'
6
+ require 'rake/gempackagetask'
7
+ require 'rake/rdoctask'
8
+ require 'rake/contrib/rubyforgepublisher'
9
+ require 'rake/contrib/sshpublisher'
10
+ require 'fileutils'
11
+
12
+ $:.unshift File.join(File.dirname(__FILE__), 'lib')
13
+ require 'present'
14
+ include FileUtils
15
+
16
+ NAME = "present"
17
+ AUTHOR = "Genki Takiuchi"
18
+ EMAIL = "genki@s21g.com"
19
+ DESCRIPTION = "Presentation tool for terminal."
20
+ RUBYFORGE_PROJECT = "cocktail-party"
21
+ HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org"
22
+ BIN_FILES = %w(present)
23
+
24
+ VERS = Present::VERSION
25
+ REV = File.read(".svn/entries")[/committed-rev="(d+)"/, 1] rescue nil
26
+ CLEAN.include ['**/.*.sw?', '*.gem', '.config']
27
+ RDOC_OPTS = [
28
+ '--title', "#{NAME} documentation",
29
+ "--charset", "utf-8",
30
+ "--opname", "index.html",
31
+ "--line-numbers",
32
+ "--main", "README",
33
+ "--inline-source",
34
+ ]
35
+
36
+ task :default => [:test]
37
+ task :package => [:clean]
38
+
39
+ Rake::TestTask.new("test") do |t|
40
+ t.libs << "test"
41
+ t.pattern = "test/**/*_test.rb"
42
+ t.verbose = true
43
+ end
44
+
45
+ spec = Gem::Specification.new do |s|
46
+ s.name = NAME
47
+ s.version = VERS
48
+ s.platform = Gem::Platform::RUBY
49
+ s.has_rdoc = true
50
+ s.extra_rdoc_files = ["README", "ChangeLog"]
51
+ s.rdoc_options += RDOC_OPTS + ['--exclude', '^(examples|extras)/']
52
+ s.summary = DESCRIPTION
53
+ s.description = DESCRIPTION
54
+ s.author = AUTHOR
55
+ s.email = EMAIL
56
+ s.homepage = HOMEPATH
57
+ s.executables = BIN_FILES
58
+ s.rubyforge_project = RUBYFORGE_PROJECT
59
+ s.bindir = "bin"
60
+ s.require_path = "lib"
61
+ #s.autorequire = ""
62
+ s.test_files = Dir["test/*_test.rb"]
63
+
64
+ #s.add_dependency('activesupport', '>=1.3.1')
65
+ s.add_dependency('ncurses')
66
+ s.add_dependency('text')
67
+ s.add_dependency('escape')
68
+ #s.required_ruby_version = '>= 1.8.2'
69
+
70
+ s.files = %w(README ChangeLog Rakefile) +
71
+ Dir.glob("{bin,doc,test,lib,templates,generator,extras,website,script}/**/*") +
72
+ Dir.glob("ext/**/*.{h,c,rb}") +
73
+ Dir.glob("examples/**/*.rb") +
74
+ Dir.glob("tools/*.rb") +
75
+ Dir.glob("rails/*.rb")
76
+
77
+ s.extensions = FileList["ext/**/extconf.rb"].to_a
78
+ end
79
+
80
+ Rake::GemPackageTask.new(spec) do |p|
81
+ p.need_tar = true
82
+ p.gem_spec = spec
83
+ end
84
+
85
+ task :install do
86
+ name = "#{NAME}-#{VERS}.gem"
87
+ sh %{rake package}
88
+ sh %{sudo gem install pkg/#{name}}
89
+ end
90
+
91
+ task :uninstall => [:clean] do
92
+ sh %{sudo gem uninstall #{NAME}}
93
+ end
94
+
95
+
96
+ Rake::RDocTask.new do |rdoc|
97
+ rdoc.rdoc_dir = 'html'
98
+ rdoc.options += RDOC_OPTS
99
+ rdoc.template = "resh"
100
+ #rdoc.template = "#{ENV['template']}.rb" if ENV['template']
101
+ if ENV['DOC_FILES']
102
+ rdoc.rdoc_files.include(ENV['DOC_FILES'].split(/,\s*/))
103
+ else
104
+ rdoc.rdoc_files.include('README', 'ChangeLog')
105
+ rdoc.rdoc_files.include('lib/**/*.rb')
106
+ rdoc.rdoc_files.include('ext/**/*.c')
107
+ end
108
+ end
109
+
110
+ desc "Publish to RubyForge"
111
+ task :rubyforge => [:rdoc, :package] do
112
+ require 'rubyforge'
113
+ Rake::RubyForgePublisher.new(RUBYFORGE_PROJECT, 'takiuchi').upload
114
+ end
115
+
116
+ desc 'Package and upload the release to rubyforge.'
117
+ task :release => [:clean, :package] do |t|
118
+ v = ENV["VERSION"] or abort "Must supply VERSION=x.y.z"
119
+ abort "Versions don't match #{v} vs #{VERS}" unless v == VERS
120
+ pkg = "pkg/#{NAME}-#{VERS}"
121
+
122
+ require 'rubyforge'
123
+ rf = RubyForge.new.configure
124
+ puts "Logging in"
125
+ rf.login
126
+
127
+ c = rf.userconfig
128
+ # c["release_notes"] = description if description
129
+ # c["release_changes"] = changes if changes
130
+ c["preformatted"] = true
131
+
132
+ files = [
133
+ "#{pkg}.tgz",
134
+ "#{pkg}.gem"
135
+ ].compact
136
+
137
+ puts "Releasing #{NAME} v. #{VERS}"
138
+ rf.add_release RUBYFORGE_PROJECT, NAME, VERS, *files
139
+ end
140
+
141
+ desc 'Show information about the gem.'
142
+ task :debug_gem do
143
+ puts spec.to_ruby
144
+ end
145
+
146
+ desc 'Update gem spec'
147
+ task :gemspec do
148
+ open("#{NAME}.gemspec", 'w').write spec.to_ruby
149
+ end
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+ $:.unshift File.join(File.dirname(__FILE__), '../lib')
3
+ require 'optparse'
4
+ require 'present'
5
+
6
+ Version = Present::VERSION
7
+ opt = OptionParser.new
8
+ opt.banner = "Usage: present [options] file [duration] [page]"
9
+ opt.on_tail('-v', '--version', 'Show version.'){puts opt.ver; exit}
10
+ opt.order!(ARGV)
11
+
12
+ Present.new(*ARGV).start
@@ -0,0 +1,227 @@
1
+ require 'rubygems'
2
+ require 'ncurses'
3
+ require 'text'
4
+ require 'escape'
5
+ require 'nkf'
6
+ require 'present/page'
7
+
8
+ class Present
9
+ VERSION = '0.0.2'
10
+ TIOCGWINSZ = 0x5413
11
+
12
+ def initialize(path, timer = 5, page = 1)
13
+ @source = path
14
+ @script = NKF.nkf('-e', open(path).read)
15
+ @stanzas = @script.split(/\n\n+/)
16
+ str = [0, 0, 0, 0].pack("SSSS")
17
+ if $stdin.ioctl(TIOCGWINSZ, str) >= 0 then
18
+ @rows, @cols, xpixels, ypixels = str.unpack("SSSS")
19
+ else
20
+ @rows, @cols = 13, 40
21
+ end
22
+ @pages = @stanzas.map{|stanza| Page.new(stanza, self)}
23
+ @page = page.to_i - 1
24
+ @timer = timer.to_i * 60
25
+ end
26
+
27
+ def start
28
+ Ncurses.initscr
29
+ Ncurses.raw
30
+ Ncurses.cbreak
31
+ Ncurses.noecho
32
+ Ncurses.start_color
33
+ Ncurses.refresh
34
+ @win = Ncurses::WINDOW.new @rows - 1, @cols, 0, 0
35
+ @win.keypad true
36
+ Ncurses.nodelay @win, 1
37
+ @status = Ncurses::WINDOW.new 1, @cols + 1, @rows - 1, 0
38
+ @status.color_set 1, nil
39
+ @start = Time.now
40
+ @colors = {}
41
+ register_pair Ncurses::COLOR_BLACK, Ncurses::COLOR_WHITE
42
+ while page = @pages[@page]
43
+ @row = @rows / 4
44
+ paginate
45
+ page.start
46
+
47
+ begin
48
+ input = @win.getch
49
+ case input
50
+ when 27, ?q; return # exit
51
+ when ?:; scan_command
52
+ when ?k, ?h, 259, 260; @page = [@page - 1, 0].max
53
+ when ?<; @page = 0
54
+ when ?>; @page = @pages.size - 1
55
+ when ?j, ?l, 10, 13, 32, 258, 261
56
+ @page = [@page + 1, @pages.size - 1].min
57
+ when ?r; reload
58
+ else
59
+ sleep 0.1
60
+ paginate
61
+ end
62
+ end while input == -1
63
+ end
64
+ ensure
65
+ Ncurses.endwin
66
+ end
67
+
68
+ def figlet(font, cols, text)
69
+ font = 'term' if mb?(text)
70
+ cmd = Escape.shell_command(['figlet', '-f', "#{font}.flf", '-w', cols.to_s])
71
+ IO.popen(cmd, 'r+') do |io|
72
+ io.write text
73
+ io.close_write
74
+ io.read
75
+ end
76
+ end
77
+
78
+ def reload
79
+ Ncurses.endwin
80
+ exec "#{$0} #{@source} #{@timer/60} #{@page + 1}"
81
+ end
82
+
83
+ def center(text, options = {})
84
+ return if text.empty?
85
+ font = options[:font] || 'mini'
86
+ text = figlet font, @cols, text
87
+ rows, cols = sizeof(text)
88
+ top = (@rows - rows)/2
89
+ left = (@cols - cols)/2
90
+ @win.attron Ncurses::A_BOLD
91
+ text = text.split("\n").each_with_index do |line, i|
92
+ mvwprintw top + i, left, line
93
+ end
94
+ @win.attroff Ncurses::A_BOLD
95
+ end
96
+
97
+ def caption(text, options = {})
98
+ return if text.empty?
99
+ font = options[:font] || 'mini'
100
+ text = figlet font, @cols, text
101
+ rows, cols = sizeof(text)
102
+ top = (@rows - rows - 2)/2
103
+ left = (@cols - cols)/2
104
+ @win.attron Ncurses::A_BOLD
105
+ text = text.split("\n").each_with_index do |line, i|
106
+ mvwprintw top + i, left, line
107
+ end
108
+ @win.attroff Ncurses::A_BOLD
109
+ @row = top + rows + 1
110
+ end
111
+
112
+ def line(text, options = {})
113
+ return @row += 1 if text.empty?
114
+ font = options[:font] || 'term'
115
+ @row = options[:row] if options[:row]
116
+ @row += options[:padding] if options[:padding]
117
+ text = figlet font, @cols, text
118
+ rows, cols = sizeof(text)
119
+ left = options[:left] || (@cols - cols)/2
120
+ left = @cols - cols - options[:right] if right = options[:right]
121
+ @win.attron Ncurses::A_BOLD if options[:bold]
122
+ text = text.split("\n").each_with_index do |line, i|
123
+ mvwprintw @row + i, left, line
124
+ end
125
+ @win.attroff Ncurses::A_BOLD if options[:bold]
126
+ @row += rows + options[:margin].to_i
127
+ end
128
+
129
+ def color(front, back = Ncurses::COLOR_BLACK)
130
+ if front =~ /^\d+$/
131
+ pair_id = front.to_i
132
+ elsif front.is_a?(String)
133
+ front = eval "Ncurses::COLOR_#{front.upcase}"
134
+ end
135
+ if back.is_a?(String)
136
+ back = eval "Ncurses::COLOR_#{back.upcase}"
137
+ end
138
+ pair_id ||= register_pair front, back
139
+ @win.color_set pair_id, nil
140
+ end
141
+
142
+ def wait(time)
143
+ if time == 0.0
144
+ case input = @status.getch
145
+ when ?j, 32, 10, 13, 27
146
+ else Ncurses.ungetch input
147
+ end
148
+ else
149
+ sleep time
150
+ end
151
+ end
152
+
153
+ def sizeof(text)
154
+ lines = text.split("\n")
155
+ cols = lines.map{|line| line.length}.max
156
+ [lines.size, cols]
157
+ end
158
+
159
+ def mb?(text)
160
+ text.split(//u).size != text.length
161
+ end
162
+
163
+ def paginate
164
+ @status.mvwprintw 0, 0, " " * @cols
165
+ pages = @pages.size
166
+ k = pages.to_s.length
167
+ j = 2 + k*2
168
+ @status.mvwprintw 0, 0, "%#{k}d/%#{k}d|" % [@page + 1, pages]
169
+ cols = @cols - 6 - j
170
+ q = cols % pages
171
+ r = q > 0 ? pages / q : 0
172
+ w = [cols / pages, 1].max
173
+ w += 1 if r > 0 && @page % r == r - 1
174
+ x = (@page*cols + pages/2) / pages
175
+ @status.mvwprintw 0, x + j, "*" * w
176
+ time = Time.now.to_i - @start.to_i
177
+ min, sec = time / 60, time % 60
178
+ @status.mvwprintw 0, cols + j, "|%02d:%02d" % [min, sec]
179
+ @status.refresh
180
+ end
181
+
182
+ def scan_command
183
+ @status.mvwprintw 0, 0, " "*@cols
184
+ @status.mvwprintw 0, 0, ':'
185
+ buf = []
186
+ begin
187
+ case input = @status.getch
188
+ when 10, 13; break
189
+ when 27; return nil
190
+ when 127; buf.pop
191
+ else buf << input
192
+ end
193
+ @status.mvwprintw 0, 1, " "*(@cols - 1)
194
+ @status.mvwprintw 0, 1, buf.pack('C*')
195
+ @status.refresh
196
+ end while input > 0
197
+ command, *args = buf.pack('C*').split(/\s+/)
198
+ command = "do_#{command}"
199
+ send command, *args rescue nil if respond_to? command
200
+ end
201
+
202
+ def register_pair(front, back)
203
+ key = [front, back]
204
+ return @colors[key] if @colors[key]
205
+ pair_id = @colors.size + 1
206
+ Ncurses.init_pair pair_id, front, back
207
+ @colors[key] = pair_id
208
+ end
209
+
210
+ def method_missing(method, *args, &block)
211
+ @win.send method, *args, &block
212
+ end
213
+
214
+ def do_go(page)
215
+ @page = [[0, page.to_i - 1].max, @pages.size - 1].min
216
+ end
217
+
218
+ def do_sh
219
+ Ncurses.endwin
220
+ system ENV['SHELL'] || 'sh'
221
+ Ncurses.resetty
222
+ end
223
+
224
+ def do_q
225
+ exit
226
+ end
227
+ end
@@ -0,0 +1,55 @@
1
+ class Present
2
+ class Page
3
+ def initialize(stanza, screen)
4
+ @lines = stanza.split("\n")
5
+ @screen = screen
6
+ end
7
+
8
+ def start
9
+ @screen.clear
10
+ stack = [['cap', '']]
11
+ execute_command = proc do
12
+ command, text = stack.pop
13
+ dispatch_command command, text
14
+ @screen.refresh
15
+ end
16
+ @lines.each do |line|
17
+ text, command = line.split(/\s+/, 2).reverse
18
+ if command
19
+ execute_command.call
20
+ stack.push [command, text]
21
+ else
22
+ stack.last[1] += "\n#{text}"
23
+ end
24
+ end
25
+ execute_command.call
26
+ end
27
+
28
+ private
29
+ def dispatch_command(command, text)
30
+ case command
31
+ when '='
32
+ @screen.caption text
33
+ when '-'
34
+ @screen.line text
35
+ when '<'
36
+ @screen.line text, :left => 1, :padding => 1
37
+ when '>'
38
+ @screen.line text, :right => 1, :padding => 1
39
+ when /(\++)(\-?)/
40
+ @screen.line '- ' + text, :left => $1.length*2 - 1,
41
+ :padding => $2.empty? ? 1 : 0
42
+ when '*'
43
+ @screen.line text, :row => 1, :bold => true
44
+ when '.'
45
+ @screen.center text.empty? ? "fin" : text, :font => 'mini'
46
+ when '#'
47
+ @screen.center text, :font => 'mini'
48
+ when '%'
49
+ @screen.color *text.split(/\s+/)
50
+ when ','
51
+ @screen.wait text.to_f
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,5 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ require "test/unit"
4
+ class PresentTest < Test::Unit::TestCase
5
+ end
@@ -0,0 +1,3 @@
1
+ require 'test/unit'
2
+ require File.dirname(__FILE__) + '/../lib/present'
3
+
metadata ADDED
@@ -0,0 +1,102 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: present
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Genki Takiuchi
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-08-31 00:00:00 +09:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: ncurses
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: text
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "0"
34
+ version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: escape
37
+ type: :runtime
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: "0"
44
+ version:
45
+ description: Presentation tool for terminal.
46
+ email: genki@s21g.com
47
+ executables:
48
+ - present
49
+ extensions: []
50
+
51
+ extra_rdoc_files:
52
+ - README
53
+ - ChangeLog
54
+ files:
55
+ - README
56
+ - ChangeLog
57
+ - Rakefile
58
+ - bin/present
59
+ - test/test_helper.rb
60
+ - test/present_test.rb
61
+ - lib/present
62
+ - lib/present/page.rb
63
+ - lib/present.rb
64
+ has_rdoc: true
65
+ homepage: http://cocktail-party.rubyforge.org
66
+ post_install_message:
67
+ rdoc_options:
68
+ - --title
69
+ - present documentation
70
+ - --charset
71
+ - utf-8
72
+ - --opname
73
+ - index.html
74
+ - --line-numbers
75
+ - --main
76
+ - README
77
+ - --inline-source
78
+ - --exclude
79
+ - ^(examples|extras)/
80
+ require_paths:
81
+ - lib
82
+ required_ruby_version: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ version: "0"
87
+ version:
88
+ required_rubygems_version: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: "0"
93
+ version:
94
+ requirements: []
95
+
96
+ rubyforge_project: cocktail-party
97
+ rubygems_version: 1.2.0
98
+ signing_key:
99
+ specification_version: 2
100
+ summary: Presentation tool for terminal.
101
+ test_files:
102
+ - test/present_test.rb